C++实现仿Office风格的颜色选取框代码
2010-08-22 20:47:08 来源:WEB开发网ColorPicker.cpp
#include <stdafx.h>
#include "ColorPicker.h"
WNDPROC ColorPickerWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
CColorPicker* lpColorPicker = (CColorPicker*)GetWindowLong(hwnd, GWL_USERDATA);
if (!lpColorPicker) return (WNDPROC)DefWindowProc(hwnd, msg, wParam, lParam);
/*========================================================================
作者: 彭国辉
DATE: 2007-12-25
EMAIL: kacarton( at )sohu.com
文章为作者原创,转载前请先与本人联系,转载请注明文章出处、保留作者信息,谢谢支持!
=========================================================================*/
switch (msg)
{
case WM_PAINT:
lpColorPicker->OnPaint();
break;
case WM_CLOSE:
DestroyWindow(hwnd);
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
case WM_LBUTTONDOWN:
lpColorPicker->OnLButtonDown(LOWORD(lParam), HIWORD(lParam));
break;
case WM_LBUTTONUP:
lpColorPicker->OnLButtonUp(LOWORD(lParam), HIWORD(lParam));
break;
case WM_MOUSEMOVE:
lpColorPicker->OnMouseMove(LOWORD(lParam), HIWORD(lParam));
break;
case WM_KEYDOWN:
if (wParam==VK_ESCAPE)
{
PostMessage(hwnd, WM_CLOSE, 0, 0);
break;
}
default:
return (WNDPROC)DefWindowProc(hwnd, msg, wParam, lParam);
}
return 0;
}
CColorPicker::CColorPicker(POINT *pt, DWORD DefaultColor)
{
m_hwnd = NULL;
m_Color = DefaultColor;
m_HotRow = m_HotCol = 255;
m_bCustomColor = true;
m_bMouseDown = false;
CreateColorPicker(pt);
}
CColorPicker::~CColorPicker()
{
ReleaseCapture();
}
void CColorPicker::CreateColorPicker(POINT *pt)
{
WNDCLASS wndclass;
//注册窗体类名
if (GetClassInfo(m_hInstance, COLORPICKERWINNAME, &wndclass) == 0)
{
memset(&wndclass, 0, sizeof(WNDCLASS));
wndclass.style = CS_VREDRAW | CS_HREDRAW;
wndclass.lpfnWndProc = (WNDPROC)ColorPickerWndProc;
wndclass.hInstance = m_hInstance;
wndclass.hbrBackground = (HBRUSH)GetStockObject(COLOR_WINDOW);
//wndclass.hCursor = LoadCursor(NULL, IDC_ARROW);
wndclass.lpszClassName = COLORPICKERWINNAME;
RegisterClass(&wndclass);
}
//创建工具栏窗体,定位于主窗口上方
RECT rc;
GetWindowRect(AfxGetMainWnd()->m_hWnd, &rc);
m_hwnd = CreateWindowEx(0, COLORPICKERWINNAME, "颜色拾取窗", WS_POPUP | WS_BORDER | WS_TABSTOP, pt->x, pt->y, 8*18+12, 126, 0, NULL, /**//*AfxGetInstanceHandle()*/m_hInstance, NULL);
if (!m_hwnd) return;
SetWindowLong(m_hwnd, GWL_USERDATA, (LONG)this);
//显示窗体,进入消息循环
ShowWindow(m_hwnd, SW_SHOW);
UpdateWindow(m_hwnd);
SetCapture(m_hwnd);
MSG msg;
while (GetMessage (&msg, NULL, 0,0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
HWND CColorPicker::GetHwnd() ...{return m_hwnd;}
DWORD CColorPicker::GetColor() ...{return m_Color;}
//响应WM_PAINT重画整个窗口
void CColorPicker::OnPaint()
{
PAINTSTRUCT ps;
RECT rc;
HBRUSH hb;
HDC hdc = BeginPaint(m_hwnd, &ps);
GetClientRect(m_hwnd, &rc);
hb = CreateSolidBrush(GetSysColor(COLOR_WINDOW));
FillRect(hdc, &rc, hb);
DeleteObject(hb);
//绘制色块
for (byte i=0; i<5; i++)
for (byte j=0; j<8; j++)
{
Draw(hdc, i, j, false, 1);
if (m_Color == ColorMap[i][j]) m_bCustomColor = false;
}
//绘自定义文字
Draw(hdc, 5, 0, m_HotRow==5, 1);
EndPaint(m_hwnd, &ps);
}
//根据参数画指定区域
//窗体重绘与局部刷新竟相差了一个点,correction参数用于校正
void CColorPicker::Draw(HDC hdc, byte row, byte col, bool hot, byte correction)
{
RECT rc;
HGDIOBJ hpen, holdpen, hbold;
HBRUSH hb;
if (row<5 && col<8)
{
rc.left = col*18 + 5 - correction;
rc.top = row*18 + 5 - correction;
rc.right = rc.left + 18;
rc.bottom = rc.top + 18;
//显示选中热区
if (hot || ColorMap[row][col] == m_Color)
{
hb = CreateSolidBrush(GetSysColor(m_bMouseDown ? COLOR_HIGHLIGHT : COLOR_INACTIVECAPTIONTEXT));
hpen = CreatePen(PS_SOLID, 1, GetSysColor(m_bMouseDown ? COLOR_WINDOWFRAME : COLOR_INACTIVECAPTION));
hbold = SelectObject(hdc, hb);
holdpen = SelectObject(hdc, hpen);
Rectangle(hdc, rc.left, rc.top, rc.right, rc.bottom);
SelectObject(hdc, holdpen);
SelectObject(hdc, hbold);
DeleteObject(hb);
DeleteObject(hpen);
}
else
FillRect(hdc, &rc, NULL); //GetSysColorBrush
//显示颜色
InflateRect(&rc, -3, -3);
hb = CreateSolidBrush(ColorMap[row][col]);
hpen = CreatePen(PS_SOLID, 1, GetSysColor(COLOR_ACTIVEBORDER));
hbold = SelectObject(hdc, hb);
holdpen = SelectObject(hdc, hpen);
Rectangle(hdc, rc.left, rc.top, rc.right, rc.bottom);
SelectObject(hdc, holdpen);
SelectObject(hdc, hbold);
DeleteObject(hb);
DeleteObject(hpen);
}
else if (row==5)
{
//绘自定义文字
GetClientRect(m_hwnd, &rc);
if (correction) OffsetRect(&rc, -correction, -correction); //校正位置
InflateRect(&rc, -5, -5);
rc.top = 5*18+10;
if (hot)
{
hb = CreateSolidBrush(GetSysColor(m_bMouseDown ? COLOR_HIGHLIGHT : COLOR_INACTIVECAPTIONTEXT));
hpen = CreatePen(PS_SOLID, 1, GetSysColor(m_bMouseDown ? COLOR_WINDOWFRAME : COLOR_INACTIVECAPTION));
hbold = SelectObject(hdc, hb);
holdpen = SelectObject(hdc, hpen);
Rectangle(hdc, rc.left, rc.top, rc.right, rc.bottom);
SelectObject(hdc, holdpen);
SelectObject(hdc, hbold);
DeleteObject(hb);
DeleteObject(hpen);
}
else
FillRect(hdc, &rc, NULL);
//if (b_CustomColor) rc.right = 7*18;
SetBkMode(hdc, TRANSPARENT);
HFONT m_Font = CreateFont(-12, 0, 0, 0, 400, 0, 0, 0, GB2312_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY, DEFAULT_PITCH, "宋体");
HGDIOBJ m_OldFont = SelectObject(hdc, m_Font);
DrawText(hdc, "其他颜色...", -1, &rc, DT_CENTER|DT_VCENTER|DT_SINGLELINE);
SelectObject(hdc, m_OldFont);
DeleteObject(m_Font);
if (m_bCustomColor)
{
rc.right = 8*18+3;
rc.left = 7*18;
rc.top += 2;
rc.bottom = rc.top + 15;
hb = CreateSolidBrush(m_Color);
hbold = SelectObject(hdc, hb);
Rectangle(hdc, rc.left, rc.top, rc.right, rc.bottom);
//SelectObject(hdc, holdpen);
DeleteObject(hb);
}
}
}
//重绘指定区域
void CColorPicker::ReDraw(byte row, byte col, bool hot)
{
HDC hdc = GetWindowDC(m_hwnd);
Draw(hdc, row, col, hot, 0);
ReleaseDC(m_hwnd, hdc);
}
void CColorPicker::OnLButtonDown(long x, long y)
{
//POINT pt;
RECT rc;
//pt.x = x; pt.y = y;
//ClientToScreen(m_hwnd, &pt);
GetClientRect(m_hwnd, &rc);
//if (!PtInRect(&rc, pt))
if (x<rc.left || x>rc.right || y<rc.top || y>rc.bottom)
PostMessage(m_hwnd, WM_CLOSE, 0, 0);
else
{
m_bMouseDown = true;
ReDraw(m_HotRow, m_HotCol, true);
}
}
void CColorPicker::OnLButtonUp(long x, long y)
{
m_bMouseDown = false;
ReDraw(m_HotRow, m_HotCol, true);
if (y>=5*18+10 && m_HotRow==5)
{
ShowWindow(m_hwnd, SW_HIDE);
CColorDialog * crDlg = new CColorDialog(m_Color, CC_FULLOPEN | CC_ANYCOLOR);
int nResult = crDlg->DoModal();
m_Color = crDlg->GetColor();
PostMessage(m_hwnd, WM_CLOSE, 0, 0);
}
else if (m_HotRow<5 && m_HotCol<8)
{
m_Color = ColorMap[m_HotRow][m_HotCol];
PostMessage(m_hwnd, WM_CLOSE, 0, 0);
}
}
void CColorPicker::OnMouseMove(long x, long y)
{
RECT rc;
GetClientRect(m_hwnd, &rc);
InflateRect(&rc, -2, -2);
if (x<rc.left || x>rc.right || y<rc.top || y>rc.bottom)
{
if (m_HotRow != 255)
{
ReDraw(m_HotRow, m_HotCol, false);
m_HotRow = 255;
}
}
else
{
if (y>=5*18+10)
{
if (m_HotRow != 5)
{
ReDraw(m_HotRow, m_HotCol, false);
m_HotRow = 5;
ReDraw(5, 0, true);
}
}
else if (((byte)(y-2) / 18)!=m_HotRow || ((byte)(x-2) / 18)!=m_HotCol)
{
ReDraw(m_HotRow, m_HotCol, false);
m_HotRow = (byte)(y-2) / 18;
m_HotCol = (byte)(x-2) / 18;
ReDraw(m_HotRow, m_HotCol, true);
}
}
}
更多精彩
赞助商链接