bmelling9
asked on
Splitter windows
I am attempting to simulate dynamic splitter windows by creating a new static window as the user requests a new column or row. The problem is that I can't get the splitter window (which is a child of the MainFrame window)to paint after the new splitter is created. It will only paint if I minimize and restore. Here is a section of code for adding a new row:
delete m_wndSplitter;
m_wndSplitter = new CSplitterWindow;
CCreateContext context;
context.m_pCurrentFrame = this/*MainFrame CWnd*/;
if (m_nRows < 16)
m_nRows++;
BOOL returnVal = m_wndSplitter->CreateStati c(this, m_nRows,
m_nCols);
CRect rect;
GetClientRect(rect);
int width = rect.right/m_nCols;
int height = rect.bottom/m_nRows;
for (int i = 0; i < m_nRows; i++)
{
for (int j = 0; j < m_nCols; j++)
{
if (! m_wndSplitter->CreateView( i, j, RUNTIME_CLASS (CSplitterView), CSize(width,height), &context))
returnVal = FALSE;
}
}
m_wndSplitter is a member of the MainFrame class. I even put a posted a WM_PAINT message to m_wndSplitter at the end of the MainFrame's OnPaint function, but no luck. Any help would be greatly appreciated. Thanks
delete m_wndSplitter;
m_wndSplitter = new CSplitterWindow;
CCreateContext context;
context.m_pCurrentFrame = this/*MainFrame CWnd*/;
if (m_nRows < 16)
m_nRows++;
BOOL returnVal = m_wndSplitter->CreateStati
m_nCols);
CRect rect;
GetClientRect(rect);
int width = rect.right/m_nCols;
int height = rect.bottom/m_nRows;
for (int i = 0; i < m_nRows; i++)
{
for (int j = 0; j < m_nCols; j++)
{
if (! m_wndSplitter->CreateView(
returnVal = FALSE;
}
}
m_wndSplitter is a member of the MainFrame class. I even put a posted a WM_PAINT message to m_wndSplitter at the end of the MainFrame's OnPaint function, but no luck. Any help would be greatly appreciated. Thanks
Did You try m_wndSplitter->Invalidate( ) ?
Replace the lines:
if (! m_wndSplitter->CreateView( i, j, RUNTIME_CLASS (CSplitterView), CSize(width,height), &context))
returnVal = FALSE;
with:
if (m_wndSplitter->CreateView (i, j, RUNTIME_CLASS (CSplitterView), CSize(width,height), &context))
RedrawWindow(NULL, NULL, RDW_INVALIDATE | RDW_UPDATENOW | RDW_ERASE | RDW_ALLCHILDREN );
else
returnVal = FALSE;
if (! m_wndSplitter->CreateView(
returnVal = FALSE;
with:
if (m_wndSplitter->CreateView
RedrawWindow(NULL, NULL, RDW_INVALIDATE | RDW_UPDATENOW | RDW_ERASE | RDW_ALLCHILDREN );
else
returnVal = FALSE;
ASKER
this did not solve the problem- the splitter window is still not getting painted. I have developed a work around for this situation- I am posting a WM_SIZE to the MainFrame Window at the end of the MainFrame Window's OnPaint function. However, this seems unnecessary, so I would still be interested in knowing the source of this problem and/or a more logical solution.
I've never done a dynamic splitter like your application, but Invalidate() followed by UpdateWindow() will almost always work.
CSplitterWnd::RecalcLayout () should be working, i think ...
It is called upon WM_SIZE messages, and should be called after layout changes.
Hope this works :)
It is called upon WM_SIZE messages, and should be called after layout changes.
Hope this works :)
I think you are not associating the current document to the newly created views.
Give the current document to the context.
context.m_pCurrentDoc = ???//Current Document pointer
Try this.
Give the current document to the context.
context.m_pCurrentDoc = ???//Current Document pointer
Try this.
ASKER
I am not currently working with a document- all I have is a frame window and the splitter window. I have tried nearly all possible combinations of calling Invalidate() and UpdateWindow() for both as well as RecalcLayout() for the Splitter. I have also posted WM_PAINT messages to both windows at various points in the process of creating the splitter, but the only thing that has worked is the work around I mentioned in my note on 9/3. I guess I don't have to have an answer to this, but my curiosity is piqued, so I'm upping the points a little...
Have U tried using UpdateAllViews().
If you want to Create a splitter window use static view, you must overwrite OnCreateClient(...).
Now I give you this code.I set View is CMyView1 and CMyView2.
//in Hpp File
class CMyFrame : CFrameWnd
{
.....
CSplitterWnd m_wndSplitter; //This Value is by AppWizard Create
//If you Con't see it,
//you can write it
}
//in Cpp File
BOOL CMyFrame::OnCreateClient(L PCREATESTR UCT /*lpcs*/, CCreateContext* pContext)
{
// TODO: Add your specialized code here and/or call the base class
if(!m_wndSplitter.CreateSt atic(this, 2, 1) ||
!m_wndSplitter.CreateView( 0, 0, RUNTIME_CLASS(CMyView1), CSize(100, 200), pContext) ||
!m_wndSplitter.CreateView( 1, 0, RUNTIME_CLASS(CMyView2), CSize(100, 200), pContext))
return FALSE;
return TRUE;
//Don't Call System OnCreateClient(...)
//return CFrameWnd::OnCreateClient( lpcs, pContext);
}
Now I give you this code.I set View is CMyView1 and CMyView2.
//in Hpp File
class CMyFrame : CFrameWnd
{
.....
CSplitterWnd m_wndSplitter; //This Value is by AppWizard Create
//If you Con't see it,
//you can write it
}
//in Cpp File
BOOL CMyFrame::OnCreateClient(L
{
// TODO: Add your specialized code here and/or call the base class
if(!m_wndSplitter.CreateSt
!m_wndSplitter.CreateView(
!m_wndSplitter.CreateView(
return FALSE;
return TRUE;
//Don't Call System OnCreateClient(...)
//return CFrameWnd::OnCreateClient(
}
This is the source code of CFrameWnd::OnSize():
(mainfrm.cpp)
void CFrameWnd::OnSize(UINT nType, int cx, int cy)
{
CWnd::OnSize(nType, cx, cy); // important for MDI Children
if (nType != SIZE_MINIMIZED)
RecalcLayout();
}
You said, when you post a WM_SIZE message at the end of a OnPaint() handler, it works.
Maybe you should try this in your splitter update function:
Invalidate(); // Invalidate client rectangle
UpdateWindow(); // Wait for WM_PAINT to be sent
RecalcLayout(); // called by WM_SIZE
This should have the same effect as what you did in the OnPaint() handler. If this doesn't work,
perhaps you could replace RecalcLayout() with your WM_SIZE posting.
(mainfrm.cpp)
void CFrameWnd::OnSize(UINT nType, int cx, int cy)
{
CWnd::OnSize(nType, cx, cy); // important for MDI Children
if (nType != SIZE_MINIMIZED)
RecalcLayout();
}
You said, when you post a WM_SIZE message at the end of a OnPaint() handler, it works.
Maybe you should try this in your splitter update function:
Invalidate(); // Invalidate client rectangle
UpdateWindow(); // Wait for WM_PAINT to be sent
RecalcLayout(); // called by WM_SIZE
This should have the same effect as what you did in the OnPaint() handler. If this doesn't work,
perhaps you could replace RecalcLayout() with your WM_SIZE posting.
ASKER
I did override the OnCreateClient function and it works when the frame window is created. The problem occurs after the frame has been created when, in response to a user command, I attempt to delete the static splitter and create another with different dimensions.
When you set up a CCreateContext like the one passed to OnCreateClient, this should work:
C...Frame::OnUserAction()
{
CCreateContext context;
// set up context
...
m_wndSplitter.DestroyWindo w();
// insert here the code part from OnCreateClient which creates the m_wndSplitter
}
C...Frame::OnUserAction()
{
CCreateContext context;
// set up context
...
m_wndSplitter.DestroyWindo
// insert here the code part from OnCreateClient which creates the m_wndSplitter
}
ASKER
Thanks snoegler, your comment of 9/13 worked. I was calling RecalcLayout() on the CSplitterWnd derived class, not the CFrameWnd derived class. Adding the RecalcLayout() call to the end of my CreateSplitter routine did the trick. This is my first question at experts exchange, so I don't know how to get you the points for this question since you did not submit an "answer". Let me know if I need to do anything. Thanks again.
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
ASKER