ComboBox ListBox 重绘

// 重绘.cpp : Defines the entry point for the application.
//

#include "stdafx.h"
#include "resource.h"


#define MAX_LOADSTRING 100

// Global Variables:
HINSTANCE hInst;                                // current instance
TCHAR szTitle[MAX_LOADSTRING];                                // The title bar text
TCHAR szWindowClass[MAX_LOADSTRING];                                // The title bar text

// Foward declarations of functions included in this code module:
ATOM                MyRegisterClass(HINSTANCE hInstance);
BOOL                InitInstance(HINSTANCE, int);
LRESULT CALLBACK    WndProc(HWND, UINT, WPARAM, LPARAM);

int APIENTRY WinMain(HINSTANCE hInstance,
                     HINSTANCE hPrevInstance,
                     LPSTR     lpCmdLine,
                     int       nCmdShow)
{
     // TODO: Place code here.
    MSG msg;
    HACCEL hAccelTable;

    // Initialize global strings
    LoadString(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING);
    LoadString(hInstance, IDC_MY, szWindowClass, MAX_LOADSTRING);
    MyRegisterClass(hInstance);

    // Perform application initialization:
    if (!InitInstance (hInstance, nCmdShow)) 
    {
        return FALSE;
    }

    hAccelTable = LoadAccelerators(hInstance, (LPCTSTR)IDC_MY);

    // Main message loop:
    while (GetMessage(&msg, NULL, 0, 0)) 
    {
        if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg)) 
        {
            TranslateMessage(&msg);
            DispatchMessage(&msg);
        }
    }

    return msg.wParam;
}



//
//  FUNCTION: MyRegisterClass()
//
//  PURPOSE: Registers the window class.
//
//  COMMENTS:
//
//    This function and its usage is only necessary if you want this code
//    to be compatible with Win32 systems prior to the 'RegisterClassEx'
//    function that was added to Windows 95. It is important to call this function
//    so that the application will get 'well formed' small icons associated
//    with it.
//
ATOM MyRegisterClass(HINSTANCE hInstance)
{
    WNDCLASSEX wcex;

    wcex.cbSize = sizeof(WNDCLASSEX); 

    wcex.style            = CS_HREDRAW | CS_VREDRAW;
    wcex.lpfnWndProc    = (WNDPROC)WndProc;
    wcex.cbClsExtra        = 0;
    wcex.cbWndExtra        = 0;
    wcex.hInstance        = hInstance;
    wcex.hIcon            = LoadIcon(hInstance, (LPCTSTR)IDI_MY);
    wcex.hCursor        = LoadCursor(NULL, IDC_ARROW);
    wcex.hbrBackground    = (HBRUSH)(COLOR_WINDOW+1);
    wcex.lpszMenuName    = (LPCSTR)IDC_MY;
    wcex.lpszClassName    = szWindowClass;
    wcex.hIconSm        = LoadIcon(wcex.hInstance, (LPCTSTR)IDI_SMALL);

    return RegisterClassEx(&wcex);
}

//
//   FUNCTION: InitInstance(HANDLE, int)
//
//   PURPOSE: Saves instance handle and creates main window
//
//   COMMENTS:
//
//        In this function, we save the instance handle in a global variable and
//        create and display the main program window.
//
BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
{
   HWND hWnd;

   hInst = hInstance; // Store instance handle in our global variable

   hWnd = CreateWindowEx(NULL, szWindowClass, szTitle, WS_OVERLAPPEDWINDOW,
      CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, NULL, NULL, hInstance, NULL);

   if (!hWnd)
   {
      return FALSE;
   }

   ShowWindow(hWnd, nCmdShow);
   UpdateWindow(hWnd);

   return TRUE;
}

void _cdecl Trace(LPCSTR lpszFormat, ...)
{
    va_list args;
    va_start(args, lpszFormat);

    char szBuffer[1024*20];

    int nBuf = _vsnprintf(szBuffer, sizeof(szBuffer), lpszFormat, args);

    OutputDebugStringA(szBuffer);
    va_end(args);
}

#define TRACE Trace

BOOL ModifyStyle(HWND hWnd, DWORD dwRemove, DWORD dwAdd, UINT nFlags = 0)
{

    DWORD dwStyle = ::GetWindowLong(hWnd, GWL_STYLE);
    DWORD dwNewStyle = (dwStyle & ~dwRemove) | dwAdd;
    if(dwStyle == dwNewStyle)
        return FALSE;

    ::SetWindowLong(hWnd, GWL_STYLE, dwNewStyle);
    if(nFlags != 0)
    {
        ::SetWindowPos(hWnd, NULL, 0, 0, 0, 0,
            SWP_NOSIZE | SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE | nFlags);
    }

    return TRUE;
}

