CMainDialog::DoSomething()
{
CMyDialog1 dlg1;
dlg1.DoModal();
CMyDialog2 dlg2;
dlg2.DoModal();
}
The problem is that after dlg1 returns, the parent dialog briefly shows up before dlg2 is displayed causing a flicker. This is undesirable, how can I get rid of this? I used SetRedraw(FALSE) in the above function but that didn't help.
In your resource editor, go to properties for CMyDialog1 and make dlg1 initially invisible.
When you are ready to show dlg1, use dlg1.ShowWindow(SW_SHOW).
Related
Fig1:
Fig2:
As in Fig1, after I clicked radio button, the radio button seems not get correctly painted, seems 50% transparent.
As in Fig2, after I move my mouse to hover the radio button again, it got correctly painted.
I have no idea about what is going on behind.
What are the possible reasons?
By the way, after I pressed a shortcut key PrtSc to get a screenshot(a freeware: Greeshot), this problem disappeared.
One hint I just found is: the dialog holding the radios were in modeless mode. The problem disappeared after I showed it as a modal dialog.
Actually, to achieve below goals, I am implementing the message pump for this dialog. Perhaps I am doing something wrong in the message pump logic. Continue to check the pump.
My Goal: user can interact with other windows while showing this dialog, one exception is: user should not be able to interact with the parent dialog of this dialog in question, so that database transaction may be issued prematurally.
I used to have a similar problem within wxWidgets. Turns out it's a long lasting bug that really never had been fixed. I now use a workaround with a simple wrapper function that 'enables' the element (places focus on it) and then 'unfocuses' it. Not sure in your current setup.
As a result, it seems I did something wrong in the message pump for the dialog in question.
I am implementing the message pump for this dialog.
To avoid user interact with the parent dialog of the dialog in question, I was ignoring message for the parent dialog and to children of parent dialog.
After I changed the above logic to below, the problem got solved.
EnableWindow(hParent, FALSE);
EnableWindow(hParent, TRUE);
So, I think I was doing something wrong in ignoring message, not sure exactly where.
Generally I have some button that opens child window and the second press on this button should close it. I use a touch screen.
The problem is when I try to press the button for closing the child window, it is not pressed the first time, so I need another click.
In order to fix this I am trying to return the focus to the parent window after the child window is opened.
I register the OnShowWindow message and call SetFocus on the parent window:
void CFlashGuidanceSteps::OnShowWindow(BOOL bShow, UINT nStatus)
{
CDialog::OnShowWindow(bShow, nStatus);
GetParent()->SetFocus();
}
While the function is called (I can see it in debugger), the focus is not returned to the parent window.
However, it works with the OnSetFocus event:
void CFlashGuidanceSteps::OnSetFocus(CWnd* pOldWnd)
{
CDialog::OnSetFocus(pOldWnd);
GetParent()->SetFocus();
}
Why is the focus is not retained with the OnShowWindow event?
The explanation
The usual rule in MFC is that OnXxx functions are called in response to similarly named window messages, e.g. WM_Xxx. So OnShowWindow would be called in response to WM_SHOWWINDOW.
And according to the documentation, WM_SHOWWINDOW is
Sent to a window when the window is about to be hidden or shown.
That means it is sent before the window is actually shown. So when you set the focus to the parent window inside of the OnShowWindow function, nothing actually happens because the parent window already has the focus. Then, after OnShowWindow finishes running, the child window is displayed and demands the focus. It is as if you never made any attempt to change the focus.
By contrast, OnSetFocus, which corresponds to WM_SETFOCUS, is not called until after the window has gained the focus. So when you reassign the focus here, it works because the child window doesn't steal the focus back.
The better idea
That explains the behavior you are seeing, and as you know, things work fine when you adjust the focus in OnSetFocus. But this really isn't the best way of solving the problem.
Manually changing the focus when a window gets and/or loses the focus is approaching the problem the wrong way around, and generally error-prone. You'll get all kinds of focus-related bugs that are difficult to debug. You are better off looking for ways to prevent the focus from changing when you don't want it to.
It sounds to me like you want to prevent the child window from getting the focus when it is created. And there is a way to do precisely that.
When you display the child window, presumably by calling the ShowWindow function or its moral equivalent in MFC, you should pass the SW_SHOWNA flag. That causes the window to be shown without activating it (i.e., granting it the focus).
I have a CFormView SDI which calls and opens up a CDialog.
In the CDialog I have a button which has a bitmap displayed.
All works well, until I close the CDialog.
When I open up the same CDialog (using create function), the button appears, and the button's functionality is there, however the bitmap disappears.
Can someone please tell me why the bitmap on the button disappears on subsequent calls to CDialog?
Thank you in advance.
Here is the code:
In the CFormView I have a button that creates the CDialog:
void CTest4View::OnButton1()
{
m_dialog_calculator.Create(IDD_DIALOG1, GetDesktopWindow());
m_dialog_calculator.ShowWindow(SW_SHOW);
}
In the CDialog I have the bitmap put on the button in the InitDialog:
BOOL CCalculator::OnInitDialog()
{
CDialog::OnInitDialog();
if(!bitmapNew.LoadBitmap(IDB_BITMAP_NEW)){
MessageBox("problem in loadbitmap");
}
if(!m_button.SetBitmap(bitmapNew)){
MessageBox("problem in SetBitmap");
}
bitmapOpen.LoadBitmap(IDB_BITMAP_OPEN);
m_buttonOpen.SetBitmap(bitmapOpen);
//==========================
return TRUE; // return TRUE unless you set the focus to a control
// EXCEPTION: OCX Property Pages should return FALSE
}
Upon further investigation, the problem seems to be in: m_button.SetBitmap(bitmapNew) since this returns FALSE. Can someone please help me?
Quick fix:
void CTest4View::OnButton1()
{
// only create the dialog once
if (m_dialog_calculator.m_hWnd==NULL)
m_dialog_calculator.Create(IDD_DIALOG1, GetDesktopWindow());
m_dialog_calculator.ShowWindow(SW_SHOW);
}
Additional information 1:
The information that OP provided in his question/code is quite little, so I actually have to recreate a similar test project to guess what is wrong with the missing bitmap. What I found is that the CDialog and CBitmap is being created multiple times when the button is pressed, this causes subsequent creation api call to fail, other than the first creation call. The result is some unexpected behavior as you can see now.
The program is supposed to generate some assertion errors when run in debug mode due to the creation failure but I guess the OP compiled it in release mode so all warnings are being suppressed.
The problem occurred because the calculator dialog is created as a modeless dialog as compared to a normal DoModal way of activation. The usual way of doing such modeless dialog is to create the dialog only once, by monitoring the m_hWnd member variable. When the user want the dialog to be dismissed, it is simply being hidden instead of being destroyed. This will avoid all the multiple creation problems altogether.
I guess presently, the calculator dialog is assumed to be closed and destroy by clicking the "X" button on the top right of dialog, well, actually it is only hidden but not actually being destroyed by the default handling of CDialog. The correct way to dismiss the modeless calculator dialog is thus to overide the OnClose event to hide it using ShowWindow(SW_HIDE). To activate it again, use ShowWindow(SW_SHOWNORMAL).
I need to create dialog and button.When I click on button with arrow dialog hide, it should looks like dialog moves to top and in ahother case shows for user.
ShowWindow(SW_HIDE). I know about it. I guess to get CRect from window, change it and after that set it to ScreeToClient().
Probably somebody knows some examples with it or another ways?
thanks
To hide or show a window, you use ShowWindow() as you indicated. No rectangle needed.
Otherwise, please re-explain your question, I can't make head or tails of it.
Normally, if you need to show a dialog that contains settings (similar to the Visual Studio "Options" dialog) then what you would typically do is this:
List item.
Create a CDialog-derived class.
Create an instance of that class.
call DoModal on that object. This shows the dialog.
Do nothing else. Once DoModal returns the dialog has been closed.
I have a dialog (CDialog derived class) that can be used in two different ways (edition mode and programming mode).
When the dialog is open to be used in programming mode it is a modeless dialog that it is used for modifying the main view (kind of a toolbar). When it is open in edition mode the user can change the configuration of the dialog itself and in this case it is a modal dialog.
Right now they are two different dialogs with few differences and I would like to have just want dialog and let the user change between programming mode and edition mode just by pressing a button in the dialog.
So I need to convert the modeless dialog in a modal dialog and vice versa at runtime. Is there a way to achive that?
Thanks.
As maybe someone could be interested in doing something similar in the future, this is the way I eventually did it:
I use this two functions of main frame: CMainFrame::BeginModalState() and CMainFrame::EndModalState().
The problem with these functions is the same that with disabling the parent window. The window you want to make modal also gets disabled. But the solution is easy, just re-enable the window after calling BeginModalState.
void CMyDialog::MakeModal()
{
//disable all main window descendants
AfxGetMainWnd()->BeginModalState();
//re-enable this window
EnableWindow(TRUE);
}
void CMyDialog::MakeModeless()
{
//enable all main window descendants
AfxGetMainWnd()->EndModalState();
}
Thanks for your help.
That can't be done easily without closing and reopening the dialog. Then you can call ShowWindow or DoModal as appropriate.
That is not correct. This can be done, if you look at MFC's source you will realize that it's modal dialogs are not technically even modal. You will have to do a lot of mucking about to make this work properly, but basically you just have to disable the parent of the 'modal' window, and re-enable it when the 'modal' window closes.
I have done this personally so this may work for you, though I am not exactly sure what you are trying to do.