Перетащите, как шпион Winspector - PullRequest
       24

Перетащите, как шпион Winspector

5 голосов
/ 21 февраля 2010

Мне было интересно, кто-нибудь может дать представление о том, как реализовать селектор окон в Winspector Spy. По сути, я хотел бы предоставить панель, на которую можно было бы навести курсор мыши, перетащить в другое окно процессов (или подокно) и получить из него что-то вроде HWND. В идеале я хотел бы сделать это в C #, но если это возможно только путем переноса C API, то я могу просто сделать это в C ++.

Я возился с событием DragDrop и вызывал DoDragDrop при наведении мыши в C #, но не был уверен, что это даст мне то, что я хочу. Будет ли проще просто получить глобальную X / Y позицию мыши и найти самое верхнее окно в этом месте? Есть ли API, который делает это автоматически для меня, учитывая параметры x, y?

РЕДАКТИРОВАТЬ: Только что обнаружил WindowFromPoint для последнего вопроса

Ответы [ 6 ]

5 голосов
/ 21 февраля 2010

Вы обычно не получаете сообщения мыши, когда мышь не находится над окном. Но вам нужно, чтобы сделать операции перетаскивания. Итак, Windows предоставляет механизм, называемый захватом мыши. Чтобы предотвратить злоупотребление захватом мыши, вы можете захватить только мышку при нажатии кнопки вниз. После захвата вы получаете сообщения о перемещении мыши, независимо от того, где находится мышь на экране, пока вы не отпустите захват или когда Windows увидит соответствующее сообщение о нажатии кнопки вверх.

Код C ++ для этого выглядит примерно так

 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;      

Функция GetAncestor может быть полезна для перехода из окна в точке к окну верхнего уровня, которому она принадлежит. GetWindow может использоваться для обхода дерева окон.

В .NET класс Control имеет свойство Capture, которое делает то же самое http://msdn.microsoft.com/en-us/library/system.windows.forms.control.capture.aspx

2 голосов
/ 22 февраля 2010

Вам нужно будет подумать, как вы будете сначала рисовать прямоугольник вокруг окна, что влияет на остальную часть вашего кода. Самый простой способ сделать это - использовать Form, для которой для TransparencyKey установлено значение BackColor, а для FormBorderStyle установлено значение None. Нарисуйте прямоугольник в событии Paint, того же размера, что и форма ClientRectangle, и вы получите видимый прямоугольник со всем остальным прозрачным. Задайте свойство формы и размер формы в соответствии с найденным окном.

Теперь находим окно с позиции мыши. Вы не можете использовать WindowFromPoint (), он не учитывает отключенные окна. Вам нужно будет использовать EnumWindows (). В обратном вызове вызовите GetWindowRect () и проверьте, находится ли мышь внутри прямоугольника. Обязательно игнорируйте окно рисования прямоугольника.

Когда вы получите совпадение, теперь несколько раз вызывайте GetWindow () с GW_HWNDPREV, чтобы найти окна, которые перекрывают найденное вами окно. Продолжайте проверять прямоугольник и продолжайте игнорировать окно прямоугольника.

В конечном итоге вы получите окно верхнего уровня, на котором находится курсор мыши. Теперь используйте ChildWindowFromPoint (), чтобы проверить, находится ли мышь на дочернем окне, если оно есть. При необходимости создайте форму для рисования прямоугольника и присвойте ей тот же размер и местоположение, что и у найденного окна.

Вызовите этот код из события MouseMove, скажем, PictureBox, которое отображает графику «бычьего глаза». Установите для его свойства Capture значение true в событии MouseDown.

Закройте метод Close () формы рисования прямоугольника в событии MouseUp.

1 голос
/ 22 февраля 2010

Поскольку вы пометили это с помощью C #, я могу добавить одну или две ссылки для этой работы, которую вы пытаетесь выполнить, и, надеюсь, даст вам необходимое понимание того, как этого добиться:

Все вышеперечисленные статьи находятся на CodeProject.

Надеюсь, это поможет, С уважением, Том.

0 голосов
/ 22 февраля 2010

Вы можете посмотреть на исходный код C ++ для Winspy ++ , еще одной программы для проверки окон, похожей на Winspector Spy. Однако я не знаю ни одной программы на C # с открытым исходным кодом, подобной этой.

0 голосов
/ 21 февраля 2010

Simple. Вы просто устанавливаете захват мыши при нажатии кнопки мыши, поэтому вы получаете все сообщения мыши, даже если они находятся за пределами вашего собственного окна. Затем при наведении мыши используйте WindowFromPoint.

Я не знаком с .NET, но с Win32 API вы используете SetCapture для установки захвата мыши.

0 голосов
/ 21 февраля 2010

Импорт: использование System.Runtime.InteropServices;

Мое предложение: когда мышь находится на вашей форме, обрабатывайте события перемещения мыши / вверх (чтобы захватить мышь за пределами формы с помощью хука окон, посмотрите здесь: http://support.microsoft.com/kb/318804), и когда Отпустите кнопку мыши, установите положение мыши на экране и установите окно за курсором, используя указанную вами ссылку:

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

Теперь у вас есть ручка окна, оттуда возможности безграничны.

ПРИМЕЧАНИЕ. Приведенная выше ссылка (хук окон) будет работать только в том случае, если на вашей форме происходит нажатие мыши, а хук заканчивается, когда мышь поднята

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...