MFC Send message to MAIN thread (rather than a window)? - c++

I'm writing a GUI application for Windows using MFC and C++.
So I need to send messages to my MAIN thread from my worker thread to tell it to update my GUI. However I'm not sure how to send a message to the actual MAIN thread rather than a Window. As it is I can see it is in the MAIN thread when it receives the message but I am not sure if this is guaranteed or just luck.
In worker:
PostMessage( *myTestToolDlg, WM_YOU_HAVE_DATA,UPDATE_GUI, 0 );
In application window:
LRESULT CTestToolDlg::OnData(WPARAM wp, LPARAM )
Does this somehow mean that?

You can get your main thread's thread id by using something like threadId = GetCurrentThreadId(); in the main thread, and then send a message to it by calling PostThreadMessage(threadId, ...) from your worker thread.
However, as Hans Passant said -> here <-, you should avoid using PostThreadMessage to send messages to UI threads, and should better send messages to its window.

If you want to modify a ListBox or ListView directly, you can use SendDlgItemMessageA()
Example :
char const* pChar = "My text to be updated";
SendDlgItemMessageA(hWindow, IDC_LISTBOX, LB_DELETESTRING, 0, 0);
SendDlgItemMessageA(hWindow, IDC_LISTBOX, LB_INSERTSTRING, -1, (LPARAM)pChar);

Related

