Thema: Delphi Taskleiste aktualisieren

Einzelnen Beitrag anzeigen

endeffects

Registriert seit: 27. Jun 2004
450 Beiträge
 
#3

Re: Taskleiste aktualisieren

  Alt 9. Mär 2007, 12:34
so ich hab dazu eine lösung im netz gefunden,
die ist allerdings nicht ganz unproblematisch.

Delphi-Quellcode:
uses
   CommCtrl, ShellAPI;
...

function TMainForm.RefreshTray: Boolean;
  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;
type
   TExtraData = packed record
     Wnd: THandle;
     uID: UINT;
   end;
var
   ToolbarHandle: THandle;
   ProcessID: DWORD;
   Process: THandle;
   ButtonCount: Integer;
   Data: Pointer;
   Index: Integer;
   BytesRead: DWORD;
   Button: TTBButton;
   ExtraData: TExtraData;
   IconData: TNotifyIconData;
begin
   Result := False;

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

   FillChar(IconData, SizeOf(IconData), #0);
   IconData.cbSize:= SizeOf(IconData);

   // 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
         // First we have to determine if the button with index Index is our
         // button.
         SendMessage(ToolbarHandle, TB_GETBUTTON, Index, Longint(Data));

         // Read the data from the tray process into the current process.
         Result := ReadProcessMemory(Process, Data, @Button, SizeOf(Button), BytesRead) and (BytesRead = SizeOf(Button));
         if not Result then
           Continue;

         // Read the extra data, Button.dwData points to its location
         Result := ReadProcessMemory(Process, Pointer(Button.dwData),
           @ExtraData, SizeOf(ExtraData), BytesRead) and (BytesRead = SizeOf(ExtraData));
         if not Result then
           Continue;

         if not IsWindow(ExtraData.Wnd) then
         begin
           IconData.Wnd:= ExtraData.Wnd;
           IconData.uID:= ExtraData.uID;
           Shell_NotifyIcon(NIM_DELETE, @IconData);
         end;
       end;
     finally
       VirtualFreeEx(Process, Data, 0, MEM_RELEASE);
     end;
   finally
     CloseHandle(Process);
   end;
end;
  Mit Zitat antworten Zitat