Yan`s Notepad

--- My Notepad......Articles, tools and etc.
VC自绘颜色选择器
拦截组合框的绘画消息,然后让程序自己绘画。
对于组合框的项目而言,除了项目文本,还有一个32位的附加数据。其实这个思想方法很简单,在画的时候取回这个32位的数据就可以了。
#include "resource.h"
#include <Windows.h>
#include <Windowsx.h>
using namespace std;

LRESULT CALLBACK WndProc(HWND , UINT, WPARAM, LPARAM );
int PASCAL WinMain(HINSTANCE ,HINSTANCE ,LPSTR , int );

#define vaWidth 230
#define vaHeight 180

#define BruColor1	0xffffff			// 正常刷子的颜色
#define BruColor2	RGB(209,232,255)	// 点燃刷子的颜色
#define BruColor3	0					// 边框刷子的颜色
#define BruColorM	RGB(102,167,232)	// 边框刷子的颜色(点燃)
#define BruColor4	RGB(217,217,217)	// 边框刷子的颜色(组合框)
#define PenColor1	RGB(128,128,128)	// 边上按钮的颜色(笔)

HWND mhWnd;
HINSTANCE hInst;

HWND cmhWnd;						// 组合框句柄
HBRUSH Hover_Brush, Normal_Brush;	// 刷子句柄:点燃,正常的背景刷子
HBRUSH Bru_bor, NorBru_bor;			// 刷子句柄:点燃,正常边框的刷子
HFONT hFont;						// 字体

HDC ComDC;			// 组合框设备场景句柄
HBRUSH	BorBsh_Com;		// 组合框的边框的刷子
HPEN hPen_Com;		// 组合框的下拉按钮的刷子
RECT cRect;			// 组合框的矩形

LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
	switch (message)
	{
	case WM_DRAWITEM: {
		DRAWITEMSTRUCT *dItem;
		dItem = (DRAWITEMSTRUCT*)lParam;

		if (dItem->CtlType = ODT_COMBOBOX) {
			/* 是组合框控件 */
			SelectObject(dItem->hDC, hFont);
			SetBkMode(dItem->hDC, TRANSPARENT);
			SetTextColor(dItem->hDC, 0);

			FillRect(ComDC, &cRect, Normal_Brush);
			FrameRect(ComDC, &cRect, BorBsh_Com);

			MoveToEx(ComDC, cRect.right - 15, cRect.top + 9, NULL);
			LineTo(ComDC, cRect.right - 11, cRect.top + 14);
			LineTo(ComDC, cRect.right - 7, cRect.top + 9);

			if ((dItem->itemState & ODS_FOCUS) != 0) {
				/* 是选中(焦点)的项目 */
				FillRect(dItem->hDC, &(dItem->rcItem), Hover_Brush); // 填充点燃项目的背景矩形
				FrameRect(dItem->hDC, &(dItem->rcItem), Bru_bor);

				wchar_t buf[255];
				wsprintfW(buf, L"颜色值:%d", dItem->itemData);
				TextOut(dItem->hDC, dItem->rcItem.right - 20 - wcslen(buf) * 6, dItem->rcItem.top + 4, buf, wcslen(buf)); // 画出文本
			}
			else {
				/* 不是选中的项目 */
				FillRect(dItem->hDC, &(dItem->rcItem), Normal_Brush); // 填充点燃项目的背景矩形
			}

			int strlength = SendMessage(dItem->hwndItem, CB_GETLBTEXTLEN, dItem->itemID, 0);	// 取得项目文本长度
			wchar_t str[255] = L"";

			SendMessage(dItem->hwndItem, CB_GETLBTEXT, dItem->itemID, (LPARAM)(void*)str);
			TextOut(dItem->hDC, dItem->rcItem.left + 40, dItem->rcItem.top + 4, str, strlength); // 画出文本

			RECT rect0;
			rect0.top = dItem->rcItem.top + 3;
			rect0.left = dItem->rcItem.left + 4;
			rect0.right = dItem->rcItem.left + 30;
			rect0.bottom = dItem->rcItem.top + 16;

			HBRUSH hbsh = CreateSolidBrush(dItem->itemData);	// 用刚刚的附加数据做颜色
			FillRect(dItem->hDC, &rect0, hbsh); // 填充项目的颜色矩形
			FrameRect(dItem->hDC, &rect0, NorBru_bor);
			DeleteObject(hbsh);

			return 0;
		}
		return DefWindowProc( hWnd, message, wParam, lParam);
	}
					  break;

	case WM_COMMAND:
	{
		int wmId = LOWORD(wParam);
		HWND hwndCtl = (HWND)lParam;

		if (wParam == 65536 && hwndCtl == cmhWnd) {
			/* 选择项目 */
			int selIndex = SendMessage(cmhWnd, CB_GETCURSEL, 0, 0);
			int sColor = SendMessage(cmhWnd, CB_GETITEMDATA, selIndex, 0);
			/* 如上代码获得颜色 */

			HDC WMDC = GetDC(hWnd);

			/*在这里画出窗口的底色*/

			HBRUSH FFBru = CreateSolidBrush(sColor);
			RECT RR;
			GetClientRect(hWnd, &RR);
			RR.top += 40;
			FillRect(WMDC, &RR, FFBru);
			DeleteObject(FFBru);
			ReleaseDC(hWnd, WMDC);
		}
	}
	break;

	case WM_CREATE: {
		Normal_Brush = CreateSolidBrush(BruColor1);
		Hover_Brush = CreateSolidBrush(BruColor2);
		NorBru_bor = CreateSolidBrush(BruColor3);
		Bru_bor = CreateSolidBrush(BruColorM);

		hFont = CreateFont(12, 0, 0, 0, 0, 00, 0, 0, 0, 0, 0, 0, 0, L"宋体");

		BorBsh_Com = CreateSolidBrush(BruColor4);

		hPen_Com = CreatePen(PS_SOLID, 3, PenColor1);

		return DefWindowProc(hWnd, message, wParam, lParam);
	}
					break;

	case WM_DESTROY: {
		ReleaseDC(cmhWnd, ComDC);

		DeleteObject(Normal_Brush);
		DeleteObject(Hover_Brush);
		DeleteObject(NorBru_bor);
		DeleteObject(Bru_bor);

		DeleteObject(hFont);

		DeleteObject(BorBsh_Com);
		DeleteObject(hPen_Com);

		PostQuitMessage(0);
	}
					 break;
	default:
		return DefWindowProc( hWnd, message, wParam, lParam);
	}
	return 0;
}

int PASCAL WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) {
	WNDCLASS wc = { 0 };


	wc.style = CS_HREDRAW | CS_VREDRAW;	// 窗口类样式
	wc.lpfnWndProc = WndProc;			// 窗口线程处理函数
	wc.cbClsExtra = 0;
	wc.cbWndExtra = 0;
	wc.hInstance = hInstance;			// 模块句柄
	wc.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_ICON1));	// 图标句柄
	wc.hCursor = LoadCursor(nullptr, IDC_ARROW);				// 鼠标指针句柄
	wc.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);				// 背景颜色
	wc.lpszClassName = L"colorchange_demo_win";							// 类名

	if (!RegisterClassW(&wc))return 0;	// 注册窗口类
	if (!(mhWnd = CreateWindowEx(	// 创建窗口
		WS_EX_ACCEPTFILES | WS_EX_LAYERED,
		L"colorchange_demo_win",			// 窗口类名
		L"颜色选择器",				// 窗口标题
		WS_OVERLAPPED | WS_SYSMENU | WS_CAPTION | WS_BORDER,	// 窗口样式
		200,					// 窗口出现的X
		200,					// 窗口出现的Y
		vaWidth,				// 窗口宽度
		vaHeight,				// 窗口高度
		nullptr,
		nullptr,
		hInstance,				// 模块句柄
		nullptr)))return 0;

	hInst = hInstance;

	ShowWindow(mhWnd, SW_SHOWNORMAL);	// 显示窗口
	UpdateWindow(mhWnd);				// 重画窗口

	SetLayeredWindowAttributes(mhWnd, 0, 250, 2);	// 窗口半透明

	/////////////////////////////////////////////
	cmhWnd = CreateWindowEx(0,
		L"ComboBox",
		L"",
		WS_CHILD | WS_TABSTOP | WS_VISIBLE | WS_VSCROLL | CBS_OWNERDRAWFIXED | CBS_HASSTRINGS | CBS_DROPDOWNLIST | CBS_AUTOHSCROLL,
		8,
		8,
		200,
		180, mhWnd,
		0,
		0,
		0);

	SendMessage(cmhWnd, CB_ADDSTRING, 0, (LPARAM)(void*)L"松花绿");	// 插入项目
	SendMessage(cmhWnd, CB_SETITEMDATA, 0, 4769541);				// 设置附加数据
	SendMessage(cmhWnd, CB_ADDSTRING, 1, (LPARAM)(void*)L"玉色");
	SendMessage(cmhWnd, CB_SETITEMDATA, 1, RGB(0x2e, 0xdf, 0xa3));
	SendMessage(cmhWnd, CB_ADDSTRING, 2, (LPARAM)(void*)L"橙黄色");
	SendMessage(cmhWnd, CB_SETITEMDATA, 2, RGB(0xff, 0xa4, 0x00));
	SendMessage(cmhWnd, CB_ADDSTRING, 3, (LPARAM)(void*)L"丁香色");
	SendMessage(cmhWnd, CB_SETITEMDATA, 3, RGB(0xcc, 0xa4, 0xe3));
	SendMessage(cmhWnd, CB_ADDSTRING, 4, (LPARAM)(void*)L"淡红藤");
	SendMessage(cmhWnd, CB_SETITEMDATA, 4, RGB(0xe6, 0xcd, 0xe3));
	SendMessage(cmhWnd, CB_ADDSTRING, 5, (LPARAM)(void*)L"青磁鼠");
	SendMessage(cmhWnd, CB_SETITEMDATA, 5, RGB(0xbe, 0xd2, 0xc3));

	SendMessage(cmhWnd, CB_SETCURSEL, 0, 0);		// 设置选中项
	SendMessage(cmhWnd, CB_SETITEMHEIGHT, 0, 20);	// 设置项目的高度

	ComDC = GetWindowDC(cmhWnd);
	SelectObject(ComDC, hPen_Com);

	GetClientRect(cmhWnd, &cRect);
	///////////////////////////////////////////

	HACCEL hAccelTable = LoadAccelerators(hInstance, L"colorchange_demo_win");

	MSG msg;

	// 主消息循环: 
	while (GetMessage(&msg, nullptr, 0, 0))
	{
		if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg))
		{
			TranslateMessage(&msg);
			DispatchMessage(&msg);
		}
	}
	return 0;
}