Visual Studio 2012 — окно C ++, перетаскиваемое с помощью строки меню

Поэтому я использую Visual C ++ и создал перетаскиваемое окно без полей. В любом случае, вверху есть панель инструментов, и я хочу иметь возможность перетаскивать окно на эту панель инструментов. Я все еще хочу, чтобы панель инструментов была функциональной, но я понятия не имею, как можно перетаскивать окно за нее. Это мое текущее окно (см. Панель инструментов вверху):

окно

И это мой текущий код, чтобы сделать его перетаскиваемым:

case WM_NCHITTEST: {
LRESULT hit = DefWindowProc(hWnd, message, wParam, lParam);
if(hit == HTCLIENT) hit = HTCAPTION;
return hit;
}
break;

1

Решение

Вы находитесь на правильном пути с подключением WM_NCHITTEST. Теперь вам нужно изменить то, что представляет собой попадание клиента по сравнению с обращением к заголовку. Если я понимаю ваш код прямо сейчас, то, где бы вы ни щелкнули в пределах клиентской области окна (все, кроме границы), вы сможете перетащить окно в другое место. Это сделает взаимодействие с вашим приложением очень сложным. Вместо этого вам следует возвращать HTCAPTION только после того, как вы определили, что попадание было в пределах области меню. В частности, область меню, которая не содержит кнопок File / Edit / Help.

case WM_NCHITTEST: {
LRESULT hit = DefWindowProc(hWnd, message, wParam, lParam);
if (hit == HTCLIENT) { // The hit was somewhere in the client area. Don't know where yet.
// Perform your test for whether the hit was in the region you would like to intercept as a move and set hit only when it is.
// You will have to pay particular attention to whether the user is actually clicking on File/Edit/Help and take care not to intercept this case.
// hit = HTCAPTION;
}
return hit;
break;
}

Вот некоторые вещи, которые следует иметь в виду:

  • Это может очень запутать пользователя, который хочет свернуть, закрыть или переместить ваше приложение. Меню не сообщают пользователю, что вы можете перемещать окно, перетаскивая его.
  • Если вас интересуют вертикальные пиксели, вы можете подумать о том, что начинают делать другие приложения в Windows — перенести функциональность меню на одну кнопку, которая отображается в заголовке. (Смотрите последние версии Firefox / Opera или проводника Windows в Windows 8, чтобы узнать, как перенести вещи в заголовок.
1

Другие решения

В одном из моих приложений я также хотел сделать окно, которое я называю «клиентской областью, перетаскиваемым». К сожалению, упомянутое решение (замена HTCLIENT на HTCAPTION)
действительно есть серьезные недостатки:

Двойной щелчок в клиентской области теперь показывает то же поведение, что и
дважды щелкнув заголовок (то есть свернуть / развернуть окно)!

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

        case WM_MOUSEMOVE:
// Move window if we are dragging it
if (mIsDragging) // variable: bool mIsDragging;
{
POINT mousePos = {GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam)};

mIsDragging = (ClientToScreen(hWnd, &mousePos) &&
SetWindowPos(hWnd,
NULL,
mDragOrigin.left + mousePos.x - mDragPos.x,
mDragOrigin.top + mousePos.y - mDragPos.y,
0,
0,
SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE));
}
break;

case WM_LBUTTONDOWN:
// Check if we are dragging and safe current cursor position in case
if (wParam == MK_LBUTTON)
{
POINT mousePos = {GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam)};
if (ClientToScreen(hWnd, &mousePos) &&
DragDetect(hWnd, mousePos))
{
// Check if the cursor is pointing to your new caption here!!!!
mIsDragging = true;
mDragPos = mousePos;

GetWindowRect(hWnd, &mDragOrigin);
SetCapture(hWnd);
}
}
break;

// Remove this case when ESC key handling not necessary
case WM_KEYDOWN:
// Restore original window position if ESC is pressed and dragging active
if (!mIsDragging || wParam != VK_ESCAPE)
{
break;
}

// ESC key AND dragging... we restore original position of window
// and fall through to WM_LBUTTONUP as if mouse button was released
// (i.o.w. NO break;)
SetWindowPos(hWnd, NULL, mDragOrigin.left, mDragOrigin.top, 0, 0,
SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE);

case WM_LBUTTONUP:
ReleaseCapture();
break;

case WM_CAPTURECHANGED:
mIsDragging = false;
break;

(Псевдо) код пропускает возвращаемые значения (по умолчанию: 0) и определения переменных, но
в любом случае следует прояснить процедуру? (Если не напишите мне, и я добавлю больше
или весь код).

PS: я только что нашел другое подробное описание, которое также объясняет различия
из этих двух решений: http://tinyurl.com/bqtyt3q

0

По вопросам рекламы ammmcru@yandex.ru
Adblock
detector