Win32--自定义下拉框
上一周要求做一个小的任务,分给我的是自定义下拉框,刚开始接触Windows编程,很多东西都是新的,不知如何去做,如何去查看资料,怎样查资料才会更有效,碰到很多东西,也给我很多启示。
Windows编程中消息贯穿始终,对消息理解不透彻,在编程中往往会迷惑,本文讲解下拉框的相关消息,以及如何自定义下拉框。
一、建立模态对话框
DialogBox (hlnst, MAKEINTRESOURCE(IDD_DIALOG_ICON), hwnd, AboutDlgProc) ;
1.绑定到AboutDlgProc,这个AboutDlgProc回调函数,拦截了对话框的消息,对自己
感兴趣的消息,可以在这里进行处理,不处理的消息返回到系统,由系统处理。这是
一种处理机制,万不可自己处理很多消息,记住只对自己感兴趣的消息进行处理。
2.这句话很重要,就是要把自己不处理的消息,返回给系统,由系统处理:
default:
DefWindowProc (hDlg, message, wParam, lParam) ;
这里的message是一个消息的代号,即消息的标志,消息在windows中的作用是那么的重要。
3.在对话框建立后会发出初始化消息,在这里进行初始化对话框的组件,即初始化对话框里
的一些控件或者自定义控件,
响应这个消息时一定要有返回值,否则系统默认初始化不成功。
case WM_INITDIALOG :
//加载图标
if(!LoadIconBitmaps()) //这里要对加载图标进行判断,但是我后面没有进行判断
{
EndDialog(hDlg,-1);
break;
}
//初始化下拉框
InitComboxList(hDlg);
//设置默认显示
SendDlgItemMessage(hDlg,IDCOMBO,CB_SETCURSEL,0,0);
return TRUE ;
4.WM_MEASUREITEM 消息,所有的自定义控件都要根据这个消息来设置item的大小,
保存在lpMeasureItem = (LPMEASUREITEMSTRUCT) lParam;中,
The WM_MEASUREITEM message is sent to the owner window of a combo box, list box, list view control, or menu item when the control or menu is created.
A window receives this message through its WindowProc function.
这个消息是当下拉框创建时,发送的消息,无论是控件还是资源,都会在创建时发送消息,在这里可以进行相关的初始化设置,这里就是受到这个消息,进行下拉框文本大小的设置。
case WM_MEASUREITEM:
{
//设置默认下拉框设置
LPMEASUREITEMSTRUCT lpmis = (LPMEASUREITEMSTRUCT)lParam;
if(lpmis->itemHeight < CY_BITMAP + 2)
lpmis->itemHeight = CY_BITMAP + 2;
break;
}
注意一定要把下拉框设置为自定义:CBS_OWNERDRAWVARIABLE,这个在资源设置面板里设置
4.WM_DRAWITEM 消息,MSDN:
The WM_DRAWITEM message is sent to the parent window of an owner-drawn button,
combo box, list box, or menu when a visual aspect of the button, combo box, list box, or menu has changed.
当Windows要画这个控件时,控件会把此消息发送给父窗口,父窗口接收到这个消息后
对要画的控件进行预设置。
lpDrawItem = (LPDRAWITEMSTRUCT) lParam;
里保存的是要绘制控件的消息
而下拉框控件的消息在对话框初始化发出的消息里就进行了初始化case WM_INITDIALOG
hbmIcon = (HBITMAP) lpdis->itemData;
这句话很重要,这里包含了下拉框很多信息
5.BitBlt函数
BOOL BitBlt(
HDC hdcDest, // handle to destination DC
int nXDest, // x-coord of destination upper-left corner
int nYDest, // y-coord of destination upper-left corner
int nWidth, // width of destination rectangle
int nHeight, // height of destination rectangle
HDC hdcSrc, // handle to source DC
int nXSrc, // x-coordinate of source upper-left corner
int nYSrc, // y-coordinate of source upper-left corner
DWORD dwRop // raster operation code
);
这个函数是把源目标的像素转移到目标矩形区域,记得还有一个函数可以实现透明的转移
这个函数的目的:画透明的图像,即是把一副图像以一定的透明度混合到目标区域
BLENDFUNCTION blendFunction = { AC_SRC_OVER, 0, 0xff, AC_SRC_ALPHA };
::AlphaBlend(lpdis->hDC, x, lpdis->rcItem.top + 3,
CX_BITMAP, CY_BITMAP, hdc, 0, 0,CX_BITMAP,CY_BITMAP, blendFunction);
源代码:
LRESULT CALLBACK WndProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message)
{
case WM_CREATE :
hInst = ((LPCREATESTRUCT) lParam)->hInstance ;
return 0 ;
case WM_COMMAND :
switch (LOWORD (wParam))
{
case ID_HELP_ABOUT :
DialogBox(hInst, MAKEINTRESOURCE(IDC_ABOUT_DIALOG), hwnd, AboutDlgProc) ;
break ;
}
return 0 ;
case WM_PAINT:
break;
case WM_DESTROY :
PostQuitMessage (0) ;
return 0 ;
}
return DefWindowProc (hwnd, message, wParam, lParam) ;
}
INT_PTR CALLBACK AboutDlgProc (HWND hDlg, UINT message,
WPARAM wParam, LPARAM lParam)
{
UNREFERENCED_PARAMETER(lParam);
TCHAR achTemp[256];
switch (message)
{
case WM_INITDIALOG :
{//初始化下拉框相关信息
if(!LoadIconBitmap())
{
EndDialog(hDlg,-1);
break;
}
//初始化下拉框
InitComboxList(hDlg);
SendDlgItemMessage(hDlg,IDCOMBO,CB_SETCURSEL,0,0);
return (INT_PTR)TRUE;
}
case WM_MEASUREITEM:
{
//设置默认下拉框设置
LPMEASUREITEMSTRUCT lpmis = (LPMEASUREITEMSTRUCT)lParam;
if(lpmis->itemHeight < CY_BITMAP + 2)
lpmis->itemHeight = CY_BITMAP + 2;
break;
}
case WM_DRAWITEM:
{
//设置下拉框的文本和位图
COLORREF clrBackground;
COLORREF clrForeground;
TEXTMETRIC tm;
int x;
int y;
HRESULT hr;
size_t cch;
LPDRAWITEMSTRUCT lpdis = (LPDRAWITEMSTRUCT)lParam;
if(lpdis->itemID == -1)
break;
//获得item图标
hbmIcon = (HBITMAP)lpdis->itemData;
// The colors depend on whether the item is selected.
clrForeground = SetTextColor(lpdis->hDC,
GetSysColor(lpdis->itemState & ODS_SELECTED ?
COLOR_HIGHLIGHTTEXT : COLOR_WINDOWTEXT));
clrBackground = SetBkColor(lpdis->hDC,
GetSysColor(lpdis->itemState & ODS_SELECTED ?
COLOR_HIGHLIGHT : COLOR_WINDOW));
// Calculate the vertical and horizontal position.
GetTextMetrics(lpdis->hDC, &tm);
y = (lpdis->rcItem.bottom + lpdis->rcItem.top - tm.tmHeight) / 2;
x = LOWORD(GetDialogBaseUnits()) / 4;
// Get and display the text for the list item.
SendMessage(lpdis->hwndItem, CB_GETLBTEXT,
lpdis->itemID, (LPARAM) achTemp);
hr = StringCchLength(achTemp, 256, &cch);
ExtTextOut(lpdis->hDC, CX_BITMAP + 2 * x, y,
ETO_CLIPPED | ETO_OPAQUE, &lpdis->rcItem,
achTemp, (UINT)cch, NULL);
// Restore the previous colors.
SetTextColor(lpdis->hDC, clrForeground);
SetBkColor(lpdis->hDC, clrBackground);
// Draw the food icon for the item.
HDC hdc = CreateCompatibleDC(lpdis->hDC);
if (hdc == NULL)
break;
SelectObject(hdc, hbmMask);
BitBlt(lpdis->hDC, x, lpdis->rcItem.top + 1,
CX_BITMAP, CY_BITMAP, hdc, 0, 0, SRCAND);
SelectObject(hdc, hbmIcon);
BitBlt(lpdis->hDC, x, lpdis->rcItem.top + 1,
CX_BITMAP, CY_BITMAP, hdc, 0, 0, SRCPAINT);
DeleteDC(hdc);
// If the item has the focus, draw the focus rectangle.
if (lpdis->itemState & ODS_FOCUS)
DrawFocusRect(lpdis->hDC, &lpdis->rcItem);
break;
}
case WM_COMMAND :
switch (LOWORD (wParam))
{
case IDOK :
case IDCANCEL :
EndDialog (hDlg, -1) ;
return TRUE ;
break;
}
}
return (INT_PTR)FALSE;
}
BOOL LoadIconBitmap()
{
hbmBread = LoadBitmap(hInst, MAKEINTRESOURCE(IDB_BREAD));
if (hbmBread != NULL)
hbmMask = LoadBitmap(hInst, MAKEINTRESOURCE(IDB_BREAD));
if (hbmTemp != NULL)
hbmTemp = LoadBitmap(hInst, MAKEINTRESOURCE(IDB_BREAD));
if (hbmMask != NULL)
hbmMask = LoadBitmap(hInst, MAKEINTRESOURCE(IDB_BREAD));
if (hbmMask != NULL)
return TRUE;
}
void InitComboxList(HWND hDlg)
{
TCHAR achTemp[256] = TEXT("Food");
TCHAR achTemp_One[256] = TEXT("Dog");
TCHAR achTemp_Two[256] = TEXT("Fish");
DWORD dwIndex;
// Get the handle of the food groups combo box.
HWND hwndGroupsBox = GetDlgItem(hDlg, IDCOMBO);
dwIndex = SendMessage(hwndGroupsBox, CB_ADDSTRING, 0, (LPARAM) achTemp);
SendMessage(hwndGroupsBox, CB_SETITEMDATA, dwIndex, (LPARAM) hbmBread);
dwIndex = SendMessage(hwndGroupsBox, CB_ADDSTRING, 0, (LPARAM) achTemp_One);
SendMessage(hwndGroupsBox, CB_SETITEMDATA, dwIndex, (LPARAM) hbmMask);
dwIndex = SendMessage(hwndGroupsBox, CB_ADDSTRING, 0, (LPARAM) achTemp_Two);
SendMessage(hwndGroupsBox, CB_SETITEMDATA, dwIndex, (LPARAM) hbmTemp);
}