title: How to create a modeless dialog from a worker thread when main GUI thread is blocked?
body: <p>My goal is to write a class (let's call it <code>CProgressDlg</code>) that can be used to display a dialog window with a progress bar when some operation in the main UI thread takes longer than, say 1 second, to finish. So a previously written method:</p>
  
  <pre><code>if(do_work)
  {
      for(int i = 0; i &lt; a_lot; i++)
      {
          //Do work...
          ::Sleep(100);     //Use sleep to simulate work
      }
  }
  </code></pre>
  
  <p>can be easily adjusted as something like this (pseudo-code):</p>
  
  <pre><code>if(do_work)
  {
      CProgressDlg m_progDlg;
  
      for(int i = 0; i &lt; a_lot; i++)
      {
          //Do work...
          ::Sleep(100);     //Use sleep to simulate work
  
          if(m_progDlg.UpdateWithProgress(i))
          {
              //User canceled it
              break;
          }
      }
  }
  </code></pre>
  
  <p>So to implement it I would start a worker thread from the <code>CProgressDlg</code> constructor:</p>
  
  <pre><code>::CreateThread(0, 0, ThreadProcProgressDlg, (LPVOID)0, 0, 0);
  </code></pre>
  
  <p>And then from a worker thread I would create a modeless dialog that will display the progress bar and a cancel button for the user:</p>
  
  <pre><code>DWORD WINAPI ThreadProcProgressDlg(
    _In_ LPVOID lpParameter
  )
  {
      //Wait a little
      ::Sleep(1000);
  
      HMODULE hModule = AfxGetResourceHandle();
      ASSERT(hModule);
  
      //Get parent window
      //(Can't use main window, as its UI thread is blocked)
      HWND hParentWnd = NULL;
  
      const static BYTE dlgTemplate[224] = {
          0x1, 0x0, 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xc8, 0x0, 0xc8, 0x90, 0x4, 0x0, 0x0, 0x0, 0x0, 0x0, 0xdb, 0x0, 0x4b, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8, 0x0, 0x90, 0x1, 0x0, 0x1, 0x4d, 0x0, 0x53, 0x0, 0x20, 0x0, 0x53, 0x0, 0x68, 0x0, 0x65, 0x0, 0x6c, 0x0, 0x6c, 0x0, 0x20, 0x0, 0x44, 0x0, 0x6c, 0x0, 0x67, 0x0, 0x0, 0x0, 
          0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x0, 0x1, 0x50, 0x92, 0x0, 0x36, 0x0, 0x42, 0x0, 0xe, 0x0, 0x2, 0x0, 0x0, 0x0, 0xff, 0xff, 0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x81, 0x0, 0x2, 0x50, 0x7, 0x0, 0x7, 0x0, 0xcd, 0x0, 0x19, 0x0, 0xed, 0x3, 0x0, 0x0, 0xff, 0xff, 0x82, 0x0, 0x0, 0x0, 0x0, 0x0, 
          0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x80, 0x50, 0x7, 0x0, 0x21, 0x0, 0xcd, 0x0, 0x7, 0x0, 0xec, 0x3, 0x0, 0x0, 0x6d, 0x0, 0x73, 0x0, 0x63, 0x0, 0x74, 0x0, 0x6c, 0x0, 0x73, 0x0, 0x5f, 0x0, 0x70, 0x0, 0x72, 0x0, 0x6f, 0x0, 0x67, 0x0, 0x72, 0x0, 0x65, 0x0, 0x73, 0x0, 0x73, 0x0, 0x33, 0x0, 0x32, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 
          0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x81, 0x0, 0x2, 0x50, 0x7, 0x0, 0x29, 0x0, 0xcd, 0x0, 0x8, 0x0, 0xee, 0x3, 0x0, 0x0, 0xff, 0xff, 0x82, 0x0, 0x0, 0x0, 0x0, 0x0, };
  
      //Show dialog
      HWND hDlgWnd = ::CreateDialogIndirectParam(hModule, (LPCDLGTEMPLATE)dlgTemplate, hParentWnd, DlgWndProc, (LPARAM)0);
      ASSERT(hDlgWnd);
      if(hDlgWnd)
      {
          ::ShowWindow(hDlgWnd, SW_SHOW);
      }
  
      return 0;
  }
  </code></pre>
  
  <p>Where the minimal dialog procedure (just to display it) will be something like this:</p>
  
  <pre><code>INT_PTR CALLBACK DlgWndProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
  {
      UNREFERENCED_PARAMETER(wParam);
      UNREFERENCED_PARAMETER(lParam);
  
      switch (uMsg)
      {
          case WM_INITDIALOG:
          {
          }
          return TRUE;
  
          case WM_COMMAND:
          {
              UINT uCmd = LOWORD(wParam);
  
              if (uCmd == IDOK || 
                  uCmd == IDCANCEL)
              {
                  ::DestroyWindow(hDlg);
  
                  return (INT_PTR)TRUE;
              }
          }
          break;
      }
  
      return (INT_PTR)FALSE;
  }
  </code></pre>
  
  <p>But when I run this code, my modeless dialog is shown for a split second and then disappears. I understand that I probably haven't done something to display it properly from a worker thread. </p>
  
  <p>Any idea what am I missing?</p>