┏第46号━━━━━━━━━━━━━━━━━━━━━━━━━━┓ ┃         .NETプログラミング研究         ┃ ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛ ──<メニュー>─────────────────────── ■.NET質問箱 ・ListViewのColumnの順番を取得、設定するには? ・画像をクリックして拡大、縮小表示できるようにするには? ■.NET Tips ・PictureBoxに表示されている画像を取得する ・Refresh、Update、Invalidateメソッドの違い ─────────────────────────────── ─────────────────────────────── ■.NET質問箱 ─────────────────────────────── 「.NET質問箱」では、「どぼん!のプログラミング掲示板」に書き込 まれた.NETプログラミングに関する投稿を基に、さらに考察を加え、 Q&A形式にまとめて紹介します。 [URL]どぼん!のプログラミング掲示板 http://dobon.net/vb/bbs.html ─────────────────────────────── ●ListViewのColumnの順番を取得、設定するには? 【質問】 ListViewコントロールのAllowColumnReorderプロパティをTrueにして ユーザーがColumnの並び替えをできるようにしたとき、並び替えられ たColumnの順番を取得したいのですが、その方法が分かりません。 【回答】 ListViewコントロールのColumnの順番を取得する方法は、残念ながら. NET Frameworkでは用意されていないようです。よってこの問題を解 決するには、Win32 APIのSendMessage関数を使うことになりそうです。 この問題の解決法として「どぼん!のプログラミング掲示板」でピラ ルクさん、深山さんにより提示された方法は、LVM_GETHEADERメッセー ジを使ってListViewコントロールの列ヘッダに関する情報を取得する というものです。この方法に関してはこの記事の最後に示したリンク 先を見ていただくことにさせていただき、ここでは LVM_GETCOLUMNORDERARRAYメッセージを使った方法を紹介します。 LVM_GETCOLUMNORDERARRAYメッセージを使用した場合、Columnの順番 は、ColumnHeader.Indexをインデックスとした整数値の1次元配列と して取得できます。 以下にその具体例を示します。ここでは、Windowsフォームに ListViewコントロール(ListView1)とボタン(Button1)が配置されてお り、Button1をクリックした時にListView1のColumnの順番を取得する ものとします。 ‥‥▽VB.NET ここから▽‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥ Private Declare Auto Function SendMessage Lib "user32.dll" ( _ ByVal hWnd As IntPtr, ByVal msg As Integer, _ ByVal wParam As Integer, ByVal lParam() As Integer) As Integer Private Const LVM_FIRST As Integer = &H1000 Private Const LVM_GETCOLUMNORDERARRAY As Integer = LVM_FIRST + 59 '/ '/ ListViewの列ヘッダの順番を取得する '/ '/ 対象とするListView '/ 列ヘッダの順番を示した配列 Private Shared Function GetColumnHeaderOrder( _ ByVal lv As ListView) As Integer() Dim count As Integer = lv.Columns.Count Dim order(count) As Integer If SendMessage(lv.Handle, LVM_GETCOLUMNORDERARRAY, _ count, order) = 0 Then Throw New ApplicationException( _ "Columnの順番の取得に失敗しました。") End If Return order End Function ‥‥△VB.NET ここまで△‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥ ‥‥▽C# ここから▽‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥ [DllImport("user32.dll", CharSet=CharSet.Auto)] private static extern int SendMessage( IntPtr hWnd, int msg, int wParam, int [] lParam); private const int LVM_FIRST = 0x1000; private const int LVM_GETCOLUMNORDERARRAY = (LVM_FIRST + 59); /// /// ListViewの列ヘッダの順番を取得する /// /// 対象とするListView /// 列ヘッダの順番を示した配列 private static int[] GetColumnHeaderOrder(ListView lv) { int count = lv.Columns.Count; int[] order = new int[count]; if (SendMessage(lv.Handle, LVM_GETCOLUMNORDERARRAY, count, order == 0) throw new ApplicationException( "Columnの順番の取得に失敗しました。"); return order; } //Button1のクリックイベントハンドラ private void Button1_Click(object sender, System.EventArgs e) { //列ヘッダの順番を取得 int[] orders = GetColumnHeaderOrder(ListView1); //列ヘッダのTextとその順番を表示する for (int i = 0; i < ListView1.Columns.Count; i++) Console.WriteLine(ListView1.Columns[i].Text + ":Position=" + orders[i].ToString()); } ‥‥△C# ここまで△‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥ 次にListViewコントロールのColumnの順番を設定する方法を紹介しま す。 これは、ListViewコントロールにColumnHeaderを追加するときの順番 を変えればいいだけの話ですが、上記の方法のように、 LVM_SETCOLUMNORDERARRAYメッセージを使うという方法もあります。 以下にLVM_SETCOLUMNORDERARRAYメッセージを使ってListViewコント ロールのColumnの順番を設定する例を示します。ここでは、Windows フォームにListViewコントロール(ListView1)とボタン(Button2)が配 置されており、Button2をクリックした時にListView1のColumnの順番 をものと戻す(Index通りの順番に戻す)ようにしています。 ‥‥▽VB.NET ここから▽‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥ Private Declare Auto Function SendMessage Lib "user32.dll" ( _ ByVal hWnd As IntPtr, ByVal msg As Integer, _ ByVal wParam As Integer, ByVal lParam() As Integer) As Integer Private Const LVM_FIRST As Integer = &H1000 Private Const LVM_SETCOLUMNORDERARRAY As Integer = LVM_FIRST + 58 '/ '/ ListViewの列ヘッダの順番を設定する '/ '/ 対象とするListView '/ 列ヘッダの順番を示した配列 Private Shared Sub SetColumnHeaderOrder( _ ByVal lv As ListView, ByVal order() As Integer) If SendMessage(lv.Handle, LVM_SETCOLUMNORDERARRAY, _ order.Length, order) = 0 Then Throw New ApplicationException( _ "Columnの順番の設定に失敗しました。") End If End Sub 'Button2のクリックイベントハンドラ Private Sub Button2_Click(ByVal sender As Object, _ ByVal e As System.EventArgs) Handles Button2.Click '列ヘッダの順番を配列に入れる Dim orders(ListView1.Columns.Count - 1) As Integer Dim i As Integer For i = 0 To orders.Length - 1 orders(i) = i Next i '列ヘッダの順番を設定する SetColumnHeaderOrder(ListView1, orders) End Sub ‥‥△VB.NET ここまで△‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥ ‥‥▽C# ここから▽‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥ [DllImport("user32.dll", CharSet=CharSet.Auto)] private static extern int SendMessage( IntPtr hWnd, int msg, int wParam, int [] lParam); private const int LVM_FIRST = 0x1000; private const int LVM_SETCOLUMNORDERARRAY = (LVM_FIRST + 58); /// /// ListViewの列ヘッダの順番を設定する /// /// 対象とするListView /// 列ヘッダの順番を示した配列 private static void SetColumnHeaderOrder(ListView lv, int[] order) { if (SendMessage(lv.Handle, LVM_SETCOLUMNORDERARRAY, order.Length, order) == 0) throw new ApplicationException( "Columnの順番の設定に失敗しました。"); } //Button2のクリックイベントハンドラ private void Button2_Click(object sender, System.EventArgs e) { //列ヘッダの順番を配列に入れる int[] orders = new int[ListView1.Columns.Count]; for (int i = 0; i < orders.Length; i++) orders[i] = i; //列ヘッダの順番を設定する SetColumnHeaderOrder(ListView1, orders); } ‥‥△C# ここまで△‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥ ○この記事の基になった掲示板のスレッド [題名] ListViewで列順の変更を保持する方法 [投稿者(敬称略)] こう, ピラルク, 深山 [URL] http://dobon.net/vb/bbs/log3-4/1894.html ─────────────────────────────── ●画像をクリックして拡大、縮小表示できるようにするには? 【質問】 ピクチャボックスに表示した画像をマウスクリックにより、クリック した位置を中央にして、拡大(左クリックした時)、縮小(右クリッ クした時)させたいのですが、どのようにすればいいですか? 【回答】 ここでは、ピクチャボックスのPaintイベントでGraphics.DrawImage メソッドを使って画像を表示させることにします。ピクチャボックス がクリックされた時に(ここではMouseDownイベントを使います)、 画像の表示倍率を決定し、ピクチャボックスで画像を表示させる範囲 を計算します。ピクチャボックスのPaintイベントハンドラでは、 Graphics.DrawImageメソッドを使って実際にこの範囲に画像を表示し ます。 それでは実際に作成してみましょう。仕様としては、テキストボック スに画像ファイル名を入力し、ボタンをクリックすると、ピクチャボ ックスに画像が表示されるようにします。さらに、ピクチャボックス を左クリックすると、クリックした位置がピクチャボックスの中央に し、画像が倍に拡大されて表示されます。右クリックでは、クリック した位置がピクチャボックスの中央に来るように、画像が1/2に縮小 して表示します。 まずフォーム(Form1)にピクチャボックス(PictureBox1)とテキス トボックス(TextBox1)とボタン(Button1)を配置します。さらに、 PictureBox1のClickイベントハンドラとしてButton1_Clickを、 MouseDownイベントハンドラとしてPictureBox1_MouseDownを、さらに Button1のクリックイベントハンドラとしてButton1_Clickを作成しま す。 これで準備は完了です。後はForm1クラスに以下のようなコードを書 き込み、完成です。 ‥‥▽VB.NET ここから▽‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥ '表示する画像 Private img As Bitmap '倍率 Private ratio As Single = 1.0F '画像を表示させる範囲 Private imgRect As Rectangle 'Button1のクリックイベントハンドラ Private Sub Button1_Click(ByVal sender As Object, _ ByVal e As System.EventArgs) Handles Button1.Click '表示する画像を読み込む img = New Bitmap(TextBox1.Text) '初期化 imgRect = New Rectangle(0, 0, img.Width, img.Height) ratio = 1.0F '画像を表示する PictureBox1.Invalidate() End Sub 'PictureBox1のMouseDownイベントハンドラ Private Sub PictureBox1_MouseDown(ByVal sender As Object, _ ByVal e As System.Windows.Forms.MouseEventArgs) _ Handles PictureBox1.MouseDown Dim pb As PictureBox = CType(sender, PictureBox) 'クリックされた位置を画像上の位置に変換 Dim imgPoint As New Point(CInt((e.X - imgRect.X) / ratio), _ CInt((e.Y - imgRect.Y) / ratio)) '倍率を変更する If e.Button = MouseButtons.Left Then ratio *= 2.0F Else If e.Button = MouseButtons.Right Then ratio *= 0.5F End If End If '画像の表示範囲を計算する imgRect.Width = CInt(Math.Round((img.Width * ratio))) imgRect.Height = CInt(Math.Round((img.Height * ratio))) imgRect.X = CInt(Math.Round((pb.Width / 2 - imgPoint.X * ratio))) imgRect.Y = CInt(Math.Round((pb.Height / 2 - imgPoint.Y * ratio))) '画像を表示する PictureBox1.Invalidate() End Sub 'PictureBox1のPaintイベントハンドラ Private Sub PictureBox1_Paint(ByVal sender As Object, _ ByVal e As System.Windows.Forms.PaintEventArgs) _ Handles PictureBox1.Paint If Not (img Is Nothing) Then '画像を指定された範囲に描画する e.Graphics.DrawImage(img, imgRect) End If End Sub ‥‥△VB.NET ここまで△‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥ ‥‥▽C# ここから▽‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥ //表示する画像 private Bitmap img; //倍率 private float ratio = 1F; //画像を表示させる範囲 private Rectangle imgRect; //Button1のクリックイベントハンドラ private void Button1_Click(object sender, System.EventArgs e) { //表示する画像を読み込む img = new Bitmap(TextBox1.Text); //初期化 imgRect = new Rectangle(0, 0, img.Width, img.Height); ratio = 1F; //画像を表示する PictureBox1.Invalidate(); } //PictureBox1のMouseDownイベントハンドラ private void PictureBox1_MouseDown(object sender, System.Windows.Forms.MouseEventArgs e) { PictureBox pb = (PictureBox) sender; //クリックされた位置を画像上の位置に変換 Point imgPoint = new Point( (int) Math.Round((e.X - imgRect.X) / ratio), (int) Math.Round((e.Y - imgRect.Y) / ratio)); //倍率を変更する if (e.Button == MouseButtons.Left) { ratio *= 2F; } else if (e.Button == MouseButtons.Right) { ratio *= 0.5F; } //画像の表示範囲を計算する imgRect.Width = (int) Math.Round(img.Width * ratio); imgRect.Height = (int) Math.Round(img.Height * ratio); imgRect.X = (int) Math.Round(pb.Width / 2 - imgPoint.X * ratio); imgRect.Y = (int) Math.Round(pb.Height / 2 - imgPoint.Y * ratio); //画像を表示する PictureBox1.Invalidate(); } //PictureBox1のPaintイベントハンドラ private void PictureBox1_Paint(object sender, System.Windows.Forms.PaintEventArgs e) { if (img != null) { //画像を指定された範囲に描画する e.Graphics.DrawImage(img, imgRect); } } ‥‥△C# ここまで△‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥ ○この記事の基になった掲示板のスレッド [題名] ピクチャーボックス [投稿者(敬称略)] 水野, 琴, 管理人 [URL] http://dobon.net/vb/bbs/log3-3/1683.html ─────────────────────────────── ■.NET Tips ─────────────────────────────── ●PictureBoxに表示されている画像を取得する ここではInvokePaintメソッド、及びInvokePaintBackgroundメソッド を使ってPictureBoxに表示されている画像を取得する方法を紹介しま す。この方法で取得できる画像は、PictureBoxのPaintイベント、及 びPaintBackgroundイベントでPaintEventArgs.Graphicsに描画された 画像だけであり、具体的には、PictureBoxのImageプロパティ、 BackGroundImageプロパティ、BackColorプロパティで指定された画像 や、PaintイベントハンドラでPaintEventArgs.Graphicsを使って描画 された画像などに限られます。(これ以外の方法で描画された画像を 取得するには、画面をキャプチャーする必要があるでしょう。) 以下に、この方法によりPictureBox(PictureBox1)に表示されている 画像を画像ファイルに保存する方法を示します。 ‥‥▽VB.NET ここから▽‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥ 'PictureBox1の大きさを取得 Dim rect As Rectangle = PictureBox1.ClientRectangle 'PictureBox1に表示されている画像を取得するためのBitmap Dim bmp As New Bitmap(rect.Width, rect.Height) 'bmpに画像を入れるための準備 Dim g As Graphics = Graphics.FromImage(bmp) Dim pea As New PaintEventArgs(g, rect) 'PaintBackgroundイベントを発生 Me.InvokePaintBackground(PictureBox1, pea) 'Paintイベントを発生 Me.InvokePaint(PictureBox1, pea) '画像を保存する bmp.Save("C:\test.png") '後始末 g.Dispose() bmp.Dispose() ‥‥△VB.NET ここまで△‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥ ‥‥▽C# ここから▽‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥ //PictureBox1の大きさを取得 Rectangle rect = PictureBox1.ClientRectangle; //PictureBox1に表示されている画像を取得するためのBitmap Bitmap bmp = new Bitmap(rect.Width, rect.Height); //bmpに画像を入れるための準備 Graphics g = Graphics.FromImage(bmp); PaintEventArgs pea = new PaintEventArgs(g, rect); //PaintBackgroundイベントを発生 this.InvokePaintBackground(PictureBox1, pea); //Paintイベントを発生 this.InvokePaint(PictureBox1, pea); //画像を保存する bmp.Save(@"C:\test.png"); //後始末 g.Dispose(); bmp.Dispose(); ‥‥△C# ここまで△‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥ この方法によりPictureBox以外のコントロールの外見も画像として取 得できるように期待されるかもしれませんが、実際にはほとんどのコ ントロールでうまく行きません。(Label、Button、DataGridコント ロール等だけでうまく行くようですが、FlatStyleプロパティが Systemの時は失敗します。) ─────────────────────────────── ●Refresh、Update、Invalidateメソッドの違い ControlクラスのRefresh、Update、Invalidateメソッドは主にコント ロールの再描画を促すために使用されますが、これらの違いはヘルプ を読んだだけでは非常に分かりにくいです。 ヘルプによると、これらのメソッドは次のように説明されています。 Refresh : 強制的に、コントロールがクライアント領域を無効化し、 直後にそのコントロール自体とその子コントロールを再描画するよう にします。 Update : コントロールによって、クライアント領域内の無効化され た領域が再描画されます。 Invalidate : コントロールの特定の領域を無効にし、そのコントロー ルに描画メッセージを送信します。 [URL]Refreshメソッド http://www.microsoft.com/japan/msdn/library/ja/cpref/html/frlrfsystemwindowsformscontrolclassrefreshtopic.asp [URL]Updateメソッド http://www.microsoft.com/japan/msdn/library/ja/cpref/html/frlrfsystemwindowsformscontrolclassupdatetopic.asp [URL]Invalidateメソッド http://www.microsoft.com/japan/msdn/library/ja/cpref/html/frlrfsystemwindowsformscontrolclassinvalidatetopic.asp これらのメソッドが実際に何をしているのか調べるには、「 Reflector for .NET」などの逆アセンブラを使ってDecompileすれば よいでしょう。その結果、次のようなことが分かります。 [URL]Reflector for .NET http://www.aisto.com/roeder/DotNet/ まず、Refreshメソッドは、Invalidateメソッド(パラメータはTrue) を呼び出した後、さらにUpdateメソッドを呼び出しているだけです。 また、Invalidateメソッドは、Win32 APIのRedrawWindow(子コント ロールを再描画する時)または、InvalidateRect関数を呼び出してお り、Updateメソッドは、Win32 APIのUpdateWindow関数を呼び出して いるらしいということが分かります。 つまり、Invalidateメソッドはアプリケーションキューが空になった 時にコントロールを再描画し、Updateメソッドはアプリケーションキ ューが空でなくても再描画すべき領域があるならばすぐに再描画し、 Refreshはアプリケーションキューが空でなくてもコントロールとそ の子コントロールをすぐに再描画するということになります。 言葉だけでは分かりにくいので、実際のコードでその動作を確認して みましょう。次のサンプルは、Windowsフォーム(Form1)にボタンを4 つ配置し、これらをクリックすると、フォームに0から10までの数字 が1秒おきにカウントアップして表示されるようにしたものです。4つ のボタンはそれぞれカウンターをインクリメントした後にRefresh、 Update、Invalidateメソッドを呼び出す(あるいは呼び出さない)と いう違いがあります。 ‥‥▽VB.NET ここから▽‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥ 'カウンターの値 Private counter As Integer = 0 'Button1のクリックイベントハンドラ Private Sub Button1_Click(ByVal sender As Object, _ ByVal e As System.EventArgs) Handles Button1.Click Dim i As Integer For i = 0 To 9 'カウンターを増やす counter += 1 'フォームを再描画しない '1秒間停止する System.Threading.Thread.Sleep(1000) Next i End Sub 'Button2のクリックイベントハンドラ Private Sub Button2_Click(ByVal sender As Object, _ ByVal e As System.EventArgs) Handles Button2.Click Dim i As Integer For i = 0 To 9 'カウンターを増やす counter += 1 'Invalidateを呼び出す Me.Invalidate() '1秒間停止する System.Threading.Thread.Sleep(1000) Next i End Sub 'Button3のクリックイベントハンドラ Private Sub Button3_Click(ByVal sender As Object, _ ByVal e As System.EventArgs) Handles Button3.Click Dim i As Integer For i = 0 To 9 'カウンターを増やす counter += 1 'Updateを呼び出す Me.Update() '1秒間停止する System.Threading.Thread.Sleep(1000) Next i End Sub 'Button4のクリックイベントハンドラ Private Sub Button4_Click(ByVal sender As Object, _ ByVal e As System.EventArgs) Handles Button4.Click Dim i As Integer For i = 0 To 9 'カウンターを増やす counter += 1 'Refreshを呼び出す Me.Refresh() '1秒間停止する System.Threading.Thread.Sleep(1000) Next i End Sub 'PictureBox1のPaintイベントハンドラ Private Sub PictureBox1_Paint(ByVal sender As Object, _ ByVal e As System.Windows.Forms.PaintEventArgs) _ Handles MyBase.Paint 'カウンターを描画する e.Graphics.DrawString(counter.ToString(), Me.Font, _ Brushes.Black, 0, 0) End Sub ‥‥△VB.NET ここまで△‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥ ‥‥▽C# ここから▽‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥ //カウンターの値 private int counter = 0; //Button1のクリックイベントハンドラ private void Button1_Click(object sender, System.EventArgs e) { for (int i = 0; i < 10; i++) { //カウンターを増やす counter++; //フォームを再描画しない //1秒間停止する System.Threading.Thread.Sleep(1000); } } //Button2のクリックイベントハンドラ private void Button2_Click(object sender, System.EventArgs e) { for (int i = 0; i < 10; i++) { //カウンターを増やす counter++; //Invalidateを呼び出す this.Invalidate(); //1秒間停止する System.Threading.Thread.Sleep(1000); } } //Button3のクリックイベントハンドラ private void Button3_Click(object sender, System.EventArgs e) { for (int i = 0; i < 10; i++) { //カウンターを増やす counter++; //Updateを呼び出す this.Update(); //1秒間停止する System.Threading.Thread.Sleep(1000); } } //Button4のクリックイベントハンドラ private void Button4_Click(object sender, System.EventArgs e) { for (int i = 0; i < 10; i++) { //カウンターを増やす counter++; //Refreshを呼び出す this.Refresh(); //1秒間停止する System.Threading.Thread.Sleep(1000); } } //PictureBox1のPaintイベントハンドラ private void PictureBox1_Paint( object sender, System.Windows.Forms.PaintEventArgs e) { //カウンターを描画する e.Graphics.DrawString( counter.ToString(), this.Font, Brushes.Black, 0, 0); } ‥‥△C# ここまで△‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥ まず、カウンターをインクリメントした後に何もしない時(Button1 をクリックした時)は、フォームに表示された数字は全く変化しませ ん(ただし、10秒後フォームを一回隠してもう一度表示するなどすれ ば、カウンターの値が表示されます)。しかもこの10秒間は、フォー ム全体はフリーズしたようになり、フォームの上に別のウィンドウを 重ねても、フォームは一切再描画されません。 Invalidateメソッドを呼び出した時(Button2をクリックした時)も 同様に10秒間変化しませんが、10秒後ようやくカウンターが更新され て表示されます。しかし、10秒間フォーム全体はフリーズしたように なります。 Updateメソッドを呼び出した時(Button3をクリックした時)も同じ く何も変化しないように見えますが、フォームの上に別のウィンドウ を重ね、またどけるというようなことを行うと、フォームは1秒おき に再描画されます。カウンターが表示される部分を別のウィンドウで 隠せば、カウンターも更新されて表示されます。 Refreshメソッドを呼び出した時(Button4をクリックした時)は、何 もしなくても1秒おきにフォーム全体が再描画され、カウンターも更 新されて表示されます。 実際のこれらのメソッドの使い分けとしては、コントロールを再描画 したいがすぐである必要がないときはInvalidateメソッドを使い、今 すぐ再描画する必要があるときはRefreshメソッドを使うということ になるでしょう。 =============================== ■このマガジンの購読、購読中止、バックナンバー、説明に関しては  次のページをご覧ください。  http://www.mag2.com/m/0000104516.htm ■発行人・編集人:どぼん!  (Microsoft MVP for Visual Basic, Oct 2004-Oct 2005)  http://dobon.net  dobon_info@yahoo.co.jp ■ご質問等はメールではなく、掲示板へお願いいたします。  http://dobon.net/vb/bbs.html ■上記メールアドレスへのメールは確実に読まれる保障はありません  (スパム、ウィルス対策です)。メールは下記URLのフォームメール  から送信してください。  http://dobon.net/mail.html Copyright (c) 2003 - 2004 DOBON! All rights reserved. ===============================