crashtuak
29-01-2010, 19:29
Была у меня проблема создания кнопки BS_OWNERDRAW. Впринципе проблему я решил, создав для себя удобный класс. Для загрузки и отрисовки картинок использовал стороннюю либу CxImage.
class PNG_Button
{
public:
int Create(int x_pos,int y_pos,int x_sz,int y_sz,HWND parent,
LPCSTR normalimage,
LPCSTR lightedimage,
LPCSTR pushedimage)
{
x_position=x_pos, y_position=y_pos, x_size=x_sz, y_size=y_sz, B_Parent=parent;
Handle=CreateWindowEx(0,"Button",NULL,WS_CHILD | WS_VISIBLE | BS_OWNERDRAW, x_position, y_position, x_size,y_size,B_Parent,NULL,NULL,NULL);
SetWindowLong(Handle, GWL_USERDATA, (LONG)this);
oldbtnproc=(WNDPROC)SetWindowLong(Handle, GWL_WNDPROC, (LONG)BNG_Button_Procedure);
bMouseTrack=false;
btnrect.left=x_pos,btnrect.top=y_pos,btnrect.right=x_pos+x_sz,btnrect.bottom=y_pos+y_sz;
//"E:\\TMP2\\btn_normal.png"
image[0].Load(normalimage,CXIMAGE_FORMAT_PNG);
image[1].Load(lightedimage,CXIMAGE_FORMAT_PNG);
image[2].Load(pushedimage,CXIMAGE_FORMAT_PNG);
draw=0;
if(Handle!=0)
{
//MessageBox(NULL,"Вызван конструктор PNG_Button","Диагностика",MB_OK);
return 0;
}
else
{
MessageBox(NULL,"Ошибка при создании\nкнопки.","Диагностика",MB_OK);
return -1;
}
}
int Draw()
{
HDC hdc;
PAINTSTRUCT ps;
hdc = BeginPaint(Handle, &ps);
image[draw].Draw(hdc,0,0,-1,-1,0,false);
EndPaint(Handle, &ps);
return 0;
}
static LRESULT CALLBACK BNG_Button_Procedure ( HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam )
{
PNG_Button* pThis = (PNG_Button*)GetWindowLong(hwnd, GWL_USERDATA);
switch ( msg )
{
case WM_LBUTTONDOWN:
//MessageBox(NULL, "Pushed", "Pushed", MB_ICONHAND);
pThis->draw=2;
InvalidateRect(pThis->B_Parent,&pThis->btnrect,false);
return 0;
case WM_MOUSELEAVE:
pThis->bMouseTrack = false;
//MessageBox(NULL,"Leaved","Leaved",MB_OK);
pThis->draw=0;
InvalidateRect(pThis->B_Parent,&pThis->btnrect,false);
return 0;
case WM_LBUTTONUP:
pThis->draw=1;
InvalidateRect(pThis->B_Parent,&pThis->btnrect,false);
return 0;
case WM_MOUSEMOVE:
if(pThis->bMouseTrack==false)
{
pThis->TrackMouse(pThis->Handle);
pThis->bMouseTrack = true;
pThis->draw=1;
InvalidateRect(pThis->B_Parent,&pThis->btnrect,false);
}
return 0;
}
return CallWindowProc(pThis->oldbtnproc, hwnd, msg, wParam, lParam);
}
private:
int draw;
CxImage image[3];
RECT btnrect;
WNDPROC oldbtnproc;
HWND Handle;
HWND B_Parent;
int x_position;
int y_position;
int x_size;
int y_size;
BOOL bMouseTrack;
BOOL TrackMouse(HWND i_hwnd)
{
TRACKMOUSEEVENT treMouse;
treMouse.cbSize=sizeof(TRACKMOUSEEVENT);
treMouse.hwndTrack=i_hwnd;
treMouse.dwFlags=TME_LEAVE ;
treMouse.dwHoverTime=1;
if (!TrackMouseEvent(&treMouse))
{
MessageBox(0, "::TrackMouseEvent failed!", "Error", MB_ICONHAND);
return false;
}
else
{
return true;
}
}
};
Делаем глобальными нужное число екземпляров класса PNG_Button pngbtn1, pngbtn2;, Далее код для создания самих кнопок:
pngbtn1.Create(100,100,31,31,hWnd,
"E:\\TMP2\\btn_normal.png",
"E:\\TMP2\\btn_lighted.png",
"E:\\TMP2\\btn_pushed.png");
pngbtn2.Create(200,200,75,23,hWnd,
"E:\\TMP2\\Новая папка\\400.bmpx",
"E:\\TMP2\\Новая папка\\402.bmpx",
"E:\\TMP2\\Новая папка\\401.bmpx");
При обработке события WM_PAINT окна, в котором находятся наши кнопки, надо выполнить функции:
pngbtn1.Draw();
pngbtn2.Draw();
этому коду характерен баг »У моей кнопке такого бага нету, потому что при WM_MOUSELEAVE картинка по любому сменяется на отжатую.
ПС: это черновая версия класса для кнопки, кому будет интересно, можно будет доработать.
class PNG_Button
{
public:
int Create(int x_pos,int y_pos,int x_sz,int y_sz,HWND parent,
LPCSTR normalimage,
LPCSTR lightedimage,
LPCSTR pushedimage)
{
x_position=x_pos, y_position=y_pos, x_size=x_sz, y_size=y_sz, B_Parent=parent;
Handle=CreateWindowEx(0,"Button",NULL,WS_CHILD | WS_VISIBLE | BS_OWNERDRAW, x_position, y_position, x_size,y_size,B_Parent,NULL,NULL,NULL);
SetWindowLong(Handle, GWL_USERDATA, (LONG)this);
oldbtnproc=(WNDPROC)SetWindowLong(Handle, GWL_WNDPROC, (LONG)BNG_Button_Procedure);
bMouseTrack=false;
btnrect.left=x_pos,btnrect.top=y_pos,btnrect.right=x_pos+x_sz,btnrect.bottom=y_pos+y_sz;
//"E:\\TMP2\\btn_normal.png"
image[0].Load(normalimage,CXIMAGE_FORMAT_PNG);
image[1].Load(lightedimage,CXIMAGE_FORMAT_PNG);
image[2].Load(pushedimage,CXIMAGE_FORMAT_PNG);
draw=0;
if(Handle!=0)
{
//MessageBox(NULL,"Вызван конструктор PNG_Button","Диагностика",MB_OK);
return 0;
}
else
{
MessageBox(NULL,"Ошибка при создании\nкнопки.","Диагностика",MB_OK);
return -1;
}
}
int Draw()
{
HDC hdc;
PAINTSTRUCT ps;
hdc = BeginPaint(Handle, &ps);
image[draw].Draw(hdc,0,0,-1,-1,0,false);
EndPaint(Handle, &ps);
return 0;
}
static LRESULT CALLBACK BNG_Button_Procedure ( HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam )
{
PNG_Button* pThis = (PNG_Button*)GetWindowLong(hwnd, GWL_USERDATA);
switch ( msg )
{
case WM_LBUTTONDOWN:
//MessageBox(NULL, "Pushed", "Pushed", MB_ICONHAND);
pThis->draw=2;
InvalidateRect(pThis->B_Parent,&pThis->btnrect,false);
return 0;
case WM_MOUSELEAVE:
pThis->bMouseTrack = false;
//MessageBox(NULL,"Leaved","Leaved",MB_OK);
pThis->draw=0;
InvalidateRect(pThis->B_Parent,&pThis->btnrect,false);
return 0;
case WM_LBUTTONUP:
pThis->draw=1;
InvalidateRect(pThis->B_Parent,&pThis->btnrect,false);
return 0;
case WM_MOUSEMOVE:
if(pThis->bMouseTrack==false)
{
pThis->TrackMouse(pThis->Handle);
pThis->bMouseTrack = true;
pThis->draw=1;
InvalidateRect(pThis->B_Parent,&pThis->btnrect,false);
}
return 0;
}
return CallWindowProc(pThis->oldbtnproc, hwnd, msg, wParam, lParam);
}
private:
int draw;
CxImage image[3];
RECT btnrect;
WNDPROC oldbtnproc;
HWND Handle;
HWND B_Parent;
int x_position;
int y_position;
int x_size;
int y_size;
BOOL bMouseTrack;
BOOL TrackMouse(HWND i_hwnd)
{
TRACKMOUSEEVENT treMouse;
treMouse.cbSize=sizeof(TRACKMOUSEEVENT);
treMouse.hwndTrack=i_hwnd;
treMouse.dwFlags=TME_LEAVE ;
treMouse.dwHoverTime=1;
if (!TrackMouseEvent(&treMouse))
{
MessageBox(0, "::TrackMouseEvent failed!", "Error", MB_ICONHAND);
return false;
}
else
{
return true;
}
}
};
Делаем глобальными нужное число екземпляров класса PNG_Button pngbtn1, pngbtn2;, Далее код для создания самих кнопок:
pngbtn1.Create(100,100,31,31,hWnd,
"E:\\TMP2\\btn_normal.png",
"E:\\TMP2\\btn_lighted.png",
"E:\\TMP2\\btn_pushed.png");
pngbtn2.Create(200,200,75,23,hWnd,
"E:\\TMP2\\Новая папка\\400.bmpx",
"E:\\TMP2\\Новая папка\\402.bmpx",
"E:\\TMP2\\Новая папка\\401.bmpx");
При обработке события WM_PAINT окна, в котором находятся наши кнопки, надо выполнить функции:
pngbtn1.Draw();
pngbtn2.Draw();
этому коду характерен баг »У моей кнопке такого бага нету, потому что при WM_MOUSELEAVE картинка по любому сменяется на отжатую.
ПС: это черновая версия класса для кнопки, кому будет интересно, можно будет доработать.