• 追加された行はこの色です。
  • 削除された行はこの色です。
#title(.NETプログラミング研究 第54号)

#navi(.NET プログラミング研究)
#navi(.NETプログラミング研究)

#contents

*.NETプログラミング研究 第54号 [#d3bc8994]

**お知らせ [#k63c0f5f]

***CodeZineがプレオープン [#l20e35ad]

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

-[[CodeZine>http://codezine.jp/]]

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

-[[.NETによるプラグイン機能を持つテキストエディタの作成>http://codezine.jp/a/article.aspx?aid=1]]
-[[TCPを利用した複数クライアント接続可能なチャットアプリケーションの作成>http://codezine.jp/a/article.aspx?aid=22]]
-[[DataGridにComboBoxを表示可能な列を作る>http://codezine.jp/a/article.aspx?aid=3]]

**.NET質問箱 [#l15cd55b]

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

-[[どぼん!のプログラミング掲示板>http://dobon.net/vb/bbs.html]]
-[[どぼん!のプログラミング掲示板>https://dobon.net/vb/bbs.html]]

***表示色を反転して線を引くには? [#pdcc7c3f]

#column(注意){{
この記事の最新版は「[[表示色を反転して線を引く>http://dobon.net/vb/dotnet/graphics/drawreversibleline.html]]」で公開しています。
この記事の最新版は「[[表示色を反転して線を引く>https://dobon.net/vb/dotnet/graphics/drawreversibleline.html]]」で公開しています。
}}

''【質問】''

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

''【回答】''

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

-[[DOBON.NET .NET Tips - コントロールを描画する>http://dobon.net/vb/dotnet/graphics/drawcontrols.html]]
-[[DOBON.NET .NET Tips - コントロールを描画する>https://dobon.net/vb/dotnet/graphics/drawcontrols.html]]

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

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

#code(vbnet){{
'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)
}}

#code(csharp){{
//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);
}}

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

-[[Xorペン | 投稿者(敬称略) ぼろん, よねKEN>http://dobon.net/vb/bbs/log3-2/983.html]]
-[[Drawmode=6 | 投稿者(敬称略) ぱーやん, 管理人>http://dobon.net/vb/bbs/log3-7/3762.html]]
-[[DrawMode = vbInvert機能 | 投稿者(敬称略) NINE, テラオメガ, 深山>http://dobon.net/vb/bbs/log3-8/4830.html]]
-[[Xorペン | 投稿者(敬称略) ぼろん, よねKEN>https://dobon.net/vb/bbs/log3-2/983.html]]
-[[Drawmode=6 | 投稿者(敬称略) ぱーやん, 管理人>https://dobon.net/vb/bbs/log3-7/3762.html]]
-[[DrawMode = vbInvert機能 | 投稿者(敬称略) NINE, テラオメガ, 深山>https://dobon.net/vb/bbs/log3-8/4830.html]]

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

#column(注意){{
この記事の最新版は「[[クリップボードにファイルをコピーする、クリップボードからファイルを取得する>http://dobon.net/vb/dotnet/file/copyfiletoclipboard.html]]」で公開しています。
この記事の最新版は「[[クリップボードにファイルをコピーする、クリップボードからファイルを取得する>https://dobon.net/vb/dotnet/file/copyfiletoclipboard.html]]」で公開しています。
}}

''【質問】''

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

''【回答】''

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

-[[DOBON.NET .NET Tips - クリップボードに文字列をコピー、クリップボードから文字列を取得>http://dobon.net/vb/dotnet/string/clipboard.html]]
-[[DOBON.NET .NET Tips - クリップボードに文字列をコピー、クリップボードから文字列を取得>https://dobon.net/vb/dotnet/string/clipboard.html]]

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

#code(vbnet){{
'クリップボードのデータを取得する
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
}}

#code(csharp){{
//クリップボードのデータを取得する
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オブジェクトをクリップボードに貼り付けます。この様にしてクリップボードに貼り付けたファイルはエクスプローラでペーストできます。

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

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

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

-[[コードからクリップボードへファイルをコピー(配置)する方法 | 投稿者(敬称略) とざマン>http://dobon.net/vb/bbs/log3-2/1018.html]]
-[[コードからクリップボードへファイルをコピー(配置)する方法 | 投稿者(敬称略) とざマン>https://dobon.net/vb/bbs/log3-2/1018.html]]

***システム時計の日時を設定するには? [#p98818aa]

#column(注意){{
この記事の最新版は「[[システム時計の日時を設定する>http://dobon.net/vb/dotnet/system/setlocaltime.html]]」で公開しています。
この記事の最新版は「[[システム時計の日時を設定する>https://dobon.net/vb/dotnet/system/setlocaltime.html]]」で公開しています。
}}

''【質問】''

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

''【回答】''

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

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

#code(vbnet){{
'システム日付を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"
}}

#code(csharp){{
//システム日付を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型で日時を指定してシステム日時を変更するメソッドです。

#code(vbnet){{
<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
}}

#code(csharp){{
//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);
}
}}

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

-[[システム時計について | 投稿者(敬称略) カー君, よねKEN>http://dobon.net/vb/bbs/log3-2/1156.html]]
-[[システム時計について | 投稿者(敬称略) カー君, よねKEN>https://dobon.net/vb/bbs/log3-2/1156.html]]

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

#column(注意){{
この記事の最新版は「[[DataGridの列の幅をユーザーが変更できないようにする>http://dobon.net/vb/dotnet/datagrid/lockcolumnwidth.html]]」で公開しています。
この記事の最新版は「[[DataGridの列の幅をユーザーが変更できないようにする>https://dobon.net/vb/dotnet/datagrid/lockcolumnwidth.html]]」で公開しています。
}}

''【質問】''

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

''【回答】''

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

-[[Windows Forms FAQ - How can I prevent my user from sizing columns in my datagrid?>http://www.syncfusion.com/faq/winforms/search/872.asp]]

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

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

#code(vbnet){{
''' <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
}}

#code(csharp){{
/// <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);
    }
}
}}

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

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

-[[カラムヘッダの固定に関して | 投稿者(敬称略) 咲くら, こど。>http://dobon.net/vb/bbs/log3-4/2044.html]]
-[[DetaGlidの列幅を操作不可にしたいです。 | 投稿者(敬称略) こう, 管理人, java.lang.Nullpo>http://dobon.net/vb/bbs/log3-12/7060.html]]
-[[カラムヘッダの固定に関して | 投稿者(敬称略) 咲くら, こど。>https://dobon.net/vb/bbs/log3-4/2044.html]]
-[[DetaGlidの列幅を操作不可にしたいです。 | 投稿者(敬称略) こう, 管理人, java.lang.Nullpo>https://dobon.net/vb/bbs/log3-12/7060.html]]

**コメント [#y9658a1c]
#comment

//これより下は編集しないでください
#pageinfo([[:Category/.NET]],2005-04-02 (土) 23:40:00,DOBON!,2010-03-22 (月) 02:10:06,DOBON!)

[ トップ ]   [ 新規 | 子ページ作成 | 一覧 | 単語検索 | 最終更新 | ヘルプ ]