草庐IT

windows - 窗口向左无闪烁扩展(调整大小)

coder 2024-06-14 原文

假设您有一个可以向左展开以显示其他控件的表单:

折叠:

展开:

在 Delphi 中实现这一点的最简单方法是使用 alRight 作为所有控件的主要 anchor (而不是 alLeft),然后简单地调整宽度和 X 坐标的形式。您可以单独设置 WidthLeft 属性,也可以使用同时设置它们的函数,例如

if FCollapsed then
  SetWindowPos(Handle, 0, Left - Width, Top, 2 * Width, Height, 0)
else
  SetWindowPos(Handle, 0, Left + Width div 2, Top, Width div 2, Height, 0)

问题 是在展开或折叠时窗体始终可见的部分(在本例中为按钮)有相当明显的闪烁。自己试试吧!

操作系统可以将窗体的大小调整到左边而根本没有任何闪烁——只需使用鼠标捕获窗体的左边缘,然后向左或向右拖动鼠标——但我做不到在 Windows API 中找到公开这种调整大小的任何函数。

我尝试使用几个不同的 Windows API 函数来调整窗体的大小和位置,尝试了它们的各种参数(例如,SWP_* 标志),尝试了 LockWindowUpdate , WM_SETREDRAW, TForm.DoubleBuffered 等无济于事。我还研究了使用 WM_SYSCOMMAND SC_SIZE 方法的可能性。

我还不确定问题出在操作系统级别还是 VCL 级别。

有什么建议吗?

编辑:看到这个问题获得了非常接近的选票,我感到非常惊讶。让我试着澄清一下:

  1. 创建一个新的 VCL 表单应用程序。

  2. 在主窗体的右侧添加几个按钮,在左侧添加一个备忘录。在所有 控件上将Anchors 设置为[alTop, alRight]。在按钮的 OnClick 处理程序上,添加以下代码:

    if FCollapsed then
      SetWindowPos(Handle, 0, Left - Width, Top, 2 * Width, Height, 0)
    else
      SetWindowPos(Handle, 0, Left + Width div 2, Top, Width div 2, Height, 0);
    
    FCollapsed := not FCollapsed;
    

    其中 FCollapsed 是表单的私有(private) bool 字段(初始化为 false)。

  3. 现在,重复单击按钮。 (或者给其中一个键盘焦点并按住 Enter 键几秒钟。)您可能会注意到显示器上带有按钮的区域不会显示完美的静止图像,但会闪烁.此外,您实际上可能会在实际按钮列的左侧看到按钮的“重影”。

我无法使用屏幕捕捉捕捉到这一毫秒的闪烁,所以我使用数码相机来记录我的屏幕:

https://privat.rejbrand.se/VCLFormExpandFlicker.mp4

在这个视频片段中,显然按钮列不是屏幕上的静态图像;取而代之的是,每次调整表单大小时,该区域都会有几毫秒的变化。同样明显的是,左侧有一列“幽灵”按钮。

我的问题是是否有任何相当简单的方法来消除这些视觉人工制品(至少对我来说是非常明显的,即使您展开/折叠表单一次)。

在我工作的 Windows 10/Delphi 10.1 计算机上,当我使用鼠标拖动窗体的最左边缘时,窗体以完美的方式调整大小:窗体未受影响的客户区在显示器上完全静止。但是,在我家里的 Windows 7/Delphi 2009 PC 上,我确实看到当我这样做时有很多重新定位。

最佳答案

我可以提供一些见解,说明为什么您会看到另一半 UI 的重影图像,并可能提供阻止它的方法。幻影表示有人在复制您的客户区像素(并将它们复制到错误的位置,总是在您的窗口中左对齐),然后您才有机会使用正确的像素重新绘制它们。

这些重影像素可能有两个不同的、重叠的来源。

第一层适用于所有 Windows 操作系统,来自 BitBlt里面SetWindowPos .你可以去掉那个BitBlt在几个方面。您可以创建自己的自定义实现 WM_NCCALCSIZE告诉 Windows 什么都不做 blit(或者在它自己的顶部 blit 一个像素),或者你可以拦截 WM_WINDOWPOSCHANGING (首先将其传递给 DefWindowProc )并设置 WINDOWPOS.flags |= SWP_NOCOPYBITS ,这会禁用 BitBlt在对 SetWindowPos() 的内部调用中Windows 在调整窗口大小时所做的。这与跳过 BitBlt 的最终效果相同。 .

然而,Windows 8/10 aero 添加了另一个更麻烦的层。应用程序现在绘制到一个屏幕外缓冲区,然后由新的、邪恶的 DWM.exe 窗口管理器合成。事实证明 DWM.exe 有时会自己做 BitBlt在旧版 XP/Vista/7 代码已经完成的操作之上键入操作。阻止 DWM 执行它的 blit 要困难得多;到目前为止,我还没有看到任何完整的解决方案。

突破XP/Vista/7层,至少提升8/10层性能的示例代码,请看:

How to smooth ugly jitter/flicker/jumping when resizing windows, especially dragging left/top border (Win 7-10; bg, bitblt and DWM)?

因为你有多个子窗口,情况就更复杂了。 BitBlt我上面提到的类型操作发生在整个顶级窗口上(它们将窗口视为一组像素,而不管下面有多少个窗口,也不管 CLIPCHILDREN )。但是您需要让窗口自动移动,以便在下一次重绘时它们都能正确定位。你可能会发现 BeginDeferWindowPos/DeferWindowPos/EndDeferWindowPos对此很有用(但只有在上述技巧不起作用时才去那里)。

关于windows - 窗口向左无闪烁扩展(调整大小),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48825519/

有关windows - 窗口向左无闪烁扩展(调整大小)的更多相关文章

  1. ruby-on-rails - 在 Rails 中将文件大小字符串转换为等效千字节 - 2

    我的目标是转换表单输入,例如“100兆字节”或“1GB”,并将其转换为我可以存储在数据库中的文件大小(以千字节为单位)。目前,我有这个:defquota_convert@regex=/([0-9]+)(.*)s/@sizes=%w{kilobytemegabytegigabyte}m=self.quota.match(@regex)if@sizes.include?m[2]eval("self.quota=#{m[1]}.#{m[2]}")endend这有效,但前提是输入是倍数(“gigabytes”,而不是“gigabyte”)并且由于使用了eval看起来疯狂不安全。所以,功能正常,

  2. ruby - 在 Ruby 程序执行时阻止 Windows 7 PC 进入休眠状态 - 2

    我需要在客户计算机上运行Ruby应用程序。通常需要几天才能完成(复制大备份文件)。问题是如果启用sleep,它会中断应用程序。否则,计算机将持续运行数周,直到我下次访问为止。有什么方法可以防止执行期间休眠并让Windows在执行后休眠吗?欢迎任何疯狂的想法;-) 最佳答案 Here建议使用SetThreadExecutionStateWinAPI函数,使应用程序能够通知系统它正在使用中,从而防止系统在应用程序运行时进入休眠状态或关闭显示。像这样的东西:require'Win32API'ES_AWAYMODE_REQUIRED=0x0

  3. ruby - 使用 C 扩展开发 ruby​​gem 时,如何使用 Rspec 在本地进行测试? - 2

    我正在编写一个包含C扩展的gem。通常当我写一个gem时,我会遵循TDD的过程,我会写一个失败的规范,然后处理代码直到它通过,等等......在“ext/mygem/mygem.c”中我的C扩展和在gemspec的“扩展”中配置的有效extconf.rb,如何运行我的规范并仍然加载我的C扩展?当我更改C代码时,我需要采取哪些步骤来重新编译代码?这可能是个愚蠢的问题,但是从我的gem的开发源代码树中输入“bundleinstall”不会构建任何native扩展。当我手动运行rubyext/mygem/extconf.rb时,我确实得到了一个Makefile(在整个项目的根目录中),然后当

  4. ruby - 在 Windows 机器上使用 Ruby 进行开发是否会适得其反? - 2

    这似乎非常适得其反,因为太多的gem会在window上破裂。我一直在处理很多mysql和ruby​​-mysqlgem问题(gem本身发生段错误,一个名为UnixSocket的类显然在Windows机器上不能正常工作,等等)。我只是在浪费时间吗?我应该转向不同的脚本语言吗? 最佳答案 我在Windows上使用Ruby的经验很少,但是当我开始使用Ruby时,我是在Windows上,我的总体印象是它不是Windows原生系统。因此,在主要使用Windows多年之后,开始使用Ruby促使我切换回原来的系统Unix,这次是Linux。Rub

  5. c - mkmf 在编译 C 扩展时忽略子文件夹中的文件 - 2

    我想这样组织C源代码:+/||___+ext||||___+native_extension||||___+lib||||||___(Sourcefilesarekeptinhere-maycontainsub-folders)||||___native_extension.c||___native_extension.h||___extconf.rb||___+lib||||___(Rubysourcecode)||___Rakefile我无法使此设置与mkmf一起正常工作。native_extension/lib中的文件(包含在native_extension.c中)将被完全忽略。

  6. Vscode+Cmake配置并运行opencv环境(Windows和Ubuntu大同小异) - 2

    之前在培训新生的时候,windows环境下配置opencv环境一直教的都是网上主流的vsstudio配置属性表,但是这个似乎对新生来说难度略高(虽然个人觉得完全是他们自己的问题),加之暑假之后对cmake实在是爱不释手,且这样配置确实十分简单(其实都不需要配置),故斗胆妄言vscode下配置CV之法。其实极为简单,图比较多所以很长。如果你看此文还配不好,你应该思考一下是不是自己的问题。闲话少说,直接开始。0.CMkae简介有的人到大二了都不知道cmake是什么,我不说是谁。CMake是一个开源免费并且跨平台的构建工具,可以用简单的语句来描述所有平台的编译过程。它能够根据当前所在平台输出对应的m

  7. 深度学习部署:Windows安装pycocotools报错解决方法 - 2

    深度学习部署:Windows安装pycocotools报错解决方法1.pycocotools库的简介2.pycocotools安装的坑3.解决办法更多Ai资讯:公主号AiCharm本系列是作者在跑一些深度学习实例时,遇到的各种各样的问题及解决办法,希望能够帮助到大家。ERROR:Commanderroredoutwithexitstatus1:'D:\Anaconda3\python.exe'-u-c'importsys,setuptools,tokenize;sys.argv[0]='"'"'C:\\Users\\46653\\AppData\\Local\\Temp\\pip-instal

  8. HBase Region 简介和建议数量&大小 - 2

    Region是HBase数据管理的基本单位,region有一点像关系型数据的分区。region中存储这用户的真实数据,而为了管理这些数据,HBase使用了RegionSever来管理region。Region的结构hbaseregion的大小设置默认情况下,每个Table起初只有一个Region,随着数据的不断写入,Region会自动进行拆分。刚拆分时,两个子Region都位于当前的RegionServer,但处于负载均衡的考虑,HMaster有可能会将某个Region转移给其他的RegionServer。RegionSplit时机:当1个region中的某个Store下所有StoreFile

  9. ruby-on-rails - Ruby 中意外的大小写行为 - 2

    我在一段非常简单的代码(如我所想)中得到了一个错误的值:org=4caseorgwhenorg=4val='H'endputsval=>nil请不要生气,我希望我错过了一些非常明显的东西,但我真的想不通。谢谢。 最佳答案 这是典型的Ruby错误。case有两种被调用的方法,一种是你传递一个东西作为分支的基础,另一种是你不传递的东西。如果您确实在case中指定了一个表达式语句然后评估所有其他条件并与===进行比较.在这种情况下org评估为false和org===false显然不是真的。所有其他情况也是如此,它们要么是真的,要么是假的。

  10. ruby - (Ruby || Python) 窗口管理器 - 2

    我想用这两种语言中的任何一种(最好是ruby​​)制作一个窗口管理器。老实说,除了我需要加载某种X模块外,我不知道从哪里开始。因此,如果有人有线索,如果您能指出正确的方向,那就太好了。谢谢 最佳答案 XCB,X的下一代API使用XML格式定义X协议(protocol),并使用脚本生成特定语言绑定(bind)。它在概念上与SWIG类似,只是它描述的不是CAPI,而是X协议(protocol)。目前,C和Python存在绑定(bind)。理论上,Ruby端口只是编写一个从XML协议(protocol)定义语言到Ruby的翻译器的问题。生

随机推荐