Get notified when a Window closes (or it's owning thread disappears)

I have a hwnd, which my process does not own, and I want to be notified when it disappears so that my code can perform cleanup actions. What's the best way to do this?
To detect when the HWND's owning process disappears, you can get the HWND's process ID from GetWindowThreadProcessId(), then get a HANDLE to the process using OpenProcess(), and then use WaitForSingleObject() or other related wait function. A process handle is signaled when the process exits.
To detect when just the HWND disappears, get the HWND's thread ID from GetWindowThreadProcessId() and then use SetWindowsHookEx() to hook the message queue of that thread so you can intercept WM_DESTROY and WM_NCDESTROY messages for all HWNDs belonging to that thread, looking for the particular HWND that you are interested in. Note that your hook must be implemented in a DLL when hooking another process, so you will have to use an inter-process communication mechanism of your choosing to notify your main app when the HWND is destroyed.

c++ MFC setting/appending text to a richedit control from a worker thread

from the main thread i can use member variables like so:
CString updatetext;
updatetext.Format(L"character length: %d\n", length );
long nStart, nEnd;
m_richeditcont.
GetSel(nStart, nEnd);
m_richeditcont.SetSel(nEnd, nEnd);
m_richeditcont.ReplaceSel(updatetext);
however, without a worker thread the program would just hang. you can't use member variables from a worker thread, so how would i go about updating a richedit control with the text stored in updatetext from a worker thread?
i don't have any actual code, the code above is just an example, i just want to know how i would go about appending text stored in updatetext to a richedit control from a worker thread.
The worker thread can send data over to the GUI thread using PostMessage or SendMessage. Then the GUI thread should be responsible for modifying the GUI. See FAQ 12 here:
http://vcfaq.mvps.org/mfc/index.htm
The worker thread should allocate the CString on the heap, then post the pointer in the lparam or wparam of the custom message. The GUI thread casts the pointer back to CString* and updates the control. Finally, the GUI thread deletes the CString from the heap.

Wait for handle/event async or call back within the same thread

I have a global event created with CreateEvent, and I get a handle to this event in another application using OpenEvent.
Then I wish to do something like:
(pesudo code)
register_event_change_notification(my_call_back);
void my_call_back()
{
// do work
}
Where my_call_back is executed on the same thread that called register_event_change_notification. However my problem is that I can't find any API's that allow this. It appears that you only have the following options:
Create a thread which uses WaitForSingleObject and then just calls my_call_back and put critical sections around everything.
Create a thread which uses WaitForSingleObject and block your main thread with a message loop, then post events when WaitForSingleObject to get my_call_back executed in the same thread as the message loop - which might not be the same thread that called register_event_change_notification.
This seems like a simple problem that must have been solved many times? Its overkill to have to deal with threading issues just to know when an event has been signaled IMO.
Edit:
In the end I went for using QueueUserApc - but it means your message put must use the *Ex API's to put the thread in an alertable state. Another gotcha is that you must track your outstanding APC's and not to destruct objects before they have serviced all of their APC's. Otherwise you'll get an APC queued to a destructed/deleted object.
Your analysis of your options is correct. For option 2, which uses a message, you have two options to steer the notification to a desired thread. (a) For a non-GUI thread destination use PostThreadMessage. (b) For a GUI thread destination you can PostMessage or SendMessage to a destination HWND. The message is received by the thread that created the HWND.
Here - http://pastebin.com/ucpDdYGZ - is my decision of a problem. Sorry for non-english comments (they are in russian).
The main idea is to create a dummy window with
m_wnd = CreateWindowA( "STATIC", "", 0,
CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
HWND_MESSAGE, NULL, NULL, NULL);
and to send it a message via SendMessage

How do I SendMessage() to a window created on another thread?

I have a situation where I want to SendMessage to a window that was created on another thread than the one that is calling SendMessage.
The default behaviour seems to be block forever and not work.
So I changed the call to PostMessage, which didn't block the sending thread, but the message never appears to arrive at the intended window.
So how do I SendMessage to a window created on a separate thread, or is this impossible?
The PostThreadMessage function posts a message to the message queue of the specified thread. you can specified Identifier of the thread to which the message is to be posted. is that you want?
What is the thread that owns the target window doing? It needs to be pumping messages in order to be able to receive messages that are either sent or posted to it. Typically this is done by having a GetMessage/TranslateMessage/DispatchMessage loop. If the thread is doing something else - such as blocking waiting for an event or mutex or IO to complete, or is busy in some other loop carrying out a calculation, it won't receive messages: SendMessage to the thread will block, and PostMessage will post but not get delivered.
If that target thread needs to both manage events or similar, and it also owns a window, you may need to use MsgWaitForMultipleObjects in that thread's message loop.
You are running into a deadlock. An example, if you SendMessage to another thread, then the windowProc in that thread does SendMessage back to your window, they will lock waiting each other forever.
You need to either fix PostMessage (it does deliver messages, there's just error in your code somewhere), or be very careful about who calls who and when.
To protect against threads that are busy or hung, there is SendMessageTimeout.
Each control you create belongs to the thread that created it, which means that the WndProc for that control will be running in the thread that created the control. You send messages with SendMessage and PostMessage freely to any control.
The issue with CWnd::PostMessage and CWnd::SendMessage is the same. The message is being pushed out, and not being received by anything. SendMessage is blocking by design; it's job is to block the thread until the message is received.
MSDN says this about SendMessage:
"The SendMessage function calls the window procedure for the specified
window and does not return until the window procedure has processed
the message."
It is possible to send a message to window on another thread using CWnd::PostThreadMessage or winapi PostMessage. When you create the window you can use GetSafeHwnd() to get the handle or you can use a thread ID when the thread is created.

Timer in a win32 service

Can someone please point me to the easiest way to have a timer in a Win32 service?
I suppose I could create a dummy window for this purpose or have a second thread do tick counts, but what's best? Is there a more elegant way?
Thanks in advance.
You can use Timer Queues (http://msdn.microsoft.com/en-us/library/ms686796.aspx). They don't require an HWND.
Instead of using UI timers (even though you can use the NULL window handle as shown by Mr. 1800-INFO) you can use kernel waitable timer objects. See CreateWaitableTimer in the API docs. These can then be waited-on using WaitForSingleObject or WaitForMultipleObjects, etc, which is especially useful if that's already how your service waits for external events.
If it's not clear from that first link, the SetWaitableTimer function can associate a completion routine (user callback) with the timer. Remember to use the ...Ex versions of WaitForMultipleObjects (etc.) so that the thread is in an "alertable" state.
You can send your main thread WM_TIMER messages. The lParam for the message is the address of a callback function, or you can leave it NULL and handle it yourself in your message pump.
In this example, we are sending the timer to the thread message pump, there is no requirement to have a window associated with the timer.
UINT timer;
VOID CALLBACK Timer(HWND hwnd,
UINT uMsg,
UINT_PTR idEvent,
DWORD dwTime
)
{
KillTimer(0, timer);
}
timer=SetTimer(0, // window handle
0, // id of the timer message, leave 0 in this case
10000, // millis
Timer // callback
);
// pump messages
while (GetMessage) etc...
The Timer callback will be called by DispatchMessage. This question reminded me of the recent ONT.
You can use SetTimer to set the timer, then catch the WM_TIMER message in your message loop.
Example:
// Set a timer to expire in 10 seconds
SetTimer(hwnd,IDT_TIMER1, 10000,(TIMERPROC) NULL);
... then in message loop:
switch (wParam)
{
case IDT_TIMER1:
// Boom goes the dynamite
You can also decleare a function of type TIMERPROC and have that be called when the timer expires, if you don't want to do the message loop handling.
In one of your comments you said that "...the service is processing stuff in other threads, I just need to check the status of a few files every second."
Polling is not an optimal way of checking file status, and will adversely affect system performance. While there are (sometimes) problems doing this over networks, you should check out http://msdn.microsoft.com/en-us/library/aa364417(VS.85).aspx or http://msdn.microsoft.com/en-us/library/aa365261(VS.85).aspx for how to do it and http://blogs.msdn.com/oldnewthing/archive/2006/01/24/516808.aspx for why you should.
Are you just trying to "wake up" every now and then to do some work? You can always use Sleep().
Additionally, I typically have a thread that is in a while(1 == 1) loop with a sleep inside. There I can check for the shutdown request and other misc housekeeping. You could use that system to tickle an event or mutex for the worker thread in the app.