views:

1149

answers:

8

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.

A: 

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...

Gordon Carpenter-Thompson
This is on 2 separate 64-bit machines with different video cards. Drivers are up to date.
Davy8
Different brands or different models?
Gordon Carpenter-Thompson
Not sure what the other machine is as it's not mine, but it's a Dell machine that's 1-3 years old, mine is a custom built machine GeForce 8400 GS and the latest drivers as of 6 days ago (just built it last week)
Davy8
A: 

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.

steve.platz
Even with new drivers from January 2009 from NVidia, still same issues
Davy8
A: 

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.

Morten Christiansen
+1  A: 

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.

dhopton
+1  A: 

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.

JaredPar
+7  A: 

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.

Bids
That did the trick, thanks a bunch!
Davy8
+2  A: 

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 );
    }
  }
}
stusmith
Good explaination and answer, but the link Bids gave provided a simpler solution by just doing the resizing asynchronously.
Davy8
No worries, just thought I'd include my alternative solution for the record.
stusmith
+1  A: 

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.

David Lynch