如何使用 WM_CTLCOLORLISTBOX?

问题描述

我正在尝试将画笔设置为在组合框的背景颜色中使用,如下所示:

    case WM_CTLCOLORLISTBox:
      if(hwndCombo == (HWND)lParam)
      {
        return (LRESULT) hBrush;
      }
      else
      {
        break;
      }

然而,hwndCombo == (HWND)lParam 从来都不是真的。我可以看到消息已发送,因为这有效:

case WM_CTLCOLORLISTBox:
        return (LRESULT) hBrush;

但我想选择那些我要设置颜色的。我错过了什么?

完整代码

#pragma comment(lib,"user32.lib")
#pragma comment(lib,"Comctl32.lib")
#pragma comment(lib,"Gdi32.lib")
#pragma comment(lib,"Comdlg32.lib")

#define WIN32_LEAN_AND_MEAN
#define UNICODE
#define _UNICODE

#include <windows.h>
#include <winuser.h>
#include <assert.h>

#define COUNTOF(a) (sizeof(a)/sizeof(a[0]))

LRESULT CALLBACK WndProc(HWND,UINT,WParaM,LParaM);
HFONT getDefaultFont();
void SetDefaultFont(HWND hwnd);

HFONT hDefaultSystemFont;

HINSTANCE g_hinst;

const wchar_t *items[] =
{ 
  L"Windows",L"Mac",L"FreeBSD",L"Arch",};
HWND hwndCombo;
HBrush hBrush;

enum
{
  ID_COMBO = 10,ID_BTN1,};

int WINAPI wWinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,PWSTR lpCmdLine,int nCmdshow) {

    HWND hwnd;
    MSG  msg ;    
    WNDCLASSW wc = {0};
    wc.lpszClassName = L"Application";
    wc.hInstance     = hInstance ;
    wc.hbrBackground = GetSysColorBrush(COLOR_3DFACE);
    wc.lpfnWndProc   = WndProc ;
    wc.hCursor       = LoadCursor(0,IDC_ARROW);

    g_hinst = hInstance;
  
    RegisterClassW(&wc);
    hwnd = CreateWindowW(wc.lpszClassName,L"",WS_OVERLAPPEDWINDOW | WS_VISIBLE,100,300,170,hInstance,0);  


    while (GetMessage(&msg,NULL,0))
    {
        dispatchMessage(&msg);
    }

    return (int) msg.wParam;
}

LRESULT CALLBACK WndProc(HWND hwnd,UINT msg,WParaM wParam,LParaM lParam) {

    switch(msg)
    {
    
        case WM_CREATE:
        {
              hwndCombo = CreateWindow(L"ComboBox",WS_CHILD | WS_VISIBLE | CBS_DROPDOWN,10,120,110,hwnd,(HMENU) ID_COMBO,g_hinst,NULL);
              for (int i = 0; i < COUNTOF(items); i++ )
              {
                SendMessageW(hwndCombo,CB_ADDSTRING,(LParaM) items[i]);
              }
              SetDefaultFont(hwndCombo);

              HWND btn1 =
              CreateWindow(L"Button",L"Click me",WS_CHILD | WS_VISIBLE,5,40,90,25,(HMENU) ID_BTN1,NULL); 
              SetDefaultFont(btn1);
              hBrush = CreateSolidBrush(RGB(0,128,0));
        }
        break;

        case WM_DESTROY:
            DeleteObject(hDefaultSystemFont);
            hDefaultSystemFont = NULL;
            PostQuitMessage(0);
            break;

        case WM_CTLCOLORLISTBox:
          if(hwndCombo == (HWND)lParam)
          {
            return (LRESULT) hBrush;
          }
          else
          {
            break;
          }
    }
  
    return DefWindowProcW(hwnd,msg,wParam,lParam);
}


HFONT getDefaultFont()
{
  if(hDefaultSystemFont == NULL) {
    NONCLIENTMETRICS ncm;
    ncm.cbSize = sizeof(NONCLIENTMETRICS);
    SystemParametersInfo(SPI_GETNONCLIENTMETRICS,sizeof(NONCLIENTMETRICS),&ncm,0);
    hDefaultSystemFont = CreateFontIndirect(&ncm.lfMessageFont);
  }
  return hDefaultSystemFont;
}


void SetDefaultFont(HWND hwnd)
{
    SendMessage(hwnd,WM_SETFONT,(LParaM) getDefaultFont(),TRUE);
}

解决方法

HWND 消息的 lParam 中提供的 WM_CTLCOLORLISTBOX 是用于 ListBox,而不是用于 ComboBox。您可以使用 GetComboBoxInfo()CB_GETCOMBOBOXINFO 获取 ComboBox 列表框的 HWND

UPDATE:您也可以在 GetParent() 提供的 HWND 上使用 WM_CTLCOLORLISTBOX 来获取其拥有的 ComboBox 的 HWND