2010-02-21 16 views
5

Mi chiedevo se qualcuno potesse dare informazioni su come implementare il selettore di finestre in Winspector Spy. Fondamentalmente, vorrei fornire un pannello su cui poter scorrere il mouse, trascinare su un'altra finestra dei processi (o sotto finestra) e ricavarne qualcosa come HWND. Idealmente, lo farei in C#, ma se è possibile solo avvolgendo le API C, allora posso farlo in C++.Trascinare e rilasciare come Winspector Spy

Ho fatto un po 'di casino con l'evento DragDrop e ho richiamato DoDragDrop al puntatore del mouse in C#, ma non ero sicuro che potesse darmi quello che volevo. Sarà più semplice ottenere la posizione X/Y globale del mouse e trovare la finestra più in alto in quella posizione? Esiste un'API che esegue automaticamente per me i parametri x, y?

EDIT: appena scoperto WindowFromPoint per quest'ultima domanda

risposta

5

Normalmente non si ottengono i messaggi del mouse quando il mouse non è sopra la finestra. Ma è necessario per eseguire operazioni di trascinamento e rilascio. Quindi, Windows fornisce un meccanismo chiamato cattura del mouse. Per impedire che l'acquisizione del mouse venga abusata, è possibile catturare il mouse solo su un messaggio button-down. Una volta acquisita, si ottengono i messaggi di spostamento del mouse indipendentemente dal punto in cui si trova il mouse sullo schermo fino a quando non viene rilasciata l'acquisizione o quando Windows visualizza il corrispondente messaggio a comparsa.

Il codice C++ per questo sembra qualcosa di simile

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 funzione GetAncestor può essere utile per passare dalla finestra al punto, alla finestra di livello superiore che possiede. GetWindow può essere utilizzato per aggirare l'albero della finestra.

In .NET, la classe di controllo ha una proprietà Capture che fa la stessa cosa vedere http://msdn.microsoft.com/en-us/library/system.windows.forms.control.capture.aspx

+0

Questo è stato fantastico, grazie mille. –

0

Importazioni: using System.Runtime.InteropServices;

Il mio suggerimento, quando il mouse è sul modulo, gestire gli eventi di spostamento del mouse/mouse (Per catturare il mouse all'esterno del modulo utilizzando un gancio di Windows, guarda qui: http://support.microsoft.com/kb/318804) e quando viene rilasciato il pulsante del mouse , ottenere la posizione del mouse sullo schermo, e ottenere la finestra dietro il cursore, utilizzando il link che hai fornito in questo modo:

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

Ora avete il vostro handle di finestra, da qui le possibilità sono infinite.

NOTA: Il link qui sopra, (il gancio finestre) funziona solo se il mouse verso il basso si verifica sul modulo, e il gancio si conclude quando il mouse viene sollevato

0

semplice. Basta impostare l'acquisizione del mouse con il mouse verso il basso, in modo da ottenere tutti i messaggi del mouse anche se si trovano fuori dalla propria finestra. Quindi, alza il mouse, usa WindowFromPoint.

Non ho familiarità con .NET, ma con l'API Win32, si usa SetCapture per impostare l'acquisizione del mouse.

0

si poteva guardare il sorgente C++ per Winspy++, un altro programma finestra Impostazioni simile a Winspector Spy. Tuttavia, non conosco nessun programma C# open-source come questo.

2

È necessario considerare come disegnare il rettangolo intorno alla finestra per primo, che influisce sul resto del codice. Il modo più semplice per farlo consiste nell'utilizzare un modulo con TransparencyKey impostato su BackColor e FormBorderStyle impostato su Nessuno.Disegna un rettangolo nell'evento Paint, della stessa dimensione del ClientRectangle del modulo, che ti offre un rettangolo visibile con tutto il resto trasparente. Imposta la proprietà Posizione e Dimensioni del modulo in modo che corrisponda alla finestra che hai trovato.

Ora trovare la finestra dalla posizione del mouse. Non è possibile utilizzare WindowFromPoint(), non considera le finestre disabilitate. Dovrai utilizzare EnumWindows(). Nel callback, chiama GetWindowRect() e controlla se il mouse si trova all'interno del rettangolo. Assicurati di ignorare la finestra di disegno del rettangolo.

Quando ottieni una corrispondenza, chiama ripetutamente GetWindow() con GW_HWNDPREV per trovare le finestre che si sovrappongono alla finestra trovata. Continua a controllare il rettangolo e continua a ignorare la finestra del rettangolo.

In questo modo si ottiene la finestra di livello superiore su cui è posizionato il cursore del mouse. Ora utilizzare ChildWindowFromPoint() per verificare se il mouse si trova su una finestra secondaria, se presente. Crea il tuo modulo di disegno rettangolare, se necessario, e dargli le stesse dimensioni e la stessa posizione della finestra trovata.

Chiama questo codice dall'evento MouseMove di, ad esempio, un PictureBox che mostra una grafica a occhio di bue. Imposta la proprietà Capture su true nel suo evento MouseDown.

Chiudere il metodo Close() del modulo di disegno del rettangolo nell'evento MouseUp.

1

Dal momento che avete etichettato questo con C#, posso mettere in un link o due per questo lavoro che si sta cercando di realizzare e, auspicabilmente, ti darò la necessaria conoscenza come raggiungere questo obiettivo:

Tutti gli articoli di cui sopra sono su CodeProject.

Spero che questo aiuti, Cordiali saluti, Tom.

Problemi correlati