BOOL ModifyStyleEx(HWND hWnd, DWORD dwRemove, DWORD dwAdd, UINT nFlags = 0)
{

    DWORD dwStyle = ::GetWindowLong(hWnd, GWL_EXSTYLE);
    DWORD dwNewStyle = (dwStyle & ~dwRemove) | dwAdd;
    if(dwStyle == dwNewStyle)
        return FALSE;

    ::SetWindowLong(hWnd, GWL_EXSTYLE, dwNewStyle);
    if(nFlags != 0)
    {
        ::SetWindowPos(hWnd, NULL, 0, 0, 0, 0,
            SWP_NOSIZE | SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE | nFlags);
    }

    return TRUE;
}

void DrawGradientV(HDC hDC, COLORREF colorStart, COLORREF colorEnd, RECT& DrawRect )
{
    //如果开始结束色相同,则使用绘制色块命令绘制
    if (colorStart==colorEnd)
    {
        HBRUSH h_Brush=CreateSolidBrush(colorStart);
        FillRect(hDC,&DrawRect,h_Brush);
        DeleteObject(h_Brush);
        return ;
    }

    //找到其实颜色和结束颜色之间的最大颜色值,决定渐变步长等
    int r, g, b;
    float rStep, gStep, bStep;

    r = (GetRValue(colorEnd) - GetRValue(colorStart));
    g = (GetGValue(colorEnd) - GetGValue(colorStart));
    b = (GetBValue(colorEnd) - GetBValue(colorStart));

    int nSteps = max(abs(r), max(abs(g), abs(b)));

    nSteps=DrawRect.bottom-DrawRect.top;

    //计算每个颜色的步长
    rStep = abs(r/(float)nSteps);
    gStep = abs(g/(float)nSteps);
    bStep = abs(b/(float)nSteps);

    int r1,g1,b1;

    r1 = GetRValue(colorStart);
    g1 = GetGValue(colorStart);
    b1 = GetBValue(colorStart);

    //准备GDI
    HDC hMemDC=CreateCompatibleDC(hDC);     //创建内存DC
    HBITMAP hBitmap=::CreateCompatibleBitmap(hDC,1,nSteps);//创建位图
    ::SelectObject(hMemDC,hBitmap);   //把位图选进内存DC


    for(int i = 0; i<nSteps ; i ++ ) 
    {
        SetPixel(hMemDC,0,i,RGB( r1+r*i/nSteps, g1+g*i/nSteps, b1+b*i/nSteps));
    }

    //内存DC映射到屏幕DC
    StretchBlt(hDC, DrawRect.left,DrawRect.top,DrawRect.right-DrawRect.left,DrawRect.bottom-DrawRect.top,hMemDC,0,0,1,nSteps,SRCCOPY); 

    //删除
    ::DeleteDC(hMemDC);
    ::DeleteObject(hBitmap); 
}



HWND    hwListbox=NULL;
WNDPROC old_ListBox_WndProc=NULL;

LRESULT CALLBACK ListBox_WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    //TRACE("message:%08X", message);

    if (message == WM_ERASEBKGND)
    {

        return TRUE;
    }

    return CallWindowProc(old_ListBox_WndProc,hWnd,message,wParam,lParam);
}

HWND CreateListBox(HWND hParent)
{

   HWND hList=::CreateWindowEx(   NULL, "ListBox",
                                  NULL,
                                  WS_CHILD|WS_VSCROLL|WS_VISIBLE|LBS_NOTIFY|LBS_HASSTRINGS|LBS_DISABLENOSCROLL|LBS_NOINTEGRALHEIGHT|LBS_OWNERDRAWVARIABLE,
                                  10,10,300,300,
                                  hParent,
                                  (HMENU)0x1000,
                                  hInst,
                                  NULL);

   
    old_ListBox_WndProc=(WNDPROC)::SetWindowLong(hList,GWL_WNDPROC,(LONG)ListBox_WndProc);

    int i;

    char text[256];

    for (i=0;i<1000;i++)
    {
        sprintf(text,"list item %d", i);
        ListBox_AddString(hList, text);
    }

    for (i=0;i<1000;i++)
    {
        ListBox_SetItemHeight(hList,i,30);
    }
    
    
    return hList;
}

