如题,DLL向主程序中一个自定义对象发送消息,这个怎么弄?

解决方案 »

  1.   

    一样的吧,先要取得对象句柄,然后sentmessage?
      

  2.   

    方法1:在主程序中调用DLL中的函数时把句柄传给DLL;
    方法2:在DLL中用FindWindow找到主程序的窗口;
    方法3:用进程间数据共享的方法,把主程序的句柄放到共享。
      

  3.   

    需要接受消息的对象是一个自定义的对象(特地让它继承自TForm,其实跟From没什么关系),我搞不清楚这样的对象的句柄是什么东西?或者说是不是只有窗体才有句柄呢?
    我的想法是使用 在应用程序间发送消息的方法,
    即:
    1.在DLL和主程序中同时定义一个消息常量,用到函数RegesterWindowMessage('AMsg');
    2.在主程序中覆盖对象的WndProc()方法处理自定义的消息(AMsg)
    3.在DLL中用BrodcastSystemMessage()函数发送消息
    可是实际效果是:被覆盖的WndProc()方法根本截获不到DLL中发送的消息.
    请高手赐教,分不够可在加.
      

  4.   

    我正写的一个程序中正好有这方面的东西,不过我用的是内存映射
    主程序的部份代码  
      private
        { Private declarations }
      public
        { Public declarations }
         procedure getShareInfo(var Msg: TMessage); message WM_DATA; {处理WM_DATA}
      end;procedure TForm1.getShareInfo(var Msg: TMessage); {处理WM_DATA}
    begin
      if msg.LParam=1 then begin{是我们设定的消息参数}
         //这里进行读取映射文件的操作,同时把读取的东西赋给你所要的对象.
      end;
    end;DLL部份
    //先把需的数据写入内存映射文件
    PostMessage(FindWindow(nil, '主窗口标题'), WM_DATA, 1, 1);//通知主程序有数据注意的是:DLL和主程序中的WM_DATA值要一致,这个值可以自己定义,如const WM_DATA=WM_USER + 100等等写入和读取内存映射文件代码就很长了,楼主可以参考相关资料.总的思路是:通过发送消息给程序主程序,告诉主程序数据写到了内存映象文件.然后主程序读取内存映象文件中的数据,赋给相应的对象.
       
      

  5.   

    应该用DLL回调EXE的函数,建议不要用消息。
      

  6.   

    谢谢楼上的.尤其是oyshgame讲的很详细.
    关于内存映射我也用过,不够由于当初设计不好,这里用起来比较困难.
    我昨天晚上想了一种方法,就是在再主程序的一个自定义类中定义一个过程(比如HandleAppMsg)来处理Application的OnMessage事件.
    通过同时在DLL和主程序中用RegisterWindowMessage('AMsg')注册消息,
    然后在DLL中BroadcastSystemmessage,这样主程序中能接收到消息,并且处理了.
    但是在HandleAppMsg中对一个全局变量赋值却不行(即,在处理Application的OnMessage事件的过程中,
    不能将通过消息传递过来的值赋给一个全局变量).现在问题是:
     一个类中用于处理消息的过程和普通过程有什么区别么? 是不是在 消息处理过程中给全局变量赋值注定不会成功?
      

  7.   

    我觉得你可以在主程序里做个对象池,对象句柄和对象名一一对应,
    DLL里可以直接发送消息给住程序,把对象名也带过去,
    主程序接到消息后,根据名称再转发给具体的对象。
      

  8.   

    不管是用消息还是回调.你首先要理好思路.别一开始就想把所有的都做好.首先要最简单的能调成功先.
    开始不要用什么RegisterWindowMessage,BroadcastSystemmessage.
    你先别管消息是否会和其他人写的重复先,定义一个你自己绝对不大会重复的.
    WM_MyMsg =WM_User +1999;这样之类的.先按3楼第一个办法,调用dll时把handle传入.
    (当然对应的handle的窗体要有消息响应函数,或者能在wndproc里截获),然后用sendmessage来发消息.
    我想不成功的话估计是你自己哪个步骤错了.
    如果用回调的话可以简单点,直接用个init函数,把回调函数地址初始化到dll的变量里.然后调用
      

  9.   

    我把问题说的具体点:
    我在DLL中做了一个登录窗体,用户登录成功后,需要返回用户名和用户ID到主程序中,然后登录窗体关闭,释放这个DLL.
    因为在DLL中的登录窗体关闭后主窗体才显示出来,所以如果在DLL中发消息,没有办法得到主程序的窗口句柄,所有只能用
    BroadcastSystemmessage广播消息了.
    这样就出现了我在9楼中所说的问题,即:在消息处理过程中无法赋值给全局变量.
    关于回调函数,因为没有具体使用过,不知道该怎么用,高手能给个思路么?
    继续求教,谢谢!
      

  10.   

    主程序还在为何无法赋值dll传的数据?跟主窗体有没显示有什么关系?
      

  11.   

    因为主程序是在,但是主窗体还没有创建.当登录成功后,登录窗体关闭,卸载显示登录窗体的DLL,然后再创建DLL.
    我所建立的自定义对象就是为了处理 先掉了登录DLL,显示登录窗体,登录成功后,再创建主窗体.
      

  12.   

    楼主并未把程序的真正意图表达出来,所以按照楼主所表达的,只能说思路有问题,如果你想让主程序响应DLL,那么用回调函数、接口等技术都能实现,没必要为对象有无句柄而伤脑筋。
      

  13.   

    发消息不分DLL或你的主EXE,都是一样的。你的表述不清。你是想发消息传值过去?还是只发消息让主程序响应一下?
      

  14.   

    我是想发消息传个值过去.但是如果在主程序中自定义一个消息如:WM_MYMSG = WM_USER + 1000 然后再定义一个消息处理过程
    (是自定义对象的一个方法);
    再在DLL中定义同样的消息 :WM_MYMSG = WM_USER + 1000  ,然后在DLL中发消息给主EXE(广播消息),
    为什么主程序中不能调用消息处理过程呢?
      

  15.   

    我理解的不知道对不对。你的意思就是你的登陆窗体是在DLL中写的,在程序运行的时候先调用DLL,然后在DLL中通过用户认证后返回用户名和用户ID到主程序中,然后才创建主窗体。如果是这样的话,用回调函数应该是最简单的吧
      

  16.   


    其实我是想发两个值过去,及时DLL登录窗口中登录成功后保存的用户名(字符串)和用户ID(integer),
    无奈不知道怎么通过消息传字符串
      

  17.   


    原来是是这样啊,那也简单,在DLL中定义变量,把变量地址用消息传递给主程序,记着主程序及时保存这个变量数据就行了,也没必要再映射文件什么的。
      

  18.   

    要用消息处理啊,那就是实现DLL想应用程序传递消息咯!DLL中用SendMessage()函数向   应用程序发送消息,有四个参数:   
      1.应用程序的窗口句柄,可以在应用程序调用dll时通过函数传给dll   
      2.消息ID,需要在dll和调用dll的程序中做相同的定义,比如   vc中   #define   WM_MESSAGE1   WM_USER+100,delphi中   const   WM_MESSAGE1=   WM_USER+100   
      3.4分别为wparam,lparam,将发送的消息放到这两个变量里,比如dll向应用程序发送50,就可以指定第三个参数为50   
      应用程序想接收这个消息,就必须先定义消息const   WM_MESSAGE1=   WM_USER+100,然后定义消息结构,比如:   
      type   
      TmyMessage   =   record   
        MSGID:   Cardinal;   
        wParam:   WPARAM;   
        lParam:   LPARAM;   
      end;   
      然后还要定义相应的消息处理过程,如下:   
      procedure   ProcessMessage(var   message:TmyMessage);message   WM_MESSAGE1;   
      这样在这个过程中就可以接收消息了
      

  19.   

    看一下TTimer的实现代码,看一下它是如何接收时间消息的.
      

  20.   

    你目的也是为了得到登陆dll中的用户名密码吧?直接传给主程序不行吗?跟主窗体显不显示,存不存在没关系啊
      

  21.   

    C++跟Delphi互相调用
    //---------------------------------------------
    //C++调用Delphi接口,由Delphi实例化 
    class ID2C { 
      public: 
        virtual int respone(int i) = 0; 
    }; //Delphi调用C++接口,由C++实例化 
    class IC2D { 
      public: 
        virtual int max(int a, int b) = 0; 
        virtual void SetID2C(ID2C *d2c) = 0; //将Delphi实例化的指针传入 
    }; //C++实例化 
    class CC2D { 
      public: 
        virtual void SetID2C(ID2C *d2c) { 
          m_d2c = d2c; 
        } 
        virtual int max(int a, int b) { 
          //这里调用delphi的代码 
          if (m_d2c != NULL) { 
            m_d2c->respone(); 
          } 
          if (a >= b) return a; 
          else return b; 
        } 
      private: 
        ID2C *m_d2c; 
    }; //导出dll实例的指针 
    library Test 
    Exports CreateIC2D; IC2D* CreateIC2D() { 
      IC2D *c2d = new CC2D; 
      return c2d; 

    type 
    //C++调用Delphi接口,由Delphi实例化 
    ID2C = class 
    public 
      function respone(i: integer): integer;virtual;stdcall;abstract; 
    end; //Delphi实例化 
    TD2C = class(ID2C) 
    public 
      function respone(i: integer): integer;override; 
    end; //Delphi调用C++接口,由C++实例化 
    IC2D = class 
    public: 
      function max(a, b: integer): integer;virtual;stdcall;abstract; 
      procedure SetID2C(d2c: ID2C);virtual;stdcall;abstract; 
    end; //Delphi响应C++的处理 
    function TD2C.respone(i: integer): integer; 
    begin 
      result: = i*2; 
    end; //在Delphi里调用过程------------------------ 
    var 
      c2d: IC2D; 
      d2c: ID2C; 
    begin 
      //调用dll暴露出的C++得到接口 
      c2d: = CreateIC2D; 
      //delphi实例化接口,并将指针传给c2d 
      d2c:=TD2C.create(); 
      c2d.SetID2C(d2c);   //那么此时,调用max的过程中,回调了respone,而这段代码是由delphi写的,作为对底层的响应 
      c2d.max(2, 3); 
    end;
      

  22.   

    你的要求
    无非是UI跑dll;但dll跑时,也想要UI响应
      

  23.   


    我们一般不是都在窗体类中处理自定义消息的吗?像这样:type
      TForm1 = class(TForm)
      private
        procedure getAA(var msg:TMessage);message WM_MYMSG;
      public
        { Public declarations }
      end;
    如果 该程序 只有一个 窗体(即主窗体),那如何在 窗体创建前 处理自定义消息?
    我试过把'procedure getAA(var msg:TMessage);message WM_MYMSG;'拿出来,做全局函数,是报错的。要是这个程序里不止1个窗体,倒是可以先创建另一个,处理消息后,再看是否要创建 主窗体。
    这个要关注下,学习学习