加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 综合聚焦 > 服务器 > Windows > 正文

如何在.NET中监听Windows广播消息?

发布时间:2020-12-14 02:00:45 所属栏目:Windows 来源:网络整理
导读:我有一个想要从 Windows收听广播消息的对象(即非形式),例如: WM_SETTINGCHANGE WM_DWMCOLORIZATIONCOLORCHANGED WM_DWMCOMPOSITIONCHANGED WM_THEMECHANGED WM_POWERBROADCAST .NET中设置非WinForm窗口的机制是什么,可以监听广播消息? 即是否有WindowsList
我有一个想要从 Windows收听广播消息的对象(即非形式),例如:

> WM_SETTINGCHANGE
> WM_DWMCOLORIZATIONCOLORCHANGED
> WM_DWMCOMPOSITIONCHANGED
> WM_THEMECHANGED
> WM_POWERBROADCAST

.NET中设置非WinForm窗口的机制是什么,可以监听广播消息?

即是否有WindowsListener类?

奖金Chatter

在过去,在其他开发环境中,框架提供了AllocateHwnd功能:

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);
}

秘诀是AllocateHwnd功能:

伪代码:

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相关的更多密码.

当你完成后,你会DeallocateHwnd:

DeallocateHwnd(listenerWindow);

我知道在.NET框架深处,他们将响应WM_SETTINGCHANGE并更新内部.NET数据结构.我会窃取该代码,但Reflector找不到对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);
    }

解决方法

我假设您给出的示例仅仅是:示例.因为其中许多已经管理了等价物,已经为您包装了所有这些.就像WM_POWERBROADCAST由 Microsoft.Win32.SystemEvents.PowerModeChanged event包装一样.WM_SETTINGCHANGED相当于 Microsoft.Win32.SystemEvents.UserPreferenceChanged.

无论如何,像你描述的广播消息被发送到所有顶级窗口,所以你真正需要做的就是创建一个顶级窗口并覆盖其WndProc方法来处理你感兴趣的通知消息.

使用NativeWindow class让自己轻松自如.在这种情况下,您不需要Form类提供的所有内容,您只需要包装CreateWindowEx并提供窗口过程.只需创建没有WS_VISIBLE标志的窗口,因为您不希望它出现在屏幕上.

.NET Framework在内部完成所有这些工作.例如,用于System.Windows.Forms.Timer的内部TimerNativeWindow类.如果您想在Reflector中查看自己的实现,请从那里开始查看.您应该能够搜索常量,但深入到类的层次结构中,您知道必须在内部处理这样的通知消息,这通常是一种更智能的搜索方式. SystemEvents类(如上所述)也是开始寻找实现策略的好地方.

请注意,你不能在这里使用仅消息窗口(HWND_MESSAGE),因为they won’t receive broadcast events.我上面提到的TimerNativeWindow确实这样做,因为它不关心广播事件,所以不要只复制和粘贴代码从那里!

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读