3

シナリオ

KryptonSeparatorを使用して助けが必要です。

下の画像のセパレーターを使用して、左右のコントロールの幅を変更したいと思います。

ここに画像の説明を入力

問題

問題は、セパレーターを左に移動しようとすると非常に邪魔な視覚効果が作成され、セパレーターを右に移動すると多かれ少なかれ同じことが起こりますが、左に移動するとはるかに顕著です (そして恐ろしい) ):

ここに画像の説明を入力

セパレーターを左に移動すると、イベントデータの代わりにセパレーターの幅を使用して計算に基づいているため、のeventargsを適切に使用していないと思いKryptonSeparatorます(適切に行う方法がわからないため)。

質問

サイズ変更の問題を解決するには、コードでどのような変更を行う必要がありますか?

コード

左と右の両方のコントロールにプロパティが割り当てられています。到達したMinimumSize場合はサイズ変更を停止しようとしています。MinimumSize.Width

これは、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

これは 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)
//=======================================================

アップデート

読みやすくするために上記のコードを更新しました。設計上の問題を確認できるこの新しいビデオを共有しています。

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

4

1 に答える 1

3

まず、ドラッグする前にユーザーがクリックした場所mouse down event of splitter controlと、次total widthの 3 つのコントロールを取得する必要があります。

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

編集

これを試して:

//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

とで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
... 

編集2

2 つのウィンドウのサイズを変更するロジックには、2 つの小さなバグがあります。

  1. を使用e.MouseCursorXしてサイズ変更の方向 (左または右) を決定するのは間違っています。たとえば、カーソルを左 (左方向)に移動し、セパレーター内に残ったまま、e.MouseCursorXまだ正であるため、にサイズ変更しています(もちろん e .MouseCursorX が負になる) の代わりに!
  2. コードは最小サイズをチェックしますが、比較がfalseの場合、つまりコントロールの結果のサイズが小さい場合は何もしません。その場合、実際にコントロールのサイズを設定する必要があります。たとえば、最小サイズが50で、コントロール サイズが55であるとします。サイズ変更が非常に高速な場合、結果としてコントロールのサイズが49になることがあります。コードは何もせず (比較は false)、コントロールのサイズは50に設定する代わりに55のままです。

私のソリューションは、これらの状況の両方を解決します。ただし、あなたが言ったように、あなたの恐ろしい影響の本当の問題は、これら2つのバグではありません. 実際には、コントロールのサイズを変更すると、アプリケーションの応答が遅すぎます。より具体的には、右のコントロール (ListBox_Files)のサイズを変更して移動する場合。少数 (1 つまたは 2 つ) のファイルをドラッグ アンド ドロップして結果を確認すると、自分で確認できます。それは途方もない違いです。残念ながら、それについては何もできないことがわかります。サイズ変更のロジックを変更する必要があります。2 つのソリューション:

  1. 1 つのコントロールを使用して、すべて、テキスト、アイコン、垂直/水平スクロールバーなどをカスタム描画します.. (お勧めしません!)
  2. Visual Studio や他のアプリケーションが行っていることを行います。ボタンを離すまで、コントロールのサイズを変更しないでください。垂直線を表示するだけです:

ここに画像の説明を入力

ここに画像の説明を入力

于 2014-12-01T17:54:29.173 に答える