2010-02-21 18 views
5

Zastanawiam się, czy ktokolwiek mógłby dać wgląd w to, jak zaimplementować selektor okien w Winspector Spy. Zasadniczo chciałbym udostępnić panel, na którym mogłem umieścić mysz, przeciągnąć do innego okna procesów (lub okna podrzędnego) i pobrać coś takiego jak HWND. Najlepiej byłoby zrobić to w języku C#, ale jeśli jest to możliwe tylko przez zawijanie API C, to mogę to zrobić w C++.Przeciągnij i upuść jak Spy Winspector

Przezwyciężyłem z powodu zdarzenia DragDrop i wywołanie DoDragDrop na myszy w dół w C#, ale nie był naprawdę pewien, czy to może dać mi to, co chcę. Czy łatwiej będzie po prostu uzyskać globalną pozycję X/Y myszy i znaleźć najwyższe okno w tej lokalizacji? Czy istnieje API, które robi to automagicznie dla mnie z podanymi parametrami x, y?

EDIT: właśnie odkrył WindowFromPoint na tym ostatnim pytaniu

Odpowiedz

5

Zazwyczaj wiadomości myszy nie są wyświetlane, gdy mysz nie znajduje się nad oknem. Ale musisz wykonać operacje przeciągania i upuszczania. Tak więc system Windows udostępnia mechanizm nazywany przechwytywaniem myszy. Aby zapobiec nadużyciom myszy, możesz przechwycić mysz tylko po naciśnięciu przycisku. Po przechwyceniu otrzymujesz komunikaty przenoszenia myszki bez względu na to, gdzie znajduje się mysz, dopóki nie zwolnisz przechwytywania lub gdy system Windows zobaczy odpowiedni komunikat.

C++ kod za to wyglądać tak

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;  

Funkcja GetAncestor mogą być pomocne, aby przejść z okna w miejscu, do okna najwyższego poziomu, który go posiada. GetWindow może być używany do chodzenia po drzewie okna.

W .NET, klasa Kontrola ma właściwość przechwytywania, który robi to samo zobaczyć http://msdn.microsoft.com/en-us/library/system.windows.forms.control.capture.aspx

+0

To było wspaniałe - wielkie dzięki. –

0

Import: pomocą System.Runtime.InteropServices;

Moja sugestia, gdy mysz znajduje się w twojej formie, obsługuj ruch myszy/poruszaj myszką w górę zdarzeń (Aby przechwycić mysz poza formularz za pomocą haka systemu Windows, zajrzyj tutaj: http://support.microsoft.com/kb/318804), a po zwolnieniu przycisku myszy , uzyskać pozycji myszy na ekranie i uzyskać okno za kursorem, korzystając z linku, który podałeś tak:

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

teraz masz uchwyt okna, stamtąd możliwości są nieograniczone.

UWAGA: Powyższy link, (hak windows) będzie działać tylko wtedy, gdy mysz w dół odbywa się na formularzu, a hak kończy się, gdy mysz jest podnoszony

0

proste. Ustawiasz przechwycenie myszy myszką w dół, więc dostajesz wszystkie komunikaty myszy, nawet jeśli znajdują się poza twoim własnym oknem. Następnie myszką w górę, użyj WindowFromPoint.

Nie jestem zaznajomiony z .NET, ale z Win32 API, używasz SetCapture do ustawienia przechwytywania myszy.

0

Można by spojrzeć na C++ źródło dla Winspy++, innym programem okno inspektora podobny do Winspector Szpiega. Jednak nie znam żadnego programu open-source C#.

2

Musisz zastanowić się, w jaki sposób najpierw narysujesz prostokąt wokół okna, co ma wpływ na resztę kodu. Najłatwiej to zrobić za pomocą formularza, w którym ustawiono TransparencyKey na jego zestaw BackColor i FormBorderStyle na Brak.Narysuj prostokąt w zdarzeniu Paint, o tym samym rozmiarze co ClientRectangle formularza, który dostarczy ci widoczny prostokąt z całą pozostałą przezroczystością. Ustaw właściwość Lokalizacja i rozmiar formularza, aby pasowała do znalezionego okna.

Teraz znajdowanie okna z pozycji myszy. Nie można używać WindowFromPoint(), nie bierze pod uwagę wyłączonych okien. Musisz użyć EnumWindows(). W wywołaniu zwrotnym wywołaj GetWindowRect() i sprawdź, czy mysz znajduje się wewnątrz prostokąta. Pamiętaj, aby zignorować okno rysowania prostokąta.

Po uzyskaniu dopasowania wywołaj teraz funkcję GetWindow() z GW_HWNDPREV, aby znaleźć okna, które pokrywają się z odnalezionym oknem. Kontynuuj sprawdzanie prostokąta i ignoruj ​​okno prostokąta.

Powoduje to wyświetlenie okna najwyższego poziomu, w którym znajduje się kursor myszy. Teraz użyj ChildWindowFromPoint(), aby sprawdzić, czy mysz znajduje się w oknie podrzędnym, jeśli takie istnieje. W razie potrzeby utwórz swój prostokątny formularz rysunkowy i nadaj mu ten sam rozmiar i położenie, co okno wyszukiwania.

Wywołanie tego kodu ze zdarzenia MouseMove, powiedzmy, PictureBox, który wyświetla grafikę. Ustaw właściwość Przechwytuj na wartość true w zdarzeniu MouseDown.

Zamknij metodę Close() swojego rysunku prostokąta w zdarzeniu MouseUp.

1

Ponieważ określili to z C#, mogę umieścić w linku lub dwa do tej pracy, które chce osiągnąć i mam nadzieję, że dadzą Ci niezbędną wgląd w jaki sposób osiągnąć to:

Wszystkie powyższe artykuły znajdują się na CodeProject.

Mam nadzieję, że to pomoże, Pozdrawiam, Tom.

Powiązane problemy