//========================================================================
//TITLE:
// 自绘按钮的实现
//AUTHOR:
// norains
//DATE:
// Saturday 12-January-2008
//Environment:
// VS2005 + SDK-WINCE5.0-MIPSII
// EVC + SDK-WINCE5.0-MIPSII
//========================================================================
自绘按钮的实现并不难,只不过如果是在非MFC类库中实现,却是显得有点麻烦,或是说,更需要一点小技巧.
文章打算在CMainWnd窗口类中实现一个自绘按钮,为了方便讲解以及突出重点,CMainWnd直接派生于CWndBase类.关于CWndBase类的信息,可以在此找到:http://blog.youkuaiyun.com/norains/archive/2008/01/12/2040109.aspx
首先我们先要创建一个按钮,我将它命名为m_hBnExit:
m_hBnExit
=
CreateWindowEx(WS_EX_TOPMOST,
TEXT( " BUTTON " ),
TEXT( "" ),
BS_PUSHBUTTON | WS_VISIBLE | WS_CHILD | BS_OWNERDRAW ,
POS_EXIT.left,
POS_EXIT.top,
POS_EXIT.right - POS_EXIT.left,
POS_EXIT.bottom - POS_EXIT.top,
m_hWnd,
(HMENU)IDC_BTN_EXIT,
m_hInst,
NULL);
TEXT( " BUTTON " ),
TEXT( "" ),
BS_PUSHBUTTON | WS_VISIBLE | WS_CHILD | BS_OWNERDRAW ,
POS_EXIT.left,
POS_EXIT.top,
POS_EXIT.right - POS_EXIT.left,
POS_EXIT.bottom - POS_EXIT.top,
m_hWnd,
(HMENU)IDC_BTN_EXIT,
m_hInst,
NULL);
这里有点需要注意,因为我们需要重新绘制按钮,所以BS_OWNERDRAW风格一定需要设置.一旦设置该风格,CMainWnd窗口的消息处理函数就能接收到按钮的WM_DRAWITEM消息:
LRESULT CMainWnd::WndProc(HWND hWnd, UINT wMsg, WPARAM wParam, LPARAM lParam)
{
...
switch (wMsg)
{
case WM_DRAWITEM:
if (((LPDRAWITEMSTRUCT)lParam) -> CtlID == IDC_BTN_EXIT)
{
// TODO something;
}
...
}
...
}
{
...
switch (wMsg)
{
case WM_DRAWITEM:
if (((LPDRAWITEMSTRUCT)lParam) -> CtlID == IDC_BTN_EXIT)
{
// TODO something;
}
...
}
...
}
接下来需要做的就很简单了,我们只需要在接收到WM_DRAWITEM消息时,判断是否为退出按键的ID号(在本文例子中为IDC_BTN_EXIT),如果是的话就重新绘制.为此,我们定义一个OnDrawItemBtnExit()函数,用来绘制该按钮:
void
CMainWnd::OnDrawItemBtnExit(HWND hWnd, UINT wMsg, WPARAM wParam, LPARAM lParam)
{
LPDRAWITEMSTRUCT lpdis = (LPDRAWITEMSTRUCT) lParam;
// 读取按钮的图片
HANDLE hBmp = LoadImage(m_hInst,MAKEINTRESOURCE(IDB_EXIT),IMAGE_BITMAP, 0 , 0 , 0 );
if (hBmp == NULL)
{
return ;
}
// Draw the button
HDC hdcBmp = CreateCompatibleDC(lpdis -> hDC);
HGDIOBJ hOldSel = SelectObject(hdcBmp,hBmp);
if ((lpdis -> itemState & ODS_SELECTED ) && ! (lpdis -> itemState & ODS_DISABLED))
{
// 按下状态
TransparentBlt(lpdis -> hDC,
lpdis -> rcItem.left,
lpdis -> rcItem.top,
lpdis -> rcItem.right - lpdis -> rcItem.left,
lpdis -> rcItem.bottom - lpdis -> rcItem.top,
hdcBmp,
IMG_EXIT_PUSH.left,
IMG_EXIT_PUSH.top,
IMG_EXIT_PUSH.right - IMG_EXIT_PUSH.left,
IMG_EXIT_PUSH.bottom - IMG_EXIT_PUSH.top,
DEFAULT_TRANSPARENT_COLOR);
}
else if (lpdis -> itemState & ODS_DISABLED)
{
// 无效状态
TransparentBlt(lpdis -> hDC,
lpdis -> rcItem.left,
lpdis -> rcItem.top,
lpdis -> rcItem.right - lpdis -> rcItem.left,
lpdis -> rcItem.bottom - lpdis -> rcItem.top,
hdcBmp,
IMG_EXIT_DISABLE.left,
IMG_EXIT_DISABLE.top,
IMG_EXIT_DISABLE.right - IMG_EXIT_DISABLE.left,
IMG_EXIT_DISABLE.bottom - IMG_EXIT_DISABLE.top,
DEFAULT_TRANSPARENT_COLOR);
}
else
{
// 正常状态
TransparentBlt(lpdis -> hDC,
lpdis -> rcItem.left,
lpdis -> rcItem.top,
lpdis -> rcItem.right - lpdis -> rcItem.left,
lpdis -> rcItem.bottom - lpdis -> rcItem.top,
hdcBmp,
IMG_EXIT_ENABLE.left,
IMG_EXIT_ENABLE.top,
IMG_EXIT_ENABLE.right - IMG_EXIT_ENABLE.left,
IMG_EXIT_ENABLE.bottom - IMG_EXIT_ENABLE.top,
DEFAULT_TRANSPARENT_COLOR);
}
if (hdcBmp != NULL && hOldSel != NULL)
{
SelectObject(hdcBmp,hOldSel);
DeleteDC(hdcBmp);
hdcBmp = NULL;
hOldSel = NULL;
}
if (hBmp != NULL)
{
DeleteObject(hBmp);
hBmp = NULL;
}
}
{
LPDRAWITEMSTRUCT lpdis = (LPDRAWITEMSTRUCT) lParam;
// 读取按钮的图片
HANDLE hBmp = LoadImage(m_hInst,MAKEINTRESOURCE(IDB_EXIT),IMAGE_BITMAP, 0 , 0 , 0 );
if (hBmp == NULL)
{
return ;
}
// Draw the button
HDC hdcBmp = CreateCompatibleDC(lpdis -> hDC);
HGDIOBJ hOldSel = SelectObject(hdcBmp,hBmp);
if ((lpdis -> itemState & ODS_SELECTED ) && ! (lpdis -> itemState & ODS_DISABLED))
{
// 按下状态
TransparentBlt(lpdis -> hDC,
lpdis -> rcItem.left,
lpdis -> rcItem.top,
lpdis -> rcItem.right - lpdis -> rcItem.left,
lpdis -> rcItem.bottom - lpdis -> rcItem.top,
hdcBmp,
IMG_EXIT_PUSH.left,
IMG_EXIT_PUSH.top,
IMG_EXIT_PUSH.right - IMG_EXIT_PUSH.left,
IMG_EXIT_PUSH.bottom - IMG_EXIT_PUSH.top,
DEFAULT_TRANSPARENT_COLOR);
}
else if (lpdis -> itemState & ODS_DISABLED)
{
// 无效状态
TransparentBlt(lpdis -> hDC,
lpdis -> rcItem.left,
lpdis -> rcItem.top,
lpdis -> rcItem.right - lpdis -> rcItem.left,
lpdis -> rcItem.bottom - lpdis -> rcItem.top,
hdcBmp,
IMG_EXIT_DISABLE.left,
IMG_EXIT_DISABLE.top,
IMG_EXIT_DISABLE.right - IMG_EXIT_DISABLE.left,
IMG_EXIT_DISABLE.bottom - IMG_EXIT_DISABLE.top,
DEFAULT_TRANSPARENT_COLOR);
}
else
{
// 正常状态
TransparentBlt(lpdis -> hDC,
lpdis -> rcItem.left,
lpdis -> rcItem.top,
lpdis -> rcItem.right - lpdis -> rcItem.left,
lpdis -> rcItem.bottom - lpdis -> rcItem.top,
hdcBmp,
IMG_EXIT_ENABLE.left,
IMG_EXIT_ENABLE.top,
IMG_EXIT_ENABLE.right - IMG_EXIT_ENABLE.left,
IMG_EXIT_ENABLE.bottom - IMG_EXIT_ENABLE.top,
DEFAULT_TRANSPARENT_COLOR);
}
if (hdcBmp != NULL && hOldSel != NULL)
{
SelectObject(hdcBmp,hOldSel);
DeleteDC(hdcBmp);
hdcBmp = NULL;
hOldSel = NULL;
}
if (hBmp != NULL)
{
DeleteObject(hBmp);
hBmp = NULL;
}
}
不过这么一来会有个很明显的问题,如图1:

我们发现在按钮周围有一圈非常不雅的灰色地带,而这灰色区域是窗口创建的时候自绘的.有经验的朋友都知道,如果是自己创建的窗口,要让这灰色区域消失是非常简单的事情,只需要在调用RegisterClass函数时选择一个无颜色的画刷即可.但由于所有的Windows Control的注册函数都是封装的,我们无法对其参数进行变更,所以唯一的方法只能是另寻窍门.
所谓的去掉灰色地带,无非就是把主窗口那处被掩盖的区域重新绘制出来.有这个思路一切就好办了,我们只需要在主窗口的WM_PAINT响应函数中存储主窗口的DC数据,然后在按钮重绘的时候再把它显示出来即可:
void
CMainWnd::OnPaint(HWND hWnd, UINT wMsg, WPARAM wParam, LPARAM lParam)
{
...
// 存储主窗口的所有DC数据到m_hdcBufBk中
// Create the memory DC for storing the background.
m_hBmpBufBk = CreateCompatibleBitmap(hdc,rcWnd.right - rcWnd.left,rcWnd.bottom - rcWnd.top);
m_hdcBufBk = CreateCompatibleDC(hdc);
m_hOldSelBufBk = SelectObject(m_hdcBufBk,m_hBmpBufBk);
// Draw the background
HPEN hPen = CreatePen(PS_SOLID, 1 ,RGB( 0 , 255 , 0 ));
HPEN hOldPen = NULL;
hOldPen = (HPEN)SelectObject(m_hdcBufBk,hPen);
// the rect color
HBRUSH hBrush = CreateSolidBrush(RGB( 0 , 255 , 0 ));
HGDIOBJ hOldBrush = SelectObject(m_hdcBufBk,hBrush);
// Draw
Rectangle(m_hdcBufBk, 0 , 0 ,rcWnd.right - rcWnd.left + 1 , rcWnd.bottom - rcWnd.top + 1 );
// Realse the resource
SelectObject(m_hdcBufBk,hOldBrush);
DeleteObject(hBrush);
SelectObject(m_hdcBufBk,hOldPen);
DeleteObject(hPen);
...
}
{
...
// 存储主窗口的所有DC数据到m_hdcBufBk中
// Create the memory DC for storing the background.
m_hBmpBufBk = CreateCompatibleBitmap(hdc,rcWnd.right - rcWnd.left,rcWnd.bottom - rcWnd.top);
m_hdcBufBk = CreateCompatibleDC(hdc);
m_hOldSelBufBk = SelectObject(m_hdcBufBk,m_hBmpBufBk);
// Draw the background
HPEN hPen = CreatePen(PS_SOLID, 1 ,RGB( 0 , 255 , 0 ));
HPEN hOldPen = NULL;
hOldPen = (HPEN)SelectObject(m_hdcBufBk,hPen);
// the rect color
HBRUSH hBrush = CreateSolidBrush(RGB( 0 , 255 , 0 ));
HGDIOBJ hOldBrush = SelectObject(m_hdcBufBk,hBrush);
// Draw
Rectangle(m_hdcBufBk, 0 , 0 ,rcWnd.right - rcWnd.left + 1 , rcWnd.bottom - rcWnd.top + 1 );
// Realse the resource
SelectObject(m_hdcBufBk,hOldBrush);
DeleteObject(hBrush);
SelectObject(m_hdcBufBk,hOldPen);
DeleteObject(hPen);
...
}
然后在按钮的自绘函数中将其绘制出来:
void
CMainWnd::OnDrawItemBtnExit(HWND hWnd, UINT wMsg, WPARAM wParam, LPARAM lParam)
{
...
// Draw the background
BitBlt(lpdis -> hDC,
lpdis -> rcItem.left,
lpdis -> rcItem.top,
lpdis -> rcItem.right - lpdis -> rcItem.left,
lpdis -> rcItem.bottom - lpdis -> rcItem.top,
m_hdcBufBk,
POS_EXIT.left,
POS_EXIT.top,
SRCCOPY);
...
}
{
...
// Draw the background
BitBlt(lpdis -> hDC,
lpdis -> rcItem.left,
lpdis -> rcItem.top,
lpdis -> rcItem.right - lpdis -> rcItem.left,
lpdis -> rcItem.bottom - lpdis -> rcItem.top,
m_hdcBufBk,
POS_EXIT.left,
POS_EXIT.top,
SRCCOPY);
...
}
添加背景绘制代码之后显示的效果如图2所示:

如果你的目的仅仅是用图片替代原来那种死板的按钮样式的话,那么到这步已经是大功告成,可以举杯欢庆了.但如果你还需要更多的需求,比如显示出通过SetWindowText设置的字符串,那么你还必须要做更多的工作.
因为我们无法直接通过GetWindowText获取设置文本的真正长度,所以我们必须在按钮接收WM_SETTEXT消息时获取窗口文本.也许有人说,我设置一个很大的缓冲区不就行了么?可是,你需要设置多大?最好不要抱这种想法,因为我们永远不知道用户的真正意思!
除了文档中明白指出的按钮消息,其它的消息我们都无法在MainProc函数中截获,比如按钮的WM_PAINT,WM_ERASEBKGND等.所以,这里我们需要在创建按钮控件的时候用SetWindowLong函数来转移按钮消息(关于SetWindowLong与消息转移可以参加我这篇文章:http://blog.youkuaiyun.com/norains/archive/2008/01/03/2023986.aspx).
//
Store the pointer in the window
SetWindowLong(m_hBnExit, GWL_USERDATA, (DWORD) this );
// Set the new window procedure
m_PreProcBnExit = (WNDPROC)SetWindowLong(m_hBnExit,GWL_WNDPROC,(DWORD)CtrlProc);
SetWindowLong(m_hBnExit, GWL_USERDATA, (DWORD) this );
// Set the new window procedure
m_PreProcBnExit = (WNDPROC)SetWindowLong(m_hBnExit,GWL_WNDPROC,(DWORD)CtrlProc);
我们需要在转移的消息处理函数中截获WM_SETTEXT消息,并分配合适的内存空间存储设置的字符串:
LRESULT CMainWnd::CtrlProc(HWND hWnd, UINT wMsg, WPARAM wParam, LPARAM lParam)
{
CMainWnd * pObject = (CMainWnd * )GetWindowLong(hWnd,GWL_USERDATA);
if (pObject != NULL)
{
if (hWnd == pObject -> m_hBnExit)
{
switch (wMsg)
{
case WM_SETTEXT:
{
if (pObject -> m_pszBnExit != NULL)
{
delete []pObject -> m_pszBnExit;
pObject -> m_pszBnExit = NULL;
}
pObject -> m_pszBnExit = new TCHAR [_tcslen( reinterpret_cast < LPCTSTR > (lParam)) + 1 ];
_tcscpy(pObject -> m_pszBnExit,reinterpret_cast < LPCTSTR > (lParam));
break ;
}
}
return CallWindowProc(pObject -> m_PreProcBnExit,hWnd,wMsg,wParam,lParam);
}
}
return DefWindowProc(hWnd,wMsg,wParam,lParam);
}
{
CMainWnd * pObject = (CMainWnd * )GetWindowLong(hWnd,GWL_USERDATA);
if (pObject != NULL)
{
if (hWnd == pObject -> m_hBnExit)
{
switch (wMsg)
{
case WM_SETTEXT:
{
if (pObject -> m_pszBnExit != NULL)
{
delete []pObject -> m_pszBnExit;
pObject -> m_pszBnExit = NULL;
}
pObject -> m_pszBnExit = new TCHAR [_tcslen( reinterpret_cast < LPCTSTR > (lParam)) + 1 ];
_tcscpy(pObject -> m_pszBnExit,reinterpret_cast < LPCTSTR > (lParam));
break ;
}
}
return CallWindowProc(pObject -> m_PreProcBnExit,hWnd,wMsg,wParam,lParam);
}
}
return DefWindowProc(hWnd,wMsg,wParam,lParam);
}
既然我们已经获得了字符串,要绘制出来就是轻而易举的事情了:
void
CMainWnd::OnDrawItemBtnExit(HWND hWnd, UINT wMsg, WPARAM wParam, LPARAM lParam)
{
...
// Draw the text
SetBkMode(lpdis -> hDC,TRANSPARENT);
DrawText(lpdis -> hDC,m_pszBnExit, - 1 , & lpdis -> rcItem,DT_CENTER | DT_VCENTER);
...
}
{
...
// Draw the text
SetBkMode(lpdis -> hDC,TRANSPARENT);
DrawText(lpdis -> hDC,m_pszBnExit, - 1 , & lpdis -> rcItem,DT_CENTER | DT_VCENTER);
...
}
该工程可以在此下载:http://download.youkuaiyun.com/source/333479
CMainWnd完整的代码如下:
#pragma once
#include " Wndbase.h "
class CMainWnd :
public CWndBase
{
public :
virtual BOOL Create(HINSTANCE hInst, HWND hWndParent, const TCHAR * pcszWndClass, const TCHAR * pcszWndName);
CMainWnd( void );
~ CMainWnd( void );
protected :
virtual LRESULT WndProc(HWND hWnd, UINT wMsg, WPARAM wParam, LPARAM lParam);
static LRESULT CtrlProc(HWND hWnd, UINT wMsg, WPARAM wParam, LPARAM lParam);
void OnClickedBtnExit(HWND hWnd, UINT wMsg, WPARAM wParam, LPARAM lParam);
void OnDrawItemBtnExit(HWND hWnd, UINT wMsg, WPARAM wParam, LPARAM lParam);
void OnPaint(HWND hWnd, UINT wMsg, WPARAM wParam, LPARAM lParam);
private :
HDC m_hdcBufBk; // The dc buffer is just for storing the background data.
HBITMAP m_hBmpBufBk;
HGDIOBJ m_hOldSelBufBk;
HWND m_hBnExit;
TCHAR * m_pszBnExit;
WNDPROC m_PreProcBnExit;
};
#include " stdafx.h "
#include " resource.h "
#include " MainWnd.h "
// *****************************************************************************************************
// The default transparent color for the image
#define DEFAULT_TRANSPARENT_COLOR RGB(255,0,255)
// *****************************************************************************************************
// The struct data
// The image displayed information
#ifndef _DISPIMAGEINFO
#define _DISPIMAGEINFO
typedef struct
{
LONG imgID;
LONG left;
LONG top;
LONG right;
LONG bottom;
}DISPIMAGEINFO, * PDISPIMAGEINFO;
#endif // _DISPIMAGEINFO
// ------------------------------------------------------------------------------
// The resource information
const DISPIMAGEINFO IMG_EXIT_ENABLE = {IDB_EXIT, 1 , 1 , 46 , 46 };
const DISPIMAGEINFO IMG_EXIT_DISABLE = {IDB_EXIT, 93 , 1 , 138 , 46 };
const DISPIMAGEINFO IMG_EXIT_PUSH = {IDB_EXIT, 47 , 1 , 92 , 46 };
// *****************************************************************************************************
// -------------------------------------------------------------------
// Macro
#define IDC_BTN_EXIT 103
// -------------------------------------------------------------------
// const value
const RECT POS_EXIT = { 0 , 0 , 45 , 45 };
// -------------------------------------------------------------------
CMainWnd::CMainWnd( void ):
m_hBnExit(NULL),
m_hdcBufBk(NULL),
m_hBmpBufBk(NULL),
m_hOldSelBufBk(NULL),
m_PreProcBnExit(NULL),
m_pszBnExit(NULL)
{
}
CMainWnd:: ~ CMainWnd( void )
{
if (m_hdcBufBk != NULL && m_hOldSelBufBk != NULL)
{
SelectObject(m_hdcBufBk,m_hOldSelBufBk);
}
if (m_hBmpBufBk != NULL)
{
DeleteObject(m_hBmpBufBk);
m_hBmpBufBk = NULL;
}
if (m_hdcBufBk != NULL)
{
DeleteDC(m_hdcBufBk);
m_hdcBufBk = NULL;
}
if (m_pszBnExit != NULL)
{
delete []m_pszBnExit;
m_pszBnExit = NULL;
}
}
// ----------------------------------------------------------------------
// Description:
// Create the window. It's override function
//
// ----------------------------------------------------------------------
BOOL CMainWnd::Create(HINSTANCE hInst, HWND hWndParent, const TCHAR * pcszWndClass, const TCHAR * pcszWndName)
{
CWndBase::Create(hInst,hWndParent,pcszWndClass,pcszWndName);
// The button for exiting
m_hBnExit = CreateWindowEx(WS_EX_TOPMOST,
TEXT( " BUTTON " ),
TEXT( "" ),
BS_PUSHBUTTON | BS_CENTER | WS_TABSTOP | WS_VISIBLE | WS_CHILD | BS_OWNERDRAW ,
POS_EXIT.left,
POS_EXIT.top,
POS_EXIT.right - POS_EXIT.left,
POS_EXIT.bottom - POS_EXIT.top,
m_hWnd,
(HMENU)IDC_BTN_EXIT,
m_hInst,
NULL);
// Store the pointer in the window
SetWindowLong(m_hBnExit, GWL_USERDATA, (DWORD) this );
// Set the new window procedure
m_PreProcBnExit = (WNDPROC)SetWindowLong(m_hBnExit,GWL_WNDPROC,(DWORD)CtrlProc);
SetWindowText(m_hBnExit,TEXT( " X " ));
return TRUE;
}
// ----------------------------------------------------------------------
// Description:
// Window process. It's override function
//
// ----------------------------------------------------------------------
LRESULT CMainWnd::WndProc(HWND hWnd, UINT wMsg, WPARAM wParam, LPARAM lParam)
{
switch (wMsg)
{
case WM_DRAWITEM:
if (((LPDRAWITEMSTRUCT)lParam) -> CtlID == IDC_BTN_EXIT)
{
OnDrawItemBtnExit(hWnd,wMsg,wParam,lParam);
return 0 ;
}
case WM_COMMAND:
{
if (HIWORD(wParam) == BN_CLICKED && LOWORD(wParam) == IDC_BTN_EXIT)
{
OnClickedBtnExit(hWnd,wMsg,wParam,lParam);
}
}
case WM_PAINT:
{
OnPaint(hWnd,wMsg,wParam,lParam);
return 0 ;
}
}
return DefWindowProc(hWnd,wMsg,wParam,lParam);
}
// ----------------------------------------------------------------------
// Description:
// Windows control process
//
// ----------------------------------------------------------------------
LRESULT CMainWnd::CtrlProc(HWND hWnd, UINT wMsg, WPARAM wParam, LPARAM lParam)
{
CMainWnd * pObject = (CMainWnd * )GetWindowLong(hWnd,GWL_USERDATA);
if (pObject != NULL)
{
if (hWnd == pObject -> m_hBnExit)
{
switch (wMsg)
{
case WM_SETTEXT:
{
if (pObject -> m_pszBnExit != NULL)
{
delete []pObject -> m_pszBnExit;
pObject -> m_pszBnExit = NULL;
}
pObject -> m_pszBnExit = new TCHAR [_tcslen( reinterpret_cast < LPCTSTR > (lParam)) + 1 ];
_tcscpy(pObject -> m_pszBnExit,reinterpret_cast < LPCTSTR > (lParam));
break ;
}
}
return CallWindowProc(pObject -> m_PreProcBnExit,hWnd,wMsg,wParam,lParam);
}
}
return DefWindowProc(hWnd,wMsg,wParam,lParam);
}
// -----------------------------------------------------------------------------------------
// Description:
// On the message WM_DRAWITEM and it is for the button exit
//
// ----------------------------------------------------------------------------------------------
void CMainWnd::OnDrawItemBtnExit(HWND hWnd, UINT wMsg, WPARAM wParam, LPARAM lParam)
{
LPDRAWITEMSTRUCT lpdis = (LPDRAWITEMSTRUCT) lParam;
HANDLE hBmp = LoadImage(m_hInst,MAKEINTRESOURCE(IDB_EXIT),IMAGE_BITMAP, 0 , 0 , 0 );
if (hBmp == NULL)
{
return ;
}
// Draw the background
BitBlt(lpdis -> hDC,
lpdis -> rcItem.left,
lpdis -> rcItem.top,
lpdis -> rcItem.right - lpdis -> rcItem.left,
lpdis -> rcItem.bottom - lpdis -> rcItem.top,
m_hdcBufBk,
POS_EXIT.left,
POS_EXIT.top,
SRCCOPY);
// Draw the button
HDC hdcBmp = CreateCompatibleDC(lpdis -> hDC);
HGDIOBJ hOldSel = SelectObject(hdcBmp,hBmp);
if ((lpdis -> itemState & ODS_SELECTED ) && ! (lpdis -> itemState & ODS_DISABLED))
{
TransparentBlt(lpdis -> hDC,
lpdis -> rcItem.left,
lpdis -> rcItem.top,
lpdis -> rcItem.right - lpdis -> rcItem.left,
lpdis -> rcItem.bottom - lpdis -> rcItem.top,
hdcBmp,
IMG_EXIT_PUSH.left,
IMG_EXIT_PUSH.top,
IMG_EXIT_PUSH.right - IMG_EXIT_PUSH.left,
IMG_EXIT_PUSH.bottom - IMG_EXIT_PUSH.top,
DEFAULT_TRANSPARENT_COLOR);
}
else if (lpdis -> itemState & ODS_DISABLED)
{
TransparentBlt(lpdis -> hDC,
lpdis -> rcItem.left,
lpdis -> rcItem.top,
lpdis -> rcItem.right - lpdis -> rcItem.left,
lpdis -> rcItem.bottom - lpdis -> rcItem.top,
hdcBmp,
IMG_EXIT_DISABLE.left,
IMG_EXIT_DISABLE.top,
IMG_EXIT_DISABLE.right - IMG_EXIT_DISABLE.left,
IMG_EXIT_DISABLE.bottom - IMG_EXIT_DISABLE.top,
DEFAULT_TRANSPARENT_COLOR);
}
else
{
TransparentBlt(lpdis -> hDC,
lpdis -> rcItem.left,
lpdis -> rcItem.top,
lpdis -> rcItem.right - lpdis -> rcItem.left,
lpdis -> rcItem.bottom - lpdis -> rcItem.top,
hdcBmp,
IMG_EXIT_ENABLE.left,
IMG_EXIT_ENABLE.top,
IMG_EXIT_ENABLE.right - IMG_EXIT_ENABLE.left,
IMG_EXIT_ENABLE.bottom - IMG_EXIT_ENABLE.top,
DEFAULT_TRANSPARENT_COLOR);
}
if (hdcBmp != NULL && hOldSel != NULL)
{
SelectObject(hdcBmp,hOldSel);
DeleteDC(hdcBmp);
hdcBmp = NULL;
hOldSel = NULL;
}
if (hBmp != NULL)
{
DeleteObject(hBmp);
hBmp = NULL;
}
// Draw the text
SetBkMode(lpdis -> hDC,TRANSPARENT);
DrawText(lpdis -> hDC,m_pszBnExit, - 1 , & lpdis -> rcItem,DT_CENTER | DT_VCENTER);
}
// -----------------------------------------------------------------------------------------
// Description:
// On the message WM_COMMAND and the HIWORD(wParam) is BN_CLICKED for the button exit
//
// ----------------------------------------------------------------------------------------------
void CMainWnd::OnClickedBtnExit(HWND hWnd, UINT wMsg, WPARAM wParam, LPARAM lParam)
{
DestroyWindow(m_hWnd);
PostQuitMessage( 0x00 );
}
// -----------------------------------------------------------------------------------------
// Description:
// On the message WM_PAINT.
//
// ----------------------------------------------------------------------------------------------
void CMainWnd::OnPaint(HWND hWnd, UINT wMsg, WPARAM wParam, LPARAM lParam)
{
RECT rcWnd = { 0 };
GetWindowRect(hWnd, & rcWnd);
PAINTSTRUCT ps;
HDC hdc = BeginPaint(hWnd, & ps);
if (m_hdcBufBk == NULL)
{
// Create the memory DC for storing the background.
m_hBmpBufBk = CreateCompatibleBitmap(hdc,rcWnd.right - rcWnd.left,rcWnd.bottom - rcWnd.top);
m_hdcBufBk = CreateCompatibleDC(hdc);
m_hOldSelBufBk = SelectObject(m_hdcBufBk,m_hBmpBufBk);
// Draw the background
HPEN hPen = CreatePen(PS_SOLID, 1 ,RGB( 0 , 255 , 0 ));
HPEN hOldPen = NULL;
hOldPen = (HPEN)SelectObject(m_hdcBufBk,hPen);
// the rect color
HBRUSH hBrush = CreateSolidBrush(RGB( 0 , 255 , 0 ));
HGDIOBJ hOldBrush = SelectObject(m_hdcBufBk,hBrush);
// Draw
Rectangle(m_hdcBufBk, 0 , 0 ,rcWnd.right - rcWnd.left + 1 , rcWnd.bottom - rcWnd.top + 1 );
// Realse the resource
SelectObject(m_hdcBufBk,hOldBrush);
DeleteObject(hBrush);
SelectObject(m_hdcBufBk,hOldPen);
DeleteObject(hPen);
}
BitBlt(hdc,
rcWnd.left,
rcWnd.top,
rcWnd.right - rcWnd.left,
rcWnd.bottom - rcWnd.top,
m_hdcBufBk,
rcWnd.left,
rcWnd.top,
SRCCOPY);
EndPaint(hWnd, & ps);
UpdateWindow(m_hBnExit);
}