Link to home
Start Free TrialLog in
Avatar of akoyuncu
akoyuncuFlag for Türkiye

asked on

SendMessage & PostMessage does not work.

Hi,

I need to send various set of keycodes to an application. For this purpose, I use the following
code:

[NativeWin32.cs]
       ...
        [DllImport("user32.dll")]
        public static extern int FindWindow(
            string lpClassName, // class name 
            string lpWindowName // window name 
        );

        [DllImport("user32.dll", SetLastError = true)]
        public static extern int FindWindowEx(
            int parentHandle, 
            int childAfter, 
            string className, 
            int windowTitle
        );

        [DllImport("user32.dll")]
        public static extern int SendMessage(
            int hWnd, // handle to destination window 
            uint Msg, // message 
            int wParam, // first message parameter 
            int lParam // second message parameter 
        );
       ...

Open in new window


and

            int iHandle = NativeWin32.FindWindow(null, txtTitle.Text);
           // int cHandle = NativeWin32.FindWindowEx(iHandle, 0, null, 0); 

            MessageBox.Show("iHandle is " + iHandle.ToString()+" "+cHandle.ToString());

            NativeWin32.SetForegroundWindow(iHandle);
            
            string keys = "";
            string space = " ";

            //  WM_KEYDOWN = 0x0100
            // NativeWin32.BTN_LEFT = 0x025
            NativeWin32.SendMessage(iHandle, NativeWin32.WM_KEYDOWN, NativeWin32.BTN_LEFT, 0);

Open in new window

     
The problem is the fact that when I send this message to the application in question, nothing happens -- I exactly know that this application supports and listens these keycodes.

What I want to do is to send the following keys to the application:

- LEFT_ARROW
- RIGHT_ARROW
- UP / DOWN
- ENTER
- ESC
and etc.

Could you please check and tell me where I am wrong?

Thanks in advance.
Avatar of AndyAinscow
AndyAinscow
Flag of Switzerland image

Have you actually checked (eg. Spy++) that the correct window is found?
You might have to send the WM_KEYUP message as well as the WM_KEYDOWN.


Also have a look at the SendInput function in help.  That is how one ought to synthesise keyboard events.
Avatar of akoyuncu

ASKER

Yes, I checked and verified that it finds the correct window.
Let me try WM_KEYUP
Andy;

WM_KEYUP also does not work.

I did some modifications on my code as follows:

        [DllImport("user32.dll")]
        public static extern IntPtr FindWindow(
            string lpClassName, // class name 
            string lpWindowName // window name 
        );

        [DllImport("user32.dll", SetLastError = true)]
        public static extern IntPtr FindWindowEx(
            IntPtr parentHandle, 
            int childAfter, 
            string className,
            string windowTitle
        );

        [DllImport("user32.dll", SetLastError = true)]
        public static extern bool PostMessage(
            IntPtr hWnd, 
            uint Msg,
            IntPtr wParam,
            IntPtr lParam
        );


        [DllImport("user32.dll")]
        public static extern int SendMessage(
            IntPtr hWnd, // handle to destination window 
            uint Msg, // message 
            IntPtr wParam, // first message parameter 
            IntPtr lParam // second message parameter 
        );

        [DllImport("user32.dll")]
        public static extern int SetForegroundWindow(
            IntPtr hWnd // handle to window
            );

Open in new window


and I used POSTMESSAGE instead of SENDMESSAGE,

NativeWin32.PostMessage(iHandle, 0x0101, (IntPtr) Keys.Left, IntPtr.Zero);

Open in new window


But it doesn't work!
PostMessage and SendMessage differ only in that PostMessage returns immediately, SendMessage waits until the message is processed.


