在 .NET WInForms 中,什么可能会导致 64 位 Vista 上出现重画问题,但不会出现 32 位重画问题?

发布于 2024-07-09 23:11:52 字数 622 浏览 7 评论 0原文

当针对 Any Cpu 进行编译以及编译至 x86 时,会发生这种情况。 GUI 的部分不会重绘,除非调整大小,例如,如果主窗体最大化,则某些控件不会随之调整大小,而其他部分则不会重绘并显示之前的内容。

这在 32 位机器(XP 和 Vista)上工作正常,但在 64 位 Vista(没有 x64 XP 来测试)上,重绘无法正常工作。

有人知道从哪里开始追踪这个问题吗?

编辑:这种情况发生在两台独立的机器上,至少我当前使用的机器具有 NVidia 的最新驱动程序。

Edit2:在我的 64 位计算机上运行 32 位 XP 虚拟机,并且应用程序没有在 VM 中出现重绘问题

Edit3:这可能是驱动程序问题,但我们不知道驱动程序是否或何时会修复问题。 一位同事说,家里使用 ATI 卡的问题比使用 NVidia 的要少,但过去几个月我几乎每月都会更新我的视频驱动程序,但问题仍然没有解决,所以我们不能只是发布我们的产品并告诉我们的客户,有一天驱动程序制造商可能会抽出时间来解决这个问题。

有谁知道应该避免哪些事情? 我们编译为 x86,并且所有组件都是 x86。 我似乎无法使用测试项目中的任何组件重现此问题,并且我没有听到其他人在大多数组件论坛上报告这些问题,因此很可能这是我们正在做的事情。

This happens when compiling for Any Cpu as well as compiling to x86. Sections of the GUI doesn't redraw unless it's resized, for instance if the main form is maximized some of the controls don't resize with it, and others have sections that don't redraw and displays the what was previously there.

