Professional UI Solutions
Site Map   /  Register
 
 

Forum

Please Log In to post a new message or reply to an existing one. If you are not registered, please register.

NOTE: Some forums may be read-only if you are not currently subscribed to our technical support services.

Forums » Prof-UIS General Discussion » MainFrame wnd loosing focus on internal windows (2.83) Collapse All
Subject Author Date
Andrej Kasa Jun 15, 2008 - 9:58 AM

Hello,


after upgrade to 2.83 (from 2.82) I’ve found out that the MainFrame window is loosing focus when a new internal window (meaning own window of the app) is opened as shown in the attached screenshot. It happens on dialog windows as you can see and as well on windows like MessageBox, etc.


Is that behaviour a bug or a new feature? Is it somehow possible to configure ProfUIS so that the focus is lost only on external windows? Because it does not look good as you can see on the screenshot.



best regards,


krompo


 

Andrej Kasa Jun 19, 2008 - 7:14 AM

hi,


to demostrate this issue (in version 2.83) see the 2 following screenshot. Both open a modal dialog box (about box) where in the case of the first one dialog is opened in main thread (when user clicks on toolbar). Second image shows the same dialog but opened from a worker thread.


As you can see, the titlebar in the second image looks as the focus were lost.


Opening modal dialogbox in main thread:



opening the same modal dialogbox, but now in worker thread:



Do you see what I mean?


 

Technical Support Jun 22, 2008 - 1:32 PM

The CExtNcFrameImpl::NcFrameImpl_PreWindowProc() method receives a WM_ACTIVATEAPP message with a zero WPARAM value when the message box is displayed from other thread. That is why the main frame’s caption becomes inactive. You can send some WM_USER message from your second thread to the main frame window. This message will be received by the main frame window in its main UI thread and display a message box.

Andrej Kasa Jun 23, 2008 - 5:01 AM

I am not sure if I get what you mean. Do you mean that I should send for evey UI element I need to show from a worker thread a specific WM_USER message to the mainframe and then in the mainframe check for all WM_USER messages and based on them perform the actual GUI operation like displaying a MessageBox? Is that what you mean?


That can work for the MessageBox but it is problematic for a dialog progress bar (see the first screenshot) since I need to update the progress bar during my lenghty operation several times from the worker thread. That would be not that straightforward to implement by using WM_USER messages.


If I would check for WM_USER in the WindowProc I can not allow to block the entire app until my lenghty process ends - my app in such a case would freeze and not process any messages. It would look like this:


LRESULT CMainFrame::WindowProc(UINT message, WPARAM wParam, LPARAM lParam)

{

    if (message == WM_USER)

    {

  //MessageBox("wm_user");

     CWaitDlg dlg;

  dlg.Create(IDD_WAIT);

  dlg.ProgressBar->SetRange(0,15);

  MessageBox("wm_user");

 }

   return CExtNCW<CFrameWnd>::WindowProc(message, wParam, lParam);

}

Andrej Kasa Jun 23, 2008 - 5:01 AM

I am not sure if I get what you mean. Do you mean that I should send for evey UI element I need to show from a worker thread a specific WM_USER message to the mainframe and then in the mainframe check for all WM_USER messages and based on them perform the actual GUI operation like displaying a MessageBox? Is that what you mean?


That can work for the MessageBox but it is problematic for a dialog progress bar (see the first screenshot) since I need to update the progress bar during my lenghty operation several times from the worker thread. That would be not that straightforward to implement by using WM_USER messages.


If I would check for WM_USER in the WindowProc I can not allow to block the entire app until my lenghty process ends - my app in such a case would freeze and not process any messages. It would look like this:


LRESULT CMainFrame::WindowProc(UINT message, WPARAM wParam, LPARAM lParam)

{

    if (message == WM_USER)

   {

  //MessageBox("wm_user");

     CWaitDlg dlg;

  dlg.Create(IDD_WAIT);

  dlg.ProgressBar->SetRange(0,15);

  MessageBox("wm_user");

 }

   return CExtNCW<CFrameWnd>::WindowProc(message, wParam, lParam);

}

Andrej Kasa Jun 23, 2008 - 5:01 AM

I am not sure if I get what you mean. Do you mean that I should send for evey UI element I need to show from a worker thread a specific WM_USER message to the mainframe and then in the mainframe check for all WM_USER messages and based on them perform the actual GUI operation like displaying a MessageBox? Is that what you mean?


That can work for the MessageBox but it is problematic for a dialog progress bar (see the first screenshot) since I need to update the progress bar during my lenghty operation several times from the worker thread. That would be not that straightforward to implement by using WM_USER messages.


