flat assembler
Message board for the users of flat assembler.

Index > Windows > tray apps listing

Author
Thread Post new topic Reply to topic
dacid



Joined: 31 Aug 2008
Posts: 57
dacid 09 Mar 2009, 10:17
is there any way to list apps that are in the tray bar?
Post 09 Mar 2009, 10:17
View user's profile Send private message Reply with quote
Grom PE



Joined: 13 Mar 2008
Posts: 114
Location: i@grompe.org.ru
Grom PE 09 Mar 2009, 13:10
dacid, yes.
I have Delphi WinAPI code that lists process ID of programs that have an icon in tray.
Is this what you want?
Post 09 Mar 2009, 13:10
View user's profile Send private message Visit poster's website Reply with quote
dacid



Joined: 31 Aug 2008
Posts: 57
dacid 09 Mar 2009, 17:06
yes, this should work...
Post 09 Mar 2009, 17:06
View user's profile Send private message Reply with quote
Grom PE



Joined: 13 Mar 2008
Posts: 114
Location: i@grompe.org.ru
Grom PE 09 Mar 2009, 17:22
Code:
{$APPTYPE CONSOLE}
uses Windows, Messages, ShellAPI, CommCtrl, TlHelp32;

type
  TExtraData = packed record
    Wnd: THandle;
    uID: integer;
    uCallbackMessage: cardinal;
    Reserved: array [0..1] of cardinal;
    Icon: HICON;
  end;

function GetToolbarHandle: THandle;
begin
  Result := FindWindowEx(0, 0, 'Shell_TrayWnd', nil);
  if Result = 0 then Exit;
  Result := FindWindowEx(Result, 0, 'TrayNotifyWnd', nil);
  if Result = 0 then Exit;
  Result := FindWindowEx(Result, 0, 'SysPager', nil);
  if Result = 0 then Exit;
  Result := FindWindowEx(Result, 0, 'ToolbarWindow32', nil);
end;

function GetProcessFileName(pid: cardinal): string;
var
  snapshot: THandle;
  procentry: TProcessEntry32;
  ret: BOOL;
begin
  Result := '';
  snapshot := CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
  if snapshot <> INVALID_HANDLE_VALUE then
  begin
    procentry.dwSize := Sizeof(procentry);
    ret := Process32FIRST(snapshot, procentry);
    while ret do
    begin
      if procentry.th32ProcessID = pid then
      begin
        Result := procentry.szExeFile;
        Break;
      end else begin
        ret := Process32Next(snapshot, procentry);
      end;
    end;
    CloseHandle(snapshot);
  end;
end;

procedure ListTrayProcesses;
var
  ToolbarHandle: THandle;
  ProcessID: DWORD;
  Process: THandle;
  ButtonCount: Integer;
  Data: Pointer;
  Index: Integer;
  BytesRead: DWORD;
  Button: TTBButton;
  ExtraData: TExtraData;
  Res: boolean;
  ProcID: cardinal;
begin
  // The tray icons are actually buttons on a toolbar
  ToolbarHandle := GetToolbarHandle;
  if ToolbarHandle = 0 then Exit;
  ButtonCount := SendMessage(ToolbarHandle, TB_BUTTONCOUNT, 0, 0);
  if ButtonCount < 1 then Exit;

  // We want to get data from another process - it's not possible
  // to just send messages like TB_GETBUTTON with a locally
  // allocated buffer for return data. Pointer to locally allocated
  // data has no usefull meaning in a context of another
  // process (since Win95) - so we need
  // to allocate some memory inside Tray process.
  // Use @ProcessId for C5/D5 compatibility

  if GetWindowThreadProcessId(ToolbarHandle, @ProcessID) = 0 then Exit;

  Process := OpenProcess(PROCESS_ALL_ACCESS, False, ProcessID);
  if Process = 0 then Exit;

  // Allocate needed memory in the context of the tray process. We reuse
  // Data to read multiple parts so we set it to the biggest chunk we need
  // (TTBButton)
  Data := VirtualAllocEx(Process, nil, SizeOf(TTBButton), MEM_COMMIT, PAGE_READWRITE);
  if Data = nil then Exit;

  for Index := ButtonCount - 1 downto 0 do
  begin
    SendMessage(ToolbarHandle, TB_GETBUTTON, Index, Longint(Data));
    Res := ReadProcessMemory(Process, Data,
      @Button, SizeOf(Button), BytesRead) and (BytesRead = SizeOf(Button));
    if not Res then Continue;
    Res := ReadProcessMemory(Process, Pointer(Button.dwData),
      @ExtraData, SizeOf(ExtraData), BytesRead) and (BytesRead = SizeOf(ExtraData));
    if not Res then Continue;
    // Skip totally hidden icons
    if (Cardinal(ExtraData.uID) and $80000000)<>0 then Continue;

    if IsWindow(ExtraData.Wnd) then
    begin
      GetWindowThreadProcessId(ExtraData.Wnd, @ProcID);
      WriteLn(GetProcessFileName(ProcID));
    end;
  end;
  VirtualFreeEx(Process, Data, 0, MEM_RELEASE);

  CloseHandle(Process);
end;

begin
  ListTrayProcesses;
end.    
Post 09 Mar 2009, 17:22
View user's profile Send private message Visit poster's website Reply with quote
Display posts from previous:
Post new topic Reply to topic

Jump to:  


< Last Thread | Next Thread >
Forum Rules:
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum
You cannot attach files in this forum
You can download files in this forum


Copyright © 1999-2024, Tomasz Grysztar. Also on GitHub, YouTube.

Website powered by rwasa.