2013-05-16 110 views
0

我從一個自定義Colordialog類和另一個其他自定義Colordialog中取了一塊。將標題和位置屬性添加到此自定義ColorDialog

第一類已經實現了Title屬性。

這是第一類(被標記的答案轉換爲VBNET):How do I change the title of ColorDialog?

第二類實施了顏色的實時選擇。

這是第二類(標記爲答案):Get color property while ColorDialog still open, before confirming the dialog?

Unafortunatelly的位置屬性我不知道任何關於如何落實到甚至被搜索的解決方案的對話框。

好吧,現在我試圖合併兩段代碼來獲得強大的「默認」ColorDialog。

用Title屬性翻譯成VB.NET的自定義ColorDialog類正在工作,但是當我嘗試合併兩個類的title屬性不起作用時,我可以更改屬性字段中的標題值,但不顯示任何標題(ColorDialog標題爲空)。

我的問題是什麼樣的變化,我需要爲這一類正常工作Title屬性,如果我怎麼能在ColorDialog類在屏幕上實現一個「位置」屬性來容易移居如果我的願望,例如:MyColorDialog .Location = new point(),我之前使用RECT結構嘗試過它。

這就是我所做的更改合併類的重要組成部分:

(Title屬性的東西regioned和獨立的評論。)

Imports System.Runtime.InteropServices 

Public Class Colordialog_Realtime 
    Inherits ColorDialog 

#Region " Title property things" 

    <DllImport("user32.dll")> _ 
    Private Shared Function SetWindowText(hWnd As IntPtr, lpString As String) As Boolean 
    End Function 

    Private m_title As String = String.Empty 
    Private titleSet As Boolean = False 

    Public Property Title() As String 
     Get 
      Return m_title 
     End Get 
     Set(value As String) 
      If value IsNot Nothing AndAlso value <> m_title Then 
       m_title = value 
       titleSet = False 
      End If 
     End Set 
    End Property 

#End Region 

    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 

     ' Title property things" 
     If Not titleSet Then 
      SetWindowText(hWnd, m_title) 
      titleSet = True 
     End If 
     ' End of title property things 

     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 

這是其他類:

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

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 

回答

1

實例:

Private Sub PicBox_Click(sender As Object, e As EventArgs) Handles PicBox.Click 
    Dim prevColor As Color = PicBox.BackColor 

    ColorDlg = New Colordialog_Realtime 
    ColorDlg.Color = PicBox.backcolor 
    ColorDlg.Title = "Please Select a New Color:" 
    ColorDlg.Location = New Point(Me.Location.X + Me.Width, Me.Location.Y) 
    If ColorDlg.ShowDialog() = Windows.Forms.DialogResult.OK Then 
     PicBox.BackColor = ColorDlg.Color 
    Else 
     PicBox.BackColor = prevColor 
    End If 
    ColorDlg = Nothing 
End Sub 

Colordialog_Realtime類:

Public Class Colordialog_Realtime 
    Inherits ColorDialog 

    Public Event CurrentColor(ByVal c As Color) 

    Private Const GA_ROOT As Integer = 2 
    Private Const WM_PAINT As Integer = &HF 
    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 

    <Runtime.InteropServices.DllImport("user32.dll")> _ 
    Private Shared Function SetWindowText(hWnd As IntPtr, lpString As String) As Boolean 
    End Function 

    Private Const SWP_NOSIZE As Integer = &H1 
    Private Declare Function SetWindowPos Lib "user32" Alias "SetWindowPos" _ 
     (ByVal hwnd As IntPtr, ByVal hWndInsertAfter As Integer, ByVal x As Integer, ByVal y As Integer, ByVal cx As Integer, ByVal cy As Integer, ByVal wFlags As Integer) As Integer 

    Private m_title As String = String.Empty 
    Private titleSet As Boolean = False 

    Public Property Title() As String 
     Get 
      Return m_title 
     End Get 
     Set(value As String) 
      If value IsNot Nothing AndAlso value <> m_title Then 
       m_title = value 
       titleSet = False 
      End If 
     End Set 
    End Property 

    Private m_location As Point = Point.Empty 
    Private locationSet As Boolean = False 

    Public Property Location() As Point 
     Get 
      Return m_location 
     End Get 
     Set(value As Point) 
      If Not value.Equals(Point.Empty) AndAlso Not value.Equals(m_location) Then 
       m_location = value 
       locationSet = False 
      End If 
     End Set 
    End Property 

    <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_PAINT 
       If Not titleSet AndAlso Title <> String.Empty Then 
        SetWindowText(GetAncestor(hWnd, GA_ROOT), Title) 
        titleSet = True 
       End If 
       If Not locationSet AndAlso Not m_location.Equals(Point.Empty) Then 
        SetWindowPos(GetAncestor(hWnd, GA_ROOT), 0, m_location.X, m_location.Y, 0, 0, SWP_NOSIZE) 
        locationSet = True 
       End If 

      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 
+0

我無法測試到明天早上,但肯定的代碼將如預期,很多東西從你的代碼再學習,感謝和等待我的評論或讚美。 – ElektroStudios

+0

真的很棒,但現在ColorDialog失去了你第一次做的「實時選擇顏色」修改。 – ElektroStudios

+0

它沒有在我身邊。確保您仍然在Class級別上使用「ColorDlg」聲明並使用WithEvents,並且您在其末尾具有「Handles ColorDlg.CurrentColor」的自定義事件處理程序。 –