PDA

Просмотр полной версии : Кнопки и стиль BS_OWNERDRAW



Alezis
26.09.2004, 22:43
Нужно создать кнопку чтобы она была представлена в виде битмапа, кароче какого нить изображения. ну и , конечно, при наведении нажатии битмапы менялись. Если кто нить знает где взять пример или инфу по данной теме, то подскажите плиззз. И ещё: вопрос касается
:!: НЕ MFC :!: а нуно именно под родной :!: API :!:

SeregaLBN
27.09.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
27.09.2004, 17:19
Всё конечно было бы правильно если бы мне надо было сделать кнопку, а наверх её прикрепить битмап или иконку. В этом случае стандартная кнопка остается тока сверху висит картинка. Тогда действительно надо стиль включить BS_ICON или BS_BITMAP а дальше по алгоритму SeregaLBN, но... мне надо чтобы изображениее не вешалось на кнопку сверху, а кнопкой было само изображение, т.е. прерисовывать всю кнопку самому, а поэтому, если я ничего не напутал трэба поставить именно слиль BS_OWNERDRAW

SeregaLBN
27.09.2004, 20:00
Не, ну раз такое дело...
Тогда да, раз ты хочешь рисовать пымпочку полностью сам, то надо:
1. Иметь кнопку со стилем BS_OWNERDRAW
2. Иметь готовый хендл рисунка.
3. У окна на котором размещается это кнопка, надо перехватить сообщение WM_DRAWITEM.
4. Создай обработчик этого сообщения, и имея сруктуру DRAWITEMSTRUCT в этом обработчике, рисуй на DRAWITEMSTRUCT::hDC свои картинки (создавай совместимый HDC, ассоцируй с ним с помощью ::SelectObject хендл рисунка, и с помощью ::BitBlt/::StretchBlt переноси рисунок с совместимого HDC на DRAWITEMSTRUCT::hDC)
Й усё...

Alezis
27.09.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
28.09.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
28.09.2004, 20:54
SeregaLBN большое тебе человеческое сэнкс, ещё код не вставлял но есть точка опоры. Спасибо всем, вернее тока тебе :D

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