Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / desktop / MFC

Activate Document Window in MDI Application

4.67/5 (6 votes)
8 Dec 2022CPOL2 min read 10.9K  
Activate a particular document window in MDI application via MFC/C++
Sometimes, you need to activate a particular document window in the MDI application. It has nothing in common with opening the same document. You need it when an event happens, or user changed something somewhere and you need to notify him that one of the opened documents received changes or finished computation or whatever I can’t even imagine. In this case, you need a way to pop the random document…

Introduction

In the text below, you can find a weird code that was written while sequentially approaching the working solution. The code below contains only code that illustrates the technology, no error handling or complete function code provided.

Background

In my case, I required documents which represents a filesystem folders which cannot be opened, changes since they were opened and, of course they must not be opened more than once. Don't ask me why I have to use an MDI (multiple document interface) MFC application for this purpose.

Using the Code

A long time ago, I got some experience in writing MFC applications. Windows was young and made first steps as a 32-bit operating system at that time. Moreover, most of my applications were SDI (single document interface) or dialog based. And I was more or less calm and happy that time.

However, returns to our muttons MDI application. For my task, I have to use MDI interface and, after some iterations, I felt the need to activate the opened document when user did some action. I began with the document lookup (the easiest part):

C++
// Get the first document template position (since I don't create more)
POSITION pos = pApp->GetFirstDocTemplatePosition();
CDocTemplate* pDocTmpl = pApp->GetNextDocTemplate(pos);
// get the first document position
POSITION posD = pDocTmpl->GetFirstDocPosition();
// Iterate the opened documents
while (posD != NULL)
{
    // get the document
    CDocument* pDoc = pDocTmpl->GetNextDoc(posD);
    // identify document by path
    if (pDoc->GetTitle().CompareNoCase(path) == 0)
    {
        // get first view position for the document
        POSITION posW = pDoc->GetFirstViewPosition();
        // iterate views
        while (posW != NULL)
        {
            // receive a view
            CView* pView = pDoc->GetNextView(posW);
            // basic validation
            if (pView && ::IsWindow(pView->GetSafeHwnd()))
            {
                // here is a view to activate

It is easy to identify that you need, but the next steps were not easy to me. My first view activation code is shown below:

C++
CWnd* pWnd = pView->SetActiveWindow();
pView->FlashWindow(TRUE);
pView->SetFocus();

Very naive, isn't' it? However, it doesn't have any visible effect on the application, because there is no easy way to impress the window at the bottom of the deep windows stack.

The next approach was found on Stack overflow (C++, MFC MDI, activate specific tab). It contains the code below:

C++
CMDIChildWnd* pChild = (CMDIChildWnd*)pMainFrame->GetActiveFrame();
// the if statement protect the application from the exception which can not be handled
if (pChild && ::IsWindow(pChild->GetSafeHwnd()) && pChild->IsChild(pView))
{
   pChild->SetActiveView(pView, TRUE);
}

This code is better than the previous one, it works when the document is selected :-). 

After some investigations with Microsoft Spy++ (by default, Visual Studio runs a 32 bit Microsoft Spy++) tool, I discovered that we've got a stack of Windows which produced the unreadable amount of messages and there is no use to touch this stack of windows...

Finally, I was able to find the code at the CMDIFrameWnd Class | Microsoft Learn page I need and it looks like:

C++
// this code is working
CMainFrame* pMainFrame = (CMainFrame*)AfxGetMainWnd();
CMDIChildWnd* child = pMainFrame->MDIGetActive();
do
{
    CString str;
    child->GetWindowText(str);
    if (str == path)
     {
         child->MDIActivate(); // or MDIActivate(child);
         break;
     }

     child = (CMDIChildWnd*)child->GetWindow(GW_HWNDNEXT);
} while (child);

And it works!

Points of Interest

I have no words to express my impression.

History

  • 8th December, 2022: Initial version

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)