用VC寫了個顏色選取框,仿Office風格用VC寫了個顏色選取框,仿Office風格,沒用MFC什麼的框架,調用很簡單指定顯示位置POINT和默認顏色就可以,如:
POINT pt;
pt.x = 100; pt.y = 100;
CColorPicker *clrpk = new CColorPicker(&pt, HexClr(0xFF0000));
效果圖:
C++的顏色拾取框
代碼:
ColorPicker.h
#define HexClr(rgb) ((DWORD)(rgb>>16)|(rgb&0xFF00)|((rgb&0xFF)<<16))
#define COLORPICKERWINNAME "ColorPickerWin"
#define WM_COLORSELECTED WM_USER+2938
static DWORD ColorMap[5][8] =
{
{ HexClr(0x000000), HexClr(0x993300), HexClr(0x333300), HexClr(0x003300), HexClr(0x003366), HexClr(0x000080), HexClr(0x333399), HexClr(0x333333)},
{ HexClr(0x800000), HexClr(0xFF6600), HexClr(0x808000), HexClr(0x008000), HexClr(0x008080), HexClr(0x0000FF), HexClr(0x666699), HexClr(0x808080)},
{ HexClr(0xFF0000), HexClr(0xFF9900), HexClr(0x99CC00), HexClr(0x008080), HexClr(0x33CCCC), HexClr(0x3366FF), HexClr(0x800080), HexClr(0x999999)},
{ HexClr(0xFF00FF), HexClr(0xFFCC00), HexClr(0xFFFF00), HexClr(0x00FF00), HexClr(0x00FFFF), HexClr(0x00CCFF), HexClr(0x993366), HexClr(0xC0C0C0)},
{ HexClr(0xFF99CC), HexClr(0xFFCC99), HexClr(0xFFFF99), HexClr(0xCCFFCC), HexClr(0xCCFFFF), HexClr(0x99CCFF), HexClr(0xCC99FF), HexClr(0xFFFFFF)}
};
class CColorPicker
{
public:
HINSTANCE m_hInstance; //debug
CColorPicker(POINT *pt, DWORD DefaultColor);
~CColorPicker();
HWND GetHwnd();
DWORD GetColor();
void OnPaint();
void OnLButtonDown(long x, long y);
void OnLButtonUp(long x, long y);
void OnMouseMove(long x, long y);
private:
HWND m_hwnd;
DWORD m_Color;
byte m_HotRow, m_HotCol;
bool m_bCustomColor;
bool m_bMouseDown;
void CreateColorPicker(POINT *pt);
void Draw(HDC hdc, byte row, byte col, bool hot, byte correction);
void ReDraw(byte row, byte col, bool hot);
};
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);
}
}
}