2013-05-16 29 views
1

我想要做的是在打開ColorDialog的同時,在Colordialog的「完全打開」模式下獲取臨時選定的顏色。在確認對話框之前,ColorDialog仍然打開時獲取顏色屬性?

例如在這個圖像中,我有一個白色的圖片框,並且選擇了「紅色」顏色打開ColorDialog,我想要的是將圖片框背景顏色更改爲所選顏色(紅色),而不按「ok」按鈕確認ColorDialog類,並得到顏色結果...

enter image description here

這可能是與默認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 
+0

我不認爲這是可能的。 –

+0

我相信建立你的colorDialog – Nianios

回答

1

免責聲明:只是因爲我們可以,並不意味着我們應該!

本示例專門設計用於FullOpen模式下的ColorDialog。它依賴於在對話中的「紅色:」,「綠色:」和「藍色:」控件實時更新的事實,因爲用戶更改顏色,並且每個發送一個WM_CTLCOLOREDIT這些控件的更新時間(這也適用於手動輸入這些值的時間)。每次我們要使用它時,我們都必須創建一個新的MyColorDialog實例,以便這些控件的窗口句柄是正確的。

下面的WindowsEnumerator類是基於鮑勃的(TheLearnedOne)工作here

*我是Idle_Mind專家交流。

這是在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 
+0

OH-MY-GOD更容易,你是一個API大師,真的我印象深刻,你無法想象我多麼感謝你的幫助和答案,代碼正在做什麼我需要。只有一個問題,如果我想將你的類編譯成一個dll,那麼你推薦我在項目設置中定位哪個Framework版本? (對不起,如果是一個愚蠢的問題) – ElektroStudios

+0

該代碼使用泛型列表,因此它至少需要.Net 2.0。如果你想要降低到.Net 1.1,你可以切換到ArrayLists。除此之外,這裏沒有什麼特別的用來保證.Net的更高版本。 –

+0

如果您覺得問題「已解決」,請隨時點擊該複選標記。 –