1

私がやりたいことは、ColorDialog が開かれている間に、Colordialog の「フルオープン」モードで一時的に選択された色を取得することです。

たとえば、この画像では、白色のピクチャボックスがあり、「赤」の色が選択された状態で ColorDialog が開かれています。「OK」ボタンを押して確認せずに、ピクチャボックスの背景色を選択した色 (赤) に変更する必要があります。 ColorDialog と Color 結果を取得するには...

ここに画像の説明を入力

これはおそらくデフォルトの ColorDialog に関係していますか?

これは私が試したことです:

Public Class Form1

    Dim WithEvents PicBox As New PictureBox
    Dim ColorDlg As New ColorDialog

    Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
        PicBox.BackColor = Color.Blue
        ColorDlg.FullOpen = True
        Me.Controls.Add(PicBox)
    End Sub

    Private Sub PicBox_Click(sender As Object, e As EventArgs) Handles PicBox.Click
        ColorDlg.Color = sender.backcolor
        While Not ColorDlg.ShowDialog() = Windows.Forms.DialogResult.OK
            sender.BackColor = ColorDlg.Color
        End While
        ' sender.BackColor = ColorDlg.Color
    End Sub

End Class
4

1 に答える 1

2

免責事項:できるからといって、そうするべきだというわけではありません。

ColorDialogこの例は、 in theFullOpenモードで動作するように特別に設計されています。これは、ダイアログ内の「赤:」、「緑:」、および「青:」Editコントロールがユーザーによって色が変更されるとリアルタイムで更新されるという事実と、WM_CTLCOLOREDITそれらの色が変更されるたびに a が送信されるという事実に依存しています。コントロールが更新されます (これは、これらの値が手動で入力された場合にも当てはまります)。MyColorDialogこれらのコントロールへのウィンドウ ハンドルが正しくなるように、使用するたびに新しいインスタンスを作成する必要があります。

以下のクラスは、Bob (TheLearnedOne) の作品hereWindowsEnumeratorに基づいています。

* Idle_MindExperts-Exchange にもいます。

これは、VS2010 Premium の Win8 Pro でテストされました。他のバージョンの Windows で ColorDialog を変更する必要があるかどうかはわかりません。

Public Class Form1

    Private WithEvents PicBox As New PictureBox
    Private WithEvents ColorDlg As MyColorDialog = Nothing

    Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
        PicBox.BackColor = Color.Blue
        Me.Controls.Add(PicBox)
    End Sub

    Private Sub PicBox_Click(sender As Object, e As EventArgs) Handles PicBox.Click
        ColorDlg = New MyColorDialog
        ColorDlg.Color = sender.backcolor
        If ColorDlg.ShowDialog() = Windows.Forms.DialogResult.OK Then
            sender.BackColor = ColorDlg.Color
        End If
        ColorDlg = Nothing
    End Sub

    Private Sub ColorDlg_CurrentColor(c As System.Drawing.Color) Handles ColorDlg.CurrentColor
        PicBox.BackColor = c
    End Sub

End Class

Public Class MyColorDialog
    Inherits ColorDialog

    Public Event CurrentColor(ByVal c As Color)

    Private Const GA_ROOT As Integer = 2
    Private Const WM_CTLCOLOREDIT As Integer = &H133

    Public Declare Function GetAncestor Lib "user32.dll" _
        (ByVal hWnd As IntPtr, ByVal gaFlags As Integer) As IntPtr

    Private EditWindows As List(Of ApiWindow) = Nothing

    Public Sub New()
        Me.FullOpen = True
    End Sub

    <System.Security.Permissions.PermissionSetAttribute(System.Security.Permissions.SecurityAction.Demand, Name:="FullTrust")> _
    Protected Overrides Function HookProc(ByVal hWnd As IntPtr, ByVal msg As Integer, ByVal wParam As IntPtr, ByVal lParam As IntPtr) As IntPtr
        Select Case msg
            Case WM_CTLCOLOREDIT
                If IsNothing(EditWindows) Then
                    Dim mainWindow As IntPtr = GetAncestor(hWnd, GA_ROOT)
                    If Not mainWindow.Equals(IntPtr.Zero) Then
                        EditWindows = New List(Of ApiWindow)((New WindowsEnumerator).GetChildWindows(mainWindow, "Edit"))
                    End If
                End If

                If Not IsNothing(EditWindows) AndAlso EditWindows.Count = 6 Then
                    Dim strRed As String = WindowsEnumerator.WindowText(EditWindows(3).hWnd)
                    Dim strGreen As String = WindowsEnumerator.WindowText(EditWindows(4).hWnd)
                    Dim strBlue As String = WindowsEnumerator.WindowText(EditWindows(5).hWnd)

                    Dim Red, Green, Blue As Integer
                    If Integer.TryParse(strRed, Red) Then
                        If Integer.TryParse(strGreen, Green) Then
                            If Integer.TryParse(strBlue, Blue) Then
                                RaiseEvent CurrentColor(Color.FromArgb(Red, Green, Blue))
                            End If
                        End If
                    End If
                End If
        End Select

        Return MyBase.HookProc(hWnd, msg, wParam, lParam)
    End Function

