C# と VB.NET の質問掲示板

ASP.NET、C++/CLI、Java 何でもどうぞ

ログ内検索
  • キーワードを複数指定する場合は 半角スペース で区切ってください。
  • 検索条件は、(AND)=[A かつ B] (OR)=[A または B] となっています。
  • [返信]をクリックすると返信ページへ移動します。
キーワード/ 検索条件 /
検索範囲/ 強調表示/ ON (自動リンクOFF)
結果表示件数/ 記事No検索/ ON
大文字と小文字を区別する

No.75887 の関連記事表示

<< 0 >>
■75887  Re[6]: オリジナルTextBoxにカスタムコントロール
□投稿者/ 魔界の仮面弁士 -(2015/05/14(Thu) 15:12:55)
    No75882 (ni さん) に返信
    > を同時にイベント処理したい、

    MyTextBox は、System.Windows.Forms.TextBox を継承して作られています。

    TextBox や RichTextBox は System.Windows.Forms.TextBoxBase を継承していますし、
    TextBox は System.Windows.Forms.Control を継承しています。
    そして Control は Object から継承されています。

    …ここまでは認識されているでしょうか?


    アプリ作成時に、まずは Form1 クラスが用意されるかと思いますが、
    これも、System.Windows.Forms.Form クラスを継承したものですし、
    その Form クラスは、System.Windows.Forms.Control を継承しています。


    そして Control クラスには、TextChanged イベントや MouseDown イベントや Click イベントが
    用意されているため、Control の派生クラスである Form や Form1、TextBox や MyTextBox も
    同様にこれらのイベントを利用できるはずです;本来は。

    にもかかわらず
    >> なぜ継承しているのに、イベントが正しく発生しないのか今現在わかりません。
    という状態になるのであれば、イベントが発生しないというよりは、
    コーディング上の問題により、
     ・自作クラス MyTextBox が、イベントを発生させていない
     ・利用側となる Form1 で、そのイベントを受け取っていない
    のいずれかであろうと推察します。



    > 魔界の仮面弁士 さんの例ではTextBox0、TextBox1、TextBox2、
    > と3つ分のイベントをバラバラで回していらっしゃいますが、
    一箇所で受け取りたいのであれば、
    Private Sub TextBoxes_TextChanged(sender As Object, e As EventArgs) Handles TextBox0.TextChanged, TextBox1.TextChanged, TextBox2.TextChanged
    のように、Handles 句で対象イベントを列挙する方法があります。

    ただし、Handles 句を使う場合には、WithEvents 変数も必要になります。
    コントロールが 10 個あるなら、WithEvents 変数も10個必要です。

    あるいは、「AddHandler ステートメント」を用いるのも良いでしょう。
    これなら、WithEvents 変数を用意せずとも、複数のイベントをまとめて処理できます。
    解除する場合は、ご存知のように「RemoveHandler」です。


    Public Class Form1
     Private Sub Test(sender As Object, e As EventArgs)
      MsgBox("クリック@" & sender.GetType().Name & "@" & sender.Name)
     End Sub

     Private Sub Form1_Load(sender As System.Object, e As System.EventArgs) Handles MyBase.Load
      AddHandler Me.TextBox1.Click, AddressOf Me.Test
      AddHandler Me.Label1.Click, AddressOf Me.Test
      AddHandler Me.ListBox1.Click, AddressOf Me.Test
      AddHandler Me.Click, AddressOf Me.Test
     End Sub
    End Class


    もし、
      AddHandler Me.TextBox1.Click, AddressOf Me.Test
      AddHandler Me.TextBox1.Click, AddressOf Me.Test
    のように複数回に割り当てると、イベント通知も複数回発生するので注意して下さい。




    >>標準のコンテキストメニューに対しての操作を、
    >>NativeWindow クラスまたは TextBox クラスの
    >>WndProc メソッドで拾っている、ということでしょうか。
    >>
    >>それとも、ContextMenuStrip プロパティを
    >>差し替えている、ということでしょうか。
    > の辺りの意味が解りませんでした。

    分かりにくくてすみません。
    TextBox のコンテキストメニューは、通常、OS で用意されたものが使われますよね。

    「ContextMenuStrip プロパティを差し替える」というのは、
    ツールボックスからContextMenuStrip をフォームに貼り、それを TextBox の
    ContextMenuStrip プロパティに割り当てることで、標準のメニューではなく
    自作のメニューにするということです。

    そして「WndProc メソッド」の方は、じゃんぬさんの MyTextBox で使われている方法です。
    『Protected Overrides Sub WndProc(ByRef m As Message)』の中で、
    WM_PASTE メッセージを処理している部分がそれにあたります。


    そして、継承せずに WndProc を処理する場合には、NativeWindow クラスを使えます。

    たとえばこんな感じです。下記を実行すると、「コンテキストメニュー」や
    「Ctrl+V」「Shift+Insert」を含むあらゆる貼り付け処理を事前に横取りできます。

    --------------------------
    Imports System.ComponentModel
    Public Class Form1
      Private WithEvents sample As NativeWindowSample

      Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
        sample = New NativeWindowSample(Me.TextBox1)
      End Sub

      Private Sub sample_Pasting(sender As Object, e As CancelEventArgs) Handles sample.Pasting
        If MsgBox("貼り付けますか", vbQuestion Or vbOKCancel) = vbCancel Then
          e.Cancel = True
        End If
      End Sub

    End Class

    Public Class NativeWindowSample
      Inherits NativeWindow
      Private Owner As Form1
      Public Event Pasting As CancelEventHandler

      Public Sub New(owner As Control)
        MyBase.AssignHandle(owner.Handle)
      End Sub

      Protected Overrides Sub WndProc(ByRef m As Message)
        'Const WM_CUT = &H300
        'Const WM_COPY = &H301
        Const WM_PASTE = &H302
        'Const WM_CONTEXTMENU = &H7B

        Dim e As New CancelEventArgs(False)
        If m.Msg = WM_PASTE Then
          RaiseEvent Pasting(Me, e)
        End If
        If Not e.Cancel Then
          MyBase.WndProc(m)
        End If
      End Sub
    End Class
    --------------------------


    > ご提案いただいたTextBoxBaseを取り入れて後、なぜかまったく
    TextBoxBase は利用しないでください。(継承関係の参考として提示しただけです。すみません)
    通常は、TextBox あるいは MyTextBox をそのまま利用すれば OK です。


    > TextBoxBaseでの処理が何か関係あるのでしょうか。
    関係しないと思います。WithEvents 変数の扱いを間違えていたりはしませんか?



    > 常に、最後のUndoが戻ってくる、右クリックコンテキストメニュー内容は
    > 本当にそっくりそのままメモ帳仕様を希望しております。
    であれば無理に作りこまず、標準の Undo 動作を活かす方法を模索するのがよろしいかと。


    > テキストボックスでいくつかの文字列がある時、フォーカスがなくとも
    > 【インターネットブラウザの様に右クリックでカーソルがポイント位置に移動する】
    コンテキストメニューを無効にしてみましたが、その場合、右クリックや中クリックでは、
    フォーカスの移動が行われないようですね。

    とりあえず、こんな感じで如何でしょう。
    WndProc メソッドを下記のように実装してみて下さい。

     Select Case m.Msg
      Case WM_RBUTTONDOWN '&H204
       Dim m2 = Message.Create(m.HWnd, m.Msg, m.WParam, m.LParam)
       m.Msg = WM_LBUTTONDOWN '&H201
       MyBase.WndProc(m)
       MyBase.WndProc(m2)
       Return
      Case …
記事No.75841 のレス /過去ログ128より / 関連記事表示
削除チェック/



<< 0 >>

パスワード/

- Child Tree -