MFC SDI access View from DOC - mfc

I am new to MFC SDI app. In my CMyDOC.cpp like to access the functions in CMyView.cpp. What is the best and cleanest way to do this?. As well as going opposite.

Doc->View: If you are going to have only one view connected to the document, you can use something like:
CMyView* pView = NULL;
POSITION pos = GetFirstViewPosition();
if (pos != NULL)
pView = (CMyView*) GetNextView(pos);
View->Doc:
CMyDoc* pDoc = GetDocument();

MFC recommended way is not to directly access CView from CDocument. You should reconsider your design if you have to do that because typically your view would access the document but not other way round. You should use UpdateAllViews mechanism to let your view(s) know of change in document.

Related

How to get CDocument for derived CMFCShellTreeCtl on an Outlook Style MFC program?

I am new to MFC and have built an "outlook" style MFC app using the wizard. I've extended the CMFCShellTreetCtrl using CMyShellTreeCtrl and had data member variables and all was working fine. Now I want to move the data over to the CDocument class. Since there is several accesses to the data as each item is clicked or enumerated, I thought I would create a member variable m_pDoc to access the public variables in the CDocument. The problem I'm having, I can't find where to get the CDocument as it appears it's not setup when the trees OnCreate is called. That is in OnCreate
CWnd* pWndMain = AfxGetMainWnd();
ASSERT(pWndMain);
ASSERT(pWndMain->IsKindOf(RUNTIME_CLASS(CFrameWnd)) && !pWndMain->IsKindOf(RUNTIME_CLASS(CMDIFrameWnd))); // Not an SDI app.
m_pDoc = (CMyDoc*) ((CFrameWnd*)pWndMain)->GetActiveDocument();
returns NULL in m_pDoc and if I tried in an AfterCreate() (which is called after CreateOutlookBar) it's too late as m_pDoc is already being used and get a crash.
// Create and setup "Outlook" navigation bar:
if (!CreateOutlookBar(m_wndNavigationBar, ID_VIEW_NAVIGATION, m_wndTree, m_wndCalendar, 250))
{
TRACE0("Failed to create navigation pane\n");
return -1; // fail to create
}
m_wndTree.AfterCreate();
Any Ideas?
TIA!!
I came up with the following but I'm not sure if this is the proper way. Again, I'm new to MFC (I always have used Win32 directly). This works so it's AN answer, but is it THE correct answer?
POSITION docpos = AfxGetApp()->GetFirstDocTemplatePosition();
CDocTemplate *doctemplate = AfxGetApp()->GetNextDocTemplate(docpos);
docpos=doctemplate->GetFirstDocPosition();
m_pDoc = (CMyDoc*)doctemplate->GetNextDoc(docpos);
ASSERT(m_pDoc);
ASSERT(m_pDoc->IsKindOf(RUNTIME_CLASS(CMyDoc)));
TIA!!

Disabling (Greying out) multiple GUI Items in C++

Question:
I am looking for an effective way to disable(grey) mutiple items in a MFC C++ application. Depending on if the user is signed into a SQL Server or Oracle account, I wish to disable a section of GUI items.
What I have tried:
I have used the following code to disable one of my two "Create User" buttons.
if(checkIsSQLServer())
{
CWnd *oraCreateUser = GetDlgItem(BTN_ORA_CREATE);
oraCreateUser->EnableWindow(false); //Disable Oracle "Create User" button
}
else
{
CWnd *sqlCreateLogin = GetDlgItem(BTN_SQL_CREATE);
sqlCreateLogin->EnableWindow(false); //Disable SQL Server "Create User" button.
}
.
This code works perfectly, however it only disables the button. I wish to disable all items within either groupbox.
Do I need to create a CWnd* object for every item I wish to disable? Is there a more effective way, such as a way to disable all items that are contained within a group box?
I use this:
void EnableDlgItem (CWnd *dlg, int items[], BOOL bEnable)
{
int i = 0, item ;
while ((item = items[i++]) != 0)
{
CWnd *pControl = dlg->GetDlgItem(item) ;
if (pControl != NULL)
pControl->EnableWindow(bEnable) ;
}
}
...
And in some CYourDialog::OnSomethingFunction()
static int ids[] = {IDOK, IDC_EDIT1, IDC_EDIT2, 0};
EnableDlgItem(this, ids, FALSE);
As others have said, MFC does not expose a method that allows you to enable/disable a group of controls. You'll need to craft your own code to do that.
I was faced with the very same situation and decided to handle it by deriving my own groupbox class. In my situation, the groupbox enable/disable functioning was tied to the state of a checkbox as seen below.
(I've redacted some information from it).
Clicking on the checkbox will toggle the enable/disable of all controls within the groupbox. There's nothing stopping you from deriving your own class for the groupbox and exposing a method that can be called (rather than a checkbox) to enable/disable controls. The advantage to this approach is that if you create the class in a generic manner, you can re-use it in other situations where a groupbox is the "parent" of other controls.

Switching between different ribbons in an MDI application

I'd like to switch between different ribbons for different MDI child frames in my application. I know it's possible with the old style menus, but I can't get it working with the feature pack ribbons.
The code used when it's old style menus:
pDocTemplate = new CMultiDocTemplate(
IDR_MAINFRAME,//Menu to load
RUNTIME_CLASS(CModDoc),
RUNTIME_CLASS(CModFrame), // custom MDI child frame
RUNTIME_CLASS(CdotView));
if (!pDocTemplate)
return FALSE;
AddDocTemplate(pDocTemplate);
pDocTemplate = new CMultiDocTemplate(
IDR_RES_RNGACTIV,//Menu to load
RUNTIME_CLASS(CModRangeDoc),
RUNTIME_CLASS(CModRangeFrame), //custom MDI child frame
RUNTIME_CLASS(CBlankView));
if (!pDocTemplate)
return FALSE;
AddDocTemplate(pDocTemplate);
Another approach I'm thinking of is to unload the current Ribbon and load a new Ribbon from resources?
//Unload ribbon code?
m_wndRibbonBar.LoadFromResource(IDR_RIBBON);
there is no need to have multiple CMFCRibbonBar objects if you don't need to, you can just use the CMFCRibbonBar::LoadFromResource and then you will have to use the CMFCRibbonBar::RecalcLayout method to apply the changes to the User Interface.
Remember to check the return value of CMFCRibbonBar::LoadFromResource to be sure that the load was successful, and it is really important that you call the CMFCRibbonBar::RecalcLayout otherwise you will not see the new ribbon.
I ended up hiding the original ribbonbar and then loading and displaying a new one. Not sure if it's the best way to do it though.
CMultiDocTemplate *pDoc = GetDocTemplate(7);
if (pDoc)
{
CFloorActivDoc* pDocument = (CFloorActivDoc*)pDoc->CreateNewDocument();
CFloorFrame* pFrame = (CFloorFrame*)pDoc->CreateNewFrame(pDocument, NULL);
if (pFrame)
{
pDoc->InitialUpdateFrame(pFrame, pDocument);
m_wndRibbonBar.ShowPane(FALSE, FALSE, TRUE);//Hide original ribbon
m_FloorRibbonBar.Create(this);
m_FloorRibbonBar.LoadFromResource(IDR_RIBBON_FLOORACT);
}

Create a ListView in MFC without having dialogs

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...

C++ MFC MDI how to change what class view displays based on active document

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