程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> VC >> 關於VC++ >> C++實現仿Office風格的顏色選取框代碼

C++實現仿Office風格的顏色選取框代碼

編輯:關於VC++

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

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved