I need to handle another windows application programatically, searching google I found a sample which handles windows calculator using DLLImport Attribute and importing the user32.dll functions into managed ones in C#.
The application is running, I am getting the handle for the main window i.e. Calculator itself, but the afterwards code is not working. The FindWindowEx method is not returning the handles of the children of the Calculator like buttons and textbox.
I have tried using the SetLastError=True on DLLImport and found that I am getting an error code of 127 which is "Procedure not found".
This is the link from where I got sample application:
http://www.codeproject.com/script/Articles/ArticleVersion.aspx?aid=14519&av=34503
Please help if anyone knows how to solve it.
UPDATE: The DLLImport is:
[DllImport("user32.dll", SetLastError = true)]
public static extern IntPtr FindWindowEx(IntPtr parentHandle, IntPtr childAfter, string className, string windowTitle);
The Code that is not working is:
hwnd=FindWindow(null,"Calculator"); // This is working, I am getting handle of Calculator
// The following is not working, I am getting hwndChild=0 and err = 127
hwndChild = FindWindowEx((IntPtr)hwnd,IntPtr.Zero,"Button","1");
Int32 err = Marshal.GetLastWin32Error();
I was able to repro this on Win7 Pro. Your problem is likely that the labels on the buttons are drawn via the theme of the calculator and not as a caption. When the Themes service is running, starting Calculator will cause it to have buttons with no caption.
In order to get proper button captions, you must:
net stop themes
from an elevated command prompt or use the Services administrative tool).If you have Calculator running when you stop the Themes service, you will notice that all of its buttons become blank.
The code you're trying relies on the captions of the individual buttons to identify them. For example, it uses the following code to get a handle to the "1" button:
Which specifies "Button" for the name of the window class, and "1" for the name of the window (in the case of a button, this is the same as the caption text displayed on the button itself).
This code worked fine under Windows XP (and previous versions), where the calculator buttons were identified with textual captions. The "1" button had a window name of "1", and thus "1" was displayed as the button's caption.
However, it looks like things have changed under Windows 7 (possibly under Vista as well, although I can't verify this because I don't have access to such a system). Using Spy++ to investigate the calculator window confirms that the "1" button no longer has a window name of "1". In fact, it doesn't have a window name at all; the caption is NULL. Presumably, the new fancy look of the calculator required that buttons be custom drawn, thus the captions are no longer necessary to indicate which button corresponds to which function. The custom painting routines take care of drawing the necessary captions.
Since no button can be found with the window text you specified, a value of 0 (
NULL
) is returned for the window handle.The documentation for the
FindWindowEx
function indicates that you can specifyNULL
for thelpszWindow
parameter, but that this will, of course, match all windows of the specified class. Probably not what you want in this case, as the calculator app has a bunch of buttons.I don't know a good workaround. Calculator wasn't designed to be "automated" this way, and Microsoft never guaranteed that they wouldn't change its internal workings. That's a risk you take in using this approach to mess with the windows of other applications.
EDIT: The code you've linked to is also wrong in another fairly serious way, even on earlier versions of Windows. It declares the
hwnd
variable as typeint
, rather than as typeIntPtr
. Since a window handle is a pointer, you should always store it as anIntPtr
type. That also fixes the ugly cast in theFindWindowEx
function call that should have sent up red flags.You'll also need to fix the declaration of
SendMessage
so that its first parameter is of typeIntPtr
.The code should have been written like this:
The following code works fine in Caculator of Windows 7 in Classic theme (won't working in Basic or Aero theme):
==================================================