Доступ к и изменение области уведомлений оболочки является хакерским, но возможным. Сначала нужно найти окно верхнего уровня:
var
Wnd: HWND;
begin
Wnd := FindWindow('Shell_TrayWnd', nil);
if IsWindow(Wnd) then
EnumChildWindows(Wnd, @FindTrayWnd, 0);
end;
затем перечислить свои ребенок, чтобы найти область уведомлений панели задач:
function FindTrayWnd(AWnd: HWND; AParam: LPARAM): BOOL; stdcall;
var
ClassName: string;
begin
SetLength(ClassName, 64);
SetLength(ClassName, GetClassName(AWnd, PChar(ClassName), 64));
Result := True;
if AnsiCompareText(ClassName, 'TrayNotifyWnd') = 0 then begin
EnumChildWindows(AWnd, @FindToolbar, 0);
Result := False;
end;
end;
затем перечислить свои ребенок, чтобы найти стандартную панель инструментов для Windows с иконками уведомлений. Сообщения Windows используются для получения или установки свойств панели инструментов. Поскольку панель инструментов живет в другом процессе необходимо использовать ReadProcessMemory()
и WriteProcessMemory()
для всех сообщений, которые вовлекают буфер какой-то (как получить текст кнопки или данные):
function FindToolbar(AWnd: HWND; AParam: LPARAM): BOOL; stdcall;
const
VMFLAGS = PROCESS_VM_OPERATION or PROCESS_VM_READ or PROCESS_VM_WRITE;
var
ClassName: string;
i, ButtonCount: integer;
ProcessId, BytesRead: Cardinal;
ProcessHandle: THandle;
ExplorerButtonInfo: PTBButton;
ButtonInfo: array of TTBButton;
begin
SetLength(ClassName, 64);
SetLength(ClassName, GetClassName(AWnd, PChar(ClassName), 64));
if AnsiCompareText(ClassName, 'ToolbarWindow32') = 0 then begin
GetWindowThreadProcessId(AWnd, @ProcessId);
ProcessHandle := OpenProcess(VMFLAGS, FALSE, ProcessId);
ExplorerButtonInfo := VirtualAllocEx(ProcessHandle, nil, SizeOf(TTBButton),
MEM_RESERVE or MEM_COMMIT, PAGE_READWRITE);
if ExplorerButtonInfo <> nil then try
ButtonCount := SendMessage(AWnd, TB_BUTTONCOUNT, 0, 0);
SetLength(ButtonInfo, ButtonCount);
for i := 0 to ButtonCount - 1 do begin
SendMessage(AWnd, TB_GETBUTTON, i, LPARAM(ExplorerButtonInfo));
ReadProcessMemory(ProcessHandle, ExplorerButtonInfo, @ButtonInfo[i],
SizeOf(TTBButton), BytesRead);
end;
// manipulate the button info, use WriteProcessMemory() and SendMessage()
// to repopulate the toolbar
finally
VirtualFreeEx(ProcessId, ExplorerButtonInfo, SizeOf(TTBButton),
MEM_RELEASE);
end;
Result := False;
end else
Result := True;
end;
Вы должны быть в состоянии идентифицировать кнопку вашего значка уведомления через его имя, затем удалите эту кнопку, а затем вставьте ее в нужную позицию. Вся обработка ошибок опущена, но это должно заставить вас начать.
Каждый раз, когда вы хотите что-то сделать и не можете найти решение в Windows API, вы, вероятно, должны спросить себя, есть ли для этого веские причины, например, это просто не ваш бизнес. Это не точное совпадение, но см. Http://blogs.msdn.com/oldnewthing/archive/2006/11/01/922449.aspx для общей идеи.Возможно, вы должны пересмотреть свои различные причины, чтобы иметь значок в трее. И если причина действительно звучит, просто придумайте хорошую икону и оставьте ее в покое. – mghie
@mghie - Трудно не понимать как тон вашего комментария, так и ссылку, которую вы предоставляете, что вы подразумеваете, что я пытаюсь захватить или вторгаться в некоторые настройки, контролируемые пользователем. Это не тот случай - я пытаюсь помочь пользователю контролировать положение значка, потому что он запросил * его, Windows (XP, в любом случае) не облегчает его напрямую, и я видел, как это было полезно в другом месте. – Jamo
@ Джамо: Извините, я не хотел ничего подразумевать. Интерфейс Windows API огромен и часто имеет несколько способов достижения одного и того же; если нет готового способа добиться чего-то, то это чаще, чем не намеренно. И вы, конечно, не будете вторгаться в некоторые контролируемые пользователем настройки - ваш клиент требует контроля над чем-то, что не предназначено для контроля. – mghie