#title(.NETプログラミング研究 第63号)

#contents

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

**.NET質問箱 [#g8faeb73]

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

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

***16進数、8進数、2進数の文字列を整数に変換する、整数を16進数、8進数、2進数の文字列に変換する [#a5bd1303]

#column(注意){{
この記事の最新版は「[[16進数、8進数、2進数の文字列を整数に変換する>http://dobon.net/vb/dotnet/programing/converthex.html]]」で公開しています。
}}

''【質問】''

16進数、8進数、2進数を表した文字列を整数に変換するには、どのようにすればよいのでしょうか?また逆に整数を16進数、8進数、2進数を表す文字列に変換するにはどのようにすればよいのでしょうか?

''【回答】''

基本的には、文字列を整数に変換するにはConvertクラスのToInt32メソッドを、整数を文字列に変換するにはConvertクラスのToStringメソッドを使います。しかし、これ以外の方法も考えられます。

以下に一つずつ説明していきます。

''16進数の文字列を整数に変換''

ConvertクラスのToInt32メソッド等や、Int32構造体等のParseメソッドを使うことにより可能です。

Convert.ToInt32メソッドを使うと、次のようになります。

#code(vbnet){{
Dim num16 As Integer = Convert.ToInt32("FFFF", 16)
}}

#code(csharp){{
int num16 = Convert.ToInt32("FFFF", 16);
}}

Int32のParseメソッドを使った例は、次のようなものです。なおConvert.ToInt32では変換する文字列の頭に「0x」を付けることができますが、Int32.Parseでは付けることができません。

#code(vbnet){{
Dim num16 As Integer = Integer.Parse("FFFF", _
    System.Globalization.NumberStyles.HexNumber)
}}

#code(csharp){{
int num16 = int.Parse("FFFF",
    System.Globalization.NumberStyles.HexNumber);
}}

VB.NETでは、CInt関数等を使って変換することもできます。

#code(vbnet){{
Dim num16 as Integer = CInt("&HFFFF")
}}

''整数を16進数の文字列に変換''

ConvertクラスのToStringメソッドや、Int32構造体等のToStringメソッドを使います。

Convert.ToStringを使った例は、次の通りです。

#code(vbnet){{
Dim num As Integer = 65535
Dim str As String = Convert.ToString(num, 16)
}}

#code(csharp){{
int num = 65535;
string str = Convert.ToString(num, 16);
}}

Int32.ToStringを使うと、次のようになります。

#code(vbnet){{
Dim num As Integer = 65535
Dim str As String = num.ToString("X")
}}

#code(csharp){{
int num = 65535;
string str = num.ToString("X");
}}

VB.NETでは、Hex関数を使うこともできます。

#code(vbnet){{
Dim num as Integer = 65535
Dim str as String = Hex(num)
}}

''8進数の文字列を整数に変換''

ConvertクラスのToInt32メソッド等を使うことにより、可能です。

#code(vbnet){{
Dim num8 As Integer = Convert.ToInt32("1750", 8)
}}

#code(csharp){{
int num8 = Convert.ToInt32("1750", 8);
}}

VB.NETでは、CInt関数等を使って変換することもできます。

#code(vbnet){{
Dim num8 as Integer = CInt("&O1750")
}}

''整数を8進数の文字列に変換''

ConvertクラスのToStringメソッドにより、可能です。

#code(vbnet){{
Dim num As Integer = 1000
Dim str As String = Convert.ToString(num, 8)
}}

#code(csharp){{
int num = 1000;
string str = Convert.ToString(num, 8);
}}

VB.NETでは、Oct関数を使うこともできます。

#code(vbnet){{
Dim num as Integer = 1000
Dim str as String = Oct(num)
}}

''2進数の文字列を整数に変換''

これも、ConvertクラスのToInt32メソッド等を使うことにより、可能です。

#code(vbnet){{
Dim num2 As Integer = Convert.ToInt32("1111101000", 2)
}}

#code(csharp){{
int num2 = Convert.ToInt32("1111101000", 2);
}}

''整数を2進数の文字列に変換''

これも、ConvertクラスのToStringメソッドにより、可能です。

#code(vbnet){{
Dim num As Integer = 1000
Dim str As String = Convert.ToString(num, 2)
}}

#code(csharp){{
int num = 1000;
string str = Convert.ToString(num, 2);
}}

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

-[[string "ff"を数値型の 255 に変換したい | 投稿者(敬称略) yukko, よねKEN>http://dobon.net/vb/bbs/log3-7/3881.html]]

***フォームの「閉じる」ボタンを無効にする [#e1a547c2]

#column(注意){{
この記事の最新版は「[[フォームの「閉じる」ボタンを無効にする>http://dobon.net/vb/dotnet/form/disabledclosebutton.html]]」で公開しています。
}}

''【質問】''

Windowsフォームの右上にある「閉じる」ボタン(Xボタン)を無効にしたいのですが、どのようにすればよいでしょうか?

''【回答】''

幾つかの方法が考えられます。

まず一番単純なのは、フォームのControlBoxプロパティをFalseにしたり、FormBorderStyleプロパティをNoneにしたりすることにより、「閉じる」ボタンを消す方法です。この場合は、最小化、最大化ボタン、コントロールボックスも消えてしまうという欠点があります。

また、「フォームが閉じられる時その原因を知る」と「条件によりフォームが閉じられないようにする」により、「閉じる」ボタンが押されてフォームが閉じられる場合に、フォームを閉じないようにする方法もあります。

-[[DOBON.NET .NET Tips - フォームが閉じられる時その原因を知る>http://dobon.net/vb/dotnet/form/unloadmode.html]]
-[[DOBON.NET .NET Tips - 条件によりフォームが閉じられないようにする>http://dobon.net/vb/dotnet/form/closingcancel.html]]

この方法を使った例は、次のようなものです。なおこの例では、システムメニューの「閉じる」や、「Alt」+「F4」キーも無効になります。

#code(vbnet){{
Protected Overrides Sub WndProc( _
        ByRef m As System.Windows.Forms.Message)
    Const WM_SYSCOMMAND As Integer = &H112
    Const SC_CLOSE As Integer = &HF060

    If m.Msg = WM_SYSCOMMAND And m.WParam.ToInt32() = SC_CLOSE Then
        Return
    End If

    MyBase.WndProc(m)
End Sub
}}

#code(csharp){{
protected override void WndProc(ref Message m)
{
    const int WM_SYSCOMMAND = 0x112;
    const int SC_CLOSE = 0xF060;

    if (m.Msg == WM_SYSCOMMAND && m.WParam.ToInt32() == SC_CLOSE)
    {
        return;
    }

    base.WndProc (ref m);
}
}}

補足:上の例では「条件によりフォームが閉じられないようにする」は使いませんでした。これを使う場合は、「閉じる」ボタンが押された時にフラッグを立てて、Closingイベントで閉じないようにします。

さらに、GotDotNetの掲示板の「Disabling the close button?」にMickDohertyさんがとてもおもしろい投稿をされています。

-[[GotDotNet Message Boards - Disabling the close button?>http://www.gotdotnet.com/Community/MessageBoard/Thread.aspx?id=248554&Page=1#248801]]

これはフォームのCreateParamsプロパティをオーバーライドするという方法で、「閉じる」ボタンが無効状態となり、押すことができなくなります。システムメニューの「閉じる」も表示されなくなり、「Alt」+「F4」キーも無効になります。

以下にそのコードを引用させていただきます。

#code(vbnet){{
Protected Overrides ReadOnly Property CreateParams() As _
        System.Windows.Forms.CreateParams
    Get
        Const CS_NOCLOSE As Integer = &H200
        Dim cp As CreateParams = MyBase.CreateParams
        cp.ClassStyle = cp.ClassStyle Or CS_NOCLOSE

        Return cp
    End Get
End Property

}}

#code(csharp){{
protected override CreateParams CreateParams
{
    get
    {
        const int CS_NOCLOSE = 0x200;
        CreateParams cp = base.CreateParams;
        cp.ClassStyle = cp.ClassStyle | CS_NOCLOSE;

        return cp;
    }
}
}}

最後にWin32 APIを使う方法も紹介しておきます。下記の方法では、「閉じる」ボタンが無効状態となり、システムメニューの「閉じる」が表示されなくなりますが、「Alt」+「F4」キーは有効です。

#code(vbnet){{
<System.Runtime.InteropServices.DllImport("user32.dll")> _
Shared Function GetSystemMenu(ByVal hWnd As IntPtr, _
    ByVal bRevert As Boolean) As IntPtr
End Function

<System.Runtime.InteropServices.DllImport("user32.dll")> _
Shared Function GetMenuItemCount(ByVal hMenu As IntPtr) As Integer
End Function

<System.Runtime.InteropServices.DllImport("user32.dll")> _
Shared Function DrawMenuBar(ByVal hWnd As IntPtr) As Boolean
End Function

<System.Runtime.InteropServices.DllImport("user32.dll")> _
Shared Function RemoveMenu(ByVal hMenu As IntPtr, _
    ByVal uPosition As Integer, _
    ByVal uFlags As Integer) As Boolean
End Function

Protected Overrides Sub OnLoad(ByVal e As EventArgs)
    MyBase.OnLoad(e)

    Const MF_BYPOSITION As Int32 = &H400
    Const MF_REMOVE As Int32 = &H1000

    Dim menu As IntPtr = GetSystemMenu(Me.Handle, False)
    Dim menuCount As Integer = GetMenuItemCount(menu)
    If menuCount > 1 Then
        'メニューの「閉じる」とセパレータを削除
        RemoveMenu(menu, menuCount - 1, MF_BYPOSITION Or MF_REMOVE)
        RemoveMenu(menu, menuCount - 2, MF_BYPOSITION Or MF_REMOVE)
        DrawMenuBar(Me.Handle)
    End If
End Sub
}}

