2010-02-21 11 views
5

Ich frage mich, ob jemand Einblick geben könnte, wie man die Fensterauswahl in Winspector Spy implementiert. Grundsätzlich würde ich ein Panel zur Verfügung stellen, auf das ich mit der Maus klicken, in ein anderes Prozessfenster (oder Unterfenster) ziehen und etwas wie das HWND daraus herausholen könnte. Im Idealfall würde ich dies in C# tun, aber wenn es nur durch das Umschließen der C-APIs möglich ist, kann ich es einfach in C++ tun.Drag and Drop wie Winspector Spy

Ich habe mich mit dem DragDrop-Ereignis herumgetrieben und DoDragDrop mit der Maus in C# aufgerufen, war mir aber nicht wirklich sicher, ob das mir geben könnte, was ich will. Ist es einfacher, die globale X/Y-Position der Maus zu erhalten und das oberste Fenster an dieser Stelle zu finden? Gibt es eine API, die das automatisch bei x, y Parametern macht?

EDIT: entdeckt gerade WindowFromPoint für die letztere Frage

Antwort

5

Sie erhalten normalerweise keine Mausnachrichten, wenn sich die Maus nicht über Ihrem Fenster befindet. Aber Sie müssen, um Drag-and-Drop-Operationen durchzuführen. Windows bietet also einen Mechanismus namens Mauserfassung. Um zu verhindern, dass die Mausübernahme missbraucht wird, können Sie die Maus nur über eine Schaltfläche mit der Tastenbelegung erfassen. Sobald Sie die Erfassung abgeschlossen haben, erhalten Sie Mausbewegungsmeldungen unabhängig davon, wo sich die Maus befindet, bis Sie die Aufzeichnung freigeben oder Windows die entsprechende Meldung anzeigt.

Der C++ Code für diese sieht so etwas wie dieses

case WM_LBUTTONDOWN: 
    { 
    SetCapture(hwnd); 
    } 
    break; 

case WM_MOUSEMOVE: 
    if (GetCapture() == hwnd) 
     { 
     POINT pt = {GET_MOUSE_X(lParam), GET_MOUSE_Y(lParam)); 
     ClientToScreen(hwnd, &pt); 
     HWND hwndAtPoint = WindowFromPoint(pt); 
     // Show info for hwndAtPoint.... 
     } 
    break; 

    case WM_LBUTTONUP: 
    if (GetCapture() == hwnd) 
     { 
     ReleaseCapture(); 
     } 
    break; 

    case WM_CANCELMODE: 
    // this is a request from Windows that leave my modal state 
    if (GetCapture() == hwnd) 
     ReleaseCapture(hwnd); 
    break; 

    case WM_CAPTURECHANGED: 
    // notification that I lost capture (I released it or it was taken from me) 
    break;  

Die GetAncestor Funktion kann hilfreich sein, aus dem Fenster auf den Punkt zu gehen, auf der obersten Ebene Fenster, das sie besitzen. GetWindow kann verwendet werden, um den Fensterbaum herumzugehen.

In .NET hat die Control-Klasse eine Capture-Eigenschaft, die die gleiche Sache sehen tut http://msdn.microsoft.com/en-us/library/system.windows.forms.control.capture.aspx

+0

Das war großartig - vielen Dank. –

0

Importe: using System.Runtime.InteropServices;

