我创建了一个带透明度选项的自定义滚动条。这种透明度的工作方式非常简单,我使所需的区域无效并让父级擦除并绘制自己,然后我重新绘制滚动条本身。这是一段代码:
void Refresh(bool bForceOwnerRedraw)
{
if (Gui.OwnerRedraw || bForceOwnerRedraw)
InvalidateBackgroundRegion(State.CurrentState);
RedrawWindow(Gui.OwnerWindow, &Gui.DrawingRectangle, NULL, RDW_INVALIDATE | RDW_NOERASE | RDW_INTERNALPAINT);
}
void InvalidateBackgroundRegion(DWORD State)
{
HWND hWndParent = GetParent(Gui.OwnerWindow);
POINT p = {0};
MapWindowPoints(Gui.OwnerWindow, hWndParent, &p, 1);
HRGN BackGroundRegion = CreateRectRgn(Gui.DrawingRectangle.left + p.x, Gui.DrawingRectangle.top + p.y, Gui.DrawingRectangle.right + p.x, Gui.DrawingRectangle.bottom + p.y);
HRGN MainRegion = NULL;
if (State & SELECTED || State & SELECTED_HOVER)
{
int Width = Gui.DrawingRectangle.left + Position.SelectedState.MainDrawing.right + p.x + 1,
Height = Gui.DrawingRectangle.top + Position.SelectedState.MainDrawing.bottom + p.y + 1;
MainRegion = CreateRoundRectRgn(Position.SelectedState.MainDrawing.left + Gui.DrawingRectangle.left + p.x, Position.SelectedState.MainDrawing.top + Gui.DrawingRectangle.top + p.y, Width, Height, Gui.uiCornerRoundness, Gui.uiCornerRoundness);
}
else if (State & UNSELECTED || State & UNSELECTED_HOVER)
{
int Width = Gui.DrawingRectangle.left + Position.UnselectedState.MainDrawing.right + p.x + 1,
Height = Gui.DrawingRectangle.top + Position.UnselectedState.MainDrawing.bottom + p.y + 1;
MainRegion = CreateRoundRectRgn(Position.UnselectedState.MainDrawing.left+Gui.DrawingRectangle.left+p.x, Position.UnselectedState.MainDrawing.top+Gui.DrawingRectangle.top+p.y, Width, Height, Gui.uiCornerRoundness, Gui.uiCornerRoundness);
}
else if (State & INTERMEDIATE || State & INTERMEDIATE_HOVER)
{
int Width = Gui.DrawingRectangle.left + Position.IntermediateState.MainDrawing.right + p.x + 1,
Height = Gui.DrawingRectangle.top + Position.IntermediateState.MainDrawing.bottom + p.y + 1;
MainRegion = CreateRoundRectRgn(Position.IntermediateState.MainDrawing.left + Gui.DrawingRectangle.left + p.x, Position.IntermediateState.MainDrawing.top + Gui.DrawingRectangle.top + p.y, Width, Height, Gui.uiCornerRoundness, Gui.uiCornerRoundness);
}
CombineRgn(BackGroundRegion, BackGroundRegion, MainRegion, RGN_DIFF);
RedrawWindow(hWndParent, NULL, BackGroundRegion, RDW_INVALIDATE | RDW_ERASE | RDW_INTERNALPAINT);
DeleteObject(MainRegion);
DeleteObject(BackGroundRegion);
}
当我调整主窗口大小时出现问题,一切都闪烁。但是我可以通过在主窗口上使用WS_CLIPCHILDREN
标志来防止这种情况,但是我的滚动条会失去它的透明度,因为我不再无法使子窗口拥有的部分无效。
到目前为止我尝试过:
在使父级无效之前,我删除了WS_CLIPCHILDREN
标记,重新绘制,然后重新设置WS_CLIPCHILDREN
标记。 [结果:它工作正常,但是我的CPU使用率超过了30%,所以这是不行的。]
在删除和重新绘制之前,尝试验证子窗口(没有WS_CLIPCHILDREN
)。
[结果:没有用,不知道为什么......也许我......不知道。]
完全禁用了我的滚动条中的所有重新绘制(没有WS_CLIPCHILDREN
)[结果:无效,仍然闪烁。]
我想在这里实现的是通过手动使窗口无效来找到绕过WS_CLIPCHILDREN的方法(可能以某种方式使用SendMessage()绕过它无效)。任何其他建议也欢迎。感谢
编辑:
有关如何创建滚动条的更多信息。在下面的代码中,您可以看到我的滚动条只是一个带有WS_VISIBLE
和WS_CHILD
标志的空子窗口,所有绘画都是使用旧的gdi完成的。
void RegisterScrollbarClass()
{
if (RegisteredClasses.bCustomScrollBar)
return;
WNDCLASSEX wc;
wc.cbSize = sizeof(WNDCLASSEX);
wc.style = CS_HREDRAW | CS_VREDRAW;
wc.lpfnWndProc = BaseWindow::stWinMsgHandler;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = NULL;
wc.hIcon = NULL;
wc.hCursor = NULL;
wc.hbrBackground = NULL;
wc.lpszMenuName = NULL;
wc.lpszClassName = TEXT("CUSTOM_SCROLLBAR");
wc.hIconSm = NULL;
if (!RegisterClassEx(&wc))
{
MessageBox(NULL, TEXT("Button Class Registration Failed!"), TEXT("ERROR!"), MB_ICONERROR);
exit(EXIT_FAILURE);
}
RegisteredClasses.bCustomScrollBar = true;
}
HWND CreateScrollbar(DWORD dwExStyle, LPCTSTR lpClassName, LPCTSTR lpWindowName, DWORD dwStyle, int x, int y, int nWidth, int nHeight, HWND hWndParent, HMENU hMenu, HINSTANCE hInstance, LPVOID lpParam)
{
DWORD ScrollbarStyle = NULL, Child = NULL;
if ((dwStyle & SB_VERT) == SB_VERT)
ScrollbarStyle = SB_VERT;
else if ((dwStyle & SB_HORZ) == SB_HORZ)
ScrollbarStyle = SB_HORZ;
else
return NULL;
if ((dwStyle & WS_CHILD) == WS_CHILD)
Child = WS_CHILD;
if ((dwStyle & WS_VISIBLE) == WS_VISIBLE)
Child |= WS_VISIBLE;
RegisterScrollbarClass();
Scrollbar.push_back(CustomScrollbar(ScrollbarStyle, x, y, nWidth, nHeight, (int)hMenu));
for(unsigned int i = 0; i < Scrollbar.size(); i++)
Scrollbar.at(i).Create();
if (Scrollbar.at(Scrollbar.size()-1).Create(dwExStyle, lpClassName, NULL, Child, x, y, nWidth, nHeight, hWndParent, hMenu, hInstance, lpParam) != NULL)
{
if (Scrollbar.size() == 2)
Scrollbar.at(Scrollbar.size() - 1).EnableTransparent(true);
return Scrollbar.at(Scrollbar.size()-1).WindowHandle();
}
else
{
Scrollbar.pop_back();
return NULL;
}
}
您可以在此下载示例程序:http://www.putlocker.com/file/B8704C613BC7EC96
解决:
感谢Raymond Chen,我从我的Scroll bar课程中删除了CS_HREDRAW | CS_VREDRAW
,我的工作就像没有WS_CLIPCHILDREN
的魅力。