.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
| | 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
| | 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"}
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"};
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
| | Today = New DateTime(2005, 1, 2, 0, 0, 0)
DateString = "2005-2-3"
TimeOfDay = New DateTime(2000, 1, 1, 6, 15, 30)
TimeString = "8:25:45"
|
1
2
3
4
5
6
7
8
9
10
11
12
13
| | Microsoft.VisualBasic.DateAndTime.Today =
new DateTime(2005, 1, 2, 0, 0, 0);
Microsoft.VisualBasic.DateAndTime.DateString =
"2005-2-3";
Microsoft.VisualBasic.DateAndTime.TimeOfDay =
new DateTime(2000, 1, 1, 6, 15, 30);
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
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
| |
[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);
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コントロールの列の幅をユーザーが変更できないようにするには? †
【質問】
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
| | 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
| | 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);
}
}
|
掲示板では、こど。さんが列の幅が変更された時に列の幅を元に戻すという方法を紹介されています。詳しくは、下の「カラムヘッダの固定に関して」をご覧ください。
○この記事の基になった掲示板のスレッド
コメント †