This works fine on 32-bit machines, both XP and Vista, but on 64-bit Vista (don't have x64 XP to test with) the redrawing just isn't working properly.

Anyone have any ideas on where to start tracking this down?

Edit: This occurs on 2 separate machines, and at least the one I'm currently on has the latest drivers from NVidia.

Edit2: Running a 32-bit XP virtual machine on my 64-bit machine and the application doesn't exhibit the redrawing issue in the VM

Edit3: It may be a driver issue, but we don't know if or when drivers will fix the issue. A co-worker says there's fewer issues with an ATI card at home than with NVidia, but I've been updating my video drivers pretty much monthly for the past few months and it's still not resolved, so we can't just release our product and just tell our customers that some day the driver manufacturers may get around to fixing this.

Does anyone have any insight on what things to try to avoid? We're compiling as x86 and all our components are x86. I can't seem to reproduce this issue with any of the components in test projects, and I haven't heard anyone else report these issues on most of the the component forums, so it is fairly likely that it's something we're doing.

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

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

发布评论

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

评论(8

眼中杀气 2024-07-16 23:11:52

这听起来非常像 这个问题。

在 Windows 上调整窗口大小时,您通常会得到一个链,其中每个窗口接收 WM_SIZE 消息,然后对其子窗口调用 MoveWindow() (或类似),而子窗口又接收 WM_SIZE 消息。代码>WM_SIZE等等。 我确信 .NET 在幕后也做了同样的事情。

在 x64 上,Windows 限制了这种嵌套的深度,并且在某个点(12-15 个嵌套窗口)之后,它将不再发送 WM_SIZE 消息。 x86 上似乎不存在此限制。 此限制会影响在 x64 版本的 Windows 上运行的 x86 和 x64 代码。

这让我们困扰了很长时间,因为不同的 x64 安装会显示不同的症状。 上面的 MSDN 博客文章有一些可能的解决方法 - 我们最终使用辅助线程来异步调整窗口大小,这相当巧妙地解决了问题。

That sounds horribly like this problem.

When resizing windows on Windows you typically get a chain where each window receives a WM_SIZE message and then calls MoveWindow() (or similar) on its children which in turn receive a WM_SIZE and so on. I'm sure that .NET does the same thing under the covers.

On x64, Windows limits the depth of this nesting, and after a certain point (12-15 nested windows) it will just not send the WM_SIZE messages anymore. This limitation does not appear to exist on x86. This limitation affects both x86 and x64 code running on x64 versions of Windows.

This foxed us for ages, as different x64 installs would show different symptoms. The MSDN blog posting above has some possible workarounds - we ended up using a secondary thread to do the window sizes asynchronously, this solved the problem fairly neatly.

吻安 2024-07-16 23:11:52

如果您使用的是 Windows 窗体,则可能与 Windows 64 位上的嵌套限制问题有关。

详细信息请参见:http://www.feedghost.com/Blogs/BlogEntry.aspx ?EntryId=17829

总之...

来自 MS 源,在 Control.SetBoundsCore 中:

SafeNativeMethods.SetWindowPos(new HandleRef(window, Handle), NativeMethods.NullHandleRef, x, y, width, height, flags);

// NOTE: SetWindowPos causes a WM_WINDOWPOSCHANGED which is processed
// synchonously so we effectively end up in UpdateBounds immediately following
// SetWindowPos.
//
//UpdateBounds(x, y, width, height);

以及来自 MSDN:

http://social.msdn.microsoft.com/forums/en-US/windowsuidevelopment/thread/25181bd5-394d-4b94- a6ef-06e3e4287527/

“一项小调查表明 Windows 停止发送 WM_SIZE
当它达到某个特定的嵌套时
等级。 换句话说,它不会发送
WM_SIZE 到您的子窗口,如果您
处理时尝试调整它们的大小
父级中的 WM_SIZE。 取决于
关于用户内容/更新/服务
包装最大嵌套级别为
它可能会停止传播 WM_SIZE
从 15 到 31 不等,甚至更多
更高(实际上无法到达)
最新的 XP 32bit/sp2。

但在 XP x64 下它仍然太少了,而且仍然有一些类似的丑陋的东西
发生在某些情况下的其他消息
Vista 的构建。

所以这肯定是一个 Windows 错误。”

您有两个选择:要么减少控件层次结构的深度(更理想的解决方案),要么从您使用的每个系统控件中派生“固定”控件,如下所示:

public class FixedPanel : Panel
{
  protected override void SetBoundsCore( int x, int y, int width, int height, BoundsSpecified specified )
  {
    base.SetBoundsCore( x, y, width, height, specified );

    if( specified != BoundsSpecified.None )
    {
      if( ( specified & BoundsSpecified.X ) == BoundsSpecified.None )
      {
        x = Left;
      }
      if( ( specified & BoundsSpecified.Y ) == BoundsSpecified.None )
      {
        y = Top;
      }
      if( ( specified & BoundsSpecified.Width ) == BoundsSpecified.None )
      {
        width = Width;
      }
      if( ( specified & BoundsSpecified.Height ) == BoundsSpecified.None )
      {
        height = Height;
      }
    }

    if( x != Left || y != Top || width != Width || height != Height )
    {
      UpdateBounds( x, y, width, height );
    }
  }
}

If you're using Windows Forms, it could be to do with nesting limitation issues on Windows 64-bit.

Details here: http://www.feedghost.com/Blogs/BlogEntry.aspx?EntryId=17829

In summary...

From the MS source, in Control.SetBoundsCore:

SafeNativeMethods.SetWindowPos(new HandleRef(window, Handle), NativeMethods.NullHandleRef, x, y, width, height, flags);

// NOTE: SetWindowPos causes a WM_WINDOWPOSCHANGED which is processed
// synchonously so we effectively end up in UpdateBounds immediately following
// SetWindowPos.
//
//UpdateBounds(x, y, width, height);

And from MSDN:

http://social.msdn.microsoft.com/forums/en-US/windowsuidevelopment/thread/25181bd5-394d-4b94-a6ef-06e3e4287527/

"A little investigation showed that Windows stops sending WM_SIZE
when it reaches some certain nesting
level. In other words, it won't send
WM_SIZE to your child windows if you
try to resize them when you process
WM_SIZE in the parent ones. Depending
on the USER stuff/updates/serivice
packs the maximum nesting level at
which it stops propagating WM_SIZE may
vary from 15 to 31 and even much
higher (effectively unreachable) under
latest XP 32bit/sp2.

But it still too little under XP x64 and still some similar ugly things
happen to other messages under some
builds of Vista.

So it is certainly a Windows bug."

You have two choices: either reduce the depth of your control hierarchy (the more ideal solution), or else derive "fixed" controls from each of the system ones that you use, as follows:

public class FixedPanel : Panel
{
  protected override void SetBoundsCore( int x, int y, int width, int height, BoundsSpecified specified )
  {
    base.SetBoundsCore( x, y, width, height, specified );

    if( specified != BoundsSpecified.None )
    {
      if( ( specified & BoundsSpecified.X ) == BoundsSpecified.None )
      {
        x = Left;
      }
      if( ( specified & BoundsSpecified.Y ) == BoundsSpecified.None )
      {
        y = Top;
      }
      if( ( specified & BoundsSpecified.Width ) == BoundsSpecified.None )
      {
        width = Width;
      }
      if( ( specified & BoundsSpecified.Height ) == BoundsSpecified.None )
      {
        height = Height;
      }
    }

    if( x != Left || y != Top || width != Width || height != Height )
    {
      UpdateBounds( x, y, width, height );
    }
  }
}
蓝海似她心 2024-07-16 23:11:52

我认为此问题最可能的原因是应用程序中的重绘问题。 64 位上可能存在细微的 Windows 消息排序差异,从而在您的代码中暴露了此问题。

您可以通过执行以下操作来进行实验。

  1. 向您的应用程序添加一个计时器。
  2. 在事件处理程序调用 flakyControl.Update() 中,

我将计时器设置为 5 秒之类的长值。 然后在 Win64 上运行该应用程序,看看是否可以解决问题。 如果是这样,那么最可能的原因是您的控件之一没有正确发出其已失效的信号。

我将从应用程序中的任何自定义控件开始。 系统地向代码中的每个重写方法和事件处理程序添加 Update 调用。 最终你会找到解决问题的方法,然后你就会知道错误到底在哪里。

I think the most likely cause of this problem is a redraw issue in your application. It's possible that there is a subtle windows message ordering difference on 64 bit that is exposing this issue in your code.

You can experiment with this by doing the following.

  1. Add a timer to your application.
  2. In the event handler call flakyControl.Update()

I would set the timer to something long like 5 seconds. Then run the application on Win64 and see if that fixes the issue. If so then the most likely cause is one of your controls is not properly signaling that it's been invalidated.

I would start with any custom controls in the application. Systematically add an Update call to every overriden method and event handler in the code. Eventually you'll find the one that fixes the issue and then you'll know where the bug actually is.

千里故人稀 2024-07-16 23:11:52

如果您使用 MSDN 上描述的 BeginInvoke() 解决方案 blog 确保禁用覆盖 OnSizeChanged() 的控件子级的停靠。 我有 Dock = DockStyle.Fill,并且必须更改为 DockStyle.None 才能使修复工作。

If you use the BeginInvoke() solution described on the MSDN blog make sure to disable docking of the children of the control that overrides OnSizeChanged(). I had Dock = DockStyle.Fill and had to change to DockStyle.None for the fix to work.

土豪我们做朋友吧 2024-07-16 23:11:52

对我来说听起来像是显示驱动程序问题...

尝试更新到最新的驱动程序,看看是否可以解决问题? 64/32 位的差异可能是转移注意力的......

Sounds like a display-driver problem to me...

Try updating to the latest drivers and see if that fixes the problem? The 64/32 bit difference is probably a red-herring...

亣腦蒛氧 2024-07-16 23:11:52

我同意戈登的观点。 我见过这样的问题:全新的 64 位机器出现显示问题,而程序在 32 位下看起来很好,但在 64 位机器上会出现奇怪的问题。 更新到最新/推荐的驱动程序几乎总能解决问题。

I would agree with Gordon. I've seen issues where brand new 64-bit machines had display issues with programs that looked fine under 32-bit, but would exhibit odd issues on 64-bit machines. Updating to the latest/recommended drivers almost always fixed the issue.

浅唱ヾ落雨殇 2024-07-16 23:11:52

事实上,您可以在虚拟操作系统上运行该程序而不会出现任何问题,这表明这是一个驱动程序问题,因为(至少在 VirtualPC 中)显卡是模拟的。 这意味着显卡通常处理的一些事情现在由 CPU 完成,因此不与显卡驱动程序交互。 请注意,我不是虚拟化方面的专家,我认为虚拟化层可能会以其他方式影响该问题。

The fact that you can run the program on a virtual OS without issues suggests that it is a driver issue, because (at least in VirtualPC) the graphics card is emulated. This means that some things which the graphics card would normally handle is now done by the CPU, and thus not interacting with the graphics driver. Mind you that I'm not an expert on virtualization and I suppose the virtualization layer could affect the issue in other ways.

清晰传感 2024-07-16 23:11:52

我相信这与树中嵌套的 HWND 的数量有关。 我不知道具体细节,但 64 位的嵌套 HWND 有一些限制。 当我看到这种情况发生时,我会通过从完整的 vista basic(或 aero)主题退回到 windows classic 来解决它。 此时问题就消失了。

尝试切换到经典,如果可以解决问题,看看是否可以减少嵌套 HWND 的数量。

I believe this is related to the number nested HWND's in the tree. I don't know the specific details, but there were some restrictions placed on nested HWNDs with 64bit. The times I've seen it occur, I work around it by dropping back from the full vista basic (or aero) theme, to windows classic. At this point the issues go away.

Try switching to classic, and if that resolves it, see if you can reduce the number of nested HWNDs.

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