Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Win32/Win64 API (native code) (https://www.delphipraxis.net/17-win32-win64-api-native-code/)
-   -   Delphi Rechtsklick auf TreeView Item in einem Fenster (https://www.delphipraxis.net/98152-rechtsklick-auf-treeview-item-einem-fenster.html)

Die Muhkuh 22. Aug 2007 11:26


Rechtsklick auf TreeView Item in einem Fenster
 
Hi,

ich möchte in einem fremden TreeView auf eine bestimmte Node rechtsklicken. Handle des Fensters bzw. des TreeViews hab ich schon.

Nur hab ich das Problem, dass ich nicht weiß, wie ich auf ein bestimmtes Node (dessen Text mit meinem übereinstimmt) rechtsklicke.

Beispiel: Ich schreib in meinem Programm, dass auf das Node mit dem Text "Test" ein Rechtsklick ausgeführt werden soll. Und genau auf diese Node soll dann im fremden Programm ein Rechtsklick ausgeführt werden.

Wie stellt man sowas am geschicktesten an?

Die Muhkuh 23. Aug 2007 13:01

Re: Rechtsklick auf TreeView Item in einem Fenster
 
*Schubkarre auspack*
*Thread in Schubkarre einlad*
*Mit Schubkarre hochfahren*
*Thread ausladen*

Die Muhkuh 25. Aug 2007 10:24

Re: Rechtsklick auf TreeView Item in einem Fenster
 
*hatschi*

DGL-luke 25. Aug 2007 10:49

Re: Rechtsklick auf TreeView Item in einem Fenster
 
WIndowsmessages? WM_CLICK? WM_MOUSEDOWN?

Die Muhkuh 25. Aug 2007 12:29

Re: Rechtsklick auf TreeView Item in einem Fenster
 
Hi Lukas,

das ist soweit klar. Jedoch muss ich ein bestimmtes Item anklicken, dessen Name mit einem bestimmten Namen übereinstimmt. Das heißt, ich bräuchte erstmal die Koordinaten oder ein Handle zum Senden einer Nachricht.

bitsetter 26. Aug 2007 12:51

Re: Rechtsklick auf TreeView Item in einem Fenster
 
Hi,

mit einer Rekursion könnte man von allen Items den Text und dann die Position auslesen. Mein Lösungsansatz sieht so aus:
Delphi-Quellcode:
procedure TreeItemRect(hTree: THandle);
const
  BufferSize= 1024;
var
  MemL, MemR : Pointer;
  hProc : THandle;

  procedure NextItem(hItem: HTREEITEM; Code: Integer);
  var
    BytesR, BytesW: Cardinal;
    ItemRect, TreeRect: TRect;
  begin
    while Assigned(hItem) do
    begin
      ZeroMemory(MemL, BufferSize);
      PTVItem(MemL)^.hItem:= hItem;
      PTVItem(MemL)^.mask:= TVIF_TEXT or TVIF_CHILDREN;
      PTVItem(MemL)^.pszText:= Pointer(Cardinal(MemR)+ SizeOf(TTvItem)+ SizeOf(TRect));
      PTVItem(MemL)^.cchTextMax:= BufferSize- SizeOf(TTVItem)- SizeOf(TRect);

      HTreeItem(Pointer(Cardinal(MemL)+ SizeOf(TTvItem))^):= hItem;//GETITEMRECT

      if WriteProcessMemory(hProc, MemR, MemL, BufferSize, BytesW)
        and (SendMessage(hTree, TVM_GETITEM, 0, LPARAM(MemR))> 0)
        and ReadProcessMemory(hProc, MemR, MemL, BufferSize, BytesR)
        and (SendMessage(hTree, TVM_GETITEMRECT, Integer(true), Cardinal(MemR)+ SizeOf(TTvItem))> 0)//GETITEMRECT
        and ReadProcessMemory(hProc, Pointer(Cardinal(MemR)+ SizeOf(TTvItem)), Pointer(Cardinal(MemL)+ SizeOf(TTvItem)), SizeOf(TRect), BytesR) then
        begin
          ItemRect:= PRect(Cardinal(MemL)+ SizeOf(TTvItem))^;
          if PChar(Cardinal(MemL) + SizeOf(TTVItem)+ SizeOf(TRect))= 'Arbeitsplatz' then
          begin
             windows.GetWindowRect(hTree, TreeRect);
             SetCursorPos(TreeRect.Left+ (ItemRect.Right+ ItemRect.Left) div 2, TreeRect.Top+ (ItemRect.Bottom+ ItemRect.Top) div 2);
             mouse_event(MOUSEEVENTF_RIGHTDOWN, 0, 0, 0, 0);
             mouse_event(MOUSEEVENTF_RIGHTUP, 0, 0, 0, 0);
          end;
          //Form1.ListBox1.Items.Add(format('Text= %s Left= %d Top= %d', [PChar(Cardinal(MemL) + SizeOf(TTVItem)+ SizeOf(TRect)), ItemRect.Left, ItemRect.Top]) );
        end;
      NextItem(Treeview_GetNextItem(hTree, hItem, TVGN_CHILD), 0);
      hItem := TreeView_GetNextItem(hTree, hItem, TVGN_NEXT);
    end;
  end;

var
  ProcessId: DWORD;
  hTVItem: HTREEITEM;
begin
  GetWindowThreadProcessId(hTree, @ProcessId);
  hProc := OpenProcess(PROCESS_ALL_ACCESS, False, ProcessId);
  if hProc > 0 then
  try
    MemL:= VirtualAlloc(nil, BufferSize, MEM_COMMIT, PAGE_READWRITE);
    MemR:= VirtualAllocEx(hProc, nil, BufferSize, MEM_COMMIT, PAGE_READWRITE);
    try
      if Assigned(MemL) and Assigned(MemR) then
      begin
        hTVItem:= TreeView_GetRoot(hTree);
        NextItem(hTVItem, 0);
      end;
    finally
      if Assigned(MemR) then
        VirtualFreeEx(hProc, MemR, 0, MEM_RELEASE);
      if Assigned(MemL) then
        VirtualFree(MemL, 0, MEM_RELEASE);
    end;
  finally
    CloseHandle(hProc);
  end;
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
  sleep(2000);
  TreeItemRect(...);
end;
Wie zu sehen ist funktioniert dieser Code nur auf Windows NT 32-Bit Systemen.
Getestet habe ich das Ganze mit dem Windows Explorer unter Windows XP. Es wird dort ein Rechtsklick auf das Item Arbeitsplatz durchgeführt.

EDIT: Der Code wurde noch etwas überarbeitet.

Die Muhkuh 26. Aug 2007 12:53

Re: Rechtsklick auf TreeView Item in einem Fenster
 
Wow, das schau ich mir später mal an. Erstmal den Source verstehen :D

Die Muhkuh 27. Aug 2007 16:20

Re: Rechtsklick auf TreeView Item in einem Fenster
 
Hi bitsetter,

funktioniert an sich ganz gut. Jedoch, sobald viele Items da sind und gescrollt werden muss, funktioniert das ganze nicht mehr. Da werde ich wohl erst noch runterscrollen müssen.

[edit] Nach dem Scrollen funktioniert es wieder 1a. Danke vielmals :)[/edit]

bitsetter 30. Aug 2007 21:36

Re: Rechtsklick auf TreeView Item in einem Fenster
 
Zitat:

Zitat von Die Muhkuh
Da werde ich wohl erst noch runterscrollen müssen.

[edit] Nach dem Scrollen funktioniert es wieder 1a. Danke vielmals :)[/edit]

