繁体   English   中英

双缓冲公共控件

[英]Double buffer common controls

有没有办法双重缓冲共同控件 目前,当他们调整大小时,他们闪烁。 很多.....

编辑:如果它有帮助,它是一组按钮控件和一些编辑控件,都位于选项卡控件的顶部。 Tab控件重绘自身,然后按钮重绘自己。 当按钮重绘时,它们会闪烁。

EDIT2:这是我遇到的问题的一个例子: http//billy-oneal.com/Lobfuscator.exe

我知道这个话题已经很老了,但这可能与遇到闪烁问题的人有关。

非常像Billy,我遇到了一个问题,当切换标签时会弹出一个问题,当显示和隐藏时,放置在标签上的控件会闪烁。 作为参考,我广泛使用ShowWindow函数来隐藏和显示控件。

我一直在摆弄WS_EX_COMPOSITED几个小时,它给了我非常奇怪的结果。 我也没有调整任何大小,对话框设计为全屏运行,它适应当前的桌面分辨率。

这是我手动创建的对话框的布局,为每个控件调用CreateWindowEx函数:

主窗口 - 一些控件 - 选项卡控件----更多控件

缩进代表父子关系。 选项卡控件在创建时设置了WS_CHILD和WS_CLIPCHILDREN样式,所有控件都设置了WS_CHILD样式。

最终诀窍是什么呢?

MainProc proc hWnd:DWORD,uMsg:DWORD,wParam:DWORD,lParam:DWORD
    mov eax,uMsg
    cmp eax,WM_INITDIALOG
    je @WM_INITDIALOG
    ...

    invoke DefWindowProc,hWnd,uMsg,wParam,lParam
    ret

@WM_INITDIALOG:
    ...

    invoke GetWindowLong,hWnd,GWL_EXSTYLE
    or eax,WS_EX_COMPOSITED
    invoke SetWindowLong,hWnd,GWL_EXSTYLE,eax
    ...

MainProc endp

这个位是用汇编语言(MASM32)编写的,但我确信你会得到它的要点。 简单地说,在WM_INITDIALOG期间的某个时间获取主窗口的EX_STYLE并向其添加WS_EX_COMPOSITED。

在这个单一的情况下,这种方法适用于32位Windows XP SP3和64位Windows 7 SP1。 没有必要将WS_EX_COMPOSITED样式添加到任何选项卡的子控件(我使用的一些静态控件设置了WS_EX_TRANSPARENT,但这是出于其他原因),此时没有明显需要在WM_ERASEBKGND上返回非零值信息。 我也没有在中等强大的C2D机器上遇到任何性能问题。

作为参考,这是我的主要

Main proc hInst:DWORD,hPrevInst:DWORD,CmdLine:DWORD,CmdShow:DWORD
    LOCAL wc:WNDCLASSEX,msg:MSG

    mov wc.cbSize,sizeof WNDCLASSEX
    mov wc.style,CS_HREDRAW or CS_VREDRAW
    mov wc.lpfnWndProc,offset MainProc
    mov wc.cbClsExtra,NULL
    mov wc.cbWndExtra,DLGWINDOWEXTRA
    push hInst
    pop wc.hInstance
    mov wc.hbrBackground,COLOR_BTNFACE+1
    mov wc.lpszClassName,offset szClassName
    invoke LoadIcon,NULL,IDI_APPLICATION
    mov wc.hIcon,eax
    mov wc.hIconSm,eax
    invoke LoadCursor,NULL,IDC_ARROW
    mov wc.hCursor,eax
    invoke RegisterClassEx,addr wc
    invoke CreateDialogParam,hInstance,IDD_MAIN,NULL,addr MainProc,NULL
    invoke ShowWindow,hWin,SW_SHOWNORMAL
    invoke UpdateWindow,hWin
    invoke LoadAccelerators,hInstance,IDD_ACC_TABLE
    mov hAcc,eax
    jmp @2
@1:
    invoke TranslateAccelerator,hWin,hAcc,addr msg
    test eax,eax
    jne @2
    invoke TranslateMessage,addr msg
    invoke DispatchMessage,addr msg
@2:
    invoke GetMessage,addr msg,NULL,0,0
    test eax,eax
    jne @1

    mov eax,msg.wParam
    ret

Main endp

这里没有什么特别的,也没有。 我将“对话框控件灰色”设置为背景颜色并使用CS_ * REDRAW样式,这些似乎不会影响这种情况。 我用来创建主窗口的“空”对话框模板就是这个

IDD_MAIN DIALOGEX 0,0,318,177
FONT 8,"MS Sans Serif",0,0,0
CLASS "DLGCLASS"
STYLE 0x90800000
EXSTYLE 0x00000008
BEGIN
END

希望这可以为寻找答案的人节省一些时间。 这有点长,但我想尽可能详细地说明一下。

问候。

查看使用WS_EX_COMPOSITEDWS_EX_TRANSPARENT样式。 它们提供双重缓冲,当底层位图完成绘制时,将调用WM_PAINT,因为它从下到上绘制子控件,因此您只能在窗口过程中绘制。 我过去曾经使用它并且工作得很好。

将顶级窗口(容器)设置为扩展样式WS_EX_COMPOSITED,将子窗口设置为WS_EX_TRANSPARENT。 另外,请记住定义:

#define WINVER 0x501 

有关合成样式的信息,请参阅CreateWindowEx 这也使得在子窗口上实现每像素透明度成为可能。

UPDATE

如何使用WM_PRINTCLIENT将客户区传输到DC上的位图并将整个客户区作为整体进行blit?

http://blogs.msdn.com/larryosterman/archive/2008/08/27/larry-s-new-favorite-windows-message-wm-printclient.aspx

拉里奥斯特曼最近在博客上写了这个主题; 你可能会在那里找到一些有趣的细节

确实,

有人刚才在我的一个帖子上发布了这个问题的答案。 看看: 这里

并且一定要赞美他的真棒。

代码是C#,希望有一个简单的翻译。

在不确切知道你在做什么的情况下,我假设你正在使用MFC或Win32 C。

您可能想要对WM_SIZE消息进行大小调整。 我不确定你在哪里调整控件的大小,但我认为你在调整大小的时候就是这样做了,这就是为什么它会导致闪烁。

另外,我在想,但我不知道,你可能会使用SetWindowPos函数,对于uFlags,你可以使用SWP_NOREDRAW。 虽然我不确定这对普通控制有多好。

您可以在一开始就创建一个内存设备上下文MemDC。 将所有内容绘制到MemDC中,然后当窗口收到WM_PAINT消息或无效时,通过位blitting将MemDC复制到实际DC。

我记得几年前Herbert Schildt在他的书中阅读了这项技术(Windows 98 Programming from the Ground Up)。 这样,当你将内存直流电压到实际直流时,所有的重绘都会更快。 但是最重​​要的一点是,你想要使用的内存直流有多大! 但他展示了如何做到这一点。 Osborne McGraw Hill出版的那本书的所有章节都有代码下载。

希望这会有所帮助,最好的问候,汤姆。

你没有使用WS_EX_TRANSPARENT,是吗? 这将导致在控件之前绘制底层窗口,当底部窗口擦除时,您会闪烁。

WTL::CDoubleBufferImpl我们使用WTL::CDoubleBufferImpl混合。 我们甚至用GDI +绘制东西。 零闪烁。

用法非常简单:您只需公开继承WTL::CDoubleBufferImpl<YourClass> ,并将其链接到ATL消息映射中。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM