縦書きにはできましたが、まだコントロールとしての動作で不足している部分が見受けられます。
CoreateWindow関数で作ってやっているので、プロパティを変更するにはAPIで宣言するしかないのですが、このままではやはり使いにくい、、、
ということで、作成したコントロールにプロパティを持たせてやろうと思います。
まず最初に気になったのが、コントロールのサイズが固定されてしまう部分。
hwndEdit = Class_API.CreateWindowEx(Class_API.WS_EX_CLIENTEDGE, "RICHEDIT50W", "",
Class_API.WS_CHILD + Class_API.WS_VISIBLE + Class_API.ES_MULTILINE,
Me.Left, Me.Top,
Me.Width, Me.Height,
Me.Handle, IntPtr.Zero,
IntPtr.Zero, IntPtr.Zero)
という風に「Me.Left, Me.Top, Me.Width, Me.Height」で位置とサイズを宣言しています。
コントロールを作成するとき、事前にサイズと位置を固定し変更しないのであれば定数に固定値を入れてやればいいのですが、実際はデザイン時しているのは可変したいですし、コントロールをDOCKしているときはウインドウのサイズが変更するのに合わせて可変させたいわけです。
なのでまず、コントロールに「Location」と「Size」及び「top」「left」「width」「Height」当たりのプロパティをつける方向で追加したいと考えます。
で、それらを操作するAPI関数といえば、「GetWindowRect」関数と「SetWindowPos」関数の二つになるかなと思われます。
前者は位置とサイズの取得に、後者は設定に使用する形です。
まずはそれぞれの定数を含めた宣言から。なお、「GetWindowRect」は構造体に値を格納するため、それに合わせた構造体を宣言する必要があります。
#Region "GetWindowRect関連"
''' <summary>ウインドウの位置及びサイズ情報格納用構造体</summary>
Structure RECT
''' <summary>左位置</summary>
Public left As Integer
''' <summary>上位置</summary>
Public top As Integer
''' <summary>右位置</summary>
Public right As Integer
''' <summary>下位置</summary>
Public bottom As Integer
End Structure
''' <summary>
''' 指定されたウインドウの左上端と右下端の座標をスクリーン座標で取得します。
''' </summary>
''' <param
name="hWnd">ウインドウのハンドル</param>
''' <param
name="lpRect">ウインドウの座標値</param>
''' <returns></returns>
''' <remarks>スクリーン座標は、表示画面の左上端が0,0となります</remarks>
<System.Runtime.InteropServices.DllImport("user32.dll", SetLastError:=True, CharSet:=System.Runtime.InteropServices.CharSet.Auto)> _
Public Shared Function GetWindowRect(ByVal
hWnd As IntPtr,
ByRef lpRect As
RECT) As Boolean
End Function
#End Region
#Region "SetWindowPos関連"
''' <summary>
''' 子ウインドウ、ポップアップウインドウ、またはトップレベルウインドウのサイズ、位置及びZオーダーを変更します。
''' </summary>
''' <param
name="hWnd">ウインドウのハンドル</param>
''' <param
name="hWndInsertAfter">配置順序のハンドル</param>
''' <param
name="x">横方向の位置</param>
''' <param
name="y">縦方向の位置</param>
''' <param
name="cx">幅</param>
''' <param
name="cy">高さ</param>
''' <param
name="uFlags">ウインドウ位置のオプション</param>
''' <returns></returns>
''' <remarks>これらのウインドウは、その画面上での表示に従って順序が決められます。最前面にあるウインドウは最も高いランクを与えられ、Zオーダーの先頭におかれます</remarks>
<System.Runtime.InteropServices.DllImport("user32.dll", SetLastError:=True, CharSet:=System.Runtime.InteropServices.CharSet.Auto)> _
Public Shared Function SetWindowPos(ByVal
hWnd As IntPtr,
ByVal hWndInsertAfter As
IntPtr, ByVal
x As Integer, ByVal y As Integer, cx As Integer, cy As Integer, uFlags As UInteger) As Boolean
End Function
#Region "hWndInsertAfter用パラメータ"
''' <summary>ウインドウをZオーダーの最後に置きます。hWndパラメーターで指定したウインドウが最前面ウインドウだった場合、このウインドウは最前面ウインドウではなくなり、ほかのすべてのウインドウの下に置かれます。</summary>
Friend Const
HWND_BOTTOM As Integer
= 1
''' <summary>ウインドウを最前面ウインド以外のすべてのウインドウの前(つまり、すべての最前面ウインドウの後ろ)に挿入します。hWndパラメータで指定したウインドウがすでに最善目ぬ引導ではなかった場合、このフラグは意味を持ちません。</summary>
Friend Const
HWND_NOTOPMOST As Integer
= -2
''' <summary>ウインドウをZオーダーの先頭に置きます。</summary>
Friend Const HWND_TOP
As Integer = 0
''' <summary>ウインドウを最前面ウインドではないすべてのウインドウの前に挿入します。子のウインドウは、アクティブでないときにも最前面に表示されます。</summary>
Friend Const
HWND_TOPMOST As Integer
= -1
#End Region
#Region "uFlags用パラメータ"
''' <summary>この関数を呼び出したスレッドとウインドウを所有するスレッドが異なる入力キューに関連付けられている場合、ウインドウを所有するスレッドへ要求が送られます。こうすると、要求を受け取ったスレッドが要求を処理している間も、関数を呼び出したスレッドの実行が止まってしまうことはありません。</summary>
Friend Const SWP_ASYNCWINDOWPOS
As Integer =
&H4000
''' <summary>WM_SYNCPAINTメッセージが生成されないようにします。</summary>
Friend Const
SWP_DEFERERASE As Integer
= &H2000
''' <summary>ウインドウを囲む枠(ウインドウクラスの記述部分で定義されている)を描画します</summary>
Friend Const
SWP_DRAWFRAME As Integer
= &H20
''' <summary>SetWindoLong関数を使って新しいフレームスタイルの設定を適用します。ウインドウサイズが変更されない場合にも、ウインドウにWM_NCCALCSIZEメッセージを送ります。このフラグを指定しなかった場合、ウインドウサイズが変更される場合にしかWM_NCCALCSIZEメッセージは送られません。</summary>
Friend Const
SWP_FRAMECHANGED As Integer
= &H20
''' <summary>ウインドウを非表示にします</summary>
Friend Const
SWP_HIDEWINDOWS As Integer
= &H80
''' <summary>ウインドウをアクティブ化しません。このフラグをセットしなかった場合、ウインドウはアクティブ化され、最前面ウインドウまたは非最前面ウインドウのどちらかのグル―プ(hWndInsertAferパラメータの設定による)の最上位にいどうします。</summary>
Friend Const
SWP_NOACTIVATE As Integer
= &H10
''' <summary>クライアント領域の内容全体を破棄します。このフラグをセットしなかった場合は、クライアント領域の有効な内容が保存され、再配置後のウインドウクライアント領域にコピーしなおされます。</summary>
Friend Const
SWP_NOCOPYBITS As Integer
= &H100
''' <summary>現在の位置を維持します(XパラメーターとYパラメーターを無視します)</summary>
Friend Const
SWP_NOMOVE As Integer
= &H2
''' <summary>オーナーウインドウのZオーダーを変更しません。</summary>
Friend Const
SWP_NOOWNERZORDER As Integer
= &H200
''' <summary>変更結果を再描画しません。このフラグを指定すると、再描画は一切行われません。このフラグは、クライアント領域、非クライアント領域、及び親ウインドウの、子のウインドウが移動した結果あらわれた部分すべてに適用されます。このフラグをセットした場合、ウインドウや親ウインドウの再描画の必要な場合は、アプリケーションで明示的に無効化または再描画しなければなりません。</summary>
Friend Const
SWP_NOREDRAW As Integer
= &H8
''' <summary>SWP_NOOWNERZORDERと同じです。</summary>
Friend Const
SWP_NOREPOSITION As Integer
= SWP_NOOWNERZORDER
''' <summary>ウインドウにWM_WINDOWPOSCHANGINGメッセージが送られないようにします。</summary>
Friend Const
SWP_NOSENDCHANGING As Integer
= &H400
''' <summary>現在のサイズを維持します(cxパラメーターとcyパラメータを無視します)</summary>
Friend Const
SWP_NOSIZE As Integer
= &H1
''' <summary>現在のZオーダーを維持します(hWndInsertAfterパラメータを無視します)</summary>
Friend Const
SWP_NOZORDER As Integer
= &H4
''' <summary>ウインドウを表示します。</summary>
Friend Const
SWP_SHOWWINDOW As Integer
= &H40
#End Region
#End Region
使うかどうかはともかく、定数も事前に宣言しておきます。
次に、というか最初にやらなければならなかったかもしれませんが、テキストの入出力も同様にやります。
「SetWindowText」関数と「GetWindowText」関数あたりを使えば行けるかな? と思ったのですが、結論から言うと「GetWindowText」関数の方がエラーを吐き出してうまくいかない。
仕方がないので「SendMessage」関数の方で実装します。
''' <summary>
''' 縦書きコントロールのサイズの取得と設定
''' </summary>
''' <value>サイズ</value>
''' <returns></returns>
''' <remarks></remarks>
Property SizeText As System.Drawing.Size
Get
Dim r As Class_API.RECT
Class_API.GetWindowRect(hwndEdit, r)
Return New Size(r.right - r.left, r.bottom - r.top)
End Get
Set(value As
System.Drawing.Size)
Dim r As Class_API.RECT
Class_API.GetWindowRect(hwndEdit, r)
Class_API.SetWindowPos(hwndEdit, 0, r.left, r.top,
value.Width, value.Height, Class_API.SWP_NOMOVE
Or Class_API.SWP_NOZORDER)
End Set
End Property
''' <summary>
''' コントロールのサイズ変更に合わせて、縦書きボックスのサイズも変更する。
''' </summary>
''' <param
name="sender"></param>
''' <param
name="e"></param>
''' <remarks></remarks>
Private Sub
TateTextBox_SizeChanged(sender As Object, e As System.EventArgs) Handles
Me.SizeChanged
Dim s As
System.Drawing.Size = Me.Size
SizeText = s
End Sub
''' <summary>
''' テキストの取得と設定
''' </summary>
''' <value></value>
''' <returns></returns>
''' <remarks></remarks>
Property Texts As String
Get
Dim buf As New System.Text.StringBuilder
buf.Length
= 32767
Class_API.SendMessage(hwndEdit, Class_API.WM_GETTEXT, buf.Length, buf)
Return buf.ToString
End Get
Set(value As String)
Call Class_API.SetWindowText(hwndEdit,
value)
End Set
End Property
とりあえずうまくいきました。
しかし、アルファベットのフォント情報が違うのか、微妙に違うのがわかります。
テキスト情報のみの受け渡しでしかありませんので仕方がありませんが、文字のフォント情報の取得(ボックスではない)を個別設定したいときは、フォント情報ごと取得できるようなプロパティをどうにかしないといけないかもしれません。
また、メモ帳などでは右クリックでコピーや貼り付けといったメニューが現れますが、リッチテキストボックスの場合は自作してやらないとどうにもなりません。
なんだかデザイナを使わずにやるのはどうにもめんどくさくなってきたぞ、、、
0 件のコメント:
コメントを投稿