前回において、コンテキストメニューのウインドウとプロパティと動作は終了となります。
基本的にユーザーコントロールのプロパティに依存する形でしょう。
しかし、次のプロパティの設定の前に、重大な問題が残っています。これを今回の課題としたいと。
問題となるのが「コピー」と「貼り付け」です。
このように、貼り付け時にコピー元がフォント情報を持っていると、それごと張り付けられてしまいます。
どこが問題なのか?というと、リッチテキストボックスとして使用する分にも問題ありませんが、通常のテキストボックスとして使用する場合、この動作は誠によろしくないのが実態としてあります。
これは貼り付けだけでなく、縦型テキストボックスを他のウインドウに張り付ける時も同様です。
問題はどのように操作するか?なんですよね。
クリップボードのデータを直接操作するか、クリップボードのデータはそのままで、COPY又は貼り付け時の処理自体に手を加えるか。
今回は後者で考えていきたいと思います。
まずは、Ctrl+V又はCtrl+Cのイベントの取得から。
Select Case uMsg
Case WM_COPY
If Copy() Then
End If
End Select
''' <summary>
''' テキストボックスのモードを設定及び取得します。
''' </summary>
''' <value>リッチテキストボックスモードの場合はTrue。テキストボックスモードの場合はFalse。</value>
''' <returns></returns>
''' <remarks></remarks>
Property RichMode As Boolean = False
''' <summary>
''' コントロールが押されているかどうかの判別用。Trueで押されている。Falseで押されていない。
''' </summary>
''' <remarks></remarks>
Dim _ControlKey As Boolean = False
''' <summary>
''' Ctrl+C or Vの取得のための関数
''' </summary>
''' <param name="uMsg">メッセージ</param>
''' <param name="wParam">パラメータ</param>
''' <returns>True:方向キーの変更を実施 False:方向キーの変更を未実施</returns>
''' <remarks></remarks>
Private Function KeyCheckCopyPaste(ByVal uMsg As IntPtr, ByRef wParam As IntPtr) As Boolean
'リッチテキストモードの場合は何もしない。
If RichMode Then Return True
Select Case wParam
Case Windows.Forms.Keys.ControlKey
Select Case uMsg
Case WM_KEYUP
_ControlKey = False
Case WM_KEYDOWN
_ControlKey = True
End Select
End Select
Return True
End Function
こういう感じのコード書いたのですが、いろいろよくわからない。
次に、動作の順序を確認する必要があるんだろうと判断し、デバックの為
Private Function KeyCheckCopyPaste(ByVal uMsg As IntPtr, ByRef wParam As IntPtr) As Boolean
'リッチテキストモードの場合は何もしない。
If RichMode Then Return True
Select Case wParam
Case Windows.Forms.Keys.ControlKey
Select Case uMsg
Case WM_KEYUP
_ControlKey = False
Case WM_KEYDOWN
_ControlKey = True
End Select
Case Windows.Forms.Keys.V, Windows.Forms.Keys.C
If _ControlKey AndAlso uMsg = WM_KEYDOWN Then
Return False
End If
End Select
Return True
End Function
「TateControlProc」内を下のように記載。
If KeyCheck(uMsg, wParam) = False Then
If KeyCheckCopyPaste(uMsg, wParam) = False Then
'テキストモードであり、コピーまたは貼り付けが選択されています
If wParam = Windows.Forms.Keys.V Then
Debug.Print(count & ":Ctrl+V")
Dim Te As String = Text
Text &= count & ":Ctrl+V" & vbCrLf
Else
Debug.Print(count & ":Ctrl+c")
End If
count += 1
End If
End If
Select Case uMsg
Case WM_COPY
If _ControlKey Then
Debug.Print(count & ":WM_COPY")
count += 1
End If
End Select
すると下記のように、貼り付けられた後にメッセージを拾っています。
なので考え方を変えます。
ユーザーコントロール内にて、Ctrl+V及びCtrl+Cを無効すると同時に、それぞれの処理プロシージャを実行する形に変えます。
''' <summary>
''' ショートカット制御用 Ctrl+C及びctrl+Vの無効及びコピー、貼り付け処理の実施
''' </summary>
''' <param name="msg"></param>
''' <param name="keyData"></param>
''' <returns></returns>
''' <remarks></remarks>
Protected Overrides Function ProcessCmdKey(ByRef msg As System.Windows.Forms.Message, keyData As System.Windows.Forms.Keys) As Boolean
If (keyData And Keys.Control) = Keys.Control AndAlso c IsNot Nothing AndAlso RichMode = False Then
Select Case (keyData And Keys.KeyCode)
Case Keys.V
Call c.Paste()
Return True
Case Keys.C
Call c.Copy()
Return True
End Select
End If
Return MyBase.ProcessCmdKey(msg, keyData)
End Function
''' <summary>
''' 選択されている範囲をコピーする。(テキストボックスモードのみに使用)コピー処理に成功した場合はTrueを、必要ない場合はFalseを返す。
''' </summary>
''' <remarks></remarks>
Public Function Copy() As Boolean
'選択されているテキストを取得し、クリップボードに張り付ける。
'コピーする文字列の有無を確認。
Dim c As AutoVerbMenu.CHARRANGE
Class_API.SendMessageA(_Handle, AutoVerbMenu.EM_GETSEL, c.cpMin, c.cpMax)
'コピーする文字列がない場合は処理を終了する。
If c.cpMax = c.cpMin Then Return False
Dim buf As New System.Text.StringBuilder
buf.Length = 32767
Class_API.SendMessage(_Handle, AutoVerbMenu.EM_GETSELTEXT, 0, buf)
If buf.ToString.Length > 0 Then
Debug.Print(buf.ToString)
Clipboard.SetText(buf.ToString)
Return True
Else
Return False
End If
End Function
''' <summary>
''' クリップボードのデータをボックスに張り付ける(テキストボックスモードのみに使用)
''' </summary>
''' <remarks></remarks>
Public Sub Paste()
Dim temp As IDataObject = Clipboard.GetDataObject
If temp.GetDataPresent(DataFormats.Text) = False Then Exit Sub
Dim str As String = temp.GetData(DataFormats.Text, True)
If str Is Nothing OrElse str.Length = 0 Then Exit Sub
Class_API.SendMessage(_Handle, AutoVerbMenu.EM_REPLACESEL, 0, New System.Text.StringBuilder(str))
End Sub
これで、コピーアンドペースト時に含まれるフォント情報を除外した形で貼り付けとコピーを行うことができるようになりました。
後はコンテキストメニューのボタンをクリックしたときも、テキストボックスモードの時に上記のプロシージャを呼び出すようにしてやれば完了となります。
Ctrl+Paste時
コンテキストメニューからの貼り付け時
最後に、このコンテキストメニューについては、作成時に下記の感じで自動追加する形にしていますが、プロパティで設定できるようにします。
''' <summary>
''' コントロールに追加する
''' </summary>
''' <param name="sender"></param>
''' <remarks></remarks>
Public Sub ADD(ByRef sender As Control)
If IntInstance(sender) = False Then Exit Sub
lpord = Class_API.SetWindowLong(_Handle, Class_API.GWL_WNDPROC, AddressOf TateControlProc)
'mlpord = Class_API.SetWindowLong(_NowParent, Class_API.GWL_WNDPROC, AddressOf MainFormProc)
AddHandler sender.SizeChanged, AddressOf ReSetWindow
AddHandler sender.Move, AddressOf ReSetWindow
'コンテキストメニューの設定
_AVM = New AutoVerbMenu(_Handle)
sender.ContextMenuStrip = _AVM.AVM
_AVM.TateClass = Me
End Sub
これを下記の通りに直す。
''' <summary>
''' コントロールに追加する
''' </summary>
''' <param name="sender"></param>
''' <remarks></remarks>
Public Sub ADD(ByRef sender As Control)
If IntInstance(sender) = False Then Exit Sub
lpord = Class_API.SetWindowLong(_Handle, Class_API.GWL_WNDPROC, AddressOf TateControlProc)
'mlpord = Class_API.SetWindowLong(_NowParent, Class_API.GWL_WNDPROC, AddressOf MainFormProc)
AddHandler sender.SizeChanged, AddressOf ReSetWindow
AddHandler sender.Move, AddressOf ReSetWindow
If _AutoVerbMenu Then AutoVerbMenu = True
End Sub
''' <summary>
''' 標準コンテキストメニュー設定用。
''' </summary>
''' <remarks></remarks>
Dim _AutoVerbMenu As Boolean = False
''' <summary>
''' 右クリック時にコンテキストメニューが自動で表示されるかどうを設定します。表示されるコンテキストメニューは標準のものです。
''' </summary>
''' <value>独自に設定する場合はFalse。標準コンテキストメニューを使用する場合はTrue。</value>
''' <returns></returns>
''' <remarks></remarks>
Property AutoVerbMenu As Boolean
Get
Return _AutoVerbMenu
End Get
Set(value As Boolean)
_AutoVerbMenu = value
If UC Is Nothing Then Exit Property
If UC.ContextMenuStrip IsNot Nothing Then
UC.ContextMenuStrip.Close()
End If
If value = True Then
'コンテキストメニューの設定
Dim _AVM As new AutoVerbMenuSplit(_Handle)
UC.ContextMenuStrip = _AVM.AVM
_AVM.TateClass = Me
End If
End Set
End Property
これでAutoVerbMenuを新たに実装した形となりました。
プロパティ名
|
説明
|
AutoVerbMenu
|
ユーザーがコントロールを右クリックしたときに表示されるショートカットメニューです。
|
ContextMenuStripプロパティについては、ユーザーコントロールに依存する形となります。
プロパティ名
|
説明
|
ContextMenuStrip
|
ユーザーがコントロールを右クリックしたときに表示されるショートカットメニューです。
|
とはいえ、テキストボックス内の文字列などを操作するわけですから、それに合わせた形でプロシージャを一通り用意してやる必要はあるだろうなぁと。
本日はここまで。
参考までに、今までのテストでやってたプロジェクトのデータを添付します。まぁ、こんなものの需要なんてないでしょうがw
0 件のコメント:
コメントを投稿