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); 

}

你可能感兴趣的:(Win32)