Русская справка по Delphi 5
Мастерская Delphi программирования.
Главная Мастерская Архив Ссылки Отдых Для гостей  
Секреты VCL Секреты API            

Кнопка в заголовке окна

пример: capbtn.zip

Обычно окно приложения имеют 3 кнопки в своем заголовке, свернуть, развернуть и закрыть. На этой страничке будет рассказано, как в заголовок окна добавить свою кнопку. Если вас это заинтересовало, начнем.

После недолгого капания в недрах windows API удалось добиться желаемого результата. Вот что получилось:

исходный код unit main.

Вся основная работа по рисованию кнопки в заголовке окна происходит в процедуре DrawBtn. Рассмотрим код подробней.

procedure TForm1.DrawBtn;
var
  WDc: HDc;
  Cx,Cy: Integer;
  XFrame, Yframe: Integer;
begin
 WDc := GetWindowDc(Handle);
 Cx := GetSystemMetrics(SM_CXSize);
 Cy := GetSystemMetrics(SM_CYSize);
 xFrame := GetSystemMetrics(SM_CXFrame);
 yFrame := GetSystemMetrics(SM_CYFrame);
 R := Bounds(Width - xFrame - 4*Cx + 2, yFrame + 2, Cx - 2, Cy - 4);
 if Press then
  DrawFrameControl(WDc,R,DFC_BUTTON,DFCS_ButtonPUSH or DFCS_PUSHED)
 else
  DrawFrameControl(WDc,R,DFC_BUTTON,DFCS_ButtonPUSH);
 ReleaseDc(Handle,WDC);
end;

Переменная WDc содержит контекст устройства окна, полученной функцией GetWindowsDc. Он понадобится для рисования окна. С помощью нескольких вызовов функции GetSystemMetrics узнаем размер стандартной кнопки заголовка окна. Затем вычисляем положение и размер прямоугольника, в котором будет рисоваться кнопка. И самое основное вызываем функцию DrawFrameControl. Эта функция рисует стандартный Control заданного типа и стиля. Используя тип DFC_BUTTON рисуем кнопку. Задавая стиль DFCS_BUTTONPUSH рисуется кнопка в нормальном состоянии, если задать стиль DFCS_BUTTONPUSH or DFCS_PUSHED рисуется кнопка в нажатом состоянии. Переменная Press содержит состояние в котором следует рисовать кнопку. В конце работы освобождаем контекст.

Теперь о самом неприятном. Чтобы все это заработало так как надо необходимо обработать кучу сообщений которое windows посылает приложению.Куча это, конечно, громко сказано, но у меня получилось 7, плюс 1 определенное мной для отслеживания Click. Вот эти сообщения:

  • WM_NCPAINT
  • WM_NCACTIVATE
  • WM_NCLBUTTONDOWN
  • WM_NCHITTEST
  • WM_SIZE
  • WM_NCLBUTTONUP
  • WM_LBUTTONUP
В основном обработка сообщений сводится к вызову DrawBtn. В обработке WM_NCLBUTTONDOWN определяется, была ли опущена левая кнопка мыши в области занятой кнопкой. WM_NCHITTEST предотвращает максимизацию окна. WM_SIZE правильно отрисовывает кнопку при изменении размеров окна. WM_NCLBUTTONUP Определяет был ли щелчок кнопкой мыши. И вызывает обработчик по средствам PostMessage. Вызов PostMessage сделан для того чтобы окно успело отреагировать на другие сообщения. WM_LBUTTONUP используется, если пользователь передумал и убрал курсор с кнопки при нажатой кнопке мыши.

PS: Можно обьединить кнопку в заголовке окна и пункт системного меню, описаный на страничке манипуляции с системным меню

пример: capbtn.zip


Главная Мастерская Архив Ссылки Отдых Для гостей  
Секреты VCL Секреты API            
Дизайн и программирование - Valler© ,2000,2001.
http://www.valler.narod.ru
Используются технологии uCoz