C# と VB.NET の質問掲示板

ASP.NET、C++/CLI、Java 何でもどうぞ

ログ内検索
  • キーワードを複数指定する場合は 半角スペース で区切ってください。
  • 検索条件は、(AND)=[A かつ B] (OR)=[A または B] となっています。
  • [返信]をクリックすると返信ページへ移動します。
キーワード/ 検索条件 /
検索範囲/ 強調表示/ ON (自動リンクOFF)
結果表示件数/ 記事No検索/ ON
大文字と小文字を区別する

No.86661 の関連記事表示

<< 0 >>
■86661  コントロール単位でスクロールさせたい
□投稿者/ 大阪 -(2018/02/27(Tue) 00:25:26)

    分類:[.NET 全般] 

    環境:VB2010,Win7,WinFormアプリ

    FlowLayoutPanel(AutoScroll = False)内の垂直方向に配置されたコントロールを
    VScrollBarでコントロール単位でスクロールさせたいです。
    コンテナ内のコントロールのサイズはすべて同じという前提です。

    具体的には以下のコードのValueChangedイベントで_VScrollBar.Valueと同じインデックス
    のボタンをTop位置にスクロールさせたいです。
    ValueChangedイベントでどのような実装が必要か教えてください。

    Public Class Form1
    Private _max As Integer = 100
    WithEvents _VScrollBar As New VScrollBar
    Private Sub Form1_Load(sender As System.Object, e As System.EventArgs) Handles MyBase.Load
    With _VScrollBar
    .Maximum = _max
    .Minimum = 0
    .LargeChange = 10
    .SmallChange = 1
    .Value = 0
    .Dock = DockStyle.Right
    End With
    Dim FlowLayoutPanel1 As New FlowLayoutPanel
    With FlowLayoutPanel1
    .AutoScroll = False
    .Dock = DockStyle.Fill
    .WrapContents = False
    .FlowDirection = FlowDirection.TopDown
    End With
    For i As Integer = 0 To _max
    Dim btn As New Button
    btn.Text = i
    btn.Height = 50
    FlowLayoutPanel1.Controls.Add(btn)
    Next
    With Me
    .Controls.Add(FlowLayoutPanel1)
    .Controls.Add(_VScrollBar)
    .Text = 0
    End With
    End Sub

    Private Sub _VScrollBar_ValueChanged(sender As Object, e As System.EventArgs) Handles _VScrollBar.ValueChanged
    Me.Text = _VScrollBar.Value
    'ここで_VScrollBar.Valueと同じインデックスのボタンをTopに持ってきたいです。
    End Sub
    End Class
親記事 /過去ログ148より / 関連記事表示
削除チェック/

■86667  Re[1]: コントロール単位でスクロールさせたい
□投稿者/ 魔界の仮面弁士 -(2018/02/27(Tue) 10:09:03)
    No86661 (大阪 さん) に返信
    > FlowLayoutPanel(AutoScroll = False)内の垂直方向に配置されたコントロールを
    AutoScroll = True では駄目なのですか?
    自動的にスクロールバーが出るので、追加のコーディングが不要になりそうですが。

    それと、キーボード(ScrollUp/ScrollDown/上矢印/下矢印/Tab/Shift+Tab)による操作や、
    フォームのリサイズ(高さ変更)への追従、スクロール領域外のコントロールに
    フォーカスがあることを許容するかどうかなども検討しておく必要がありそうです。


    > 具体的には以下のコードのValueChangedイベントで_VScrollBar.Valueと同じインデックス
    > のボタンをTop位置にスクロールさせたいです。
    その仕様だと、最後のボタンを表示しきれない気もしますが、
    それはとりあえず後で考えるとして。


    Option Strict On
    Public Class Form1
      Private _max As Integer = 100
      Private FlowLayoutPanel1 As New FlowLayoutPanel() With {.AutoScroll = False, .Dock = DockStyle.Fill, .WrapContents = False, .FlowDirection = FlowDirection.TopDown}
      Private WithEvents _VScrollBar As New VScrollBar() With {.Maximum = _max, .Minimum = 0, .LargeChange = 10, .SmallChange = 1, .Value = 0, .Dock = DockStyle.Right}
      Private Buttons As New List(Of Button)()
      Private Sub Form1_Load(sender As System.Object, e As System.EventArgs) Handles MyBase.Load
        FlowLayoutPanel1.SuspendLayout()
        For i = 0 To _max
          Dim btn As New Button() With {.Text = i.ToString()}
          btn.Height = 50
          Buttons.Add(btn)
          FlowLayoutPanel1.Controls.Add(btn)
        Next
        Controls.Add(FlowLayoutPanel1)
        FlowLayoutPanel1.ResumeLayout(False)
        Controls.Add(_VScrollBar)
        Text = "0"
      End Sub

      Private Sub _VScrollBar_ValueChanged(sender As Object, e As System.EventArgs) Handles _VScrollBar.ValueChanged
        FlowLayoutPanel1.SuspendLayout()
        For i = _max To 0 Step -1
          Buttons(i).Visible = i >= _VScrollBar.Value
        Next
        FlowLayoutPanel1.ResumeLayout(True)
        Me.Text = _VScrollBar.Value.ToString()
      End Sub
    End Class


    上記は、Visible プロパティを切り替えることで、スクロールされたボタンを
    非表示にする方法で実装しています。

    フォーカスが失われることを嫌うなら、マイナス座標に別のコンテナを用意しておき、
    ボタンをそこに移動させるという手もありそうです。
記事No.86661 のレス /過去ログ148より / 関連記事表示
削除チェック/

■86672  Re[2]: コントロール単位でスクロールさせたい
□投稿者/ 大阪 -(2018/02/27(Tue) 12:14:31)
    No86667 (魔界の仮面弁士 さん) に返信
    ありがとうございます。
    提示頂いたコードで期待通りの動作をしました。
    
    > AutoScroll = True では駄目なのですか?
    特に駄目と云う事ではないですけど、コードから動的にコントロールを追加、削除を
    繰り返すような実装になっている場合、自動でスクロールバーが出たり消えたりする為、
    スクロールバーの有無でコントロールの幅が変わるので(縦スクロールバーの場合)、
    それが嫌なケースもあります。
    特に今回、何かアプリを作成しているわけではないので、具体的にといわれると困りますが... 
    
    
    > それと、キーボード(ScrollUp/ScrollDown/上矢印/下矢印/Tab/Shift+Tab)による操作や、
    マウスホイールと上下キーには以下のコードで対応しました。
    
    > フォームのリサイズ(高さ変更)への追従、
    フォームのリサイズ(高さ変更)への追従はちょっと意味がわかりませんでした。
    リサイズ時に問題がでそうな事項があれば、教えてください。
    
    > スクロール領域外のコントロールにフォーカスがあることを許容するかどうかなども検討しておく必要がありそうです。
    これはケースバイケースで対応します。
    
    
    > その仕様だと、最後のボタンを表示しきれない気もしますが、
    > それはとりあえず後で考えるとして。
    これは、質問した後、気付きました。
    これについては、VScrollBarのMaximumプロパティを変更する事で、対応しました。
    
    もし何か、お気づきの点があれば、ご指摘ください。
    
    Option Strict On
    Public Class Form1
        Private _max As Integer = 100
        Private WithEvents FlowLayoutPanel1 As New FlowLayoutPanel() With {.AutoScroll = False, .Dock = DockStyle.Fill, .WrapContents = False, .FlowDirection = FlowDirection.TopDown}
        Private WithEvents _VScrollBar As New VScrollBar() With {.Maximum = _max, .Minimum = 0, .LargeChange = 10, .SmallChange = 1, .Value = 0, .Dock = DockStyle.Right}
        Private Buttons As New List(Of Button)()
    
        Private Sub Form1_Load(sender As System.Object, e As System.EventArgs) Handles MyBase.Load
            FlowLayoutPanel1.SuspendLayout()
            For i = 0 To _max
                Dim btn As New Button() With {.Text = i.ToString()}
                btn.Height = 50
                AddHandler btn.PreviewKeyDown, AddressOf btn_PreviewKeyDown
                AddHandler btn.MouseWheel, AddressOf btn_MouseWheel
                Buttons.Add(btn)
                FlowLayoutPanel1.Controls.Add(btn)
            Next
            Controls.Add(FlowLayoutPanel1)
            FlowLayoutPanel1.ResumeLayout(False)
            Controls.Add(_VScrollBar)
            Text = "0"
            '最後のボタンを表示しきれない対応
            With _VScrollBar
                .Maximum = .Maximum + .LargeChange - 1
            End With
    
        End Sub
        Private Sub _VScrollBar_ValueChanged(sender As Object, e As System.EventArgs) Handles _VScrollBar.ValueChanged
            FlowLayoutPanel1.SuspendLayout()
            For i = _max To 0 Step -1
                Buttons(i).Visible = i >= _VScrollBar.Value
            Next
            FlowLayoutPanel1.ResumeLayout(True)
            Me.Text = _VScrollBar.Value.ToString()
        End Sub
    
        Private Sub btn_PreviewKeyDown(sender As Object, e As System.Windows.Forms.PreviewKeyDownEventArgs)
            Select Case e.KeyCode
                Case Keys.Up
                    _VScrollBar.Value = If(_VScrollBar.Value - 1 < 0, 0, _VScrollBar.Value - 1)
                Case Keys.Down
                    _VScrollBar.Value = If(_VScrollBar.Value + 1 > _max, _max, _VScrollBar.Value + 1)
            End Select
        End Sub
    
        Private Sub btn_MouseWheel(sender As Object, e As System.Windows.Forms.MouseEventArgs)
            Select Case Math.Sign(e.Delta)
                Case 1
                    _VScrollBar.Value = If(_VScrollBar.Value - 1 < 0, 0, _VScrollBar.Value - 1)
                Case -1
                    _VScrollBar.Value = If(_VScrollBar.Value + 1 > _max, _max, _VScrollBar.Value + 1)
            End Select
        End Sub
    End Class
    
    
