读书人

Win32-自定义上拉框

发布时间: 2012-09-25 09:55:58 作者: rapoo

Win32--自定义下拉框
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); }

读书人网 >编程

热点推荐