質問

トレイアイコン(PX)のロケートのトレイアイコンを見つけました。

トレイを見つけることができますが、アイコンもアイコンではありません。これは私が使っているコードです:

unit uTrayIconPosition;

interface

uses
  Types;

function GetTrayIconPosition(const AWnd: THandle; const AButtonID: Integer; var APosition: TRect): Boolean;

implementation

uses
  Windows, CommCtrl, Classes, SysUtils;

function EnumWindowsFunc(AHandle: THandle; AList: TStringList): Boolean; stdcall;
var
  P: array [0..256] of Char;
  S: string;
begin
  if GetClassName(AHandle, P, SizeOf(P) - 1) <> 0 then
  begin
    S := P;
    if S = AList[0] then
    begin
      AList[0] := IntToStr(AHandle);
      Result := False;
    end
    else
      Result := True;
  end
  else
    Result := True;
end;

function FindClass(AName: string; AHandle: THandle; var AChild: THandle): Boolean;
var
  List: TStringList;
begin
  Result := False;
  try
    List := TStringList.Create;
    try
      List.Add(AName);
        EnumChildWindows(AHandle, @EnumWindowsFunc, LParam(List));
      if List.Count > 0 then
      begin
        AChild := StrToInt(List[0]);
        Result := True;
      end;
    finally
      List.Free;
    end;
  except
  end;
end;
.

// ---通知WND のハンドル

function GetTrayNotifyWnd: THandle;
var
  ShellTray: THandle;
  TrayNotify: THandle;
  ToolBar: THandle;
begin
    Result := 0;
  ShellTray := FindWindow('Shell_TrayWnd', nil);
  if ShellTray <> 0 then
    if FindClass('TrayNotifyWnd', ShellTray, TrayNotify) then
      if IsWindow(TrayNotify) then
        if FindClass('ToolbarWindow32', TrayNotify, ToolBar) then
                Result := ToolBar;
end;
.

//--トレイ四捨て

function GetTrayWndRect: TRect;
var
  R: TRect;
  Handle: THandle;
  Width: Integer;
  Height: Integer;
begin
    Handle := GetTrayNotifyWnd;
    if Handle > 0 then
    begin
        GetWindowRect(Handle, R);
        Result := R;
    end
  else
  begin
      Width := GetSystemMetrics(SM_CXSCREEN);
    Height := GetSystemMetrics(SM_CYSCREEN);
    Result := Rect(Width - 40, Height - 20, Width, Height);
  end;
end;
.

// ---トレイアイコンを見つけるべき主な機能

function GetTrayIconPosition(const AWnd: THandle; const AButtonID: Integer; var APosition: TRect): Boolean;
var
  hWndTray: HWND;
  dwTrayProcessID: DWORD;
  hTrayProc: THandle;
  iButtonsCount: Integer;
  lpData: Pointer;
  bIconFound: Boolean;
  iButton: Integer;
  dwBytesRead: DWORD;
    ButtonData: TTBBUTTON;
  dwExtraData: array [0..1] of DWORD;
  hWndOfIconOwner: THandle;
  iIconId: Integer;
//  rcPosition: TPoint;
  rcPosition: TRect;
