WinAPI. Перетаскивание окна за любую его часть

{lang: 'ru'}

В этом коротком посте я расскажу, как можно обеспечить возможность перетаскивания окна за любую точку его содержимого. А коротким он будет потому, что опишу я только один способ. Самый, на мой взгляд, элегантный, простой и красивый для решения данной задачи. В принципе, то же самое можно сделать и через обработку сообщения WM_MOVE, но это, в данном случае, будет, как мне кажется, слишком сложным. Мы пойдем другим путем. Путем «обмана» Windows. Когда пользователь будет пытаться перетащить окно за клиентскую область, мы заставим Windows думать, что перетаскивание на самом деле осуществляется за заголовок окна. Таким образом, все операции, требуемые для осуществления этого действия, возьмет на себя ОС.

Для осуществления задуманного нам понадобятся: сообщение WM_NCHITTEST, обработчик событий по умолчанию DefWindowProc() и немного смекалки.

Справка: Сообщение WM_NCHITTEST посылается при изменении координат расположения курсора на экране, при нажатии какой-либо кнопки мыши и после её отпускания. Обработчик событий по умочанию, при обработке этого события, возвращает нам область окна, над которой находился курсор в момент отправки сообщения. Вот некоторые из возможных возвращаемых значений:

HTCAPTION – курсор находится над заголовком
HTCLIENT – над клиентской областью
HTCLOSE – над кнопкой «закрыть»
HTMENU – над меню
HTTOP – над верхним горизонтальным бордюром

Остальные варианты значений можно посмотреть в MSDN. В данном случае нас интересуют первые два.

Суть метода: В цикле обработки сообщений выполняем обработку WM_NCHITTEST. Делаем это следующим образом:


  1. Вызываем обработчик по умолчанию DefWindowProc()
  2. Сохраняем возвращенное им значение в специальной переменной
  3. Проверям, если оно равно HTCLIENT, т.е. если курсор находится над клиентской областью окна, то «подменяем» возвращаемое значение на HTCAPTION.
  4. В противном случае просто возвращаем то же самое, что вернул нам DefWindowProc()

Вот как это выглядит в коде:

Все, мы успешно провели Windows и заставили её выполнять всю работу за нас Правда, не стоит забывать, что реализация этого через WM_MOVE будет хоть и сложнее, но и более гибкой. Однако, описание этого способа уже выходит за рамки моего «короткого» поста.


Полезная статья? Их будет больше, если вы поддержите меня!