Einzelnen Beitrag anzeigen

der_kumpel

Registriert seit: 30. Jun 2007
42 Beiträge
 
#5

Re: Drag&Drop von Dateien auf TrayIcon

  Alt 9. Apr 2008, 16:55
Hui, das war vielleicht ein Akt. Und so alles verstanden hab ich auch noch nicht, manches konnte man ja auch simpel übernehmen...

Delphi-Quellcode:
function FileDroppedAtIcon(const a_hWndOwner: HWND; const a_iButtonID: integer; const PPoint: TPoint): boolean;
var
  hWndTray, hWndOfIconOwner: HWND;
  dwTrayProcessID, dwBytesRead: DWORD;
  hTrayProc: THandle;
  iButtonsCount, iButton, iIconId: integer;
  lpData: Pointer;
  buttonData: TTBBUTTON;
  bIconFound: BOOL;
  dwExtraData: array[0..1] of DWORD;
  rcPosition: TRect;
begin
  hWndTray:=FindTrayHWND; {FindTrayHWND s.o.}

  //now we have to get an ID of the parent process for system tray
  dwTrayProcessID:=DWORD(-1);
  GetWindowThreadProcessId(hWndTray, dwTrayProcessID);

  //here we get a handle to tray application process
  hTrayProc:=OpenProcess(PROCESS_ALL_ACCESS, false, dwTrayProcessID);

  //now we check how many buttons is there - should be more than 0
  iButtonsCount:=SendMessage(hWndTray, TB_BUTTONCOUNT, 0, 0);

  //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.
  //We allocate sizeof(TBBUTTON) bytes of memory -
  //because TBBUTTON is the biggest structure we will fetch.
  //But this buffer will be also used to get smaller
  //pieces of data like RECT structures.
  lpData:=VirtualAllocEx(hTrayProc, nil, SizeOf(TTBBUTTON), MEM_COMMIT, PAGE_READWRITE);

  bIconFound:=false;

  for iButton := 0 to iButtonsCount - 1 do
    begin
      //first let's read TBUTTON information
      //about each button in a task bar of tray
      dwBytesRead:=DWORD(-1);
      SendMessage(hWndTray, TB_GETBUTTON, iButton, LPARAM(lpData));

      //we filled lpData with details of iButton icon of toolbar
      //- now let's copy this data from tray application
      //back to our process
      ReadProcessMemory(hTrayProc, lpData, @buttonData, SizeOf(TTBBUTTON), dwBytesRead);

      //let's read extra data of each button:
      //there will be a HWND of the window that
      //created an icon and icon ID
      dwExtraData[0] := 0;
      dwExtraData[1] := 0;

      ReadProcessMemory(hTrayProc, Pointer(buttonData.dwData), @dwExtraData, SizeOf(dwExtraData), dwBytesRead);

      hWndOfIconOwner:=HWND(dwExtraData[0]);
      iIconId:=Integer(dwExtraData[1]);

      if (hWndOfIconOwner <> a_hWndOwner) or (iIconId <> a_iButtonID) then
        begin
          Continue; {sollte man hier nicht lieber den nachfolgenden Code
                      reinschreiben, anstatt eine if Abfrage später auf
                      Break zu prüfen?}

        end;

      //we found our icon - in WinXP it could be hidden - let's check it:
      if (buttonData.fsState and TBSTATE_HIDDEN) > 0 then
        begin
          Break;
        end;

      //now just ask a tool bar of rectangle of our icon
      SendMessage(hWndTray, TB_GETITEMRECT, iButton, LPARAM(lpData));
      ReadProcessMemory(hTrayProc, lpData, @rcPosition, SizeOf(TRECT), dwBytesRead);

      MapWindowPoints(hWndTray, 0, rcPosition, 2);

      if (PPoint.X > rcPosition.Left) and (PPoint.X < rcPosition.Right) and
         (PPoint.Y > rcPosition.Top) and (PPoint.Y < rcPosition.Bottom) then
        begin
          //stuff dropped at our icon
          bIconFound:=true;
          Break;
        end;
    end;

  VirtualFreeEx(hTrayProc, lpData, 0, MEM_RELEASE);
  CloseHandle(hTrayProc);

  result:=bIconFound;
end;
Vermutung: Könnte man nicht jetzt schon die procedure WMDropFiles(var Msg: TMessage); Message WM_DropFiles; einsetzen? Da man ja weiß, dass etwas gedroppt wurde, braucht man doch jetzt nur noch die Pfade der gedropten Datei(en).

Btw, ist das erste Mal, dass ich so windowsnah unterwegs bin.
  Mit Zitat antworten Zitat