这段代码是一个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;

解决方案 »

  1.   

    如果目标程序确定为delphi程序,自己写一个FindControl。
    可参考这个:http://hi.baidu.com/topcoder/blog/item/2f591897bde2a06955fb9612.html
    你的程序不需要注入,可直接跳过如何注入dll部分,看看第二点,讲的原理以及实现方法
      

  2.   

    问题倒是解决了,但是那代码FindControl的代码看得有点模糊。前辈能指点否?
    原来的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的原理是什么?谢谢!
      

  3.   

    你看一下Controls单元initcontrols中对ControlAtomString的写法,
    在对比这样的写法
    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對象地址。
      

  4.   

    呵呵~~你要记住,在寻址方面,基本上是通过指针来的,所以Handle是一种比较特殊的指针类型FindControl是在于寻找对象类,也可以通过指定指针来寻找!
      

  5.   

    在DLL中不能直接用API函数,而需自己加工,如楼上所述