If I would check for WM_USER in the WindowProc I can not allow to block the entire app until my lenghty process ends - my app in such a case would freeze and not process any messages. It would look like this:


LRESULT CMainFrame::WindowProc(UINT message, WPARAM wParam, LPARAM lParam)

{

    if (message == WM_USER)

  {

  //MessageBox("wm_user");

     CWaitDlg dlg;

  dlg.Create(IDD_WAIT);

  dlg.ProgressBar->SetRange(0,15);

  MessageBox("wm_user");

 }

   return CExtNCW<CFrameWnd>::WindowProc(message, wParam, lParam);

}

Technical Support Jun 23, 2008 - 7:21 AM

What do you think about not using popup windows at all. Your WM_USER message handler can insert a new status bar pane, create and attach a slider to it.

Andrej Kasa Jun 23, 2008 - 5:01 AM

I am not sure if I get what you mean. Do you mean that I should send for evey UI element I need to show from a worker thread a specific WM_USER message to the mainframe and then in the mainframe check for all WM_USER messages and based on them perform the actual GUI operation like displaying a MessageBox? Is that what you mean?


That can work for the MessageBox but it is problematic for a dialog progress bar (see the first screenshot) since I need to update the progress bar during my lenghty operation several times from the worker thread. That would be not that straightforward to implement by using WM_USER messages.


If I would check for WM_USER in the WindowProc I can not allow to block the entire app until my lenghty process ends - my app in such a case would freeze and not process any messages. It would look like this:


LRESULT CMainFrame::WindowProc(UINT message, WPARAM wParam, LPARAM lParam)

{

    if (message == WM_USER)

 {

  //MessageBox("wm_user");

     CWaitDlg dlg;

  dlg.Create(IDD_WAIT);

  dlg.ProgressBar->SetRange(0,15);

  MessageBox("wm_user");

 }

   return CExtNCW<CFrameWnd>::WindowProc(message, wParam, lParam);

}

Andrej Kasa Jun 23, 2008 - 5:01 AM

I am not sure if I get what you mean. Do you mean that I should send for evey UI element I need to show from a worker thread a specific WM_USER message to the mainframe and then in the mainframe check for all WM_USER messages and based on them perform the actual GUI operation like displaying a MessageBox? Is that what you mean?


That can work for the MessageBox but it is problematic for a dialog progress bar (see the first screenshot) since I need to update the progress bar during my lenghty operation several times from the worker thread. That would be not that straightforward to implement by using WM_USER messages.


If I would check for WM_USER in the WindowProc I can not allow to block the entire app until my lenghty process ends - my app in such a case would freeze and not process any messages. It would look like this:


LRESULT CMainFrame::WindowProc(UINT message, WPARAM wParam, LPARAM lParam)

{

   if (message == WM_USER)

 {

  //MessageBox("wm_user");

     CWaitDlg dlg;

  dlg.Create(IDD_WAIT);

  dlg.ProgressBar->SetRange(0,15);

  MessageBox("wm_user");

 }

   return CExtNCW<CFrameWnd>::WindowProc(message, wParam, lParam);

}

Andrej Kasa Jun 23, 2008 - 5:01 AM

I am not sure if I get what you mean. Do you mean that I should send for evey UI element I need to show from a worker thread a specific WM_USER message to the mainframe and then in the mainframe check for all WM_USER messages and based on them perform the actual GUI operation like displaying a MessageBox? Is that what you mean?


That can work for the MessageBox but it is problematic for a dialog progress bar (see the first screenshot) since I need to update the progress bar during my lenghty operation several times from the worker thread. That would be not that straightforward to implement by using WM_USER messages.


If I would check for WM_USER in the WindowProc I can not allow to block the entire app until my lenghty process ends - my app in such a case would freeze and not process any messages. It would look like this:


LRESULT CMainFrame::WindowProc(UINT message, WPARAM wParam, LPARAM lParam)

{

  if (message == WM_USER)

 {

  //MessageBox("wm_user");

     CWaitDlg dlg;

  dlg.Create(IDD_WAIT);

  dlg.ProgressBar->SetRange(0,15);

  MessageBox("wm_user");

 }

   return CExtNCW<CFrameWnd>::WindowProc(message, wParam, lParam);

}

Andrej Kasa Jun 18, 2008 - 9:22 AM

I have found out the reason for the mentioned behaviour!


The point is that I am performing MessageBox calls and my other dialogs (as seen on screenshot) not from a primary thread but from a worker thread I create dynamically this way:


