Is there any way to see if the contents of a 'window' have changed, that is referenced only by a handle? Such as one obtained from a pinvoke FindWindow?
If you want to be notified that the text changed, then no. Some windows send notifications of changes to their parent windows, but you would have to be in the process to intercept those messages, and not all windows even send notifications. (I presume by the fact that you are using FindWindow that you are not in-process)
If you want to get the text and check for yoursef, you can do that with a pinvoke to GetWindowText or to SendMessage(hwnd, WM_GETTEXT, ...); (GetWindowText is just a helpful wrapper around a SendMessage)
Related
The title says it all. How can I ask my keyboard hook to tackle incoming keyboard message AFTER the parent window has processed them? Reading the docs I found there is a value named WH_CALLWNDPROCRET that does exactly this, but I need to specify WH_KEYBOARD there (to make it a keyboard hook of course), and the value doesn't appear to be a bit flag, so I can't combine both.
Background: I'm writing an add-in for Word 2013, which needs to monitor certain keys and take appropriate action only after Word has finished processing those keys. I'm using globalmousekeyhook project for hooking.
The library you are referring to is subscribing to following four hooks:
WH_KEYBOARD_LL
WH_KEYBOARD
WH_MOUSE_LL
WH_MOUSE
When you subscribe to a hook you give a system a callback to your code, which will be executed according to the rules which differ from hook type to hook type. Also the information the callback will deliver to you must be interpreted differently. These 4 deliver information about mouse positions, key strokes etc.
There are many different types of hooks you can subscribe to. See: Hook Overview
The WH_CALLWNDPROCRET yo are referring to is one of them. It has different callback invocation behavior and delivers you all messages sent to window. These may include theoretically any of hundreds of possible messages, not only keyboard and mouse messages.
To answer your question the library globalmousekeyhook can not subscribe to any other hooks than those 4 mentioned above.
Good news is that you can probably reuse code form the library to implement your own subscription.
You can reuse code to install the hook.
The signature of your callback will of course be different.
Then you will get all messages.
Filter out only those messages you are interested in e.g. WM_KEYDOWN, WM_KEYUP, WM_SYSKEYDOWN, WM_SYSKEYUP.
Interpret the data delivered along with messages. Also here you can reuse some code from the library.
Conclusion
No, the library can not do what you are looking for.
Yes, you can probably achieve that by reusing code from that library.
What is the best way to manage an external windows application in C# (or .NET)?
So far my I've been able to launch a process using System.Diagnostics.Process, however this simply allows me to launch/kill a process. (from what I've gathered)
I noticed System.Diagnostics.Process has a CloseMainWindow() routine which will send a request to a process' window. Can I use this Process class to send different messages? (if so, can anyone point me in direction of where I can learn about these windows messages)
I need to be able to manage an external program and manipulate it the following ways:
1) Launch
2) Kill Process
3) Show Application (Fullscreen and in taskbar)
4) Hide Application (Fullscreen and in taskbar)
Further details:
Windows 7, Restricted to .Net 3.5 Framework
You might be able to use interop and use SendMessage to do all of your functionality. See this: http://pinvoke.net/default.aspx/user32.SendMessage
Try sending a message to that window. Take a look at SendMessage . The messages you need are SW_MINIMIZE,SW_RESTORE and SW_SHOWMAXIMIZED.
You're going to need to use some Win32 P/Invoke stuff to send window messages in order to do what you want.
See this code sample on ShowWindow or SendMessage which tells an external window to show or hide itself. You'll first need to get the window handle you want with FindWindowEx.
you can do all you want in different ways, once you start the process yourself or you find it in the list of running processes, using classes or methods of System.Diagnostics.Process, then you can follow different options...
for example consider that once you have this handle: Process.MainWindowHandle you can send messages to that handle, with SendMessage and PostMessage and this allows you to do very very much; or you can use PInvoke APIs like SetWindowPos or ShowWindow or SetWindowLong and do basically really everything...
see this for example:
How to use the ShowWindow API to hide and show a form
I can send you more links but won't like to refer to the whole MSDN ;-)
Assuming I have a valid hWnd to an active window (it was retrieved using ‘GetForegroundWindow’ or FindWindow, for example), can I register to windows message of this hWnd, from another application, of course? Is there any Win32 API for this, or a built-in C# method?
Example: In my console application I have a hWnd to the ‘Notepad’ window (running in the background). Can I register somehow to messages indicating the ‘Notepad’ window had moved, changed size, minimized, closed, etc.?
Thanks,
Elad
You have to inject a DLL into the process that owns the window. Use SetWindowsHookEx(), WH_CALLWNDPROC hook. You cannot write such a DLL using the C# language, the process won't have a CLR initialized and ready to run your code. Native code is required. Check this project.
If you just need to know about it moving or closing, then check out SetWinEventHook. You'll have to write a P/Invoke wrapper for this, since there's no equivalent in the .Net API. You can use this without needing to inject a DLL (use the WINEVENT_OUTOFCONTEXT
flag), so can keep everything in C# (and it also avoids the hassle of having to communicate between a separate DLL and your main process).
You'll likely want the events EVENT_OBJECT_LOCATIONCHANGE and EVENT_OBJECT_DESTROY. Note that you get these for all HWNDs on the thread you are listening to, so you'll need to filter by HWND in your callback.
Note that when you use WINEVENT_OUTOFCONTEXT, your own code will need to have a message loop running on the thread that calls SetWinEventHook. Also, the notifications that you receive are not delivered instantly, but with a slight delay (similar to PostMessage), but that may still be fast enough for your purposes that you can avoid doing an in-proc hook.
You can use the Accessible Event Watcher app (AccEvent) that's part of the Windows SDK to see what messages are available from notepad before you start writing code.
Is it possible to utilize the sendInput function on windows that currently do not have focus, and maybe through the use of multithreading, sendinput to multiple minimized windows at the same time, or send input to one window while you're working on another window?
I'd like to do something like this in c#
thanks in advance.
You can only use SendInput to send input to the HWND with keyboard focus. Furthermore the window must be attached to the calling thread's message queue, so one cannot simply SetFocus either.
You'll need to get the window's thread id with GetProcessIdOfThread.
When you have the thread id you can use the AttachThreadInput function to attach your thread to the other threads input processing.
After all this you can probably use SetFocus and SendInput.
You'll probably want to detach your thread when you've sent your input.
To get access to these method you'll have to use P/Invoke for C# or C++/CLI. PInvoke.net is very handy as a reference. It will be a small chore importing all those functions, but when you are done you should be able to send input to whatever "window" you want.
Also as a side note, I'm not sure if you are aware of this, but in pure Win32 everything is regarded as a window, even a button. If you are unlucky you may have to send the input to the handle of the text control belonging to the notepad application.
That is not possible with SendInput. What you probably want to do is find the messages that were sent to the window by the OS when that particular event was performed then emulate them. You can use Spy++ to attach to the target window and perform your event. Then use SendMessage() and PostMessage() to reproduce the messages that were generated by your event. This will work fine for notepad.
If you do use this method, note that you need to send messages to notepad's child window which you can find with FindWindowEx() with a classname of "edit". For example to type text you could try WM_KEYDOWN. You should note that this method is not necessarily reliable:
http://blogs.msdn.com/b/oldnewthing/archive/2005/05/30/423202.aspx
I am trying to emulate "hardware" mouse clicks as it appears that some software blocks input from PostMessage for instance. I know there's SendInput, but that's not an option as I need this to be compatible in background windows as well. The solution seems to be a low-level mouse hook but I've searched around and couldn't find anything other than just the loggers, no manipulation of moving mouse, clicking etc. I'd like this to happen without having to write some sort of C++/C wrapper to use as a fake mouse driver.
http://support.microsoft.com/kb/318804, I found this but it doesn't seem to be of any further help.
Any help appreciated :)
Not sure what 'some software' might be, but sure, UAC stops you from poking messages into the windows of elevated programs. It is called UIPI, User Interface Privilege Isolation.
In general, faking input with PostMessage doesn't work well at all. It is especially a problem for keyboard input but mouse input has trouble too. There is no good way to alter the keyboard state for another process. That matters when the program checks the state of the Shift, Ctrl and Alt keys when it processes the input message. Many do.
The only real solution is to emulate input with SendInput(). Now you got a focus problem to solve.
mouse_event or SendInput used to inject mouse input. But just like a real mouse it's global input and can't work on hidden windows.
A low-level-mouse-hook is global too, but it is used to intercept and manipulate mouse-input, not to inject input.
When targeting a specific window you'll need to use SendMessage, but as you noted it doesn't work for everything.
You can also use dll hooking(for example an IAT hook) to intercept calls to APIs which return the gobal cursor position or the state of the mousebuttons. But for that you need to inject a dll into the target application, and that dll shouldn't use .net.
When I have to simulate mouse input I first try with SendMessage but sometimes some control or the application could eat the message.
In that situations I use spy++ to intercept messages of the window that holds the control, I do exactly what I want to simulate and then, I just use:
GetWindowLong(hwnd, GWL_WNDPROC);
to get window proc and then call the wnd proc(process) directly with:
CallWindowProc(WNDPROC lpPrevWndFunc, HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam)
Sending exactly those messages that I saw using Spy++. That always work because the window proc is called immediately instead of queued in the message loop.
Take a look at this library http://globalmousekeyhook.codeplex.com/.
It is 100% managed c# code to install global mouse and keyboard hooks.