2010-02-21 5 views
5

Je me demandais si quelqu'un pouvait donner un aperçu sur la façon d'implémenter le sélecteur de fenêtre dans Winspector Spy. Fondamentalement, je voudrais fournir un panneau sur lequel je puisse glisser la souris, glisser vers une autre fenêtre de processus (ou sous-fenêtre) et obtenir quelque chose comme le HWND hors de lui. Idéalement, je le ferais en C#, mais si c'est seulement possible en encapsulant les API C, alors je peux le faire en C++.Glisser-déposer comme Winspector Spy

J'ai joué avec l'événement DragDrop et j'ai appelé DoDragDrop en descendant la souris en C#, mais je ne savais pas vraiment si cela pouvait me donner ce que je voulais. Sera-t-il plus facile d'obtenir simplement le point X/Y global de la souris et de trouver la fenêtre la plus haute à cet endroit? Y a-t-il une API qui le fait automagiquement pour moi étant donné les paramètres x, y?

EDIT: vient de découvrir WindowFromPoint pour cette dernière question

Répondre

5

Normalement, vous n'obtenez pas de messages de la souris lorsque la souris ne se trouve pas sur votre fenêtre. Mais vous devez dans le but de faire glisser et déposer des opérations. Windows fournit donc un mécanisme appelé capture de la souris. Pour empêcher la capture de la souris d'être abusé, vous pouvez seulement capturer la souris sur un message de bouton. Une fois que vous avez capturé, vous obtenez des messages de déplacement de la souris, peu importe où la souris est à l'écran jusqu'à ce que vous libérez la capture ou lorsque Windows voit le message de bouton correspondant.

Le code C++ pour cela ressemble quelque chose comme ça

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;  

La fonction GetAncestor peut être utile de passer de la fenêtre au point, à la fenêtre de niveau supérieur qui le possèdent. GetWindow peut être utilisé pour marcher autour de l'arbre de la fenêtre.

Dans .NET, la classe de contrôle a une propriété de capture qui fait la même chose voir http://msdn.microsoft.com/en-us/library/system.windows.forms.control.capture.aspx

+0

C'était génial - merci beaucoup. –

0

Importations: utilisant System.Runtime.InteropServices; Ma suggestion, lorsque la souris est sur votre formulaire, gérer les événements de déplacement de souris/souris (Pour capturer la souris en dehors de votre formulaire en utilisant un crochet de Windows, regardez ici: http://support.microsoft.com/kb/318804), et quand le bouton de la souris est relâché , obtenir la position de la souris sur l'écran, et obtenir la fenêtre derrière le curseur, à l'aide du lien fourni comme ceci:

[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); 
} 

maintenant que vous avez votre poignée de fenêtre, à partir de là les possibilités sont infinies.

NOTE: Le lien ci-dessus, (le crochet Windows) ne fonctionnera que si la souris se produit vers le bas sur votre formulaire, et les extrémités crochet lorsque la souris est soulevé

0

simple. Vous venez de définir la capture de la souris sur la souris, de sorte que vous obtenez tous les messages de la souris, même si elles sont en dehors de votre propre fenêtre. Ensuite, à la souris, utilisez WindowFromPoint.

Je ne suis pas familier avec .NET, mais avec l'API Win32, vous utilisez SetCapture pour définir la capture de la souris.

0

Vous pouvez regarder le C++ source pour Winspy++, un autre programme d'inspecteur de fenêtre similaire à Winspector Spy. Je ne connais pas de programme C# open-source comme celui-ci, cependant.

2

Vous devrez d'abord considérer comment vous allez dessiner le rectangle autour de la fenêtre, ce qui affecte le reste de votre code. La méthode la plus simple consiste à utiliser un formulaire dont le paramètre TransparencyKey est défini sur BackColor et FormBorderStyle sur None.Dessinez un rectangle dans l'événement Paint, de la même taille que ClientRectangle du formulaire, pour obtenir un rectangle visible avec tout le reste transparent. Définissez la propriété Emplacement et taille du formulaire pour correspondre à la fenêtre que vous avez trouvée.

Trouver maintenant la fenêtre à partir de la position de la souris. Vous ne pouvez pas utiliser WindowFromPoint(), il ne considère pas les fenêtres désactivées. Vous devrez utiliser EnumWindows(). Dans le rappel, appelez GetWindowRect() et vérifiez si la souris est située à l'intérieur du rectangle. Assurez-vous d'ignorer la fenêtre de dessin de votre rectangle.

Lorsque vous obtenez une correspondance, appelez maintenant GetWindow() plusieurs fois avec GW_HWNDPREV pour trouver les fenêtres qui chevauchent la fenêtre que vous avez trouvée. Continuez à vérifier le rectangle et continuez d'ignorer votre fenêtre rectangle.

Cela vous permettra éventuellement d'obtenir la fenêtre de niveau supérieur sur laquelle se trouve le curseur de la souris. Maintenant, utilisez ChildWindowFromPoint() pour vérifier si la souris est sur une fenêtre enfant, le cas échéant. Créez votre formulaire de dessin rectangle, si nécessaire, et donnez-lui la même taille et le même emplacement que la fenêtre trouvée.

Appelez ce code à partir de l'événement MouseMove de, disons, un PictureBox qui affiche un graphique œil-de-bœuf. Définissez sa propriété Capture sur true dans son événement MouseDown.

Fermez la méthode Close() de votre formulaire de dessin rectangle dans l'événement MouseUp.

1

Puisque vous avez marqué cela avec C#, je peux mettre un lien ou deux pour ce travail que vous essayez d'accomplir et nous espérons vous donner les connaissances nécessaires sur la façon d'y parvenir:

Tous les articles ci-dessus sont sur CodeProject.

Espérons que cela aide, Cordialement, Tom.

Questions connexes