Click to See Complete Forum and Search --> : SendMessage Hangs on WM_LBUTTONDOWN to TreeView


wilmo
August 15th, 2008, 11:41 AM
short int ypos = 8;
short int xpos = 27;
short int down_message = WM_LBUTTONDOWN;

LRESULT mouse;
mouse = SendMessage( tv_handle, WM_MOUSEACTIVATE, (WPARAM) mainwindow_handle, down_message << 16 | 1 );

mouse = SendMessage( tv_handle, WM_LBUTTONDOWN, MK_LBUTTON , ypos << 16 | xpos ); /**** Hangs on this call, until mouse enters main window area */
printf( " Mouse Down %d\n" , mouse );

mouse = SendMessage( tv_handle, WM_LBUTTONUP, MK_LBUTTON , ypos << 16 | xpos );
printf( " Mouse up %d\n" , mouse );

mouse = SendMessage( tv_handle, WM_MOUSELEAVE, 0, 0);
printf( " Mouse leave %d\n" , mouse );

----------------------------------------

I am new to win32 programming.
The code above is an experiment with automating windows. This code runs from a seperate process ( a console app ). It uses FindWindow() to find the main window handle, then uses EnumChildWindows() to inspect the main windows contents.
I am trying to set/unset a checkbox in a SysTreeView32. The target application is a wxWindows app. I found the relative x,y positions by using MS Spy++. These messages are trying to simulate the messages I see when clicking the checkbox.

I've tried TreeView_SelectItem() and TreeView_SetCheckState() with no luck.

Does anybody know why the call commented above might hang until the mouse moves over the window? I'm at my end.

Thanks,
wil

kirants
August 15th, 2008, 12:19 PM
Have you investigated using SendInput ?

wilmo
August 15th, 2008, 02:00 PM
Have you investigated using SendInput ?

I started playing with it but when I couldn't find where to pass the window handle, I gave up. Plus, Its struct gave me a compiler error.

I started setting up the input struct array like so:

INPUT minputs[2];
minputs[0].type = INPUT_MOUSE;
minputs[0].mi.dx = 27;
minputs[0].mi.dy = 8;
minputs[0].mi.mouseData = 0;
minputs[0].mi.dwFlags = MOUSEEVENTF_LEFTDOWN;
minputs[0].mi.time = 0;
minputs[0].mi.dwExtraInfo = 0;

minputs[1].type = INPUT_MOUSE ;
minputs[1].mi.dx = 27;
minputs[1].mi.dy = 8;
minputs[1].mi.mouseData = 0;
minputs[1].mi.dwFlags = MOUSEEVENTF_LEFTUP;
minputs[1].mi.time = 0;
minputs[1].mi.dwExtraInfo = 0;

but w/o the handle I think my x,y positions would be relative to the desktop. This didn't seem like what I want.

Did I miss something with this api?

Also, as a side note, I'm using MS Studio 2003 and got :
error C2065: 'INPUT' : undeclared identifier
even though I was including Windows.h . ( even if winuser.h is included directly ) Perhaps _WIN32_WINNT define is not right? I don't know.

MikeAThon
August 15th, 2008, 05:42 PM
Before sending messages to the target window, try calling SetForegroundWindow() on its handle.

Mike

muse1987
August 16th, 2008, 02:08 AM
Where that treeview you're sending message to belongs? Is it created by your program or other? The only reason I can think is, SendMessage() waits until the target window processes the message. That means, if you're calling SendMessage() in your application's main thread where the target window's message loop is, then the call will hang.

To explain, SendMessage() puts the message into message queue and waits until the target window processes the message. But the message will be processed when the message loop executes GetMessage()/TranslateMessage()/DispatchMessage() sequence, which is only possible after SendMessage() finishes. Thus it results deadlock.

Maybe you can use PostMessage() instead. But there're certain cases you do need SendMessage(). If you need to ensure the message has been processed before proceeding, then you can use CallWindowProc() function.

BTW, was it the reason, anyway?

muse1987
August 17th, 2008, 12:39 AM
Well, I was wrong :blush: SendMessage() calls the window procedure directly. I'm curious to know whether SetForegroundWindow() will work... :confused:

However could you try using PostMessage()? I'd love to see what happens.

wilmo
August 18th, 2008, 08:30 AM
Thanks for the Suggestions.

To clarify:
I am using one process to talk to another separate process not created by me.

Results:

SetForegroundWindow( mainwindow_handle ) did execute and brought the window to the forground. However, the sending process still hung.

When replacing the SendMessage() calls with PostMessage(), The background process does handle the message and the sending process does not hang.

So in summary, PostMessage() is the solution to my problem.


RTFM:
It turns out, I should have read the documentation more carefully.

http://msdn.microsoft.com/en-us/library/ms644950(VS.85).aspx

Sends the specified message to a window or windows. The SendMessage function calls the window procedure for the specified window and does not return until the window procedure has processed the message.

To send a message and return immediately, use the SendMessageCallback or SendNotifyMessage function. To post a message to a thread's message queue and return immediately, use the PostMessage or PostThreadMessage function.


http://msdn.microsoft.com/en-us/library/ms644944(VS.85).aspx

The PostMessage function places (posts) a message in the message queue associated with the thread that created the specified window and returns without waiting for the thread to process the message.


Thanks for your assistance.
wil