Внешний вид сайта:

Перетаскивание формы без заголовка

Наиболее распространенный способ перетаскивания окна приложения — за заголовок окна. Настоящая статья продемонстрирует, как можно перетаскивать форму без заголовка, просто нажав на любом месте формы.

Сообщение Windows WM_NCHITTEST

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

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

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

Вставьте следующую строку в раздел Private declarations (объявление процедур обработки сообщений):

procedure WMNCHitTest(var Msg: TWMNCHitTest) ; message WM_NCHitTest;

Добавьте следующий код в раздел implementation в модуле формы:

procedure TForm1.WMNCHitTest(var Msg: TWMNCHitTest) ;
begin
  inherited;
  if Msg.Result = htClient then Msg.Result := htCaption;
end;

Первая строка кода в обработчике сообщений вызывает унаследованный метод обработки сообщения WM_NCHITTEST. Важная часть находится в значении поля Msg.Result. Мы можем изменить сообщение результата.

Если пользователь щелкнет мышью в клиентской области формы, нам нужно заставить Windows думать, что пользователь щелкнул мышью на заголовке формы. Просто нужно в результате возвращения функции изменить HTCLIENT на HTCAPTION.

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

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

Форма может быть изменена и другим путем - применяя метод CreateParams.

Другие хитрости WM_NCHITTEST

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

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

if Msg.Result = htClose then Msg.Result := htNowhere;

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

if Msg.Result = htCaption then Msg.Result := htClient;

А если есть компоненты на форме?

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

В этом случае, чтобы перетащить нашу форму, мы должны добавить несколько строк кода в процедуре OnMouseDown для компонента Panel.

procedure TForm1.Panel1MouseDown
    (Sender: TObject; Button: TMouseButton;
     Shift: TShiftState; X, Y: Integer) ;
begin
  ReleaseCapture;
  SendMessage(Form1.Handle, WM_SYSCOMMAND, 61458, 0) ;
end;

Примечание: этот код не работает с не оконнымы управлениями, типа TLabel.

Комментарии

Нет комментариев. Ваш будет первым!