AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Programmierung allgemein Win32/Win64 API (native code) Delphi Drag&Drop von Dateien auf TrayIcon

Drag&Drop von Dateien auf TrayIcon

Ein Thema von der_kumpel · begonnen am 7. Apr 2008 · letzter Beitrag vom 16. Apr 2008
Antwort Antwort
der_kumpel

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

Drag&Drop von Dateien auf TrayIcon

  Alt 7. Apr 2008, 16:14
Ich führe hier mal eine spezielle Frage zum CoolTrayIcon weiter:

Mein Problem ist, dass ich gerne per Drag&Drop eine Datei
(oder auch mehrere) aus dem Windows-Explorer auf mein TrayIcon
ziehen möchte, damit ich diese analysieren kann.

Auf meine Frage hat toms in diesem Tutorial für das CoolTrayIcon diesen Link gepostet.

Jetzt hab ich aber ein Problem den ganzen Spaß umzusetzen:

Die function auf der Seite, die das WindowHandle sucht,
hab ich glaub ich soweit erfolgreich in Delphi umgesetzt
(war gar nicht so schwer wie ich gedacht hatte ):


Delphi-Quellcode:
function FindTrayHWND: hWnd;
var
  MyhWnd: hWnd;
begin
  MyhWnd:=FindWindow('Shell_TrayWnd', nil);
  if (MyhWnd <> 0) then
    begin
      MyhWnd:=FindWindowEx(MyhWnd, 0, 'TrayNotifyWnd', nil);
      if (MyhWnd <> 0) then
        begin
          MyhWnd:=FindWindowEx(MyhWnd, 0, 'SysPager', nil);
          if (MyhWnd <> 0) then
            begin
              MyhWnd:=FindWindowEx(MyhWnd, 0, 'ToolbarWindow32', nil);
            end;
        end;
    end;
  result:=MyhWnd;
end;
Aber wie gehts jetzt weiter?
  Mit Zitat antworten Zitat
Benutzerbild von toms
toms
(CodeLib-Manager)

Registriert seit: 10. Jun 2002
4.648 Beiträge
 
Delphi XE Professional
 
#2

Re: Drag&Drop von Dateien auf TrayIcon

  Alt 7. Apr 2008, 16:27
Weiter geht's so:

Zitat:
After the window is found, you need to figure out the correct icon. This is done by using the POINT send with the WM_DROPFILES and looping through all icons, which are actually buttons. This way one can figure out on which icon you dropped the files.

Using the code
The code is splitt into 2 files. One exe file that represents the tray icon app and a message hook dll. The dll installs a message hook to catch the WM_DROPFILES message and will check if we dropped anything on our tray icon. Then I send the message to the window that belongs to our tray icon app.
Als nächstes gilt es also, die C-Sourcen zu studieren.
Habe diese mal als Anhang hochgeladen, falls du kein Konto bei codeproject hast.
Angehängte Dateien
Dateityp: zip dragndrop_tray_414.zip (416,6 KB, 13x aufgerufen)
Thomas
  Mit Zitat antworten Zitat
der_kumpel

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

Re: Drag&Drop von Dateien auf TrayIcon

  Alt 7. Apr 2008, 18:54
Danke für deine Mühe, aber da blick ich überhaupt nicht durch.

Ich vermute mal, dass der wichtige Teil in der Drag-Drop.cpp steht,
allerdings versteh ich da kaum was.
  Mit Zitat antworten Zitat
Benutzerbild von toms
toms
(CodeLib-Manager)

Registriert seit: 10. Jun 2002
4.648 Beiträge
 
Delphi XE Professional
 
#4

Re: Drag&Drop von Dateien auf TrayIcon

  Alt 8. Apr 2008, 23:14
Zitat von der_kumpel:
Ich vermute mal, dass der wichtige Teil in der Drag-Drop.cpp steht,
allerdings versteh ich da kaum was.
Genau, dort befindet sich der HOOK.
Ist ein WH_GETMESSAGE Hook.