BOOL OnDrawListBox(LPDRAWITEMSTRUCT lpdis)
{
    
    if (lpdis->itemState & ODS_SELECTED)
    {
        DrawGradientV(lpdis->hDC,0xffcccc,0xcc9999,lpdis->rcItem);
    }else{

        HBRUSH hBrush=::CreateSolidBrush(0xFEF5EA);
        FillRect(lpdis->hDC,&lpdis->rcItem,hBrush);
        DeleteObject(hBrush);
    }

    char buff[256];

    ListBox_GetText(lpdis->hwndItem,lpdis->itemID,buff);

    SIZE s;
    GetTextExtentPoint32(lpdis->hDC," ", 1, &s);

    RECT drc=lpdis->rcItem;
    drc.top=drc.top+(drc.bottom-drc.top-s.cy)/2;
    drc.bottom=drc.top+s.cy;
    drc.left+=s.cy/2;
    SetBkMode(lpdis->hDC, TRANSPARENT);
    DrawText(lpdis->hDC,buff,strlen(buff),&drc,DT_LEFT|DT_VCENTER);

    return TRUE;
}

HWND    hwComboBox=NULL;
WNDPROC old_ComboBox_WndProc=NULL;
WNDPROC old_ComboBox_ListBox_WndProc=NULL;

LRESULT CALLBACK ComboBox_ListBox_WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{

    if (message == WM_ERASEBKGND) return TRUE;

    return CallWindowProc(old_ComboBox_ListBox_WndProc,hWnd,message,wParam,lParam);
}

LRESULT CALLBACK ComboBox_WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    PAINTSTRUCT ps;
    HDC hdc;

    if (message == WM_ERASEBKGND)  return TRUE;

    if (message == WM_PAINT)
    {
        hdc = BeginPaint(hWnd, &ps);

        DRAWITEMSTRUCT drawItem;
        memset(&drawItem,0,sizeof(drawItem));
        drawItem.hDC=hdc;
        drawItem.hwndItem=hWnd;
        GetClientRect(hWnd,&drawItem.rcItem);
        drawItem.CtlID=GetWindowLong(hWnd,GWL_ID);

        if (::GetKeyState(VK_LBUTTON) & 0x80)
        {
            drawItem.itemState=1;
        }

        drawItem.itemID=-1;

        SendMessage(GetParent(hWnd),WM_DRAWITEM,0,(LPARAM)&drawItem);

        EndPaint(hWnd, &ps);

        return TRUE;
    }


    return CallWindowProc(old_ComboBox_WndProc,hWnd,message,wParam,lParam);
}

HWND CreateComboBox(HWND hParent)
{
   HWND hComboBox=::CreateWindowEx( NULL, "ComboBox",
                                    NULL,
                                    WS_CHILD|WS_VSCROLL|WS_VISIBLE|CBS_DROPDOWNLIST|CBS_HASSTRINGS|CBS_DISABLENOSCROLL|CBS_NOINTEGRALHEIGHT|CBS_OWNERDRAWVARIABLE,
                                    320,10,300,320,
                                    hParent,
                                    (HMENU)0x1001,
                                    hInst,
                                    NULL);

    old_ComboBox_WndProc=(WNDPROC)SetWindowLong(hComboBox,GWL_WNDPROC,(LONG)ComboBox_WndProc);


    COMBOBOXINFO cbi= { sizeof(COMBOBOXINFO) };
    if (GetComboBoxInfo(hComboBox,&cbi))
    {
        //TRACE("hComboBox:%08X cbi.hwndCombo:%08X cbi.hwndItem:%08X cbi.hwndList:%08X", hComboBox, cbi.hwndCombo, cbi.hwndItem, cbi.hwndList);

        ModifyStyle(cbi.hwndList,WS_BORDER,0,0);
        ModifyStyleEx(cbi.hwndList,WS_EX_CLIENTEDGE,0,0);

        old_ComboBox_ListBox_WndProc=(WNDPROC)SetWindowLong(cbi.hwndList,GWL_WNDPROC,(LONG)ComboBox_ListBox_WndProc);
    }

    int i;

    char text[256];

    for (i=0;i<1000;i++)
    {
        sprintf(text,"list item %d", i);
        ComboBox_AddString(hComboBox, text);
    }

    ComboBox_SetItemHeight(hComboBox,-1,20);

    for (i=0;i<1000;i++)
    {
        ComboBox_SetItemHeight(hComboBox,i,30);
    }

    return hComboBox;
}

