win32 DialogBox app: how to make the dialog box hidden on startup? - winapi

I have a win32 app which uses DialogBox() to display its main window.
I now want to start this app up with the dialog box invisible, and later set it visible with
SetWindowPos(hDlg, HWND_TOPMOST, ...
Unfortunately
http://msdn.microsoft.com/en-us/library/ms645452(VS.85).aspx
The function displays the dialog box (regardless of whether the template specifies the WS_VISIBLE style)
... it seems that there's no way of doing this using DialogBox().
I could add a call to
SetWindowPos(hDlg, HWND_NOTOPMOST...
in my dialog procedure in the WM_INITDIALOG handler.
... but I'm concerned that under heavy system loading the dialog box will briefly appear then disappear, giving an ugly flicker effect.
Is there a way of creating my dialog box via DialogBox() without showing it?

ShowWindow(Hwnd, SW_HIDE);
i think it will work.
http://www.winprog.org/tutorial/modeless_dialogs.html

I had some success with this technique
void CMyDlg::OnWindowPosChanging(WINDOWPOS* lpWndPos)
{
// hide dialog
lpWndPos->flags &= ~SWP_SHOWWINDOW;
CDialog::OnWindowPosChanging(lpWndPos);
}
from here

Related

MFC: how to show a welcome dialog first?

When launch the program, I want to show a welcome dialog first before showing the main window. My current approach is like below.
BOOL CMyApp::InitInstance()
{
...
// The one and only window has been initialized, so show and update it
m_pMainWnd->ShowWindow(SW_HIDE);
//m_pMainWnd->UpdateWindow();
// call DragAcceptFiles only if there's a suffix
// In an SDI app, this should occur after ProcessShellCommand
CWelcomeDialog welcome_dialog;
welcome_dialog.DoModal();
m_pMainWnd->ShowWindow(SW_SHOW);
m_pMainWnd->UpdateWindow();
return TRUE;
}
Towards the end of InitInstance(), originally it uses (SW_SHOW). At first, I try commenting it out but it still shows. So I change to (SW_HIDE). It works but has unpleasant visual artifacts. Is there way to stop showing the main window as early as possible?
Another issue is that when I hide main window and show the dialog, the dialog is not in the center position of the main window.
In general, how to implement a welcome dialog and to show it well-centered before anything else?

How can a dialog become responsive while waiting for a call to DoModal() to return?

A button on a dialog causes a child dialog to be created, and displayed modally.
e.g:
void ParentDialog::OnButton()
{
ChildDialog dlg;
int ret = dlg.DoModal();
}
The parent dialog is initially unresponsive as expected. But, the child dialog also makes COM calls to a server module, which causes the server to make COM calls back to the parent dialog... to update displayed data, etc. In one case, this causes the parent dialog to suddenly become responsive again even though the child dialog is still on screen. Both dialogs can now be interacted with even though the parent dialog is still patiently waiting for OnButton()to return.
How can this happen? I'm trawling the code but is there anything specific I should be looking for?
The dialog has its own message pump/loop and inside the call it has a loop where it keeps receiving and dispatching window messages. This includes COM related messages worker windows receive and convert to COM callbacks you are seeing. Once the dialog is closed, respective windows are destroyed, the function exits from the loop and returns control to your code.
That is, without returning control to your code immediately, window message dispatching still keeps working as usually and UI is responsive.
MSDN:
... The function displays the dialog box, disables the owner window, and starts its own message loop to retrieve and dispatch messages for the dialog box.
When the dialog box procedure calls the EndDialog function, DialogBox destroys the dialog box, ends the message loop, enables the owner window (if previously enabled), and returns the nResult parameter specified by the dialog box procedure when it called EndDialog.
You can create a modeless dialog and use RunModalLoop to wait for the dialog to finish, somewhat similar to DoModal()
void CMyWnd::foo()
{
static BOOL isOpen = FALSE;
if (isOpen) return;//optional, prevents opening multiple dialogs
CDialog dlg;
dlg.Create(IDD_DIALOG1, this);
dlg.ShowWindow(SW_SHOW);
isOpen = TRUE;
int result = dlg.RunModalLoop(0);
dlg.DestroyWindow();
isOpen = 0;
TRACE("res:%d\n", result);
}
Problem: Note that in the above example you can close the program but the dialog will still be up. You have to force the dialog close, the above function doesn't deal with that.
Or you can create modeless dialog the usual way:
if (m_Dlg) return;
m_Dlg = new CDialog
m_Dlg.Create(IDD_DIALOG1, this);
m_Dlg.ShowWindow(SW_SHOW);
However in this example if user clicks OK/Cancel then you don't know about it, you have to override OnOK()/OnCancel then send message to parent Window/Dialog, process message, and then destroy the dialog manually.

How to show a dialog from another dialog?

I am newbie to MFC. I have a native C++ MFC app. I want to show a dialog from main dialog. In the main dialog I am having three button (Back, Next, Cancel) respectively.
On the Next button click event I am calling DoModal to show another dialog by hiding the main dialog as follows,
void CFirstPage::OnBnNextButton()
{
::ShowWindow(this->GetSafeHwnd(),SW_HIDE);
CSecondPage secondDlg;
secondDlg.DoModal();
}
void CSecondPage::OnBnBackBtnClicked()
{
::ShowWindow(this->GetSafeHwnd(),SW_HIDE);
CFirstPage FirstPage;
FirstPage.DoModal();
}
After executing this code snippet, the main dialog got hidden and even the application icon also disappears from the taskbar and again appears when the other dialog pops up.
(Basically I am having the same icon for both the dialogs, the icon should not get disappeared and appear again. It has to remain same without appearing and disappearing .)
How can show the icon in the taskbar without any flickering effect?
During traversing from back to next in middle I clicked cancel and the Cancel event is handled as follows,
void CFirstPage::OnCancel()
{
CDialog::EndDialog(TRUE);//For closing the dialog.
}
void CSecondPage::OnCancel()
{
CDialog::EndDialog(TRUE);//For closing the dialog.
}
Steps1:Click Next in the main dialog
Step2: Click Cancel in the second page
Now the application closes. But still instance is active in the "TaskManager". As per my understanding no instance should be alive once windows is closed ?
I suspect as the first dialog is only hidden not ended that instance is still existing in the TaskManager. Is this understanding correct?
How can I resolve this issue?
Can anyone kindly help me to resolve this issue.
As said by Iinspectable property sheets are best suited for your your problem statement.A very good example on how to use CPropertysheets can be found in codeproject
CProperty sheet example
Probably your main windows is still hidden after you end dialog with second page. Ending dialog of CSecondPage does not close application only closes active CSecondPage dialog.
Also OnCancel/OnOK does not need to be overriden if you just EndDialog with it. There is default behaviour implemented in OnCancel, which will close the dialog.
After secondPage.DoModal() show your main dialog again, or close it if that is the behaviour you want to achieve.
FirstPage isn't the original first dialog now, so you should store the first dialog object by yourself. You can do that like this:
void CFirstPage::OnBnNextButton()
{
::ShowWindow(this->GetSafeHwnd(),SW_HIDE);
CSecondPage secondDlg;
secondDlg.setFirstDialog(this); //customer function to store first dialig object
secondDlg.DoModal();
}
void CSecondPage::OnBnBackBtnClicked()
{
::ShowWindow(this->GetSafeHwnd(),SW_HIDE);
::ShowWindow(m_firstDialog->GetSafeHwnd(), SW_SHOW);
}

How to simulate modal dialog UI behaviour in a modeless dialog?

Is there an easy way to display a dialog modelessly while retaining the UI blocking a modal dialog provides?
I want to stop a user interacting with other dialogs/controls when the dialog is shown, but let the application carry on running. Is there a way to set a dialog as "exclusive focus" or something like that?
No, there is no easy way to do what you want.
If you really want to go the route you describe, I recommend first reading the whole 'modality' series on Raymond Chen's blog. First installment is on http://blogs.msdn.com/b/oldnewthing/archive/2005/02/18/376080.aspx .
However, this seems like an instance of the XY problem. What is it that you are trying to do? Get the main application to keep updating itself? If so, I think (with the information we are given) that calling AfxPumpMessage() will do what you want. Or do you want to continue processing data in the main application? Then you'll save yourself a world of hurt by using a worker thread.
Untested, but you can try do disable the owner window (the app. main window), create a modeless dialog, and then, when the dialog is closed, enable it again:
To disable the main window:
AfxGetMainWnd()->EnableWindow(FALSE);
To create the modal/non-blocking dialog:
dlg->Create(resId)
And to enable it again, on the OnClose event, or similar:
AfxGetMainWnd()->EnableWindow(TRUE);
There may be other details in a modal dialog that I'm not aware of. If you are willing to investigate, read the source code of MFC's CDialog::DoModal(). If I remember correctly, this MFC function simulates a modal-blocking dialog using the modeless Win32 API CreateDialog*() in order to implement global accelerators, hooks, messages and the like.
Here is possible answer to your question:
You could disable all the other controls in the application then re-enable them after the dialog has finished.
Use this callback
BOOL CALLBACK EnableDisableAllChildren ( HWND hwnd, LPARAM lp )
{
::EnableWindow ( hwnd, (BOOL)lp );
return TRUE;
}
With a Call to
EnumChildWindows ( HWNDToYourApp, EnableDisableAllChildren, true );
Do Modaless Dialog
EnumChildWindows ( HWNDToYourApp, EnableDisableAllChildren, false );
Something different to think about.

windows application showing behind the taskbar on vista

I have an MFC application. In my application if I run on Windows XP it's working fine. But if I run in Windows Vista the MFC dialog hides behind the taskbar.
bool bHide=true;
CRect rectWorkArea = CRect(0,0,0,0);
CRect rectTaskBar = CRect(0,0,0,0);
CWnd* pWnd = CWnd::FindWindow("Shell_TrayWnd", "");
pWnd->ShowWindow(SW_SHOW);
if( bHide )
{ // Code to Hide the System Task Bar
SystemParametersInfo(SPI_GETWORKAREA,0,(LPVOID)&rectWorkArea,0);
if( pWnd )
{
pWnd->GetWindowRect(rectTaskBar);
// rectWorkArea.bottom -= rectTaskBar.Height();
rectWorkArea.bottom += rectTaskBar.Height();//-----to hide taskbar
SystemParametersInfo(SPI_SETWORKAREA,0,(LPVOID)&rectWorkArea,0);
// pWnd->ShowWindow(SW_SHOW);
pWnd->ShowWindow(SW_HIDE); //--to hide taskbar
}
}
I used this code but it hides the taskbar. But I want to show the application above the task bar.
You don't own the taskbar, so you are not supposed to hide it. You have the option to auto-minimize it by the way. You have another option of using secondary monitor without taskbar there.
On the primary monitor your app is given work area, you are being able to locate (judging from the code snippet provided above). It is the best to position your window within this area without interfering with the taskbar, whether it is above or beyond.
If you still feel like making it more like a competition "who is on top" with the task bar, you might want to take a look at SetWindowPos API and window Z-Order.
finally i found the solution , what we want to do is we should add the below code in our oninitdialog,
SetWindowPos(&this->wndTopMost,0,0,0,0,SWP_NOMOVE|SWP_NOSIZE);
the above line is enough to show the mfc dialog on above the taskbar . but sometimes the focus of the dialog get changed looks hanged(no response in dialog) the application.if it occurs put the below code.
SetWindowPos(&this->wndBottom,0,0,0,0,SWP_NOMOVE|SWP_NOSIZE);

Resources