AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Programmierung allgemein Win32/Win64 API (native code) Delphi Handle einer Form aus Taskbareintrag erhalten
Thema durchsuchen
Ansicht
Themen-Optionen

Handle einer Form aus Taskbareintrag erhalten

Ein Thema von Mazel · begonnen am 22. Apr 2007 · letzter Beitrag vom 25. Apr 2007
Antwort Antwort
Seite 2 von 3     12 3      
Benutzerbild von toms
toms
(CodeLib-Manager)

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

Re: Handle einer Form aus Taskbareintrag erhalten

  Alt 22. Apr 2007, 19:11
Habe den Code nochmals ueberarbeitet aber es wird nicht ein korrektes Windowhandle
zurueck gegeben. Irgendwo scheint noch ein Fehler in der Uebersetzung zu sein.
Thomas
  Mit Zitat antworten Zitat
Benutzerbild von toms
toms
(CodeLib-Manager)

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

Re: Handle einer Form aus Taskbareintrag erhalten

  Alt 22. Apr 2007, 20:29
Vielleicht kann ja mal jemand den C Code ausfueheren und berichten, ob er funktioniert.
Thomas
  Mit Zitat antworten Zitat
Benutzerbild von Mazel
Mazel

Registriert seit: 11. Nov 2005
Ort: Leipzig
831 Beiträge
 
#13

Re: Handle einer Form aus Taskbareintrag erhalten

  Alt 23. Apr 2007, 12:52
Das wär natürlich eine Idee.

Ich habe jetzt mal beide Codes zusammengefügt, da mir aufgefallen ist, dass mehrere Fragmente in beiden wiederholt werden, im Ergebnis hat sich nichts geändert: es wird immernoch ein Wert ausgegeben, kein Wnd-Handle ist.
Delphi-Quellcode:
{--[TaskbarEntry]--------------------------------------------------------------}

procedure TaskbarEntry;
var
 Pos : TPoint;
 // variables that needed to open taskbar (explorer) process
 TaskbarPID : DWORD; // TaskbarProcessID
 TaskbarPHandle : THandle; // TaskbarProcessHandle
 // variable that helds pointer to a remote buffer in taskbar process
 TaskbarPBuffer : Pointer; // TaskbarProcessBuffer
 lpPoint : Pointer;
 NumBytes : DWORD;
 ButtonIndex : Integer;
 tbButton : TTBButton;
 PtbButton : Pointer;
 dwBytesRead : DWORD;
 lpRemoteData : Pointer;
 localBuffer : array[0..BUFFER_SIZE - 1] of Byte;
 pLocalBuffer : ^Byte;
 ipLocalBuffer : Pointer;
 Wnd : HWND;

