Sunday, April 17, 2011

Class containing auto_ptr stored in vector

In an answer to http://stackoverflow.com/questions/700588/is-it-safe-to-store-objects-of-a-class-which-has-an-stdautoptr-as-its-member-v I stated that a class that contained an auto_ptr could be stored in a vector provided the class had a user-defined copy constructor.

There were several comment suggesting that this was not the case, so this question is an attempt to clear the issue up. Consider the following code:

#include <memory>
#include <vector>
using namespace std;

struct Z {};

struct A {

    A( Z z ) 
     : p( new Z(z) ) {} 

    A( const A & a ) 
     : p( a.p.get() ? new Z( *a.p.get()) : 0 ) {}

    // no assigment op or dtor defined by intent

    auto_ptr <Z> p;
};

int main() {
    vector <A> av;    
    Z z;     
    A a(z);
    av.push_back( a );  
    av.push_back( A(z) ); 
    av.clear();    
}

Please examine the above & in your reply indicate where undefined behaviour in the meaning of the C++ Standard could occur for this particular class used in this particular way. I am not interested whether the class is useful, well-behaved, sortable, or how it performs under exceptions.

Please also note that this is not a question about the validity of creating a vector of auto_ptrs - I am well aware of the issues regarding that.

Thanks all for your inputs on what in retrospect is probably a rather silly question. I guess I focussed too much on the copy ctor & forgot about assignment. The lucky winner of my acceptance points (and points mean prizes!) is litb for a typically exhaustive explanation (sorry earwicker)

