c++visual-studiomfcmdititlebar

MFC MDI Getting file path and updated titles on document switch by overriding FWS_ADDTOTITLE?


TL;DR: How do you add the full path for each document title?

I've seen a lot of threads just by searching FWS_ADDTOTITLE. My particular old app I'm updating uses this specifically:

lpwndMainFrame->LoadFrame(IDR_MAINFRAME, WS_OVERLAPPEDWINDOW|FWS_ADDTOTITLE);

My app specifically deals with MP4 files and meta data tagging and as an MDI, it can open 1 or multiple mp4 files simultaneously for editing, copying/cut/paste of meta data etc...that all works and is all good.

The one thing I really want is to see is the full path + filename of the MP4 in the apps title which changes based on what document is selected.

I can use this to override the title as a hard code method:

m_pMainWnd->SetWindowText(_T("My hardcoded title with no help to my topic example"));

So I know the mechanism works to replace the document title on focus.

Since the app already handles the filename in the title switching between documents just fine, I want that same exact functionality but with the path in the title.

Why? There are times where I can have two files with the same exact name, but different folders and it can get confusing if I don't know which one I am modifying.

So I'm looking for the title of the app to show something like:

MyApp - C:\MyHarddrive\Folder1\ThisIsMyFile1.mp4
MyApp - C:\MyHarddrive\Folder17\ThisIsMyFile2.mp4
MyApp - C:\MyHarddrive\FolderA\ThisIsMyFile1.mp4

as I select document 1 -3 respectively.

EDIT:

I'm adding where FWS_ADDTOTITLE lives in my App. I picked up the code that was abandoned years ago so I have no control without rewriting the whole thing which I'm not wanting to do. The code below lives in a file called application.cpp. Their is no other reference to FWS_ADDTOTITLE in my files called MainFrame.cpp or ChildFrame.cpp. I tried the override as mentioned below, but it comes up with a &hookpointer unknown identifier from the VC source code files copied into the override function after pasting. Does this help in anyway?

BOOL CApplication::InitInstance()
{
    CWinApp::InitInstance();

    // set registry key
    SetRegistryKey(_T("AppNameC"));
    //CleanState(); 

    // create document template
    CMultiDocTemplate* m_pkDocTemplate;
    m_pkDocTemplate = new CMultiDocTemplate(
        IDR_MOVIE,
        RUNTIME_CLASS(CMovieDoc),
        RUNTIME_CLASS(CChildFrame),
        RUNTIME_CLASS(CMovieView));
    if (!m_pkDocTemplate)
        return FALSE;
    AddDocTemplate(m_pkDocTemplate);    

    // create main window
    CMainFrame *lpwndMainFrame = new CMainFrame();
    lpwndMainFrame->LoadFrame(IDR_MAINFRAME, WS_OVERLAPPEDWINDOW|FWS_ADDTOTITLE);
    m_pMainWnd = lpwndMainFrame;
    m_pMainWnd->DragAcceptFiles(); // Added
    lpwndMainFrame->ShowWindow(m_nCmdShow); 
    //lpwndMainFrame->ShowWindow(SW_MAXIMIZE); // Added start full screen
    //m_pMainWnd->SetWindowText(_T("History database")); // Added Valid
    lpwndMainFrame->UpdateWindow();

    // parse command line
    return ParseCommandLine();
    
}

EDIT 3/24/2021

So I've got it mostly working by the help already stated but a new issue arises and not sure how to fix it. In BOTH my MainFrame.cpp & ChildFrame.cpp both have these same exact overrides verbatim:

BOOL CChildFrame::PreCreateWindow(CREATESTRUCT& cs)
{
    // TODO: Add your specialized code here and/or call the base class
    
    cs.style &= ~(LONG)FWS_ADDTOTITLE;

    
    return CMDIChildWndEx::PreCreateWindow(cs);
}


void CChildFrame::OnUpdateFrameTitle(BOOL bAddToTitle)
{
    // TODO: Add your specialized code here and/or call the base class


    CView* pView = GetActiveView();
    if (pView) {
        CDocument* pDoc = pView->GetDocument();
        if (pDoc) {
            CString title;

            title = pDoc->GetPathName();
            //title.Format("My App - %s", pDoc->GetPathName());
            AfxGetMainWnd()->SetWindowText(title.GetString());
        }
    }


    CMDIChildWndEx::OnUpdateFrameTitle(bAddToTitle);
}