begin
 GetCursorPos(Pos);
 Windows.ScreenToClient(Main.TBHandle, Pos);
 TaskbarPID := 0;
 ButtonIndex := 0;
 // Main.TBHandle ist Taskbarhandle, welches beim Start der Anwendung ermittelt wird
 GetWindowThreadProcessId(Main.TBHandle, @TaskbarPID);
 TaskbarPHandle := OpenProcess(PROCESS_ALL_ACCESS, False, TaskbarPID);
 If TaskbarPHandle <> 0 then
  try
   lpPoint := VirtualAllocEx(TaskbarPHandle, nil, SizeOf(TPoint), MEM_RESERVE or MEM_COMMIT, PAGE_READWRITE);
   NumBytes := 0;
   WriteProcessMemory(TaskbarPHandle, lpPoint, @Pos, SizeOf(TPoint), NumBytes);
   // Index ermittlen
   ButtonIndex := SendMessage(Main.TBHandle, TB_HITTEST, 0, Integer(lpPoint));
   If Assigned(lpPoint) then VirtualFreeEx(TaskbarPHandle, lpPoint, 0, MEM_RELEASE);
  finally
   CloseHandle(TaskbarPHandle);
  end;
 TaskbarPID := 0;
 GetWindowThreadProcessId(Main.TBHandle, @TaskbarPID);
 TaskbarPHandle := OpenProcess(PROCESS_ALL_ACCESS, False, TaskbarPID);
 If TaskbarPHandle <> 0 then
  try
   // allocate space for remote buffer in taskbar process
   TaskbarPBuffer := VirtualAllocEx(TaskbarPHandle, nil, BUFFER_SIZE, MEM_COMMIT, PAGE_READWRITE);
   If Assigned(TaskbarPBuffer) then
    begin
     // declare and prepare variables that will held data
     // about PRESSED button in a taskbar
     PtbButton := @tbButton;
     // Now, retrieve information about the PRESSED button in a taskbar / data is placed in remote buffer
     SendMessage(Main.TBHandle, TB_GETBUTTON, ButtonIndex, Integer(TaskbarPBuffer));
     // And now, the remote data about PRESSED button is transferred to a local variable
     dwBytesRead := 0;
     ReadProcessMemory(TaskbarPHandle, TaskbarPBuffer, PtbButton, SizeOf(TBButton), dwBytesRead);
     // the window handle is in dwData field of TBBUTTON structure (the first 4 bytes)
     pLocalBuffer := @localBuffer[0];
     ipLocalBuffer := pLocalBuffer;
     // initialize remote buffer
     lpRemoteData := @tbButton.dwData;
     // and read the dwData fields of a TBBUTTON from remote process
     dwBytesRead := 0;
     ReadProcessMemory(TaskbarPHandle, lpRemoteData, ipLocalBuffer, SizeOf(Pointer), dwBytesRead);
     // obtain window handle, copy first 4 bytes
     Move(ipLocalBuffer^, Wnd, 4);
     If Assigned(TaskbarPBuffer) then VirtualFreeEx(TaskbarPHandle, TaskbarPBuffer, 0, MEM_RELEASE);
    end;
  finally
   CloseHandle(TaskbarPHandle);
  end;
 Main.Caption := inttostr(Wnd);
end;
Marcel Jänicke
www.mj-software.net
  Mit Zitat antworten Zitat
Benutzerbild von DGL-luke
DGL-luke

Registriert seit: 1. Apr 2005
Ort: Bad Tölz
4.149 Beiträge
 
Delphi 2006 Professional
 
#14

Re: Handle einer Form aus Taskbareintrag erhalten

  Alt 23. Apr 2007, 16:48
Hallo,

könnte das sein, dass du mit deine Pointern bisschen mehr aufpassen musst?

Move(ipLocalBuffer^, Wnd, 4);
Lukas Erlacher
Suche Grafiktablett. Spenden/Gebrauchtangebote willkommen.
Gotteskrieger gesucht!
For it is the chief characteristic of the religion of science that it works. - Isaac Asimov, Foundation I, Buch 1
  Mit Zitat antworten Zitat
Benutzerbild von Mazel
Mazel

Registriert seit: 11. Nov 2005
Ort: Leipzig
831 Beiträge
 
#15

Re: Handle einer Form aus Taskbareintrag erhalten

  Alt 23. Apr 2007, 17:02
Ich habe eben den Code nochmal überarbeitet und deine Änderung mit eingebunden. Nun kommt allerdings 0 als Wnd heraus.

Wo steckt der Fehler?

Gruß
Mazel
Marcel Jänicke
www.mj-software.net
  Mit Zitat antworten Zitat
Benutzerbild von toms
toms
(CodeLib-Manager)

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

Re: Handle einer Form aus Taskbareintrag erhalten

  Alt 23. Apr 2007, 19:06
Dieser Code kommt immer noch doppelt vor:

Delphi-Quellcode:
TaskbarPID := 0;
GetWindowThreadProcessId(Main.TBHandle, @TaskbarPID);
TaskbarPHandle := OpenProcess(PROCESS_ALL_ACCESS, False, TaskbarPID);
//...

VirtualAllocEx(TaskbarPHandle, nil,...)
Thomas
  Mit Zitat antworten Zitat
Benutzerbild von toms
toms
(CodeLib-Manager)

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

