title: Calling ShowWindow(SW_SHOW) on ATL modeless dialog not bringing window to front
body: <p>I have a modeless dialog which I am showing and hiding programmatically from a worker thread. The problem is that the <em>CWindow::ShowWindow(SW_SHOW)</em> function is sometimes bringing the dialog to the front, and sometimes not.</p>
  <p>Task: Show/Hide a simple logging &amp; control window for an ATL COM object (dll) that runs in a separate thread. The COM object isn't a control: it is being used to wrap processing code for use in Excel VBA.</p>
  <p>I've created a CMyDialog class derived from the CAxDialogImpl template. Then I'm using the CWorkerThread template for the worker thread. This is the Execute block (ie the function that runs in the worker thread).</p>
  <pre><code>HRESULT CLogProcessor::Execute(DWORD_PTR dwParam, HANDLE hObject)
  {
      m_bRunning = true; //Winging it as this isn't thread-safe, but I don't think that's the issue.
      if (m_pDlg == 0)
      {
          m_pDlg = new CMyDialog(); //My dialog class
          m_pDlg-&gt;SetStopEvent(m_hStopEvent); //Save the handle of the stop event in the Dialog class
          m_pDlg-&gt;Create(NULL); //Create with no parent
          m_pDlg-&gt;ShowWindow(SW_SHOW); //Show the window
      }
  
      //Loop here until told to stop by the Stop Event being signalled in the calling thread
      while (WaitForSingleObject(m_hStopEvent, 0) == WAIT_TIMEOUT) //Polling Stop Event
      {
          //Have to keep the message loop going!
          MSG uMsg;
          while (PeekMessage(&amp;uMsg, m_pDlg-&gt;m_hWnd, 0, 0, PM_REMOVE))
          {
              TranslateMessage(&amp;uMsg);
              DispatchMessage(&amp;uMsg);
          }
          
          //The thread uses a protected &quot;stack&quot; of string messages to write to my logging window
          string strMsg;
          while (m_MsgStack.PopFront(strMsg))
          {
              std::wstring ws = std::wstring(strMsg.begin(), strMsg.end());
              CWindow eb(m_pDlg-&gt;GetDlgItem(IDC_EDIT1));
              eb.SendMessage(EM_REPLACESEL, 0, (LPARAM)ws.c_str());
          }
      }
  
      //Stop event has been signalled so clear up the dialog
      m_pDlg-&gt;DestroyWindow();
      delete m_pDlg;
      m_pDlg = 0;
  
      m_bRunning = false;
  
      return S_OK;
  }
  </code></pre>
  <p>My Log object has two functions, StartLog() and StopLog() which are called by the COM object which is doing the main work of data processing.</p>
  <pre><code>void CLogProcessor::StartLog()
  {
      if (!m_bRunning)
      {
          ::SetEvent(m_hStartEvent);
      }
  }
  
  void CLogProcessor::StopLog()
  {
      if (m_bRunning)
      {
          ::SetEvent(m_hStopEvent);
      }
  }
  </code></pre>
  <p>This works fine. I run VBA code in an Excel spreadsheet with buttons that call (via the COM object) StartLog() and StopLog(). The first time the Log Dialog appears all is good: it is activated and comes to the front. Firing StopLog() closes the dialog and it disappears. But the <strong>second</strong> time I call StartLog() the dialog window appears but it is not at the front, but behind other windows. I have tried a <em>CWindow::BringWindowToTop()</em> and/or <em>SetFocus()</em> call straight after the ShowWindow() but it makes no difference.</p>
  <p>Another interesting feature is that my dialog has a system menu and so an 'X' to close it in the top-right hand corner. In the Dialog's message map, I am handling the WM_CLOSE message:</p>
  <pre><code>    BEGIN_MSG_MAP(CMyDialog)
          ... Other entries
          MESSAGE_HANDLER(WM_CLOSE, OnClose)
          ...
         CHAIN_MSG_MAP(CAxDialogImpl&lt;CMyDialog&gt;)
      END_MSG_MAP()
  </code></pre>
  <p>With OnClose() setting the Stop Event handle (previously passed to the Dialog object). Ie doing pretty much the same as the StopLog() function.</p>
  <pre><code>LRESULT CMyDialog::OnClose(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL&amp; bHandled)
  {
      ::SetEvent(m_hStopEvent);
      
      return 0;
  }
  </code></pre>
  <p>If I close the log dialog with the mouse click, it goes away as before. BUT the next time I call StartLog() the dialog does what it is supposed to do and comes to the front, which is the action I want. So I replaced the StopLog() code with a SendMessage(WM_CLOSE) to my dialog: it closed the window, but again it did not reappear on top. Another difference is that using the Close X on the dialog means that the Dialog has the focus when it is closed. Closing it from the Excel button means that the Excel window has the focus.</p>
  <p>I realize this is rather a long question, and thanks very much if you have soldiered down to the end! I'd been keen for any solution / insight.</p>