微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

拖动窗口的左边框时无法消除抖动

截至2015年3月26日,问题解决了,看到这个页面底部一个很脏的伎俩。

截至2014年8月18日,部分解决:DWM是罪魁祸首(见最后的评论)。

我已经使用win32 API构build了自己的窗口样式。 在Windows XP和Windows 7下一切正常。但是,在Windows 8下发生了奇怪的事情:拖动窗口的左边缘导致右侧极端的抖动,而不应该移动。 看看这个 ,你会明白我的意思。

当我拖动右边框时,左侧不会按原样移动。 诚然,有一些闪烁,但这是可以接受的。 看到这个

什么导致FileSystemWatcher对象过时?

编译一个有限的库访问的程序

添加generics来形成

shell如何pipesubprocess?

使用xscreensaver编写屏幕保护程序的提示和技巧?

我用几个标志尝试了SetwindowPos()和(begin/End)DeferWindowPos ,但无济于事。 即使使用SWP_norEDRAW并阻止所有其他绘画也无济于事。 无论有没有CS_HREDRAW和CS_VREDRAW 。

当然,我正在使用双缓冲。 然而摆脱这种讨厌的抖动似乎是不可能的。 我也尝试了另一个驱动程序的英特尔HD 4000graphics引擎,再次无济于事。 我忽略了什么? 这是Windows 8的错误吗?

顺便说一句,当我打开“拖动时显示窗口内容”选项(在“高级系统设置”菜单中),所有其他应用程序显示相同的行为。

任何帮助将不胜感激。

干杯,爱德蒙。

PS:禁用“拖动时显示窗口内容”是没有select的,因为它是build立在我的应用程序的function。

编辑1:似乎d7samurai正在与同样的问题挣扎。

跟进:我已经尝试了很多东西来摆脱抖动,但没有任何帮助。 问题是W8根本就没有做它应该做的事情。 以SWP_norEDRAW标志为例。 正如所料,被移动的窗户边的重新粉刷被压制了,迄今为止这么好。 但是…(窗户的)另一边,这仍然是有效的,这个重新粉刷! 这不仅是完全不必要和无用的,而且是用抖动重新绘制的! 而且,绘画比W7和XP要慢两倍。 在这个问题上花了整整一周之后,我完全用W8完成了! 这真的是一个POC和负责这个烂摊子工作的人是精神错乱。 我真的希望W9能够做得更好。 阿门。

你不要这样:

看起来,上述exception并不仅限于W8。 当W7被设置为“最佳外观”或者至less“启用桌面组合”和“在窗口和button上使用视觉样式”时,W7也显示相同的行为。 然后我认为有可能根本不使用SetwindowPos函数,而是通过发送ShowWindow( hWnd,SW_MAXIMIZE )命令并拦截WM_GETMINMAXINFO消息来指定所需的大小和位置。 你猜怎么了? 我仍然有抖动。 唉!

接下来做什么? 是否有可能在较低/较深的层次(钩?)上截取绘画,以便以一种体面的方式重新绘制窗户?

更新日03-26-2015,一个非常肮脏的把戏:

find了! 我终于find了解决问题的办法。 但首先,让我解释发生了什么,以及为什么拖动伴随着抖动。 假设你想展开一个窗口的左边。 与扩大右侧相反,这是分两步完成的。 首先,将原始大小的窗口内容移到左边。 完成之后,内容扩大到新的右侧与前一个右侧重合的程度。 总之,它是一个“移动”,然后是“resize”的组合,这是什么导致丑陋的抖动。 拖动窗口顶部时会发生类似的情况。 在Windows 8.1或10中,没有什么可以对付它。 我也尝试了新的DWM函数( BufferedPaintinit , BeginBufferedPaint , EndBufferedPaint , BufferedPaintUnInit )遗憾,无济于事。 SetwindowPlacement()产生抖动。 显然,所有这些function导致相同的罪魁祸首resize。 然后我推断,当你创build一个新的窗口,并显示一个新的大小,它根本不抖动。 很明显,我会说。 所以反复创build一个新窗口,然后摧毁以前的窗口,可能是一个解决scheme,但这当然不是很有效率。 在玩这个想法的时候,我偶然发现,用新的/另一个尺寸制作一个隐藏的窗口,然后隐藏以前的窗口,也不会显示抖动。 这个过程比创build/销毁序列更有效率。 所以在我的程序开始时,我创build了两个窗口,第一个隐藏,第二个隐藏。 下面的代码片段应该更详细地解释无抖动resize的过程:

........ i = prm->hpi; // get current index h1 = prm->parent[i]; // get current handle flags = SWP_NOcopYBITS; flags |= SWP_NOSENDCHANGING; // if DWM tries to make a mess of it: // DWM enabled top border right border if( prm->parent[1] && ( rgn == TBE || rgn == LBE ) ) { i = i + 1 & 1; // get new index prm->hpi = i; // save new index h2 = prm->parent[i]; // get new handle prm->hParent = h2; // set as current one flags |= SWP_norEDRAW; // bypass message pump flags |= SWP_SHOWWINDOW; // make h2 visible SetwindowPos( h2,HWND_TOP,px,py,cx,cy,flags ); PaintParent( h2 ); // paint it Now DwmFlush(); // wait till finished ShowWindow( h1,SW_HIDE ); // make h1 invisible } // DWM disabled or dragging the right or bottom border: else SetwindowPos( h1,flags );

还有一件事:使用DwmFlush()确保新窗口的所有绘制完成,然后隐藏另一个窗口,否则会出现一些闪烁。 当然,上面的程序比普通程序慢一点。 在我的系统上(使用i5-3570K处理器)3..26ms,取决于窗口的大小及其内容。 但至less那可怕的抖动已经消失了。

我意识到这是一个非常肮脏的伎俩,所以如果有人知道一个整洁的解决scheme,请让我们知道。

NPTL在65528处限制最大线程数?

TCP,尽pipeKEEPALIVE挂起recv函数

Windows上的NSOperationQueue是否等价?

C ++读取和编辑位图图像的像素

你如何以编程方式从父级获取subprocess的堆栈跟踪?

它看起来像Windows 8.1及以上,你必须与DWM合作,而不是绕过它。

这意味着您必须通过DwmGetCompositionTimingInfo找出合成的时间DwmGetCompositionTimingInfo ,并确保您在适当的时候将渲染事件插入到队列中。 您也可能发现需要在WM_SIZING事件之后重新使无效和重新绘制窗口,甚至使用自己的计时器来绘制比WM_SIZING事件发送更频繁的窗口。 例如,如果DWM以50 fps的速度合成,但是每秒只能获得WM_Sizing事件,那么如果使用GetwindowPos自己的计时器,则可能比使用WM_SIZING更频繁地进行绘制。

您可能会发现,在绘画之后DwmFlush地使用DwmFlush也可能有助于减少这种抖动。

我找到了解决问题的办法。 请参阅原始消息的最新更新。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 [email protected] 举报,一经查实,本站将立刻删除。

相关推荐