Mein Vorschlag, wenn die Maus auf Ihrem Formular ist, behandeln die Maus bewegen/mouse up Ereignisse (Um die Maus außerhalb des Formulars mit einem Windows-Haken zu erfassen, schauen Sie hier: http://support.microsoft.com/kb/318804), und wenn die Maustaste losgelassen wird erhalten, auf dem Bildschirm die Mausposition, und das Fenster hinter dem Cursor erhalten, mit dem Link, den Sie wie folgt vorgesehen:

[DllImport("user32.dll")] 
public static extern IntPtr WindowFromPoint(Point lpPoint); 
[DllImport("user32.dll")] 
public static extern bool GetCursorPos(out Point lpPoint); 
public static IntPtr GetWindowUnderCursor() 
{ 
    Point ptCursor = new Point(); 
    if (!(PInvoke.GetCursorPos(out ptCursor))) 
     return IntPtr.Zero; 
    return WindowFromPoint(ptCursor); 
} 

Jetzt haben Sie Ihre Fenster-Handle, von dort die Möglichkeiten sind endlos.

HINWEIS: Der Link oben, (die Fenster Haken) wird nur funktionieren, wenn die Maus auf dem Formular tritt nach unten, und der Haken endet, wenn die Maus

0

Einfach angehoben wird. Sie setzen die Mausaufnahme einfach auf die Maus, damit Sie alle Mausnachrichten erhalten, auch wenn sie sich außerhalb Ihres eigenen Fensters befinden. Verwenden Sie dann bei Mausbewegung WindowFromPoint.

Ich bin nicht vertraut mit .NET, aber mit der Win32-API verwenden Sie SetCapture, um die Mauserfassung festzulegen.

0

Sie an der C++ Quelle für Winspy++, ein anderes Fenster Inspektoren Programm ähnlich wie Winspector Spy aussehen könnten. Ich kenne kein Open-Source-C# -Programm wie dieses.

2

Sie müssen überlegen, wie Sie zuerst das Rechteck um das Fenster zeichnen, das sich auf den Rest Ihres Codes auswirkt. Der einfachste Weg dazu besteht in der Verwendung eines Formulars, dessen TransparencyKey auf BackColor und FormBorderStyle auf None gesetzt ist.Zeichnen Sie im Paint-Ereignis ein Rechteck, das die gleiche Größe wie das ClientRectangle des Formulars hat. Dadurch erhalten Sie ein sichtbares Rechteck, in dem alles andere transparent ist. Legen Sie die Standort- und Größeneigenschaft des Formulars so fest, dass sie dem von Ihnen gefundenen Fenster entspricht.

Jetzt das Fenster von der Mausposition finden. Sie können WindowFromPoint() nicht verwenden, deaktivierte Fenster werden nicht berücksichtigt. Sie müssen EnumWindows() verwenden. Rufen Sie GetWindowRect() im Callback auf und überprüfen Sie, ob sich die Maus innerhalb des Rechtecks ​​befindet. Achten Sie darauf, das Rechteck-Zeichenfenster zu ignorieren.

Wenn Sie eine Übereinstimmung erhalten, rufen Sie GetWindow() wiederholt mit dem GW_HWNDPREV, um Fenster zu finden, die das gefundene Fenster überlappen. Überprüfen Sie das Rechteck und ignorieren Sie weiterhin das Rechteckfenster.

Dadurch erhalten Sie schließlich das oberste Fenster, auf dem sich der Mauszeiger befindet. Verwenden Sie jetzt ChildWindowFromPoint(), um zu überprüfen, ob sich die Maus in einem unterordneten Fenster befindet, falls vorhanden. Erstellen Sie ggf. Ihr Rechteck-Zeichnungsformular, und weisen Sie ihm dieselbe Größe und denselben Ort wie das gefundene Fenster zu.

Rufen Sie diesen Code vom MouseMove-Ereignis, sagen wir, eine PictureBox, die eine Bulls-Eye-Grafik anzeigt. Setzen Sie die Capture-Eigenschaft in seinem MouseDown-Ereignis auf true.

Schließen Sie die Close() - Methode des Rechtecks ​​im MouseUp-Ereignis.

1

Da Sie dies mit C# markiert habe, kann ich in einen Link oder zwei für diesen Job setzen, die Sie versuchen, hoffentlich zu erreichen und geben Sie die notwendigen Einblick, wie diese zu erreichen:

Alle oben genannten Artikel sind auf CodeProject.

Hoffen, dass dies hilft, Mit freundlichen Grüßen, Tom.