C++ 绕过WS_CLIPCHILDREN
我创建了一个带有透明度选项的自定义滚动条。这种透明度的工作方式非常简单,我使所需区域无效,让父对象擦除并绘制自己,然后重新绘制滚动条本身。下面是一些代码:C++ 绕过WS_CLIPCHILDREN,c++,winapi,C++,Winapi,我创建了一个带有透明度选项的自定义滚动条。这种透明度的工作方式非常简单,我使所需区域无效,让父对象擦除并绘制自己,然后重新绘制滚动条本身。下面是一些代码: void Refresh(bool bForceOwnerRedraw) { if (Gui.OwnerRedraw || bForceOwnerRedraw) InvalidateBackgroundRegion(State.CurrentState); RedrawWind
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%,所以它是一个no no.]WS\u CLIPCHILDREN
)。
[结果:不起作用,不知道为什么…也许我…不知道。]WS\u CLIPCHILDREN
)[结果:未工作,仍闪烁。]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;
}
}
void RegisterScrollbarClass()
{
if(registeredClass.bCustomScrollBar)
返回;
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=文本(“自定义滚动条”);
wc.hIconSm=NULL;
如果(!RegisterClassEx(&wc))
{
MessageBox(NULL,文本(“按钮类注册失败!”)、文本(“错误!”)、MB_ICONERROR);
退出(退出失败);
}
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;
其他的
返回NULL;
if((dwStyle&WS_CHILD)==WS_CHILD)
Child=WS_Child;
如果((dwStyle&WS_可见)==WS_可见)
Child |=WS|u可见;
RegisterScrollbarClass();
滚动条。向后推(自定义滚动条(滚动条样式,x,y,nWidth,nHeight,(int)humenu));
for(无符号int i=0;i
您可以在此处下载示例程序:
已解决:
多亏了Raymond Chen,我从我的滚动条课程中删除了
CS|HREDRAW | CS|u VREDRAW
,我的工作就像一个没有WS_CLIPCHILDREN
的魔咒 WS_CLIPCHILDREN
与“组框”(按钮带有BS_group
somethingsomething样式)的透明度也非常不兼容。只是观察。这不是我的问题,我只有WS_可见和WS_子标志。我添加了一些代码来解释我的意思。我的滚动条只是一个孤独的窗口:)闪烁来自CS|HREDRAW | CS|u VREDRAW
和你在屏幕上而不是在屏幕下作曲的事实。哇,我没有话。。。我想我检查了CS|HREDRAW | CS|u VREDRAW
,但它不起作用,但我错了。非常感谢。圣诞快乐:)