KryptonSeparator resizing issue

469 views Asked by At

Scenario

I'm in need of help using a KryptonSeparator.

I would like to use the separator in the image below to resize the width of the left and right controls:

enter image description here

Problem

The problem is when I try to move the separator to the left then it creates a very disturbing visual effect, and more or less the same thing happens when I move the separator to the right, but to the left is much more appreciable (and horrible):

enter image description here

I think that I'm not using properly the eventargs of the KryptonSeparator because when I move the separator to the left I'm basing the calculations using the separator's width instead the event data (because I don't know how to do it properly).

Question

What modifications I should do in my code to fix the resizing problem?

Code

Both the left and the right control has a MinimumSize property assigned, I'm trying to stop the resize if MinimumSize.Width is reached.

This is the source code, in VB.Net:

''' <summary>
''' Handles the SplitterMoving event of the KryptonSeparator1 control.
''' </summary>
Private Sub KryptonSeparator1_SplitterMoving(ByVal sender As Object, ByVal e As SplitterCancelEventArgs) _
Handles KryptonSeparator1.SplitterMoving

    Dim separator As KryptonSeparator = DirectCast(sender, KryptonSeparator)
    Dim leftCtrl As Control = Control1
    Dim rightCtrl As Control = Control2

    If (e.MouseCursorX > 0) _
    AndAlso Not ((rightCtrl.Size.Width - e.MouseCursorX) < rightCtrl.MinimumSize.Width) Then

        separator.Location = New Point(separator.Location.X + e.MouseCursorX, separator.Location.Y)
        leftCtrl.Width += e.MouseCursorX
        rightCtrl.Width -= e.MouseCursorX
        rightCtrl.Left = separator.Right

    ElseIf (e.MouseCursorX < 0) _
    AndAlso Not ((leftCtrl.Size.Width + e.MouseCursorX - separator.Width) < leftCtrl.MinimumSize.Width) Then

        separator.Location = New Point(separator.Location.X - separator.Width, separator.Location.Y)
        leftCtrl.Width -= separator.Width
        rightCtrl.Width += separator.Width
        rightCtrl.Left = separator.Right

    End If

End Sub

This is the source code, in C#:

/// Handles the SplitterMoving event of the KryptonSeparator1 control.
/// </summary>
private void KryptonSeparator1_SplitterMoving(object sender, SplitterCancelEventArgs e)
{
    KryptonSeparator separator = (KryptonSeparator)sender;
    FolderView leftCtrl = this.FolderView_Files;
    KryptonListBox rightCtrl = this.KryptonListBox_Files;

    if ((e.MouseCursorX > 0) && !((rightCtrl.Size.Width - e.MouseCursorX) < rightCtrl.MinimumSize.Width)) {
        separator.Location = new Point(separator.Location.X + e.MouseCursorX, separator.Location.Y);
        leftCtrl.Width += e.MouseCursorX;
        rightCtrl.Width -= e.MouseCursorX;
        rightCtrl.Left = separator.Right;


    } else if ((e.MouseCursorX < 0) && !((leftCtrl.Size.Width + e.MouseCursorX - separator.Width) < leftCtrl.MinimumSize.Width)) {
        separator.Location = new Point(separator.Location.X - separator.Width, separator.Location.Y);
        leftCtrl.Width -= separator.Width;
        rightCtrl.Width += separator.Width;
        rightCtrl.Left = separator.Right;

    }

}

//=======================================================
//Service provided by Telerik (www.telerik.com)
//=======================================================

UPDATE

I've updated the codes above to simplify the reading, and I'm sharing this new video where you can see the design problem:

www.youtube.com/watch?v=-MhmyE3MZX0

1

There are 1 answers

9
γηράσκω δ' αεί πολλά διδασκόμε On BEST ANSWER

First, you need to get where the user clicked before the dragging,mouse down event of splitter control and total width of three controls:

Private mouse_Down As Point //you can use an integer also because y coordinate remains the same
Private totalWidth As Integer

//mouse down event
mouse_Down.X = e.MouseCursorX
totalWidth = seperator.Width + LeftControl.Width + RightControl.Width

Private Sub KryptonSeparator1_SplitterMoving(ByVal sender As Object, ByVal e As SplitterCancelEventArgs) Handles KryptonSeparator1.SplitterMoving

    Dim separator As KryptonSeparator = DirectCast(sender, KryptonSeparator)
    Dim leftCtrl As Control = Control1
    Dim rightCtrl As Control = Control2
    Dim leftWidth, rightWidth As Integer

    leftWidth = leftCtrl.Width + (e.MouseCursorX - mouse_Down.X)
    rightWidth = rightCtrl.Width - (e.MouseCursorX - mouse_Down.X)

    If leftWidth <= leftCtrl.MinimumSize.Width Then
        leftCtrl.Width = leftCtrl.MinimumSize.Width
        separator.Left = leftCtrl.Left + leftCtrl.MinimumSize.Width
        rightCtrl.Left = leftCtrl.Left + leftCtrl.MinimumSize.Width + separator.Width
        rightCtrl.Width = totalWidth - leftCtrl.MinimumSize.Width - separator.Width

        Return
    End If

    If rightWidth <= rightCtrl.MinimumSize.Width Then
        leftCtrl.Width = totalWidth - rightCtrl.MinimumSize.Width - separator.Width
        separator.Left = leftCtrl.Left + leftCtrl.Width
        rightCtrl.Left = leftCtrl.Left + leftCtrl.Width + separator.Width
        rightCtrl.Width = rightCtrl.MinimumSize.Width

        Return
    End If

    separator.Left += (e.MouseCursorX - mouse_Down.X)
    leftCtrl.Width = leftWidth
    rightCtrl.Width = rightWidth
    rightCtrl.Left = leftCtrl.Left + leftWidth + separator.Width

End Sub

EDIT

Try this:

//mouse down event
//mouse_Down.X = e.MouseCursorX
mouse_Down.X = MousePosition.X
mouse_Down.Y = MousePosition.Y
mouse_Down = seperator.PointToClient(mouse_Down)

totalWidth = seperator.Width + LeftControl.Width + RightControl.Width

and in SplitterMoving:

Dim leftWidth, rightWidth As Integer
Dim pnt As Point

pnt.X = MousePosition.X
pnt.Y = MousePosition.Y

pnt = seperator.PointToClient(pnt)

//replace e.MouseCursorX with pnt.X
... 

EDIT 2

Your logic of resizing the two windows have two minor bugs:

  1. Using e.MouseCursorX to determine the direction of the resizing(left or right) is wrong, eg you move the cursor to the left(left direction), remaining inside the separator, e.MouseCursorX is still positive, so you are resizing to the right(until of course e.MouseCursorX becomes negative) instead of left !
  2. Your code checks for the minimum size but does nothing when the comparison is false, meaning when the resulting size of the control is smaller. When that happens you need to actually set the size of the control eg lets say the minimum size is 50 and the controls size is 55. If the resize is very fast, the resulting size of the control may become 49. Your code does nothing(comparison is false) and the size of the control remains 55 instead of seting it to 50.

My solution solves both of these situations. However, the real issue of your horible effect as you said is not these two bugs. It is actually, the way too slow responsiveness of the application, when you resize the controls. To be more specific, when you resize and move the right control(ListBox_Files). You can check it your self if you drag and drop a small number(1 or 2) of files and see the result. It is a tremendous difference. That unfortunately tells me that you can not do anything about it. You need to change the logic of the resize. Two solutions:

  1. Use one control and custom draw everything, text, icons, vertical-horizontal scrollbars etc.. (not recommended!)
  2. Do what visual studio and other application is doing. Do not resize the controls until you release the button. Just show a vertical line:

enter image description here

enter image description here