begin
    Result := False;

  hWndTray := GetTrayNotifyWnd;
  if hWndTray = 0 then
    Exit;

    dwTrayProcessID := 0;
    GetWindowThreadProcessId(hWndTray, dwTrayProcessID);
    if dwTrayProcessID <= 0 then
        Exit;

    hTrayProc := OpenProcess(PROCESS_ALL_ACCESS, False, dwTrayProcessID);
    if hTrayProc = 0 then
        Exit;

    iButtonsCount := SendMessage(hWndTray, TB_BUTTONCOUNT, 0, 0);
  lpData := VirtualAllocEx(hTrayProc, nil, SizeOf(TTBBUTTON), MEM_COMMIT, PAGE_READWRITE);
    if (lpData = nil) or (iButtonsCount < 1) then
    begin
        CloseHandle(hTrayProc);
        Exit;
    end;

    bIconFound := False;
    for iButton :=0 to  iButtonsCount - 1 do
    begin
        dwBytesRead := 0;
        SendMessage(hWndTray, TB_GETBUTTON, iButton, LPARAM(lpData));
        ReadProcessMemory(hTrayProc, lpData, @ButtonData, SizeOf(TTBBUTTON), dwBytesRead);
        if dwBytesRead < SizeOf(TTBBUTTON) then
            Break;

    dwExtraData[0] := 0;
    dwExtraData[1] := 0;
        ReadProcessMemory(hTrayProc, Pointer(ButtonData.dwData), @dwExtraData, SizeOf(dwExtraData), dwBytesRead);
        if dwBytesRead < SizeOf(dwExtraData) then
            Break;

        hWndOfIconOwner := THandle(dwExtraData[0]);
        iIconId := Integer(dwExtraData[1]);
        if hWndOfIconOwner = AWnd then
        if iIconId = AButtonID then
            begin
            if (ButtonData.fsState or TBSTATE_HIDDEN) = 1 then
                Break;

        SendMessage(hWndTray, TB_GETITEMRECT, iButton, LPARAM(lpData));
        ReadProcessMemory(hTrayProc, lpData, @rcPosition, SizeOf(TREct), dwBytesRead);
        if dwBytesRead < SizeOf(TRect) then
          Break;

        MapWindowPoints(hWndTray, 0, rcPosition, 2);
        APosition := rcPosition;
        bIconFound := True;
        Break;
      end;
    end;

    if not bIconFound then
        APosition := GetTrayWndRect;
    VirtualFreeEx(hTrayProc, lpData, 0, MEM_RELEASE);
    CloseHandle(hTrayProc);
    Result := True;
end;

end.
.

Algoはトレイアイコンの数を検出しますが、それらのそれぞれをマップしません。

これを追加します。

原因この解決策は、次のXPシステムと32ビットシステムでのみ機能します。

{$EXTERNALSYM Shell_NotifyIconGetRect}
function Shell_NotifyIconGetRect(const _in: NOTIFYICONIDENTIFIER; var _out: TRECT): HRESULT; stdcall;

implementation

function Shell_NotifyIconGetRect; external 'Shell32.dll' name 'Shell_NotifyIconGetRect';
.

Delphi 2007はこの機能をマッピングしており、この構造もありません:

type
  NOTIFYICONIDENTIFIER = record
    cbSize  : DWORD;
    hWnd    : HWND;
    uID     : UINT;
    guidItem: TGUID;
end;
  PNOTIFYICONIDENTIFIER = ^NOTIFYICONIDENTIFIER;
.

Shell_NotifyICONでトレイアイコンを作成した後、この新しいNotifyIconIdentifier Structure> に渡すことを試みました。

var
  R: TRect;
  S: NOTIFYICONIDENTIFIER;

FillChar(S, SizeOf(S), #0);
S.cbSize := SizeOf(NOTIFYICONIDENTIFIER);
S.hWnd := ATrayIcon.Data.Wnd;
S.uID := ATrayIcon.Data.uID;

Result := Shell_NotifyIconGetRect(S, R) = S_OK;
.

これは正しく機能していて、私は私のトレイアイコンの左上隅の直線構造に受け取ります。

役に立ちましたか?

解決

Windows 7と上に上にMSが紹介されたAPI関数を使用する必要があります。 Shell_NotifyIconGetRect

あなたの現在のコードは、以下の1つ以上の理由で失敗しています:

  1. 64ビットプロセスからの構造の32ビットバージョンを読みようとしています。この場合、TTBBUTTONは64ビットの下で異なるレイアウトとサイズを持ち、攻撃しているプロセスは64ビットエクスプローラです。
  2. 通知領域の実装(頼っている)の実装(存在する)はXPと7の間で変更されました。これが当てはまるかどうかわからないが、それは!
ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top