#code(csharp){{
[System.Runtime.InteropServices.DllImport("user32.dll")]
static extern IntPtr GetSystemMenu(IntPtr hWnd, bool bRevert);
[System.Runtime.InteropServices.DllImport("user32.dll")]
static extern int GetMenuItemCount(IntPtr hMenu);
[System.Runtime.InteropServices.DllImport("user32.dll")]
static extern bool DrawMenuBar(IntPtr hWnd);
[System.Runtime.InteropServices.DllImport("user32.dll")]
static extern bool RemoveMenu(IntPtr hMenu, uint uPosition, uint uFlags);

protected override void OnLoad(EventArgs e)
{
    base.OnLoad (e);

    const Int32 MF_BYPOSITION = 0x400;
    const Int32 MF_REMOVE = 0x1000;

    IntPtr menu = GetSystemMenu(this.Handle, false);
    int menuCount = GetMenuItemCount(menu);
    if (menuCount > 1)
    {
        //メニューの「閉じる」とセパレータを削除
        RemoveMenu(menu, (uint) (menuCount - 1), MF_BYPOSITION | MF_REMOVE);
        RemoveMenu(menu, (uint) (menuCount - 2), MF_BYPOSITION | MF_REMOVE);
        DrawMenuBar(this.Handle);
    }
}
}}

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

-[[フォーム右上の閉じるボタン無効化 | 投稿者(敬称略) なかじ, 琴, NowhereMan, 管理人>http://dobon.net/vb/bbs/log3-7/3914.html]]

***TextBoxやRichTextBoxのタブの幅を変更する [#o9535c93]

#column(注意){{
この記事の最新版は「[[TextBoxやRichTextBoxのタブの幅を変更する>http://dobon.net/vb/dotnet/control/tbtacwidth.html]]」で公開しています。
}}

''【質問】''

TextBoxやRichTextBoxのタブの幅(文字数)を変更することができますか?

''【回答】''

RichTextBoxであれば、SelectionTabsプロパティにより、タブの位置を設定することができます。ただしこれはタブの位置をピクセル単位で、数値型の配列として指定するものです。

SelectionTabsプロパティを使わないのであれば、Win32 APIを使うことになります。EM_SETTABSTOPSメッセージを使って、タブ幅の文字数を指定できます。

次の例では、Button1をクリックすることにより、TextBox1のタブの幅を16にしています。

#code(vbnet){{
<System.Runtime.InteropServices.DllImport("User32.dll")> _
Shared Function SendMessage(ByVal hWnd As IntPtr, _
    ByVal msg As Integer, ByVal wParam As Integer, _
    ByVal lParam() As Integer) As IntPtr
End Function

Private Sub Button1_Click(ByVal sender As Object, _
    ByVal e As System.EventArgs) Handles Button1.Click
    Const EM_SETTABSTOPS As Integer = &HCB
    SendMessage(TextBox1.Handle, EM_SETTABSTOPS, 1, New Integer() {16})
End Sub
}}

#code(csharp){{
[System.Runtime.InteropServices.DllImport("User32.dll")]
static extern IntPtr SendMessage(
    IntPtr hWnd, int msg, int wParam, int [] lParam);

private void Button1_Click(object sender, System.EventArgs e)
{
    const int EM_SETTABSTOPS = 0x00CB;
    SendMessage(TextBox1.Handle, EM_SETTABSTOPS, 1, new int[] {16});
}
}}

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

