Click here to Skip to main content
15,559,669 members
Articles / Desktop Programming / MFC
Tip/Trick
Posted 8 Dec 2022

Tagged as

Stats

8.3K views
7 bookmarked

Activate Document Window in MDI Application

Rate me:
Please Sign up or sign in to vote.
4.62/5 (4 votes)
8 Dec 2022CPOL2 min read
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)


Written By
Software Developer (Senior) NetCracker
Russian Federation Russian Federation
I came to the industry at the end of that times when the computer program executes as it was written. I saw a quite big machines, occupied more than 100 square meters for its central processor, but I started my professional activity as a programmer on IBM PC clones. There were different CPU architectures (68k, PowerPC, 386/486, SPARC...) when I began, but Intel defeated them all with Pentium CPU (marketing) family.
I saw the knowledge and technology fragmentation. I saw many technologies started, developed and retired. However, I have not seen many things yet.
I have some experience, but my experience is not perfectly comprehensive. I still have many things to learn and I still cannot make a poker face when I find out some aspects about how the things were designed and works. My experience does not make me an absolute expert in some areas, because these areas are changing. I know some things, but I also understand that some things I know could be useless for nowadays.

Comments and Discussions

 
GeneralMy vote of 5 Pin
Shao Voon Wong9-Dec-22 1:33
mvaShao Voon Wong9-Dec-22 1:33 
GeneralRe: My vote of 5 Pin
Alexey Shtykov9-Dec-22 3:33
professionalAlexey Shtykov9-Dec-22 3:33 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.