.NETプログラミング研究 第54号

お知らせ

CodeZineがプレオープン

開発者のための実装系Webマガジン「CodeZine」がプレオープンしました。CodeZineは今までの日本のサイトにはあまりない一般読者が記事を投稿できるタイプのサイトで、.NET関係のカテゴリも用意されています。私「どぼん!」も記事を登録させていただいていますので、興味のある方はぜひ覗いてみてください。

以下が私の書いた記事です。

.NET質問箱

「.NET質問箱」では、「どぼん!のプログラミング掲示板」に書き込まれた.NETプログラミングに関する投稿を基に、さらに考察を加え、Q&A形式にまとめて紹介します。

表示色を反転して線を引くには?

注意

この記事の最新版は「表示色を反転して線を引く」で公開しています。

【質問】

VB6では、ピクチャボックスのDrawModeプロパティをvbInvert(6)としてから線を描画することにより表示色を反転して出力できましたが、同じことを.NETで行うにはどのようにしたらよいのでしょうか?

【回答】

.NETでは、ControlPaintクラスのDrawReversibleLineメソッドを使うことにより、表示色を反転して線を引くことができます。また、ControlPaintクラスのDrawReversibleFrameメソッドにより枠を、FillReversibleRectangleメソッドにより塗りつぶされた四角を描くことができます。

なおこれらのメソッドは画面に描画するもので、指定する座標も画面座標です。よって例えばPictureBoxでの座標を指定したい場合は、PointToScreenメソッドなどでクライアント座標から画面座標を計算しなければなりません。

次の例では、ピクチャボックス「PictureBox1」の座標(20, 10)-(200, 100)に反転した線を引いています。

  1
  2
  3
  4
  5
  6
'PictureBox1の(20, 10)-(200, 100)に反転した線を引く
'PictureBox1上の座標を画面座標に変換する
Dim startPoint As Point = PictureBox1.PointToScreen(New Point(20, 10))
Dim endPoint As Point = PictureBox1.PointToScreen(New Point(200, 100))
'黒で反転した線を引く
ControlPaint.DrawReversibleLine(startPoint, endPoint, Color.Black)
  1
  2
  3
  4
  5
  6
//PictureBox1の(20, 10)-(200, 100)に反転した線を引く
//PictureBox1上の座標を画面座標に変換する
Point startPoint = PictureBox1.PointToScreen(new Point(20, 10));
Point endPoint = PictureBox1.PointToScreen(new Point(200, 100));
//黒で反転した線を引く
ControlPaint.DrawReversibleLine(startPoint, endPoint, Color.Black);

○この記事の基になった掲示板のスレッド

クリップボードにファイルをコピーする、またはクリップボードからファイルを取得するには?

注意

この記事の最新版は「クリップボードにファイルをコピーする、クリップボードからファイルを取得する」で公開しています。

【質問】

エクスプローラでコピーしたファイルのパスを取得するにはどのようにすればよいのでしょうか?また、指定したファイルをクリップボードへコピーすることはできますか?

【回答】

DOBON.NET .NET Tipsの「クリップボードに文字列をコピー、クリップボードから文字列を取得」で紹介しているのと同じように、Clipboard.GetDataObjectメソッドを使うことにより、エクスプローラでコピーしたファイルのパスを取得できます。IDataObject.GetDataメソッドでデータを抽出する際にはDataFormats.FileDropデータ形式を指定し、文字列配列として取得します。

次のコードでは、クリップボードにファイルがコピーされている時にそのパスを取得し、出力しています。

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
'クリップボードのデータを取得する
Dim iData As IDataObject = Clipboard.GetDataObject()
'クリップボードにファイルドロップ形式のデータがあるか確認
If iData.GetDataPresent(DataFormats.FileDrop) Then
    'データを取得する
    Dim fileNames As String() = _
        CType(iData.GetData(DataFormats.FileDrop), String())
    '取得したファイル名を列挙する
    Dim fileName As String
    For Each fileName In fileNames
        Console.WriteLine(fileName)
    Next fileName
End If
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
//クリップボードのデータを取得する
IDataObject iData = Clipboard.GetDataObject();
//クリップボードにファイルドロップ形式のデータがあるか確認
if (iData.GetDataPresent(DataFormats.FileDrop))
{
    //データを取得する
    string[] fileNames = (string[]) iData.GetData(DataFormats.FileDrop);
    //取得したファイル名を列挙する
    foreach (string fileName in fileNames)
    {
        Console.WriteLine(fileName);
    }
}

