12

C# および WinForms で VS2010 および .NET 4.0 を使用する:

パネルに垂直スクロールバーを無効なスクロールバーとして表示することを常に望んでいます(必要でない場合は、使用できる場合は有効なスクロールバーを表示します)。

つまり、ハイブリッド AutoScroll のようなものです。VScrollBars を使用してみましたが、これを機能させるために配置する場所がわかりません。

基本的に、コントロールの「ドキュメント」として機能するユーザーコントロールを持っています。そのサイズは変更されるため、自動スクロールを使用すると完全に機能します。ユーザーコントロールが収まらず、ユーザーが上下に移動できる場合、スクロールバーが表示されます。

基本的にはウェブブラウザのようなものです。ただし、コントロールの再描画には長い時間がかかります(パネル内のグリッド内のグループ内に多くのフィールドやボタンなどがあるフォームです:P

とにかく、自動スクロールが垂直スクロールバーを有効にすると、ウィンドウの再描画に時間がかかります。上記のように(有効化/無効化機能を使用して)垂直スクロールバーを常に表示したいと思います。

誰か助けがあれば、自動スクロールに関する多くの投稿を読みましたが、私が何を求めているのか誰も尋ねておらず、解決策を思い付くことができません。

4

6 に答える 6

4

パネルの自動スクロール機能を使用できます。垂直スクロールバーを表示するには、Windows メッセージを送信するだけです。

<DllImport("user32.dll")> _
Public Shared Function ShowScrollBar(ByVal hWnd As System.IntPtr, ByVal wBar As Integer, ByVal bShow As Boolean) As Boolean
End Function

Private Const SB_VERT As Integer = 1


Public Sub New()

    ' This call is required by the designer.
    InitializeComponent()

    ShowScrollBar(Panel1.Handle, SB_VERT, True)
End Sub

スクロールバーが表示され、スクロールできるように見えますが、実際にスクロールできるようになるまで何もしません。無効にすると、自動的に再度有効になることはないため、これがおそらく最善の方法です。

また、サイズ変更中のパフォーマンスを向上させるために、更新前にパネルでSuspendLayoutを呼び出し、完了したらResumeLayoutを呼び出すことができます。

于 2011-12-31T21:47:21.620 に答える
3

私にとってうまくいったのは、CreateParams呼び出しをオーバーライドしてWS_VSCROLLスタイルを有効にすることでした。

public class VerticalFlowPanel : FlowLayoutPanel
{
    protected override CreateParams CreateParams
    {
        get
        {
            var cp = base.CreateParams;
            cp.Style |= 0x00200000; // WS_VSCROLL
            return cp;
        }
    }
}

AutoScrollロジックは、スクロールバーを非表示にすることなくスクロール境界を調整するようになりました。

于 2016-08-17T22:05:26.440 に答える
1

これが私にとってこれを解決したものです。私の場合は、別の 3 つのパネルの間にパネルが挟まれており、どの方向にも自由度がありません。このパネルは、構造全体が 1920x1080 の画面からはみ出すほど大きくする必要がありました。解決策は実際には非常に簡単です。スクロール バーが必要なパネルでは、AutoScroll プロパティを true に設定します。次に、右端の一番下の位置 (右下の位置) に別のコントロールを追加します。私が選択したコントロールは、私が非表示にしたラベルです....そして、それだけです。現在、パネルは制限された領域を占有していますが、必要なサイズまでスクロールして、必要なサイズで使用できます。水平スクロール バーのみが必要な場合は、非表示のコントロールを左の外側に追加し、垂直方向のみを一番下に追加します。

パネルの実際のサイズは、表示時に制限したサイズですが、仮想サイズは非表示のコントロールによって決まります。

于 2016-08-11T23:11:11.233 に答える
0

このコードは、パネルの組み込みスクロールバーが非表示の場合は常に、無効な垂直スクロールバーを描画します。コードはそれを前提としています

AutoScroll = true;
AutoSize   = false;

次のコードは速度が最適化されています。OnPaint() でできるだけ少ないことを行います。

Panel からクラスを派生させます。次のメンバー変数を追加します。

// NOTE: static variables are not thread safe. 
// But as we have only one GUI thread this does not matter.
static IntPtr mh_ScrollTheme   = IntPtr.Zero;
static int    ms32_ScrollWidth = SystemInformation.VerticalScrollBarWidth;

Win32.RECT mk_ScrollTop;
Win32.RECT mk_ScrollBot;   // coordinates of top scrollbar button
Win32.RECT mk_ScrollShaft; // coordinates of bottom scrollbar button

次に、OnSizeChanged をオーバーライドします。

protected override void OnSizeChanged(EventArgs e)
{
    base.OnSizeChanged(e);

    Win32.RECT k_ScrollBar = new Win32.RECT(ClientRectangle);
    k_ScrollBar.Left = k_ScrollBar.Right - ms32_ScrollWidth;

    mk_ScrollTop   = new Win32.RECT(k_ScrollBar);
    mk_ScrollBot   = new Win32.RECT(k_ScrollBar);
    mk_ScrollShaft = new Win32.RECT(k_ScrollBar);

    int s32_Upper = k_ScrollBar.Top    + ms32_ScrollWidth;
    int s32_Lower = k_ScrollBar.Bottom - ms32_ScrollWidth;

    mk_ScrollTop  .Bottom = s32_Upper;
    mk_ScrollBot  .Top    = s32_Lower;
    mk_ScrollShaft.Top    = s32_Upper;
    mk_ScrollShaft.Bottom = s32_Lower;
}

必要に応じてスクロールバーをペイントします。

protected override void OnPaint(PaintEventArgs e)
{
    base.OnPaint(e);

    if (VScroll)
        return; // The 'real' scrollbar is visible
            
    if (mh_ScrollTheme == IntPtr.Zero)
        mh_ScrollTheme = Win32.OpenThemeData(Handle, "SCROLLBAR");

    if (mh_ScrollTheme == IntPtr.Zero)
        return; // The user has disabled themes

    // Draw the disabled vertical scrollbar.
    IntPtr h_DC = e.Graphics.GetHdc();

    // Draw shaft
    const int SBP_UPPERTRACKVERT = 7;
    const int SCRBS_DISABLED     = 4;
    Win32.DrawThemeBackground(mh_ScrollTheme, h_DC, SBP_UPPERTRACKVERT, SCRBS_DISABLED, ref mk_ScrollShaft, IntPtr.Zero);

    // Draw top button
    const int SBP_ARROWBTN       = 1;
    const int ABS_UPDISABLED     = 4;
    Win32.DrawThemeBackground(mh_ScrollTheme, h_DC, SBP_ARROWBTN, ABS_UPDISABLED,   ref mk_ScrollTop,  IntPtr.Zero);

    // Draw lower button
    const int ABS_DOWNDISABLED   = 8;
    Win32.DrawThemeBackground(mh_ScrollTheme, h_DC, SBP_ARROWBTN, ABS_DOWNDISABLED, ref mk_ScrollBot,  IntPtr.Zero);

    e.Graphics.ReleaseHdc(h_DC);
}
于 2020-08-18T21:35:22.650 に答える