「.NET質問箱」では、「どぼん!のプログラミング掲示板」に書き込まれた.NETプログラミングに関する投稿を基に、さらに考察を加え、Q&A形式にまとめて紹介します。注意この記事の最新版は「DataGridをスクロールさせた時に、別のDataGridを同時にスクロールさせる」で公開しています。【質問】System.Windows.Forms.DataGridコントロールを垂直方向にスクロールした時に、別のDataGridも同時にスクロールされるようにしたいのですが、どのようにすればよいのでしょうか?【回答】まずDataGridコントロールが垂直方向にスクロールされたことを知るには、Scrollイベントを捕捉したり、プロテクトメンバのGridVScrolledメソッドをオーバーライドしたり、同じくプロテクトメンバのVertScrollBarプロパティのScrollイベントを捕捉したりする方法があります。GridVScrolledメソッドやVertScrollBarプロパティのScrollイベントを捕捉する場合は、注意が必要です。これらは、マウスのホイールを使ったスクロールや、カーソルキーによるスクロールには反応しません。よって、これらによるスクロールにも対応するためには、MouseWheelイベントなどの別の方法も併用する必要があります。DataGridを指定した行までスクロールさせるには、「DataGrid内の指定された行までスクロールする」で紹介している方法が使えます。DataGrid内の指定された行までスクロールする以下に同時スクロールを可能にするDataGridの例を示します。ここではScrollイベントによりDataGridがスクロールされたことを感知しています。GridVScrolledメソッドを使った例に関しては、この記事の最後に示す掲示板のログをご覧ください。ApplicationException("自分自身に設定できません。ApplicationException("自分自身に設定できません。}}このクラスを使用するには、DataGridコントロールをこのMyDataGridに置き換えます。ユーザーがスクロールするDataGridと、そのスクロールと同時にスクロールさせたいDataGridの両方にMyDataGridを使用します。ユーザーがスクロールするMyDataGridのSyncScrollGridプロパティに、同時にスクロールさせたいMyDataGridを指定します。両者のMyDataGridの行数は必ず同じにしてください。注意この記事の最新版は「DataGridを印刷する」で公開しています。印刷」という例が紹介されています。これらは残念ながら表示されている範囲のみしか印刷できず、それ以外を印刷するには、適当な位置までスクロールして印刷するという処理を繰り返す必要があります。それも正確に行うのは難いため、この方法は実用的とは言えないでしょう。Basic)実際に良く使われている方法は、DataGridで表示しているデータを自分で描画して印刷する方法です。この方法はかなり手間がかかりますが、自由度が高く、融通が利きます。ここではその方法を具体的には説明しません。このようにしてDataGridを印刷するためのクラスは数多く公開されています。以下にその幾つかを紹介させていただきますので、参考にしてください。注意この記事の最新版は「単位を変更して描画する」で公開しています。方法は、描画先のGraphicsオブジェクトのPageUnitプロパティを変更してから描画するという方法でしょう。PageUnitプロパティはページ座標で使用する長さの単位を指定するためのプロパティで、ページ変換(ページ座標からデバイス座標への変換)で使用されます。GDI+の座標系について詳しくは、MSDNの「座標系の種類」をご覧ください。座標系の種類PageUnitプロパティにはGraphicsUnit列挙体を指定しますが、GraphicsUnit列挙体には、以下のようなメンバーがあります(MSDNからの引用です)。これらの単位を指定できるわけです。1/75インチを長さの単位に指定します。ドキュメント単位(1/300インチ)を長さの単位に指定します。インチを長さの単位に指定します。ミリメートルを長さの単位に指定します。デバイスピクセルを長さの単位に指定します。プリンタポイント(1/72インチ)を長さの単位に指定します。ワールド単位を長さの単位に指定します。PageUnitプロパティを使った例を以下に示します。ここでは、フォームのOnPaintメソッドをオーバーライドすることにより、フォームに太さ0.1インチで4X2インチの長方形を描画しています。inch)を取得して、それを元にピクセル単位の長さを計算できるのであれば、そうすることもできます。dpiはその名の通り、1インチ内のピクセル数を表し、水平方向および垂直方向のdpiは、GraphicsクラスのDpiXとDpiYプロパティで取得することができます。Measurement」では、GetDeviceCaps関数を使ってdpiを取得する方法が紹介されています。ちなみにDpiXプロパティはGdipGetDpiX関数を使っているようです。Measurementこのような方法により、先ほどと同じようにインチ単位で描画する例を示します。redPen.Dispose();}このように長さをいちいち計算するのが面倒であれば、ScaleTransformメソッドにより、ワールド変換を使って解決することもできます。水平方向と垂直方向のdpiが同じであれば、PageScaleプロパティにより、ページ変換で行うこともできます。ScaleTransformメソッドを使った例を以下に示します。redPen.Dispose();}もちろんPageUnitプロパティが使えるならばこのような方法を使う必要はないと思いますが、PageUnitプロパティで指定できない単位を使いたい場合はこのような方法が必要になるでしょう。最後に蛇足ですが、寸単位で描画する例を示します。ここでは、DpiXとDpiYが同じものとし、PageScaleプロパティを使っています。注意この記事の最新版は「VB6のScaleHeight、ScaleWidthプロパティに代わるものは?」で公開しています。オブジェクトの変更点」によると、これらに代わるものはありません。座標の単位がピクセルの場合は、FormクラスのClientRectangleプロパティやClientSizeプロパティのHeight、Widthプロパティがその代わりとして使えます。オブジェクトの変更点ただし、コントロールの大きさをフォームの大きさに合わせて変える目的でScaleHeightとScaleWidthプロパティを使用するのであれば、DockやAnchorプロパティを使うのがよいでしょう。サポートされていない」によると、VB6のコードをVS.NETによりアップグレードすると、VB6.TwipsToPixelsXやTwipsToPixelsYを使って単位をtwipからピクセルに変換するようです。2Microsoft.VisualBasic.Compatibility.VB6.Support.TwipsToPixelsX(500)Microsoft.VisualBasic.Compatibility.VB6.Support.TwipsToPixelsY(800)のようにして呼び出します。これらのメソッドを使いたくないのであれば、次のようにしてTwipsPerPixelXとTwipsPerPixelYの値を計算することもできます。ここではフォームクラス内に記述するものとし、フォームのある画面のTwipsPerPixelXとTwipsPerPixelYの値を計算しています。g.DpiY;g.Dispose();しかしながら、TwipsToPixelsXやTwipsToPixelsYはできるだけ使わない方が良いでしょう。