我有一个Object (即不是一种forms),想要侦听来自Windows的广播消息,例如:
WM_SETTINGCHANGE
WM_DWMCOLORIZATIONCOLORCHANGED
WM_DWMCOMPOSITIONCHANGED
WM_THEMECHANGED
WM_POWERbroADCAST
.NET中的机制是什么设置非WinForm的窗口,可以监听广播消息?
即有一个WindowsListener类?
奖金喋喋不休
在过去的其他开发环境中,框架提供了一个AllocateHwnd函数:
Microsoft.CSharp库中的BadImageFormatexception
有没有办法检测到“几乎”远程桌面断开连接(即短暂的高延迟时间)?
以编程方式打印文档
什么会导致进程停止重新创build?
HWND listener = AllocateHWnd(ListenerWindowProc);
ListenerWindowProc是我的窗口过程方法:
private void ListenerWindowProc(ref Message msg) { switch (msg.msg) { case WM_SETTINGCHANGE: { ... } break; case WM_POWERbroADCAST: { ... } break; case WM_THEMECHANGED: { ... } break; ... } DefWindowProc(msg); }
秘密酱是AllocateHwndfunction:
伪代码:
public static HWND AllocateHWnd(WndMethod method) { HWND result; WNDCLASS tempClass; Boolean classRegistered; UtilWindowClass.hInstance := HInstance; Boolean classRegistered = GetClassInfo(HInstance,UtilWindowClass.lpszClassName,tempClass); if (!classRegistered || (tempClass.lpfnWndProc != @DefWindowProc) { if classRegistered { UnregisterClass(utilWindowClass.lpszClassName,HInstance); RegisterClass(utilWindowClass); } result = CreateWindowEx(WS_EX_TOOLWINDOW,'',WS_POPUP,HInstance,null); if (!Method != null) SetwindowLong(result,GWL_WNDPROC,UInt32(MakeObjectInstance(Method))); } }
有了更多与UtilWindowClass相关的UtilWindowClass 。
而当你完成你会DeallocateHwnd :
DeallocateHwnd(listenerWindow);
我知道在.NET框架深处,他们将要响应WM_SETTINGCHANGE并更新内部的.NET数据结构。 我会偷代码,但reflection器找不到WM_SETTINGCHANGE引用; 大概是因为反编译的代码不显示常量名称 ,只是常量0x001A 。
更新 :
注意 :这个对象应该是独立的。 任何使用该类的人都不应该修改他们的应用程序,以便我的类能够返回正确的数据。 它应该监听来自Windows本身的广播,而不需要开发人员修改他们的应用程序来为我监听某些消息(即不应该破坏困难或复杂操作的封装)
例如:
public class FrobbingGrobber: Idisposable { private IntPtr hwnd = IntPtr.Zero; public FrobbingGrobber { _hwnd = AllocateHwnd(listenerWindowProc); } protected virtual void listenerWindowProc(ref Message msg) { switch (msg.msg) { case WM_DwmColorizationColorChanged,WM_DwmCompositionChanged: { UpdateColorizationColor(); } break; } DefWindowProc(msg); } public void UpdateColorizationColor() { NativeMethods.DwmGetColorizationColorParameters_UndocumentedExport137(ref _color); } public void dispose() { dispose(true); } protected void dispose(Boolean safetodisposeManagedobjects) { if (_hwnd != 0) { DeallocateHwnd(_hwnd); _hwnd = 0; } if (safetodisposeManagedobjects) GC.SuppressFinalize(this); } public ~FrobbingGrobber { //If the user forgot to call dispose i Could (correctly) leak a handle,//or i Could fix their mistake for them dispose(false); }
使内存密集的后台应用程序“友好”
在Linux / Ubuntu上大规模部署.net单声道应用程序
在Windows Server 2012上运行.NET 4.0上的服务构build时发生System.Configuration.ConfigurationException
.NET – 从代码中设置电源选项
我假设你给的例子只是这个例子。 因为有一些已经管理的等价物已经包装了所有这些给你。 像WM_POWERbroADCAST由Microsoft.Win32.SystemEvents.PowerModeChanged事件包装。 而WM_SETTINGCHANGED等同于Microsoft.Win32.SystemEvents.UserPreferenceChanged 。
无论如何,像你所描述的广播消息被发送到所有的顶级窗口,所以你真正需要做的是创建一个顶级窗口,并重写它的WndProc方法来处理你感兴趣的通知消息。
使用NativeWindow类可以NativeWindow您自己的工作。 在这种情况下,你不需要Form类提供的所有东西,所有你需要的东西是包装CreateWindowEx并提供一个窗口过程。 只需创建没有WS_VISIBLE标志的窗口,因为您不希望它出现在屏幕上。
.NET Framework在内部完成这个任务。 例如,用于System.Windows.Forms.Timer的内部TimerNativeWindow类。 如果您想在Reflector中查看自己的实现,请开始查看。 你应该能够搜索常量,但深入到你知道必须有这样一个内部处理的通知消息的类层次结构通常是一个更聪明的方式来搜索。 SystemEvents类(上面讨论过的)也是开始寻找实现策略的好地方。
请注意,您不能在此处使用仅消息窗口( HWND_MESSAGE ),因为它们不会收到广播事件 。 我上面提到的TimerNativeWindow 确实这样做,因为它不关心广播事件,所以不要只复制和粘贴代码!
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 [email protected] 举报,一经查实,本站将立刻删除。