CodeGuru Home VC++ / MFC / C++ .NET / C# Visual Basic VB Forums Developer.com
Results 1 to 13 of 13
  1. #1
    Join Date
    Aug 2002
    Posts
    756

    [RESOLVED] MDI "More Windows..." dialog

    Hi, ALL,
    How do I implement my own "More Windows..." dialog? I need to know the standard ID that is being used by Windows...

    Thank you.

  2. #2
    Join Date
    Feb 2003
    Location
    Iasi - Romania
    Posts
    8,234

    Re: MDI "More Windows..." dialog

    I presume you need a dialog that displays a list of all open documents in an MDI application in order to activate or close one of the corresponding MDI child windows. Is that true?
    Ovidiu
    "When in Rome, do as Romans do."
    My latest articles: https://codexpertro.wordpress.com/

  3. #3
    Join Date
    Aug 2002
    Posts
    756

    Re: MDI "More Windows..." dialog

    Yes, you are correct.

    Thank you.

  4. #4
    Join Date
    Feb 2003
    Location
    Iasi - Romania
    Posts
    8,234

    Re: MDI "More Windows..." dialog

    Well then, you can do the following:
    1. Get a list of all documents open in the MDI application
    2. Use this list to fill a listbox or listview control in "More Windows..." dialog; basically can add document titles and keep a pointer to document object in each item data.
    3. Handle button commands in order to activate or do anything else with the document selected in the listbox/listview.

    Here is a sample function which enumerates documents:
    Code:
    void CSomeMDIApp::GetAllDocuments(CTypedPtrList<CObList, CDocument*>& listDocs)
    {
       listDocs.RemoveAll();
       POSITION posDocTemplate = GetFirstDocTemplatePosition();
       while(NULL != posDocTemplate)
       {
          CDocTemplate* pDocTemplate = GetNextDocTemplate(posDocTemplate);
          POSITION posDoc = pDocTemplate->GetFirstDocPosition();
          while(NULL != posDoc)
          {
             CDocument* pDoc = pDocTemplate->GetNextDoc(posDoc);
             listDocs.AddTail(pDoc); 
          }
       }
    }
    You can find something similar with more implementation details in my weblog: http://codexpert.ro/blog/2012/12/22/...-applications/
    Last edited by ovidiucucu; December 22nd, 2012 at 01:11 PM.
    Ovidiu
    "When in Rome, do as Romans do."
    My latest articles: https://codexpertro.wordpress.com/

  5. #5
    Join Date
    Aug 2002
    Posts
    756

    Re: MDI "More Windows..." dialog

    ovidiucucu,
    Yes, I understand all of this.
    My question though is a little different.

    I have MDI application. By default in the MDI application if there are more than 9 windows open, system will show additional menu item "More Windows..." in the "Window" menu in the menu bar.

    What I'm interested in is: what id does this newly created menu have?
    Then all I will need is to respond to this menu selection with the appropriate dialog.
    I don't want to override the system behavior to display this menu every time. I want to keep the system functionality.

    Thank you.

  6. #6
    Join Date
    Feb 2003
    Location
    Iasi - Romania
    Posts
    8,234

    Re: MDI "More Windows..." dialog

    Quote Originally Posted by OneEyeMan View Post
    ovidiucucu,
    [...]
    I have MDI application. By default in the MDI application if there are more than 9 windows open, system will show additional menu item "More Windows..." in the "Window" menu in the menu bar.

    What I'm interested in is: what id does this newly created menu have?
    Then all I will need is to respond to this menu selection with the appropriate dialog.
    The "More Windows..." menu item value is... 0x0000FF09.
    Please don't tell it to anybody! It's one of the most terrible secrets kept by Microsoft...

    Now serios, getting rid of some "hacking" methods to find that magic number, we can do the folowing "investigation":
    1. Search in "AFXRES.H" where are usally defined the IDs used by he MFC framework. We can find these menu command IDs:
      Code:
      // Window commands
      #define ID_WINDOW_NEW                   0xE130
      #define ID_WINDOW_ARRANGE               0xE131
      #define ID_WINDOW_CASCADE               0xE132
      #define ID_WINDOW_TILE_HORZ             0xE133
      #define ID_WINDOW_TILE_VERT             0xE134
      #define ID_WINDOW_SPLIT                 0xE135
      #ifndef RC_INVOKED      // code only
      #define AFX_IDM_WINDOW_FIRST            0xE130
      #define AFX_IDM_WINDOW_LAST             0xE13F
      #define AFX_IDM_FIRST_MDICHILD          0xFF00  // window list starts here
      #endif //!RC_INVOKED
      Hmmm... nothing about "More Windows...", but AFX_IDM_FIRST_MDICHILD (commented with "window list starts here") seems to be closer to what we need.
    2. Search AFX_IDM_FIRST_MDICHILD in MFC source files. Beside other places, two may be interesting for us:
      Code:
      BOOL CMDIFrameWnd::OnCommand(WPARAM wParam, LPARAM lParam)
      {
         // ...
         ASSERT(AFX_IDM_FIRST_MDICHILD == 0xFF00);
         if (hWndCtrl == NULL && (LOWORD(wParam) & 0xf000) == 0xf000)
         {
            // menu or accelerator within range of MDI children
            // default frame proc will handle it
            DefWindowProc(WM_COMMAND, wParam, lParam);
            return TRUE;
         }
         // ...
      Code:
      BOOL CMDIFrameWnd::CreateClient(LPCREATESTRUCT lpCreateStruct,
      	CMenu* pWindowMenu)
      {
         // ...
         CLIENTCREATESTRUCT ccs;
         // ...
         ccs.idFirstChild = AFX_IDM_FIRST_MDICHILD;
         // ...
    3. Having a look in that code, we can say: "good news and bad news!"
      • Bad news: The Windows menu items for activating some open MDI child plus "More Windows..." menu item, are not added by the MFC framework. Also, the corresonding comand IDs are not handled in the MFC freamework, but in default window procedure. Most possible, for that reason, MFC team didn't define IDs for each of them.
      • Good news: Now we know that in MFC, first ID has AFX_IDM_FIRST_MDICHILD value. Next IDs are in order, incremented by one. If more than 8 MDI child windows are open, the system adds the "More Windows..." menu item having value AFX_IDM_FIRST_MDICHILD + 9.
    4. Finally let's handle it!
      Code:
      // MainFrm.h
      #define IDM_APP_MOREWINDOWS (AFX_IDM_FIRST_MDICHILD + 9)
      
      class CMainFrame : public CMDIFrameWnd
      {
         // ...
         afx_msg void OnAppMoreWindows();
      };
      Code:
      // MainFrm.cpp
      // ...
      #include "MoreWindowsDlg.h" // our custom "More Windows..." dialog class
      // ...
         ON_COMMAND(IDM_APP_MOREWINDOWS, OnAppMoreWindows)
      END_MESSAGE_MAP()
      // ...
      void CMainFrame::OnAppMoreWindows()
      {
         // "More Windows..." menu item has been selected.
         // Show our own custom "More Windows" dialog;
         CMoreWindowsDlg dlg;
         dlg.DoModal();
      }


    // (Working with MFC is) piece of cake, no sweat, like a walking in the park...
    Last edited by ovidiucucu; December 23rd, 2012 at 01:14 PM. Reason: typo
    Ovidiu
    "When in Rome, do as Romans do."
    My latest articles: https://codexpertro.wordpress.com/

  7. #7
    Join Date
    Feb 2003
    Location
    Iasi - Romania
    Posts
    8,234

    Re: MDI "More Windows..." dialog

    Just to conclude in fewer words:
    There is no standard ID for "More Windows..." command.
    It depends on value passed in CLIENTCREATESTRUCT::idFirstChild when creating the MDI Client window.
    In MFC framework implemetation, the command ID for "More Windows..." menu is AFX_IDM_FIRST_MDICHILD + 9.
    Ovidiu
    "When in Rome, do as Romans do."
    My latest articles: https://codexpertro.wordpress.com/

  8. #8
    Join Date
    Aug 2002
    Posts
    756

    Re: MDI "More Windows..." dialog

    ovidiucucu,
    So how do I determine the id of this menu item in plain Win32 application?
    Just scan the "Window" menu till the end if the MDI child list is more than 9?

    All I want is to react to the appropriate Windows command and use my own dialog for that.
    I know how to make the dialog and all that but what I don't know is what to react to.

    Thank you.

    [EDIT]
    P.S. Or let me ask it a different way. Is there a standard handler for this menu inside Windows? It looks like it as there is no such handler in simple MFC wizard generated code, but it's just MFC...
    [/EDIT]
    Last edited by OneEyeMan; December 29th, 2012 at 04:36 AM.

  9. #9
    Join Date
    Feb 2003
    Location
    Iasi - Romania
    Posts
    8,234

    Re: MDI "More Windows..." dialog

    First, please let me try to clarify this, which seems to be a little bit confusing:
    Quote Originally Posted by OneEyeMan View Post
    [...]
    Is there a standard handler for this menu inside Windows? It looks like it as there is no such handler in simple MFC wizard generated code, but it's just MFC...
    There is not any "standard handler" in Windows. A message handler is an application-defined function designed to "handle" (process) a message (doing something as a response to a message sent to a window).
    For example, in a raw-WinAPI program we can have the following:
    Code:
    void OnTimer(HWND hWnd, UINT nIDEvent); // WM_TIMER message handler
    // ...
    
    // Window procedure. Processes all messages sent to a window
    LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
    {
       switch (message)
       {
       case WM_TIMER:
          OnTimer(hWnd, (UINT)wParam);
          break;
       // ...
       // ...
       default:
          return DefWindowProc(hWnd, message, wParam, lParam);
       }
       return 0;
    }
    //...
    
    // WM_TIMER message handler. Processes  WM_TIMER message.
    void OnTimer(HWND hWnd, UINT nIDEvent)
    {
       // handle WM_TIMER message here.
    }
    OnTimer is a handler for WM_TIMER messages. I've called it "OnTimer" just to be asier for anybody to get what that function is doing, not because it is "standard". Someone else can call it "HumptyDumpty", as well.

    In MFC there is something similar, except that message handlers are class member functions and MFC Wizard makes our life easier, by "mapping" message handlers with the help of some macros:
    Code:
    class CMainFrame : public CMDIFrameWnd
    { 
       // ...
       afx_msg void OnTimer(UINT_PTR nIDEvent);
    };
    // ...
    
    BEGIN_MESSAGE_MAP(CMainFrame, CMDIFrameWnd)
       ON_WM_TIMER()
    END_MESSAGE_MAP()
    // ...
    
    void CMainFrame::OnTimer(UINT_PTR nIDEvent)
    {
       // TODO: Add your message handler code here and/or call default
       CMDIFrameWnd::OnTimer(nIDEvent);
    }
    Again, even here "OnTimer" isn't a "standard handler". If my muscles really want , I can, for example, manually map WM_TIMER as follows:
    Code:
    class CMainFrame : public CMDIFrameWnd
    { 
       // ...
       afx_msg LRESULT HumptyDumpty(WPARAM wParam, LPARAM lParam);
    };
    // ...
    
    BEGIN_MESSAGE_MAP(CMainFrame, CMDIFrameWnd)
       ON_MESSAGE(WM_TIMER, HumptyDumpty)
    END_MESSAGE_MAP()
    // ...
    
    LRESULT CMainFrame::HumptyDumpty(WPARAM wParam, LPARAM lParam)
    {
       UINT_PTR nIDEvent = (UINT_PTR)wParam;
       // Handle WM_TIMER here.
       return 0;
    }
    Or can override CWnd::WindowProc and map a handler function in a way more similar to that from raw-WinAPI example.
    Of course, I'll never do something like that in practice, for an MFC application. It's just an example to demonstrate what I said in the top of this post.

    [to be continued]
    Last edited by ovidiucucu; December 30th, 2012 at 04:51 AM.
    Ovidiu
    "When in Rome, do as Romans do."
    My latest articles: https://codexpertro.wordpress.com/

  10. #10
    Join Date
    Aug 2002
    Posts
    756

    Re: MDI "More Windows..." dialog

    ovidiucucu,
    That is all correct statements.
    However, let me try to clarify what I meant.

    Let's say I have a dialog where I have a list box. There are predefined message that is sent to that list box.
    One of such messages is LB_SETCURSEL.
    Now somewhere, in one of the Windows DLL, there is a predefined handler for that message which will do the following:

    1. Search for the string that is passed as a parameter to this message in the inner string container of the list box
    2. If the string is found, it will be scrolled into a view and the background of this string will be painted blue (or the predefined themed colour).
    3. If the string passed to this message will not be found, nothing happens.

    Now, in your (my) program we can override such behavior by defining our own message handler for the LB_SETCURSEL message which might do some additional stuff or just paint the background red or just do some error message if the string passed will not be found. It is up to an application. Nevertheless the default behavior which is defined inside Windows for that message will stay.

    Now my question is: Is there a predefined handler that will display "More Windows..." dialog in response to me selecting the menu? If it is - great, it means I don't need to do anything in my app. If it does not exist - I'd like to know what message to connect such a handler on pure Win32 application.

    I hope I made myself clear this time.

    Thank you.

  11. #11
    Join Date
    Feb 2003
    Location
    Iasi - Romania
    Posts
    8,234

    Re: MDI "More Windows..." dialog

    [ continued ]

    Now, returning a little bit closer to OP problem.
    When the user chooses a menu item, the window receives WM_COMMAND notification message, having the menu item identifier in lower word of WPARAM.
    So, in a raw-WinAPI program we can handle a given menu item command having, let's say ID_FILE_NEW identifier, as follows:

    Code:
    void OnFileNew(); // ID_FILE_NEW command handler
    // ...
    
    LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
    {
       switch (message)
       {
       case WM_COMMAND:
          switch(LOWORD(wParam))
          {
          case ID_FILE_NEW:
             OnFileNew();
             break;
          // ...
      // ...
    }
    // ...
    
    // Handle WM_COMMAND notification message for ID_FILE_NEW menu item
    void OnFileNew()
    {
       // do something cool here!
    }
    Again, OnFileNew isn't "standard", I've named it like that for the sake of code readability.

    In a MFC-based program, the good MFC Wizard can help us by mapping a handler for ID_FILE_NEW as follows:
    Code:
    class CMainFrame : public CMDIFrameWnd
    {
       // ...
       afx_msg void OnFileNew();
    };
    // ...
    
    BEGIN_MESSAGE_MAP(CMainFrame, CMDIFrameWnd)
       // ...
       ON_COMMAND(ID_FILE_NEW, &CMainFrame::OnFileNew)
    END_MESSAGE_MAP()
    // ...
    
    void CMainFrame::OnFileNew()
    {
       // TODO: Add your command handler code here
    }
    And again, also here "OnFileNew" isn't "standard". As I said in the previous post, it is possible to map that command in other way.

    Nice and easy, like a walking in the park, as long as ID_FILE_NEW has been found in the project's resources.
    Otherwise, there's no way, we have to map it manually. The Wizard isn't enough empathic to guess and/or has not a glass ball to see that we want to map a command identifier which isn't present in the project's resources.

    This is case of that "More Windows..." menu command, which has not an ID defined in our application's resources. Not even in the MFC framework...
    See my earlier posts, #6 and #7.

    [ to be continued ]
    Last edited by ovidiucucu; December 30th, 2012 at 06:24 AM.
    Ovidiu
    "When in Rome, do as Romans do."
    My latest articles: https://codexpertro.wordpress.com/

  12. #12
    Join Date
    Feb 2003
    Location
    Iasi - Romania
    Posts
    8,234

    Re: MDI "More Windows..." dialog

    [ continued ]

    Quote Originally Posted by OneEyeMan View Post
    Now my question is: Is there a predefined handler that will display "More Windows..." dialog in response to me selecting the menu? If it is - great, it means I don't need to do anything in my app. If it does not exist - I'd like to know what message to connect such a handler on pure Win32 application.
    Of course, there is a predefined handler that will display "More Windows..." dialog somewhere in the default window procedure.
    As long as a menu command is sent via WM_COMMAND message, you can change the default by handling WM_COMMAND in your own application-defined window procedure.
    Additionally, you have to know the menu item ID (see examples in post #11).

    • In an MFC application this ID has the value AFX_IDM_FIRST_MDICHILD + 9 (see #7)
    • In a raw-WinAPI application, it is 9 plus the value of idFirstChild member of CLIENTCREATESTRUCT structure used when your application creates the MDI Client window (also, see #7).
    Ovidiu
    "When in Rome, do as Romans do."
    My latest articles: https://codexpertro.wordpress.com/

  13. #13
    Join Date
    May 1999
    Location
    ALABAMA, USA
    Posts
    9,917

    Re: MDI "More Windows..." dialog

    I am somewhat confused here.
    A question to OOP:
    Are you trying to override MFC MDI application default behavior or you are trying to implement MFC "More Windows…" behavior in Win32 application?
    There are only 10 types of people in the world:
    Those who understand binary and those who do not.

Tags for this Thread

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  





Click Here to Expand Forum to Full Width

Featured