读书人

请教关于用DLL来分割模块与EXE交互的

发布时间: 2012-03-09 16:54:57 作者: rapoo

请问关于用DLL来分割模块,与EXE交互的问题!大大们请指点!
假如说有EXE和DLL,动态调用,EXE直接调用DLL的exports接口,没有问题。如果DLL要向EXE返回信息呢?
除了回调,有其他比较好的办法吗?
另外,不知道DELPHI 2010/XE里的RTTI能不能实现.net里直接对DLL进行反射的功能呢?

[解决办法]
EXE 与DLL 通信可以用句柄来通信的

DLL 向主程序发送消息
var
wp, lp: longint;
begin
wp := GlobalAddAtom(pchar(wParam));
lp := 0;
if lparam <> '' then lp := GlobalAddAtom(pchar(lParam));
if pr_Systems.MainHandle > 0 then
begin
PostMessage(pr_Systems.MainHandle, WM_mainmessage, wp, lp);
end;
end

//主程序接收消息
procedure WM_messageMain(var Message: TMessage); message WM_Mainmessage;
var
sl, index: integer;
formhandle: THandle;
strcommand, strcommandtext, strcommandsend, strcommandtextsend: string;
commandarr: Array[0..1023] of char; // 消息命令
commandtextarr: array[0..1023] of char; // 消息内容
windhand: THandle;
wp: longint;
begin
strcommand := '';
strcommandtext := '';
if Message.WParam <> 0 then //消息命令
begin
sl := GlobalGetAtomName(Message.WParam, @commandarr, sizeof(commandarr));
GlobalDeleteAtom(Message.WParam);
if sl > 0 then
begin
commandarr[sl] := #0;
strcommand := commandarr;
strcommand := lowercase(strcommand);
end;
end;
if Message.LParam <> 0 then//消息内容体
begin
sl := GlobalGetAtomName(Message.LParam, @commandtextarr, sizeof(commandtextarr));
GlobalDeleteAtom(Message.LParam);
if sl > 0 then
begin
commandtextarr[sl] := #0;
strcommandtext := commandtextarr;
strcommandtext := trim(strcommandtext);
end;
end;
if strcommand = '' then exit;
if self.FIsrecordMessage then //记录消息
begin
self.FMsgMainList.Append(strcommand + '=' + strcommandtext);
if FMsgMainList.Count > MaxStringListCount then
begin
ttjpubfun.WriteToLog(FMsgMainList,
TtjAppRegInfo.GetApplicationAppLogPath + 'mdiform_message_' +
FormatDateTime('YYYYMMDD', Now()) + '.txt');
FMsgMainList.Clear;
end;
end;
if strcommand = 'login' then //DLL登录
begin // formhandle = <billidend>xxxx<billiden>
formhandle := strtointdef(ttjpubfun.ExtractName(strcommandtext, '0'), 0);
if formhandle > 0 then
begin
index := self.FMDIFormList.IndexOfName(inttostr(formhandle));
if index >= 0 then FMDIFormList.Delete(index);
FMDIFormList.Append(strcommandtext);
end;
end
else if strcommand = 'logout' then //DLL退出
begin // strcommandtext = logout form handle exmple 1
formhandle := strtointdef(strcommandtext, 0);
index := self.FMDIFormList.IndexOfName(inttostr(formhandle));
if index >= 0 then FMDIFormList.Delete(index);
end
else if strcommand = 'checksubmit' then //DLL审核提交
begin //<billiden>xxx<billiden><keyvalues>xxxxx</keyvalues>
self.Postmessagetomsgclient('checksubmit', strcommandtext, True);
end
else if strcommand = 'checkpass' then //DLL审核同意
begin
self.PostmessageTomsgclient(strcommand, strcommandtext, true);
end
else if strcommand = 'checkunpass' then //DLL审核不同意
begin
self.PostmessageTomsgclient(strcommand, strcommandtext, True);
end
else if strcommand = 'checkback' then
begin
self.PostmessageTomsgclient(strcommand, strcommandtext, True);
end
else if strcommand = 'checkcancel' then
begin
self.PostmessageTomsgclient(strcommand, strcommandtext, True);
end
else if strcommand = 'checkinfo' then
begin
self.PostmessageTomsgclient(strcommand, strcommandtext, True);
end
else if strcommand = 'help' then //DLL请求打开帮助文件
begin
self.openhelp(strcommandtext);