ファイルをクリップボードにコピーする時も同様に、Clipboard.SetDataObjectメソッドを使用し、DataFormats.FileDropデータ形式のDataObjectオブジェクトをクリップボードに貼り付けます。この様にしてクリップボードに貼り付けたファイルはエクスプローラでペーストできます。

  1
  2
  3
  4
  5
  6
'コピーするファイルのパス
Dim fileNames As String() = {"C:\1.txt", "C:\2.txt", "C:\3.txt"}
'ファイルドロップ形式のDataObjectを作成する
Dim iData = New DataObject(DataFormats.FileDrop, fileNames)
'クリップボードにコピーする
Clipboard.SetDataObject(iData)
  1
  2
  3
  4
  5
  6
//コピーするファイルのパス
string[] fileNames = {"C:\\1.txt", "C:\\2.txt", "C:\\3.txt"};
//ファイルドロップ形式のDataObjectを作成する
IDataObject iData = new DataObject(DataFormats.FileDrop, fileNames);
//クリップボードにコピーする
Clipboard.SetDataObject(iData);

○この記事の基になった掲示板のスレッド

システム時計の日時を設定するには?

注意

この記事の最新版は「システム時計の日時を設定する」で公開しています。

【質問】

システム時計の日時を設定するには、どのようにすればよいのでしょうか?

【回答】

システム日時を勝手に変更してしまうことがよいことかという議論は置いておき、システム日時を変更する方法を2つ紹介します。

VB.NETでは、Todayプロパティ及びDateStringプロパティでシステム日付を、TimeOfDayプロパティ及びTimeStringプロパティでシステム時刻を設定できます。VB.NET以外でもMicrosoft.VisualBasic.dllを参照することにより、これらのプロパティにアクセスできます。

  1
  2
  3
  4
  5
  6
  7
  8
  9
'システム日付を2005/1/2にする
Today = New DateTime(2005, 1, 2, 0, 0, 0)
'システム日付を2005/2/3にする
DateString = "2005-2-3"
 
'システム時刻を6:15:30にする
TimeOfDay = New DateTime(2000, 1, 1, 6, 15, 30)
'システム時刻を8:25:45にする
TimeString = "8:25:45"
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
//システム日付を2005/1/2にする
Microsoft.VisualBasic.DateAndTime.Today =
    new DateTime(2005, 1, 2, 0, 0, 0);
//システム日付を2005/2/3にする
Microsoft.VisualBasic.DateAndTime.DateString =
    "2005-2-3";
 
//システム時刻を6:15:30にする
Microsoft.VisualBasic.DateAndTime.TimeOfDay =
    new DateTime(2000, 1, 1, 6, 15, 30);
//システム時刻を8:25:45にする
Microsoft.VisualBasic.DateAndTime.TimeString =
    "8:25:45";

また、Win32 APIのSetLocalTime関数を使用してシステム日時を変更することもできます。下のSetNowDateTimeメソッドは、DateTime型で日時を指定してシステム日時を変更するメソッドです。

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
<StructLayout(LayoutKind.Sequential)> _
Public Structure SystemTime
    Public wYear As Short
    Public wMonth As Short
    Public wDayOfWeek As Short
    Public wDay As Short
    Public wHour As Short
    Public wMinute As Short
    Public wSecond As Short
    Public wMiliseconds As Short
End Structure
 
<DllImport("kernel32.dll")> _
Public Shared Function SetLocalTime( _
    ByRef sysTime As SystemTime) As Boolean
End Function
 
'/ <summary>
'/ 現在のシステム日時を設定する
'/ </summary>
'/ <param name="dt">設定する日時</param>
Public Shared Sub SetNowDateTime(ByVal dt As DateTime)
    'システム日時に設定する日時を指定する
    Dim sysTime As New SystemTime
    sysTime.wYear = dt.Year
    sysTime.wMonth = dt.Month
    sysTime.wDay = dt.Day
    sysTime.wHour = dt.Hour
    sysTime.wMinute = dt.Minute
    sysTime.wSecond = dt.Second
    sysTime.wMiliseconds = dt.Millisecond
 
    'システム日時を設定する
    SetLocalTime(sysTime)
End Sub
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
//using System.Runtime.InteropServices;
 
[StructLayout(LayoutKind.Sequential)]
public struct SystemTime
{
    public ushort wYear;
    public ushort wMonth;
    public ushort wDayOfWeek;
    public ushort wDay;
    public ushort wHour;
    public ushort wMinute;
    public ushort wSecond;
    public ushort wMiliseconds;
}
 
[DllImport("kernel32.dll")]
public static extern bool SetLocalTime(
    ref SystemTime sysTime);
 
