- PR -

コンボボックスの右クリックの貼り付けイベント取得について

1
投稿者投稿内容
yamayama
ベテラン
会議室デビュー日: 2006/02/10
投稿数: 68
投稿日時: 2006-02-10 16:49
vb.net2003のことでお聞きしたいのですが、
コンボボックスに貼り付ける場合、クリップボードの内容が数値である場合は、貼り付けを行い。数値以外の文字列であれば貼り付けを禁止するプログラムを実現したいと思い、コンボボックスを継承したコントロールで上記の内容を実現したいと考えております。
そこで
Protected Overrides Sub WndProc(ByRef m As System.Windows.Forms.Message)
If m.Msg = &H302 Then
・・・
End If
MyBase.WndProc(m)
End Sub
とコーディングしたのですが、貼り付けした場合のイベントが取得できません。
初心者で申し訳ないのですが教えてください。
じゃんぬねっと
ぬし
会議室デビュー日: 2004/12/22
投稿数: 7811
お住まい・勤務地: 愛知県名古屋市
投稿日時: 2006-02-10 16:59
引用:

yamachanさんの書き込み (2006-02-10 16:49) より:

とコーディングしたのですが、貼り付けした場合のイベントが取得できません。


WM_PASTE は ComboBox では捕えることができません。
実際には ComboBox 内の EditBox で起きているんじゃないかな。(確か)

TextChanged イベントなどでやった方が現実的かもしれません。

_________________
C# と VB.NET の入門サイト
じゃんぬねっと日誌
ya
大ベテラン
会議室デビュー日: 2002/05/03
投稿数: 212
投稿日時: 2006-02-10 17:45
まぁTextChangedでやるのが現実的でしょうね。それだけだと何なので恐らくできるだろうやり方を書いときます。確認していないので実際にできるかどうかはSpy++あたりで監視するなりして自力で確認してみてください。

GetComboBoxInfoを使用するとCOMBOBOXINFO 構造体からhWndItemフィールドでエディットボックスのハンドルを取得できます。これを使用して、エディットボックスをサブクラス化すればいいわけです。
ちなみにサブクラス化ですが、WinFormsではサブクラス化用にNativeWindowクラスというものがありますのでこれを使用するとよいです。
以上が概要で、具体的にどうするかですが、

1.サブクラス化用に、ネイティブウィンドウから継承し、WndProcをオーバーライドして自分が望むコード(この場合はWM_PASTEの場合に特殊な処理を行うこと)を実装する。
2.ComboBox.HandleCreatedイベントのハンドラを定義する。
3.HandleCreatedのイベントハンドラにおいて、ComboBoxのハンドルからエディットボックスのハンドラを取得し、先ほど作成したNativeWindow継承クラスをAsignする。

※これは実は「ComboBoxのハンドルが作成された後エディットボックスのハンドルは変更されない」という前提で説明しています。これには保証がないため実際はこの辺の動作を調べたり、エディットボックスのWndProcでWM_DESTROYやらに対して追加コードが必要になるかもしれません。

# ちなみにDropDownのほうは色々いじったことがあるのです
じゃんぬねっと
ぬし
会議室デビュー日: 2004/12/22
投稿数: 7811
お住まい・勤務地: 愛知県名古屋市
投稿日時: 2006-02-11 01:58
適当な雛形。

コード:

Option Strict On

Public Class ExactComboBox
    Inherits System.Windows.Forms.ComboBox

  #Region " コンポーネント デザイナで生成されたコード "

    Private components As System.ComponentModel.IContainer

    Public Sub New()
        MyBase.New()
        Me.components = New System.ComponentModel.Container()
    End Sub

    Protected Overloads Overrides Sub Dispose(ByVal disposing As Boolean)
        If disposing = True Then
            If Not Me.components Is Nothing Then
                Me.components.Dispose()
            End If
        End If

        MyBase.Dispose(disposing)
    End Sub
  
  #End Region

  #Region " P/Invoke - GetComboBox 関数 "

    <System.Runtime.InteropServices.DllImport("USER32.DLL")> _
    Private Shared Function GetComboBoxInfo( _
        ByVal comboBoxHandle As System.IntPtr, _
        ByRef pComboBoxInfo  As ComboBoxInfo) As Boolean
    End Function

  #End Region

  #Region " ComboBoxInfo 構造体 "

    <System.Runtime.InteropServices.StructLayout(System.Runtime.InteropServices.LayoutKind.Sequential)> _
    Private Structure ComboBoxInfo
        Public Size           As Integer
        Public RectItem       As System.Drawing.Rectangle
        Public RectButton     As System.Drawing.Rectangle
        Public ButtonState    As Integer
        Public ComboBoxHandle As System.IntPtr
        Public EditBoxHandle  As System.IntPtr
        Public ListBoxHandle  As System.IntPtr
    End Structure

  #End Region

  #Region " EditBoxWindow クラス "

    Private Class EditBoxWindow
        Inherits System.Windows.Forms.NativeWindow

        Public Sub New(ByVal parentComboBox As ComboBox)
            AddHandler parentComboBox.HandleDestroyed, AddressOf Me.OnHandleDestroyed
        End Sub

        Private Sub OnHandleDestroyed(ByVal sender As Object, ByVal e As System.EventArgs)
            Me.ReleaseHandle()
        End Sub

        <System.Security.Permissions.PermissionSetAttribute(System.Security.Permissions.SecurityAction.Demand)> _
        Protected Overrides Sub WndProc(ByRef m As Message)
            Const WM_PASTE As Integer = &H0302

            Select Case m.Msg
                Case WM_PASTE
                    MessageBox.Show("WM_PASTE")
            End Select

            MyBase.WndProc(m)
        End Sub

    End Class

  #End Region

  #Region " OnHandleCreated メソッド (Override) "

    Protected Overrides Sub OnHandleCreated(ByVal e As System.EventArgs)
        Dim tComboBoxInfo As New ComboBoxInfo()

        tComboBoxInfo.Size = System.Runtime.InteropServices.Marshal.SizeOf(tComboBoxInfo)

        If GetComboBoxInfo(Me.Handle, tComboBoxInfo) = False Then
            Return
        End If

        If tComboBoxInfo.EditBoxHandle.Equals(System.IntPtr.Zero) Then
            Return
        End If

        Dim hEditBoxWindow As New EditBoxWindow(Me)
        hEditBoxWindow.AssignHandle(tComboBoxInfo.EditBoxHandle)
    End Sub

  #End Region

End Class


一応ながら、WM_PASTE は拾えるハズ...

_________________
C# と VB.NET の入門サイト
じゃんぬねっと日誌
yamayama
ベテラン
会議室デビュー日: 2006/02/10
投稿数: 68
投稿日時: 2006-02-11 10:35
早速のご教授ありがとうございます。
色々と探したのですがなかなか方法が見つからず困っておりました。
早速、試して見たいと思います。
1

スキルアップ/キャリアアップ(JOB@IT)