문제

트레이 바에서 트레이 아이콘 (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;
.

//- 트레이 RECT 찾기

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.
.

알고 트레이 아이콘의 탐지하지만 각각의 각각을 맵핑하지 않습니다.

이 추가됩니다.

원인이 솔루션은 다음을 시도한 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;
.

쉘 _notifyIcon이있는 트레이 아이콘을 만든 후에는 _notifyicondata 구조의 HWND를이 새로운 NotifyIctionifier 구조> 에 전달하려고 시도했습니다.

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;
.

이것은 올바르게 작동하고 트레이 아이콘의 왼쪽 상단 모서리에서 RECT 구조로받습니다.

도움이 되었습니까?

해결책

Windows 7 및 Upwards에서는 Shell_NotifyIconGetRect .

현재 코드가 다음과 같은 이유로 하나 이상의 이유로 실패합니다.

  1. 64 비트 프로세스에서 구조물의 32 비트 버전을 읽으려고합니다.이 경우 TTBBUTTON는 64 비트 미만의 레이아웃과 크기가 다르며 공격하는 프로세스는 64 비트 탐색기입니다.
  2. 알림 영역의 구현 (귀하가 의존하는 세부 사항)은 XP와 7 사이에서 변경되었습니다. 이는 사실인지 여부를 알지 못합니다.
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top