0

I know how to force a CDialog to always stay on top of all other windows in your program ... non-modal. As seen in the test method below (code), you do not create by using *.DoModal. I understand this.

void CMFCTestAApp::OnOpenNonModalDialog()
{
  //dialogTest new_dialog;
  //new_dialog.DoModal();

  dialogTest* test_dialog = NULL;
  test_dialog = new dialogTest();
  if(test_dialog != NULL)
  {
    if(test_dialog->Create(IDD_TestA_DIALOG))
      test_dialog->ShowWindow(SW_SHOWNORMAL);
  }
}

However, I have been unsuccessful at doing the same with something which inherits from a CMultiDocTemplate/CFormView

Question: is there a way to keep a CFormView which is stuffed into a CMultiDocTemplate on the top (in the foreground ... like a non-modal CDialog behaves), even if that window is not the window which has focus. So in other words, i want classX, which inherits from CFormView to always stay in front of classY which inherits from CView.

Partial Success: I was able to achieve partial success. When classY's OnActivateView method was hit (this is the class/window which should be in the background), then, within its OnActivateView, i would loop through all the classX objects (the ones i want in front) and bring them to the front using classx->bringToTop(); This did work, however, there was a ridiculous amount of flickering going on ... I am guessing because (1) by time classY's OnActivateView is called, classY has already been brought to the front of all the classX objects AND because (2) OnActivateView doesn't just get called once but about six time (not sure why so many times) ... each object's OnActivateView gets called anytime Any other window gets activated (not just when window you care about gets activated).

Question: can anyone thing of a better way to implement this which i am missing or don't know about? I have already tried testing out the classx->SetWindowPos(&classx->wndTop,0,0,0,0,SWP_NOMOVE|SWP_NOSIZE) but this did not have an affect. I am guessing i am using this in the wrong place or it is getting undone in another part of the code.

Fractal
  • 1,748
  • 5
  • 26
  • 46
  • 1
    How about setting the `WS_EX_TOPMOST` extended window style when creating the window? – cha May 04 '16 at 06:45
  • 1
    It doesn't make sense for me to have a MDI interface with multiple documents and views and to force one of the forms to stay on top. Why? Maybe you construction is simply wrong and you shouldn't use a view here. – xMRi May 04 '16 at 07:05
  • xMRi: because the form is more like a dialog object .. the form which needs to stay on top is supposed to behave and has a similar purpose of the CDialog ... a helper UI for the main form/CDocument ... but for some reason it was coded as a CformView. – Fractal May 04 '16 at 19:07
  • cha: I already tried SetWindowPos ... I would think this would be similar to WS_EX_TOPMOST but it is worth a try. I found this stack overflow article on topmost (http://stackoverflow.com/questions/21204881/how-to-remove-ws-ex-topmost-style-from-window). It just sounds very familiar to wndTopMost which is used by SetWIndowPost (https://msdn.microsoft.com/en-us/library/a1yzfz6d.aspx). – Fractal May 04 '16 at 19:16
  • What makes this more confusing is that there are two SetWIndowPos ... one for the CWnd and one for the Hwnd. (https://msdn.microsoft.com/en-us/library/windows/desktop/ms633545%28v=vs.85%29.aspx?f=255&MSPPError=-2147217396). I am guessing the CWnd is the important one, but can't seem to get that one to force/manipulate the z-order of the windows. – Fractal May 04 '16 at 19:17

2 Answers2

1

Try to add a WM_ACTIVATETOPLEVEL message in your dialog , and use SetWindowPos() when chach WA_INACTIVE event.

like this:

void CMFCTestAApp::OnActivate(UINT nState, CWnd* pWndOther, BOOL bMinimized)
{
    CDialogEx::OnActivate(nState, pWndOther, bMinimized);

    // TODO: Add your message handler code here

    if (nState == WA_INACTIVE)
    {
        ::SetWindowPos( this->m_hWnd, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE );
    } 
}
IvoLiu
  • 41
  • 3
1

Try

SetWindowPos(&test_dialog->wndTopMost, 0,0,0,0, SWP_NOMOVE | SWP_NOSIZE);

I can affirm it worked for making some toolbars topmost in my case. But as toolbars are wrapped in a CMiniFrame object I had to do

CWnd* pWnd= pUserToolbar->GetParentMiniFrame();
if(pWnd)
    pWnd->SetWindowPos(&pWnd->wndTopMost, 0,0,0,0, SWP_NOMOVE | SWP_NOSIZE);
sergiol
  • 4,122
  • 4
  • 47
  • 81