This is a migrated thread and some comments may be shown as answers.

Splitter Changes Not Working Correctly in DPI Aware App

2 Answers 85 Views
Dock
This is a migrated thread and some comments may be shown as answers.
Robert
Top achievements
Rank 1
Iron
Robert asked on 23 Aug 2017, 11:20 PM

Hello,

There appears to be an issue making tool window width adjustments via the splitters in a DPI aware app. Dragging a splitter with the mouse will eventually hide the document window as the tool window makes large changes when only small changes are wanted. This can be demonstrated with a new app with a RadDock control dropped on the form. Add 2 tool windows and 1 document window. Make the app DPI aware. Run the app at 150% and try making small width changes to either of the tool windows. The tool window will make a couple of large jumps and then completely hide the document window. It also doesn't matter which way you drag the tool window as the same phenomenon occurs.

Telerik Control Version: 2017.2.613.40

Framework 4.52 or higher.

Best regards,

Robert

 

 

 

2 Answers, 1 is accepted

Sort by
0
Hristo
Telerik team
answered on 25 Aug 2017, 01:47 PM
Hi Robert,

Thank you for writing.

I managed to reproduce the incorrect behavior and I have logged the issue on our feedback portal, here: FIX. RadDock - the tool windows are not resized correctly in higher DPI. You can additionally subscribe to it and be updated with all of its status changes. I have also updated your Telerik points.

The item is already in development and a fix will be introduced with our R3 release scheduled for mid-September. Until then you will need to create a custom RadDock with a custom layout strategy: 
public class MyRadDock : RadDock
{
    public override string ThemeClassName
    {
        get
        {
            return typeof(RadDock).FullName;
        }
    }
 
    protected override SplitContainerLayoutStrategy CreateLayoutStrategy()
    {
        MySplitContainerLayoutStrategy strategy = null;
        if (this.LayoutStrategyType != null)
        {
            try
            {
                strategy = Activator.CreateInstance(this.LayoutStrategyType) as MySplitContainerLayoutStrategy;
            }
            catch
            {
                strategy = null;
            }
        }
 
        if (strategy == null)
        {
            strategy = new MySplitContainerLayoutStrategy();
        }
 
        strategy.RootContainerType = typeof(RadDock);
        return strategy;
    }
}
 
public class MySplitContainerLayoutStrategy : SplitContainerLayoutStrategy
{
    protected override void Measure()
    {
        SplitContainerLayoutInfo layoutInfo = (SplitContainerLayoutInfo)typeof(SplitContainerLayoutStrategy).GetField("layoutInfo", BindingFlags.Instance | BindingFlags.NonPublic).
            GetValue(this);
 
        SplitPanel fillPanel = (SplitPanel)typeof(SplitContainerLayoutInfo).GetField("fillPanel", BindingFlags.Instance | BindingFlags.NonPublic).
            GetValue(layoutInfo);
 
        if (fillPanel == null)
        {
            base.Measure();
        }
 
        this.MeasureWithFillPanel();
 
        typeof(SplitContainerLayoutStrategy).GetMethod("ClampMeasuredLength", BindingFlags.Instance | BindingFlags.NonPublic).
            Invoke(this, new object[] { });
    }
 
    private void MeasureWithFillPanel()
    {
        FieldInfo layoutInfoFi = typeof(SplitContainerLayoutStrategy).GetField("layoutInfo", BindingFlags.Instance | BindingFlags.NonPublic);
        SplitContainerLayoutInfo layoutInfo = (SplitContainerLayoutInfo)layoutInfoFi.GetValue(this);
 
        int availableLength = (int)typeof(SplitContainerLayoutInfo).GetField("availableLength", BindingFlags.Instance | BindingFlags.NonPublic).
          GetValue(layoutInfo);
 
        int remaining = availableLength;
        SplitPanel panel;
 
        //calculate the desired size of all non-fill panels
        int desiredNonFillLength = 0;
 
        List<SplitPanel> layoutTargets = (List<SplitPanel>)typeof(SplitContainerLayoutInfo).GetField("layoutTargets", BindingFlags.Instance | BindingFlags.NonPublic).
            GetValue(layoutInfo);
 
        SplitPanel fillPanel = (SplitPanel)typeof(SplitContainerLayoutInfo).GetField("fillPanel", BindingFlags.Instance | BindingFlags.NonPublic).
              GetValue(layoutInfo);
 
        int count = layoutTargets.Count;
        for (int i = 0; i < count; i++)
        {
            panel = layoutTargets[i];
            if (panel == fillPanel)
            {
                continue;
            }
 
            desiredNonFillLength += this.GetLength(panel.SizeInfo.AbsoluteSize);
        }
 
        SplitPanelSizeInfo fillInfo = fillPanel.SizeInfo;
 
        int totalSplitterLength = (int)typeof(SplitContainerLayoutInfo).GetField("totalSplitterLength", BindingFlags.Instance | BindingFlags.NonPublic).
              GetValue(layoutInfo);
        int layoutableLength = availableLength - totalSplitterLength;
        int correction = 0;
 
        int totalMinLength = (int)typeof(SplitContainerLayoutInfo).GetField("totalMinLength", BindingFlags.Instance | BindingFlags.NonPublic).
              GetValue(layoutInfo);
 
        int desiredFillLength = totalMinLength;
        if (desiredNonFillLength + desiredFillLength > layoutableLength)
        {
            correction = (desiredNonFillLength + desiredFillLength) - layoutableLength;
        }
 
        int remainingCorrection = correction;
        for (int i = 0; i < layoutTargets.Count; i++)
        {
            panel = layoutTargets[i];
            if (panel == fillPanel)
            {
                continue;
            }
 
            int length = this.GetLength(TelerikDpiHelper.ScaleSize(panel.SizeInfo.AbsoluteSize, new SizeF(1f / panel.SplitPanelElement.DpiScaleFactor.Width, 1f / panel.SplitPanelElement.DpiScaleFactor.Height)));
            if (remainingCorrection > 0 && panel.SizeInfo.SizeMode != SplitPanelSizeMode.Absolute)
            {
                float factor = (float)length / desiredNonFillLength;
                int panelCorrection = Math.Max(1, (int)(factor * correction));
                remainingCorrection -= panelCorrection;
                length -= panelCorrection;
            }
 
            panel.SizeInfo.MeasuredLength = length;
            int splitterLength = (int)typeof(SplitContainerLayoutInfo).GetField("splitterLength", BindingFlags.Instance | BindingFlags.NonPublic).
             GetValue(layoutInfo);
            remaining -= (panel.SizeInfo.MeasuredLength + splitterLength);
        }
         
        fillPanel.SizeInfo.MeasuredLength = remaining;
    }
}

I am also sending you attached my test project.

I hope this helps. Should you have further questions please do not hesitate to write back.

Regards,
Hristo
Progress Telerik
Try our brand new, jQuery-free Angular 2 components built from ground-up which deliver the business app essential building blocks - a grid component, data visualization (charts) and form elements.
0
Robert
Top achievements
Rank 1
Iron
answered on 30 Aug 2017, 12:30 PM

I have tried out your temporary work around and it does the job quite nicely. Thank you.

Robert

 

Tags
Dock
Asked by
Robert
Top achievements
Rank 1
Iron
Answers by
Hristo
Telerik team
Robert
Top achievements
Rank 1
Iron
Share this question
or