Hi,

du könntest auch das gesuchte Item als TopItem setzen, dann kurz warten und erst danach die Position des Items abfragen. Um das Item als TopItem zu setzen könntest du den Code so abändern:
Delphi-Quellcode:
        ...
        and ReadProcessMemory(hProc, Pointer(Cardinal(MemR)+ SizeOf(TTvItem)), Pointer(Cardinal(MemL)+ SizeOf(TTvItem)), SizeOf(TRect), BytesR) then
        begin
          ItemRect:= PRect(Cardinal(MemL)+ SizeOf(TTvItem))^;
          if PChar(Cardinal(MemL) + SizeOf(TTVItem)+ SizeOf(TRect))= 'Arbeitsplatz' then
          begin
             SendMessage(hTree, TVM_SELECTITEM, TVGN_FIRSTVISIBLE, Cardinal(hItem));//als TopItem setzen

             (*windows.GetWindowRect(hTree, TreeRect);
             SetCursorPos(TreeRect.Left+ (ItemRect.Right+ ItemRect.Left) div 2,TreeRect.Top+ (ItemRect.Bottom+ ItemRect.Top) div 2);
             mouse_event(MOUSEEVENTF_RIGHTDOWN, 0, 0, 0, 0);
             mouse_event(MOUSEEVENTF_RIGHTUP, 0, 0, 0, 0); *)
          end;
          ...
Damit wird praktisch automatisch auf die richtige Position gescrollt. Getestet mit dem Windows Explorer unter Windows XP.

Die Muhkuh 30. Aug 2007 21:46

Re: Rechtsklick auf TreeView Item in einem Fenster
 
Hi,

danke, aber ich komme mit meinem Scrollen auch gut zurande :-)

Was allerdings noch bleibt, ist dass z.B. bei zwei gleichnamigen SubItems das richtige aufgerufen wird. Aber da hab ich schon eine Idee, muss sie nur noch umsetzen :)


Alle Zeitangaben in WEZ +1. Es ist jetzt 01:48 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