Click here to Skip to main content
15,881,588 members
Articles / Desktop Programming / Windows Forms
Tip/Trick

Proper Resizing of SplitterContainer Controls at any DPI

Rate me:
Please Sign up or sign in to vote.
4.75/5 (6 votes)
14 Jun 2014CPOL1 min read 21.4K   7   4
A method of ensuring that SplitterContainer controls with fixed panels are properly resized when AutoScaleMode is ScaleMode.DPI

Introduction

When a SplitterContainer control with a fixed panel is resized due to the DPI setting, the SplitterDistance value is not changed. This may result in the fixed panel appearing either too small or too large, depending on whether the DPI setting was increased or decreased.

For example, a Form with AutoScaleMode set to ScaleMode.DPI, and a SplitterContainer with FixedPanel set to Panel1 and SplitterDistance set to 140 appears as follows at it's native DPI (100%):

Image 1

This is how it appears when run at a higher DPI (125%):

Image 2

All the controls were resized, but SplitterDistance was left unchanged at 140.

Note that this is only a problem when SplitterContainer.FixedPanel is set to Panel1 or Panel2. If it was set to None, then SplitterDistance would be adjusted to match the resizing.

The solution to adjust SplitterDistance during the Form.Shown event handler. The resizing does not work properly if performed in the constructor or the Form.Load event handler.

Using the code

Include the following code snippet in your Form-derived class:

C#
// Save the current scale value
// ScaleControl() is called during the Form's constructor
private SizeF scale = new SizeF(1.0f, 1.0f);
protected override void ScaleControl(SizeF factor, BoundsSpecified specified)
{
    scale = new SizeF(scale.Width * factor.Width, scale.Height * factor.Height);
    base.ScaleControl(factor, specified);
}

// Recursively search for SplitContainer controls
private void Fix(Control c)
{
    foreach (Control child in c.Controls)
    {
        if (child is SplitContainer)
        {
            SplitContainer sp = (SplitContainer)child;
            Fix(sp);
            Fix(sp.Panel1);
            Fix(sp.Panel2);
        }
        else
        {
            Fix(child);
        }
    }
}

private void Fix(SplitContainer sp)
{
    // Scale factor depends on orientation
    float sc = (sp.Orientation == Orientation.Vertical) ? scale.Width : scale.Height;
    if (sp.FixedPanel == FixedPanel.Panel1)
    {
        sp.SplitterDistance = (int)Math.Round((float)sp.SplitterDistance * sc);
    }
    else if (sp.FixedPanel == FixedPanel.Panel2)
    {
        int cs = (sp.Orientation == Orientation.Vertical) ? sp.Panel2.ClientSize.Width :sp.Panel2.ClientSize.Height;
        int newcs = (int)((float)cs * sc);
        sp.SplitterDistance -= (newcs - cs);
    }
}

Remember to call Fix(this) from the Form's Shown event handler. For Example:

C#
private void Form1_Shown(object sender, EventArgs e)
{
    Fix(this);
} 

Points of Interest

I am puzzled as to why the SplitterDistance values must be adjusted during the <code>Form.Shown event handler, and not during Form.Load or the constructor. If anyone can explain this, please leave a comment.

History

  • June 14, 2014 - First release.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Software Developer (Senior)
Canada Canada
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions

 
Praisevery useful Pin
Southmountain4-Jul-22 5:22
Southmountain4-Jul-22 5:22 
GeneralNice tip about one method of ensuring that SplitterContainer controls with fixed panels are properly resized when AutoScaleMode is ScaleMode.DPI Pin
Volynsky Alex15-Jun-14 7:21
professionalVolynsky Alex15-Jun-14 7:21 
GeneralRe: Nice tip about one method of ensuring that SplitterContainer controls with fixed panels are properly resized when AutoScaleMode is ScaleMode.DPI Pin
Graham Wilson15-Jun-14 14:47
Graham Wilson15-Jun-14 14:47 
GeneralRe: Nice tip about one method of ensuring that SplitterContainer controls with fixed panels are properly resized when AutoScaleMode is ScaleMode.DPI Pin
Volynsky Alex15-Jun-14 22:07
professionalVolynsky Alex15-Jun-14 22:07 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.