Top.Mail.Ru
Мастера DELPHI, Delphi programming community Титульная страница Поиск, карта сайта Написать письмо 
| Новости | Поиск | FAQ | Статьи | Книги | Новости VCL |
| Форумы ЧАТ | Орешник | KOL и MCK |
Форумы -» Основная («Начинающим»)/ Базы / WinAPI / Компоненты / Сети / Media / Игры / Corba и COM / KOL / FreePascal / .Net / Прочее / RSDN.ORG

« предыдущая ветвь | форум | следующая ветвь »

можноли получить хэндлы всех программ свёрнутых в трей? [D7, XP]


Adios ©   (2008-03-26 00:52:00) 

сабж


DVM   (2008-03-26 14:55:00) [1]

Да и то место где иконки - это не трей :)


Adios   (2008-03-26 14:36:00) [2]

easy, спасибо! всё работает как надо.


easy   (2008-03-26 12:09:00) [3]

unit Unit1;

interface

uses
 Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
 Dialogs, StdCtrls, CommCtrl, ShellAPI, TlHelp32, ComCtrls;

type
 TForm1 = class(TForm)
   ListView1: TListView;
   procedure FormCreate(Sender: TObject);
 private
   { Private declarations }
 public
   { Public declarations }
 end;

var
 Form1: TForm1;

implementation

{$R *.dfm}

function GetTrayHandle: THandle;
var
 ShellTrayHandle: THandle;
begin
 ShellTrayHandle := FindWindow('Shell_TrayWnd', nil);
 if ShellTrayHandle <> 0 then
   Result := FindWindowEx(ShellTrayHandle, 0, 'TrayNotifyWnd', nil)
 else
   Result := 0;
end;

function FindToolbar(Window: THandle; var ToolbarHandle: THandle): BOOL;
 stdcall;
var
 Buf: array[Byte] of Char;
begin
 GetClassName(Window, Buf, SizeOf(Buf));
  // Set result to false when we have found a toolbar
 Result := StrIComp(Buf, TOOLBARCLASSNAME) <> 0;
 if not Result then
   ToolbarHandle := Window;
end;

function GetToolbarHandle: THandle;
var
 TrayHandle: THandle;
begin
 Result := 0;
 TrayHandle := GetTrayHandle;
 if TrayHandle = 0 then
   Exit;
 EnumChildWindows(TrayHandle, @FindToolbar, Longint(@Result));
end;

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

procedure FindTrayProcess(ListView: TListView);
type
 TExtraData = packed record
   Wnd: THandle;
   uID: UINT;
 end;
var
 ToolbarHandle: THandle;
 ProcessID, pid: DWORD;
 Process: THandle;
 ButtonCount: Integer;
 Data: Pointer;
 Index: Integer;
 BytesRead: DWORD;
 Button: TTBButton;
 ExtraData: TExtraData;
 Res: boolean;
 buff: array[0..127] of char;
 ListItem: TListItem;
begin
 ListView.Clear;
  // The trayicons 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;
 try
    // 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;
   try
     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;

       if IsWindow(ExtraData.Wnd) then
       begin
         GetWindowThreadProcessID(ExtraData.Wnd, @pid);
         GetWindowText(ExtraData.Wnd, buff, sizeof(buff));
         ListItem := ListView.Items.Add;
         ListItem.Caption := inttostr(ExtraData.Wnd);
         ListItem.SubItems.Add(buff);
         ListItem.SubItems.Add(GetExenameForProcessUsingToolhelp32(pid));
       end;
     end;
   finally
     VirtualFreeEx(Process, Data, 0, MEM_RELEASE);
   end;
 finally
   CloseHandle(Process);
 end;
end;

procedure TForm1.FormCreate(Sender: TObject);
var
 NewColumn: TListColumn;
begin
 with ListView1 do
 begin
   ViewStyle := vsReport;
   NewColumn := Columns.Add;
   NewColumn.Caption := 'WndHandle';
   NewColumn.Width := 100;
   NewColumn := Columns.Add;
   NewColumn.Caption := 'WndText';
   NewColumn.Width := 250;
   NewColumn := Columns.Add;
   NewColumn.Caption := 'ExeName';
   NewColumn.Width := 150;
   Align := alClient;
 end;
 FindTrayProcess(ListView1);
end;

end.


Семеныч   (2008-03-26 07:46:00) [4]

> Adios   (26.03.08 01:04) [2]

"Свернуть в трей" - так говорят только для простоты, а вообще-то это выражение неправильное. В действительности трей-программа при запуске:
- создает невидимое окно;
- посылает специальное сообщение пользовательской оболочке системы;
И все. Как видите, ничего никуда не сворачивается.

Отрисовывает иконку оболочка. Она же следит за движениями и щелчками мыши по иконке. Оболочка перенаправляет сообщения мыши невидимому окну программы и то их обрабатывает (показывает меню и пр.). Если надо сменить или удалить  иконку, программа снова посылает оболочке специальное сообщение.

Теперь Вы сами видите, что задали вопрос так, что ответить на него невозможно. В трее нет ни программ, ни окон - и как можно перебрать то, чего нет?

Перебрать все окна в системе - легко (EnumWindows). Определить, какие из них невидимые - тоже легко (IsWindowVisible). Но вот определить, какие из них зарегистрирования в облочке для получения сообщений от иконок (тем более, от конкретной иконки) - это вряд ли получится.


Anatoly Podgoretsky   (2008-03-26 01:58:00) [5]

> Adios  (26.03.2008 01:04:02)  [2]

Окна тоже в трей не сворачиваются


Германн   (2008-03-26 01:29:00) [6]


> Adios   (26.03.08 01:04) [2]
>
> хэндлы есть у окон, и они свёрнуты в трей и я незнаю названия
> окон, как можно перебрать все хендлы окон в трее?

Никакое окно нельзя свернуть в трей.
В трее есть только иконки. И ничего более.

P.S. Ты бы почитал бы книжки. Это полезно. И пригодится в дальнейшем.


Adios   (2008-03-26 01:04:00) [7]

хэндлы есть у окон, и они свёрнуты в трей и я незнаю названия окон, как можно перебрать все хендлы окон в трее?


Германн   (2008-03-26 00:59:00) [8]


> можноли получить хэндлы всех программ свёрнутых в трей?

1. Никакую программу нельзя свернуть в трей!
2. У программ нет хэндлов.
Так об чём вопрос?


Наверх

Титульная страница Поиск, карта сайта Написать письмо