I migrated my MFC MDI application to use the new MFC Feature Pack. I have many toolbars and dockable panes. As far as I understand, the location and size of each of them is saved in the registry when closing the application, and loaded when loading the main frame.
I want to add a feature in my application to reset the layout of the toolbars/panes to the original layout.
I have tabbedpanes also in my application.
sometimes I will dock separate panes to tabbed panes.
Is there a way to actually reset the layout of my application AFTER it has been loaded?
Visual Studio has a similar feature called "Reset Window Layout".
I am getting samples in the internet for restoring mainframe window using SetWindowPlacement() and GetWindowPlacement().
I don't know how to use these functions for toolbars and CDockablePanes and achieve my requirement?
Is there any other solution apart from using SetWindowPlacement() and GetWindowPlacement()?
I am able to meet my requirement using below code.
void CMainFrame::OnPanesResetLayout()
{
CDockingManager* pDockMgr = GetDockingManager();
if (pDockMgr == NULL)return;
CRect rect;
rect.SetRectEmpty();
ClientToScreen(rect);
SetRedraw(FALSE);
CObList list;
pDockMgr->GetPaneList(list, TRUE,0,TRUE);
// UnDock and hide DockingControlBars
POSITION pos;
for (pos = list.GetHeadPosition(); pos != NULL;)
{
CBasePane* pBarNext = (CBasePane*) list.GetNext(pos);
if (!::IsWindow(pBarNext->m_hWnd))continue;
CDockablePane* pBar = DYNAMIC_DOWNCAST(CDockablePane, pBarNext);
if (pBar != NULL)
{
if(pBar->IsAutoHideMode()) pBar->SetAutoHideMode(FALSE, CBRS_ALIGN_ANY);/*ToggleAutoHide();*/
if (pBar->IsMDITabbed ())
continue;
pBar->UndockPane();
ShowPane(pBar, FALSE,FALSE, FALSE);
}
CMFCToolbar* pToolBar = DYNAMIC_DOWNCAST(CMFCToolbar, pBarNext);
if(pToolBar)
pToolBar->m_recentDockInfo.m_recentSliderInfo.m_rectDockedRect = rect;
}
m_wndBar1.DockToFrameWindow(CBRS_LEFT,m_wndBar1.GetAHRestoredRect());
ShowPane(m_wndBar1, TRUE,FALSE, FALSE);
m_wndBar2.DockToFrameWindow(CBRS_RIGHT,m_wndBar2.GetAHRestoredRect());
ShowPane(m_wndBar2, TRUE,FALSE, FALSE);
//for tabbed pane
CTabbedPane *pTabbedPane;
m_wndTab1.DockToFrameWindow(CBRS_BOTTOM,m_wndTab1.GetAHRestoredRect());
m_wndTab2.AttachToTabWnd(&m_wndTab1, DM_SHOW, FALSE,reinterpret_cast<CDockablePane**>(&pTabbedPane));
m_wndTab3.AttachToTabWnd(&m_wndTab1, DM_SHOW, FALSE,reinterpret_cast<CDockablePane**>(&pTabbedPane));
ShowPane(m_wndTab1, TRUE,FALSE, FALSE);
ShowPane(m_wndTab2, TRUE,FALSE, FALSE);
ShowPane(m_wndTab3, TRUE,FALSE, FALSE);
SetRedraw(TRUE);
RedrawWindow(NULL, NULL, RDW_INVALIDATE | RDW_UPDATENOW | RDW_ERASE | RDW_ALLCHILDREN);
AdjustClientArea();
}
As described in my comment above, one option to restore the initial layout from a running application would be to use the methods provided by CDockablePane, specifically
AttachToTabWindow
DockToWindow and
ShowPane
A second option, which would require restarting your application, is to call EnableLoadDockState(FALSE) in the constructor of your CFrameWndEx derived class. This would prevent loading the stored dock state and, as a consequence, restore the initial layout.
A simple method to solve this is to delete from registry key all keys which store the panels info: "BasePane" and "Pane" from "Workspace" registry folder from your app registry entry :) Easy.
I am trying to create a ListView in MFC C++ in my Child window. I have just finished reading this article on CodeProject. I recommend it to anyone who wants to create the control in a dialog or that has created it already and tries to learn more about it.
Here comes my question! I have to create the ListView control at ::OnCreate() of my ChildWindow. How can I do this?
Here is what I've tried so far:
int CChildFrame::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
if (CMDIChildWnd::OnCreate(lpCreateStruct) == -1)
return -1;
CListCtrl *CarsListView = new CListCtrl();
CarsListView->SetView(LVS_REPORT);
CarsListView->ShowWindow(SW_SHOW);
return 0;
}
(code that is obviously not working...)
There is no Need to use new to create a list view object.
Creating the object doesn't create the window. You Need to call CListView::Create
Maybe you should read a MFC tutorial...
I'm working on an MDI application that has an object browser (CClassView) that has to change what it displays based on what "document" is active.
PS: None of my searches have worked.
This isn't what I expected, but here's a possible solution:
http://forums.codeguru.com/showthread.php?473808-MFC-Doc-View-How-to-get-the-active-document-anywhere-in-my-application
Q: How to get the active document anywhere in my application?
A: There are several methods, one is to get first the active frame
then call CFrameWnd::GetActiveDocument. ... In MDI applications, we
have to additionally get the active MDI child frame.
CDocument* GetMDIActiveDocument()
{
CDocument* pDoc = NULL;
CWnd* pWndMain = AfxGetMainWnd();
ASSERT(pWndMain);
ASSERT(pWndMain->IsKindOf(RUNTIME_CLASS(CMDIFrameWnd))); // Not an MDI app.
CFrameWnd* pFrame = ((CMDIFrameWnd*)pWndMain)->MDIGetActive();
if(NULL != pFrame)
{
pDoc = pFrame->GetActiveDocument(); // get the active document
}
return pDoc;
}
This sample code might suggest other (perhaps even better) alternatives:
http://msdn.microsoft.com/en-us/library/cstcs513%28v=vs.90%29.aspx
I have a MFC CDocument and associated CView open in a MDI application. I would like to detach and close the view (and associated frame), while keeping the document open. Looking around the MFC code to see how it does it, reveals the following in CDocument::OnCloseDocument();
// destroy all frames viewing this document
// the last destroy may destroy us
BOOL bAutoDelete = m_bAutoDelete;
m_bAutoDelete = FALSE; // don't destroy document while closing views
while (!m_viewList.IsEmpty())
{
// get frame attached to the view
CView* pView = (CView*)m_viewList.GetHead();
ASSERT_VALID(pView);
CFrameWnd* pFrame = pView->EnsureParentFrame();
// and close it
PreCloseFrame(pFrame);
pFrame->DestroyWindow();
// will destroy the view as well
}
m_bAutoDelete = bAutoDelete;
which I guess I could use in conjunction with CDocument::RemoveView. Is there a better way to approach this than just lifting the MFC source, and is this approach going to cause me other problems or side effects? The project is VS2010 C++.
If you set CDocument::m_bAutoDelete to FALSE (after the document has been created) it should not delete the document when the last view closes.
I'm not sure what you're specifically trying to do but you might want to consider creating a separate 'data' object that can be attached to a document rather than trying to keep the document itself around.
When the user creates a new document in my SDI-application, I need to present a dialog specifying details on the document to be created (think: resolution, bit-depth, etc.) I initially put the code for displaying this dialog in OnNewDocument() (I don't need it when opening an existing document), but putting user-interface code in the document-class just doesn't feel right (also, I don't have any CWnd* to use as a parent for the dialog).
Is there a better place to do this in MFC?
You're right, the document class is no good place for UI.
CDocTemplate::[OpenDocumentFile][1](pszPath) looks like a better candidate:
pszPath==NULL means 'create a new document'.
The method is virtual -> Just derive CMySingleDocTemplate from CSingleDocTemplate and use an instance of this class in CMyWinApp::InitInstance().
This class is responsible for creating docs, frames and views, hence I think it's a good place to put a UI operation.
BOOL CMyWinApp::InitInstance()
{
...
CSingleDocTemplate* pDocTemplate;
pDocTemplate = new CMySingleDocTemplate( // <--Derives from CSingleDocTemplate
IDR_MAINFRAME,
RUNTIME_CLASS(CMyDoc),
RUNTIME_CLASS(CMainFrame),
RUNTIME_CLASS(CMyView));
AddDocTemplate(pDocTemplate);
...
}
CDocument* CMySingleDocTemplate::OpenDocumentFile(LPCTSTR lpszPathName,
BOOL bMakeVisible)
{
CDocument *pDoc =
CSingleDocTemplate::OpenDocumentFile(lpszPathName, bMakeVisible);
if (lpszPathName==NULL)
{
// GUI to get user info
// update doc
m_pOnlyDoc->Blah(input);
// update view
m_pOnlyDoc->UpdateAllViews(NULL,...,...);
}
}
This might not be ideal though: In SDI, there is one and only doc object. It's re-used accross File/Load and File/New operation.
This function will then be called a first time before the initial mainframe is created. You may not want to have a dialog presented to user before the frame is created. Ouch! It's a little more complicated:
Instead of popping up a GUI in in OpenDocumentFile(NULL) as above, just post a custom message/command to the main frame. Then add a handler that will react by the sequence pop up GUI/update doc/update views. That way, the main frame will be displayed before the GUI is popped up and your user will be happier.
This also solves your problem where you don't have a CWnd parent: the main frame is already created and your dialog will use it byt default.
BTW, another solution consists in adding a command handler for ID_FILE_NEW in your CMyWinApp's message map and add your own override of OnFileNew(). But when you write OnFileNew(), I believe you'll quickly find out that it's an ugly solution :-(