End Class

Public Class ApiWindow
    Public hWnd As IntPtr
    Public ClassName As String
    Public MainWindowTitle As String
End Class

Public Class WindowsEnumerator

    Private Delegate Function EnumCallBackDelegate(ByVal hwnd As IntPtr, ByVal lParam As Integer) As Integer

    Private Declare Function EnumWindows Lib "user32" _
        (ByVal lpEnumFunc As EnumCallBackDelegate, ByVal lParam As Integer) As Integer

    Private Declare Function EnumChildWindows Lib "user32" _
        (ByVal hWndParent As IntPtr, ByVal lpEnumFunc As EnumCallBackDelegate, ByVal lParam As Integer) As Integer

    Private Declare Function GetClassName Lib "user32" Alias "GetClassNameA" _
        (ByVal hwnd As IntPtr, ByVal lpClassName As System.Text.StringBuilder, ByVal nMaxCount As Integer) As Integer

    Private Declare Function IsWindowVisible Lib "user32" (ByVal hwnd As IntPtr) As Integer

    Private Declare Function GetParent Lib "user32" (ByVal hwnd As IntPtr) As Integer

    Private Declare Function SendMessage Lib "user32" Alias "SendMessageA" _
        (ByVal hwnd As IntPtr, ByVal wMsg As Integer, ByVal wParam As Integer, ByVal lParam As Integer) As Integer

    Private Declare Function SendMessage Lib "user32" Alias "SendMessageA" _
        (ByVal hwnd As IntPtr, ByVal wMsg As Integer, ByVal wParam As Integer, ByVal lParam As System.Text.StringBuilder) As Integer

    Private _listChildren As New List(Of ApiWindow)
    Private _listTopLevel As New List(Of ApiWindow)

    Private _topLevelClass As String = String.Empty
    Private _childClass As String = String.Empty

    Public Overloads Function GetTopLevelWindows() As ApiWindow()
        EnumWindows(AddressOf EnumWindowProc, &H0)
        Return _listTopLevel.ToArray
    End Function

    Public Overloads Function GetTopLevelWindows(ByVal className As String) As ApiWindow()
        _topLevelClass = className
        Return Me.GetTopLevelWindows()
    End Function

    Public Overloads Function GetChildWindows(ByVal hwnd As Int32) As ApiWindow()
        _listChildren.Clear()
        EnumChildWindows(hwnd, AddressOf EnumChildWindowProc, &H0)
        Return _listChildren.ToArray
    End Function

    Public Overloads Function GetChildWindows(ByVal hwnd As Int32, ByVal childClass As String) As ApiWindow()
        _childClass = childClass
        Return Me.GetChildWindows(hwnd)
    End Function

    Private Function EnumWindowProc(ByVal hwnd As Int32, ByVal lParam As Int32) As Int32
        If GetParent(hwnd) = 0 AndAlso IsWindowVisible(hwnd) Then
            Dim window As ApiWindow = GetWindowIdentification(hwnd)
            If _topLevelClass.Length = 0 OrElse window.ClassName.ToLower() = _topLevelClass.ToLower() Then
                _listTopLevel.Add(window)
            End If
        End If
        Return 1
    End Function

    Private Function EnumChildWindowProc(ByVal hwnd As Int32, ByVal lParam As Int32) As Int32
        Dim window As ApiWindow = GetWindowIdentification(hwnd)
        If _childClass.Length = 0 OrElse window.ClassName.ToLower() = _childClass.ToLower() Then
            _listChildren.Add(window)
        End If
        Return 1
    End Function

    Private Function GetWindowIdentification(ByVal hwnd As Integer) As ApiWindow
        Dim classBuilder As New System.Text.StringBuilder(64)
        GetClassName(hwnd, classBuilder, 64)

        Dim window As New ApiWindow
        window.ClassName = classBuilder.ToString()
        window.MainWindowTitle = WindowText(hwnd)
        window.hWnd = hwnd
        Return window
    End Function

    Public Shared Function WindowText(ByVal hwnd As IntPtr) As String
        Const W_GETTEXT As Integer = &HD
        Const W_GETTEXTLENGTH As Integer = &HE

        Dim SB As New System.Text.StringBuilder
        Dim length As Integer = SendMessage(hwnd, W_GETTEXTLENGTH, 0, 0)
        If length > 0 Then
            SB = New System.Text.StringBuilder(length + 1)
            SendMessage(hwnd, W_GETTEXT, SB.Capacity, SB)
        End If
        Return SB.ToString
    End Function

End Class
于 2013-05-16T19:24:35.740 に答える