┏第52号━━━━━━━━━━━━━━━━━━━━━━━━━━┓ ┃         .NETプログラミング研究         ┃ ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛ ──<メニュー>─────────────────────── ■.NET質問箱 ・コンボボックスの高さを変えるのは? ・埋め込まれたHTMLを表示するには? ・タブのテキストを縦書きにするには? ・テキストボックスの現在のカレット位置(行と列)を取得するには? ─────────────────────────────── ─────────────────────────────── ■.NET質問箱 ─────────────────────────────── 「.NET質問箱」では、「どぼん!のプログラミング掲示板」に書き込 まれた.NETプログラミングに関する投稿を基に、さらに考察を加え、 Q&A形式にまとめて紹介します。 [URL]どぼん!のプログラミング掲示板 http://dobon.net/vb/bbs.html ─────────────────────────────── ●コンボボックスの高さを変えるのは? 【質問】 System.Windows.Forms.ComboBoxコントロールの高さを変えることは 出来ますか?Heightプロパティの値を変えても高さが変わらないよう ですが。 【回答】 ComboBoxの高さを変えるには、ComboBoxをオーナードローする必要が あります。ComboBoxのオーナードローについては、次のページで紹介 しています。 [URL]コンボボックスの項目を自分で描画する http://dobon.net/vb/dotnet/control/cbownerdraw.html 以下にサンプルを示します。ここではComboBox1の項目の高さ( ItemHeightプロパティ)を20としています。 ‥‥▽VB.NET ここから▽‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥ 'フォームのLoadイベントハンドラ Private Sub Form1_Load(ByVal sender As Object, _ ByVal e As System.EventArgs) Handles MyBase.Load 'オーナードローを指定 ComboBox1.DrawMode = DrawMode.OwnerDrawFixed '項目の高さを設定 ComboBox1.ItemHeight = 20 'DrawItemイベントハンドラの追加 AddHandler ComboBox1.DrawItem, AddressOf ComboBox1_DrawItem 'ComboBox1のリストに項目を追加する ComboBox1.Items.Add("おはよう。") ComboBox1.Items.Add("こんにちは。") ComboBox1.Items.Add("こんばんは。") End Sub 'DrawItemイベントハンドラ '項目を描画する Private Sub ComboBox1_DrawItem(ByVal sender As Object, _ ByVal e As System.Windows.Forms.DrawItemEventArgs) '背景を描画する '項目が選択されている時は強調表示される e.DrawBackground() Dim cmb As ComboBox = CType(sender, ComboBox) '項目に表示する文字列 Dim txt As String If (e.Index > -1) Then txt = cmb.Items(e.Index).ToString() Else txt = cmb.Text End If '使用するブラシ Dim b As Brush = New SolidBrush(e.ForeColor) '文字列を描画する Dim ym As Single = (e.Bounds.Height - _ e.Graphics.MeasureString(txt, cmb.Font).Height) / 2 e.Graphics.DrawString(txt, cmb.Font, b, _ e.Bounds.X, e.Bounds.Y + ym) b.Dispose() 'フォーカスを示す四角形を描画 e.DrawFocusRectangle() End Sub ‥‥△VB.NET ここまで△‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥ ‥‥▽C# ここから▽‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥ //Form1のLoadイベントハンドラ private void Form1_Load(object sender, System.EventArgs e) { //オーナードローを指定 ComboBox1.DrawMode = DrawMode.OwnerDrawFixed; //項目の高さを設定 ComboBox1.ItemHeight = 20; //DrawItemイベントハンドラの追加 ComboBox1.DrawItem += new DrawItemEventHandler(ComboBox1_DrawItem); //ComboBox1のリストに項目を追加する ComboBox1.Items.Add("おはよう。"); ComboBox1.Items.Add("こんにちは。"); ComboBox1.Items.Add("こんばんは。"); } //DrawItemイベントハンドラ //項目を描画する private void ComboBox1_DrawItem(object sender, System.Windows.Forms.DrawItemEventArgs e) { //背景を描画する //項目が選択されている時は強調表示される e.DrawBackground(); ComboBox cmb = (ComboBox) sender; //項目に表示する文字列 string txt = e.Index > -1 ? cmb.Items[e.Index].ToString() : cmb.Text; //使用するブラシ Brush b = new SolidBrush(e.ForeColor); //文字列を描画する float ym = (e.Bounds.Height - e.Graphics.MeasureString( txt, cmb.Font).Height) / 2; e.Graphics.DrawString( txt, cmb.Font, b, e.Bounds.X, e.Bounds.Y + ym); b.Dispose(); //フォーカスを示す四角形を描画 e.DrawFocusRectangle(); } ‥‥△C# ここまで△‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥ ○この記事の基になった掲示板のスレッド [題名] コンボボックスの高さの変え方 [投稿者(敬称略)] hiro, よねKEN, 管理人 [URL] http://dobon.net/vb/bbs/log3-5/2743.html ─────────────────────────────── ●埋め込まれたHTMLを表示するには? 【質問】 アセンブリファイルにリソースとしてHTMLファイルを埋め込み、表示 したいのですが、いい方法はないでしょうか? 【回答】 埋め込まれたHTMLファイルを一時ファイルに書き込み、それを表示す るようにすれば済む話ですが、ここでは直接表示する方法を紹介しま す。 Internet Explore 4以降(?)では、res://プロトコルがサポートさ れています。これは、埋め込まれているリソースを表示できるように するものですので、これを使えば埋め込んだHTMLファイルを表示でき ます。ところが、res://で対応しているリソースはWin32リソースで、 これは通常.NET Frameworkで使用されるリソースとは異なります。 .NETでWin32リソースを埋め込む方法はちょっと厄介です。Visual Studio .NETでは、次のようにして埋め込むことができます。 1.リソースを埋め込むアセンブリファイルをメニューの「ファイル」 -「開く」-「ファイル」で開きます。 2.アセンブリファイル名のノード(RCノード)を右クリックしてメ ニューを表示し、「リソースの追加」を選択します。 3.「リソースの追加」ダイアログの「インポート」ボタンをクリッ クし、埋め込みたいファイルを選択します。 4.保存して、完了です。 このような方法では、アセンブリをビルドするたびにリソースを埋め 込み直す必要があります。それが面倒であれば、/win32res(VB.NET では、/win32resource)コンパイラオプションを使用してcsc.exe( VB.NETでは、vbc.exe)でコンパイルする必要があります。次にこの 方法を説明します。 /win32resオプションでは、Win32リソースファイルを指定する必要が あるので、まずはこれを作成します。Win32リソースファイルを作る には、RCファイルを作成し、リソースコンパイラ(rc.exe、"C: \Program Files\Microsoft Visual Studio .NET 2003\Vc7\bin\rc. exe"あたりにあります)でコンパイルします。 "readme.html"を"test.html"というIDで埋め込む場合、RCファイルと して次のようなテキストファイルを作成します。ここでは、"win32. rc"として保存します。 ‥‥▽ここから▽‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥ readme.html HTML "test.html" ‥‥△ここまで△‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥ コマンドラインで rc.exe win32.rc を実行すると、"win32.RES"というファイルができます。これが、 Win32リソースファイルです。 あとはリソースを埋め込むアセンブリをコンパイルする時に、 /win32resオプションでこのファイルを指定するだけです。 ‥‥▽VB.NET ここから▽‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥ vbc.exe /out:win32res.dll /target:library /win32resource:win32.RES win32res.vb ‥‥△VB.NET ここまで△‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥ ‥‥▽C# ここから▽‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥ csc.exe /out:win32res.dll /target:library /win32res:win32.RES win32res.cs ‥‥△C# ここまで△‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥ このようにして埋め込まれたファイルは、Internet Exploreから、 res://(アセンブリファイルのフルパス)/(リソースのID) としてアクセスできます。つまり上の例では、 res://(アセンブリファイルのフルパス)/test.html で埋め込まれたHTMLが表示されます。 最後に、Microsoft Web Browserコントロールで自分自身のアセンブ リに埋め込んだHTML(IDが"test.html")を表示する例を示します。 ラッパーDLLが作成されており、これを使用するものとします。 ‥‥▽VB.NET ここから▽‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥ Dim url As String = "res://" + _ System.Reflection.Assembly.GetExecutingAssembly().Location + _ "/test.html" 'WebBrowserに表示する AxWebBrowser1.Navigate(url) ‥‥△VB.NET ここまで△‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥ ‥‥▽C# ここから▽‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥ string url = "res://" + System.Reflection.Assembly.GetExecutingAssembly().Location + "/test.html"; //WebBrowserに表示する object refmissing = System.Reflection.Missing.Value; AxWebBrowser1.Navigate(url, ref refmissing, ref refmissing, ref refmissing, ref refmissing); ‥‥△C# ここまで△‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥ 参考: [URL]The Code Project - Embed Win32 resources in C# programs - C# Programming http://www.codeproject.com/csharp/embedwin32resources.asp [URL]The Code Project - Using MSHTML Advanced Hosting Interfaces - C# Programming http://www.codeproject.com/csharp/advhost.asp ○この記事の基になった掲示板のスレッド [題名] アプリに埋め込まれたhtmlファイルを表示したい [投稿者(敬称略)] 梅子, ピラルク [URL] http://dobon.net/vb/bbs/log3-5/2626.html ─────────────────────────────── ●タブのテキストを縦書きにするには? 【質問】 TabControlコントロールのAlignmentプロパティをRightにしてタブを 右側に表示していますが、タブに表示される文字列を縦書きにできな いでしょうか? 【回答】 まず、タブをオーナードローする方法があります。タブコントロール のタブをオーナードローする方法については、 [URL]DOBON.NET .NET Tips - TabControlのタブを自分で描画する http://dobon.net/vb/dotnet/control/tabownerdraw.html をご覧ください。 以下にオーナードローによりタブのTextを縦書きにする例を示します。 ‥‥▽VB.NET ここから▽‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥ 'フォームのLoadイベントハンドラ Private Sub Form1_Load(ByVal sender As Object, _ ByVal e As System.EventArgs) Handles MyBase.Load TabControl1.Alignment = TabAlignment.Right 'TabControlをオーナードローする TabControl1.DrawMode = TabDrawMode.OwnerDrawFixed 'DrawItemイベントハンドラを追加 AddHandler TabControl1.DrawItem, AddressOf TabControl1_DrawItem End Sub 'TabControl1のDrawItemイベントハンドラ Private Sub TabControl1_DrawItem(ByVal sender As Object, _ ByVal e As DrawItemEventArgs) '対象のTabControlを取得 Dim tab As TabControl = CType(sender, TabControl) Dim page As TabPage = tab.TabPages(e.Index) 'タブページのテキストを取得 Dim txt As String = page.Text 'StringFormatを作成 Dim sf As New StringFormat '縦書きにする sf.FormatFlags = StringFormatFlags.DirectionVertical Dim foreBrush, backBrush As Brush '背景の描画 backBrush = New SolidBrush(page.BackColor) e.Graphics.FillRectangle(backBrush, e.Bounds) 'Textの描画 foreBrush = New SolidBrush(page.ForeColor) e.Graphics.DrawString(txt, page.Font, foreBrush, _ RectangleF.op_Implicit(e.Bounds), sf) foreBrush.Dispose() backBrush.Dispose() End Sub ‥‥△VB.NET ここまで△‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥ ‥‥▽C# ここから▽‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥ //Form1のLoadイベントハンドラ private void Form1_Load(object sender, System.EventArgs e) { TabControl1.Alignment = TabAlignment.Right; //TabControlをオーナードローする TabControl1.DrawMode = TabDrawMode.OwnerDrawFixed; //DrawItemイベントハンドラを追加 TabControl1.DrawItem += new DrawItemEventHandler(TabControl1_DrawItem); } //TabControl1のDrawItemイベントハンドラ private void TabControl1_DrawItem(object sender, DrawItemEventArgs e) { //対象のTabControlを取得 TabControl tab = (TabControl) sender; TabPage page = tab.TabPages[e.Index]; //タブページのテキストを取得 string txt = page.Text; //StringFormatを作成 StringFormat sf = new StringFormat(); //縦書きにする sf.FormatFlags = StringFormatFlags.DirectionVertical; Brush foreBrush, backBrush; //背景の描画 backBrush = new SolidBrush(page.BackColor); e.Graphics.FillRectangle(backBrush, e.Bounds); //Textの描画 foreBrush = new SolidBrush(page.ForeColor); e.Graphics.DrawString(txt, page.Font, foreBrush, e.Bounds, sf); foreBrush.Dispose(); backBrush.Dispose(); } ‥‥△C# ここまで△‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥ また、掲示板ではピラルクさんが縦書きフォントを使用する方法を紹 介されています。オーナードローよりも簡単できれいに表示されます。 ただし、タブが左にあるときは、文字が上下逆さになってしまい、こ の方法は使えません。 ‥‥▽VB.NET ここから▽‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥ TabControl1.Alignment = TabAlignment.Right '縦書きのフォントにする TabControl1.Font = New Font( _ TabControl1.Font.FontFamily, _ TabControl1.Font.Size, _ TabControl1.Font.Style, _ TabControl1.Font.Unit, _ TabControl1.Font.GdiCharSet, _ True) ‥‥△VB.NET ここまで△‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥ ‥‥▽C# ここから▽‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥ TabControl1.Alignment = TabAlignment.Right; //縦書きのフォントにする TabControl1.Font = new Font( TabControl1.Font.FontFamily, TabControl1.Font.Size, TabControl1.Font.Style, TabControl1.Font.Unit, TabControl1.Font.GdiCharSet, true); ‥‥△C# ここまで△‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥ ○この記事の基になった掲示板のスレッド [題名] コントロールのTEXTを縦書きに [投稿者(敬称略)] うま, りょう, ピラルク [URL] http://dobon.net/vb/bbs/log3-5/2825.html ─────────────────────────────── ●テキストボックスの現在のカレット位置(行と列)を取得するには? 【質問】 テキストボックス(またはリッチテキストボックス)内で現在カレッ トのある行と列を取得するにはどのようにすればよいのでしょうか? 【回答】 行を理論的に数える場合(WordWrapがTrueで、右側で折り返されてい ても一行として数える)は、次のように計算できます。ここでは、テ キストボックス"TextBox1"の現在のカレットの位置を計算しています。 ‥‥▽VB.NET ここから▽‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥ '文字列 Dim str As String = TextBox1.Text 'カレットの位置を取得 Dim selectPos As Integer = TextBox1.SelectionStart 'カレットの位置までの行を数える Dim row As Integer = 1 Dim startPos As Integer = 0 Dim endPos As Integer While (True) endPos = str.IndexOf(vbLf, startPos) If (endPos < 0 Or endPos > selectPos) Then Exit While End If startPos = endPos + 1 row += 1 End While '列の計算 Dim col As Integer = selectPos - startPos + 1 '結果を表示 Console.WriteLine("行:{0} 列:{1}", row, col) ‥‥△VB.NET ここまで△‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥ ‥‥▽C# ここから▽‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥ //文字列 string str = TextBox1.Text; //カレットの位置を取得 int selectPos = TextBox1.SelectionStart; //カレットの位置までの行を数える int row = 1, startPos = 0; for (int endPos = 0; (endPos = str.IndexOf('\n', startPos)) < selectPos && endPos > -1; row++) { startPos = endPos + 1; } //列の計算 int col = selectPos - startPos + 1; //結果を表示 Console.WriteLine("行:{0} 列:{1}", row, col); ‥‥△C# ここまで△‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥ 行を物理的に数える場合(WordWrapがTrueで、右側で折り返されてい れば2行として数える)は、SendMessage関数を使用して取得します。 次の例では、Button1をクリックすることにより、物理的な現在のカ レットの位置を表示しています。 ‥‥▽VB.NET ここから▽‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥ _ Private Shared Function SendMessage( _ ByVal hWnd As IntPtr, _ ByVal Msg As Integer, _ ByVal wParam As Integer, _ ByVal lParam As Integer) As Integer End Function Private Const EM_LINEINDEX As Integer = &HBB Private Const EM_LINEFROMCHAR As Integer = &HC9 'Button1のクリックイベントハンドラ Private Sub Button1_Click(ByVal sender As Object, _ ByVal e As System.EventArgs) Handles Button1.Click '現在の行を取得する Dim row As Integer = SendMessage( _ TextBox1.Handle, EM_LINEFROMCHAR, -1, 0) + 1 '現在の列を取得する Dim lineIndex As Integer = SendMessage( _ TextBox1.Handle, EM_LINEINDEX, -1, 0) Dim col As Integer = TextBox1.SelectionStart - lineIndex + 1 Console.WriteLine("行:{0} 列:{1}", row, col) End Sub ‥‥△VB.NET ここまで△‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥ ‥‥▽C# ここから▽‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥ [System.Runtime.InteropServices.DllImport("User32.Dll")] private static extern int SendMessage( IntPtr hWnd,int Msg,int wParam,int lParam); private const int EM_LINEINDEX = 0xBB; private const int EM_LINEFROMCHAR=0xC9; //Button1のクリックイベントハンドラ private void Button1_Click(object sender, System.EventArgs e) { //現在の行を取得する int row = SendMessage( TextBox1.Handle, EM_LINEFROMCHAR, -1, 0) + 1; //現在の列を取得する int lineIndex = SendMessage( TextBox1.Handle, EM_LINEINDEX, -1, 0); int col = TextBox1.SelectionStart - lineIndex + 1; Console.WriteLine("行:{0} 列:{1}", row, col); } ‥‥△C# ここまで△‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥ なお、リッチテキストボックスの物理的な行は、 GetLineFromCharIndexプロパティでも取得できます。 ○この記事の基になった掲示板のスレッド [題名] リッチテキスト内のカーソル位置の取得 [投稿者(敬称略)] ひまわり, ピラルク [URL] http://dobon.net/vb/bbs/log3-5/2843.html =============================== ■ここで示したコードの多くはまずC#で書き、それを「C# to VB.NET Translator」でVB.NETのコードに変換し、修正を加えたものです。 [URL]C# to VB.NET Translator http://authors.aspalliance.com/aldotnet/examples/translate.aspx ■このマガジンの購読、購読中止、バックナンバー、説明に関しては  次のページをご覧ください。  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. ===============================