(I've never tried to do what you are trying from a .net application)

Have you looked at the SendInput function - that is the recommended function to simulate keyboard events, not KEYDOWN/KEYUP messages.
Andy;

I checked what SENDINPUT was but I didn't try. Do you have a sample code?
I've found this for .net apps - that might be more useful (you still need to set the recipient as foreground window before using this.


http://msdn.microsoft.com/en-us/library/system.windows.forms.sendkeys%28vs.71%29.aspx
I
ntPtr iHandle = NativeWin32.FindWindow(null, txtTitle.Text);
            IntPtr cHandle = NativeWin32.FindWindowEx(iHandle, 0, null, null);
 
            NativeWin32.SetForegroundWindow(cHandle);
 
           System.Windows.Forms.SendKeys.Send("{LEFT}");

Open in new window


This doesn't work :/
Btw, System.Windows.Forms.SendKeys.Send works for other external
applictions, but this :(

There is one more service that controls this application.

What I want is to code the similar one.
OK.  SendKeys does work (at least for some apps), progress of sorts.

What are you wanting to send the keyboard input to?
Andy;

- F10
- Keyboard (A, B, C, D, F, R, M, V, W)
- ESCAPE
- ENTER
- ARROWS (UP/DOWN/LEFT/RIGHT)
- HOME

On Spy++, I noticed that there are 4 sub windows:

Window (Container)
. Child Window (ATL class)
. Child Window (Shell Embedding)
... Child Window (Shell DocObject View)
...... Child Window (Internet Explorer_Server)
Maybe the window you want to be sending the keypresses to isn't the one with the focus.  Can you check that?
Yes, I double check and did this:

            IntPtr iHandle = NativeWin32.FindWindow(null, txtTitle.Text);
            IntPtr cHandle = NativeWin32.FindWindowEx(iHandle, 0, null, null);
            IntPtr dHandle = NativeWin32.FindWindowEx(cHandle, 0, null, null);
            IntPtr eHandle = NativeWin32.FindWindowEx(dHandle, 0, null, null);
            IntPtr fHandle = NativeWin32.FindWindowEx(dHandle, 0, null, null);
            IntPtr gHandle = NativeWin32.FindWindowEx(fHandle, 0, null, null);

NativeWin32.SetForegroundWindow(cHandle);

           NativeWin32.PostMessage(cHandle, 0x0101, (IntPtr)(0X25), IntPtr.Zero);
           NativeWin32.PostMessage(cHandle, 0x0101, (IntPtr)(0X50), IntPtr.Zero);

           NativeWin32.PostMessage(dHandle, 0x0101, (IntPtr)(0X25), IntPtr.Zero);
           NativeWin32.PostMessage(dHandle, 0x0101, (IntPtr)(0X50), IntPtr.Zero);

           NativeWin32.PostMessage(eHandle, 0x0101, (IntPtr)(0X25), IntPtr.Zero);
           NativeWin32.PostMessage(eHandle, 0x0101, (IntPtr)(0X50), IntPtr.Zero);

           NativeWin32.PostMessage(fHandle, 0x0101, (IntPtr)(0X25), IntPtr.Zero);
           NativeWin32.PostMessage(fHandle, 0x0101, (IntPtr)(0X50), IntPtr.Zero);

           NativeWin32.PostMessage(gHandle, 0x0101, (IntPtr)(0X25), IntPtr.Zero);
           NativeWin32.PostMessage(gHandle, 0x0101, (IntPtr)(0X50), IntPtr.Zero);

Open in new window


No use...
Would the recipient window respond to normal text?  In other words could you send "abc123" or similar.  (Preferably with SendKeys or at least with PostMessage).

I just want to see, if possible, if it has something to do with sending non text keypresses.
I sent "abc123" to two applications: Notepad and the other one.

Notepad: "abc123" appears on "Edit". No problem.

My application: no reaction.
ASKER CERTIFIED SOLUTION
Avatar of AndyAinscow
AndyAinscow
Flag of Switzerland image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Maybe
The GetForegroundWindow function returns a handle to the foreground window (the window with which the user is currently working). The system assigns a slightly higher priority to the thread that creates the foreground window than it does to other threads.

that could give you a cross check that the window you are sending to is in fact the one you think it is.
Thank you for your support.

I will dig deeply into it and get back to you if I will find something.
        [DllImportAttribute("User32.DLL")]
        public static extern IntPtr GetForegroundWindow();

Open in new window


I used. Returns the same handler.
I'd agree with Andy that you are not sending the message to the correct window.  Use Spy++ to watch each of the child windows and figure out which one actually processes the messages as keys are pressed.
Avatar of nffvrxqgrcfqvvc
nffvrxqgrcfqvvc

If the window that you really want is Internet Explorer_Server and you want to send text to it you can treat it like a normal IHTMLDocument2 interface even if it's hosted in a third party application.

How to get IHTMLDocument2 from a HWND
http://support.microsoft.com/kb/249232
Let me tell you about the application:

This is a Windows application that has four windows:

1st layer is container.
2nd layer is control panel
3rd and 4th layers are to display video stream over Silverlight (that's why Internet Explorer Service) is used.

Yesterday, using Spy++, I track down the log messages and verified that 1st (or 2nd) layer receives the following:

WM_KEYDOWN, VK_RIGHT/LEFT/UP/DOWN/F11/ESCAPE
WM_CHAR, Char(23/27)

However, when I tried to send WM_KEYDOWN to 1st and 2nd layers nothing happens. Today, I will also test my code on other system and let you know about the result.
Found!

I need to send keycodes to Microsoft Silverlight process.

Working now.

Thank you all for your help :)
Thanks.