Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/api/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何使用EnumWindows回调函数?_Windows_Api_Delphi_Winapi_Delphi Xe7 - Fatal编程技术网

如何使用EnumWindows回调函数?

如何使用EnumWindows回调函数?,windows,api,delphi,winapi,delphi-xe7,Windows,Api,Delphi,Winapi,Delphi Xe7,我希望有一个整洁的(封闭且自包含的)函数(我们称之为GetDesktopHandle),它将句柄返回到桌面窗口。我使用下面的代码。但它只在DeskHandle是全局变量时起作用 如何去掉这个全局变量?如果我将其设置为本地,当我尝试DeskHandle:=hChild时,我会在getDesktopWnd中获得一个AV VAR DeskHandle : HWND; function GetDesktopHandle: HWND; function getDesktopWnd (Handle:

我希望有一个整洁的(封闭且自包含的)函数(我们称之为GetDesktopHandle),它将句柄返回到桌面窗口。我使用下面的代码。但它只在DeskHandle是全局变量时起作用

如何去掉这个全局变量?如果我将其设置为本地,当我尝试DeskHandle:=hChild时,我会在getDesktopWnd中获得一个AV

VAR DeskHandle : HWND;

function GetDesktopHandle: HWND;

  function getDesktopWnd (Handle: HWND; NotUsed: Longint): bool; stdcall;    { Callback function }
  VAR hChild : HWND;
  begin
   if handle <> 0 then
    begin
      hChild := FindWindowEx(handle, 0, 'SHELLDLL_DefView', nil);
      if hChild <> 0 then
       begin
        hChild := FindWindowEx(hChild, 0, 'SysListView32', nil);
        if hChild <> 0
        then DeskHandle := hChild;
       end;
    end;
   Result:= TRUE;
  end;

begin
 DeskHandle := 0;
 EnumWindows(@getDesktopWnd, 0);
 Result:= DeskHandle;
end;
VAR DeskHandle:HWND;
函数GetDesktopHandle:HWND;
函数getDesktopWnd(句柄:HWND;未使用:Longint):bool;stdcall;{回调函数}
VAR-hChild:HWND;
开始
如果句柄为0,则
开始
hChild:=FindWindowEx(句柄,0,'SHELLDLL_devview',nil);
如果hChild为0,则
开始
hChild:=FindWindowEx(hChild,0,'SysListView32',nil);
如果hChild 0
然后DeskHandle:=hChild;
终止
终止
结果:=真;
终止
开始
DeskHandle:=0;
EnumWindows(@getDesktopWnd,0);
结果:=桌面句柄;
终止
主要问题是:我可以将此代码作为单个函数编写吗,或者至少可以去掉外部/全局变量吗

可能的解决方案:
文档中说,第二个参数只是IN参数

lParam[in] 类型:LPRAM 要传递给回调函数的应用程序定义的值。


使用它将结果传回是错误的吗?

本地函数不能用作回调函数。如果没有使用
@
运算符传递函数,编译器会告诉您这一点。(使用运算符将参数转换为普通的非类型指针,因此编译器无法再进行检查。)

您必须使回调函数成为独立函数


要在回调和调用者之间传递数据,请使用第二个参数,您当前将其命名为
NotUsed
。例如,您可以将指针传递给句柄变量,然后回调可以取消对指针的引用以返回结果。

谢谢Rob(and+1)。我想通过NotUsed变量传递结果库,但文档中说该变量是将参数从调用者传递到回调函数,而不是相反。您要传递的参数是一个地址,该地址实际上是从调用方传递到接收方的。您负责接收者对其接收的值所做的操作。您可以选择使其取消引用该值。您可以调用
GetShellWindow
直接转到它,而不是枚举所有查找桌面根目录的顶级窗口。然后使用
FindWindowEx
两次,就像你已经在做的那样。另请参阅,有一个现有的函数可以获取桌面窗口句柄,它被称为@RobKennedy-GetShellWindow,在某些Windows平台上会失败。详细信息:@Remko,该函数获取的内容与我们在这里处理的内容不同。请参阅我在上一篇评论中链接的问题。
Handle
正面而非负面有什么特别之处。一个更清晰的测试是
如果MyData.Handle为0,则
。而且
Result:=notresult
非常奇怪,只是为了保存一个局部变量@DavidHeffernan
THandle=NativeUInt
,因此不能为负值。关于结果变量,我确实保存了一个局部变量,但它会对代码可读性产生负面影响,所以我同意你的看法。。。
type
  TMyData = record
    Handle: HWND;
    Pid: DWORD;
    Caption: String;
    ClassName: String;
  end;
  PMyData = ^TMyData;

function GetWindowClass(const Handle: HWND): String;
begin
  SetLength(Result, MAX_PATH);
  SetLength(Result, GetClassName(Handle, PChar(Result), Length(Result)));
end;

function GetWindowCaption(const Handle: HWND): String;
 begin
  SetLength(Result, MAX_PATH);
  SetLength(Result, GetWindowText(Handle, PChar(Result), Length(Result)));
end;

function EnumChildWindowsProc(Handle: THandle; MyData: PMyData): BOOL; stdcall;
var
  ClassName: String;
  Caption: String;
  Pid: DWORD;
begin
  ClassName := GetWindowClass(Handle);
  Caption := GetWindowCaption(Handle);

  Result := (ClassName = 'SysListView32') and (Caption = 'FolderView');
  if Result then
  begin
    MyData.Handle := Handle;
    GetWindowThreadProcessId(Handle, MyData.Pid);
    MyData.Caption := Caption;
    MyData.ClassName := ClassName;
  end;

  // To continue enumeration, the callback function must return TRUE;
  // to stop enumeration, it must return FALSE
  Result := not Result;
end;

procedure TForm1.Button1Click(Sender: TObject);
var
  MyData: TMyData;
begin
  ZeroMemory(@MyData, SizeOf(MyData));
  EnumChildWindows(GetDesktopWindow, @EnumChildWindowsProc, NativeInt(@MyData));
  if MyData.Handle > 0 then
  begin
     ShowMessageFmt('Found Window in Pid %d', [MyData.Pid]);
  end
  else begin
    ShowMessage('Window not found!');
  end;
end;