2014年9月19日金曜日

縦書きテキストボックスコントロールの作成(その11)



今回はスタイルの変更に着手したいと思います。
プロパティ名
説明
BorderStyle
エディットコントロールに境界線を付けるかどうかを示します。Fixed3D,FixedSingle,None

スタイルの変更に関してはほかのプロパティでも使用するので早めに作っておくのがよいでしょう。


スタイルの取得は「GetWindowLong」関数を使用するので、宣言しておきます。

''' <summary>
''' 指定されたウインドウの属性を取得します。拡張ウインドウメモリ内に指定されたオフセット位置にあるlongデータも設定できます
''' </summary>
''' <param name="hWnd">ウインドウのハンドル</param>
''' <param name="nIndex">取得する値のオフセット</param>
''' <returns>成功すると、要求の値が帰ります。失敗すると0が返ります。</returns>
''' <remarks></remarks>
<System.Runtime.InteropServices.DllImport("user32.dll", SetLastError:=True)> _
Friend Function GetWindowLong(ByVal hWnd As IntPtr, ByVal nIndex As IntPtr) As IntPtr
End Function
スタイルの設定は先に宣言していた通り「SetWindowLong」を使用します。
ボーダースタイルの種類は、標準で用意されているのは三種類です。
None」「FixedSingle」「Fixed3D
Fixed3Dは今現在、CreateWindowEXで作成時に指定した「WS_EX_CLIENTEDGE」です。
実のところ、「WS_EX_CLIENTEDGE」ですが、「WS_BORDER」で指定してやっても同様のレイアウトになります。
None」は何も指定しなければいけると思いますが、さて「FixedSingle」をどうするか、、、実のところどのパラメーターを指定してやればいいかわかんないんですよね。現状のパラメーターを組み合わせれば行けるんだろうか?と思って試してみました。



 
 
 
 
 
拡張ではなく、通常ウインドウスタイル定数を指定
 
あまり時間をかけるのも面白くないので、ユーザーコントロール側にも働いてもらうことで疑似的に再現することにしました。

''' <summary>
''' ボーダースタイルを設定する。
''' </summary>
''' <value></value>
''' <returns></returns>
''' <remarks></remarks>
Public Overloads Property BorderStyle As Windows.Forms.BorderStyle
    Get
        Return Module_BorderStyle.BorderStyle
    End Get
    Set(value As Windows.Forms.BorderStyle)
        Static Mode As Boolean
        If Mode = False Then
            Mode = True
            If Me.DesignMode = False AndAlso Me.ParentForm IsNot Nothing AndAlso Me.ParentForm.Handle <> Me.Handle Then
                Module_BorderStyle.BorderStyle = value
                Select Case value
                    Case Windows.Forms.BorderStyle.FixedSingle
                        MyBase.BorderStyle = Windows.Forms.BorderStyle.FixedSingle
                    Case Windows.Forms.BorderStyle.Fixed3D
                        MyBase.BorderStyle = Windows.Forms.BorderStyle.None
                    Case Windows.Forms.BorderStyle.None
                        MyBase.BorderStyle = Windows.Forms.BorderStyle.None
                End Select
                Call ReSetWindow(Me, Nothing)
            Else
                _BorderStyle = value
                MyBase.BorderStyle = value
            End If
            Mode = False
        End If
    End Set
End Property
''' <summary>
''' 現在のボーダースタイルの設定
''' </summary>
''' <remarks></remarks>
Friend _BorderStyle As Windows.Forms.BorderStyle
''' <summary>
''' ボーダースタイルを設定する。
''' </summary>
''' <value></value>
''' <returns></returns>
''' <remarks></remarks>
Public Property BorderStyle As Windows.Forms.BorderStyle
    Get
        Return _BorderStyle
    End Get
    Set(value As Windows.Forms.BorderStyle)
        _BorderStyle = value
        Select Case value
            Case BorderStyle.Fixed3D
                Call SetWindowLong(_Handles.TextBox, nIndex.GWL_EXSTYLE, WS_EX_CLIENTEDGE)
            Case Else
                Call SetWindowLong(_Handles.TextBox, nIndex.GWL_EXSTYLE, 0)
        End Select
    End Set
End Property
 
 

ボーダースタイルの種類によって、縦型テキストボックスのサイズの微調整も必要です。
そのため、スタイル変更毎に「Call ReSetWindow(Me, Nothing)」を呼び出している形となります。
また、サイズの変更がないままだと、フレームスタイルのプロパティを変更しても、サイズが変更されるまで現状のフレームレイアウトを維持します。
そのため、SetWindowPosでの指定で「SWP_FRAMECHANGED」を追記してやる必要があります。
''' <summary>サイズ変更時の処理</summary>
Friend Sub ReSetWindow(sender As Object, e As System.EventArgs)
    Select Case _BorderStyle
        Case Windows.Forms.BorderStyle.FixedSingle
            SetWindowPos(_Handles.TextBox, 0, sender.left + 1, sender.top + 1, sender.Width - 2, sender.Height - 2, SWP_NOMOVE Or SWP_NOZORDER)
        Case Else ' Windows.Forms.BorderStyle.None
            SetWindowPos(_Handles.TextBox, 0, sender.left, sender.top, sender.Width, sender.Height, SWP_FRAMECHANGED Or SWP_NOMOVE Or SWP_NOZORDER)
    End Select

    'エラーが頻発するようなら数値を挙げる
    System.Threading.Thread.Sleep(10)
End Sub
これで、ようやっと見た目上の上でのフレームレイアウトの変更が完了しました。

0 件のコメント:

コメントを投稿