3

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

ElektroStudios
  • 19,105
  • 33
  • 200
  • 417
  • Can you grab the other "visual effect" separators? Because if so, it can be because you define a separator everytime you drag. – Visual Vincent Nov 30 '14 at 09:58
  • Please, see the code example or the video at the bottom of the question, you'll see that the effect only remains while I'm moving the (unique) separator and only when I move it to the left. thanks for comment! – ElektroStudios Nov 30 '14 at 10:34
  • Why dont you use *MouseCursorX* for both directions? It works for the right one. – γηράσκω δ' αεί πολλά διδασκόμε Nov 30 '14 at 19:11
  • @γηράσκω δ' αεί πολλά διδασκόμε yes I think that is where I fail, just because moving it to the left I've tried to calculate it using MouseCursorX but I didn't get the expected result, maths are not my best. sorry for my english – ElektroStudios Dec 01 '14 at 07:28
  • Two questions: 1. If you are handling the *SplitterMoving* event why do you manually set the *seperator* location also? Aren't splitter and seperator the same control? 2. What *e.MouseCursorX* represents? – γηράσκω δ' αεί πολλά διδασκόμε Dec 01 '14 at 15:28
  • @γηράσκω δ' αεί πολλά διδασκόμε 1) Yes they are the same control, but the event does not makes the control to be moved, the event is only fired to let the user move manually the controls using/calculating the eventdata args. 2) `MousecursorX`: `Gets the X coordinate of the mouse pointer in client coordinates.`, also it has other property: `SplitX`: `Gets or sets the X coordinate of the upper left corner of the System.Windows.Forms.SplitContainer in client coordinates`. And of course also has a `MouseCursorY` and `SplitY`. – ElektroStudios Dec 01 '14 at 16:26
  • That is explained in the first url of my question: As the user moves the mouse over the control it changes the mouse cursor to indicate that it provides splitter functionality. If you press the mouse and start dragging then you see feedback drawn over the application that shows what change will occur if you release the mouse. – ElektroStudios Dec 01 '14 at 16:27
  • The KryptonSeparator does not actually do anything when you release the mouse at the end of the drag as there is no way for the control to know what other controls should be resized and positioned. Instead it generates events that you can monitor and once the drag ends you use that event to decide what action to take. – ElektroStudios Dec 01 '14 at 16:28

1 Answers1

3

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

  • it does not work, when I click the separator it is moved some pixels to the right and then I can't move it more to any side. where I should put the two instructions that you left outside the sub? maybe I'm failling with that bcause The MouseDown event of the separator does not sends a MouseCursorX. – ElektroStudios Dec 01 '14 at 18:44
  • One question because your other questions: Are you using the KryptonToolkit to test the results?, if not then you can find the necessary in my sourcecode also with the separator and all that: http://www.mediafire.com/download/1ynuba8zd6uqnqa/BakgroundWorker.rar – ElektroStudios Dec 01 '14 at 18:45
  • @ElektroStudios I dont have *KryptonToolkit* thats why I dont know the events. In a winform control, in mouse down event there is `e.X and e.Y coordinates`. I thought that there where the same as *SplitterMoving* thats why I used `e.MouseCursorX`. Change it to *e.X* – γηράσκω δ' αεί πολλά διδασκόμε Dec 01 '14 at 18:51
  • I did it, but happens the same of my comment above :(. anyways it says that the e.X is the mouse coordinates as is – ElektroStudios Dec 01 '14 at 18:57
  • @ElektroStudios Remove the two *if* statements and see if the same is happening – γηράσκω δ' αεί πολλά διδασκόμε Dec 01 '14 at 18:59
  • yes, the same happens removing them, I wonder you have an idea of why is happening this. PS: The source code could help you because inside is the krypton lib and is the application of this question, thanks a lot for your help – ElektroStudios Dec 01 '14 at 19:01
  • Tested and did the changes you've said, but still happens the same, I just can move the separator some pixels to right side, after that I can't move the separator more to any side. – ElektroStudios Dec 01 '14 at 19:37
  • @ElektroStudios See the values of `mouse_Down.X` and 'pnt.X' while dragging. Use a textbox: `textbox.Text = mouse_Down.X.ToString() + " " + pnt.X.ToString()` – γηράσκω δ' αεί πολλά διδασκόμε Dec 01 '14 at 19:42
  • Sorry I dont have more time, we continue tomorrow, thanks for the help! – ElektroStudios Dec 01 '14 at 20:46