Программирование на C++ глазами хакера

         

Перемещение окна за любую область


С помощью программы, описанной в разд. 3.5, можно получить окно произвольной формы, но оно будет иметь один недостаток — его нельзя передвигать. Это потому, что у него нет обрамления и системного меню, с помощью которых и происходит перемещение окна по Рабочему столу. У этого окна есть только рабочая область, и это усложняет задачу.

Чтобы избавиться от этого недостатка, мы должны научить нашу программу двигать окно по щелчку мышки в любой его зоне. Есть два способа решения этой проблемы:

при нажатии кнопки в рабочей области можно обмануть систему и заставить ее поверить, что щелчок был произведен по заголовку окна. Тогда ОС сама будет двигать окно. Такое решение самое простое, и проблема решается одной строчкой кода, но в реальной работе это неудобно, поэтому я даже не буду его рассматривать;

самостоятельно перемещать окно. Программного кода будет намного больше, но зато он будет универсальным и гибким.

Для этого надо написать три обработчика событий:

Пользователь нажал кнопку мыши. Тогда необходимо сохранить текущую позицию курсора и запомнить в какой-нибудь переменной это событие. В нашем примере это будет глобальная переменная dragging типа bool. Помимо этого, нужно захватить мышку, чтобы все ее события посылались нашему окну, пока мы перемещаем его. Для этого служит функция SetCapture, которой надо передать в качестве параметра указатель на окно. Это необходимо для того, чтобы в случае выхода указателя за пределы рабочей области программа все равно получала сообщения о передвижении мышки.

Перемещение мышки. Если переменная dragging равна true, то пользователь нажал кнопку мыши и двигает окно. В этом случае надо подкорректировать положение окна в соответствии с новым положением курсора. Иначе это просто движение мышки поверх окна.

Пользователь отпустил кнопку мыши. В этот момент необходимо присвоить переменной dragging значение false и освободить курсор с помощью функции ReleaseCapture.

Воспользуйтесь примером из предыдущего раздела. Откройте его и найдите функцию WndProc, сгенерированную мастером при создании проекта. Добавьте в нее код из листинга 3.5, выделенный комментариями. В раздел глобальных переменных добавьте следующие две переменные:


bool dragging=false;
POINT MousePnt;

Листинг 3.5. Код перетаскивания мышки
LRESULT CALLBACK WndProc( HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { int wmId, wmEvent; PAINTSTRUCT ps; HDC hdc; HDC hdcBits;



RECT wndrect; POINT point;

switch (message) { case WM_COMMAND: wmId = LOWORD(wParam); wmEvent = HIWORD(wParam); // Parse the menu selections: switch (wmId) { case IDM_ABOUT: DialogBox(hInst, (LPCTSTR)IDD_ABOUTBOX, hWnd, (DLGPROC)About); break; case IDM_EXIT: DestroyWindow(hWnd); break; default: return DefWindowProc(hWnd, message, wParam, lParam); } break; case WM_PAINT: hdc = BeginPaint(hWnd, ps); // TODO: Add any drawing code here... hdcBits=::CreateCompatibleDC(hdc); SelectObject(hdcBits, maskBitmap); BitBlt(hdc, 0, 0, 200, 200, hdcBits, 0, 0, SRCCOPY); DeleteDC(hdcBits); EndPaint(hWnd, ps); break; case WM_DESTROY: PostQuitMessage(0); break;

/////////////////////////////////////////// // Начало кода, который надо добавить ///////////////////////////////////////////

// Следующий код обрабатывает событие, // когда нажата левая кнопка мыши case WM_LBUTTONDOWN: GetCursorPos(MousePnt); dragging = true; SetCapture(hWnd); break; // Следующий код обрабатывает событие, // когда курсор мышки движется по экрану case WM_MOUSEMOVE: if (dragging) // Если нажата кнопка, то... { // Получить текущую позицию курсора GetCursorPos(point); // Получить текущие размеры окна GetWindowRect(hWnd, wndrect);

// Откорректировать положение окна wndrect.left = wndrect.left+(point.x - MousePnt.x); wndrect.top = wndrect.top +(point.y - MousePnt.y);

// Установить новые размеры окна SetWindowPos(hWnd, NULL, wndrect.left, wndrect.top, 0, 0, SWP_NOZORDER | SWP_NOSIZE);

// Запоминаем текущую позицию курсора MousePnt=point; } break; // Следующий код обрабатывает событие, // когда левая кнопка мыши отпущена case WM_LBUTTONUP: if (dragging) { dragging=false; ReleaseCapture(); } /////////////////////////////////////////// // Конец кода, который надо добавить /////////////////////////////////////////// default: return DefWindowProc(hWnd, message, wParam, lParam); } return 0; }



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

Примечание
Исходный код примера , описанного в этом разделе , вы можете найти на компакт - диске в каталоге \Demo\Chapter3\MaskWindow2.

Содержание раздела