Re: Handle einer Form aus Taskbareintrag erhalten

  Alt 23. Apr 2007, 20:23
Habe den Code noch etwas abgeaendert und ueberarbeitet und funktioniert nun bei mir:


Delphi-Quellcode:
//Get the Taskbar handle
function getTaskbarHWND: HWND;
var
  ShellTrayWnd: HWnd;
  ReBarWindow32: HWnd;
  MSTaskSwWClass: HWnd;
begin
  Result := 0;
  ShellTrayWnd := FindWindow('Shell_TrayWnd', nil);
  if ShellTrayWnd <> 0 then
  begin
    ReBarWindow32 := FindWindowEx(ShellTrayWnd, 0, 'ReBarWindow32', nil);
    if ReBarWindow32 <> 0 then
    begin
      MSTaskSwWClass := FindWindowEx(ReBarWindow32, 0, 'MSTaskSwWClass', nil);
      if MSTaskSwWClass <> 0 then
        Result := FindWindowEx(MSTaskSwWClass, 0, 'ToolbarWindow32', nil);
    end;
  end;
end;
Delphi-Quellcode:
type
  TExtraData = packed record
    Wnd: THandle;
    uID: UINT;
  end;

// Retrieve the window handle at the cursor position

function GetWinHandleFromTBButton(hwndTaskbar: HWND; pt: TPoint): HWND;
const
  BUFFER_SIZE = $1000;
var
  taskbarProcessID: DWORD;
  taskbarProcessHandle: THandle;
  pTaskbarProcessBuffer: Pointer;
  dwBytesRead: DWORD;
  Button: TTBButton;
  ExtraData: TExtraData;
  lpPoint: Pointer;
  ButtonIndex: Integer;
begin
  Result := 0;
  if hwndTaskbar <> 0 then
  begin
    // obtain taskbar process id - by window
    GetWindowThreadProcessId(hwndTaskbar, @taskbarProcessID);
    // open taskbar process
    taskbarProcessHandle := OpenProcess(PROCESS_ALL_ACCESS, False, taskbarProcessID);
    if taskbarProcessHandle <> 0 then
    try
      // allocate space for remote buffer in taskbar process
      lpPoint := VirtualAllocEx(taskbarProcessHandle, nil, SizeOf(TPoint), MEM_RESERVE or MEM_COMMIT, PAGE_READWRITE);
      dwBytesRead := 0;
      WriteProcessMemory(taskbarProcessHandle, lpPoint, @pt, SizeOf(TPOINT), dwBytesRead);
      // Get the Button Index
      ButtonIndex := SendMessage(hwndTaskbar, TB_HITTEST, 0, Integer(lpPoint));
      if Assigned(lpPoint) then
        VirtualFreeEx(taskbarProcessHandle, lpPoint, 0, MEM_RELEASE);
      if ButtonIndex > 0 then
      begin
        // allocate space for remote buffer in taskbar process
        pTaskbarProcessBuffer := VirtualAllocEx(taskbarProcessHandle, nil, BUFFER_SIZE, MEM_COMMIT, PAGE_READWRITE);
        if Assigned(pTaskbarProcessBuffer) then
        begin
          // Retrieve information about the button in the taskbar / data is placed in remote buffer
          SendMessage(hwndTaskbar, TB_GETBUTTON, ButtonIndex, Integer(pTaskbarProcessBuffer));
          // Read the data from the Taskbar process into the current process.
          if ReadProcessMemory(taskbarProcessHandle, pTaskbarProcessBuffer, @Button, SizeOf(Button), dwBytesRead)
            and (dwBytesRead = SizeOf(Button)) then
            // Read the extra data, Button.dwData points to its location
            if ReadProcessMemory(taskbarProcessHandle, Pointer(Button.dwData),
              @ExtraData, SizeOf(ExtraData), dwBytesRead) and (dwBytesRead = SizeOf(ExtraData)) then
              Result := ExtraData.Wnd;
          if Assigned(pTaskbarProcessBuffer) then
            VirtualFreeEx(taskbarProcessHandle, pTaskbarProcessBuffer, 0, MEM_RELEASE);
        end;
      end;
    finally
      CloseHandle(taskbarProcessHandle);
    end;
  end;
