【问题标题】:How do I create a message-only window from windows forms?如何从 Windows 窗体创建仅消息窗口?
【发布时间】:2010-10-30 10:53:29
【问题描述】:

我正在尝试在 winforms 应用程序中创建一个仅消息窗口以接收来自 MFC 库类的窗口消息。

我尝试子类化NativeWindow,并在构造函数中请求这样的窗口句柄:

CreateParams cp = new CreateParams();
cp.Parent = (IntPtr)HWND_MESSAGE;
this.CreateHandle(cp);

但是我得到一个 Win32Exception 抛出的消息“创建窗口句柄时出错”。如何从 Windows 窗体创建仅消息窗口?使用NativeWindow 是正确的方法吗?

【问题讨论】:

  • 所有给出的答案都对我不起作用——最后我不得不使用 C++/CLI 并深入研究 Windows API。我会发布我使用的代码,但它属于前雇主。

标签: c# .net window-handles


【解决方案1】:

我相信您还需要指定一个窗口类。

【讨论】:

  • 我应该把它设置成什么?我已经尝试过“消息”和班级名称,但都没有奏效。 “消息”给了我同样的错误,类名给了我“窗口类名无效”。
【解决方案2】:

试试看:

[DllImport("user32.dll")]
static extern IntPtr SetParent(IntPtr hWndChild, IntPtr hWndNewParent);

static IntPtr HWND_MESSAGE = new IntPtr(-3);

protected override void OnHandleCreated(EventArgs e)
{
    base.OnHandleCreated(e);
    SetParent(this.Handle, HWND_MESSAGE);
}

【讨论】:

  • 注意:您必须设置 ShowInTaskbar = false。注意:如果您想从另一个进程发送消息,则仅消息窗口是无用的,因为尽管 MSDN 说应该使用 FindWindowEx 找到仅消息窗口,但事实并非如此。
  • @Elmue,如果你想接收广播消息,它仍然很有用
  • 您应该阅读 MSDN:仅消息窗口使您能够发送和接收消息。不可见,没有z-order,不能枚举,不接收广播消息。
【解决方案3】:

我担心您必须从Form 派生,并强制窗口不可见。

另一种方法(如果类库是可修改的)是在没有窗口的情况下运行消息泵(请参阅Application.RunApplication.AddMessageFilter,或者如果您更喜欢使用PeekMessage & Co 的pinvokes)。

在这种情况下,您可以使用PostThreadMessage 发送消息,方法是让线程 id 运行 Application.Run,​​但实际上您无法与应用程序消息泵线程同步,因为它不等待消息确认。

【讨论】:

    【解决方案4】:

    我知道这是 7.5 岁,但以防万一有人发现这个,我想我会回应。我使用了微软的TimerNativeWindow code 并删除了计时器功能。我最终使用了这种方法:

        public class MyNativeWindow : NativeWindow
        {
            private readonly string _caption;
            private const int WmClose = 0x0010;
    
            [SuppressMessage("Microsoft.Reliability", "CA2006:UseSafeHandleToEncapsulateNativeResources")]
            private static readonly HandleRef HwndMessage = new HandleRef(null, new IntPtr(-3));
    
            [DllImport("user32.dll", CharSet = CharSet.Auto)]
            [ResourceExposure(ResourceScope.None)]
            private static extern IntPtr PostMessage(HandleRef hwnd, int msg, int wparam, int lparam);
    
            [DllImport("user32.dll", ExactSpelling = true, CharSet = CharSet.Auto)]
            [ResourceExposure(ResourceScope.Process)]
            private static extern int GetWindowThreadProcessId(HandleRef hWnd, out int lpdwProcessId);
    
            [DllImport("kernel32.dll", ExactSpelling = true, CharSet = CharSet.Auto)]
            [ResourceExposure(ResourceScope.Process)]
            private static extern int GetCurrentThreadId();
    
            public MyNativeWindow(string caption)
            {
                _caption = caption;
            }
    
            public bool CreateWindow()
            {
                if (Handle == IntPtr.Zero)
                {
                    CreateHandle(new CreateParams
                    {
                        Style = 0,
                        ExStyle = 0,
                        ClassStyle = 0,
                        Caption = _caption,
                        Parent = (IntPtr)HwndMessage
                    });
                }
                return Handle != IntPtr.Zero;
            }
    
    
            public void DestroyWindow()
            {
                DestroyWindow(true, IntPtr.Zero);
            }
    
            private bool GetInvokeRequired(IntPtr hWnd)
            {
                if (hWnd == IntPtr.Zero) return false;
                int pid;
                var hwndThread = GetWindowThreadProcessId(new HandleRef(this, hWnd), out pid);
                var currentThread = GetCurrentThreadId();
                return (hwndThread != currentThread);
            }
    
            private void DestroyWindow(bool destroyHwnd, IntPtr hWnd)
            {
                if (hWnd == IntPtr.Zero)
                {
                    hWnd = Handle;
                }
    
                if (GetInvokeRequired(hWnd))
                {
                    PostMessage(new HandleRef(this, hWnd), WmClose, 0, 0);
                    return;
                }
    
                lock (this)
                {
                    if (destroyHwnd)
                    {
                        base.DestroyHandle();
                    }
                }
            }
    
            public override void DestroyHandle()
            {
                DestroyWindow(false, IntPtr.Zero);
                base.DestroyHandle();
            }
        }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-05-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-11-21
      • 1970-01-01
      • 2012-05-31
      • 2012-09-11
      相关资源
      最近更新 更多