这段代码是一个DLL工程
library Project2;uses
SysUtils,
Windows,
Dialogs,
Forms,
TLHelp32,
StdCtrls,
Controls,
Classes,
Unit1 in 'Unit1.pas';
var
hFrm:TForm;
h:HWND;
{$R *.res}
begin
h:=FindWindow(nil,'Form1');
hFrm:=TForm(FindControl(h));
ShowMessage(hFrm.Caption);
end.procedure TForm1.Button1Click(Sender: TObject);
var
hFrm:TForm;
h:HWND;
begin
{问题:}
{为什么本Application工程中这样可以找得到窗体实例,而在DLL工程中这样使用却不行?}
{请各位前辈指导,谢谢!}
h:=FindWindow(nil,'Form1');
hFrm:=TForm(FindControl(h));
ShowMessage(hFrm.Caption);
end;procedure TForm1.Button2Click(Sender: TObject);
begin
LoadLibrary('Project2.dll');
end;
library Project2;uses
SysUtils,
Windows,
Dialogs,
Forms,
TLHelp32,
StdCtrls,
Controls,
Classes,
Unit1 in 'Unit1.pas';
var
hFrm:TForm;
h:HWND;
{$R *.res}
begin
h:=FindWindow(nil,'Form1');
hFrm:=TForm(FindControl(h));
ShowMessage(hFrm.Caption);
end.procedure TForm1.Button1Click(Sender: TObject);
var
hFrm:TForm;
h:HWND;
begin
{问题:}
{为什么本Application工程中这样可以找得到窗体实例,而在DLL工程中这样使用却不行?}
{请各位前辈指导,谢谢!}
h:=FindWindow(nil,'Form1');
hFrm:=TForm(FindControl(h));
ShowMessage(hFrm.Caption);
end;procedure TForm1.Button2Click(Sender: TObject);
begin
LoadLibrary('Project2.dll');
end;
解决方案 »
- 把ASM转成PASCAL
- 上海的哪位仁兄能帮我把 DevExpress_ExpressPrinting_System 装到我的东芝笔记本电脑上,必有重谢!
- 大侠们,help!
- 关于报表的问题~~
- 这个文本文件如何排序
- 关于TDateTimePicker控件的显示问题,
- 如何去掉combobox里重复的数?
- 如何对ADOQUERY返回的数据集进行UPDATE操作?
- adodataset filed "是否借阅" not found 是怎么回事?
- 我用Query查询时,当日期参数赋=Date时,可以正常查,而赋为DatetimePicker1.Date时,却查不出来。不知是何原因。用的是Access库
- 十分方便好用的远程数据库对象
- 帮看一下我写的代码为什么不行,谢谢
可参考这个:http://hi.baidu.com/topcoder/blog/item/2f591897bde2a06955fb9612.html
你的程序不需要注入,可直接跳过如何注入dll部分,看看第二点,讲的原理以及实现方法
原来的FindControl
function FindControl(Handle: HWnd): TWinControl;
var
OwningProcess: DWORD;
begin
Result := nil;
if (Handle <> 0) and (GetWindowThreadProcessID(Handle, OwningProcess) <> 0) and
(OwningProcess = GetCurrentProcessId) then
begin
if GlobalFindAtom(PChar(ControlAtomString)) = ControlAtom then
Result := Pointer(GetProp(Handle, MakeIntAtom(ControlAtom)))
else
Result := ObjectFromHWnd(Handle);
end;
end;
修改后的
function FindControlNew(Handle: HWnd): TWinControl;
var
OwningProcess: DWORD;
begin
Result := nil;
if (Handle <> 0) and (GetWindowThreadProcessID(Handle, OwningProcess) <> 0) and
(OwningProcess = GetCurrentProcessId) then begin
if GlobalFindAtom(PChar(ControlAtomString)) = ControlAtom then begin
Result := Pointer(GetProp(Handle, MakeIntAtom(ControlAtom)));
end else begin
Result := Pointer(SendMessage(Handle, RM_GetObjectInstance, 0, 0));
end;
end;
end;
为什么要这样修改呢?FindControl的原理是什么?谢谢!
在对比这样的写法
ControlAtomString := Format('ControlOfs%.8X%.8X', [GetModuleHandle(nil), GetCurrentThreadID]);
注意红色部分...
原理大致是这样的:
vcl在調用createwindowex並把返回值給FHandle后,調用setprop,將對象的地址記錄在property list。
每個window都有一個property list,是一種自描述的數據結構包含一個序列的值清單。这样,findcontrol就可以调用getprop
begin
Result := nil;
if Handle <> 0 then
begin
Result := Pointer(GetProp(Handle, MakeIntAtom(ControlAtom)));
end;
end;
通過window的handle,定位the property list,再依据atom,尋找window對象地址。