При разработке приложений на Delphi с использованием VCL часто возникают ситуации, когда нужно показать дополнительную форму при нажатии на кнопку '?' в заголовке окна. Одним из способов реализации этой функции является использование события WMNCLBUTTONDOWN. Однако, некоторые разработчики сталкиваются с проблемой, когда это событие не срабатывает при нажатии на кнопку '?'. В данной статье мы рассмотрим причину этой проблемы и предложим решение, которое позволит показывать дополнительную форму при нажатии на кнопку '?' в заголовке окна.
Описание проблемы
Разработчик столкнулся с проблемой, когда событие WMNCLBUTTONDOWN не срабатывало при нажатии на кнопку '?' в заголовке окна VCL формы, установленной в режиме bsDialog с включенным флагом biHelp. Он следовал примеру из интернета, но не мог добиться срабатывания события при нажатии на кнопку '?'. Событие срабатывало только при нажатии на заголовок окна, как будто пользователь пытался перетащить его.
Вот код, который использовал разработчик:
procedure TMainFrm.WMNCLBUTTONDOWN(var Msg: TWMNCLButtonDown);
begin
ShowMessage('WMNCLBUTTONDOWN Pre-Help');
if Msg.HitTest = HTHELP then
Msg.Result := 0 // "eat" the message
else
inherited;
end;
procedure TMainFrm.WMNCLBUTTONUP(var Msg: TWMNCLButtonUp);
begin
if Msg.HitTest = HTHELP then
begin
Msg.Result := 0;
ShowMessage('Need help?');
end
else
inherited;
end;
Разработчик видел сообщение 'WMNCLBUTTONDOWN Pre-Help' при нажатии на заголовок окна, но не видел его при нажатии на кнопку '?'. Он пытался показать отдельную форму при нажатии на эту кнопку.
Альтернативный ответ
В комментариях к вопросу было предложено использовать OutputDebugString вместо ShowMessage, чтобы записывать сообщения без прерывания последовательности сообщений. Однако, разработчик все равно не видел сообщений при нажатии на кнопку '?'.
Подтвержденный ответ
Причина проблемы заключается в том, что Modal message loop, используемый ShowMessage, мешает обработке сообщений. Чтобы увидеть, что сообщения обрабатываются правильно, вместо ShowMessage нужно использовать OutputDebugString. Вот пример кода, который решает проблему:
type
TMainFrm = class(TForm)
protected
procedure WMNCLButtonDown(var Msg: TWMNCLButtonDown);
message WM_NCLBUTTONDOWN;
procedure WMNCLButtonUp(var Msg: TWMNCLButtonUp);
message WM_NCLBUTTONUP;
end;
...
procedure TMainFrm.WMNCLButtonDown(var Msg: TWMNCLButtonDown);
begin
if Msg.HitTest = HTHELP then
begin
OutputDebugString('Help button down');
Msg.Result := 0;
end
else
inherited;
end;
procedure TMainFrm.WMNCLButtonUp(var Msg: TWMNCLButtonUp);
begin
if Msg.HitTest = HTHELP then
begin
OutputDebugString('Help button up');
Msg.Result := 0;
end
else
inherited;
end;
При нажатии на кнопку '?' теперь должны появляться сообщения 'Help button down' и 'Help button up' в окне отладки. Важно помнить, что кнопки не нажимаются до тех пор, пока они не будут Released. Поэтому не следует выполнять действия, такие как показ диалогов, при нажатии кнопки. Дождитесь WM_NCLBUTTONUP, прежде чем показывать другой диалог.
Дополнительные комментарии
Разработчик сообщил, что видит сообщения только при добавлении кода вне блока if Msg.HitTest = HTHELP. Однако, код, предложенный в ответе, должен работать правильно и показывать сообщения при нажатии на кнопку '?'. Если вы все еще не видите сообщений, убедитесь, что правильно настроили отладку и знаете, где искать выходные данные.
Также было отмечено, что проект использует Custom Style (Project Options > Application > Appearance > Aqua Light Slate), а не Default Style. При использовании Custom Style код может работать по-разному. Если вам необходимо использовать Custom Style, возможно, придется найти другой способ показать дополнительную форму при нажатии на кнопку '?'.
Текст описывает проблему с событием WMNCLBUTTONDOWN в Delphi при попытке показать форму при нажатии кнопки '?' на VCL.
Комментарии и вопросы
Получайте свежие новости и обновления по Object Pascal, Delphi и Lazarus прямо в свой смартфон. Подпишитесь на наш Telegram-канал delphi_kansoftware и будьте в курсе последних тенденций в разработке под Linux, Windows, Android и iOS