Кнопки и стиль BS_OWNERDRAW

Модераторы: Romeo, Hawk, Absurd, WinMain, DeeJayC

Ответить
Alezis
Сообщения: 98
Зарегистрирован: 16 авг 2004, 01:10
Откуда: Минск
Контактная информация:

26 сен 2004, 22:43

Нужно создать кнопку чтобы она была представлена в виде битмапа, кароче какого нить изображения. ну и , конечно, при наведении нажатии битмапы менялись. Если кто нить знает где взять пример или инфу по данной теме, то подскажите плиззз. И ещё: вопрос касается
:!: НЕ MFC :!: а нуно именно под родной :!: API :!:
SeregaLBN
Сообщения: 23
Зарегистрирован: 17 фев 2004, 13:27
Откуда: Киев
Контактная информация:

27 сен 2004, 11:54

[Стиль BS_OWBERDRAW здесь не причём...
Тебе надо:
1. Установить у кнопки стиль BS_ICON или BS_BITMAP, в зависимости от того хочешь размещать иконку на кнопке или битмап.
2. Загрузи свои два рисунка - надо иметь их хэндлы. См. LoadImage, LoadIcon, ...
3. Ну и устанавка нужного рисунка:
::SendMessage(hWndButton, BM_SETIMAGE, (WPARAM)IMAGE_ICON, (LPARAM)hImageIcon); // для иконки
::SendMessage(hWndButton, BM_SETIMAGE, (WPARAM)IMAGE_BITMAP, (LPARAM)hImageBitmap); // для битмапы
Серёга, любит баранью ногу.
Alezis
Сообщения: 98
Зарегистрирован: 16 авг 2004, 01:10
Откуда: Минск
Контактная информация:

27 сен 2004, 17:19

Всё конечно было бы правильно если бы мне надо было сделать кнопку, а наверх её прикрепить битмап или иконку. В этом случае стандартная кнопка остается тока сверху висит картинка. Тогда действительно надо стиль включить BS_ICON или BS_BITMAP а дальше по алгоритму SeregaLBN, но... мне надо чтобы изображениее не вешалось на кнопку сверху, а кнопкой было само изображение, т.е. прерисовывать всю кнопку самому, а поэтому, если я ничего не напутал трэба поставить именно слиль BS_OWNERDRAW
SeregaLBN
Сообщения: 23
Зарегистрирован: 17 фев 2004, 13:27
Откуда: Киев
Контактная информация:

27 сен 2004, 20:00

Не, ну раз такое дело...
Тогда да, раз ты хочешь рисовать пымпочку полностью сам, то надо:
1. Иметь кнопку со стилем BS_OWNERDRAW
2. Иметь готовый хендл рисунка.
3. У окна на котором размещается это кнопка, надо перехватить сообщение WM_DRAWITEM.
4. Создай обработчик этого сообщения, и имея сруктуру DRAWITEMSTRUCT в этом обработчике, рисуй на DRAWITEMSTRUCT::hDC свои картинки (создавай совместимый HDC, ассоцируй с ним с помощью ::SelectObject хендл рисунка, и с помощью ::BitBlt/::StretchBlt переноси рисунок с совместимого HDC на DRAWITEMSTRUCT::hDC)
Й усё...
Серёга, любит баранью ногу.
Alezis
Сообщения: 98
Зарегистрирован: 16 авг 2004, 01:10
Откуда: Минск
Контактная информация:

27 сен 2004, 23:19

Не, ну раз такое дело...
Тогда да, раз ты хочешь рисовать пымпочку полностью сам, то надо:
1. Иметь кнопку со стилем BS_OWNERDRAW
2. Иметь готовый хендл рисунка.
3. У окна на котором размещается это кнопка, надо перехватить сообщение WM_DRAWITEM.
4. Создай обработчик этого сообщения, и имея сруктуру DRAWITEMSTRUCT в этом обработчике, рисуй на DRAWITEMSTRUCT::hDC свои картинки (создавай совместимый HDC, ассоцируй с ним с помощью ::SelectObject хендл рисунка, и с помощью ::BitBlt/::StretchBlt переноси рисунок с совместимого HDC на DRAWITEMSTRUCT::hDC)
Й усё...
так первые 2 пункта понятно.
Вопрос по 3:
после задания стиля BS_OWNERDRAW именно сообщения WM_DRAWITEM будут приходить либо WM_OWNERDRAW, просто уточнить надо, хотя моно и методом тыка проверить. Лана допустим с этим андерстенд.
Вопрос по 4:
структуру DRAWITEMSTRUCT надо где-то заполнять , вопрос тока где и главное как ??? Или же всё уже приходит заполненое(здеся немного туплю) :?
если можешьSeregaLBN объясни или можа прымер яки нить ёстика :?:
SeregaLBN
Сообщения: 23
Зарегистрирован: 17 фев 2004, 13:27
Откуда: Киев
Контактная информация:

28 сен 2004, 12:36

Структура DRAWITEMSTRUCT тебе приходит уже заполненная...
Держи пример.
Измени только в ::LoadImage пути к рисункам.

Код: Выделить всё

#ifdef UNICODE
   #pragma comment(linker, "/ENTRY:wWinMainCRTStartup")
#else
   #pragma comment(linker, "/ENTRY:WinMainCRTStartup")
#endif // UNICODE

#include <Windows.h>
#include <WindowsX.h>
#include <TChar.h>

HICON g_hIcon1 = NULL, g_hIcon2 = NULL; // хендлы иконок
HBITMAP g_hBmp1 = NULL, g_hBmp2 = NULL; // хендлы битмапы
HWND g_hWndBtn1 = NULL; // хендл кнопки c иконкой
HWND g_hWndBtn2 = NULL; // хендл кнопки с битмапой
BOOL g_bStateButton1 = FALSE;
BOOL g_bStateButton2 = FALSE;

SIZE SizeBitmap(HBITMAP hBmp) {
   SIZE resSize = {0,0};
   BITMAP bmp = {0,0,0,0,0,0,NULL};
   int iRes = ::GetObject(hBmp, sizeof(BITMAP), &bmp);
   if (iRes == sizeof(BITMAP)) {
      resSize.cx = bmp.bmWidth;
      resSize.cy = bmp.bmHeight;
   }
   return resSize;
}


SIZE SizeIcon(HICON hIcon) {
   SIZE resSize = {0,0};
   ICONINFO iconInfo;
   if (::GetIconInfo(hIcon, &iconInfo)) {
      resSize.cx = iconInfo.xHotspot<<1;
      resSize.cy = iconInfo.yHotspot<<1;
   }
   return resSize;
}

// обработчик сообщения WM_DRAWITEM
void OnDrawItem(HWND hWnd, const DRAWITEMSTRUCT *lpDrawItem) {
   //RECT rc = lpDrawItem->rcItem;
   //::DrawFrameControl(lpDrawItem->hDC, &rc, DFC_BUTTON, g_bStateButton1 ? DFCS_PUSHED|DFCS_BUTTONPUSH : DFCS_BUTTONPUSH);

   if (lpDrawItem->hwndItem == g_hWndBtn1)
   {
      HICON &hIco = g_bStateButton1 ? g_hIcon1 : g_hIcon2;
      BOOL bRes = ::DrawIconEx(
         lpDrawItem->hDC,
         0,0,
         hIco,
         lpDrawItem->rcItem.right - lpDrawItem->rcItem.left,  lpDrawItem->rcItem.bottom - lpDrawItem->rcItem.top,
         0,
         NULL,
         DI_NORMAL);
   }
   if (lpDrawItem->hwndItem == g_hWndBtn2)
   {
      HDC hCDC = ::CreateCompatibleDC(lpDrawItem->hDC);
      HBITMAP &hBmp = g_bStateButton2 ? g_hBmp1 : g_hBmp2;
      HBITMAP hBmpOld = (HBITMAP)::SelectObject(hCDC, hBmp);

      ::StretchBlt(
         lpDrawItem->hDC,
         0,0, lpDrawItem->rcItem.right - lpDrawItem->rcItem.left,  lpDrawItem->rcItem.bottom - lpDrawItem->rcItem.top,
         hCDC,
         0,0, SizeBitmap(hBmp).cx, SizeBitmap(hBmp).cy,
         SRCCOPY
      );

      ::SelectObject(hCDC, hBmpOld);
      ::DeleteDC(hCDC);
   }
}

// обработчик клика на кнопку с иконкой
void OnClickButton1() {
   g_bStateButton1 = !g_bStateButton1;
   ::InvalidateRect(g_hWndBtn1, NULL, TRUE);
}

// обработчик клика на кнопку с битмапой
void OnClickButton2() {
   g_bStateButton2 = !g_bStateButton2;
   ::InvalidateRect(g_hWndBtn2, NULL, TRUE);
}

// обработчик сообщения WM_COMMAND
void OnCommand(HWND hWnd, int id, HWND hWndCtl, UINT codeNotify) {
   if (hWndCtl == g_hWndBtn1) {
      if ((codeNotify == BN_CLICKED) || (codeNotify == BN_DOUBLECLICKED)) {
         OnClickButton1();
      }
   }
   if (hWndCtl == g_hWndBtn2) {
      if ((codeNotify == BN_CLICKED) || (codeNotify == BN_DOUBLECLICKED)) {
         OnClickButton2();
      }
   }
}

// обработчик сообщения WM_DESTROY
void OnDestroy(HWND hWnd) {
   ::DestroyIcon(g_hIcon1);
   ::DestroyIcon(g_hIcon2);
   ::DeleteObject(g_hBmp1);
   ::DeleteObject(g_hBmp2);
   ::PostQuitMessage(0);
}

// Процедра обработки оконных собщений
LRESULT CALLBACK WndProcTest(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam){
   switch(msg){
   HANDLE_MSG(hWnd, WM_DRAWITEM, OnDrawItem);
   HANDLE_MSG(hWnd, WM_DESTROY , OnDestroy );
   HANDLE_MSG(hWnd, WM_COMMAND , OnCommand );
   }
   return DefWindowProc(hWnd, msg, wParam, lParam);
}

// main функция
int WINAPI _tWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpszCmdLine, int nCmdShow )
{
   // создаю главное окно проги
   const WNDCLASS wc = {
      0,                                // UINT    style
      WndProcTest,                      // WNDPROC lpfnWndProc
      0,                                // int     cbClsExtra
      0,                                // int     cbWndExtra
      hInstance,                        // HANDLE  ghInstance
      LoadIcon  (NULL, IDI_APPLICATION),// HICON   hIcon
      LoadCursor(NULL, IDC_ARROW),      // HCURSOR hCursor
      GetSysColorBrush(COLOR_BTNFACE),  // HBRUSH  hbrBackground
      NULL,                             // LPCTSTR lpszMenuName
      TEXT("ClassWndProject")           // LPCTSTR lpszClassName
   };
   ::RegisterClass(&wc);
   HWND hWnd = ::CreateWindow( TEXT("ClassWndProject"), TEXT("Test Button Owner Draw"),
      WS_OVERLAPPED | WS_THICKFRAME | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX | WS_MAXIMIZEBOX,
      100, 100, 500, 300, NULL, (HMENU)0, hInstance, NULL );


   // создаю кнопку для иконки
   g_hWndBtn1 = ::CreateWindow(TEXT("button"), TEXT("пымпочка 1"), WS_CHILD | WS_VISIBLE | BS_OWNERDRAW,
      20, 20, 100, 30,
      hWnd, (HMENU)NULL, hInstance, NULL);
   // создаю кнопку для битмапы
   g_hWndBtn2 = ::CreateWindow(TEXT("button"), TEXT("пымпочка 2"), WS_CHILD | WS_VISIBLE | BS_OWNERDRAW,
      20, 60, 100, 30,
      hWnd, (HMENU)NULL, hInstance, NULL);

   // загружаю рисунки
   g_hIcon1 = (HICON)  ::LoadImage(hInstance, TEXT("btn1.ico"), IMAGE_ICON  , 0, 0, LR_DEFAULTCOLOR | LR_DEFAULTSIZE | LR_LOADFROMFILE);
   g_hIcon2 = (HICON)  ::LoadImage(hInstance, TEXT("btn2.ico"), IMAGE_ICON  , 0, 0, LR_DEFAULTCOLOR | LR_DEFAULTSIZE | LR_LOADFROMFILE);
   g_hBmp1  = (HBITMAP)::LoadImage(hInstance, TEXT("btn1.bmp"), IMAGE_BITMAP, 0, 0, LR_DEFAULTCOLOR | LR_DEFAULTSIZE | LR_LOADFROMFILE);
   g_hBmp2  = (HBITMAP)::LoadImage(hInstance, TEXT("btn2.bmp"), IMAGE_BITMAP, 0, 0, LR_DEFAULTCOLOR | LR_DEFAULTSIZE | LR_LOADFROMFILE);

   ShowWindow(hWnd, nCmdShow);

   MSG msg;
   while ( GetMessage(&msg, NULL, 0, 0)){
      DispatchMessage(&msg);
   }
   return msg.wParam;
}
Серёга, любит баранью ногу.
Alezis
Сообщения: 98
Зарегистрирован: 16 авг 2004, 01:10
Откуда: Минск
Контактная информация:

28 сен 2004, 20:54

SeregaLBN большое тебе человеческое сэнкс, ещё код не вставлял но есть точка опоры. Спасибо всем, вернее тока тебе :D
Buggy
Сообщения: 1
Зарегистрирован: 15 май 2005, 14:40
Откуда: Чебоксары
Контактная информация:

15 май 2005, 14:57

НАРОД!!! я понимаю прашел целый год, но все же попытаю счастье. В исходнике картинка меняется токо при нажатии на кнопку, я мучаюсь мучаюсь, а как сделать чтобы менялась при наведении мышки на эту кнопку???
Если ловить сообщение MOUSELEAVE то оно срабатывает также и при выходе курсора за границу клиентской части окна и при нахождении курсора над любым контролом.
Ответить