DOBON.NET DOBON.NETプログラミング掲示板過去ログ

DataGridView上にコンボボックスがある場合のダブルクリックについて

環境/言語:[OS : Windows Vista / 言語 : Visual Basic 2005]
分類:[VB6以前]

2010/05/20(Thu) 20:07:24 編集(投稿者)

【解決したい問題】

DataGridViewの列に表示したコンボボックをダブルクリックして
別画面に飛ぶようにしたく、
DataGridViewのダブルクリックイベントを使用したのですが、

まずセルを選択するためにクリックし、さらにセルを編集状態にするためにクリックし、最後にドロップダウンさせるためにクリックし、
さらにエンターキーかタブキーで選択した項目を確定させないと、
ダブルクリックできません。

項目を確定させなくてもダブルクリックできるようにするには、
どうすればよいでしょうか?

【解決するために何をしたか】

こちらで紹介されていました、
「DataGridViewのコンボボックスのドロップダウンリストが一回のクリックで表示されるようにする」
をしたところ、今度はダブルクリック自体きかなくなりました。
お疲れ様です。

要件に合わないかもしれませんが、
編集モードに入った状態でComboBoxをDoubleClickすると
「出力」ウィンドウにメッセージを表示するサンプルです。
簡単のため、DoubleClick検出処理に漏れがありますが
参考になれば幸いです。
(処理内容)
・NativeWindowを使い、ComboBox上のMouse押下を検出
  → DoubleClckを手動で判定
・DataGridViewのDoubleClickイベントも併用

Public Class Form_CboDBlClickTest
    Inherits Form
    ' DataGridView
    Dim WithEvents _dgv As New DataGridView
    ' ComboBox上のMouse押下を検出するためのNativeWindowオブジェクト
    Dim _cbonativewindow As New CboNativeWindow

    ' Form初期表示時の処理(DataGridView組み立て)
    Protected Overrides Sub OnLoad(ByVal e As System.EventArgs)
        With Me._dgv
            .EditMode = DataGridViewEditMode.EditOnEnter
            .Columns.Add("列1", "列1")
            Dim cbo As DataGridViewComboBoxColumn = Me._createComboBoxColumn
            cbo.Name = "列2"
            .Columns.Add(cbo)
            .Dock = DockStyle.Fill
            .RowCount = 10
        End With
        Me.Controls.Add(Me._dgv)
        MyBase.OnLoad(e)
    End Sub
    ' ComboBox列を作成するヘルパメソッド
    Private Function _createComboBoxColumn() As DataGridViewComboBoxColumn
        Dim cbo As New DataGridViewComboBoxColumn
        Dim dt As New DataTable
        dt.Columns.Add("Code", GetType(String))
        dt.Columns.Add("Name", GetType(String))
        dt.Rows.Add("コード1", "値1")
        dt.Rows.Add("コード2", "値2")
        dt.Rows.Add("コード3", "値3")
        dt.Rows.Add("コード4", "値4")
        cbo.ValueMember = "Code"
        cbo.DisplayMember = "Name"
        cbo.DataSource = dt
        cbo.DisplayStyleForCurrentCellOnly = True
        Return cbo
    End Function
    ' DataGridViewのDoubleClickイベントも併用する
    Private Sub _dgv_DoubleClick(ByVal sender As Object, ByVal e As System.EventArgs) Handles _dgv.DoubleClick
        Console.WriteLine("DGVDoubleClick")
    End Sub
    ' ComboBox列が編集モードに入るときに、ComboBoxにNativeWindowを適用し、
    ' Mouse押下を検出する。
    Private Sub _dgv_EditingControlShowing(ByVal sender As Object, _
        ByVal e As System.Windows.Forms.DataGridViewEditingControlShowingEventArgs) Handles _dgv.EditingControlShowing
        If TypeOf e.Control Is ComboBox Then
            Me._cbonativewindow.AttachControl(e.Control)
        End If
    End Sub
    ' 編集モード終了時に、ComboBoxをNativeWindowから解放
    Private Sub _dgv_CellEndEdit(ByVal sender As Object, _
        ByVal e As System.Windows.Forms.DataGridViewCellEventArgs) Handles _dgv.CellEndEdit
        Me._cbonativewindow.DetachControl()
    End Sub

    ' ComboBoxのMouse押下検出用のNativeWindow
    ' DataGridViewの編集コントロールのMouseDown・MouseUpイベントでは
    ' うまくいかなかったので、代わりにこれを使用
    Private Class CboNativeWindow
        Inherits NativeWindow
        ' Mouse押下を検出したいComboBox
        Dim WithEvents _cbo As Control
        ' ComboBox上のWindowMessageをWndProcで捕捉可能にする
        Public Sub AttachControl(ByVal cbo As Control)
            Me._cbo = cbo
            MyBase.AssignHandle(cbo.Handle)
        End Sub
        '
        Public Sub DetachControl()
            If Me._cbo IsNot Nothing Then
                Me._cbo = Nothing
                MyBase.ReleaseHandle()
            End If
        End Sub
        '
        Private Sub _cbo_HandleDestroyed(ByVal sender As Object, ByVal e As System.EventArgs) _
            Handles _cbo.HandleDestroyed
            Me.DetachControl()
        End Sub
        ' ComboBox上のMouse押下を検出し、ダブルクリック判定処理に渡す。
        Protected Overrides Sub WndProc(ByRef m As System.Windows.Forms.Message)
            Const WM_LBUTTONDOWN As Integer = &H201
            Const WM_LBUTTONUP As Integer = &H202
            Select Case m.Msg
                Case WM_LBUTTONDOWN
                    Me._testSpecialMatch("D"c)
                Case WM_LBUTTONUP
                    Me._testSpecialMatch("U"c)
            End Select
            MyBase.WndProc(m)
        End Sub
        ' MouseDown+MouseUp+MouseUpでダブルクリックとみなす
        Private ReadOnly _matchPattern As String = "DUU"
        ' MouseDown+MouseUp+MouseUpでダブルクリックとみなすための判定処理
        Private Sub _testSpecialMatch(ByVal inputchar As Char)
            Console.WriteLine(inputchar)
            ' ダブルクリックの時間間隔判定用の変数 
            Static timeoffirstclick As DateTime = DateTime.MinValue
            ' Me._matchPatternのどこまで進んだかを保持する変数
            Static specialkeyindex As Integer = 0
            If Me._matchPattern.Chars(specialkeyindex) = inputchar Then
                If specialkeyindex = 0 Then
                    ' ダブルクリック開始時間を記憶
                    timeoffirstclick = DateTime.Now
                End If
                specialkeyindex += 1
                ' 所定時間内にパターン末尾まで来た場合は、ダブルクリックとみなす
                If specialkeyindex >= Me._matchPattern.Length Then
                    specialkeyindex = 0
                    If (DateTime.Now - timeoffirstclick).TotalMilliseconds <= SystemInformation.DoubleClickTime Then
                        Console.WriteLine("MatchDBLCLICK")
                    End If
                End If
            Else
                specialkeyindex = 0
            End If
        End Sub

    End Class

End Class
H.K.R.様

お返事が遅くなり申し訳ありません。
ご返答ありがとうございました。

ご教授頂いた方法を参考になんとか形あるものができました。

本当にありがとうございました。
解決済み!

DOBON.NET | プログラミング道 | プログラミング掲示板