Нажмите и перетащите форму Delphi без строки заголовка

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

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

Сообщение Windows WM_NCHitTest

Операционная система Windows в значительной степени основан на обработка сообщений. Например, когда вы нажимаете на окно или элемент управления, Windows отправляет ему сообщение wm_LButtonDown, с дополнительной информацией о том, где находится курсор мыши и какие клавиши управления находятся в данный момент нажат. Звучит знакомо? Да, это не более чем событие OnMouseDown в Delphi.

instagram viewer

Аналогично, Windows отправляет сообщение wm_NCHitTest всякий раз, когда событие мыши происходит, когда курсор перемещается или когда кнопка мыши нажата или отпущена.

Код для ввода

Если мы можем заставить Windows думать, что пользователь перетаскивает (щелкнул) строку заголовка, а не область клиента, тогда пользователь может перетащить окно, щелкнув в области клиента. Самый простой способ сделать это - «обмануть» Windows, думая, что вы на самом деле нажимаете на строку заголовка формы. Вот что вы должны сделать:

1. Вставьте следующую строку в раздел «Частные объявления» вашей формы (объявление процедуры обработки сообщений):

процедура WMNCHitTest (вар Msg: TWMNCHitTest); сообщение WM_NCHITTEST; 

2. Добавьте следующий код в раздел «реализация» модуля вашей формы (где Form1 - предполагаемое имя формы):

процедура TForm1.WMNCHitTest (вар Msg: TWMNCHitTest);

начать

унаследованный;

если Msg. Результат = htClient тогда Msg. Результат: = htCaption;

конец; 

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

Это то, что мы делаем: если пользователь щелкнул в области клиента формы, мы заставляем Windows думать, что пользователь щелкнул по строке заголовка. В Объект Паскаль «слова»: если возвращаемое значение сообщения HTCLIENT, мы просто меняем его на HTCAPTION.

Нет больше событий мыши

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

Окно без заголовков

Если вы хотите, чтобы окно без заголовка было похоже на плавающую панель инструментов, установите для заголовка формы пустую строку, отключите все BorderIcons и установите для BorderStyle bsNone.

Форма может быть изменена различными способами, применяя пользовательский код в методе CreateParams.

Дополнительные хитрости WM_NCHitTest

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

Следующий фрагмент кода не позволит пользователям закрывать ваши формы, нажав кнопку Закрыть.

если Msg. Результат = htClose тогда Msg. Результат: = нигде; 

Если пользователь пытается переместить форму, щелкнув строку заголовка и перетащив, код заменяет результат сообщения на результат, который указывает, что пользователь щелкнул по области клиента. Это не позволяет пользователю перемещать окно мышью (в отличие от того, что мы делали в начале статьи).

если Msg. Результат = htCaption тогда Msg. Результат: = htClient; 

Наличие компонентов в форме

В большинстве случаев в форме будут некоторые компоненты. Скажем, например, что один объект Panel находится на форме. Если для свойства Align панели установлено значение alClient, Panel заполняет всю клиентскую область, поэтому невозможно выбрать родительскую форму, щелкнув по ней. Код выше не будет работать - почему? Это потому, что мышь всегда перемещается над компонентом Panel, а не над формой.

Чтобы переместить нашу форму путем перетаскивания панели на форму, нам нужно добавить несколько строк кода в процедуре события OnMouseDown для компонента Panel:

процедура TForm1.Panel1MouseDown

(Отправитель: TObject; Кнопка: TMouseButton;
Shift: TShiftState; X, Y: целое число);
начать

 ReleaseCapture;

 SendMessage (Form1.Handle, WM_SYSCOMMAND, 61458, 0);

конец; 

Заметка: Этот код не будет работать с неоконными элементами управления, такими как Компоненты TLabel.