// ===================================== // Функция WinMain // ===================================== #pragma argsused
int PASCAL WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpszCmdLine, int nCmdShow) { MSG msg; // структура для работы с сообщениями HWND hwnd; // идентификатор главного окна приложения
// Регистрация класса aWndClass = RegisterClass(&wc);
return (aWndClass != 0); }
// ===================================== // Функция WndProc // =====================================
LRESULT CALLBACK _export WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) { switch (msg) { // Сообщение приходит, когда вы нажимаете // на одну из двух созданных кнопок case WM_COMMAND: { // Если нажата первая кнопка, выводим // сообщение if(wParam == IDB_Button1) { MessageBox(hwnd, "Нажата кнопка Button 1", "Message WM_COMMAND",MB_OK); } else if(wParam == IDB_Button2) { SendMessage(hButton1, BM_SETSTATE, TRUE, 0L); } else if(wParam == IDB_Button3) { SendMessage(hButton1, BM_SETSTATE, FALSE, 0L); } else if(wParam == IDB_Button4) { EnableWindow(hButton1, FALSE); } else if(wParam == IDB_Button5) { EnableWindow(hButton1, TRUE); } return 0; }
// Это сообщение приходит при изменении состояния // дочернего окна органа управления, когда окно // нужно перерисовать case WM_DRAWITEM: { // Перерисовываем кнопку DrawButton( (LPDRAWITEMSTRUCT)lParam ); break; }
// ===================================== // Функция DrawButton // Перерисовывает кнопку // =====================================
void DrawButton(LPDRAWITEMSTRUCT lpInfo) { HBITMAP hbm; int ResourceID;
// Обрабатываем сообщение WM_DRAWITEM // только если оно поступило от кнопки if(lpInfo-> CtlType != ODT_BUTTON) return;
// Так как в приложении может быть несколько // кнопок, посылающих сообщение WM_DRAWITEM, // проверяем идентификатор кнопки switch (lpInfo-> CtlID) { case IDB_Button1: { // Загружаем идентификатор изображения // кнопки в нормальном (отжатом) состоянии ResourceID = IDR_BUTTONUP; break; } default: return; }
// Если кнопка выбрана, рисуем ее в нажатом // состоянии if (lpInfo-> itemState & ODS_SELECTED) { ResourceID = IDR_BUTTONDOWN; }
// если кнопка неактивна, загружаем идентификатор // изображения кнопки в неактивном состоянии else if (lpInfo-> itemState & ODS_DISABLED) { ResourceID = IDR_BUTTONGR; }
// Загружаем изображение кнопки из ресурсов приложения hbm = LoadBitmap(hInst, MAKEINTRESOURCE(ResourceID));
// При ошибке ничего не рисуем if(!hbm) return;
// Если кнопка выбрана и ее надо целиком // перерисовать, вызываем функцию DrawBitmap if((lpInfo-> itemAction & ODA_DRAWENTIRE) (lpInfo-> itemAction & ODA_SELECT)) { // Рисуем кнопку DrawBitmap(lpInfo-> hDC, (lpInfo-> rcItem).left, (lpInfo-> rcItem).top , hbm); }
// Удаляем изображение кнопки, так как оно // нам больше не нужно DeleteObject(hbm); }
В начале своей работы функция WinMain сохраняет идентификатор текущей копии приложения в глобальной переменной:
hInst = hInstance;
Затем она инициализирует главное окно приложения и создает пять кнопок, первая из которых имеет стиль BS_OWNERDRAW:
Функция главного окна приложения OWNBTN кроме сообщения WM_COMMAND дополнительно обрабатывает сообщение WM_DRAWITEM, в ответ на которое она вызывает функцию DrawButton, определенную в нашем приложении:
case WM_DRAWITEM: { DrawButton( (LPDRAWITEMSTRUCT)lParam ); break; }
Функция DrawButton перерисовывает кнопку. В качестве параметра этой функции передается указатель на структуру DRAWITEMSTRUCT, содержащую всю информацию, необходимую для перерисовки кнопки.
Вначале эта функция проверяет тип органа управления, приславшего сообщение WM_DRAWITEM. Тип должен быть равен ODT_BUTTON.
Затем проверяется идентификатор кнопки. В нашем приложении есть только одна кнопка со стилем BS_OWNERDRAW, но их могло бы быть и несколько. В переменную ResourceID загружается идентификатор ресурса (изображения bitmap), соответствующего изображению кнопки в нормальном (отжатом) состоянии:
Далее в зависимости от текущего состояния кнопки на момент прихода сообщения WM_DRAWITEM содержимое переменной ResourceID заменяется на идентификатор соответствующего изображения кнопки.
Для выбранной кнопки (в поле itemState структуры DRAWITEMSTRUCT установлен бит ODS_SELECTED) в переменную ResourceID записывается идентификатор изображения нажатой кнопки IDR_BUTTONDOWN.
Для неактивной кнопки в эту же переменную записывается идентификатор изображения неактивной кнопки IDR_BUTTONGR.
После этого нужное изображение загружается из ресурсов приложения, для чего вызывается функция LoadBitmap:
Далее функция DrawButton проверяет действие, которое нужно выполнить при рисовании кнопки. Если состояние кнопки изменилось (установлен бит ODA_SELECT) и требуется перерисовать всю кнопку (установлен бит ODA_DRAWENTIRE), выполняется вызов функции DrawBitmap, определенной в нашем приложении.
Создавая функцию DrawBitmap, мы сделали так, что количество, назначение и формат ее параметров в точности соответствует функции DrawIcon, с помощью которой мы рисовали пиктограммы (вы можете легко изменить исходный текст приложения OWNBUT для того чтобы для рисования кнопки использовать не изображения bitmap, а пиктограммы; сделайте это самостоятельно). В нашем примере в качестве первого параметра функции передается контекст устройства, полученный в структуре DRAWITEMSTRUCT вместе с сообщением WM_DRAWITEM. Второй и третий параметры используются для определения координат верхнего левого угла кнопки в системе координат, связанной с родительским окном. Последний параметр - идентификатор изображения bitmap, который необходимо нарисовать: