主程序中调用DLL的接口函数,DLL来调用硬件设备,设备提供有SDK,但是设备消息的回复是通过WINDOWS MESSAGE来实现响应的,所以用一个窗体的句柄来接收消息,访照他的例子,我也用一个窗体来接收消息(只创建,不显示),这个在单线程中是没有问题的,但是多线程就不行了,问了别人,说这样FORM无法收到消息,需要从消息队列里取,使用PeekMessage,从网上查了下用法BOOL PeekMessage(LPMSG IpMsg,HWND hWnd,UINT wMSGfilterMin,UINT wMsgFilterMax,UINT wRemoveMsg)
第二个参数hWnd如何设置,这个是DLL的句柄吗?是不是需要主程序传一个句柄过来?

解决方案 »

  1.   

    hWnd:其消息被检查的窗口的句柄。
    PeekMesssge只得到那些与参数hWnd标识的窗口相联系的消息或被lsChild确定为其子窗口相联系的消息,并且该消息要在由参数wMsgFiterMin和wMsgFiherMax确定的范围内。如果hWnd为NULL,则PeekMessage接收属于当前调用线程的窗口的消息(PeekMessage不接收属于其他线程的窗口的消息)。
      

  2.   

    就是不明白这个参数如何设置才提问,版猪,我这里是不是要设置为NULL?
      

  3.   

    消息队列中有很多消息,hWnd参数就是标记着这些消息要发往何处;
    PeekMessage若指定了hWnd,那么就是只取出发往hWnd的消息; 好像为0时,就取全部了比如消息队列中可能有上千条,但你只想要发往窗口A的消息,那么你就要事先知道窗口A的handle就行了
    也可以利用wMsgFilterMin+wMsgFilterMax这2个参数,这是一个范围,可以过滤掉范围外消息
      

  4.   

    比如在线程的Execute()里:
      while true do
      begin
        if PeekMessage(Msg,0,0,0,PM_REMOVE) then
        begin
          if Msg.message = WM_QUITTHREAD then  //WM_QUITTHREAD 自定义退出线程消息
          begin
            FQuitEvent.SetEvent;
            Break;
          end;
        end;
      ....
      ....
      end;还有,向线程传送消息,不一定非得在线程里创建一个FORM吧,可以PostThreadMessage(),只要知道线程的ID
      

  5.   

    哦, 对了, 顺便提醒你一下, 只有你创建的那个窗体的线程才可以"操作"(Peek Get)对方发来的消息, 其他的线程不可以这么访问, 如果你需要多线程操作, 那就必须通过变通的方式, 看你的应用场景吧
      

  6.   

    在线程中实现自己的WndProc,然后给线程分配个句柄 AllocateHWND(WndProc), 这样不就可以处理消息了么
      

  7.   

    看API的用法,就看最权威的MSDN嘛!
      

  8.   

    还是得有消息循环,like this:
        while( (bRet = GetMessage( &msg, NULL, 0, 0 )) != 0)
        { 
            if (bRet == -1)
            {
                // handle the error and possibly exit
            }
            else
            {
                TranslateMessage(&msg); 
                DispatchMessage(&msg); 
            }
        } 
      

  9.   

    我说的是用SendMessage而非PostThreadMessage,不需消息循环
      

  10.   


    很遗憾你没有真正理解SendMessage和PostMessage这2个函数的概念, 他们2个都是需要消息循环的, SendMessage 当调用者就是本窗口消息队列的创建线程则直接调用窗口处理过程, 如果调用者不在窗口消息队列创建线程里调用的, 则需要窗口消息队列创建的那个线程调用PeekMessage或者GetMessage否则 你可以试试SendMessage将会持续阻塞, 否则SendMessage又何谈线程安全?
      

  11.   


    很遗憾你没有真正理解SendMessage和PostMessage这2个函数的概念, 他们2个都是需要消息循环的, SendMessage 当调用者就是本窗口消息队列的创建线程则直接调用窗口处理过程, 如果调用者不在窗口消息队列创建线程里调用的, 则需要窗口消息队列创建的那个线程调用PeekMessage或者GetMessage否则 你可以试试SendMessage将会持续阻塞, 否则SendMessage又何谈线程安全?
      

  12.   

    没有窗体了,只能从这个DLL的消息队列里取,所以就牵扯到这个参数应该如何写的问题,谢谢
      

  13.   


    好心被当成驴肝肺, 我是说他说的不正确而已, 不希望产生误导, 你的问题我开始也回答你了, 一个线程只有窗口队列, 别的线程不可以直接Peek, MSDN说的很清楚了, Peek的第2个参数是你要指定取哪个窗体的消息, 比如你在该线程里创建了3个窗体, 分别对应的句柄是ha hb hc, 那么第2个参数可以指定你只取某一个窗体的消息,相当一个过滤器, 当这个参数为0的时候, 就无视任何条件, 只要是消息就取出来, 其实按照你的说法你要实现的目前你自己都已经实现好了, 多线程在这个环境下不是这么用的, 不能用别的线程来取其他线程中的消息.
      

  14.   

    服务也是可以的啊, 我怎么说你才肯试一下呢, 首先你的服务里当前线程如果不调用PeekMessage或者GetMessage, 那么系统是不会给这个线程建立消息队列的, 这么说你能理解吗, 之所以你收不到消息, 你看一下你的代码, 是不是这个原因, 你现在不贴代码, 我只能猜测你的代码里是没有消息循环的, 没有消息循环, 就谈不上系统的消息机制了, 人家的dll用的是windows的消息队列, 那么显然你必须在你的服务里建立起来这样的机制.