end;
end;

//帮助文件负责解释是哪个窗体,哪个控件,好定位到相应的帮助文件
procedure THelpFile.openhelpchm(const value: string);
var
dllname, formname, controlname, sTopic: string;
helpcontext, index: integer;
query: HH_FTS_Query;
popup: HH_POPUP;
hh: HWND;
begin
dllname := TAnalysestr.ReadString(value, 'dllname', '');
formname := TAnalysestr.ReadString(value, 'formname', '');
controlname := TAnalysestr.ReadString(value, 'controlname', '');
helpcontext := strtointdef(TAnalysestr.ReadString(value, 'helpcontext', '0'), 0);
sTopic := '';

if (dllname <> '') or (formname <> '') or (controlname <> '') then
begin
if Fadodataset_help.Locate('dllname;formname;controlname', vararrayof([dllname, formname, controlname]), []) then
sTopic := Fadodataset_help.FieldByname('htmfilename').AsString
else if Fadodataset_help.Locate('dllname;formname', vararrayof([dllname, formname]), []) then
sTopic := Fadodataset_help.FieldByname('htmfilename').AsString
else if Fadodataset_help.Locate('dllname', dllname, []) then
sTopic := Fadodataset_help.FieldByname('htmfilename').AsString;
end;

if TAnalysestr.ReadString(value, 'query', '') <> '' then
begin
with query do
begin
cbStruct := sizeof(HH_FTS_Query);
fUniCodeStrings := false;
iProximity := HH_FTS_DEFAULT_PROXIMITY;
fStemmedSearch := True;
fExecute := True;
fTitleOnly := False;
pszWindow := nil;
pszSearchQuery := pchar(TAnalysestr.ReadString(value, 'query', ''));
end;
strfullquery := TAnalysestr.ReadString(value, 'query', '');

HtmlHelpA(0, pchar(Fhelpfilename), HH_DISPLAY_SEARCH, PDWORD(@query));

hh := FindWindow('HH Parent', pchar('hrms help'));
if hh <= 0 then hh := FindWindow('HH Parent', pchar('help'));
if hh > 0 then
begin
EnumChildWindows(hh, @EnumWindowsProc, 0);
end;
end
else if helpcontext > 0 then
begin
with popup do
begin
cbStruct := sizeof(HH_POPUP);
hinst:= 0;
idString := helpcontext;
pszText:=nil;
//pt:= pt;
GetCursorPos(pt);
clrForeground:=COLORREF(-1);
clrBackground:=COLORREF(-1);
rcMargins.Left := 0;
rcMargins.Top := 0;
rcMargins.Right := 25;
rcMargins.Bottom := 25;
pszFont:=LPCTSTR('BOLD');
end;
HtmlHelpA(0, pchar(Fhelpfilename), HH_DISPLAY_TEXT_POPUP, PDWORD(@popup));
end
else if sTopic <> '' then
HtmlHelpA(0, pchar(Fhelpfilename), HH_DISPLAY_TOPIC, PDWORD(pchar(sTopic)))
else if sTopic = '' then
HtmlHelpA(0, pchar(Fhelpfilename), HH_DISPLAY_TOC, PDWORD(pchar(sTopic)))
end;


[解决办法]
dll可以封装对象的,李维的书里面讲过。利用interface,exe可以直接调用dll里导出的对象,访问对象的属性,事件,就没有什么通信的问题了~

读书人网 >.NET

热点推荐