What I want to do:
I want to create a custom menu item (along with minimize, maximize, close, etc.) when a user right-clicks on a window's title bar. Additionally, I want the user to be able to click on my menu item and trigger my code. Also, I want to do this for every newly opened windows. For example, when the user opens up a new notepad window and right clicks on its title bar, he/she will see: Restore, Move, Maximize, Minimize, Foo (my menu item), Close. Once they click on "Foo", my code gets called.
What I have so far:
I am using SetWinEventHook to hook the EventObjectCreate event. I am also following this guide to insert my own menu item (via GetSystemMenu and AppendMenu).
My question:
So now I can successfully inject my own menu item onto newly created windows, but nothing happens when the user clicks on the item. How do I register my function to this menu item when it gets clicked?
P.S. I'm doing this in C# using Pinvoke, not sure if this matters.
You have to hook the windows' window proc (also known as subclassing the window) and handle the WM_SYSCOMMAND message. You check the wParam parameter and call your function if the menu item selected is your custom item.
You're going to run into interesting problems. See, for example, Subclass a native application from C# and Subclassing a external window in C# .NET.
It can be done, but it's not simple.
You might also be interested in http://www.codeproject.com/Articles/3234/Subclassing-in-NET-The-pure-NET-way.
Related
I want to create an application that will run in the background and track the click actions of the mouse, and when the user clicks on an external WPF or Winforms app, the background app should be able to detect the clicked control and display its ID/name/text.
I'm not sure if this is possible, but since there are automation tools that can perform similar actions, I think it should be possible. For example, with some tools it is possible to get the "window" object using the external app's PID, and then the controls (for example a button) can be accessed by providing the ID of the control. However in my case it is the other way around. I need to get ID/name/text of the control the user has clicked.
I can obtain the mouse position using windows Hook
I can obtain the hwnd and Process ID of the window the user has clicked
So is it possible to obtain the information about the element clicked? Any help and advice is appreciated, thanks in advance.
I am trying to control another application with my C# code on Win 7.
I need to programmatically click an option in the menu
I am successfully sending keys to that application, or pressing a "stand-alone" button in that application with:
SendMessage
Spy++ gives me a button's handle, so that SendMessage can hit that button, however I am not able to figure out how to get a handle to the menu item and hit that option (I tried iterating though children of he parent handle, but no luck).
I'm working on a program to simultaneously control a handful of other programs of the same type.
So far I use EnumWindows() and collect the handles of the appropriate windows(programs) that I'm going to be controlling. Upon recognizing some keyboard keystroke, I iterate through all of the programs(there could be any number of them open) and I post click messages to all of these programs simultaneously by using EnumChildWindows() to find the appropriate windows(buttons) based on which keystroke was pressed and then using PostMessage() to actually send the click.
Each of these programs that I'm controlling has a button named "Load Settings" which opens an Open file dialog when clicked. What I would like to do is first use PostMessage() to click "Load Settings"(I have successfully gotten this far, what follows is what I'm trying to do). Then I want to get the handle of that Open file dialog window, fill in the text field with the path to the appropriate settings file that I've already determined, then click the "Open" button to finish the task and close the Open window.
My main problem is finding that Open window. Now, I can use EnumWindows once again to find that window but the problem with this is upon clicking "Load Settings" the Open window doesn't open instantaneously. I could sleep after clicking the button, then enum through the windows to find it, but that's not practical as the window could take any amount of time to open.
I've used spy++ to gather some information about this window, but as far as I know, none of it helps enough. Anyways, here is what I have found:
The window "Open" is the Previous Window to the program which it was opened from.
The window "Open"'s parent is the program which it was opened from.
The window "Open"'s owner is the program which it was opened from.
But even though it's listed as a child of the main program under its window properties, it's listed on the same level as the main program (it's not nested like other child windows).
I've tried FindWindowEx() and EnumChildWindows() but neither could find the Open window.
I would think there should be some way to, based on some handle, get the handle of the previous window.
Once that's working, then I need to fill the Edit(text field) window with the appropriate file path.
UIA is what you want, if your goal is to automate UI actions (e.g. for testing). UIA exposes the entire UIA tree which contains all applications active on the machine.
So what you'll see is a root node which has one child node for each application. Each of those nodes should represent the top level window of that application. Any further children depend on the application itself.
See more info at UIA Overview
In my application I have context menu which is associated with tray icon of the application, when user click on About menu item, it display the message box. Message box is still visible, user right click again on tray icon, menu pop up, user click somewhere else than context menu should disappear, but it didn't, it is still displayed.
That's a bug. Probably in Windows, the MSDN Library documentation for TrackPopupMenu documents a very similar problem. I don't see an obvious workaround, other than avoiding using MessageBox. Create a little form to be your About box. Display it with the Show() method.
You could use SendKeys.Send("{ESC}");
in the trigger event when the user clicks somewhere else.
To attach a winforms dialog on Microsoft Wordpad toolbar/menubar?
First you need to get your assembly loaded into the target process.
Then you'll need to use Win32 API functions to create the new menu item, with a unique child ID.
Finally, you'll need to subclass the window procedure and process WM_COMMAND messages, which are generated by Windows when a native menu item is selected. Be sure to process all other messages, including WM_COMMAND messages that don't match your menu item, to the original window procedure by calling base.WndProc.
Of course, this won't work on Windows 7 WordPad, since it doesn't have menus or toolbars, it uses the new "ribbon" control. The Ribbon API may give you a way to add new items, however.
The Toolbar control that is provided with the Microsoft Windows Common Controls (COMCTL32.OCX) can be customized by users...
http://support.microsoft.com/kb/q174087/