From stackoverflow
  • Since the regular auto_ptr semantic could suggests that the ownership is passed during the copying, I would rather use here boost::scoped_ptr. Of course the assignment operator is missing.

  • I don't think it's necessarily the case that the above code will even compile. Surely the implementor of std::vector is at liberty to require an assignment operator to be available, from const A&?

    And having just tried it, it doesn't compile on Visual Studio C++ 2008 Service Pack 1:

    binary '=' : no operator found which takes a right-hand operand of type 'const A' (or there is no acceptable conversion)

    My guess is that, on the guidance of Herb Sutter, the container classes in VC++ make every effort to impose the standard requirements on their type parameters, specifically to make it hard to use auto_ptr with them. They may have overstepped the boundaries set by the standard of course, but I seem to remember it mandating true assignment as well as true copy construction.

    It does compile in g++ 3.4.5, however.

    anon : Yes, now you remind me I remember that too - I guess that answers my question :-(
    Daniel Earwicker : Well where my's green tick for being a clever boy then? :)
    anon : All good things come to he who waits.
    Daniel Earwicker : Oh man. The anticipation is almost unbearable!
    Johannes Schaub - litb : that is exactly what i told him on his answer on the other question. you have to be able to assign / copy from "const T" because the requirements state it. not because it might be useful or anything like that. +1 indeed
    Johannes Schaub - litb : here is the output of gcc 4.1: http://codepad.org/P0uxxqxH
  • What about the following?

    cout << av[ 0 ] << endl;
    

    Also, conceptually, a copy should leave the item copied from unchanged. This is being violated in your implementation.

    (It is quite another thing that your original code compiles fine with g++ -pedantic ... and Comeau but not VS2005.)

    Daniel Earwicker : "Also, conceptually, a copy should leave the item copied from unchanged." - try telling that to auto_ptr!
    anon : My question wasn't about the usefulness of the class - obviously it is completely broken, but only about UB. But as Earwicker pointed out I think VC++ may be right for once. Interesting about Comeau though...
    dirkgently : @Earwicker: That was my point about auto_ptrs.
    dirkgently : @Neil Butterworth: You are only looking at part of the class and a special construct that does not invoke UB. The point of my example.
  • Objects stored in containers are required to be "CopyConstructable" as well as "Assignable" (C++2008 23.1/3).

    Your class tries to deal with the CopyConstructable requirement (though I'd argue it still doesn't meet it - I edited that argument out since it's not required and because it's arguable I suppose), but it doesn't deal with the Assignable requirement. To be Assignable (C++2008 23.1/4), the following must be true where t is a value of T and u is a value of (possibly const) T:

    t = u returns a T& and t is equivalent to u

    The standard also says in a note (20.4.5/3): "auto_ptr does not meet the CopyConstructible and Assignable requirements for Standard Library container elements and thus instantiating a Standard Library container with an auto_ptr results in undefined behavior."

    Since you don't declare or define an assignment operator, an implicit one will be provided that uses the auto_ptr's assignment operator, which definitely makes t not equivalent to u, not to mention that it won't work at all for "const T u" values (which is what Earwicker's answer points out - I'm just pointing out the exact portion(s) of the standard).

  • Trying to put the list of places together that makes the example undefined behavior.

    #include <memory>
    #include <vector>
    using namespace std;
    
    struct Z {};
    
    struct A {
    
        A( Z z ) 
            : p( new Z(z) ) {} 
    
        A( const A & a ) 
            : p( a.p.get() ? new Z( *a.p.get()) : 0 ) {}
    
        // no assigment op or dtor defined by intent
    
        auto_ptr <Z> p;
    };
    
    int main() {
        vector <A> av;  
        ...
    }
    

    I will examine the lines up to the one where you instantiate the vector with your type A. The Standard has to say

    In 23.1/3:

    The type of objects stored in these components must meet the requirements of CopyConstructible types (20.1.3), and the additional requirements of Assignable types.

    In 23.1/4 (emphasis mine):

    In Table 64, T is the type used to instantiate the container, t is a value of T, and u is a value of (possibly const) T.

    +-----------+---------------+---------------------+
    |expression |return type    |postcondition        |
    +-----------+---------------+---------------------+
    |t = u      |T&             |t is equivalent to u |
    +-----------+---------------+---------------------+
    

    Table 64

    In 12.8/10:

    If the class definition does not explicitly declare a copy assignment operator, one is declared implicitly. The implicitly-declared copy assignment operator for a class X will have the form

    X& X::operator=(const X&)
    

    if

    • each direct base class B of X has a copy assignment operator whose parameter is of type const B&, const volatile B& or B, and
    • for all the nonstatic data members of X that are of a class type M (or array thereof), each such class type has a copy assignment operator whose parameter is of type const M&, const volatile M& or M.

    Otherwise, the implicitly declared copy assignment operator will have the form

    X& X::operator=(X&)
    

    (Note the last and second last sentence)

    In 17.4.3.6/1 and /2:

    In certain cases (replacement functions, handler functions, operations on types used to instantiate standard library template components), the C++ Standard Library depends on components supplied by a C++ program. If these components do not meet their requirements, the Standard places no requirements on the implementation.

    In particular, the effects are undefined in the following cases:

    • for types used as template arguments when instantiating a template component, if the operations on the type do not implement the semantics of the applicable Requirements subclause (20.1.5, 23.1, 24.1, 26.1). Operations on such types can report a failure by throwing an exception unless otherwise specified.

    Now, if you look at the specification of auto_ptr you will note it has a copy-assignment operator that takes a non-const auto_ptr. Thus, the implicitly declared copy assignment operator of your class will also take a non-const type as its parameter. If you read the above places carefully, you will see how it says that instantiating a vector with your type as written is undefined behavior.

    anon : But my class has an _explicitly_ declared copy constructor, so I don't see how this applies.
    Johannes Schaub - litb : it does not apply to that at all. it's the copy assignment operator that is missing - not the copy constructor. i would say as defined, your copy constructor is all fine.
    anon : oops - my misread - sorry
    Johannes Schaub - litb : Neil, c++98 standard had a typo that said "copy constructor" at one particular place (and i take my quotes from c++98 - only have that). in a revisions list i read c++03 fixed that. maybe it was this that made you think of a copy constructor :) (i already fixed it a hour ago)

What is meant by 'first class object'?

In a recent question, I received suggestions to talk on, amongst other things, the aspect of JavaScript where functions are 'first class' objects. What does the 'first class' mean in this context, as opposed to other objects?

EDIT (Jörg W Mittag): Exact Duplicate: "What is a first class programming construct?"

