DLL向主程序中一个自定义对象发送消息 如题,DLL向主程序中一个自定义对象发送消息,这个怎么弄? 解决方案 » 免费领取超大流量手机卡,每月29元包185G流量+100分钟通话, 中国电信官方发货 一样的吧,先要取得对象句柄,然后sentmessage? 方法1:在主程序中调用DLL中的函数时把句柄传给DLL;方法2:在DLL中用FindWindow找到主程序的窗口;方法3:用进程间数据共享的方法,把主程序的句柄放到共享。 需要接受消息的对象是一个自定义的对象(特地让它继承自TForm,其实跟From没什么关系),我搞不清楚这样的对象的句柄是什么东西?或者说是不是只有窗体才有句柄呢?我的想法是使用 在应用程序间发送消息的方法,即:1.在DLL和主程序中同时定义一个消息常量,用到函数RegesterWindowMessage('AMsg');2.在主程序中覆盖对象的WndProc()方法处理自定义的消息(AMsg)3.在DLL中用BrodcastSystemMessage()函数发送消息可是实际效果是:被覆盖的WndProc()方法根本截获不到DLL中发送的消息.请高手赐教,分不够可在加. 我正写的一个程序中正好有这方面的东西,不过我用的是内存映射主程序的部份代码 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等等写入和读取内存映射文件代码就很长了,楼主可以参考相关资料.总的思路是:通过发送消息给程序主程序,告诉主程序数据写到了内存映象文件.然后主程序读取内存映象文件中的数据,赋给相应的对象. 应该用DLL回调EXE的函数,建议不要用消息。 谢谢楼上的.尤其是oyshgame讲的很详细.关于内存映射我也用过,不够由于当初设计不好,这里用起来比较困难.我昨天晚上想了一种方法,就是在再主程序的一个自定义类中定义一个过程(比如HandleAppMsg)来处理Application的OnMessage事件.通过同时在DLL和主程序中用RegisterWindowMessage('AMsg')注册消息,然后在DLL中BroadcastSystemmessage,这样主程序中能接收到消息,并且处理了.但是在HandleAppMsg中对一个全局变量赋值却不行(即,在处理Application的OnMessage事件的过程中,不能将通过消息传递过来的值赋给一个全局变量).现在问题是: 一个类中用于处理消息的过程和普通过程有什么区别么? 是不是在 消息处理过程中给全局变量赋值注定不会成功? 我觉得你可以在主程序里做个对象池,对象句柄和对象名一一对应,DLL里可以直接发送消息给住程序,把对象名也带过去,主程序接到消息后,根据名称再转发给具体的对象。 不管是用消息还是回调.你首先要理好思路.别一开始就想把所有的都做好.首先要最简单的能调成功先.开始不要用什么RegisterWindowMessage,BroadcastSystemmessage.你先别管消息是否会和其他人写的重复先,定义一个你自己绝对不大会重复的.WM_MyMsg =WM_User +1999;这样之类的.先按3楼第一个办法,调用dll时把handle传入.(当然对应的handle的窗体要有消息响应函数,或者能在wndproc里截获),然后用sendmessage来发消息.我想不成功的话估计是你自己哪个步骤错了.如果用回调的话可以简单点,直接用个init函数,把回调函数地址初始化到dll的变量里.然后调用 我把问题说的具体点:我在DLL中做了一个登录窗体,用户登录成功后,需要返回用户名和用户ID到主程序中,然后登录窗体关闭,释放这个DLL.因为在DLL中的登录窗体关闭后主窗体才显示出来,所以如果在DLL中发消息,没有办法得到主程序的窗口句柄,所有只能用BroadcastSystemmessage广播消息了.这样就出现了我在9楼中所说的问题,即:在消息处理过程中无法赋值给全局变量.关于回调函数,因为没有具体使用过,不知道该怎么用,高手能给个思路么?继续求教,谢谢! 主程序还在为何无法赋值dll传的数据?跟主窗体有没显示有什么关系? 因为主程序是在,但是主窗体还没有创建.当登录成功后,登录窗体关闭,卸载显示登录窗体的DLL,然后再创建DLL.我所建立的自定义对象就是为了处理 先掉了登录DLL,显示登录窗体,登录成功后,再创建主窗体. 楼主并未把程序的真正意图表达出来,所以按照楼主所表达的,只能说思路有问题,如果你想让主程序响应DLL,那么用回调函数、接口等技术都能实现,没必要为对象有无句柄而伤脑筋。 发消息不分DLL或你的主EXE,都是一样的。你的表述不清。你是想发消息传值过去?还是只发消息让主程序响应一下? 我是想发消息传个值过去.但是如果在主程序中自定义一个消息如:WM_MYMSG = WM_USER + 1000 然后再定义一个消息处理过程(是自定义对象的一个方法);再在DLL中定义同样的消息 :WM_MYMSG = WM_USER + 1000 ,然后在DLL中发消息给主EXE(广播消息),为什么主程序中不能调用消息处理过程呢? 我理解的不知道对不对。你的意思就是你的登陆窗体是在DLL中写的,在程序运行的时候先调用DLL,然后在DLL中通过用户认证后返回用户名和用户ID到主程序中,然后才创建主窗体。如果是这样的话,用回调函数应该是最简单的吧 其实我是想发两个值过去,及时DLL登录窗口中登录成功后保存的用户名(字符串)和用户ID(integer),无奈不知道怎么通过消息传字符串 原来是是这样啊,那也简单,在DLL中定义变量,把变量地址用消息传递给主程序,记着主程序及时保存这个变量数据就行了,也没必要再映射文件什么的。 要用消息处理啊,那就是实现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; 这样在这个过程中就可以接收消息了 看一下TTimer的实现代码,看一下它是如何接收时间消息的. 你目的也是为了得到登陆dll中的用户名密码吧?直接传给主程序不行吗?跟主窗体显不显示,存不存在没关系啊 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; 你的要求无非是UI跑dll;但dll跑时,也想要UI响应 我们一般不是都在窗体类中处理自定义消息的吗?像这样: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个窗体,倒是可以先创建另一个,处理消息后,再看是否要创建 主窗体。这个要关注下,学习学习 关于DevExpress和 ExpressBar的问题。 三层结构中的连接表,要怎么样保存? 错误信息:Timeout expired CreateOleobject ? 帮忙看该存储过程,巨慢,客户不能忍受,如何提高速度? 关于ADO的小问题 Delphi对Xml操作问题??????????????不用XmlDocument构件!!有兴趣可以进来! 笑话 如何实现ping 的功能?有没有返回值? 第三方组件skinengine,dxtreeview安装后如何使用的问题。 一个delphi的基础问题 将两表合并
方法2:在DLL中用FindWindow找到主程序的窗口;
方法3:用进程间数据共享的方法,把主程序的句柄放到共享。
我的想法是使用 在应用程序间发送消息的方法,
即:
1.在DLL和主程序中同时定义一个消息常量,用到函数RegesterWindowMessage('AMsg');
2.在主程序中覆盖对象的WndProc()方法处理自定义的消息(AMsg)
3.在DLL中用BrodcastSystemMessage()函数发送消息
可是实际效果是:被覆盖的WndProc()方法根本截获不到DLL中发送的消息.
请高手赐教,分不够可在加.
主程序的部份代码
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等等写入和读取内存映射文件代码就很长了,楼主可以参考相关资料.总的思路是:通过发送消息给程序主程序,告诉主程序数据写到了内存映象文件.然后主程序读取内存映象文件中的数据,赋给相应的对象.
关于内存映射我也用过,不够由于当初设计不好,这里用起来比较困难.
我昨天晚上想了一种方法,就是在再主程序的一个自定义类中定义一个过程(比如HandleAppMsg)来处理Application的OnMessage事件.
通过同时在DLL和主程序中用RegisterWindowMessage('AMsg')注册消息,
然后在DLL中BroadcastSystemmessage,这样主程序中能接收到消息,并且处理了.
但是在HandleAppMsg中对一个全局变量赋值却不行(即,在处理Application的OnMessage事件的过程中,
不能将通过消息传递过来的值赋给一个全局变量).现在问题是:
一个类中用于处理消息的过程和普通过程有什么区别么? 是不是在 消息处理过程中给全局变量赋值注定不会成功?
DLL里可以直接发送消息给住程序,把对象名也带过去,
主程序接到消息后,根据名称再转发给具体的对象。
开始不要用什么RegisterWindowMessage,BroadcastSystemmessage.
你先别管消息是否会和其他人写的重复先,定义一个你自己绝对不大会重复的.
WM_MyMsg =WM_User +1999;这样之类的.先按3楼第一个办法,调用dll时把handle传入.
(当然对应的handle的窗体要有消息响应函数,或者能在wndproc里截获),然后用sendmessage来发消息.
我想不成功的话估计是你自己哪个步骤错了.
如果用回调的话可以简单点,直接用个init函数,把回调函数地址初始化到dll的变量里.然后调用
我在DLL中做了一个登录窗体,用户登录成功后,需要返回用户名和用户ID到主程序中,然后登录窗体关闭,释放这个DLL.
因为在DLL中的登录窗体关闭后主窗体才显示出来,所以如果在DLL中发消息,没有办法得到主程序的窗口句柄,所有只能用
BroadcastSystemmessage广播消息了.
这样就出现了我在9楼中所说的问题,即:在消息处理过程中无法赋值给全局变量.
关于回调函数,因为没有具体使用过,不知道该怎么用,高手能给个思路么?
继续求教,谢谢!
我所建立的自定义对象就是为了处理 先掉了登录DLL,显示登录窗体,登录成功后,再创建主窗体.
(是自定义对象的一个方法);
再在DLL中定义同样的消息 :WM_MYMSG = WM_USER + 1000 ,然后在DLL中发消息给主EXE(广播消息),
为什么主程序中不能调用消息处理过程呢?
其实我是想发两个值过去,及时DLL登录窗口中登录成功后保存的用户名(字符串)和用户ID(integer),
无奈不知道怎么通过消息传字符串
原来是是这样啊,那也简单,在DLL中定义变量,把变量地址用消息传递给主程序,记着主程序及时保存这个变量数据就行了,也没必要再映射文件什么的。
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;
这样在这个过程中就可以接收消息了
//---------------------------------------------
//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;
无非是UI跑dll;但dll跑时,也想要UI响应
我们一般不是都在窗体类中处理自定义消息的吗?像这样: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个窗体,倒是可以先创建另一个,处理消息后,再看是否要创建 主窗体。
这个要关注下,学习学习