Probiere mal einige Funktionen zu übersetzen.
Diese sollte nicht allzu schwer sein.

Code:
BOOL FileDroppedAtIcon(const HWND a_hWndOwner, const int a_iButtonID, const PPOINT pPoint)
{
    HWND hWndTray = FindTrayToolbarWindow();

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

    //here we get a handle to tray application process
    HANDLE hTrayProc = OpenProcess(PROCESS_ALL_ACCESS, 0, dwTrayProcessID);
 
    //now we check how many buttons is there - should be more than 0
    int 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.
    LPVOID lpData = VirtualAllocEx(hTrayProc, NULL,
                    sizeof(TBBUTTON), MEM_COMMIT, PAGE_READWRITE);

    BOOL bIconFound = FALSE;

    for(int iButton=0; iButton<iButtonsCount; iButton++)
    {
        //first let's read TBUTTON information
        //about each button in a task bar of tray

        DWORD dwBytesRead = -1;
        TBBUTTON buttonData;
        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(TBBUTTON), &dwBytesRead);

        //let's read extra data of each button:
        //there will be a HWND of the window that
        //created an icon and icon ID
        DWORD dwExtraData[2] = { 0,0 };
        ReadProcessMemory(hTrayProc, (LPVOID)buttonData.dwData,dwExtraData, sizeof(dwExtraData), &dwBytesRead);

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

        if(hWndOfIconOwner != a_hWndOwner || iIconId != a_iButtonID)
        {
            continue;
        }

        //we found our icon - in WinXP it could be hidden - let's check it:
        if( buttonData.fsState & TBSTATE_HIDDEN )
        {
            break;
        }

        //now just ask a tool bar of rectangle of our icon
        RECT rcPosition = {0,0};
        SendMessage(hWndTray, TB_GETITEMRECT, iButton, (LPARAM)lpData);
       // ReadProcessMemory(hTrayProc, lpData, lprcPosition/*&rcPosition*/, sizeof(RECT), &dwBytesRead);
      ReadProcessMemory(hTrayProc, lpData, &rcPosition, sizeof(RECT), &dwBytesRead);

      MapWindowRect(hWndTray,NULL,&rcPosition);

      if (pPoint->x > rcPosition.left && pPoint->x < rcPosition.right &&
         pPoint->y > rcPosition.top && pPoint->y < rcPosition.bottom)
      {
         OutputDebugString("Stuff dropped at our icon...!!!");   

         bIconFound = TRUE;
         break;
      }

        break;
    }

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

    return bIconFound;
}
Thomas
  Mit Zitat antworten Zitat
der_kumpel

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

Re: Drag&Drop von Dateien auf TrayIcon

  Alt 9. Apr 2008, 17: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
Benutzerbild von toms
toms
(CodeLib-Manager)

Registriert seit: 10. Jun 2002
4.648 Beiträge
 
Delphi XE Professional
 
#6

Re: Drag&Drop von Dateien auf TrayIcon

  Alt 12. Apr 2008, 16:01
Bist du inzwischen schon weiter gekommen?
Thomas
  Mit Zitat antworten Zitat
der_kumpel

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

Re: Drag&Drop von Dateien auf TrayIcon

  Alt 16. Apr 2008, 21:11
Nein, bisher leider nicht.

Könntest du mir verraten, welche Funktionen ich aus der Drag-Drop.cpp und der DDHook.cpp genau brauche?
Das mit der .dll hab ich nämlich nicht verstanden: braucht das Programm diese .dll, um den Drop zu erkennen?

Und wie ich die einzelnen Funktionen zusammensetzte hab ich auch noch nicht herausgefunden. Nach welchem Ereignis muss ich den Ausschau halten?
  Mit Zitat antworten Zitat
Themen-Optionen Thema durchsuchen
Thema durchsuchen:

Erweiterte Suche
Ansicht

Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 11:39 Uhr.
Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz