在.NET WInForms中,64位vista而不是32位vista上,什么会导致重绘问题?
在为任何Cpu编译以及编译到x86时都会发生这种情况。GUI的部分不会重新绘制,除非调整大小,例如,如果主窗体最大化,则某些控件不会随之调整大小,而其他控件的部分不会重新绘制并显示以前的内容 这在32位机器上运行良好,包括XP和Vista,但在64位Vista(没有x64 XP可供测试)上,重画无法正常工作 有人知道从哪里开始追踪吗 编辑:这发生在两台不同的机器上,至少我当前使用的一台机器具有来自NVidia的最新驱动程序 Edit2:在我的64位计算机上运行32位XP虚拟机,并且应用程序在VM中没有显示重绘问题 Edit3:这可能是一个驱动程序问题,但我们不知道驱动程序是否或何时会修复该问题。一位同事说,与NVidia相比,ATI卡在家中出现的问题更少,但在过去几个月里,我几乎每月都在更新视频驱动程序,但问题仍然没有得到解决,因此我们不能只是发布产品,然后告诉客户,有一天驱动程序制造商可能会着手解决这个问题在.NET WInForms中,64位vista而不是32位vista上,什么会导致重绘问题?,winforms,windows-vista,64-bit,redraw,Winforms,Windows Vista,64 Bit,Redraw,在为任何Cpu编译以及编译到x86时都会发生这种情况。GUI的部分不会重新绘制,除非调整大小,例如,如果主窗体最大化,则某些控件不会随之调整大小,而其他控件的部分不会重新绘制并显示以前的内容 这在32位机器上运行良好,包括XP和Vista,但在64位Vista(没有x64 XP可供测试)上,重画无法正常工作 有人知道从哪里开始追踪吗 编辑:这发生在两台不同的机器上,至少我当前使用的一台机器具有来自NVidia的最新驱动程序 Edit2:在我的64位计算机上运行32位XP虚拟机,并且应用程序在VM
有人知道应该避免哪些事情吗?我们编译为x86,所有组件都是x86。我似乎无法在测试项目中的任何组件上重现这个问题,而且我还并没有听到其他任何人在大多数组件论坛上报告这些问题,所以很可能是我们正在做的事情。听起来像是显示驱动程序的问题
尝试更新到最新的驱动程序,看看这是否解决了问题?64/32位的差异可能是一种误导…我同意戈登的观点。我曾经看到过这样的问题,即全新的64位机器在32位以下的程序中出现显示问题,但在64位机器上会出现奇怪的问题。更新到最新/推荐的驱动程序几乎总能解决这个问题。您可以在虚拟操作系统上运行程序而不会出现问题,这表明这是一个驱动程序问题,因为(至少在VirtualPC中)图形卡是模拟的。这意味着图形卡通常处理的某些事情现在由CPU完成,因此不会与图形驱动程序交互。请注意,我不是虚拟化方面的专家,我认为虚拟化层可能会以其他方式影响问题。我认为这与树中嵌套的HWND的数量有关。我不知道具体细节,但对64位的嵌套HWND有一些限制。在我看到它出现的时候,我通过从完整的vista basic(或aero)主题返回到windows classic来解决它。在这一点上,问题消失了
尝试切换到classic,如果可以解决问题,请查看是否可以减少嵌套HWND的数量。我认为此问题最可能的原因是应用程序中的重画问题。在64位上可能存在细微的windows消息顺序差异,从而在代码中暴露了此问题 您可以通过执行以下操作来进行试验
WM\u SIZE
消息,然后在其子窗口上调用MoveWindow()
(或类似),然后子窗口又接收一条WM\u SIZE
,依此类推。我确信.NET在幕后也做同样的事情
在x64上,Windows限制了嵌套的深度,在某个点(12-15个嵌套窗口)之后,它将不再发送WM_SIZE
消息。x86上似乎不存在此限制。此限制影响在x64版本的Windows上运行的x86和x64代码
这让我们迷惑了很久,因为不同的x64安装会显示不同的症状。上面的MSDN博客文章有一些可能的解决方法-我们最终使用了一个辅助线程来异步处理窗口大小,这相当巧妙地解决了问题。如果您使用的是Windows窗体,则可能与Windows 64位上的嵌套限制问题有关 详情如下: 总之 从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:
“一项小调查显示Windows停止发送WM_大小的文件
当它到达某个特定的巢穴时
级别。换句话说,它不会发送
WM_大小到您的子窗口,如果您
处理时尝试调整它们的大小
父项中的WM_大小。取决于
关于用户资料/更新/服务
在以下位置打包最大嵌套级别:
它停止传播的WM_大小可能会
从15到31不等,甚至更多
在以下条件下更高(实际上无法达到)
最新XP 32位/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 );
}
}
}
如果使用MSDN中描述的BeginInvoke()解决方案,请确保禁用ch的对接