I am trying to find the handle to a dialog as soon as it opens.
Now as soon as dialog is opened I try to call FindWindowEx for that dialog in a separate thread but it returns NULL.
I then put some sleep before calling FindWindowEx. It works some time after putting sleep.
It looks like FindWindowEx is getting called before even dialog is created and sleep is helping to create the dialog and hence some times it work.
Now I have put some random value in sleep. And it doesnot look a good approach since it can fail anytime.
Is there any full proof approach so that I may get handle every time via FindWindowEx without making thread to sleep.
If the dialog you are looking for is your dialog -- that is, you control the code -- then you can send a message from your dialog to your watching app that says, "Oh, hi there!"
If the dialog is not yours, and you don't want to spin, you can create a Windows hook on the WM_CREATE message.
A very straightforward solution would be to call FindWindowEx repeatedly in a loop.
HWND h = NULL;
while (1) {
h = FindWindowEx(...);
if (h) {
break;
}
Sleep(100);
}
That's not bullet-proof - it's an infinite loop if the dialog nevers opens, or is closed too quickly (although that's unlikely). To catch both cases, let the main thread (which creates and runs the dialog) maintain a simple bool property that the worker thread queries to find out whether there's still a dialog around.
Related
I originally had an ActiveX control that registered a Windows timer (with SetTimer()) that fires every few seconds. That worked fine so far. Now in order to implement a full screen mode, I added a child window to my control that is supposed to show the content while the control itself manages all the ActiveX stuff.
The problem that I have with this approach is that my WM_TIMER suddenly stops firing at some time. I have traced it back to UIDeactivate() being called on my control but I don't know why this method is called (I believe it has something to do with losing focus) when it wasn't called before.
I would also like to know why my WM_TIMER events suddenly stop while everything else still seems to work fine. And what could it have to do with showing the content in a child window instead of on the ActiveX control itself?
Timers stops for a reason. Which might be:
You do stop timer by KillTimer call
Your window is re-created and timer is not re-enabled
Your control is windowless and you actually don't have a HWND handle
There is a collision in timer identifiers, there is something else (e.g. internal subclassed window) out there to use the same identifier, it sets, kill the timer and you no longer see WM_TIMER messages you enabled earlier
The window thread is busy (frozen) with some activity which does not include message dispatching, so timer itself exists, is healthy and alive, just no messages sent
The things to do - without yet additional information on the issue on hands:
Check threads of your window, and your Set/KillTimer calls to make sure they all make sense together
Use Spy++ tool to check messages posted for your window and/or in the thread of the interest, to find out if you really have WM_TIMERs missing, or they just don't reach your code; also you might see other interesting messages around
Here's an excerpt from ATL implementation of CComControlBase (I would guess that your control inherits from that). Check the part marked with <<<<<<<<<<<:
inline HRESULT CComControlBase::IOleInPlaceObject_InPlaceDeactivate(void)
{
if (!m_bInPlaceActive)
return S_OK;
if(m_bUIActive) {
CComPtr<IOleInPlaceObject> pIPO;
ControlQueryInterface(__uuidof(IOleInPlaceObject), (void**)&pIPO);
ATLENSURE(pIPO != NULL);
pIPO->UIDeactivate();
}
m_bInPlaceActive = FALSE;
// if we have a window, tell it to go away.
//
if (m_hWndCD)
{
ATLTRACE(atlTraceControls,2,_T("Destroying Window\n"));
if (::IsWindow(m_hWndCD))
DestroyWindow(m_hWndCD); <<<<<<<<<<<<<<<<<<<<<<<<<<<
m_hWndCD = NULL;
}
if (m_spInPlaceSite)
m_spInPlaceSite->OnInPlaceDeactivate();
return S_OK;
}
On deactivation, the control window gets destroyed. Therefore it can't process WM_TIMER anymore.
Good day!
I have an MFC dialog with progress.
Dialog automatically closes after reaching 100% using PostMessageW(WM_CLOSE).
The problem is, when, during progress, I'm moving dialog over the screen, dialog is not closing and WM_CLOSE message is ignored. Any suggestions? Thanks.
For a modal dialog you shouldn't really need to use a WM_CLOSE message.
Normally you'd use the OK or Cancel button events to close it, call the EndDialog method from functional code or just return when your processing is complete (assuming that its the process run as soon as the dialog is initialised). You can set your return value at the same time e.g. EndDialog(2);.
Either way the dialog will close once th current message handler returns, so there could well be a delay, in closure but it shouldn't be much.
Is the activity behind progress bar done in a separate thread? It look like to be the case otherwise when you drag the dialog the progress bar would have froze until you release the dialog than it would have resumed. This means you might have to look into inter thread communication, how the message is being posted to the dialog HWND.
It might have to do with the dialog being in freeze (no activity) state while you are dragging it which seems to be normal windows behavior. If that is the case you could use signals/CEvent to tell the dialog to close down.
It might be a simple question, but I don't know where to start the search for the answer. How do I create two individual windows interface in one application using native winapi? Do I put two CreateWindow() functions using same HINSTANCE? What if I want a login screen windows and the content page such that login screen comes first, and after I press the button, the login screen is destroyed, and the content page appears. How do I do such trick?
I was thinking of using DestroyWindow and then CreateWindow inside the button click message. However, this would mean the main while loop (for translate/dispatch msg) in WinMain will exit its loop and cause the whole program to exit. Another way is to pre-create it in WinMain, but how would I notify the WinMain if the button was clicked and enter the second loop instead of exiting the program?
You're over-thinking it. To create two windows, call CreateWindow twice. It's just that simple.
Calling DestroyWindow does not cause your program to exit its message pump. Calling PostQuitMessage is what does that. So don't do that.
When the button is clicked, destroy the one window and create the other. There are no tricks. The message pump delivers messages to all windows (unless you're doing it wrong by explicitly requesting messages for one window, but you shouldn't do that).
I need to open a dialog box instantiated from the same class twice. When I try this
CdelmeDlg dlg;
dlg.DoModal();
dlg.DoModal();
The second call opens the dialog only for a split second, then it is closed. My bet was there is a leftover message in the message queue, so I added this in between the calls
MSG msgCur;
while (::PeekMessage(&msgCur, NULL, NULL, NULL, PM_REMOVE))
;
This solves the problem, but it feels like a wrong kind of thing to do. Is there a way to process the leftover message properly?
Don't call EndDialog( IDOK );
To handle the ok or cancel buttons being pressed just inherit OnOk or OnCancel ... Otherwise EndDialog is going to be called twice and you'll get the problem you are getting!
I actually think that YeenFei has a good point here.
It's been a while since i've played with MFC (thank goodness), but from memory, a timer, may or may not be called from the UI thread depending on which one you use. If the timer is being raised on the main UI thread, then a modal dialog will likely halt the main thread until it is dismissed, after which it would be called by the next timer. If the timer is raised on a separate thread, then your dialog is not blocking the main UI thread as it is being shown on a separate thread.
It's does seem more conceivable as YeenFei has pointed out that you want to re-show your dialog each time the timer is raised, hiding it when the user clicks on the button to dismiss it. That way, if the time is raised again, all it does is re-show the dialog whether it is currently open or not.
There is a great post here (www.eggheadcafe.com) about Timers and concurrency that you may find interesting, and may make things clearer than what I managed to accomplish.
Why can't you code it like this:
CdelmeDlg dlg;
dlg.DoModal();
CdelmeDlg dlg1;
dlg1.DoModal();
If you want your application run in background without UI, why not juz temporary hide it? a simple function this->ShowWindow(SW_HIDE) will do the job for you.
i think you should revise your design decision as it seem illogical for an application to behave like what you wanted it to be.
I solved the problem by hiding the dialog instead of closing it and launching another thread that first sleeps and then unhides the dialog.
May be your code has line:
m_pMainWnd = &dlg;
If so, than application after first call of DoModal() will finished, all other call of DoModal() will return -1. From MSDN:
The Microsoft Foundation Class Library will automatically terminate your thread when the window referred to by m_pMainWnd is closed. If this thread is the primary thread for an application, the application will also be terminated.
I want to use XmCreate{Error|Warning|Info}Dialog to display some message in screen in my SDL based application before its main window is open and any program data is available. I want the dialog to open, print the intended message, and when the user clicks on the OK button, the dialog plus the top widget I had to create for it should be closed/removed. Now afaik XtAppMainLoop will loop and process top widget messages (a window?) until the user closes it. I want to close it when the dialog returns though. How can I do that?
After hours and hours of googling and reading I have found out that you can use XtAppSetExitFlag (XtAppContext).
It's easy, in the XtAppContext that is returned from XtAppMainLoop, just do p->exit_flag = 1;.
It's also common for applications to simply include their own main loop and do whatever they want. All XtAppMainLoop does is call XtAppNextEvent(app, &event) and then XtDispatchEvent(&event).