As shown, I have my proper path and title:

Working path in title

But a new artifact shows up: The Windows Active (not sure what it's called) are now missing the file names that would normally be there:

Windows document titles are missing because of override

If I comment out //cs.style &= ~(LONG)FWS_ADDTOTITLE; in the CHILDFRAME ONLY..then it restores my window menu titles as somehow it is using GetTitle() via FWS_ADDTOTITLE. I want the paths to show like above, but still retain the titles in the menus as each file is shown. The - [FIL-TITLE.MP4] (shown in red box in image) needs to go...but not sure how to make that happen....one thing upsets the other via the overrides...any thoughts on how to correct this one final piece? It is almost 100% except the window drop down thing. Any ideas?

Trying to get too


Solution

  • What I would do for this is search for the use of FWS_ADDTOTITLE in the MFC sources. In VS you select Edit->Find and Replace->Find in Files and in the "Look In" combo select "Visual C++ Source Directories".

    This search returns several results, but the ones that seem relevant are in winfrm.cpp and winmdi.cpp, in the OnUpdateFrameTitle() member function in both cases. The good thing is that this member is virtual and public, ie overridable. So you can override it (go to Class View and click "Overrides" in the properties toolbox). In the function implementation don't call the ancestor implementation, instead copy the code from the MFC source and replace UpdateFrameTitleForDocument(pDocument->GetTitle()) with UpdateFrameTitleForDocument(pDocument->GetPathName()). Not sure which implementation of the two (winfrm.cpp or winmdi.cpp) your code uses, but you can debug it to find out (I guess it is the one in winmdi.cpp, since your frame window is derived from CMDIFrameWnd but it would be best to check).

    Possible problem, the code may not compile, if it uses private members or variables declared/defined elsewhere, but I would say give it a try.


    EDIT :

    The OnUpdateFrameTitle() function, as it name suggests, appears to be the most proper one to override, doesn't it?

    Did what I described above, and changed the code as shown below - your MFC version may be different, so copy the code from YOUR MFC sources and modify it as needed, don't just copy what you see here. It was copied from winmdi.cpp, function CMDIFrameWnd::OnUpdateFrameTitle().

    void CMainFrame::OnUpdateFrameTitle(BOOL bAddToTitle)
    {
        if ((GetStyle() & FWS_ADDTOTITLE) == 0)
            return;     // leave it alone!
    
        // allow hook to set the title (used for OLE support)
        if (m_pNotifyHook != NULL && m_pNotifyHook->OnUpdateFrameTitle())
            return;
    
        CMDIChildWnd* pActiveChild = NULL;
        CDocument* pDocument = GetActiveDocument();
        if (bAddToTitle &&
            (pActiveChild = MDIGetActive()) != NULL &&
            (pActiveChild->GetStyle() & WS_MAXIMIZE) == 0 &&
            (pDocument != NULL ||
            (pDocument = pActiveChild->GetActiveDocument()) != NULL))
        // This was the original code: UpdateFrameTitleForDocument(pDocument->GetTitle());
        // This is the modified code, and THE ONLY CHANGE in the source
        {
            CString sDoc = pDocument->GetPathName();
            // GetPathName() returns an empty string for a newly-created document
            if (sDoc.IsEmpty()) sDoc = pDocument->GetTitle();
            UpdateFrameTitleForDocument(sDoc);
        }
        else
        {
            LPCTSTR lpstrTitle = NULL;
            CString strTitle;
    
            if (pActiveChild != NULL &&
                (pActiveChild->GetStyle() & WS_MAXIMIZE) == 0)
            {
                strTitle = pActiveChild->GetTitle();
                if (!strTitle.IsEmpty())
                    lpstrTitle = strTitle;
            }
            UpdateFrameTitleForDocument(lpstrTitle);
        }
    }
    

    This code won't compile, because as you mentioned the compiler doesn't know the type of m_pNotifyHook. This can be solved, using the VS editor features (eg right-click and select Find Declaration/Definition). The type of this variable is COleFrameHook*, which is declared in oleimpl2.h - a simple file/text search can find it. So what you need to do is include this header in your source:

    #include "oleimpl2.h"
    

    For some weird reason this file is in the sources, not in the include directories, and therefore VS cannot find it, ie #include <oleimpl2.h> doesn't work. So I used double quotes and copied the file in my project's source folder - alternatively you can specify a fully-qualified path in the #include "" directive.