記事No.86661 のレス /過去ログ148より / 関連記事表示
削除チェック/

■86674  Re[3]: コントロール単位でスクロールさせたい
□投稿者/ 魔界の仮面弁士 -(2018/02/27(Tue) 12:40:34)
    No86672 (大阪 さん) に返信
    >> その仕様だと、最後のボタンを表示しきれない気もしますが、
    > これは、質問した後、気付きました。
    > これについては、VScrollBarのMaximumプロパティを変更する事で、対応しました。

    VScrollBar のつまみを最下段まで下げたとしても、
    Value プロパティは最大値になりませんので、
    スクロールバーの可動粋は、それを考慮する必要がありますからね。


    > リサイズ時に問題がでそうな事項があれば、教えてください。

    フォームサイズが変われば、FlowLayoutPanel 内に
    表示可能なボタンの数も変わりますので、それを
    「VScrollBarのMaximumプロパティを変更する事」に
    追従させるか否かということです。


    また、最大値までスクロールさせた場合に、最後のボタンが
    最下段にあった方が良いのか、それとも
    最上段にあった方が良いのか(その下が空欄になる)でも
    スクロールバーに求める可動域が変化してくるでしょうね。
記事No.86661 のレス /過去ログ148より / 関連記事表示
削除チェック/

■86675  Re[4]: コントロール単位でスクロールさせたい
□投稿者/ 大阪 -(2018/02/27(Tue) 13:17:41)
    No86674 (魔界の仮面弁士 さん) に返信
    > フォームサイズが変われば、FlowLayoutPanel 内に
    > 表示可能なボタンの数も変わりますので、それを
    > 「VScrollBarのMaximumプロパティを変更する事」に
    > 追従させるか否かということです。
    解りました。
    ちなみに、コンテナに現在、表示されているコントロールの数を得る
    プロパティがあったりしますか?
    計算で得るにはコンテナやコントロールのパディングやマージンを考慮
    する必要がありますよね。

    > また、最大値までスクロールさせた場合に、最後のボタンが
    > 最下段にあった方が良いのか、それとも
    > 最上段にあった方が良いのか(その下が空欄になる)でも
    > スクロールバーに求める可動域が変化してくるでしょうね。
    AutoScroll = Trueだと、前者、現在のコードだと後者ということですね。
    これもケースバイケースで対応するようにします。
記事No.86661 のレス /過去ログ148より / 関連記事表示
削除チェック/

■86677  Re[5]: コントロール単位でスクロールさせたい
□投稿者/ 大阪 -(2018/02/27(Tue) 14:12:47)
    No86675 (大阪 さん) に返信
    > ちなみに、コンテナに現在、表示されているコントロールの数を得る
    > プロパティがあったりしますか?
    > 計算で得るにはコンテナやコントロールのパディングやマージンを考慮
    > する必要がありますよね。
    
    間違ってるかもしれないけど、以下で一応それらしい値は得られました。
    
    'LoadイベントでAddHandler btn.Click, AddressOf btn_Clickを追加
      Private Sub btn_Click(sender As System.Object, e As System.EventArgs)
            Dim realH As Integer = FlowLayoutPanel1.Height - FlowLayoutPanel1.Padding.Top - FlowLayoutPanel1.Padding.Bottom
            Dim btn As Button = DirectCast(sender, Button)
            Dim m As Integer = btn.Margin.Top + btn.Margin.Bottom
            MsgBox(FlowLayoutPanel1.Height / (m + btn.Height))
        End Sub
記事No.86661 のレス /過去ログ148より / 関連記事表示
削除チェック/

■86679  Re[6]: コントロール単位でスクロールさせたい
□投稿者/ 大阪 -(2018/02/27(Tue) 14:25:04)
    No86677 (大阪 さん) に返信
    > ■No86675 (大阪 さん) に返信
    訂正
    
      Private Sub btn_Click(sender As System.Object, e As System.EventArgs)
            Dim realH As Integer = FlowLayoutPanel1.Height - FlowLayoutPanel1.Padding.Top - FlowLayoutPanel1.Padding.Bottom
            Dim btn As Button = DirectCast(sender, Button)
            Dim m As Integer = btn.Margin.Top + btn.Margin.Bottom
    
            MsgBox(Math.Min(_max - _VScrollBar.Value + 1, realH / (m + btn.Height)))
        End Sub
記事No.86661 のレス /過去ログ148より / 関連記事表示
削除チェック/

■86692  Re[4]: コントロール単位でスクロールさせたい
□投稿者/ 大阪 -(2018/02/28(Wed) 09:28:38)
    魔界の仮面弁士 さん

    どうも、ありがとうございました。
    これで解決とさせて頂きます。
記事No.86661 のレス / END /過去ログ148より / 関連記事表示
削除チェック/



<< 0 >>

パスワード/

- Child Tree -