From stackoverflow
  • To quote Wikipedia:

    In computer science, a programming language is said to support first-class functions (or function literal) if it treats functions as first-class objects. Specifically, this means that the language supports constructing new functions during the execution of a program, storing them in data structures, passing them as arguments to other functions, and returning them as the values of other functions.

    This page also illustrates it beautifully:

    Really, just like any other variable

    • A function is an instance of the Object type
    • A function can have properties and has a link back to its constructor method
    • You can store the function in a variable
    • You can pass the function as a parameter to another function
    • You can return the function from a function

    also read TrayMan's comment, interesting...

    Spoike : Quoting wikipedia is nice and dandy, but the description is written in a language for scientists and not for geeks. What the heck does all that mean anyway? The last sentence in that quote is vagu.
    Sander Versluys : @Spoike, true... provided javascript resource.
    TrayMan : Conveniently a language that has first-class functions also has higher-order functions, as opposed to being limited to first-order functions, which would rule out first-class functions. (Though higher-order, not first-class is possible.)
    ProfK : I found nothing unclear in the Wikipedia quote, but the additional link is excellent.
  • It means that functions are objects, with a type and a behaviour. They can be dynamically built, passed around as any other object, and the fact that they can be called is part of their interface.

  • It means that function actually inherits from Object. So that you can pass it around and work with it like with any other object.

    In c# however you need to refrain to delegates or reflection to play around with functions. (this got much better recently with lambda expressions)

  • i guess when something is first class in a language, it means that it's supported by its syntax rather than a library or syntactic sugar. for example, classes in C are not first class

  • Simple test. If you can do this in your language (Python as example):

    def double(x):
        return x*x
    
    f = double
    
    print f(5) #prints 25
    

    Your language is treating functions as first class objects.

    Thomas L Holaday : But I can do this in C++: int twice(int x) { return x << 1; } int (*f)(int) = twice; std::cout<<(*f)(5)<
    cHao : Til you can create a function inside a function, i want to say no.
  • The notion of "first-class functions" in a programming language was introduced by British computer scientist Christopher Strachey in the 1960s. The most famous formulation of this principle is probably in Structure and Interpretation of Computer Programs by Gerald Jay Sussman and Harry Abelson:

    • They may be named by variables.
    • They may be passed as arguments to procedures.
    • They may be returned as the results of procedures.
    • They may be included in data structures.

    Basically, it means that you can do with functions everything that you can do with all other elements in the programming language. So, in the case of JavaScript, it means that everything you can do with an Integer, a String, an Array or any other kind of Object, you can also do with functions.

Determine path dynamically in Silverlight 2

I have a border with rounded corners within a canvas and want to add a clipping region to the canvas so that anything I add is clipped to the region within the border. I know that I can set the Clip property of the canvas but as the canvas and object are sized dynamically rather than having sizes assigned in the XAML, I can't figure out how to calculate the path to use. Is there some way to derive a PathGeometry from a UIElement (the border in this case)? If not what is the best way to approach this? Here is the XAML for the test page I'm working with.

<UserControl x:Class="TimelinePrototype.Page"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Grid x:Name="LayoutRoot">
 <Grid.RowDefinitions>
  <RowDefinition Height="auto" />
  <RowDefinition />
 </Grid.RowDefinitions>
 <StackPanel Orientation="Horizontal" Margin="10">
  <Button x:Name="cmdDraw" FontSize="18" Click="cmdDraw_Click" Content="Draw" Margin="0,0,5,0" VerticalAlignment="Bottom" />
  <TextBlock x:Name="txtDateRange" FontSize="18" Margin="10,0,10,10" VerticalAlignment="Bottom" />
 </StackPanel>
 <Canvas x:Name="TimelineCanvas" Grid.Row="1" HorizontalAlignment="Stretch" 
    SizeChanged="TimelineCanvas_SizeChanged">
  <Border x:Name="TimelineBorder" 
    Background="LightGray" 
    BorderBrush="Black" 
    BorderThickness="2" 
    CornerRadius="15" 
    Margin="10"
    Grid.Row="1"
    VerticalAlignment="Top">
  </Border>
 </Canvas>
</Grid>

From stackoverflow
  • Try using the ActualHeight and ActualWidth properties

    var height = TimelineCanvas.ActualHeight;
    var width = TimelineCanvas.ActualWidth;
    
    Steve Crane : I had thought of using those but was wondering if there might be some other, more clever way of doing this.
  • I ended up using this code, but would still be interested in any alternate methods.

    RectangleGeometry clipRect = new RectangleGeometry();
    clipRect.Rect = new Rect(TimelineBorder.Margin.Left, TimelineBorder.Margin.Top, TimelineCanvas.ActualWidth - (TimelineBorder.Margin.Left + TimelineBorder.Margin.Right), TimelineCanvas.ActualHeight - (TimelineBorder.Margin.Top + TimelineBorder.Margin.Bottom));
    clipRect.RadiusX = TimelineBorder.CornerRadius.TopLeft;
    clipRect.RadiusY = TimelineBorder.CornerRadius.TopLeft;
    TimelineCanvas.Clip = clipRect;
    
    MojoFilter : I'd have to endorse that method; if only because I've done it that way dozens of times without seeing a nicer approach.
  • Try blacklight

    The blacklight toolpack has a rounded corner clipping tool and is free.

    Steve Crane : Thanks, I'll check it out.

