梯度父窗口上的背景combobox?

我有窗口与渐变背景。 Combobox有自己的背景画笔。 如何删除combobox中的白色angular落? 我怎样才能改变画笔或其他方式。 在由红色框架标记的图片白色angular落。

与白色角落的组合框

我创buildcombobox为:

DWORD dwStyle = WS_CHILD | CBS_DROPDOWNLIST; if (m_bVisible) dwStyle |= WS_VISIBLE; m_hWnd = CreateWindow(WC_COMBOBOX, NULL, dwStyle, m_posX, m_posY, m_width, m_height, m_hParent, (HMENU)m_id, m_hInstance, NULL); 

我试着用消息WM_CTLCOLOREDIT改变背景画笔,但没有效果:

 case WM_CTLCOLOREDIT: if ((HWND)lParam == m_hSrcListBox) { return (LRESULT)m_hBrush; } break; 

===已解决。 工作版本===

第一种方式。

在父WndProc中:

 case WM_CTLCOLORSTATIC: if ((HWND)lParam == m_hSrcListBox) { return (LRESULT)m_pSrcListBox->GetHbrush(); } break; 

在我的课堂上:

 // // CListBox::GetHbrush(). // // Get brush. // HBRUSH CListBox::GetHbrush() { if (!m_hBrush) { m_hBrush = CreateTransparentBackgroundBrush(m_hParent, m_hWnd); } return m_hBrush; } 

创build透明背景:

 // // CListBox::CreateTransparentBackgroundBrush(). // // Create transparent background for element. // HBRUSH CListBox::CreateTransparentBackgroundBrush(HWND parent, HWND client) { RECT rct; POINT p1; POINT p2; GetWindowRect(client, &rct); p1.x = rct.left; p1.y = rct.top; ScreenToClient(parent, &p1); p2.x = rct.right; p2.y = rct.bottom; ScreenToClient(parent, &p2); HDC hdcParent = GetDC(parent); HDC hdcClient = GetDC(client); HDC hdcmem = CreateCompatibleDC(hdcClient); HBITMAP hbitmap = CreateCompatibleBitmap(hdcClient, p2.x - p1.x, p2.y - p1.y); SelectObject(hdcmem, hbitmap); BitBlt(hdcmem, 0, 0, p2.x - p1.x, p2.y - p1.y, hdcParent, p1.x, p1.y, SRCCOPY); HBRUSH pattern = CreatePatternBrush(hbitmap); DeleteDC(hdcmem); DeleteObject(hbitmap); ReleaseDC(client, hdcClient); ReleaseDC(parent, hdcParent); return pattern; } 

第二种方式。

在父WndProc在WM_ERASEBKGND消息中绘制背景,那么angular不会。

 case WM_ERASEBKGND: m_hdc = (HDC)wParam; // draw background. return TRUE; break; 

两种方法的结果:

没有白色角落的组合框

Solutions Collecting From Web of "梯度父窗口上的背景combobox?"

对于对话框,请处理WM_CTLCOLORDLG并返回组合框的背景画笔

