.NET Forum / Windows Forms / WinForm General / August 2006
Updating MinimumSize while resizing does not work ?
|
|
Thread rating:  |
Pierre Arnaud - 22 Aug 2006 09:24 GMT Hello,
I have come across a problem for which I don't see any solution in the managed world. Here is the simplest way to reproduce it :
- Create a Form with a MinimumSize set to 100 x 100.
- When the ResizeBegin event is fired, change the MinimumSize to 50 x 50.
As soon as I start dragging the right side of my form, I'd expect the new MinimumSize to become active, yet Windows somehow keeps track of the original MinimumSize : I cannot reduce the size of my window below 100 x 100.
Checking with SPY++, I see that the Form properly reports an updated MinimumSize when the WM_GETMINMAXINFO event gets fired :
- WM_MOUSEMOVE - WM_SIZING - WM_WINDOWPOSCHANGING - WM_GETMINMAXINFO - WM_NCCALCSIZE - WM_NCPAINT ... - WM_WINDOWPOSCHANGED - WM_SIZE ...
Yet, as soon as I move to far to the left (where Width would become less than 100 pixels wide), I only get a tight loop of :
- WM_MOUSEMOVE - WM_SIZING
And WM_SIZING no longer changes.
Is this by design ?
I expected to be able to change the minimum size on the fly (in my real application, I need to update it based on the new window size, as the window contents rearranges itself, the minimum can become smaller than what I had first assumed).
Is there any way to make my scenario work ? Even dirty WndProc tricks will do, as long as I can make Windows forget about the initial reply to WM_GETMINMAXINFO !
Pierre
Author of Creative Docs .NET -- http://www.creativedocs.net/
Linda Liu [MSFT] - 22 Aug 2006 11:50 GMT Hi Pierre,
I performed a test based on your description. I set up a WinForms application, set the MinimumSize of the form to 400 x 400 and the Size of the form to 500 x 500. I handle the form's ResizeBegin event. Below is the code of the form's ResizeBegin event handler.
using System.Diagnostics;
public class Form1 : Form { private void Form1_ResizeBegin(object sender, EventArgs e) { this.MinimumSize = new Size(100, 100); // When the program is running with debugging and the below code is executed, the information will be written in the Output window. Debug.WriteLine("resize begin:" + this.MinimumSize.Width.ToString()); } }
Build the project and press F5 to run the program. I found the facts as follows.
1. When I begin to resize the form for the first time, I saw the information is written in the Output window: resize begin:100, but the form can only be minimized to 400 x 400. When I begin to resize the form for the second time, I could minimize the form to 100 x 100.
2. If I move the form before resize it, the information "resize begin:100" is written in the Output window as well. Then if I resize the form, I could minimize the form to 100 x 100 at this time.
Until now, we can see that even if the value of the MinimumSize property of the form is modified, this will take effect in the next time. So I recommend you to change the value of the MinimumSize property outside the form's ResizeBegin, Resize and ResizeEnd event handlers. The detailed place where you should put this code depends on your real requirement.
Hope this helps.
If you have any questions, please feel free to let me know.
Sincerely, Linda Liu Microsoft Online Community Support
================================================== Get notification to my posts through email? Please refer to http://msdn.microsoft.com/subscriptions/managednewsgroups/default.aspx#notif ications. Note: The MSDN Managed Newsgroup support offering is for non-urgent issues where an initial response from the community or a Microsoft Support Engineer within 1 business day is acceptable. Please note that each follow up response may take approximately 2 business days as the support professional working with you may need further investigation to reach the most efficient resolution. The offering is not appropriate for situations that require urgent, real-time or phone-based interactions or complex project analysis and dump analysis issues. Issues of this nature are best handled working with a dedicated Microsoft Support Engineer by contacting Microsoft Customer Support Services (CSS) at http://msdn.microsoft.com/subscriptions/support/default.aspx. ================================================== This posting is provided "AS IS" with no warranties, and confers no rights.
Pierre Arnaud - 22 Aug 2006 13:47 GMT Hi Linda,
I am glad you were able to reproduce the problem. However, your solution does not work for me. I really need to be able to update the MinimumSize on the fly, while the user is dragging the right hand border of the window.
The only solution I see for now is to set MinimumSize to {0;0} and then somehow handle the WM_SIZING event in order to avoid having the user make the window to narrow.
But I'd be glad if you could provide me an explanation of why Windows is behaving that way. I see nothing in the documentation for the WM_* messages sent while the resizing is happening, which states that the initial WM_GETMINMAXINFO size should take precedence over the next values.
I fear I've stumbled across a .NET/WinForms bug with respect to this behaviour.
Thank you for your time.
Pierre
Stoitcho Goutsev (100) - 22 Aug 2006 16:17 GMT Pierre,
WM_GETMINMAXINFO is sent twise: before entering the size/move modal loop and once before exiting. It looks like the min track size value returned from the message is used. On the other hand OnResizeBegin is fired in response to WM_ENTERSIZEMOVE and apperantly setting MinimumSize here is too late - new size needs to be set upon receiving WM_GETMINMAXINFO. Unfortunately controls doesn't have corresponding event for WM_GETMINMAXINFO, thus it needs to be handled in the WndProc override.
Here is an examle how this can be done.
const int WM_GETMINMAXINFO = 0x0024; protected override void WndProc(ref Message m) { if (m.Msg == WM_GETMINMAXINFO) { this.MinimumSize = new Size(100, 100); } base.WndProc(ref m); }
I don't know wheter the OS behaves like this or it's a bug in the Form class. Looking in the class though I don't see a reason for this not work if Windows OS takes into accoung min track size values returned by the second WM_GETMINMAXINFO message. Unfortunately at the moment I don't have time to dig into this deeper.
 Signature HTH Stoitcho Goutsev (100)
> Hi Linda, > [quoted text clipped - 19 lines] > > Pierre Pierre Arnaud - 22 Aug 2006 18:58 GMT > the message is used. On the other hand OnResizeBegin is fired in response to > WM_ENTERSIZEMOVE and apperantly setting MinimumSize here is too late - new > size needs to be set upon receiving WM_GETMINMAXINFO. I tried that, too. I had a test application with WndProc handling the WM_GETMINMAXINFO itself, but it didn't work any better.
Thanks anyway for the idea.
Pierre
Stoitcho Goutsev (100) - 23 Aug 2006 14:32 GMT Pierre,
In my test application changing the min size in WndProc upon receiving WM_GETMINMAXINFO works OK. I mean I have from restricted to 400x400, but I can change this in WndProc to 100x100 and it works.
Are your tests show differently or you cannot use it for some other reasons?
.
 Signature Stoitcho Goutsev (100)
>> the message is used. On the other hand OnResizeBegin is fired in response >> to [quoted text clipped - 8 lines] > > Pierre Pierre Arnaud - 24 Aug 2006 15:25 GMT > Pierre, > [quoted text clipped - 4 lines] > Are your tests show differently or you cannot use it for some other > reasons? Well, it works if you just want to specify the size once at the beginning of the resizing operation. In my case, I must be able to update this *while* the user is dragging (e.g. 400x400 first, then as we reach a width of 420, I want to be able to specify a new minimum size of 350, etc.)
Pierre
Stoitcho Goutsev (100) - 24 Aug 2006 16:33 GMT Pierre,
It looks like you hit OS limitation here. Apperanly you cannot use MinimumSize for that and you should try to use the rest of the events related to control resizing.
 Signature Stoitcho Goutsev (100)
>> Pierre, >> [quoted text clipped - 12 lines] > > Pierre Pierre Arnaud - 25 Aug 2006 07:55 GMT Stoitcho,
> It looks like you hit OS limitation here. Apperanly you cannot use > MinimumSize for that and you should try to use the rest of the events > related to control resizing. You are right. I am now using a minimum size of [1;1] and handling the WM_SIZING events to restrict the window resizing to my currently active minimum size.
Pierre
Linda Liu [MSFT] - 28 Aug 2006 12:23 GMT Hi Pierre,
The WM_GETMINMAXINFO message is sent to a window when the size or position of the window is about to change. An application can use this message to override the window's default maximized size and position, or its default minimum or maximum tracking size.
> I really need to be able to update the MinimumSize on the fly, while the user is dragging the right hand border of the window.
Since each time we resize the form, the WM_GETMINMAXINFO message is sent to the form to ask the MinimumSize, we could change the form's MinimumSize property in the overridden WndProc method and the new setting takes effect immediately. Could you tell me how you update the MinimumSize on the fly? I think you could move the logic of updating the MinimumSize property to the overridden WndProc method.
The following is a sample.
private const long WM_GETMINMAXINFO = 0x24;
protected override void WndProc(ref Message m) { if (m.Msg == WM_GETMINMAXINFO) { // put your logic to update the MinimumSize property of the form here //this.MinimumSize = new Size(200, 200); } base.WndProc(ref m); } Hope this helps. If you have anything concerns, please feel free to let me know.
Sincerely, Linda Liu Microsoft Online Community Support
Stoitcho Goutsev (100) - 28 Aug 2006 14:44 GMT Linda,
What is said si correct, but not completely. As we discussed earlier in this thread. WM_GETMINMAXINFO is set twise during the operation of resizing. Once before entering the resize/move modal loop and once at the end of the loop. The problem is that the information returned in response to the first message is probably cached and used for the whole resize session. In other words the MinimumSize can be changed only before the actuall resizing.
Pierre's problem is that the minmum size is calculated during the resizing (inside thesize/move modal loop) and there is too late - windows has alreay cached the minmum track size.
If you change the MinimumSize of a form or control in any of the control events that has anything to do with interactive resizing e.g. Reszize, ResizeBegin, ResizeEnd, etc the changes won't take effect until the next resize operation.
BTW this not windows forms proble it looks like this is a probably bug in the Windows OS itself.
 Signature Stoitcho Goutsev (100)
> Hi Pierre, > [quoted text clipped - 36 lines] > Linda Liu > Microsoft Online Community Support Linda Liu [MSFT] - 29 Aug 2006 03:37 GMT Hi Stoitcho,
Thanks for your insight.
Yes, you're right. If we change the MinimumSize property of a form in its Resize or ResizeBegin or ResizeEnd event handler, the change won't take effect until the next resize operation.
But we could do it in the overridden WndProc method. I don't know what the logic is that Pierre uses to calculate the minimum size, but I think Pierre could move the code of updating the minimum size to the WndProc method to make the change take effect for the current resize session.
Sincerely, Linda Liu Microsoft Online Community Support
Stoitcho Goutsev (100) - 29 Aug 2006 15:37 GMT Linda,
Yes, that was my suggestion, but it seems it doesn't work for him.
 Signature Stoitcho Goutsev (100)
> Hi Stoitcho, > [quoted text clipped - 13 lines] > Linda Liu > Microsoft Online Community Support Pierre Arnaud - 30 Aug 2006 21:41 GMT I tried overriding the WM_GETMINMAXINFO in WndProc, and it did not help, as Windows seems to be caching the first size returned by this message.
But never mind, as I have stated elsewhere in this now deep thread, I've solved my problem by setting the minimum size to 1;1 and then handling the WM_SIZING messages instead, which allow me to control very exactly the size of the window.
My resize logic is a bit strange in that you'd normally expect the contents of a window to have a predictive minimum size. In my case, it is not. Whenever I change the window size, the contents of the window can rearrange to better use the available size (e.g. use shorter labels, smaller buttons, whatever) and this produces a smaller minimum size as originally expected. So when the user drags the window frame to resize the form, I go through a full layout phase which might update the controls and then I determine the current minimum size.
You may consider this thread as closed as my issue was solved. Thank you very much to all of you who produced advice.
And sorry for my delay in responding. My first child was born on Monday, so I've not been spending much time online.
By the way, for the curious: http://www.opac.ch/naissance/2006/
> Linda, > [quoted text clipped - 17 lines] >> Linda Liu >> Microsoft Online Community Support Linda Liu [MSFT] - 31 Aug 2006 04:55 GMT Hi Pierre,
Thank you for your reply and CONGRATULATIONS!
If you have any question in the future, please don't hesitate to contact us.
Best regards,
Linda Liu Microsoft Online Community Support
Patrice - 22 Aug 2006 17:27 GMT Could worth to try to repro this using WinAPI but IMO not really surprising and likely at the OS level. The minimum size is IMO taken and "cached" when resize begins.
Else Windows would have to repeateadly read again this info in case the resize process would have changed it (and would come accross more debatable issues such as what to do if the new minimum size is bigger than the current size etc...) plus it would generate more messages which was likely preferred to be avoided when resizing was not a cheap operation.
 Signature Patrice
> Hi Linda, > [quoted text clipped - 19 lines] > > Pierre Pierre Arnaud - 22 Aug 2006 18:56 GMT > Could worth to try to repro this using WinAPI but IMO not really surprising > and likely at the OS level. The minimum size is IMO taken and "cached" when > resize begins. This makes sense.
> Else Windows would have to repeateadly read again this info in case the > resize process would have changed it [...] Yes, but that's exactly what I see with Spy++ : Windows keeps asking for the MINMAXINFO every time I move the mouse. Really strange.
> (and would come accross more debatable > issues such as what to do if the new minimum size is bigger than the current > size etc...) plus it would generate more messages which was likely preferred > to be avoided when resizing was not a cheap operation. You have a point, there. I'll try another approach tomorrow and let you know of the results.
Thanks a lot.
Pierre
Pierre Arnaud - 23 Aug 2006 09:15 GMT My experiments have shown that the information returned by the first WM_GETMINMAXINFO message sent while the user is resizing a window gets indeed cached by Windows. Subsequent WM_GETMINMAXINFO cannot increase the minimum size.
The only solution is to return a minimum size of [1;1] in the initial WM_GETMINMAXINFO and then handle the WM_SIZING message in order to restrict the moves of the window rectangle based on my own minimum size information.
So this has nothing to do with WinForms and everything to do with the way Windows "optimizes" the message handling. I'd have loved to find this better documented on MSDN Library.
Pierre
Free MagazinesGet these publications absolutely FREE for up to 12 months. There are no hidden fees and no obligation. Simply choose a title, complete the application form and submit it. Read more ...
|
|
|