双缓冲通用控件

发布于 2024-08-13 07:53:14 字数 392 浏览 6 评论 0原文

有没有办法对常用控件进行双缓冲?目前,当它们调整大小时,它们会闪烁。很多......

编辑:如果有帮助的话,它是一堆按钮控件和一些编辑控件,全部位于选项卡控件之上。 Tab 控件会自行重绘,然后按钮也会重绘自身。当按钮重画时,它们会闪烁。

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

Is there a way to double-buffer the common controls? Currently when they resize they flicker. A lot.....

EDIT: If it helps, it is a bunch of button controls and a few edit controls, all sitting on top of a tab control. The Tab control redraws itself, then the buttons redraw themselves. When the buttons redraw, they flicker.

EDIT2: Here's an example of the problem I'm having:
http://billy-oneal.com/Lobfuscator.exe

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(8

对你的占有欲 2024-08-20 07:53:14

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

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

#define WINVER 0x501 

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

更新

使用 WM_PRINTCLIENT 将客户区传输到 DC 上的位图并将所有客户区作为一个整体进行 blit 怎么样?

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

Look at using WS_EX_COMPOSITEDand WS_EX_TRANSPARENT styles. They provide doublebuffering, altough WM_PAINT will be called when the underlying bitmap is finished drawing, since it draws child controls from bottom to top, so you can paint only in your window procedure. I've used it in the past and work pretty well.

Set your top-level window (container) to extended style WS_EX_COMPOSITED and your child windows with WS_EX_TRANSPARENT. Also, remember to define:

#define WINVER 0x501 

See CreateWindowEx for information on the composited style. This also makes possible to do perpixel transparency on child windows.

UPDATE

What about usign WM_PRINTCLIENT to transfer the client area to a bitmap on a DC and blit all the client area as a whole?

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

早茶月光 2024-08-20 07:53:14

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

与比利非常相似,我遇到了切换选项卡时弹出的问题,其中放置在选项卡上的控件在显示和隐藏时会闪烁。作为参考,我广泛使用 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

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

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

问候。

I understand the topic is quite old, but this may be relevant to someone who's running into trouble with a flicker problem.

Very much like Billy, I have run into an issue that pops up when switching tabs, where controls that are placed on the tab flicker when being shown and hidden. For reference, I'm using ShowWindow function extensively to hide and show controls.

I have been fiddling with WS_EX_COMPOSITED for a few hours and it gave me very odd results. I'm also not resizing anything, the dialog is designed to run fullscreen and it adapts to the current desktop resolution.

This is the layout of my dialog, which I have created manually, calling the CreateWindowEx function for every control:

Main window
-- some controls
-- tab control
---- some more controls

Indent represents the parent-child relations. The tab control has WS_CHILD and WS_CLIPCHILDREN styles set on creation, all of the controls have WS_CHILD style set.

What in the end did the trick was the following

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

This bit is written in assembly (MASM32), but I'm sure you get the gist of it. Simply, get the EX_STYLE of your main window sometime during WM_INITDIALOG and add WS_EX_COMPOSITED to it.

In this singular case, this method works both on 32bit Windows XP SP3 and 64bit Windows 7 SP1. There was no need to add the WS_EX_COMPOSITED style to any of the tab's child controls (some of the static controls I use have WS_EX_TRANSPARENT set, but that's for other reasons) and at this time there is no apparent need to return non-zero on WM_ERASEBKGND message. I'm also not experiencing any performance problems on a moderately powerful C2D machine.

For reference, this is my Main

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

There's nothing special here, neither. I'm setting the "dialog control grey" as the background color and using the CS_*REDRAW styles, those appear not to affect this situation.
The "empty" dialog template I used to create the main windows is this

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

Hopefully this may save some time to people looking for answers. It's a tad long, but I wanted to detail it as much as possible.

Regards.

桃气十足 2024-08-20 07:53:14

拉里·奥斯特曼 (Larry Osterman) 最近在博客中讨论了这个主题;您可能会发现一些有趣的详细信息

Larry Osterman recently blogged about this subject; you might find some interesting details there.

沙与沫 2024-08-20 07:53:14

事实上,

不久前有人在我的一篇帖子中发布了这个问题的答案。看看:这里

,并一定要为他的出色表现而投票。

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

indeed,

someone posted an answer for this on one of my posts a while ago. Check it out: Here

and be sure to upvote him for being awesome.

The code is C#, hopefully there is a simple translation.

萌无敌 2024-08-20 07:53:14

在不确切知道您在做什么的情况下,我假设您正在使用 MFC 或 Win32 C 来实现此目的。

您可能想根据 WM_SIZE 消息调整大小。我不确定你在哪里调整控件的大小,但我认为你是在调整控件大小时这样做的,这就是它导致闪烁的原因。

另外,我在想但我不知道,您可能可以使用 SetWindowPos 函数,并且对于 uFlags,可以使用 SWP_NOREDRAW。尽管我不确定这对于通用控件有多大作用。

Without knowing exactly what you're doing, I assume you're using either MFC or Win32 C for this.

You probably want to do the resize on WM_SIZE message. I'm not sure where you're resizing the controls, but I think you're doing it while it's being resized, which is why it's causing the flicker.

Also, I'm thinking but I don't know, you could probably use the SetWindowPos function, and for the uFlags, have SWP_NOREDRAW. Though I'm not sure how great this would work for common controls.

眼眸里的快感 2024-08-20 07:53:14

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

我记得几年前在 Herbert Schildt 的著作《Windows 98 编程从头开始》中读到过该技术。这样,当您将内存 dc 传输到实际 dc 时,所有重绘都会更快。但最大的问题是您要使用多大的内存 DC!但他展示了如何做到这一点。奥斯本·麦格劳·希尔 (Osborne McGraw Hill) 出版的该书中的所有章节都有代码下载。

希望这有帮助,
此致,
汤姆.

You can create a memory device context, MemDC at the very start. Draw everything into the MemDC, then when the window recieves a WM_PAINT message or is invalidated, copy the MemDC to the real DC by bit blitting.

I remember reading up the technique by Herbert Schildt in his book a few years back (Windows 98 Programming from the Ground Up). In that way, all the redrawing is faster as you blit the memory dc to the real dc. But the one big gotcha, was how big the memory dc you want to use! But he showed how to do it. There is a code download for all of the chapters in that book published by Osborne McGraw Hill.

Hope this helps,
Best regards,
Tom.

澜川若宁 2024-08-20 07:53:14

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

You're not using WS_EX_TRANSPARENT, are you? That will cause underlying windows to be painted before the controls, and when the bottom window erases you get flicker.

热情消退 2024-08-20 07:53:14

为此,我们使用 WTL::CDoubleBufferImpl mix-in。我们甚至用 GDI+ 绘制东西。零闪烁。

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

We use WTL::CDoubleBufferImpl mix-in for that purpose. We even draw stuff with GDI+ over. Zero flickering.

Usage is pretty simple: you just public-ly inherit from WTL::CDoubleBufferImpl<YourClass>, and chain it in the ATL message map.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文