如果你在对话框中显示这个组合框,这个技巧实际上是在对话框的窗口过程中处理WM_CTLCOLORDLG消息。 作为对此消息的回应,您将返回对话框将用于绘制其背景的画笔句柄。

 case WM_CTLCOLORDLG: { // NOTE: This code is wrong because it creates a new brush object each time it processes // the message, which it promptly leaks. It is merely for demonstration purposes. // Normally, you would create the brush once, in response to WM_INITDIALOG, // cache it away, and return that same cached handle each time, finally destroying // the brush in response to WM_NCDESTROY. HBRUSH hBrush = CreateSolidBrush(RGB(255, 120, 0)); return reinterpret_cast<INT_PTR>(hBrush); } 

这是改变对话框的背景颜色的标准,记录方式,也解决了组合框的问题。 显然,无论出于何种原因,组合框控件也都使用这个画刷来绘制它们的背景。 我想他们在绘制自己的时候会向他们的父母发送一个WM_CTLCOLORDLG消息。

当然,这限制了你的GDI画笔的图形功能。 您可以绘制任何您想要的系统或纯色,甚至可以使用阴影或图案/位图笔刷,但是没有简单的方法来创建渐变笔刷。 (GDI +只有一个,而不是GDI)。通常情况下,这并不重要 – 只要在WM_PAINT (甚至是WM_ERASEBKGND )消息处理程序中调用GradientFill函数。 这对于对话框的背景来说工作正常,但是组合框仍然使用WM_CTLCOLORDLG返回的笔刷绘制背景,所以在COLOR_3DFACE (这是默认对话框过程返回的笔刷)绘制的角上仍然有4个点。

WM_CTLCOLORDLG返回空画笔( NULL_BRUSH / HOLLOW_BRUSH )也不起作用。 它略微改变了外观,使得右上角和左下角的像素现在充满了看起来像COLOR_3DSKSHADOW东西,但是它们仍然明显地被填充了除实际的背景渐变之外的颜色。

所以,如果你真的希望它看起来不错,你只剩下一个选择:返回一个句柄到GDI笔刷。 当然,它需要和用来绘制对话框背景的画笔一样。

如果你想渐变填充,我能想到的唯一的解决方案是使用模式/位图刷,其中位图(DDB或DIB)是你的渐变。 不是很好,但至少在Windows 9x限制我们的8×8模式的日子早已不复存在。 也许比我更有创造力的人可以使用这些信息来想一个更好的解决方法?


对于其他窗口,请处理WM_CTLCOLORSTATIC并返回组合框的背景画笔

所有这一切的一个对话框。 但是如果你在一个标准的窗口( 比如对话框以外的东西)显示组合框呢? 在这种情况下WM_CTLCOLORDLG消息从不发送。

相反,组合框将WM_CTLCOLORSTATIC消息发送到其父窗口,然后使用响应该消息返回的画笔手柄来绘制其背景。

这很奇怪,我知道。 我只是通过经验性的测试偶然发现了这一点,我不确定这个理由是什么。 如果我不得不猜测,我会说, CBS_DROPDOWNLIST风格使组合框不可编辑( ,它不是一个真正的组合框,因为没有编辑控件),所以而不是WM_CTLCOLOREDIT ,它使用WM_CTLCOLORSTATIC 。 一个禁用的编辑框也会发送WM_CTLCOLORSTATIC ,一个禁用的组合框与“正常​​的” CBS_SIMPLECBS_DROPDOWN样式一样。

Weirder仍然只有在启用Aero主题时才会发生(Vista和7)。 它不会发生在Windows 10或Luna主题(XP下的视觉样式)或经典主题。 (我没有在Windows 8或8.1上进行测试)。我想,这并不重要,因为所有其他主题都绘制了一个简单的矩形组合框,没有任何角落像素来显示背景。

不管逻辑如何,解决方案仍然是处理WM_CTLCOLORSTATIC消息,并返回希望组合框用来绘制其背景的画笔。

这里同样的考虑适用于上面讨论的对话框。 如果您的窗口使用纯色背景或系统颜色,那么您是无家可归的。 只需将句柄返回到您设置为窗口类的背景画笔的相同笔刷即可。 如果你想使用渐变,你需要找出一种方法来以GDI画笔的形式表示该渐变。

 WNDCLASSEX wcex; wcex.cbSize = sizeof(WNDCLASSEX); wcex.style = CS_HREDRAW | CS_VREDRAW; wcex.lpfnWndProc = WndProc; wcex.cbClsExtra = 0; wcex.cbWndExtra = 0; wcex.hInstance = hInstance; wcex.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDR_APPLICATION)); wcex.hIconSm = LoadIcon(hInstance, MAKEINTRESOURCE(IDR_APPLICATION_SMALL)); wcex.hCursor = LoadCursor(NULL, IDC_ARROW); wcex.hbrBackground = reinterpret_cast<HBRUSH>(COLOR_3DDKSHADOW + 1); // background brush wcex.lpszMenuName = NULL; wcex.lpszClassName = TEXT("My Colored Window Class"); RegisterClassEx(&wcex); 
 case WM_CTLCOLORSTATIC: { // NOTE: No leak here because we're using a system brush in this example. return reinterpret_cast<LRESULT>(GetSysColorBrush(COLOR_3DDKSHADOW)); // background brush } 

我怎样才能删除组合框中的白色角落?

我不知道是否有一个更正式的方法来摆脱它,但一个选项是创建一个使用CreateRoundRectRgn()圆角的区域 ,然后使用SetWindowRgn()将其应用到组合框。 这将掩盖角落。