user32.dll 中的 FindWindowEx 使用 dllimport 返回零句柄和 127 错误代码
我需要以编程方式处理另一个 Windows 应用程序,搜索 google 我找到了一个示例,该示例使用 DLLImport 属性处理 Windows 计算器,并将 user32.dll 函数导入到 C# 中的托管函数中。
应用程序正在运行,我正在获取主窗口的句柄,即计算器本身,但随后的代码不起作用。 FindWindowEx 方法不返回计算器子项(如按钮和文本框)的句柄。
我尝试在 DLLImport 上使用 SetLastError=True ,发现收到错误代码 127,即“未找到过程”。
这是我获取示例应用程序的链接:
http: //www.codeproject.com/script/Articles/ArticleVersion.aspx?aid=14519&av=34503
如果有人知道如何解决,请帮忙。
更新: DLLImport 是:
[DllImport("user32.dll", SetLastError = true)]
public static extern IntPtr FindWindowEx(IntPtr parentHandle, IntPtr childAfter, string className, string windowTitle);
不起作用的代码是:
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 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();
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
您尝试的代码依赖于各个按钮的标题来识别它们。例如,它使用以下代码来获取“1”按钮的句柄:
其中指定“Button”作为窗口类的名称,“1”作为窗口的名称(对于按钮,这与按钮本身显示的标题文本相同)。
该代码在 Windows XP(和以前的版本)下运行良好,其中计算器按钮用文本标题标识。 “1”按钮的窗口名称为“1”,因此“1”显示为按钮的标题。
然而,在 Windows 7 下情况似乎发生了变化(也可能在 Vista 下,尽管我无法验证这一点,因为我无权访问这样的系统)。使用 Spy++ 调查计算器窗口,确认“1”按钮不再具有窗口名称“1”。事实上,它根本没有窗口名称;它没有窗口名称。标题为 NULL。据推测,计算器的新奇特外观需要自定义绘制按钮,因此不再需要标题来指示哪个按钮对应哪个功能。自定义绘画例程负责绘制必要的标题。
由于找不到具有您指定的窗口文本的按钮,因此为窗口句柄返回值 0 (
NULL
)。FindWindowEx
函数的文档指出您可以为lpszWindow
参数指定NULL
,但这当然会匹配指定类的所有窗口。在这种情况下可能不是您想要的,因为计算器应用程序有很多按钮。我不知道一个好的解决方法。计算器并不是以这种方式“自动化”设计的,微软也从未保证他们不会改变其内部运作方式。使用这种方法来扰乱其他应用程序的窗口是有风险的。
编辑:您链接到的代码在另一个相当严重的方面也是错误的,即使在早期版本的 Windows 上也是如此。它将
hwnd
变量声明为int
类型,而不是IntPtr
类型。由于窗口句柄是一个指针,因此您应该始终将其存储为 IntPtr 类型。这还修复了 FindWindowEx 函数调用中本应发出危险信号的丑陋转换。您还需要修复
SendMessage
的声明,以便其第一个参数的类型为IntPtr
。代码应该这样写:
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:
我能够在 Win7 Pro 上重现这一点。您的问题可能是按钮上的标签是通过计算器的主题绘制的,而不是作为标题绘制的。当主题服务运行时,启动计算器将导致其按钮没有标题。
为了获得正确的按钮标题,您必须:
net stop theme
或使用服务管理工具)。如果停止主题服务时计算器正在运行,您会注意到它的所有按钮都变成空白。
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.
以下代码在经典主题的 Windows 7 计算器中运行良好(不适用于基本或 Aero 主题):
The following code works fine in Caculator of Windows 7 in Classic theme (not working in Basic or Aero theme):