Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • World
  • Users
  • Groups
Skins
  • Light
  • Cerulean
  • Cosmo
  • Flatly
  • Journal
  • Litera
  • Lumen
  • Lux
  • Materia
  • Minty
  • Morph
  • Pulse
  • Sandstone
  • Simplex
  • Sketchy
  • Spacelab
  • United
  • Yeti
  • Zephyr
  • Dark
  • Cyborg
  • Darkly
  • Quartz
  • Slate
  • Solar
  • Superhero
  • Vapor

  • Default (No Skin)
  • No Skin
Collapse
Code Project
  1. Home
  2. General Programming
  3. C / C++ / MFC
  4. Modeless Dialog box using win32 API only

Modeless Dialog box using win32 API only

Scheduled Pinned Locked Moved C / C++ / MFC
questionjson
4 Posts 2 Posters 0 Views 1 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • C Offline
    C Offline
    csrss
    wrote on last edited by
    #1

    Is there any way of doing it? I am trying to write some simple class for showing modeless dialog box and just cannot understand what is wrong with it. While it is pretty easy with DialogBoxParam - there seems to be no way with CreateDialog. My goal is to pass somehow a pointer to a class to call my dlgProc. The way i am doing it with modal dlgbox:

    INT_PTR DoModal(UINT nResourceId)
    {
    ::InitCommonControls();
    return ::DialogBoxParam(::GetModuleHandle(NULL),
    MAKEINTRESOURCE(nResourceId),
    NULL, DlgProcModal, reinterpret_cast(this));
    }

    static INT_PTR __stdcall DlgProcModal(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
    {
    ....
    if( uMsg == WM_INITDIALOG )
    {
    if( !pWnd )
    {
    pWnd = reinterpret_cast(lParam);
    ::SetWindowLongPtr(hwndDlg, GWLP_USERDATA, (LONG_PTR)pWnd);
    pWnd->m_hWnd = hwndDlg;
    }
    }
    }

    The way i am trying to do it with modeless and it is just not working:

    INT_PTR DoModeless(UINT nResourceId)
    {
    ::InitCommonControls();
    if( m_hWnd = ::CreateDialog(::GetModuleHandle(NULL), MAKEINTRESOURCE(nResourceId), NULL, DlgProcModeless) )
    {
    m_bModeless = true;
    ::SetWindowLongPtr(m_hWnd, GWLP_USERDATA, (LONG_PTR)this);

    	MSG msg = { 0x00 };
    	while (::GetMessage(&msg, m\_hWnd, 0, 0)) 
    	{ 
    		if (!::IsDialogMessage(m\_hWnd, &msg))
    		{ 
    			::TranslateMessage(&msg); 
    			::DispatchMessage(&msg); 
    		}
    	}
    }
    ::DestroyWindow(m\_hWnd);
    return 0;
    

    }

    static INT_PTR __stdcall DlgProcModeless(
    HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam
    )
    {
    LONG_PTR lResult = ::GetWindowLongPtr(hwndDlg, GWLP_USERDATA);
    CBaseDlgWindow * pWnd = reinterpret_cast(lResult);
    ...
    }

    What am i doing wrong? Thanks in advance.

    011011010110000101100011011010000110100101101110 0110010101110011

    P 1 Reply Last reply
    0
    • C csrss

      Is there any way of doing it? I am trying to write some simple class for showing modeless dialog box and just cannot understand what is wrong with it. While it is pretty easy with DialogBoxParam - there seems to be no way with CreateDialog. My goal is to pass somehow a pointer to a class to call my dlgProc. The way i am doing it with modal dlgbox:

      INT_PTR DoModal(UINT nResourceId)
      {
      ::InitCommonControls();
      return ::DialogBoxParam(::GetModuleHandle(NULL),
      MAKEINTRESOURCE(nResourceId),
      NULL, DlgProcModal, reinterpret_cast(this));
      }

      static INT_PTR __stdcall DlgProcModal(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
      {
      ....
      if( uMsg == WM_INITDIALOG )
      {
      if( !pWnd )
      {
      pWnd = reinterpret_cast(lParam);
      ::SetWindowLongPtr(hwndDlg, GWLP_USERDATA, (LONG_PTR)pWnd);
      pWnd->m_hWnd = hwndDlg;
      }
      }
      }

      The way i am trying to do it with modeless and it is just not working:

      INT_PTR DoModeless(UINT nResourceId)
      {
      ::InitCommonControls();
      if( m_hWnd = ::CreateDialog(::GetModuleHandle(NULL), MAKEINTRESOURCE(nResourceId), NULL, DlgProcModeless) )
      {
      m_bModeless = true;
      ::SetWindowLongPtr(m_hWnd, GWLP_USERDATA, (LONG_PTR)this);

      	MSG msg = { 0x00 };
      	while (::GetMessage(&msg, m\_hWnd, 0, 0)) 
      	{ 
      		if (!::IsDialogMessage(m\_hWnd, &msg))
      		{ 
      			::TranslateMessage(&msg); 
      			::DispatchMessage(&msg); 
      		}
      	}
      }
      ::DestroyWindow(m\_hWnd);
      return 0;
      

      }

      static INT_PTR __stdcall DlgProcModeless(
      HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam
      )
      {
      LONG_PTR lResult = ::GetWindowLongPtr(hwndDlg, GWLP_USERDATA);
      CBaseDlgWindow * pWnd = reinterpret_cast(lResult);
      ...
      }

      What am i doing wrong? Thanks in advance.

      011011010110000101100011011010000110100101101110 0110010101110011

      P Offline
      P Offline
      pasztorpisti
      wrote on last edited by
      #2

      First, you probably have a main message loop somewhere that dispatches messages to every window (and dialog), not only to a specified window:

      // global variable, it contains the handle of all dialogs
      std::vector g_Dialogs;

      // your main loop somewhere near your main()
      MSG msg;
      while (::GetMessage(&msg, NULL, 0, 0))
      {
      // copying the global array because it might be modified during iteration
      // and we iterate over the copy...
      std::vector dialogs(g_Dialogs);
      bool was_dialog_message = false;
      for (size_t i=0,e=dialogs.size(); i

      When you want a modeless dialog, you just create it with CreateDialog(), put its handle to g_Dialogs and thats it. You don't have to run a local message loop like with modal messageboxes, especially not with a specified single window handle (m_hWnd). A modeless dialog works almost like a normal window that you created with CreateWindowEx(), you just have to handle it a bit specially with IsDialogMessage(). In a modeless multi-windowed gui program its always enough one message loop - the main message loop pumps the messages for all modeless windows.

      EDIT: warning: while you are iterating over the g_Dialogs vector, the contents of the vector might change because you dispatch messages to dialogs that can respond to those messages by creating/deleting dialogs! To avoid bugs caused by this you either use a custom container that can be modified during iteration or solve it somehow else. One good solution can be copying the vector before iteration and iterating on the copied vector, still some HWNDs might become invalid during iteration so before IsDialogMessage() it might be wise to call IsWindow() on the handles.

      C 1 Reply Last reply
      0
      • P pasztorpisti

        First, you probably have a main message loop somewhere that dispatches messages to every window (and dialog), not only to a specified window:

        // global variable, it contains the handle of all dialogs
        std::vector g_Dialogs;

        // your main loop somewhere near your main()
        MSG msg;
        while (::GetMessage(&msg, NULL, 0, 0))
        {
        // copying the global array because it might be modified during iteration
        // and we iterate over the copy...
        std::vector dialogs(g_Dialogs);
        bool was_dialog_message = false;
        for (size_t i=0,e=dialogs.size(); i

        When you want a modeless dialog, you just create it with CreateDialog(), put its handle to g_Dialogs and thats it. You don't have to run a local message loop like with modal messageboxes, especially not with a specified single window handle (m_hWnd). A modeless dialog works almost like a normal window that you created with CreateWindowEx(), you just have to handle it a bit specially with IsDialogMessage(). In a modeless multi-windowed gui program its always enough one message loop - the main message loop pumps the messages for all modeless windows.

        EDIT: warning: while you are iterating over the g_Dialogs vector, the contents of the vector might change because you dispatch messages to dialogs that can respond to those messages by creating/deleting dialogs! To avoid bugs caused by this you either use a custom container that can be modified during iteration or solve it somehow else. One good solution can be copying the vector before iteration and iterating on the copied vector, still some HWNDs might become invalid during iteration so before IsDialogMessage() it might be wise to call IsWindow() on the handles.

        C Offline
        C Offline
        csrss
        wrote on last edited by
        #3

        Hey, thanks for your reply. My problem was that i couldn't find a way to put the whole thing into nice C++ class of my own. But, problem was solved by using CreateDialogParam instead. So i can pass a pointer to the dialog class to a main message loop so i can call my own virtual methods inside children classes. Cheers.

        011011010110000101100011011010000110100101101110 0110010101110011

        P 1 Reply Last reply
        0
        • C csrss

          Hey, thanks for your reply. My problem was that i couldn't find a way to put the whole thing into nice C++ class of my own. But, problem was solved by using CreateDialogParam instead. So i can pass a pointer to the dialog class to a main message loop so i can call my own virtual methods inside children classes. Cheers.

          011011010110000101100011011010000110100101101110 0110010101110011

          P Offline
          P Offline
          pasztorpisti
          wrote on last edited by
          #4

          I though that your problem is the messagebox because your loop was inside the DoModeless() method. Anyway, your previous hooking is also fine, you just miss a few messages that come before the return of your CreateDialog() call and you have to handle uninitialized GWLP_USERDATA cases as well. Even if you initialize userdata from WM_INITDIALOG it might be better to handle uninitialized cases, who knows what the future brings? :-)

          1 Reply Last reply
          0
          Reply
          • Reply as topic
          Log in to reply
          • Oldest to Newest
          • Newest to Oldest
          • Most Votes


          • Login

          • Don't have an account? Register

          • Login or register to search.
          • First post
            Last post
          0
          • Categories
          • Recent
          • Tags
          • Popular
          • World
          • Users
          • Groups