-[[RichTextBox等のTabの幅を変えたい | 投稿者(敬称略) 春原, よねKEN>http://dobon.net/vb/bbs/log3-2/983.html]]
-[[textBoxでTAB幅調整について | 投稿者(敬称略) てんてん, YUSK, 管理人, 花ちゃん, 秋, 小野@どっとねっとふぁん>http://dobon.net/vb/bbs/log3-13/7193.html]]

***AutoScrollをTrueにしてスクロールバーを表示された時、指定した位置までスクロールする [#h33524d7]

#column(注意){{
この記事の最新版は「[[AutoScrollをTrueにしてスクロールバーを表示された時、指定した位置までスクロールする>http://dobon.net/vb/dotnet/form/autoscrollposition.html]]」で公開しています。
}}

''【質問】''

フォームのAutoScrollプロパティをTrueにしてスクロールバーを表示しているのですが、この時指定した位置までスクロールするにはどのようにすればよいのでしょうか?

''【回答】''

AutoScrollPositionプロパティにより、スクロールの位置を設定することができます。

AutoScrollPositionプロパティにスクロール位置を設定する場合は、スクロールの開始位置からどれだけ離れているかを正の整数で設定します。つまり、垂直スクロールバーでは下に、水平スクロールバーでは右に移動させるほど、大きな値を設定します。ところがAutoScrollPositionプロパティでスクロール位置を取得する時は、逆にスクロールの開始位置からどれだけ離れているかが負の整数で取得できます。例えばAutoScrollPositionプロパティに(100, 200)という位置を設定した後、AutoScrollPositionを取得すると、(-100, -200)となります。

現在の位置から右、下に10ずつスクロールさせるには、次のようにします。

#code(vbnet){{
Me.AutoScrollPosition = _
    New Point(-Me.AutoScrollPosition.X + 10, _
        -Me.AutoScrollPosition.Y + 10)
}}

#code(csharp){{
this.AutoScrollPosition =
    new Point(-this.AutoScrollPosition.X + 10,
        -this.AutoScrollPosition.Y + 10);
}}

また、ScrollControlIntoViewメソッドにより、指定したコントロールが表示されるようにスクロールすることができます。MSDNではScrollControlIntoViewメソッドについて、「このメンバは、.NET Framework インフラストラクチャのサポートを目的としています。独自に作成したコード内で直接使用することはできません。」とありますが、これは間違いで、問題なく使用できるようです(注)。

注:ニュースグループにマイクロソフトからの投稿があります。

-[[microsoft.public.dotnet.framework.windowsforms - Re: how to set scroll position programatically>http://groups.google.co.jp/group/microsoft.public.dotnet.framework.windowsforms/msg/d50dbbfb21b082c6?hl=ja&]]

補足:SB_THUMBPOSITIONやSB_THUMBTRACKメッセージによりスクロールさせる場合は、メッセージを送った後にSetDisplayRectLocationメソッドを呼び出さなければ正常に機能しないケースがあるようです。詳しくは、次のURL先をご覧ください。

-[[microsoft.public.dotnet.framework.windowsforms - Re: scrolling a panel>http://groups.google.co.jp/group/microsoft.public.dotnet.framework.windowsforms/msg/0286f32da273504a?hl=ja&]]

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

-[[フォームのスクロール | 投稿者(敬称略) UMU, NowhereMan>http://dobon.net/vb/bbs/log3-7/3962.html]]

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

//これより下は編集しないでください
#pageinfo([[:Category/.NET]],2006-01-09 (月) 18:00:00,DOBON!,2010-03-22 (月) 03:02:27,DOBON!)
[ トップ ]   [ 新規 | 子ページ作成 | 一覧 | 単語検索 | 最終更新 | ヘルプ ]