AfxBeginThread(MyWorkerThread, this, THREAD_PRIORITY_NORMAL, 0, 0, NULL);


Every time I open a dialog/MsgBox from within this thread the focus of Mainframe is lost.


Is there a chance to setup ProfUIS so that when dialogs are opened from not primary thread focus of the mainfraime will not get lost? I suppose there is such a way since as said at the begining, in version 2.82 the focus was never lost even when opening dialogs from a worker thread. Please advice me if I can overcome this somehow.

Technical Support Jun 19, 2008 - 6:00 AM

The MessageBox() and AfxMessageBox() display modal dialogs. If you are displaying any kind of modal dialog from any thread and the parent of this dialog is the main frame window, then it’s not possible to prevent the main frame window from losing its focus. Message boxes always assume interruption of current UI actions to let the use select Yes | No | OK | Cancel or even simply pressing OK after spending some time for reading an important text displayed in message box. So, message boxes are logically correct do focus gaining. It’s hardly possible to imaging message box without focus on its buttons. Of course you can use desktop window as parent window for your message boxes. But in this case main frame window will appear behind the message box if user will click somewhere on the main frame window after message box is displayed. But even if message box will have desktop as its parent window, the main frame window will lose focus when message box will appear. We think you need some other solution like dialog which looks like message box but created and displayed as non-modal window using the ShowWindow() API with SW_SHOWNOACTIVATE parameter or the SetWindowPos() API with SWP_SHOWWINDOW|SWP_NOACTIVATE parameter.

Andrej Kasa Jun 19, 2008 - 6:14 AM

But if you open the About box what is a regular modal dialog then caption of the mainframe will stay the same. As well, If I open a MessageBox the same way in version 2.82 then - as well - the caption of the mainframe does change even that MessageBox has the focus.


I probably did not make myself quite clear - I am OK with focus lost, my only concern is that I don’t want the mainframe caption changes the color as to case when a focus is lost.


Since in 2.82 it worked that way (meaning that mainframe caption did not change color on MessageBox), should I understand that it was a bug and it was fixed in 2.83? Or could you please specify the reason why the behaviour was changed in 2.83?


thanks.

Andrej Kasa Jun 19, 2008 - 6:23 AM

sorry for bug, here it is corrected:


But if you open the About box what is a regular modal dialog then caption of the mainframe will stay the same. As well, If I open a MessageBox the same way in version 2.82 then - as well - the caption of the mainframe does not change even that MessageBox has the focus.


 


I probably did not make myself quite clear - I am OK with focus lost, my only concern is that I don’t want the mainframe caption changes the color as to case when a focus is lost.


 


Since in 2.82 it worked that way (meaning that mainframe caption did not change color on MessageBox), should I understand that it was a bug and it was fixed in 2.83? Or could you please specify the reason why the behaviour was changed in 2.83?


thanks.

Andrej Kasa Jun 17, 2008 - 4:15 AM

I am using the freeware version since my app is not yet ready for sale and in the freeware version there is no PageContainer sample.


Can you please let me know if the mentioned behaviour is a bug and will be fixed in next release or do I have to modify my app somehow so that the problem will not occur? thanks.

Technical Support Jun 16, 2008 - 2:08 PM

We used PageContainer sample and v.2.83 for testing this issue. Please update MainFrm.h and MainFrm.cpp files in this sample application first:

PageContainer_UpdateForNcTest283.zip

This update makes the CDemoMiniFrameWnd class which implements a popup non-modal mini frame window with a custom drawn page container window based on the CExtNCW template. We tried to show/hide this mini frame window via menu command and we always saw active style of skinned captions both in the main frame window and floating mini frame window.

Andrej Kasa Jun 17, 2008 - 5:23 AM

I installed the 2.83 trial version to test this issue. I tried the installed version and as well the version with your modified mainframe class. However, in both cases (when turning the container window on and off) the mainframe window did not loose the focus at all.


Does it mean that the problem is in my app? Because when rebuilded the same code with 2.82 this issue never occurs. I suppose the problem will be somewhere in the relationship between the menu and the window. If I open About box wnd from the menu focus is not lost (as in the case of PageContainer). However, if I open a dialog box directly from code (which does not have the possibility to be started from menu) or a standard MessageBox is opened (with parent window being the mainframe) - then the focus is lost. Does this give you any clues as to where the problem may be?


e.g. the msgbox under which the focus is lost as well is called from within the app object this way:


m_pMainWnd->MessageBox(strText, "RFMeasure Receiver Problem [MSG21]", MB_OK|MB_ICONSTOP);


my mainframe is declared this way:


class CMainFrame : public CExtNCW < CFrameWnd >