开发者

How can I build a Windows application that intercepts and passes through keystrokes and mouse clicks to other applications?

开发者 https://www.devze.com 2023-02-27 19:33 出处:网络
I\'m working with a customer who wants to add functionality to a legacy application.The application, whose vendor is useless, has a Windows Forms UI.What my customer wants is for certain functionality

I'm working with a customer who wants to add functionality to a legacy application. The application, whose vendor is useless, has a Windows Forms UI. What my customer wants is for certain functionality ou开发者_高级运维tside this application to be triggered when the user clicks on a piece of information in the application.

I've seen a simple version of this done for another customer. In this case, there's an app consisting of a form that's been set to a topmost window using SetWindowPos. When the user clicks a button on this form, the app finds the window for the legacy app and gets information out of the window's caption. It's inelegant - there's this floating button that never goes away even if the legacy app isn't open - but it works.

I was wondering if it would be possible to do something similar to this using a borderless transparent WPF window with the Topmost property set. The app I'm thinking of would analyze the content in the legacy app's window and define a list of hotspots. It would intercept and handle any mouse click in a hotspot, and pass all remaining mouse clicks through to the legacy app.

I'm not terrifically experienced with the Windows API, so I don't know if it's straightforward (or even possible) to implement this kind of capability. And it occurs to me that if I were authoring anti-malware tools, the application I have in mind is exactly the kind of thing I'd be trying to cripple.

If this is actually a viable project, what's the best way to approach doing it? What unexpected problems should I be looking out for?


This can be done without any trickery with overlaying buttons by means of WH_CALLWNDPROC and/or WH_GETMESSAGE hooks.


I would definitely try UI Automation. It may not work, but at least, it should be fairly easy to try. And, most of the time, if it does not work, it means there won't be any other "easy" way.

UI Automation finds its root in assistive technologies for disabled people, which is most of the time what we want to do with apps we don't own: do things from an external application, without being able to really do it "the standard way".

It also logically has the notion of events, see the officiel doc here: UI Automation Events Overview


Subclassing in my opinion is what you are looking for.

When a Windows application is created, it generates a Window, then adds sub-Windows to that Window (sub-Windows are known as Controls and act EXACTLY like Windows! They can be buttons, text areas, etc...).

Each window has a Window procedure, and every time a user/program interacts with your window, your window procedure will receive a message containing information about the interaction. Quite often, controls will share one window procedure with their parent and inside that window procedure, the code determines what to do based off of the ID (hwnd) of the window/control that the message is describing - that is to say: "close program if 'click' message describes exit button control. do nothing if 'click' message describes parent window.".

To read more about Windows, look here: http://msdn.microsoft.com/en-us/library/aa383738%28v=vs.85%29.aspx

Subclassing is the process of intercepting and/or trapping messages destined for another Window procedure. It usually serves as a way to extend the behavior of controls and windows of third party apps. It is possible to subclass another process using a DLL, GetWindowLong(), SetWindowLong(), CallWindowProcedure(), and your own custom window procedure. It is pretty easy - here's how you'd go about doing it:

  • Locate the target window you wish to subclass using FindWindow()
  • Get the previous window procedure and store it.

WNDPROC wpOrigEditProc = GetWindowLong(hTargetWnd, GWL_WNDPROC)

  • Overwrite the window procedure with your own.

SetWindowLong(hTargetWnd, GWL_WNDPROC, HookWndProcedure);

Then, when you unload, restore the old window procedure again. The Window procedure is where all your magic will happen. You will be able to decide inside that function which messages you wish to handle and which messages you wish to pass on to the old window procedure. Here is an example window procedure:

LRESULT APIENTRY HookWndProcedure(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { 
    if(hwnd == hTargetWndButton_OK) {
        // This is the button we wish to intercept... do some processing, then send it back to Windows
        return DefWindowProc(hwnd, uMsg, wParam, lParam); 
    } else {
        // Allow the message to pass through to the original application's window procedure.
        return CallWindowProc(wpOrigEditProc, hwnd, uMsg, 
            wParam, lParam); 
    }
} 

`

The trick then, is to get your DLL loaded into the target process. I believe the best way to do this would be to add an import entry that points to your DLL into the application since the application and your DLL should stay bundled together anyways. To add an import use CFF Explorer!

I'm sure you'll have more questions because there may be some information missing. I'll try to answer any more questions that arise from my post, but if I do not respond immediately, read the above MSDN link :D. Hopefully this will turn out to be a great learning experience for you :)


And alternative method to davids suggestion is to use GetWindowLong, SetWindowLong and CallWindowProc to hook the applications window proc, imo its a little simpler than using the 'windows hooking' method but it can still be hooked via that method and/or subclassed again. see subclassing a window on msdn for a short example: http://msdn.microsoft.com/en-us/library/ms633570(v=vs.85).aspx#subclassing_window


Check diz: http://www.autohotkey.com/

It's scriptable, can read window titles etc., etc. (When I was using MS-Windows, I've written a tiny script, which poped up a window with the sum of item price and p+p cost, which values were parsed from the selection of an ebay webpage. Also, I've changed it to my currency. So, I've just marked the item's price and p+p, pressed a key, and voila.)

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号