トップ回答者
DataGridViewでピクセル単位で垂直スクロールをするには?

質問
-
解決していない質問を投稿中ではありますが、
別件で詰まってしまいましたので、質問させてください。
WindowsXP-sp3 VS.NET2005(VB)で開発しております。
デザイナからFormに貼り付けたDataGridViewにビットマップを表示しております。
大きなビットマップを表示し、AutoSizeで1セルの高さがDataGridViewの高さを超えるとき、
DataGridViewは垂直スクロールが行単位であるため、ビットマップの下の方を表示することができません。
水平スクロールは、列単位ではなくピクセル単位でスクロールできているようですが、
垂直方向もこのようにスクロールすることはできないでしょうか?
宜しくお願い致します。
回答
-
一番簡単なのは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
すべての返信
-
一番簡単なのは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