C#: Blowfish Encipher a single dword

Hello,

I'm translating a C++ TCP Client into C#.The client is used to encode 4 bytes of an array using blowfish.

C++ Blowfish

C# Blowfish(C# NET)

C++

    BYTE response[6] = 
 {
  0x00, 0x80, 0x01, 0x61, 0xF8, 0x17
 };

 // Encrypt the last 4 bytes of the packet only(0x01,0x061,0xF8,0x17)
 blowfish.Encode(responce + 2, responce + 2, 4); 

 // Send the packet
 send(s, (char*)sendPtr, sendSize, 0);

C#

    responce  = new byte[6] { 0x00, 0x80, 0x01, 0x61, 0xF8, 0x17};

    // Encrypt the last 4 bytes of the packet only(0x01,0x061,0xF8,0x17)
    Handshake.blowfish.Encrypt(responce, 2, responce, 2, 4);

 // Send the packet
    WS.sock.Send(encrypted);

In the C++ code,when the line "Blowfish.Encode" is called with these parameters,it goes into the cBlowfish.Encrypt function

DWORD cBlowFish::Encode(BYTE * pInput, BYTE * pOutput, DWORD lSize)
{
DWORD  lCount, lOutSize, lGoodBytes;
BYTE *pi, *po;
int  i, j;
int  SameDest =(pInput == pOutput ? 1 : 0);

lOutSize = GetOutputLength(lSize);
for(lCount = 0; lCount < lOutSize; lCount += 8)
{
 if(SameDest) // if encoded data is being written into input buffer
 {
   if(lCount < lSize - 7) // if not dealing with uneven bytes at end
   {
     Blowfish_encipher((DWORD *) pInput, (DWORD *)(pInput + 4));
   }
   else  // pad end of data with null bytes to complete encryption
   {
   po = pInput + lSize; // point at byte past the end of actual data
   j =(int)(lOutSize - lSize); // number of bytes to set to null
   for(i = 0; i < j; i++)
    *po++ = 0;
     Blowfish_encipher((DWORD *) pInput, (DWORD *)(pInput + 4));
   }
   pInput += 8;
 }
 else    // output buffer not equal to input buffer, so must copy
 {               // input to output buffer prior to encrypting
   if(lCount < lSize - 7) // if not dealing with uneven bytes at end
   {
    pi = pInput;
    po = pOutput;
    for(i = 0; i < 8; i++)
    // copy bytes to output
     *po++ = *pi++;
     // now encrypt them
   Blowfish_encipher((DWORD *) pOutput, (DWORD *)(pOutput + 4));
   }
   else  // pad end of data with null bytes to complete encryption
   {
    lGoodBytes = lSize - lCount; // number of remaining data bytes
    po = pOutput;
    for(i = 0; i <(int) lGoodBytes; i++)
     *po++ = *pInput++;
    for(j = i; j < 8; j++)
     *po++ = 0;
     Blowfish_encipher((DWORD *) pOutput, (DWORD *)(pOutput + 4));
   }
   pInput += 8;
   pOutput += 8;
 }
}
return lOutSize;
}

To make it clear,the loop is executed only one time due to the short length of the bytes passed(4).

Only one call is executed from this huge code(only once),the call is:

Blowfish_encipher((DWORD *) pInput, (DWORD *)(pInput + 4));

//meaning the code is passing the first two if statements and then leaves the loop and the function.

From my point of view,the solution is hidden somewhere inside the encipher function:

void cBlowFish::Blowfish_encipher(DWORD *xl, DWORD *xr)
{
union aword Xl, Xr;

Xl.dword = *xl;
Xr.dword = *xr;

Xl.dword ^= PArray [0];
ROUND(Xr, Xl, 1);  
ROUND(Xl, Xr, 2);
ROUND(Xr, Xl, 3);  
ROUND(Xl, Xr, 4);
ROUND(Xr, Xl, 5);  
ROUND(Xl, Xr, 6);
ROUND(Xr, Xl, 7);  
ROUND(Xl, Xr, 8);
ROUND(Xr, Xl, 9);  
ROUND(Xl, Xr, 10);
ROUND(Xr, Xl, 11); 
ROUND(Xl, Xr, 12);
ROUND(Xr, Xl, 13); 
ROUND(Xl, Xr, 14);
ROUND(Xr, Xl, 15); 
ROUND(Xl, Xr, 16);
Xr.dword ^= PArray [17];

*xr = Xl.dword;
*xl = Xr.dword;
}

The definitions:

#define S(x,i)    (SBoxes[i][x.w.byte##i])
#define bf_F(x)   (((S(x,0) + S(x,1)) ^ S(x,2)) + S(x,3))
#define ROUND(a,b,n)    (a.dword ^= bf_F(b) ^ PArray[n])

The problem is that the Blowfish_Encipher function in C++ has two parameters:Input(xl) as dword and Output(xr) as dword.

The C# Blowfish Encrypt_Block function has four parameters,why?

        public void EncryptBlock(uint hi,uint lo,out uint outHi,out uint outLo)

Unlike the C++ blowfish,EncryptBlock calls Encrypt instead Encrypt to call EncryptBlock.Maybe EncryptBlock is NOT the C++ Blowfish_Encipher?

Anyway,my problem is that when I call the C++ code with that array of 6 bytes requesting the blowfish to encode only the last 4 bytes,it does it.

While If I call the encrypt function in C# with those 4 bytes,it returns 0x00.(If you'd like to see the C# Blowfish,check my first lines - I have added a hyperlink there).

Note I can't change the packet structure,it should be just like that,but encrypted.

I also tried this:

Knowing the C++ Encrpypt functions executes only one call - blowfish Encipher.I tried to call EncryptBlock in C# directly,but there are Hi Uint32 and Low Uint32 as input and output,how to spread them into HI or LO? Will this work if the Encrypt_Block calls blowfish Encrypt in C#? I'm quite not sure.

Thank you in advance!

From stackoverflow
  • Hi John

    Blowfish works on eight byte blocks. The only way to encrypt data that falls short of eight bytes (or a multiple of eight) is to pad it out (in this case with zeroes).

    You need to pass an eight byte buffer into your C++ function, since you are encrypting in place. The code you posted will actually encrypt four additional bytes of adjacent memory ((DWORD *)(pInput + 4)), which is obviously not what you want. Furthermore, all eight output bytes are required in order to decrypt - so, unfortunately, you can't just pass four of the encrypted bytes and expect them to be decrypted successfully at the other end.

    I know this doesn't solve your problem - I don't see any way to solve it, since you want to send only four bytes of encrypted data and Blowfish always produces a minimum of eight!

.Net DefaultValueAttribute on Properties

I got this code in a user control:

[DefaultValue(typeof(Color), "Red")]
public Color MyColor { get; set; }

How can I change MyColor to be its default value?

From stackoverflow
  • The DefaultValueAttribute does not set the property to the value, it is purely informational. The Visual Studio designer will display this value as non-bold and other values as bold (changed), but you'll still have to set the property to the value in the constructor.

    The designer will generate code for the property if the value was set by the user, but you can remove that code by right clicking on the property and clicking Reset.

  • Are you initializing MyColor in your constructor?

    The DefaultValue attribute does not actually set any values. It simply instructs the designer for which value to not generate code and will also show the default value non-bold to reflect this.

  • The "DefaultValue" attribute does not write code for you... but rather it is used for you to tell people (such as Mr Property Grid, or Mr Serializer Guy) that you plan to set the default value to Red.

    This is useful for things like the PropertyGrid... as it will BOLD any color other than Red... also for serialization, people may choose to omit sending that value, because you informed them that it's the default :)

  • DefaultValueAttribute is not used by the compiler, and (perhaps confusingly) it doesn't set the initial value. You need to do this your self in the constructor. Places that do use DefaultValueAttribute include:

    • PropertyDescriptor - provides ShouldSerializeValue (used by PropertyGrid etc)
    • XmlSerializer / DataContractSerializer / etc (serialization frameworks) - for deciding whether it needs to be included

    Instead, add a constructor:

    public MyType() {
      MyColor = Color.Red;
    }
    

    (if it is a struct with a custom constructor, you need to call :base() first)

  • It is informal, but you can use it via reflection, for example, place in your constructor the following:

     foreach (FieldInfo f in this.GetType().GetFields())
     {
      foreach (Attribute attr in f.GetCustomAttributes(true))
      {
       if (attr is DefaultValueAttribute)
       {
        DefaultValueAttribute dv = (DefaultValueAttribute)attr;
        f.SetValue(this, dv.Value);
       }
      }
     }
    
    Marc Gravell : In the example given, the attribute is set against the property, not the field.
    Melursus : I adapt your code for property and it's work well, thx!
    Yossarian : Ok, so - rewrite - foreach (FieldInfo f in this.GetType().GetFields()) as foreach (PropertyInfo f in this.GetType().GetProperties())
    Samuel : Wait wtf? Why is this accepted? If this answers your question, you need to rewrite your question.