BOOL OnDrawComboBox(LPDRAWITEMSTRUCT lpdis)
{

    char buff[256]={0};

    //绘制ComboBox控件
    if (lpdis->itemID==-1) 
    {
        //读取但前选择的文字

        int icur=ComboBox_GetCurSel(lpdis->hwndItem);

        if (icur!=-1)
        {
            ComboBox_GetLBText(lpdis->hwndItem,icur,buff);
        }

        //绘制ComboBox背景
        HBRUSH hBrush;

        if (lpdis->itemState==2)
        {
            hBrush=::CreateSolidBrush(0xFBEDDF);
        }else{
            hBrush=::CreateSolidBrush(0xFEF5EA);
        }

        FillRect(lpdis->hDC,&lpdis->rcItem,hBrush);

        DeleteObject(hBrush);

        //绘制文字
        SIZE s;
        GetTextExtentPoint32(lpdis->hDC," ", 1, &s);

        RECT drc=lpdis->rcItem;
        drc.top=drc.top+(drc.bottom-drc.top-s.cy)/2;
        drc.bottom=drc.top+s.cy;
        drc.left+=s.cy/2;

        int slen=strlen(buff);
        if (slen)
        {
            SetBkMode(lpdis->hDC, TRANSPARENT);
            DrawText(lpdis->hDC,buff,slen,&drc,DT_LEFT|DT_VCENTER);
        }

    //绘制ListBox背景
    }else{ 

        if (lpdis->itemState & ODS_SELECTED)
        {
            DrawGradientV(lpdis->hDC,0xffcccc,0xcc9999,lpdis->rcItem);
        }else{

            HBRUSH hBrush=::CreateSolidBrush(0xFEF5EA); //0xFBEDDF
            FillRect(lpdis->hDC,&lpdis->rcItem,hBrush);
            DeleteObject(hBrush);
        }

        ComboBox_GetLBText(lpdis->hwndItem,lpdis->itemID,buff);

        //绘制文字
        SIZE s;
        GetTextExtentPoint32(lpdis->hDC," ", 1, &s);

        RECT drc=lpdis->rcItem;
        drc.top=drc.top+(drc.bottom-drc.top-s.cy)/2;
        drc.bottom=drc.top+s.cy;
        drc.left+=s.cy/2;

        int slen=strlen(buff);
        if (slen)
        {
            SetBkMode(lpdis->hDC, TRANSPARENT);
            DrawText(lpdis->hDC,buff,slen,&drc,DT_LEFT|DT_VCENTER);
        }

    }

    return TRUE;
}

//
//  FUNCTION: WndProc(HWND, unsigned, WORD, LONG)
//
//  PURPOSE:  Processes messages for the main window.
//
//  WM_COMMAND    - process the application menu
//  WM_PAINT    - Paint the main window
//  WM_DESTROY    - post a quit message and return
//
//
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    int wmId, wmEvent;
    PAINTSTRUCT ps;
    HDC hdc;
    TCHAR szHello[MAX_LOADSTRING];
    LoadString(hInst, IDS_HELLO, szHello, MAX_LOADSTRING);

    switch (message)
    {
        case WM_CREATE:
            {
                hwListbox  = CreateListBox(hWnd);
                hwComboBox = CreateComboBox(hWnd);
                return TRUE;
            }
            break;
        case WM_CTLCOLORLISTBOX:
            {
                //TRACE("WM_CTLCOLORLISTBOX");
            }
            break;
        case WM_DRAWITEM:
            {
                LPDRAWITEMSTRUCT lpdis=(LPDRAWITEMSTRUCT)lParam;

                if (lpdis->CtlID==0x1000)
                {
                    if (OnDrawListBox(lpdis)) return TRUE;

                }else if (lpdis->CtlID==0x1001){

                    if (OnDrawComboBox(lpdis)) return TRUE;
                }

                return DefWindowProc(hWnd, message, wParam, lParam);
            }
            break;
        case WM_COMMAND:
            wmId    = LOWORD(wParam); 
            wmEvent = HIWORD(wParam); 
            // Parse the menu selections:
            switch (wmId)
            {
                case IDM_EXIT:
                   DestroyWindow(hWnd);
                   break;
                default:
                   return DefWindowProc(hWnd, message, wParam, lParam);
            }
            break;
        case WM_PAINT:
            hdc = BeginPaint(hWnd, &ps);

            EndPaint(hWnd, &ps);
            break;
        case WM_DESTROY:
            PostQuitMessage(0);
            break;
        default:
            return DefWindowProc(hWnd, message, wParam, lParam);
   }
   return 0;
}


 

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值