获取当前正在运行的窗口的标题如何?

5
我有一个问题:我只需要将所有窗口的标题以列表形式获取,这里的标题指的是窗口顶部显示的文本,比如“记事本”、“总指挥”。目前我已经做到了这一步。
function EnumWindowProc(hHwnd: HWND; lParam : integer): boolean; stdcall;
var
  pPid : DWORD;
  title, ClassName : string;
begin
  if (hHwnd=NULL) then
  begin
    result := false;
  end
  else
  begin
    GetWindowThreadProcessId(hHwnd,pPid);
    SetLength(ClassName, 255);
    SetLength(ClassName,
              GetClassName(hHwnd,
                           PChar(className),
                           Length(className)));
    SetLength(title, 255);
    SetLength(title, GetWindowText(hHwnd, PChar(title), Length(title)));
    OptionsForm.ListBox1.Items.Add(title);
    OptionsForm.Memo1.Lines.Add
      ('Class Name = ' + className +
       '; Title = ' + title +
       '; HWND = ' + IntToStr(hHwnd) +
       '; Pid = ' + IntToStr(pPid));
    Result := true;
  end;
end;

不过,它返回了各种“窗口”,不同形式的焦点等等。我如何只获取“主要”的那些?

以下是结果示例:

Class Name = Shell_TrayWnd; Title = ; HWND = 65898; Pid = 3776
Class Name = CiceroUIWndFrame; Title = CiceroUIWndFrame; HWND = 65976; Pid = 3776
Class Name = THelpInsightWindowImpl; Title = HelpInsightWindow; HWND = 1577734; Pid = 4852
Class Name = THelpInsightWindowImpl; Title = HelpInsightWindow; HWND = 591660; Pid = 4852
Class Name = TTokenWindow; Title = CodeParamWindow; HWND = 985436; Pid = 4852
Class Name = TaskSwitcherWnd; Title = Přepínání úloh; HWND = 66824; Pid = 3776
Class Name = tooltips_class32; Title = ; HWND = 198982; Pid = 1768
Class Name = tooltips_class32; Title = ; HWND = 66046; Pid = 3776
Class Name = _SearchEditBoxFakeWindow; Title = ; HWND = 66024; Pid = 3776
Class Name = tooltips_class32; Title = ; HWND = 66008; Pid = 3776
Class Name = tooltips_class32; Title = ; HWND = 131538; Pid = 3776
Class Name = Desktop User Picture; Title = Magicmaster; HWND = 65982; Pid = 3776
Class Name = DV2ControlHost; Title = Nabídka Start; HWND = 65978; Pid = 3776
Class Name = tooltips_class32; Title = ; HWND = 327840; Pid = 1768
Class Name = tooltips_class32; Title = ; HWND = 460808; Pid = 1768
Class Name = CTSCTooltip; Title = ; HWND = 266710; Pid = 2792
Class Name = Auto-Suggest Dropdown; Title = ; HWND = 69884; Pid = 4732
Class Name = Auto-Suggest Dropdown; Title = ; HWND = 69802; Pid = 4732
Class Name = TaskbarNotifierClass; Title = DAP Message Center; HWND = 68924; Pid = 4732
Class Name = tooltips_class32; Title = ; HWND = 134356; Pid = 1992
Class Name = ATKOSD; Title = ATKOSD; HWND = 65884; Pid = 3636

提前感谢您!


1
首先,确定“main”是什么意思。 - Rob Kennedy
罗布是正确的。你在找什么?作为一个猜测,我猜你只想要在任务栏中有按钮的窗口。 - David Heffernan
从[MSDN](http://msdn.microsoft.com/en-us/library/cc144179(VS.85).aspx#Managing_Taskbar_But)中:当应用程序创建一个不被拥有的窗口时,Shell会在任务栏上创建一个按钮。为确保窗口按钮放置在任务栏上,请使用WS_EX_APPWINDOW扩展样式创建一个未拥有的窗口。 - David Heffernan
1
是的,我所说的“主要”是指那些可以通过alt+tab进行聚焦或在任务栏中具有图标的应用程序。 - Martin Melka
2个回答

10

重要信息包含在描述任务栏的MSDN主题中。基本上,您需要枚举顶级窗口并挑选那些可见、未拥有且具有WS_EX_APPWINDOW窗口样式。

这个程序向您展示了如何完成:

program EnumTaskbarWindows;

{$APPTYPE CONSOLE}

uses
  SysUtils, Windows;

function EnumWindowsProc(hwnd: HWND; lParam: LPARAM): BOOL; stdcall;
var
  s: string;
  len: Integer;
  IsVisible, IsOwned, IsAppWindow: Boolean;
begin
  Result := True;//carry on enumerating

  IsVisible := IsWindowVisible(hwnd);
  if not IsVisible then
    exit;

  IsOwned := GetWindow(hwnd, GW_OWNER)<>0;
  if IsOwned then
    exit;

  IsAppWindow := GetWindowLongPtr(hwnd, GWL_STYLE) and WS_EX_APPWINDOW<>0;
  if not IsAppWindow then
    exit;
  
  len := GetWindowTextLength(hwnd);
  if len = 0 then
    exit;
  SetLength(s, len);
  GetWindowText(hwnd, PChar(s), len+1);
  Writeln(s);
end;

begin
  EnumWindows(@EnumWindowsProc, 0);
end.

就是这样。谢谢您提供的MSDN链接。我不知道Windows的标准。 - Martin Melka
1
@David Heffernan - 快速查看后,我意识到您的代码不幸地没有显示一些窗口,例如BSPlayer、Kaspersky KIS和Delphi。 - Gabriel
为什么不呢?调试器告诉你了什么? - David Heffernan
它错过了Windows计算器。 - user30478
我在 GetWindowText 上遇到了 AV。 - Gabriel
在调用GetWindowText之前,您需要添加一个“if s ='' then EXIT”的检查。 - Gabriel

1
你想要检查这些窗口的属性。例如,排除任何不可见的窗口。您可以使用 GetWindowInfo 来实现此目的。要查找的属性为:没有标题(在 dwStyle 中缺少 WS_CAPTION),或者不可见 (WS_VISIBLE 标志)。您可能还想检查移动到屏幕之外的窗口,但这有点棘手(甚至可能存在多个负偏移的监视器)。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接