end;

Testen:

Delphi-Quellcode:
var
  pt: TPOINT;
  TaskbarHWND, windowHandle: HWND;
begin
  TaskbarHWND := getTaskbarHWND;
  GetCursorPos(pt);
  if (WindowFromPoint(pt) <> TaskbarHWND) then Exit;
  Windows.ScreenToClient(TaskbarHWND, pt);
  windowHandle := GetWinHandleFromTBButton(getTaskbarHWND, pt);
Thomas
  Mit Zitat antworten Zitat
Benutzerbild von Mazel
Mazel

Registriert seit: 11. Nov 2005
Ort: Leipzig
831 Beiträge
 
#18

Re: Handle einer Form aus Taskbareintrag erhalten

  Alt 24. Apr 2007, 19:02
Hallo,

der Code funktioniert, wirklich super. Ich danke dir, du hast dir echt Mühe gegeben. Ohne dich hätte ich das nicht hinbekommen.

Ich habe immer wieder versucht ein paar Änderungen vorzunehmen, aber es kam zu keinem Erfolg. Zudem habe ich versucht den C Code zu verstehen und ihn dann in Delphi umzusetzten, aber die Sache mit den Pointer in C habe ich überhaupt nicht verstanden. Mal wurde es so und mal so grmacht.

Nochmals vielen Danke, auch an DGL-luke.

Nun aber eine Frage:

Wozu ist ExtraData da? In dem einen Thema wurde es verwendet, in diesem hier und in den Code davor nicht.

Gruß
Mazel
Marcel Jänicke
www.mj-software.net
  Mit Zitat antworten Zitat
Benutzerbild von toms
toms
(CodeLib-Manager)

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

Re: Handle einer Form aus Taskbareintrag erhalten

  Alt 25. Apr 2007, 06:16
Zitat von Mazel:
Hallo,

der Code funktioniert, wirklich super. Ich danke dir, du hast dir echt Mühe gegeben. Ohne dich hätte ich das nicht hinbekommen.
Was hast du den vor mit dem Code? Erstellst du ein spezielles Programm? *michwundernimmt*

Zitat:
Nun aber eine Frage:

Wozu ist ExtraData da? In dem einen Thema wurde es verwendet, in diesem hier und in den Code davor nicht.

Mazel
ExtraData ist eine "Hilfs-Struktur" zum Auslesen des Handels aus Button.dwData.
Die ersten 4 Bytes enthaelt ja das Handle.
Im obigen Code wird es mit move gemacht "// obtain window handle, copy first 4 bytes",

Da THandle 32 Bit hat (= 4 Byte), wird das Handle dann direkt in das ExtraData.Wnd kopiert.
Thomas
  Mit Zitat antworten Zitat
Benutzerbild von Mazel
Mazel

Registriert seit: 11. Nov 2005
Ort: Leipzig
831 Beiträge
 
#20

Re: Handle einer Form aus Taskbareintrag erhalten

  Alt 25. Apr 2007, 13:32
Zitat:
Was hast du den vor mit dem Code? Erstellst du ein spezielles Programm? *michwundernimmt*
Ich habe ein Programm, welches sich WiVi (Window Visibility) nennt. Dieses macht Fenster durchsichtig zu einem selbstgewählten Grad. Nun wollte der "Idee-Schöpfer" eine Erweiterung: wenn man auf den Button in der Taskleiste klickt soll jenes Fenster geschlossen werden.
Wenn du möchtest, kann ich dir die fertige erweiteret Version senden.

Warum hast du das dann mit ExtraData gemacht, wenn es auch mit Move() geht? Oder ging es doch nicht so einfach?

Gruß
Mazel
Marcel Jänicke
www.mj-software.net
  Mit Zitat antworten Zitat
Antwort Antwort
Seite 2 von 3     12 3      


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 13:20 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