wxWindow.SetClientSize doesn't appear to work on Windows (?)

We're doing some dynamic resizing and positioning of controls in our wx app. We were using wxWindow.SetPosition and wxWindow.SetClientSize, and this worked fine on OS X. But when we tested on Windows, we found that wx.SetClientSize has no effect whatsoever, as far as we can tell. The controls stubbornly stayed their original sizes.

Changing that call to wx.SetSize worked fine on both platforms (on OS X, the behavior appears to be identical to .SetClientSize for all the window types we've tested, which admittedly isn't very many).

So we have a work-around, but I'd like to understand what's going on here. Why would SetClientSize be ignored under Windows? And what really is the difference between these two? The docs say:

void SetSize (int width, int height)
    Sets the size of the window in pixels.

void SetClientSize (int width, int height)
    This sets the size of the window client area in pixels.

For a frame, I think I understand the difference; the client area is the content of the window, excluding the titlebar and window borders and such, whereas the size would include those things.

For a control (button, ListCtrl, TextCtrl, etc.), is there ever a difference? Would Size allow room for a shadow or focus ring, and ClientSize not? This doesn't appear to be the case in my testing, but I'd like a more definite answer. And is there any good reason SetClientSize should be ignored under Windows?

Thanks,
- Joe

After sending this, I noticed SetPosition in the wxPython docs. That also appears to work.

Still curious about SetClientSize, though.

Also, there is one other weird effect we're seeing, only on Windows. When the window first appears, we (dynamically) reposition and resize a ListCtrl and a StaticText, so that the latter appears just below the former. We also do the same thing whenever the window is resized by the user. But initially, the static text appears actually drawn *on top of* the listbox. Only after resizing the window manually does it appear where it belongs. I'm pretty sure it's not a logic flaw in my code, since the same code works fine on OS X. Any idea what to look for here?

Thanks,
- Joe

Joe Strout wrote:

Also, there is one other weird effect we're seeing, only on Windows. When the window first appears, we (dynamically) reposition and resize a ListCtrl and a StaticText, so that the latter appears just below the former. We also do the same thing whenever the window is resized by the user. But initially, the static text appears actually drawn *on top of* the listbox. Only after resizing the window manually does it appear where it belongs. I'm pretty sure it's not a logic flaw in my code, since the same code works fine on OS X. Any idea what to look for here?

The different platforms sometimes do things in different order, which is probably what you are seeing -- also, OS-X does double buffering, so you may be getting the same effect in the offscreen buffer, but it's not blitted to the screen 'till later, so you don't see it.

Have you tried wx.Window.Freeze() before you show it, and Thaw() after?

-Chris

···

--
Christopher Barker, Ph.D.
Oceanographer

Emergency Response Division
NOAA/NOS/OR&R (206) 526-6959 voice
7600 Sand Point Way NE (206) 526-6329 fax
Seattle, WA 98115 (206) 526-6317 main reception

Chris.Barker@noaa.gov

Joe Strout wrote:

We're doing some dynamic resizing and positioning of controls in our wx app. We were using wxWindow.SetPosition and wxWindow.SetClientSize, and this worked fine on OS X. But when we tested on Windows, we found that wx.SetClientSize has no effect whatsoever, as far as we can tell. The controls stubbornly stayed their original sizes.

SetClientSize should always work, but perhaps there is something else that is resetting the size after the SetClientSize call.

Changing that call to wx.SetSize worked fine on both platforms (on OS X, the behavior appears to be identical to .SetClientSize for all the window types we've tested, which admittedly isn't very many).

So we have a work-around, but I'd like to understand what's going on here. Why would SetClientSize be ignored under Windows? And what really is the difference between these two? The docs say:

void SetSize (int width, int height)
     Sets the size of the window in pixels.

void SetClientSize (int width, int height)
     This sets the size of the window client area in pixels.

For a frame, I think I understand the difference; the client area is the content of the window, excluding the titlebar and window borders and such, whereas the size would include those things.

For a control (button, ListCtrl, TextCtrl, etc.), is there ever a difference? Would Size allow room for a shadow or focus ring, and ClientSize not? This doesn't appear to be the case in my testing, but I'd like a more definite answer.

Some child windows can have borders too, (wx.BORDER_SUNKEN, etc.) and in this case the client size is the area that is inside these borders. For other widget types the client size is always the same as the widget size.

And is there any good reason SetClientSize should be ignored under Windows?

No. Can you create a small runnable sample that shows this?

···

--
Robin Dunn
Software Craftsman
http://wxPython.org Java give you jitters? Relax with wxPython!

Joe Strout wrote:

Also, there is one other weird effect we're seeing, only on Windows. When the window first appears, we (dynamically) reposition and resize a ListCtrl and a StaticText, so that the latter appears just below the former. We also do the same thing whenever the window is resized by the user. But initially, the static text appears actually drawn *on top of* the listbox. Only after resizing the window manually does it appear where it belongs. I'm pretty sure it's not a logic flaw in my code, since the same code works fine on OS X. Any idea what to look for here?

This can happen if the widgets are initially created on top of each other then this can happen if there isn't an initial refresh after the items have been moved. (IOW, the text widget may not actually be there, but since it was painted there initially and since the listctrl hasn't repainted itself, then you can still see it.) As Chris mentioned sometimes (especially on windows) the order that things happen in is sometimes unexpected.

The fact that it is fixed after manually resizing the window is a hint about how to fix it. You can either ensure that the frame's initial size is set after the widgets have been created, or you can force an extra size event with SendSizeEvent. In this case since it seems to be a paint issue then adding a call to Refresh after Show may also be needed.

···

--
Robin Dunn
Software Craftsman
http://wxPython.org Java give you jitters? Relax with wxPython!