Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations strongm on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Multiple Dialogs Problem

Status
Not open for further replies.

redoctober

Programmer
Oct 25, 2000
37
CA
Hi guys,
i have a SDI project and at when i click a menu item i want 2 dialogs to appear. Everythings works fine except 1 little detail. If i create my dialogs

m_Dlg->Create(IDD_DIALOG1); (1)
m_DlgT->Create(IDD_DIALOG2); (2)

and then make then visible

m_Dlg->ShowWindow(SW_SHOW);
m_DlgT->ShowWindow(SW_SHOW);

i can't bring dialog (1) on top of dialog (2) not when i click on it not if i manualy set focus on it. Btw, on the task bar i can see only 1 tab for the dialogs and task manager shows only that they both run in the same process. If i change the order of creation of the dialogs then i can't bring dialog (2) to the top. Is there a way to get around this problem?
thanks a lot in advance.
 
To do it, You must derive Your own class from CDialog and change the Function
DoModal().
Original Function:
int CDialog::DoModal()
{
...
// disable parent (before creating dialog)
HWND hWndParent = PreModal();
AfxUnhookWindowCreate();
CWnd* pParentWnd = CWnd::FromHandle(hWndParent);
BOOL bEnableParent = FALSE;
if (hWndParent != NULL && ::IsWindowEnabled(hWndParent))
{
::EnableWindow(hWndParent, FALSE);
bEnableParent = TRUE;
}
...
}

This disables Main Window and all it's children. Override it for example so:
int CMyDialog::DoModal()
{
...
...
//not disable parent (before creating dialog)
HWND hWndParent = PreModal();
AfxUnhookWindowCreate();
CWnd* pParentWnd = CWnd::FromHandle(hWndParent);
BOOL bEnableParent = FALSE;
/* if (hWndParent != NULL && ::IsWindowEnabled(hWndParent))
{
::EnableWindow(hWndParent, FALSE);
bEnableParent = TRUE;
}
*/
...
}

this makes main Window and some it's children enabled
and You can use m_DlgT->DoModal() and all Dialog Functions. Or You can enable on this place Dialogs of interest (only m_Dlg).
 
Thank you very much for your reply, tchouch.
But i think i didn't make it clear in my question that i have a main window and i want 2 modeless dialogs to be running at the same time. The way i did it allows me to bring main window on top of the dialogs (since they are modeless) but the problem is that i can't switch between dialogs. I mean i can swith between them and enter values in editboxes, toggle checkboxes and so on in both of them. What i can't do is to bring dialog which was created first on top of the dialog which was created last.
What you suggested leaves parent window enabled but i that's not the problem that i'm having.
But thanks a lot for the reply. Do you have any other ideas?
I apreciate any help.
 
Don't use the DoModal function to create & display the window. Use a modeless approach instead.
Eg. if you dialog classes are CMyDlg1 & CMyDlg2, then do

CMyDlg1 dlg1;
CMyDlg2 dlg2;

dlg1.Create(IDD_DIALOG1);
dlg1.ShowWindow(SW_SHOWNORMAL);

dlg2.Create(IDD_DIALOG2);
dlg2.ShowWindow(SW_SHOWNORMAL);

Does that help?
- Karthika
 
Actually, that's exactly what i'm doing right now. I create them as modeless. The problem is what i described above.
But thanks anyway.
 
The difference between modal and modeless dialog boxes is, that a modal dialog disables the main window (and all it's children), and modeless not. The code above allows You to start how much dialogs, as You needs. If You wish to see, how it works, download Programm PCHacker.exe from:

extract it and start.
After You starts this Program:
1.Select Menu Info About ->Resources and select a File with Dialog Resources (for example, User32.dll from Winnt/System32 on Windows NT).
2. In dialog appeared select with mouse double-click one of Resources of Typ 5 (Dialog box).
3. Press Button "Show" in dialog appeared - You will see two dialogs, and You can access these dialogs and the main window too. It is not that what You wish?
 
Hello tchouch,
I tried Pchacker... This is indeed very close to what i would like to do, but in Pchacker i can set focus to the main window but i can't bring it on top of the dialog boxes. I'm sure that's meant to be this way in the program, but i want to have 3 "independent" windows (well, 1 window and 2 dialogs to be exact). I want to be able to juggle them as i see fit. But one thing that intrested me in that program is that they made 2 dialogs to be independent of each other, if just could learn how to do that i think i'd be able to figure out how to deal with my problem.
By the way i tried the way you sugested in the beginning and i ran into several dificulties. First of all if i transfer the code from original CDialog::DoModal()to CMyDialog::DoModal() some of the functions such as AfxUnhookWindowCreate();
AfxHookWindowCreate();
DELETE_EXCEPTION(e);
cannot be found. Plus if i comment them out and run the program, 1st dialog appears and then program waits for me to close it (modal dialog creation) to continue execution.
So this is not exactly the way i need it to work.
Nevertheless, thanks a lot for the suggestion.


 
I understand what you mean now. Write a handler for the "focus out" message for each dialog box & place the code for hiding the dialog box there. This way, when you click the main window, it will be unobscured.

Does this work?
- Karthika
 
I don't now, which header You needs for that code, but if You use all these headers, it will works (some from there are in stdafx.h):

#include <afxwin.h> // MFC core and standard components
#include <afxext.h> // MFC extensions
#include <afxole.h> // MFC OLE classes
#include <afxodlgs.h> // MFC OLE dialog classes
#include <afxcmn.h>
#include <afxrich.h>
#include <afxpriv.h>
#include <afxtempl.h>
#include <afxdisp.h> // MFC OLE automation classes
#include <winuser.h>

To bring main window to top, replace in DoModal()
HWND hWndParent = PreModal();
with
HWND hWndParent = ::GetDesktopWindow();
PreModal() returns handle of top-level window, from such You starts the dialog. Replacing it with Desktop window makes dialog to &quot;Top-level window&quot;.
 
I think i found a way to do it. I used threads to launch each dialog as a separate &quot;process&quot;. Took me a while because of tricks in sharing objects between the threads.
I ried few different ways, but every time i would call UpdateData() of the dialog program would crash or wouldn't update the the dialog controls.
Finaly what seems to be working is this:

in
MyDoc.h

public:
CMyThread* th;
CMyDialog* dl;
HWND d_hWnd;

in
MyThread.cpp
//Creates dialog window in a thread and returns safe handle
HWND CThr1::CreatDlg()
{
CMyDialog* dl = new CDialog();
dl->Create(IDD_DIALOG1, AfxGetApp()->m_pMainWnd);
return dl->GetSafeHwnd();
}

in
MyDoc.cpp
//creating thread calling the function which creates dialog
//then cast it to CMyDialog type
CMyDoc::CMyDoc()
{
th = new CThread();
th->m_bAutoDelete = FALSE;
th->CreateThread();
d_hWnd = th->CreatDlg();
dl = (CDialog*)CWnd::FromHandle(d_hWnd);
dl->ShowWindow(SW_SHOW);
}

I haven't had a chance to test it fully but at least UpdateData() is working now and i can use my dialogs exactly the same way as if i created them without threads.
Thanks for all your help guys, i've learnd couple of new things from you.
Cheers,
Zheka.
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top