網上找了很多,可只是給出代碼,沒有詳細解釋,不便初學者理解.我就抄回冷飯.把這個再拿出來說說.
實例圖片:

首先建立一個標准的Win32 Application 工程.選擇a simple Win32 Application.
然后建立我們的資源文件首先新建一個對話框資源,資源ID改為IDD_MAIN_DLG
然后在其上新建一個按鈕控件資源ID改為IDC_ODBUTTON,此按鈕的styles中必須選中owenerdraw屬性.
然后將其保存為.rc的資源文件.並將其導入我們的工程.同理新建一個圖標文件資源ID改為IDI_OWNERDRAW保存為.ico的圖標然后導入.
准備工作做完了下面開始寫代碼.
首先聲明如下全局變量.
#include "stdafx.h"
#include "resource.h"
#include "resource.h"
HINSTANCE odInst = NULL; //接收程序實例的句柄
HWND hMainWnd = NULL; //接收主窗口的句柄
HWND hDlgNow = NULL; //接收對話框的句柄
static HICON hOwnerDrawIcon = NULL; //用作自繪按鈕的圖標
static LONG prev_proc; //儲存按鈕先前的回調函數
static HICON hIcon = NULL; //對話框圖標句柄
HWND hMainWnd = NULL; //接收主窗口的句柄
HWND hDlgNow = NULL; //接收對話框的句柄
static HICON hOwnerDrawIcon = NULL; //用作自繪按鈕的圖標
static LONG prev_proc; //儲存按鈕先前的回調函數
static HICON hIcon = NULL; //對話框圖標句柄
然后開始寫WinMain()函數
int APIENTRY WinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
int nCmdShow)
{
// TODO: Place code here.
odInst = hInstance;
WNDCLASS wc;
wc.style = 0;
wc.lpfnWndProc = (WNDPROC)ODWndProc; //定義一個窗口默認函數,這里我們會交由默認窗口函數處理
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = hInstance;
wc.hIcon = LoadIcon(odInst,MAKEINTRESOURCE(IDI_OWNERDRAW));
wc.hCursor = NULL;
wc.hbrBackground = 0;
wc.lpszClassName = "OwnerDraw";
wc.lpszMenuName = NULL;
RegisterClass(&wc);
MSG msg;
HWND onlywin= FindWindow("OwnerDraw","MyOwnerDraw");
if (onlywin)
{
ExitProcess(1);
}
hMainWnd=CreateWindow("OwnerDraw","MyOwnerDraw",WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT,0,CW_USEDEFAULT,0,NULL,NULL,hInstance,NULL);
if (!hMainWnd)
{
return FALSE;
}
hDlgNow = DoMainDlg(hMainWnd);
ShowWindow(hDlgNow, nCmdShow);
while(GetMessage(&msg, NULL, 0, 0))
{
if (NULL == hDlgNow || !IsDialogMessage(hDlgNow, &msg))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
return msg.wParam;
}
HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
int nCmdShow)
{
// TODO: Place code here.
odInst = hInstance;
WNDCLASS wc;
wc.style = 0;
wc.lpfnWndProc = (WNDPROC)ODWndProc; //定義一個窗口默認函數,這里我們會交由默認窗口函數處理
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = hInstance;
wc.hIcon = LoadIcon(odInst,MAKEINTRESOURCE(IDI_OWNERDRAW));
wc.hCursor = NULL;
wc.hbrBackground = 0;
wc.lpszClassName = "OwnerDraw";
wc.lpszMenuName = NULL;
RegisterClass(&wc);
MSG msg;
HWND onlywin= FindWindow("OwnerDraw","MyOwnerDraw");
if (onlywin)
{
ExitProcess(1);
}
hMainWnd=CreateWindow("OwnerDraw","MyOwnerDraw",WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT,0,CW_USEDEFAULT,0,NULL,NULL,hInstance,NULL);
if (!hMainWnd)
{
return FALSE;
}
hDlgNow = DoMainDlg(hMainWnd);
ShowWindow(hDlgNow, nCmdShow);
while(GetMessage(&msg, NULL, 0, 0))
{
if (NULL == hDlgNow || !IsDialogMessage(hDlgNow, &msg))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
return msg.wParam;
}
首先注冊一個標准的窗口類,的WNDCLASS結構體,默認的窗口過程為ODWndProc.其定義如下.
LRESULT CALLBACK ODWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
return DefWindowProc(hWnd, message, wParam, lParam);//返回系統默認的窗口過程
}
{
return DefWindowProc(hWnd, message, wParam, lParam);//返回系統默認的窗口過程
}
然后判斷有無相同實例存在如有則結束之
HWND onlywin= FindWindow("OwnerDraw","MyOwnerDraw");
if (onlywin)
{
ExitProcess(1);
}
if (onlywin)
{
ExitProcess(1);
}
接下來創建主窗口
hMainWnd=CreateWindow("OwnerDraw","MyOwnerDraw",WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT,0,CW_USEDEFAULT,0,NULL,NULL,hInstance,NULL);
CW_USEDEFAULT,0,CW_USEDEFAULT,0,NULL,NULL,hInstance,NULL);
需要注意的是我們這里並不調用ShowWindow()和UpdateWindow();因為我們不需要顯示主窗口
hDlgNow = DoMainDlg(hMainWnd);
ShowWindow(hDlgNow, nCmdShow);
ShowWindow(hDlgNow, nCmdShow);
這里調用DoMainDlg函數創建一個對話框並顯示之. DoMainDlg函數實現如下.
HWND DoMainDlg(HWND parent)
{
DWORD dwErr;
HWND hRet = CreateDialog(odInst, (LPCTSTR)IDD_MAIN_DLG, parent, (DLGPROC)MainDlgProc);
if(hRet == NULL)
dwErr = GetLastError();
return hRet;
}
{
DWORD dwErr;
HWND hRet = CreateDialog(odInst, (LPCTSTR)IDD_MAIN_DLG, parent, (DLGPROC)MainDlgProc);
if(hRet == NULL)
dwErr = GetLastError();
return hRet;
}
最后為消息循環
while(GetMessage(&msg, NULL, 0, 0))
{
if (NULL == hDlgNow || !IsDialogMessage(hDlgNow, &msg))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
{
if (NULL == hDlgNow || !IsDialogMessage(hDlgNow, &msg))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
其中IsDialogMessage(hDlgNow, &msg)主要作用是把指定對話框的消息,路由給其處理.
下面是對話框窗口的默認消息響應回調函數MainDlgProc
我這里主要講響應WM_DRAWITEM消息與WM_INITDIALOG..
首先是響應WM_INITDIALOG
case WM_INITDIALOG:
if(hIcon == NULL)
hIcon = LoadIcon(odInst, MAKEINTRESOURCE(IDI_OWNERDRAW));
if(hOwnerDrawIcon == NULL)
hOwnerDrawIcon = (HICON)LoadImage(odInst,
MAKEINTRESOURCE(IDI_OWNERDRAW),
IMAGE_ICON,
38,
38,
0);
prev_proc = SetWindowLongPtr(GetDlgItem(hDlg, IDC_ODBUTTON), GWLP_WNDPROC, (LONG)ButtWindProc);
SendMessage(hDlg, WM_SETICON, ICON_SMALL, (LPARAM)hIcon);
SetFocus(GetDlgItem(hDlg, IDC_ODBUTTON));
break;
if(hIcon == NULL)
hIcon = LoadIcon(odInst, MAKEINTRESOURCE(IDI_OWNERDRAW));
if(hOwnerDrawIcon == NULL)
hOwnerDrawIcon = (HICON)LoadImage(odInst,
MAKEINTRESOURCE(IDI_OWNERDRAW),
IMAGE_ICON,
38,
38,
0);
prev_proc = SetWindowLongPtr(GetDlgItem(hDlg, IDC_ODBUTTON), GWLP_WNDPROC, (LONG)ButtWindProc);
SendMessage(hDlg, WM_SETICON, ICON_SMALL, (LPARAM)hIcon);
SetFocus(GetDlgItem(hDlg, IDC_ODBUTTON));
break;
首先為對話框加載一個圖標,我這里圖省事全部都用了一個圖標,在實際應用中.可以隨需要更換.
然后是為自繪按鈕加載圖標.接下來改變默認的自繪按鈕的窗口過程.將原按鈕過程存與prev_proc中.
最后發送WM_SETICON消息設置對話框圖標和設置焦點.
接下來是響應WM_DRAWITEM消息,需要說明的是這個消息必須要設置了BS_OWNERDRAW
我們用記事本打開我們的對話框資源文件會看到類似下面的設置
IDD_MAIN_DLG DIALOG DISCARDABLE 0, 0, 250, 142
STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
CAPTION "Dialog"
FONT 10, "System"
BEGIN
DEFPUSHBUTTON "OK",IDOK,193,7,50,14
PUSHBUTTON "Cancel",IDCANCEL,193,24,50,14
CONTROL "OwnerDraw",IDC_ODBUTTON,"Button",BS_OWNERDRAW |
WS_TABSTOP,49,31,79,26
END
STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
CAPTION "Dialog"
FONT 10, "System"
BEGIN
DEFPUSHBUTTON "OK",IDOK,193,7,50,14
PUSHBUTTON "Cancel",IDCANCEL,193,24,50,14
CONTROL "OwnerDraw",IDC_ODBUTTON,"Button",BS_OWNERDRAW |
WS_TABSTOP,49,31,79,26
END
此處資源文件中的BS_OWNERDRAW即對應創建按鈕時選中的Ownerdraw屬性.之所以這樣作是因為只有這樣
對話框才能響應WM_DRAWITEM消息.下面為代碼.
case WM_DRAWITEM:
{
LPDRAWITEMSTRUCT lpDIS = (LPDRAWITEMSTRUCT) lParam;
//聲明一個指向DRAWITEMSTRUCT結構體的指針並將其指向存儲着按鈕構造信息的lParam
if(lpDIS->CtlID != IDC_ODBUTTON)
return (0);
HDC dc = lpDIS->hDC; //用於按鈕繪制的DC
BOOL bIsPressed = (lpDIS->itemState & ODS_SELECTED);
BOOL bIsFocused = (lpDIS->itemState & ODS_FOCUS);
BOOL bIsDisabled = (lpDIS->itemState & ODS_DISABLED);
BOOL bDrawFocusRect = !(lpDIS->itemState & ODS_NOFOCUSRECT);
//判斷按鈕各種狀態的BOOL值
RECT itemRect = lpDIS->rcItem; //按鈕的矩形區域
SetBkMode(dc, TRANSPARENT); //設置繪制按鈕時的背景狀態
if (bIsFocused) //判斷按鈕是否獲得了焦點並對其邊框進行處理
{
HBRUSH br = CreateSolidBrush(RGB(0,0,0));
FrameRect(dc, &itemRect, br);
InflateRect(&itemRect, -1, -1);
DeleteObject(br);
} // if
COLORREF crColor = GetSysColor(COLOR_BTNFACE);//得到系統按鈕顏色
HBRUSH brBackground = CreateSolidBrush(crColor);//創建畫刷
FillRect(dc, &itemRect, brBackground);//繪制按鈕
DeleteObject(brBackground);
// 這里畫被按下去的按鈕
if (bIsPressed)
{
HBRUSH brBtnShadow = CreateSolidBrush(GetSysColor(COLOR_BTNSHADOW));
FrameRect(dc, &itemRect, brBtnShadow);
DeleteObject(brBtnShadow);
}
else //如果沒有被按下就這樣畫
{
UINT uState = DFCS_BUTTONPUSH |
((bIsPressed) ? DFCS_PUSHED : 0);
DrawFrameControl(dc, &itemRect, DFC_BUTTON, uState);
}
char sTitle[100];
GetWindowText(GetDlgItem(hDlg, IDC_ODBUTTON), sTitle, 100);//得到按鈕的文本
RECT captionRect = lpDIS->rcItem;//把文本的區域設置為按鈕區域
BOOL bHasTitle = (sTitle[0] !='/0');//按鈕上是否有文本存在
//這里畫按鈕上的圖標,具體實現見下面
(GetDlgItem(hDlg, IDC_ODBUTTON), &dc, bHasTitle,
&lpDIS->rcItem, &captionRect, bIsPressed, bIsDisabled);
if (bHasTitle)//如果按鈕有文本標題
{
// 按鈕被按下的處理
if (bIsPressed)
OffsetRect(&captionRect, 1, 1);
// 將文本居中
RECT centerRect = captionRect;
DrawText(dc, sTitle, -1, &captionRect, DT_WORDBREAK | DT_CALCRECT|DT_CENTER);
LONG captionRectWidth = captionRect.right - captionRect.left;
LONG captionRectHeight = captionRect.bottom - captionRect.top;
LONG centerRectWidth = centerRect.right - centerRect.left;
LONG centerRectHeight = centerRect.bottom - centerRect.top;
OffsetRect(&captionRect, (centerRectWidth - captionRectWidth)/2, (centerRectHeight - captionRectHeight)/2);
SetBkMode(dc, TRANSPARENT);
if (bIsDisabled)//如果按鈕被禁用
{
OffsetRect(&captionRect, 1, 1);
SetTextColor(dc, ::GetSysColor(COLOR_3DHILIGHT));
DrawText(dc, sTitle, -1, &captionRect, DT_WORDBREAK | DT_CENTER);
OffsetRect(&captionRect, -1, -1);
SetTextColor(dc, ::GetSysColor(COLOR_3DSHADOW));
DrawText(dc, sTitle, -1, &captionRect, DT_WORDBREAK | DT_CENTER);
}
else //如果沒被禁用正常畫
{
SetTextColor(dc, ::GetSysColor(COLOR_BTNTEXT));
SetBkColor(dc, ::GetSysColor(COLOR_BTNFACE));
DrawText(dc, sTitle, -1, &captionRect, DT_WORDBREAK | DT_CENTER);
}
}
// 畫按鈕得到焦點時的虛線方框
if (bIsFocused && bDrawFocusRect)
{
RECT focusRect = itemRect;
InflateRect(&focusRect, -3, -3);
DrawFocusRect(dc, &focusRect);
} // if
return (TRUE);
}
break;
{
LPDRAWITEMSTRUCT lpDIS = (LPDRAWITEMSTRUCT) lParam;
//聲明一個指向DRAWITEMSTRUCT結構體的指針並將其指向存儲着按鈕構造信息的lParam
if(lpDIS->CtlID != IDC_ODBUTTON)
return (0);
HDC dc = lpDIS->hDC; //用於按鈕繪制的DC
BOOL bIsPressed = (lpDIS->itemState & ODS_SELECTED);
BOOL bIsFocused = (lpDIS->itemState & ODS_FOCUS);
BOOL bIsDisabled = (lpDIS->itemState & ODS_DISABLED);
BOOL bDrawFocusRect = !(lpDIS->itemState & ODS_NOFOCUSRECT);
//判斷按鈕各種狀態的BOOL值
RECT itemRect = lpDIS->rcItem; //按鈕的矩形區域
SetBkMode(dc, TRANSPARENT); //設置繪制按鈕時的背景狀態
if (bIsFocused) //判斷按鈕是否獲得了焦點並對其邊框進行處理
{
HBRUSH br = CreateSolidBrush(RGB(0,0,0));
FrameRect(dc, &itemRect, br);
InflateRect(&itemRect, -1, -1);
DeleteObject(br);
} // if
COLORREF crColor = GetSysColor(COLOR_BTNFACE);//得到系統按鈕顏色
HBRUSH brBackground = CreateSolidBrush(crColor);//創建畫刷
FillRect(dc, &itemRect, brBackground);//繪制按鈕
DeleteObject(brBackground);
// 這里畫被按下去的按鈕
if (bIsPressed)
{
HBRUSH brBtnShadow = CreateSolidBrush(GetSysColor(COLOR_BTNSHADOW));
FrameRect(dc, &itemRect, brBtnShadow);
DeleteObject(brBtnShadow);
}
else //如果沒有被按下就這樣畫
{
UINT uState = DFCS_BUTTONPUSH |
((bIsPressed) ? DFCS_PUSHED : 0);
DrawFrameControl(dc, &itemRect, DFC_BUTTON, uState);
}
char sTitle[100];
GetWindowText(GetDlgItem(hDlg, IDC_ODBUTTON), sTitle, 100);//得到按鈕的文本
RECT captionRect = lpDIS->rcItem;//把文本的區域設置為按鈕區域
BOOL bHasTitle = (sTitle[0] !='/0');//按鈕上是否有文本存在
//這里畫按鈕上的圖標,具體實現見下面
(GetDlgItem(hDlg, IDC_ODBUTTON), &dc, bHasTitle,
&lpDIS->rcItem, &captionRect, bIsPressed, bIsDisabled);
if (bHasTitle)//如果按鈕有文本標題
{
// 按鈕被按下的處理
if (bIsPressed)
OffsetRect(&captionRect, 1, 1);
// 將文本居中
RECT centerRect = captionRect;
DrawText(dc, sTitle, -1, &captionRect, DT_WORDBREAK | DT_CALCRECT|DT_CENTER);
LONG captionRectWidth = captionRect.right - captionRect.left;
LONG captionRectHeight = captionRect.bottom - captionRect.top;
LONG centerRectWidth = centerRect.right - centerRect.left;
LONG centerRectHeight = centerRect.bottom - centerRect.top;
OffsetRect(&captionRect, (centerRectWidth - captionRectWidth)/2, (centerRectHeight - captionRectHeight)/2);
SetBkMode(dc, TRANSPARENT);
if (bIsDisabled)//如果按鈕被禁用
{
OffsetRect(&captionRect, 1, 1);
SetTextColor(dc, ::GetSysColor(COLOR_3DHILIGHT));
DrawText(dc, sTitle, -1, &captionRect, DT_WORDBREAK | DT_CENTER);
OffsetRect(&captionRect, -1, -1);
SetTextColor(dc, ::GetSysColor(COLOR_3DSHADOW));
DrawText(dc, sTitle, -1, &captionRect, DT_WORDBREAK | DT_CENTER);
}
else //如果沒被禁用正常畫
{
SetTextColor(dc, ::GetSysColor(COLOR_BTNTEXT));
SetBkColor(dc, ::GetSysColor(COLOR_BTNFACE));
DrawText(dc, sTitle, -1, &captionRect, DT_WORDBREAK | DT_CENTER);
}
}
// 畫按鈕得到焦點時的虛線方框
if (bIsFocused && bDrawFocusRect)
{
RECT focusRect = itemRect;
InflateRect(&focusRect, -3, -3);
DrawFocusRect(dc, &focusRect);
} // if
return (TRUE);
}
break;
到此WM_DRAWITEM消息響應完畢.下面我們看看DrawTheIcon這個函數.
static void DrawTheIcon(HWND hButtonWnd, HDC* dc, BOOL bHasTitle, RECT* rpItem, RECT* rpTitle, BOOL bIsPressed, BOOL bIsDisabled)
{
RECT rImage;
PrepareImageRect(hButtonWnd, bHasTitle, rpItem, rpTitle, bIsPressed, 38, 38, &rImage);
// 調用API函數按准備好的形式將圖片畫到按鈕上
DrawState( *dc,
NULL,
NULL,
(LPARAM)hOwnerDrawIcon,
0,
rImage.left,
rImage.top,
(rImage.right - rImage.left),
(rImage.bottom - rImage.top),
(bIsDisabled ? DSS_DISABLED : DSS_NORMAL) | DST_ICON);
}
{
RECT rImage;
PrepareImageRect(hButtonWnd, bHasTitle, rpItem, rpTitle, bIsPressed, 38, 38, &rImage);
// 調用API函數按准備好的形式將圖片畫到按鈕上
DrawState( *dc,
NULL,
NULL,
(LPARAM)hOwnerDrawIcon,
0,
rImage.left,
rImage.top,
(rImage.right - rImage.left),
(rImage.bottom - rImage.top),
(bIsDisabled ? DSS_DISABLED : DSS_NORMAL) | DST_ICON);
}
還有其中的PrepareImageRect函數
static void PrepareImageRect(HWND hButtonWnd, BOOL bHasTitle, RECT* rpItem, RECT* rpTitle, BOOL bIsPressed, DWORD dwWidth, DWORD dwHeight, RECT* rpImage)
{
RECT rBtn;
CopyRect(rpImage, rpItem);
GetClientRect(hButtonWnd, &rBtn);
if (bHasTitle == FALSE)//如果按鈕上有文本內容
{
// 使圖片水平居中
LONG rpImageWidth = rpImage->right - rpImage->left;
rpImage->left += ((rpImageWidth - (long)dwWidth)/2);
}
else
{ //控制圖片與焦點方框內部
LONG rpTitleWidth = rpTitle->right - rpTitle->left;
rpTitle->right = rpTitleWidth - dwWidth - 30;
rpTitle->left = 30;
rpImage->left = rBtn.right - dwWidth - 22;
LONG rpImageHeight = rpImage->bottom - rpImage->top;
rpImage->top += ((rpImageHeight - (long)dwHeight)/2);
}
if (bIsPressed)//按鈕被按下的處理
OffsetRect(rpImage, 1, 1);
}
{
RECT rBtn;
CopyRect(rpImage, rpItem);
GetClientRect(hButtonWnd, &rBtn);
if (bHasTitle == FALSE)//如果按鈕上有文本內容
{
// 使圖片水平居中
LONG rpImageWidth = rpImage->right - rpImage->left;
rpImage->left += ((rpImageWidth - (long)dwWidth)/2);
}
else
{ //控制圖片與焦點方框內部
LONG rpTitleWidth = rpTitle->right - rpTitle->left;
rpTitle->right = rpTitleWidth - dwWidth - 30;
rpTitle->left = 30;
rpImage->left = rBtn.right - dwWidth - 22;
LONG rpImageHeight = rpImage->bottom - rpImage->top;
rpImage->top += ((rpImageHeight - (long)dwHeight)/2);
}
if (bIsPressed)//按鈕被按下的處理
OffsetRect(rpImage, 1, 1);
}
行了到這里主要的工作都作完了還要說明的就是ButtWindProc這個按鈕窗口的回調函數.寫它的主要目的是為了
實現按鈕的連續單擊,在此函數中我們處理了WM_LBUTTONDBLCLK鼠標雙擊事件,並將其轉化為一個單擊事件.像這樣:
LRESULT CALLBACK ButtWindProc(
HWND hWnd, //window handle
UINT message, // type of message
WPARAM wParam, // additional information
LPARAM lParam) //additional information
{
switch (message)
{
case WM_LBUTTONDBLCLK:
PostMessage(hWnd, WM_LBUTTONDOWN, wParam, lParam);
break;
}
//將不做處理的消息路由給原默認函數
return CallWindowProc((WNDPROC)prev_proc, hWnd, message, wParam, lParam);
}
HWND hWnd, //window handle
UINT message, // type of message
WPARAM wParam, // additional information
LPARAM lParam) //additional information
{
switch (message)
{
case WM_LBUTTONDBLCLK:
PostMessage(hWnd, WM_LBUTTONDOWN, wParam, lParam);
break;
}
//將不做處理的消息路由給原默認函數
return CallWindowProc((WNDPROC)prev_proc, hWnd, message, wParam, lParam);
}
下面只需再響應WM_SETICON, WM_SYSCOMMAND, WM_COMMAND.這三個沒什么好說的.前兩個交由系統默認過程處理,最后一個對應對話框上的確定和取消,都是銷毀窗口的行為.
case WM_SETICON:
DefWindowProc(hDlg, message, wParam, lParam);
break;
case WM_SYSCOMMAND:
{
return DefWindowProc(hDlg, message, wParam, lParam);
}
case WM_COMMAND:
switch (LOWORD(wParam))
{
case IDCANCEL:
case IDOK:
DestroyIcon(hOwnerDrawIcon);
PostQuitMessage(0);
return TRUE;
}//switch
break;
DefWindowProc(hDlg, message, wParam, lParam);
break;
case WM_SYSCOMMAND:
{
return DefWindowProc(hDlg, message, wParam, lParam);
}
case WM_COMMAND:
switch (LOWORD(wParam))
{
case IDCANCEL:
case IDOK:
DestroyIcon(hOwnerDrawIcon);
PostQuitMessage(0);
return TRUE;
}//switch
break;
http://www.cnblogs.com/lidabo/p/3701199.html