none
DataGridViewでピクセル単位で垂直スクロールをするには? RRS feed

  • 質問

  • 解決していない質問を投稿中ではありますが、
    別件で詰まってしまいましたので、質問させてください。

    WindowsXP-sp3   VS.NET2005(VB)で開発しております。

    デザイナからFormに貼り付けたDataGridViewにビットマップを表示しております。
    大きなビットマップを表示し、AutoSizeで1セルの高さがDataGridViewの高さを超えるとき、
    DataGridViewは垂直スクロールが行単位であるため、ビットマップの下の方を表示することができません。

    水平スクロールは、列単位ではなくピクセル単位でスクロールできているようですが、
    垂直方向もこのようにスクロールすることはできないでしょうか?

    宜しくお願い致します。
    2009年6月25日 5:39

回答

  • 一番簡単なのはImageLayoutプロパティをDataGridViewImageCellLayout.Zoomにしてやる。
    拡大縮小がダメなら、画像のセルをクリックしたらDataGridView以外に配置したPictureBoxに表示させる。
    セルに表示しないとだめなら、スクロールで全体を見せようとせずに、画像をセルに表示させる方法をカスタマイズしたほうが楽だと思います
    #ピクセル単位で垂直スクロールをはすごく大変だと思う
    ''' <summary>マウスで表示画像を平行移動させることが出来るDataGridViewImageCell</summary>
    Friend Class DGVImageSlideCell
        Inherits DataGridViewImageCell
    
        Private beginPoint As Point
        Private slide As Point = Point.Empty
        Private sliding As Boolean
        Private _IsSlideMode As Boolean
    
        ''' <summary>画像をスライドさせることが出来る状態になっているか</summary>
        Private ReadOnly Property IsSlideMode() As Boolean
            Get
                Return (Me.ImageLayout = DataGridViewImageCellLayout.NotSet) OrElse (Me.ImageLayout = DataGridViewImageCellLayout.Normal)
            End Get
        End Property
    
        Protected Overrides Sub OnMouseDown(ByVal e As System.Windows.Forms.DataGridViewCellMouseEventArgs)
            MyBase.OnMouseDown(e)
            If (IsSlideMode) Then
                sliding = True
                beginPoint = e.Location
    
                'カーソルを十字にしてかつ移動範囲をセルの中だけに制限
                Cursor.Current = Cursors.SizeAll
                Dim clip As Rectangle = Me.DataGridView.GetCellDisplayRectangle(Me.ColumnIndex, Me.RowIndex, True)
                clip.Offset(Me.DataGridView.PointToScreen(Point.Empty))
                Cursor.Clip = clip
            End If
        End Sub
        Protected Overrides Sub OnMouseUp(ByVal e As System.Windows.Forms.DataGridViewCellMouseEventArgs)
            MyBase.OnMouseUp(e)
            If (IsSlideMode AndAlso sliding) Then
    
                'スライド量を反映して描画更新
                sliding = False
                slide.Offset(beginPoint.X - e.Location.X, beginPoint.Y - e.Location.Y)
                Cursor.Current = Me.DataGridView.Cursor
    
                Me.DataGridView.UpdateCellValue(Me.ColumnIndex, Me.RowIndex)
            End If
        End Sub
    
        Protected Overrides Sub OnMouseDoubleClick(ByVal e As System.Windows.Forms.DataGridViewCellMouseEventArgs)
            'ダブルクリックで原点復帰
            slide = Point.Empty
            If (IsSlideMode) Then
                Me.DataGridView.UpdateCellValue(Me.ColumnIndex, Me.RowIndex)
            End If
            MyBase.OnMouseDoubleClick(e)
        End Sub
    
        Protected Overrides Sub OnLeave(ByVal rowIndex As Integer, ByVal throughMouseClick As Boolean)
            'カレントセルじゃなくなったら原点復帰
            slide = Point.Empty
            MyBase.OnLeave(rowIndex, throughMouseClick)
        End Sub
    
        Protected Overrides Sub Paint(ByVal graphics As System.Drawing.Graphics, ByVal clipBounds As System.Drawing.Rectangle, ByVal cellBounds As System.Drawing.Rectangle, ByVal rowIndex As Integer, ByVal elementState As System.Windows.Forms.DataGridViewElementStates, ByVal value As Object, ByVal formattedValue As Object, ByVal errorText As String, ByVal cellStyle As System.Windows.Forms.DataGridViewCellStyle, ByVal advancedBorderStyle As System.Windows.Forms.DataGridViewAdvancedBorderStyle, ByVal paintParts As System.Windows.Forms.DataGridViewPaintParts)
            If IsSlideMode AndAlso Not (Point.Equals(slide, Point.Empty)) Then
                'スライドしていたら画像の
                Dim rect As New Rectangle(cellBounds.X + 1, cellBounds.Y + 1, cellBounds.Width - 2, cellBounds.Height - 2)
                MyBase.Paint(graphics, clipBounds, cellBounds, rowIndex, elementState, Nothing, Nothing, errorText, cellStyle, advancedBorderStyle, paintParts)
                graphics.DrawImage(CType(formattedValue, System.Drawing.Image), rect, slide.X, slide.Y, rect.Width, rect.Height, GraphicsUnit.Pixel)
            Else
                MyBase.Paint(graphics, clipBounds, cellBounds, rowIndex, elementState, value, formattedValue, errorText, cellStyle, advancedBorderStyle, paintParts)
            End If
        End Sub
    End Class
    
    '''' <summary>マウスで表示画像を平行移動させることが出来るDataGirdViewColumn</summary>
    'Friend Class DGVImageSlideColumn
    '    Inherits DataGridViewImageColumn
    '    Public Sub New()
    '        Me.CellTemplate = New DGVImageSlideCell
    '    End Sub
    'End Class
    
    Friend Class Form1
        Protected Overrides Sub OnLoad(ByVal e As System.EventArgs)
            MyBase.OnLoad(e)
    
            Dim dgv As New DataGridView
            dgv.Dock = DockStyle.Fill
            Me.Controls.Add(dgv)
    
            Dim column As New DataGridViewImageColumn
            column.CellTemplate = New DGVImageSlideCell()
            column.AutoSizeMode = DataGridViewAutoSizeColumnMode.AllCells
            dgv.Columns.Add(column)
    
            'テスト画像
            Dim img As New Bitmap(1000, 1000)
            Using g As System.Drawing.Graphics = Graphics.FromImage(img)
                Dim rnd As New System.Random()
                g.FillRectangle(Brushes.White, 0, 0, 999, 999)
                For i As Integer = 0 To 999
                    g.DrawArc(Pens.Red, rnd.Next(999), rnd.Next(999), rnd.Next(10, 100), rnd.Next(10, 100), 0, 360)
                Next
    
            End Using
            dgv.Rows.Add(img)
            dgv.Rows.Add()
        End Sub
    End Class

    • 回答としてマーク Camui 2009年6月27日 2:32
    2009年6月26日 11:55

すべての返信

  • 一番簡単なのはImageLayoutプロパティをDataGridViewImageCellLayout.Zoomにしてやる。
    拡大縮小がダメなら、画像のセルをクリックしたらDataGridView以外に配置したPictureBoxに表示させる。
    セルに表示しないとだめなら、スクロールで全体を見せようとせずに、画像をセルに表示させる方法をカスタマイズしたほうが楽だと思います
    #ピクセル単位で垂直スクロールをはすごく大変だと思う
    ''' <summary>マウスで表示画像を平行移動させることが出来るDataGridViewImageCell</summary>
    Friend Class DGVImageSlideCell
        Inherits DataGridViewImageCell
    
        Private beginPoint As Point
        Private slide As Point = Point.Empty
        Private sliding As Boolean
        Private _IsSlideMode As Boolean
    
        ''' <summary>画像をスライドさせることが出来る状態になっているか</summary>
        Private ReadOnly Property IsSlideMode() As Boolean
            Get
                Return (Me.ImageLayout = DataGridViewImageCellLayout.NotSet) OrElse (Me.ImageLayout = DataGridViewImageCellLayout.Normal)
            End Get
        End Property
    
        Protected Overrides Sub OnMouseDown(ByVal e As System.Windows.Forms.DataGridViewCellMouseEventArgs)
            MyBase.OnMouseDown(e)
            If (IsSlideMode) Then
                sliding = True
                beginPoint = e.Location
    
                'カーソルを十字にしてかつ移動範囲をセルの中だけに制限
                Cursor.Current = Cursors.SizeAll
                Dim clip As Rectangle = Me.DataGridView.GetCellDisplayRectangle(Me.ColumnIndex, Me.RowIndex, True)
                clip.Offset(Me.DataGridView.PointToScreen(Point.Empty))
                Cursor.Clip = clip
            End If
        End Sub
        Protected Overrides Sub OnMouseUp(ByVal e As System.Windows.Forms.DataGridViewCellMouseEventArgs)
            MyBase.OnMouseUp(e)
            If (IsSlideMode AndAlso sliding) Then
    
                'スライド量を反映して描画更新
                sliding = False
                slide.Offset(beginPoint.X - e.Location.X, beginPoint.Y - e.Location.Y)
                Cursor.Current = Me.DataGridView.Cursor
    
                Me.DataGridView.UpdateCellValue(Me.ColumnIndex, Me.RowIndex)
            End If
        End Sub
    
        Protected Overrides Sub OnMouseDoubleClick(ByVal e As System.Windows.Forms.DataGridViewCellMouseEventArgs)
            'ダブルクリックで原点復帰
            slide = Point.Empty
            If (IsSlideMode) Then
                Me.DataGridView.UpdateCellValue(Me.ColumnIndex, Me.RowIndex)
            End If
            MyBase.OnMouseDoubleClick(e)
        End Sub
    
        Protected Overrides Sub OnLeave(ByVal rowIndex As Integer, ByVal throughMouseClick As Boolean)
            'カレントセルじゃなくなったら原点復帰
            slide = Point.Empty
            MyBase.OnLeave(rowIndex, throughMouseClick)
        End Sub
    
        Protected Overrides Sub Paint(ByVal graphics As System.Drawing.Graphics, ByVal clipBounds As System.Drawing.Rectangle, ByVal cellBounds As System.Drawing.Rectangle, ByVal rowIndex As Integer, ByVal elementState As System.Windows.Forms.DataGridViewElementStates, ByVal value As Object, ByVal formattedValue As Object, ByVal errorText As String, ByVal cellStyle As System.Windows.Forms.DataGridViewCellStyle, ByVal advancedBorderStyle As System.Windows.Forms.DataGridViewAdvancedBorderStyle, ByVal paintParts As System.Windows.Forms.DataGridViewPaintParts)
            If IsSlideMode AndAlso Not (Point.Equals(slide, Point.Empty)) Then
                'スライドしていたら画像の
                Dim rect As New Rectangle(cellBounds.X + 1, cellBounds.Y + 1, cellBounds.Width - 2, cellBounds.Height - 2)
                MyBase.Paint(graphics, clipBounds, cellBounds, rowIndex, elementState, Nothing, Nothing, errorText, cellStyle, advancedBorderStyle, paintParts)
                graphics.DrawImage(CType(formattedValue, System.Drawing.Image), rect, slide.X, slide.Y, rect.Width, rect.Height, GraphicsUnit.Pixel)
            Else
                MyBase.Paint(graphics, clipBounds, cellBounds, rowIndex, elementState, value, formattedValue, errorText, cellStyle, advancedBorderStyle, paintParts)
            End If
        End Sub
    End Class
    
    '''' <summary>マウスで表示画像を平行移動させることが出来るDataGirdViewColumn</summary>
    'Friend Class DGVImageSlideColumn
    '    Inherits DataGridViewImageColumn
    '    Public Sub New()
    '        Me.CellTemplate = New DGVImageSlideCell
    '    End Sub
    'End Class
    
    Friend Class Form1
        Protected Overrides Sub OnLoad(ByVal e As System.EventArgs)
            MyBase.OnLoad(e)
    
            Dim dgv As New DataGridView
            dgv.Dock = DockStyle.Fill
            Me.Controls.Add(dgv)
    
            Dim column As New DataGridViewImageColumn
            column.CellTemplate = New DGVImageSlideCell()
            column.AutoSizeMode = DataGridViewAutoSizeColumnMode.AllCells
            dgv.Columns.Add(column)
    
            'テスト画像
            Dim img As New Bitmap(1000, 1000)
            Using g As System.Drawing.Graphics = Graphics.FromImage(img)
                Dim rnd As New System.Random()
                g.FillRectangle(Brushes.White, 0, 0, 999, 999)
                For i As Integer = 0 To 999
                    g.DrawArc(Pens.Red, rnd.Next(999), rnd.Next(999), rnd.Next(10, 100), rnd.Next(10, 100), 0, 360)
                Next
    
            End Using
            dgv.Rows.Add(img)
            dgv.Rows.Add()
        End Sub
    End Class

    • 回答としてマーク Camui 2009年6月27日 2:32
    2009年6月26日 11:55
  • >gekka

    ピクセル単位での垂直スクロール難しいのですね。
    プロパティを変更する程度で、簡単にできるものと考えておりました・・・。

    教えて頂いたいくつかの対処法で、検討したいと思います。

    ありがとうございました。
    2009年6月27日 2:31