Announcement

Collapse
No announcement yet.

Aktivieren durch Mausbewegung, wie?

Collapse
X
  • Filter
  • Time
  • Show
Clear All
new posts

  • Aktivieren durch Mausbewegung, wie?

    Hallo,

    kann mir jemand sagen, wie man ein (eigenes) Programm aktivieren kann, indem man nur die Maus über das Fenster zieht? (Ohne zu klicken). Habe schon SetActiveWindow in Verbindung mit WMNCHitTest probiert, aber ohne Erfolg.

    Vielen Dank

    Uli Becker

  • #2
    Hallo Ulli,<br>neulich habe ich mit den Botschaften CM_MOUSEENTER u. CM_MOUSELEAVE herumgespielt. Sieh Dir mal folgenden Sourcecode an:<br>

    <pre>

    unit Unit1;

    interface

    uses
    Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
    ComCtrls, StdCtrls;

    type
    TForm1 = class(TForm)
    StatusBar1: TStatusBar;
    Label1: TLabel;
    private
    { Private-Deklarationen }
    procedure CMMouseEnter(Var Message : TMessage); message CM_MOUSEENTER;
    procedure CMMouseLeave(Var Message : TMessage); message CM_MOUSELEAVE;
    public
    { Public-Deklarationen }
    end;

    var
    Form1: TForm1;

    implementation

    {$R *.DFM}

    { TForm1 }

    procedure TForm1.CMMouseEnter(var Message: TMessage);
    begin
    StatusBar1.SimpleText:='Maus wieder da';
    SetForeGroundWindow(Handle);
    end;

    procedure TForm1.CMMouseLeave(var Message: TMessage);
    begin
    StatusBar1.SimpleText:='Maus hat Fenster verlassen';
    end;

    end.

    </pre>

    Die CM_MOUSEENTER Botschaft wird scheinbar sicher verarbeitet. Bei CM_MOUSELEAVE gibt's noch Probleme. Solange die Maus beim verlassen des Fensters weder den Rand noch die Caption berührt klappts.<br>:-) Jens Schuman

    Comment


    • #3
      Hallo,

      das Problem hat seine Ursachen in den von Microsoft geänderten Regeln für die Win32-API-Funktion <b>SetForegroundWindow</b>. Das folgende Beispiel demonstriert, wie diese Regeln "umgangen" werden können, indem das Programm eine "erlaubte" Situation simuliert:

      Problem laut Platform-SDK: <br>
      <i>
      Windows 98, Windows 2000: The system restricts which processes can set the foreground window. A process can set the foreground window only if one of the following conditions is true: <br>
      - The process is the foreground process. <br>
      - The process was started by the foreground process.<br>
      - The process received the last input event.<br>
      - There is no foreground process. <br>
      - The foreground process is being debugged.<br>
      - The foreground is not locked (see LockSetForegroundWindow).<br>
      - The foreground lock time-out has expired (see SPI_GETFOREGROUNDLOCKTIMEOUT in SystemParametersInfo).<br>
      - Windows 2000: No menus are active.

      With this change, an application cannot force a window to the
      foreground while the user is working with another window. Instead,
      SetForegroundWindow will activate the window (see SetActiveWindow) and
      call the FlashWindowEx function to notify the user.</i>
      <pre>
      function ForceForegroundWindow(hWnd: THandle): BOOL;
      var
      hCurWnd: THandle;
      begin
      hCurWnd := GetForegroundWindow;
      AttachThreadInput(GetWindowThreadProcessId(hCurWnd , nil),
      GetCurrentThreadId, True);
      Result := SetForegroundWindow(hWnd);
      AttachThreadInput(GetWindowThreadProcessId(hCurWnd , nil),
      GetCurrentThreadId, False);
      end;

      procedure TForm1.FormMouseMove(Sender: TObject; Shift: TShiftState; X,
      Y: Integer);
      begin
      ForceForegroundWindow(Self.Handle);
      end;
      </pre&gt

      Comment


      • #4
        Danke an beide für die Hilfe; MouseLeave funktioniert tatsächlich nicht zuverlässig, MouseEnter immer!
        Die Lösung von Herrn Kosch ist (natürlich) perfekt. Großes Kompliment übrigens für Ihr Buch Win32-Lösungen. Wenn ich nun noch herausbringe, wie man zuverlässig feststellt, wann die Maus das eigene Fenster verlässt, ist das Wochenende gerettet.

        Nochmals Herzlichen Dank..

        Comment


        • #5
          Hallo,

          wenn zur Kontrolle der aktuellen Mausposition ein <b>Hook</b> oder ein <b>Capture</b> nicht in Frage kommt, steht immer noch die klassische Timer-Lösung zur Verfügung:
          <pre>
          procedure TForm1.Timer1Timer(Sender: TObject);
          var
          aPos : TPoint;
          aWnd : HWND;
          begin
          GetCursorPos(aPos);
          aWnd := WindowFromPoint(aPos);
          if aWnd <> Self.Handle then
          begin
          Self.WindowState := wsMinimized;
          Timer1.Enabled := False;
          end;
          end;
          </pre>
          Nicht elegant - aber wirkungsvoll ;-

          Comment


          • #6
            Hallo Herr Kosch,

            so einfach ist das also :-) Da hätte ich auch wirklich selber drauf kommen können. Freut mich aber, zu erfahren, dass auch ein Super-Profi mit Timern arbeitet.

            Danke

            Comment

            Working...
            X