简体   繁体   English

如何在 .Net 6 中处理 Win32 WndProc 消息?

[英]How to handle Win32 WndProc messages in .Net 6?

I'm using .Net 6 and the PInvoke nuget package to access the Win32 API and I'm creating a Win32 window in the following way:我正在使用 .Net 6 和PInvoke nuget 包来访问 Win32 API,并通过以下方式创建 Win32 窗口:

  IntPtr windowHandle = User32.CreateWindowEx(User32.WindowStylesEx.WS_EX_TOOLWINDOW,
                               "static",
                               "Window Title",
                               User32.WindowStyles.WS_OVERLAPPEDWINDOW |
                               User32.WindowStyles.WS_VISIBLE,
                               0,
                               0,
                               800,
                               800,
                               IntPtr.Zero,
                               IntPtr.Zero,
                               IntPtr.Zero,
                               IntPtr.Zero);

When the window becomes visible on screen I have the same situation as this guy The window renders fine, but is unresponsive to the user.当窗口在屏幕上可见时,我的情况与此人相同。窗口呈现正常,但对用户无响应。 When I mouse-over the window, the mouse pointer becomes the loading circle.当我将鼠标悬停在窗口上时,鼠标指针变为加载圆圈。

I believe the unresponsivness is due to window events and messages not being handled.我相信不响应是由于没有处理窗口事件和消息。 I would like to somehow override or hook into the WndProc method of the Win32 window to handle messages, as apparently the User32.GetMessage() does not return all messages.我想以某种方式覆盖或挂钩 Win32 窗口的 WndProc 方法来处理消息,因为显然User32.GetMessage() 不会返回所有消息。

In WPF you can add a hook to the HwndHost to handle the WndProc messages.在 WPF 中,您可以向 HwndHost 添加一个挂钩来处理 WndProc 消息。 How do I get the WndProc messages in .Net 6 without using WPF?如何在不使用 WPF 的情况下在 .Net 6 中获取 WndProc 消息?


TL;DR: essentially the unresponsiveness is due to your code not processing the Windows Message Pump for the offending window. TL;DR:基本上无响应是由于您的代码没有为有问题的窗口处理Windows 消息泵


As mentioned in your line "You need to get the messages for the window and dispatch them accordingly" .正如您在“您需要获取窗口的消息并相应地调度它们”行中所述 ie GetMessage , TranslateMessage , DispatchMessage , all inside a while loop otherwise known as The Message Loop .GetMessageTranslateMessageDispatchMessage ,都在一个while循环中,也称为消息循环

I would like to somehow override or hook into the WndProc method of the Win32 window to handle messages, as apparently...我想以某种方式覆盖或挂钩Win32 窗口的 WndProc 方法来处理消息,显然......

That's not how it works.这不是它的工作原理。 If you create a window in your process then the onus is on you to provide and act on The Message Loop.如果在流程中创建了一个窗口,那么有责任提供消息循环并对其采取行动。 Otherwise you will experience exactly what you are seeing now - a frozen window.否则你将体验到你现在所看到的——一个冻结的窗口。 "Hook" is not the correct term here. “钩子”在这里不是正确的术语。

eg例如

User32.MSG msg;
while (User32.GetMessage(msg, hWnd, null, null) > 0)
{
    User32.TranslateMessage(msg);
    User32.DispatchMessage(msg);
}

I suspect your app is a console app which by default does not contain a Windows Message Pump.我怀疑您的应用程序是默认情况下不包含 Windows 消息泵的控制台应用程序 That's one reason why you shouldn't use the Console App project wizard to create something that will expose a GUI.这就是为什么您不应该使用控制台应用程序项目向导来创建将公开 GUI 的东西的原因之一。 Whilst it is possible to make a console app display a GUI, it's generally easier to pick a project wizard tailored for GUIs in the first place.虽然可以使控制台应用程序显示 GUI,但首先选择为 GUI 量身定制的项目向导通常更容易。 [%] [%]

In WPF you can add a hook to the HwndHost to handle the WndProc messages...在 WPF 中,您可以向 HwndHost 添加一个挂钩来处理 WndProc 消息...

Don't forget, WPF uses Direct3D as a render surface and apart from the application window, there are no child WIN32 windows to speak of .别忘了,WPF 使用 Direct3D 作为渲染表面,除了应用程序窗口之外,没有子 WIN32 窗口可言 This is easily shown by pointing tools like Spy++ at a WPF app.这很容易通过将Spy++等工具指向 WPF 应用程序来显示。 When Microsoft designed WPF they needed a way for Microsoft UI Automation to interact with child elements.当 Microsoft 设计 WPF 时,他们需要一种让Microsoft UI 自动化与子元素交互的方法。 It does so without having to worry about child windows.它这样做而不必担心子窗口。

% Footnote % 脚注

Speaking of squeezing GUIs into something that at first glance today might look like a console app, this was kind of how things were done in Windows apps written in C prior to C++ .说到将 GUI 压缩成今天乍一看可能看起来像控制台应用程序的东西,这就是在C C++之前用 C 编写的 Windows 应用程序中的操作方式。 C apps, could spin up and serve a window all in a single main() entry point, however no console window as such appeared so the console comparison isn't quite true. C 应用程序可以在单个main()入口点中启动并提供一个窗口,但是没有出现这样的控制台窗口,因此控制台比较并不完全正确。

C apps didn't have alot of guidance. C 应用程序没有太多的指导。 Some might not have had a resource table for things like icons, keyboard accelerators, string tables but they were GUI apps nonetheless.有些人可能没有用于图标、键盘加速器、字符串表之类的资源表,但它们仍然是 GUI 应用程序。

Microsoft Visual C++ changed things with MFC (then again years later with ATL, WTL) distinct GUI project types and encapsulated much from the developer particularly The Message Pump code in addition to providing default icons, keyboard accelerators, string tables. Microsoft Visual C++用 MFC(几年后又用 ATL、WTL)改变了不同的 GUI 项目类型,并封装了来自开发人员的很多东西,特别是消息泵代码,此外还提供了默认图标、键盘加速器、字符串表。

So making a C# GUI app using a console project wizard is akin to a bare-bones C GUI app.因此,使用控制台项目向导制作 C# GUI 应用程序类似于简单的 C GUI 应用程序。

Therefore you need your message pump.因此,您需要您的消息泵。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM