Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   GUI-Design mit VCL / FireMonkey / Common Controls (https://www.delphipraxis.net/18-gui-design-mit-vcl-firemonkey-common-controls/)
-   -   Control unter dem Mauszeiger ermitteln und Scrollevent an dieses weiterleiten (https://www.delphipraxis.net/153002-control-unter-dem-mauszeiger-ermitteln-und-scrollevent-dieses-weiterleiten.html)

Exceeder 16. Jul 2010 12:49

Control unter dem Mauszeiger ermitteln und Scrollevent an dieses weiterleiten
 
Hallo,

ich möchte gerne das Scrollverhalten meiner Anwendung ändern. Unter Windows ist es ja normalerweise so, dass immer das Fenster gescrollt wird, was aktuell den Fokus hat. Ich möchte aber, dass dort gescrollt wird, wo sich der Mauscursor befindet.

Ich habe mich dazu an das Application.OnMessage Event gehangen und die Botschaft WM_MOUSEWHEEL abgefangen. In der Routine soll das aktuelle Control (nicht nur das Fenster) des Mauscursors ermittelt werden. Das Fenster bekomme ich hin, allerdings weiß ich nicht, wie die entsprechende API-Funktion aussieht, welche auch das Control ermittelt.

Hier mein Quelltext:

Delphi-Quellcode:
procedure TMainForm.MessageHandler(var Msg: TMsg; var Handled: Boolean);
var
  Handle: HWND;

begin
  if Msg.message = WM_MOUSEWHEEL then
  begin
    Handle := WindowFromPoint(Msg.pt);

    if Handle <> 0 then
    begin
      Handle := ChildWindowFromPoint(Handle, Msg.pt);

      if (Handle <> 0) and (Handle <> Msg.hwnd) then
      begin
        PostMessage(Handle, WM_MOUSEWHEEL, Msg.wParam, Msg.lParam);
        Handled := True;
      end;
    end;
  end;
end;
Leider liefert ChildWindowFromPoint auf Basis des übergebenen Handels wieder das selbe Handle zurück, welches ich reingegeben habe. Was mache ich falsch? Msg.pt scheint Screen-Koordinaten zu enthalten.

himitsu 16. Jul 2010 13:04

AW: Control unter dem Mauszeiger ermitteln und Scrollevent an dieses weiterleiten
 
Delphi-Quellcode:
procedure TForm1.MessageHandler(var Msg: TMsg; var Handled: Boolean);
var
  Handle: HWND;
begin
  if Msg.message = WM_MOUSEWHEEL then
  begin
    Handle := WindowFromPoint(Msg.pt);
    if (Handle <> 0) and (Handle <> Msg.hwnd) then
    begin
      PostMessage(Handle, WM_MOUSEWHEEL, Msg.wParam, Msg.lParam);
      Handled := True;
    end;
  end;
end;


Application.OnMessage := MessageHandler;
Weniger ist manchmal mehr :mrgreen:

Exceeder 16. Jul 2010 13:24

AW: Control unter dem Mauszeiger ermitteln und Scrollevent an dieses weiterleiten
 
Hallo,

so funktioniert es aber leider nicht. Ich habe das Gefühl es wird tatsächlich immer das umgebende Fenster zurück gegeben. Ein Scrollevent wird an die entsprechenden Controls leider nicht gesendet.

Ich vermute fast, das liegt an der Komplexität des Projekts oder an irgendeiner verwendeten Komponente. Wenn ich mir ein kleines Beispielprojekt mit zwei TMemos mache, funktionieren beide Quelltexte. Wobei meiner in der Tat etwas zu viel macht.

himitsu 16. Jul 2010 14:04

AW: Control unter dem Mauszeiger ermitteln und Scrollevent an dieses weiterleiten
 
Um was für Controls handelt es sich denn bei dir?

Eventuell könnte man auch mal mit SendMessage arbeiten, den Result auswerten und bei FALSE/0 mit dem Parent des Controls weitermachen? :gruebel:

[add]
Delphi-Quellcode:
procedure TForm5.MessageHandler(var Msg: TMsg; var Handled: Boolean);
var
  H, H2: HWND;
begin
  if Msg.message = WM_MOUSEWHEEL then
  begin
    H := WindowFromPoint(Msg.pt);
    H2 := H;
    while H2 <> 0 do
    begin
      if H2 = Msg.hwnd then Exit;
      H2 := GetParent(H2);
    end;
    while H <> 0 do
      if SendMessage(H, WM_MOUSEWHEEL, Msg.wParam, Msg.lParam) <> 0 then
      begin
        Handled := True;
        Exit;
      end else H := GetParent(H);
  end;
end;

Exceeder 17. Jul 2010 00:12

AW: Control unter dem Mauszeiger ermitteln und Scrollevent an dieses weiterleiten
 
Hallo,

die Idee hört sich gut an. Möglicherweise hilft das tatsächlich weiter. In der Anwendung werden unter anderem die VCL-Controls von der Firma DevExpress verwendet.

Ich werde auf meiner Testanwendung mal weiterforschen und schauen, was ich tun muss, damit es da auch nicht mehr funktioniert. Das mit dem Parent könnte aber durchaus sein, weil die Control von DevExpress großteils die normalen VCL-Controls/Windows Controls nochmal kapseln. Im Prinzip wird z.B. bei einem Edit oder einer ComboBox alles an Rahmen abgeschaltet. Der wird dann von den Control wieder außenrum gezeichnet.

Eine Sache ist aber dennoch merkwürdig: Wenn ich im MessageHandler die Botschaften WM_MOUSEWHEEL, WM_VSCROLL und WM_HSCROLL abfange (also Handled auf True setze) und gleichzeitig einfach mal ein Beep ausgebe, so Beept es, aber das fokusierte Control erhält trotzdem noch die Scrollevents. Irgendwas ist das definitiv im Busch. Wie kann sowas sein? Ich hab nen Hooking für die WindowProc vieler Controls, aber auch wenn ich das abschalte, bleibt das Problem bestehen. Noch eine Idee zu dem Problem? Vielleicht ist das auch die Ursache dafür, dass es nicht richtig funktioniert.


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