How to pass variable to a function created through the guide

I developed a form using with guide, i want to send a variable to that function through command line how it is possible if aanybody know s please tell to me

thanks in advance

From stackoverflow
  • I have no idea what you want to do exactly, but you may probably want to use the figure's UserData property:

    Passing somevar when opening the form myfig:

    h = myfig('UserData', somevar);
    

    or later:

    h = myfig();
    [...]
    set(h, 'UserData', somevar);
    

    In the figure you can access the property with:

    function some_Callback(hObject, eventdata, handles)
        somevar = get(hObject, 'UserData');
    

    See link text and link text

  • The links supplied by ymihere look very helpful. In addition, some of the options (nested functions and using GUIDATA) discussed at those links are addressed in another post on SO: How to create a GUI inside a function in MATLAB? There are a couple of examples there of how the code looks for each case.

    I am personally partial to using nested functions, as I feel like it creates shorter, cleaner code in most cases. However, it's probably the more difficult of the methods for sharing application data if you are a newer MATLAB user (it can take a little getting used to). The easiest option for you may be to set the 'UserData' property on your call to your function (as suggested by ymihere). If you saved your GUIDE GUI to "myGUI.m", then you would call:

    >> hGUI = myGUI('UserData','hello');
    

    where hGUI is a handle to your GUI object. You can then get the 'UserData' property to see that it contains the string 'hello':

    >> get(hGUI,'UserData')
    
    ans =
    
    hello
    

    Instead of 'hello', you can put anything you want, like a structure of data. You should be able to access the 'UserData' field of the figure from within the callbacks of your GUIDE m-file. You will have to get the figure handle from the handles argument passed to your callbacks.

    EDIT: One drawback to using the 'UserData' property, or some of the other methods which attach data to an object, is that the data could be accidentally (or intentionally) overwritten or otherwise corrupted by the user or other applications. The benefit of using nested functions to share data between your GUI callbacks is that it insulates your code from anything the user or another application might do. Conversely, using global variables can be rather dangerous.

Looking for Recommendation on Windows Forms .Net Resizing Component

By default windows forms resize logic is limited--anchoring and docking. In the past I've rolled my own custom resize logic when required. However, I'm getting started on a project that has a large number of very complex forms that must auto-resize to different resolutions. I don't care to invest a ton of time in resize logic.

I see that there are companies selling components that advertise uniform resizing. Does anyone have any experience with any resizing components/have any recommendations?

From stackoverflow
  • Have you looked at the TableLayoutPanel? It should allow you have different "cells" each containing a single UI element and have all the cells grow at the same rate.

  • Aye, TableLayoutPanel and setting AutoSize to True on the form can be quite powerful, but it takes a bit to understand what is going on, but if you have a few hours to get used to it, you can make some awesome dialogs without having to do a lot of work.

  • I found a component .net resize which seems to work really well. Simply drop it on the form and it makes the form completely resizable. Unfortunately, at $178 a seat it's a bit on the expensive side.

  • If you don't want to buy anything and the TableLayoutPanel is not good enough for your needs (which would mean you have some very special needs), you could always create a component yourself to manage the resize, which could work for all your forms. (a bit like .net resize you described above)

    You could also take into calculation the time it would require you to create something that does the same work as .net resize. If the time versus cost seems similar, depending on your deadlines, you might prefer to code it yourself so you have full control.

  • See following:
    http://urenjoy.blogspot.com/2008/11/make-resolution-independent-windows-app.html