How to know when Dialog is open
-
I would like call a function as soon as a dialog is open and visible, but i cannot find a way of telling when this is so. The dialog is a simple CDialog and is run by using DoModal. I have tried OnInitDialog amongst a number of other overrides but they all seem to be called just before the dialog is displayed. Any help would be greatly appreciated. Thanks
At the end of
OnInitDialog()
, post a message to the dialog, such asWM_APP
. The handler can then do whatever work you want.--Mike-- Visual C++ MVP :cool: LINKS~! Ericahist | PimpFish | CP SearchBar v3.0 | C++ Forum FAQ
-
I would like call a function as soon as a dialog is open and visible, but i cannot find a way of telling when this is so. The dialog is a simple CDialog and is run by using DoModal. I have tried OnInitDialog amongst a number of other overrides but they all seem to be called just before the dialog is displayed. Any help would be greatly appreciated. Thanks
-
At the end of
OnInitDialog()
, post a message to the dialog, such asWM_APP
. The handler can then do whatever work you want.--Mike-- Visual C++ MVP :cool: LINKS~! Ericahist | PimpFish | CP SearchBar v3.0 | C++ Forum FAQ
How do you advise doing this, because when i use postmessage with a WM_COMMAND message, the dialog isn't displayed until the handling function has ended? -- modified at 17:28 Thursday 8th June, 2006
-
I haven't overridden anything, that's the problem, i don't know what to override that would work the way i want it to? Any suggestions? Thanks -- modified at 17:28 Thursday 8th June, 2006
-
I haven't overridden anything, that's the problem, i don't know what to override that would work the way i want it to? Any suggestions? Thanks -- modified at 17:28 Thursday 8th June, 2006
-
How do you advise doing this, because when i use postmessage with a WM_COMMAND message, the dialog isn't displayed until the handling function has ended? -- modified at 17:28 Thursday 8th June, 2006
WM_COMMAND messages are specific to dialog controls and similar. As Michael said you should use WM_APP. In code it would look something like this the following: for the dialog header file, define a message ID...
#define UWM_DOMYFIRSTHING (WM_APP + 1)
and add a message handler as a member function...
LRESULT OnDoMyFirstThing( WPARAM wParam, LPARAM lParam );
in the implementation file add your message to the message map...
BEGIN_MESSAGE_MAP(CMyDialogClass, CDialog) //{{AFX_MSG_MAP(CMyDialogClass) ON_WM_SYSCOMMAND() ON_WM_PAINT() ON_WM_QUERYDRAGICON() ON_WM_CLOSE() //}}AFX_MSG_MAP ON_MESSAGE( UWM_DOMYFIRSTTHING, OnDoMyFirstThing ) // This line is added manually END_MESSAGE_MAP()
and add your message handler implementation...
LRESULT CMyDialogClass::OnDoMyFirstThing( WPARAM wParam, LPARAM lParam ) { // Do whatever you need to do, the dialog is now visible }
Don't forget to post the message from the bottom of OnInitDialog()...
PostMessage( UWM_DOMYFIRSTTHING );
It's important that you use PostMessage instead of SendMessage, otherwise the message handler will be called before OnInitDialog() returns and the dialog won't be visible yet. Hope this helps -- Roger
_It's supposed to be hard, otherwise anybody could do it!
Regarding CodeProject: "resistance is pointless; you will be assimilated"_ -- modified at 19:04 Thursday 8th June, 2006: added <code> tags
-
I would like call a function as soon as a dialog is open and visible, but i cannot find a way of telling when this is so. The dialog is a simple CDialog and is run by using DoModal. I have tried OnInitDialog amongst a number of other overrides but they all seem to be called just before the dialog is displayed. Any help would be greatly appreciated. Thanks
sschilachi wrote:
I would like call a function as soon as a dialog is open and visible, but i cannot find a way of telling when this is so.
iS WM_SHOWWINDOW or WM_SIZE message of any help
"Opinions are neither right nor wrong. I cannot change your opinion. I can, however, change what influences your opinion." - David Crow
cheers, Alok Gupta VC Forum Q&A :- I/ IV Support CRY- Child Relief and You
-
WM_COMMAND messages are specific to dialog controls and similar. As Michael said you should use WM_APP. In code it would look something like this the following: for the dialog header file, define a message ID...
#define UWM_DOMYFIRSTHING (WM_APP + 1)
and add a message handler as a member function...
LRESULT OnDoMyFirstThing( WPARAM wParam, LPARAM lParam );
in the implementation file add your message to the message map...
BEGIN_MESSAGE_MAP(CMyDialogClass, CDialog) //{{AFX_MSG_MAP(CMyDialogClass) ON_WM_SYSCOMMAND() ON_WM_PAINT() ON_WM_QUERYDRAGICON() ON_WM_CLOSE() //}}AFX_MSG_MAP ON_MESSAGE( UWM_DOMYFIRSTTHING, OnDoMyFirstThing ) // This line is added manually END_MESSAGE_MAP()
and add your message handler implementation...
LRESULT CMyDialogClass::OnDoMyFirstThing( WPARAM wParam, LPARAM lParam ) { // Do whatever you need to do, the dialog is now visible }
Don't forget to post the message from the bottom of OnInitDialog()...
PostMessage( UWM_DOMYFIRSTTHING );
It's important that you use PostMessage instead of SendMessage, otherwise the message handler will be called before OnInitDialog() returns and the dialog won't be visible yet. Hope this helps -- Roger
_It's supposed to be hard, otherwise anybody could do it!
Regarding CodeProject: "resistance is pointless; you will be assimilated"_ -- modified at 19:04 Thursday 8th June, 2006: added <code> tags
I have done everything you have said above, and it still calls the message handler before OnInitDialog() returns, so the dialog is not visible. Have you tried this yourself to see if it works, am i making a silly mistake somewhere? This is my code:
#define UWM_DELETEFILE (WM_APP + 1) LRESULT OnDeleteFile(WPARAM wParam, LPARAM lParam); BEGIN_MESSAGE_MAP(CStatusDlg, CDialog) ON_MESSAGE(UWM_DELETEFILE, OnDeleteFile) END_MESSAGE_MAP() BOOL CStatusDlg::OnInitDialog() { CDialog::OnInitDialog(); PostMessage(UWM_DELETEFILE ); return TRUE; } LRESULT CStatusDlg::OnDeleteFile(WPARAM wParam, LPARAM lParam) { //dialog should be visible but isn't }
-
I have done everything you have said above, and it still calls the message handler before OnInitDialog() returns, so the dialog is not visible. Have you tried this yourself to see if it works, am i making a silly mistake somewhere? This is my code:
#define UWM_DELETEFILE (WM_APP + 1) LRESULT OnDeleteFile(WPARAM wParam, LPARAM lParam); BEGIN_MESSAGE_MAP(CStatusDlg, CDialog) ON_MESSAGE(UWM_DELETEFILE, OnDeleteFile) END_MESSAGE_MAP() BOOL CStatusDlg::OnInitDialog() { CDialog::OnInitDialog(); PostMessage(UWM_DELETEFILE ); return TRUE; } LRESULT CStatusDlg::OnDeleteFile(WPARAM wParam, LPARAM lParam) { //dialog should be visible but isn't }
What both I and Michael Dunn suggested is a common technique used when something has to be done when all dialog controls has been created and initialized. I thought this was your problem since it's quite common. The last message handled when a dialog is created is usually WM_PAINT. Both WM_SIZE and WM_SHOWWINDOW are sent prior to WM_PAINT. If it's imperative that your dialog is visible to the user there is no message handler you can override. You have to write code inside the message handler for WM_PAINT, OnPaint(). Like this:
void CShowDlg::OnPaint() { static BOOL bShown = FALSE; if (IsIconic()) { CPaintDC dc(this); // device context for painting SendMessage(WM_ICONERASEBKGND, (WPARAM) dc.GetSafeHdc(), 0); // Center icon in client rectangle int cxIcon = GetSystemMetrics(SM_CXICON); int cyIcon = GetSystemMetrics(SM_CYICON); CRect rect; GetClientRect(&rect); int x = (rect.Width() - cxIcon + 1) / 2; int y = (rect.Height() - cyIcon + 1) / 2; // Draw the icon dc.DrawIcon(x, y, m_hIcon); } else { CDialog::OnPaint(); } if( !bShown ) { // Write code here or post your message bShown = TRUE; } }
Sorry that I misunderstood your needs. :-> I just haven't encountered a initialization situation yet that actually requires the dialog to be visible and I can't figure out why this would be necessary. It's not necessarily wrong, I'm just curious. -- Roger
_It's supposed to be hard, otherwise anybody could do it!
Regarding CodeProject: "resistance is pointless; you will be assimilated"_
-
What both I and Michael Dunn suggested is a common technique used when something has to be done when all dialog controls has been created and initialized. I thought this was your problem since it's quite common. The last message handled when a dialog is created is usually WM_PAINT. Both WM_SIZE and WM_SHOWWINDOW are sent prior to WM_PAINT. If it's imperative that your dialog is visible to the user there is no message handler you can override. You have to write code inside the message handler for WM_PAINT, OnPaint(). Like this:
void CShowDlg::OnPaint() { static BOOL bShown = FALSE; if (IsIconic()) { CPaintDC dc(this); // device context for painting SendMessage(WM_ICONERASEBKGND, (WPARAM) dc.GetSafeHdc(), 0); // Center icon in client rectangle int cxIcon = GetSystemMetrics(SM_CXICON); int cyIcon = GetSystemMetrics(SM_CYICON); CRect rect; GetClientRect(&rect); int x = (rect.Width() - cxIcon + 1) / 2; int y = (rect.Height() - cyIcon + 1) / 2; // Draw the icon dc.DrawIcon(x, y, m_hIcon); } else { CDialog::OnPaint(); } if( !bShown ) { // Write code here or post your message bShown = TRUE; } }
Sorry that I misunderstood your needs. :-> I just haven't encountered a initialization situation yet that actually requires the dialog to be visible and I can't figure out why this would be necessary. It's not necessarily wrong, I'm just curious. -- Roger
_It's supposed to be hard, otherwise anybody could do it!
Regarding CodeProject: "resistance is pointless; you will be assimilated"_
Hello, that's still not quite what i want, maybe i'm going about it all wrong. The dialog box has a text box inside, and i would like this to display text strings about the status of the program to the user. The whole process needs to be launched by pressing a button, which launches the form, and only then once the form and controls are visible can the program's main function begin as otherwise any realtime messages to the controls won't be visible. I know i could probably do this more efficiently using another thread but i thought it would be much more complex and error prone. Is there a better way of doing this? Thanks a lot for all your help btw.