m.qayyum
m.qayyum

Reputation: 411

Unknown behaviour in winforms

I'm using this code to hide the minimize/maximize controls of the form and only show border

protected override System.Windows.Forms.CreateParams CreateParams
{
    get
    {
        var parms = base.CreateParams;

        parms.Style &= ~0x00C00000; // remove WS_CAPTION
        parms.Style |= 0x00040000;  // include WS_SIZEBOX
        return parms;
    }
}

Form looks like this in Visual Studio enter image description here

And after running the application it looks like that enter image description here

You can see that when I run the application I see more space on left side of the application as compare to right side of the application. I'm stuck and don't know about this behaviour.

Upvotes: 0

Views: 216

Answers (2)

Adam Maras
Adam Maras

Reputation: 26843

The reason for this happening is that the Form.Size property that defines the width and height of you form includes the border size of the window. In the Forms Designer, there's no border defined, so you see the entire form as you have it laid out. However, when the window is rendered by Windows, the border that is added counts against the specified size.

To counteract this, upon loading or displaying the form, you can add to the size of the window twice the value of the border size. You can retrieve that border size by P/Invoking the GetSystemMetrics Win32 API function using SM_CXSIZEFRAME (32) as a parameter to retrieve the width or SM_CYSIZEFRAME (33) to retrieve the height.

Here's about what you're looking for:

[DllImport("user32.dll")]
private static extern int GetSystemMetrics(int index);

private static int WindowBorderWidth
{
    get { return GetSystemMetrics(32); }
}

private static int WindowBorderHeight
{
    get { return GetSystemMetrics(33); }
}

protected override void OnLoad(EventArgs e)
{
    int increaseWidth = WindowBorderWidth * 2;
    int increaseHeight = WindowBorderHeight * 2;

    this.Size = new Size(
        this.Size.Width + increaseWidth,
        this.Size.Height + increaseHeight
    );
}

Upvotes: 2

Hans Passant
Hans Passant

Reputation: 941277

I cannot repro this exactly. First possible issue is that this looks like an inherited form, this can cause trouble if the controls in the base form have the Anchor set with the bottom or right anchor turned on. Which positions the control based on the size of the base form, not the inherited form. Fix this by only turning on those anchors in the derived form.

Second, and more likely issue is that you are battling an appcompat issue in Aero. The fat borders are a significant problem in Aero since an app specifies the outer window size. But really cares about the inner window size, the size of the client rectangle. If Aero wouldn't deal with this, the window will end up with a client area that's too small, not leaving enough room for the controls. It does so by lying about the window size, secretly making it larger than what the app asked for. And then lying when you ask for the size, reporting a smaller size than the window actually has.

Your CreateParams override turns that lie off because of the non-standard window styles. Correspondingly, the client area of the window is smaller by the amount the borders are fatter, 6 pixels by default.

This lie causes many other subtle problems, hard to get windows aligned for example. This issue was finally addressed in .NET 4.5, the first version of .NET that doesn't have to support XP anymore. And therefore doesn't need the lie anymore. It marks the EXE file of your program as requiring Vista or higher. Which in turns off the lie.

It isn't clear from your question which way you want to go. In a case like this, it is probably best to just force the size of the window. You do so in the form's OnLoad() method, something like this:

    protected override void OnLoad(EventArgs e) {
        this.ClientSize = new Size(NoButton.Right + 10, NoButton.Bottom + 10);
        base.OnLoad(e);
    }

Upvotes: 1

Related Questions