/// <summary>
/// 現在のシステム日時を設定する
/// </summary>
/// <param name="dt">設定する日時</param>
public static void SetNowDateTime(DateTime dt)
{
    //システム日時に設定する日時を指定する
    SystemTime sysTime = new SystemTime();
    sysTime.wYear = (ushort) dt.Year;
    sysTime.wMonth = (ushort) dt.Month;
    sysTime.wDay = (ushort) dt.Day;
    sysTime.wHour = (ushort) dt.Hour;
    sysTime.wMinute = (ushort) dt.Minute;
    sysTime.wSecond = (ushort) dt.Second;
    sysTime.wMiliseconds = (ushort) dt.Millisecond;
    //システム日時を設定する
    SetLocalTime(ref sysTime);
}

○この記事の基になった掲示板のスレッド

DataGridコントロールの列の幅をユーザーが変更できないようにするには?

注意

この記事の最新版は「DataGridの列の幅をユーザーが変更できないようにする」で公開しています。

【質問】

System.Windows.Forms.DataGridコントロールの列の幅をユーザーが変更できないようにできますか?

【回答】

これに関しては、「Windows Forms FAQ」が参考になります。

この記事で紹介されている方法は、DataGridクラスの派生クラスを作成し、OnMouseMoveとOnMouseDownメソッドをオーバーライドし、マウスが列ヘッダの境界線上にあるときは何もしないようにするというものです。

この方法によるサンプルを以下に示します。このDataGridExクラスをSystem.Windows.Forms.DataGridの代わりに使用してください。

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
''' <summary>
''' 列ヘッダの幅をユーザーが変更することができないDataGrid
''' </summary>
Public Class DataGridEx
    Inherits System.Windows.Forms.DataGrid
 
    Protected Overrides Sub OnMouseMove( _
        ByVal e As System.Windows.Forms.MouseEventArgs)
        '列ヘッダの境界線上にマウスがあるときは何もしない
        Dim hti As System.Windows.Forms.DataGrid.HitTestInfo = _
            Me.HitTest(New System.Drawing.Point(e.X, e.Y))
        If hti.Type = _
            System.Windows.Forms.DataGrid.HitTestType.ColumnResize Then
            Return
        End If
 
        MyBase.OnMouseMove(e)
    End Sub
 
    Protected Overrides Sub OnMouseDown( _
        ByVal e As System.Windows.Forms.MouseEventArgs)
        '列ヘッダの境界線上にマウスがあるときは何もしない
        Dim hti As System.Windows.Forms.DataGrid.HitTestInfo = _
            Me.HitTest(New System.Drawing.Point(e.X, e.Y))
        If hti.Type = _
            System.Windows.Forms.DataGrid.HitTestType.ColumnResize Then
            Return
        End If
 
        MyBase.OnMouseDown(e)
    End Sub
End Class
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
/// <summary>
/// 列ヘッダの幅をユーザーが変更することができないDataGrid
/// </summary>
public class DataGridEx : System.Windows.Forms.DataGrid
{
    protected override void OnMouseMove(
        System.Windows.Forms.MouseEventArgs e)
    {
        //列ヘッダの境界線上にマウスがあるときは何もしない
        System.Windows.Forms.DataGrid.HitTestInfo hti =
            this.HitTest(new System.Drawing.Point(e.X, e.Y));
        if(hti.Type ==
            System.Windows.Forms.DataGrid.HitTestType.ColumnResize)
        {
            return;
        }
 
        base.OnMouseMove(e);
    }
 
    protected override void OnMouseDown(
        System.Windows.Forms.MouseEventArgs e)
    {
        //列ヘッダの境界線上にマウスがあるときは何もしない
        System.Windows.Forms.DataGrid.HitTestInfo hti =
            this.HitTest(new System.Drawing.Point(e.X, e.Y));
        if(hti.Type ==
            System.Windows.Forms.DataGrid.HitTestType.ColumnResize)
        {
            return;
        }
 
        base.OnMouseDown(e);
    }
}

掲示板では、こど。さんが列の幅が変更された時に列の幅を元に戻すという方法を紹介されています。詳しくは、下の「カラムヘッダの固定に関して」をご覧ください。

○この記事の基になった掲示板のスレッド

コメント



ページ情報
  • カテゴリ : .NET
  • 作成日 : 2005-04-02 (土) 23:40:00
  • 作成者 : DOBON!
  • 最終編集日 : 2010-03-22 (月) 02:10:06
  • 最終編集者 : DOBON!
[ トップ ]   [ 新規 | 子ページ作成 | 一覧 | 単語検索 | 最終更新 | ヘルプ ]