Win API
Создание кнопок средствами Win API

:: Меню ::
:: На главную ::
:: FAQ ::
:: Заметки ::
:: Практика ::
:: Win API ::
:: Проекты ::
:: Скачать ::
:: Секреты ::
:: Ссылки ::

:: Сервис ::
:: Написать ::

:: MVP ::

:: RSS ::

Яндекс.Метрика


Сегодня мы поговорим о том, как создаются кнопки. За основу возьмем наш шаблон (если вы не читали статью "Минимальная программа на Win API", прочтите, именно с этим шаблоном мы будем работать). На некоторых кнопках нарисуем стандартные иконки, на некоторых выведем текст. И конечно обработаем событие, вызываемое нажатием на кнопку. Кроме этого, кнопки с текстом смогут иметь "фокус", который будет оставаться после нажатия на одну из них.

Начнем с того, что для каждой кнопки создадим константу с уникальным идентификационным номером. Объявление самих кнопок удобнее всего сделать в виде массива, это сделает код более компактным. Также создадим переменные для работы с иконками и шрифтом.

const
  // Кнопки, на которые будут выведены иконки
  BTN_APPLICATION = 0;
  BTN_HAND =        1;
  BTN_QUESTION =    2;
  BTN_EXCLAMATION = 3;
  BTN_ASTERISK =    4;
  BTN_WINLOGO =     5;
  // Кнопки, на которые будет выведен текст
  BTN_TEXT_0 = 6;
  BTN_TEXT_1 = 7;
  BTN_TEXT_2 = 8;

var
  Buttons: array[0..8] of HWND;
  Icon: HICON;
  Font: HFONT;

Кнопка, по своей сути, немногим отличается от главной формы приложения (это самостоятельное окно, имеющее "родителя", и обладающее своим собственным дескриптором). По этому для ее создания воспользуемся уже знакомой функцией CreateWindowEx. Посмотрим, как создается кнопка с иконкой.

Buttons[0] := CreateWindowEx( WS_EX_STATICEDGE, 'Button', nil, BS_ICON or WS_VISIBLE or WS_CHILD,
                              10, 15, 40, 40, Wnd, BTN_APPLICATION, hInstance, nil );
// Получаем описание нужной иконки
Icon := LoadIcon( 0, IDI_APPLICATION );
// Вставляем полученную иконку в кнопку
SendMessage( Buttons[0], BM_SETIMAGE, IMAGE_ICON, Icon );

Второй параметр функции CreateWindowEx говорит о том, что мы создаем именно кнопку. Определяя стиль кнопки, мы указываем, что она имеет родителя (WS_CHILD, дескриптор родителя указывается в 9-ом параметре) и будет отображать иконку (BS_ICON). С остальными параметрами мы уже знакомы. Функция LoadIcon загружает указанную иконку в наше приложение. Если первый параметр 0 (как в нашем случае), это значит, что мы работаем со стандартными системными значками (их константы указаны в модуле Windows). Загрузив иконку, назначаем ее кнопке, послав соответствующее сообщение. Остальные кнопки создаются по аналогии.

Теперь поговорим о кнопках с текстом.

   Buttons[6] := CreateWindowEx( WS_EX_STATICEDGE, 'Button', 'Button1', WS_VISIBLE or WS_CHILD,
                                 10, 70, 90, 40, Wnd, BTN_TEXT_0, hInstance, nil );
   Font := GetStockObject( ANSI_VAR_FONT  );
   SendMessage( Buttons[6], WM_SETFONT, Font, 0 );

   Buttons[7] := CreateWindowEx( WS_EX_STATICEDGE, 'Button', 'Button2', WS_VISIBLE or WS_CHILD,
                                 110, 70, 90, 40, Wnd, BTN_TEXT_1, hInstance, nil );
   Font := GetStockObject( ANSI_FIXED_FONT );
   SendMessage( Buttons[7], WM_SETFONT, Font, 0 );

   Buttons[8] := CreateWindowEx( WS_EX_STATICEDGE, 'Button', 'Button3',
                                 BS_DEFPUSHBUTTON or WS_VISIBLE or WS_CHILD,
                                 210, 70, 90, 40, Wnd, BTN_TEXT_2, hInstance, nil );

Основное отличие от создания предыдущих кнопок заключается в том, что в 3-ем параметре вместо nil пишется заголовок кнопки. Обратите внимание, в описании стиля отсутствует константа BS_ICON. В принципе этого достаточно для того, чтобы отобразить надпись на кнопке (посмотрите на создание последней кнопки - Buttons[8]). Однако мы можем кое-что сделать с текстом, а именно, изменить стиль шрифта. Делается это с помощью функции GetStockObject, параметром которой и задается необходимый нам стиль.

Обратим внимание на то, что последняя кнопка выглядит не совсем так, как остальные. Добиться такого результата можно, используя константу BS_DEFPUSHBUTTON при задании стиля.

Теперь посмотрим, как следует обрабатывать событие, полученное от нажатия кнопки.

function WindowProc( Wnd: HWND; Msg: UINT; wParam: WPARAM; lParam: LPARAM ): LRESULT; stdcall;
begin
   case Msg of
      WM_DESTROY: begin
         PostQuitMessage( 0 );
         Result := 0;
         Exit;
      end;
      // Обработка сообщений от кнопок
      WM_COMMAND:
         case LoWord( wParam ) of
            BTN_APPLICATION: MessageBox( Wnd, 'IDI_APPLICATION', 'Константа:', MB_OK );
            BTN_HAND:        MessageBox( Wnd, 'IDI_HAND', 'Константа:', MB_OK );
            BTN_QUESTION:    MessageBox( Wnd, 'IDI_QUESTION', 'Константа:', MB_OK );
            BTN_EXCLAMATION: MessageBox( Wnd, 'IDI_EXCLAMATION', 'Константа:', MB_OK );
            BTN_ASTERISK:    MessageBox( Wnd, 'IDI_ASTERISK', 'Константа:', MB_OK );
            BTN_WINLOGO:     MessageBox( Wnd, 'IDI_WINLOGO', 'Константа:', MB_OK );
            BTN_TEXT_0: begin
               MessageBox( Wnd, 'Button1', 'Кнопка:', MB_OK );
               SetFocus( Buttons[6] );
            end;
            BTN_TEXT_1: begin
               MessageBox( Wnd, 'Button2', 'Кнопка:', MB_OK );
               SetFocus( Buttons[7] );
            end;
            BTN_TEXT_2: begin
               MessageBox( Wnd, 'Button3', 'Кнопка:', MB_OK );
               SetFocus( Buttons[8] );
            end;
         end;
      else
         Result := DefWindowProc( Wnd, Msg, wParam, lParam );
   end;
end;

Как видим, нам нужно обработать сообщение WM_COMMAND. Параметр wParam хранит уникальный идентификатор кнопки, которая вызвала это событие. Сравниваем его с определенными в самом начале константами, идентифицируем кнопку, и выполняем связанный с ней код.

И последнее на сегодня. В нашей программе кнопки с текстом должны иметь фокус. Для этого, после выполнения кода, связанного с кнопкой, вызываем процедуру SetFocus. Теперь посмотрим, как это работает. После того, как мы уберем сообщение, вызванное нажатием на одну из трех нижних кнопок, мы увидим на ней пунктирный прямоугольник, нарисованный рядом с бордюром. Это и есть результат работы процедуры SetFocus. Теперь, нажав на клавишу "пробел", мы заставим эту кнопку сработать.

На этом все. Успехов в программировании.

.: Пример к данной статье :.


При использовании материала - ссылка на сайт обязательна