是这样的,我想要实时监视程序的窗体创建,所以添加了一个消息筛选器。通过查MSDN知道窗体创建的消息号为0x0001。接口的实现     public bool PreFilterMessage(ref Message m)
      {
            if (m.Msg != 0x0001)
                return false;
            Form form = Control.FromChildHandle(m.HWnd) as Form;
           return false;
        }可问题来了,我发现好像0x0001是不对的。通过    public bool PreFilterMessage(ref Message m)
        {
            Form form = Control.FromChildHandle(m.HWnd) as Form;
            if (form != null)
                Console.WriteLine(m.Msg);
            return false;
        }调试后发现创建窗体的消息号不但不是0x0001,而且在每次系统重启后数字都是不同的。

解决方案 »

  1.   

    某些消息,例如:WM_CLOSE、WM_CREATE 
    PreFilterMessage方法不能拦截的,原因是窗体自身处理后就不在传递了用如下方法,在弹出的窗口中可以拦截创建消息
    protected override void WndProc(ref Message m)
            {
                if (m.Msg == WM_CREATE)            else
                    base.WndProc(ref m);
            }
      

  2.   

    消息能够被分为「队列化的」和「非队列化的」。队列化的消息是由Windows放入程序消息队列中的。在程序的消息循环中,重新传回并分配给窗口消息处理 程序。非队列化的消息在Windows呼叫窗口时直接送给窗口消息处理程序。也就是说,队列化的消息被「发送」给消息队列,而非队列化的消息则「发送」给 窗口消息处理程序。任何情况下,窗口消息处理程序都将获得窗口所有的消息--包括队列化的和非队列化的。窗口消息处理程序是窗口的「消息中心」。 队列化消息基本上是使用者输入的结果,以击键(如WM_KEYDOWN和WM_KEYUP消息)、击键产生的字符(WM_CHAR)、鼠标移动 (WM_MOUSEMOVE)和鼠标按钮(WM_LBUTTONDOWN)的形式给出。队列化消息还包含时钟消息(WM_TIMER)、更新消息 (WM_PAINT)和退出消息(WM_QUIT)。 非队列化消息则是其它消息。在许多情况下,非队列化消息来自呼叫特定的Windows函数。例如,当WinMain呼叫CreateWindow 时,Windows将建立窗口并在处理中给窗口消息处理程序发送一个WM_CREATE消息。当WinMain呼叫ShowWindow 时,Windows将给窗口消息处理程序发送WM_SIZE和WM_SHOWWINDOW消息。当WinMain呼叫UpdateWindow 时,Windows将给窗口消息处理程序发送WM_PAINT消息。键盘或鼠标输入时发出的队列化消息信号,也能在非队列化消息中出现。例如,用键盘或鼠 标选择了一个菜单项时,键盘或鼠标消息就是队列化的,而说明菜单项已选中的WM_COMMAND消息则可能就是非队列化的我抄袭一段文章,来说明PreFilterMessage为什么无法获取WM_CREATE和WM_CLOSE等消息的原因
      

  3.   


    public bool PreFilterMessage(ref Message m)
            {
                if (m.Msg == WM_CREATE)
                {
                    return true;
                }
                else
                    return false;
            }        protected override void WndProc(ref Message m)
            {
                if (m.Msg == WM_CREATE)
                    // 调用该方法可以传递消息到程序的筛选器,并返回修改后的消息
                    Application.FilterMessage(ref m);
                else
                    base.WndProc(ref m);
            }
      

  4.   

    但是我这个过滤器是注册在整个程序的  Application.AddMessageFilter(),按理说应该是处理整个程序的消息。
      

  5.   

    还有我尝试用窗体焦点消息号就可以正常
    public bool PreFilterMessage(ref Message m)
      {
      if (m.Msg != 0xF)
      return false;
      Form form = Control.FromChildHandle(m.HWnd) as Form;
      return false;
      }
      

  6.   

    关键看你的参数Message 是什么用钩子钩到的消息么?还是窗体内部的消息?只看你那个方法看不出什么吧意思就是说,你这个方法在这里能用,其他地方就不能用了都不是通用的监听解决方案那还不如你在窗体OnCreate或者OnLoad的时候做委托,监听,还便于调试呢
      

  7.   


    你仔细看看我四楼写的文字,PreFilterMessage只能拦截应用程序消息队列中的消息,
    而WM_CREATE,WM_CLOSE消息不会被发送到消息队列中,而是直接发送到该窗口的回调函数WndProc()中直接处理了。明白了吗?
      

  8.   

    嗯 测试了下 果然是这样
    protected override void WndProc(ref Message m)
            {
                if (m.Msg == 0x0001)
                {            }
                base.WndProc(ref m);
            }
    可以接收到创建消息。
    不过这样就只能自己写个基类窗体,然后让其他窗体继承才能实现我要的效果了,就没其他的办法吗? 还有你4楼那段是从哪本书看的啊,我怎么找不到这种资料。
      

  9.   

    这个方法,可以将创建消息引入你的消息筛选接口中,我抄的那段文字是从网上拷贝的,
    究竟是那本书中的我也不知道了,去看一下windows sdk和MFC,会讲述这些知识的
    public bool PreFilterMessage(ref Message m)
            {
                if (m.Msg == WM_CREATE)
                {
                    return true;
                }
                else
                    return false;
            }        protected override void WndProc(ref Message m)
            {
                if (m.Msg == WM_CREATE)
                    // 调用该方法可以传递消息到程序的筛选器,并返回修改后的消息
                    Application.FilterMessage(ref m);
                else
                    base.WndProc(ref m);
            }