![]() 圖1 帶分隔條的窗體 |
’生成類模塊clsTest的一個實例test Dim test as new clsTest |
test.DoSomthing() ’調用test的方法DoSomthing() |
![]() 圖2 編輯類模塊 |
’定義一個帶事件的文本框變量 Dim WithEvents MyText As TextBox ’保存文本框是否獲得焦點的布爾變量 Dim bSetted As Boolean ’自己定義的類模塊的方法,傳入參數是文本框。 Public Sub BindText(t As TextBox) ’將文本框變量設置為傳入的文本框,即是對傳入文本框的引用 Set MyText = t End Sub |
Private Sub Class_Initialize() ’將文本框變量初始化Nothing Set MyText = Nothing bSetted = False End Sub |
Private Sub MyText_GotFocus() bSetted = True End Sub Private Sub MyText_LostFocus() bSetted = False End Sub ’鼠標在控件上移動時,如果還沒設置焦點,將它設為焦點, ’并將內容選中 Private Sub MyText_MouseMove(Button As Integer, Shift As Integer, X As Single, Y As Single) If (Not bSetted) Then MyText.SetFocus MyText.SelStart = 0 MyText.SelLength = 9999 End If End Sub |
’定義類模塊的實例,因為有3個TextBox所以定義3個實例 Dim t1 As New clsTest Dim t2 As New clsTest Dim t3 As New clsTest |
Private Sub Form_Load() ’調用類模塊的方法BindText 參數是窗體上的TextBox們 t1.BindText Text1 t2.BindText Text2 t3.BindText Text3 End Sub |
Option Explicit ’強制變量聲明 ’API與數據類型定義: ’點數據類型POINTAPI的定義 Private Type POINTAPI X As Long Y As Long End Type ’將屏幕坐標轉化為窗體坐標 Private Declare Function ScreenToClient Lib "user32" (ByVal hwnd As Long, lpPoint As POINTAPI) As Long ’將窗體坐標轉化為屏幕坐標 Private Declare Function ClientToScreen Lib "user32" (ByVal hwnd As Long, lpPoint As POINTAPI) As Long ’設置鼠標捕捉 Private Declare Function SetCapture Lib "user32" (ByVal hwnd As Long) As Long ’釋放鼠標捕捉 Private Declare Function ReleaseCapture Lib "user32" () As Long ’獲得鼠標在屏幕上的位置 Private Declare Function GetCursorPos Lib "user32" (lpPoint As POINTAPI) As Long ’設置鼠標在屏幕上的位置 Private Declare Function SetCursorPos Lib "user32" (ByVal X As Long, ByVal Y As Long) As Long |
’分割條類型: 0 水平,1垂直 Dim HorV As Integer ’窗體變量 引用當前的窗體 Dim mForm As Form ’控件數組類型 Private Type BindControl binControl As Control ’控件 ’ 控件位置: 0左側,1右側,2上方,3下方 pos As Integer End Type ’控件數組 定義了10個控件的容量 可以根據實際需要增減 Dim myBindControls(10) As BindControl ’控件數組中已有元素的數量 Dim numControls As Integer ’鼠標位置點 Dim pot As POINTAPI ’鼠標是否在移動分割條 Dim Resizing As Boolean ’分割條的最小位置和最大位置 Dim iMin As Integer Dim iMax As Integer ’帶事件的控件定義 這里我們選用Label Dim WithEvents SplitBar As Label |
’給分割條控件指定所在的窗體、Label控件、分割條類型等 Public Sub Attach(f As Form, sp As Label, hv As Integer,min As Long, max As Long) Set mForm = f ’設置窗體變量 ’設置分割條控件變量為傳入的Label控件 Set SplitBar = sp ’給分割條做個標記,表明這個Label是分割條 SplitBar.Tag = "SPLIT" If hv = 0 Then ’如果是水平分割條 HorV = 0 ’設置分割條類型 ’ 設置Label控件的鼠標光標為左右箭頭 SplitBar.MousePointer = 9 ’最小位置與最大位置設置 If max < min + SplitBar.Width Then iMin = 100 iMax = mForm.ScaleWidth - SplitBar.Width - 100 Else iMin = min iMax = max End If Else HorV = 1 ’如果是水平分割條 ’設置Label控件的鼠標光標為上下箭頭 SplitBar.MousePointer = 7 If max < min + SplitBar.Height Then iMin = 100 iMax = mForm.ScaleWidth - SplitBar.Height - 100 Else iMin = min iMax = max End If End If End Sub ’添加分割條左側的控件 如果不是水平分割條則退出 Public Sub SetLeftBind(c As Control) If HorV = 1 Then Exit Sub AddBindControl c, 1 End Sub ’添加分割條上方的控件 如果不是垂直分割條則退出 Public Sub SetUpBind(c As Control) If HorV = 0 Then Exit Sub AddBindControl c, 2 End Sub ’添加分割條下方的控件 如果不是垂直分割條則退出 Public Sub SetDownBind(c As Control) If HorV = 0 Then Exit Sub AddBindControl c, 3 End Sub ’幫助函數 私有 往控件數組里加入一個控件 Private Sub AddBindControl(c As Control, ipos As Integer) If numControls < 10 Then ’確??丶到M不溢出 numControls = numControls + 1 Set myBindControls(numControls - 1).binControl = c myBindControls(numControls - 1).pos = ipos End If End Sub ’計算控件位置 Public Sub ArrangePosition() On Error GoTo err Dim i As Integer If HorV = 0 Then ’水平分割條 設置高度為窗體的高度 SplitBar.Height = mForm.ScaleHeight - _ SplitBar.Top - 10 Else ’垂直分割條 設置寬度為窗體的寬度 如果要將垂直分割條嵌入水平分割條中 則將此分支去掉(見本文例圖) ’SplitBar.Width = mForm.ScaleWidth - SplitBar. Left - 10 End If Dim i1 As Integer Dim i2 As Integer Dim lf1 As Integer ’控件右側或底部的邊界 Dim lf2 As Integer ’控件右側或底部的邊界 ’垂直分割 找到最右端的控件 上方為i1,下方為i2 If HorV = 1 Then For i = 0 To numControls - 1 With myBindControls(i) If .pos = 2 Then If .binControl.Left + .binControl.Width > lf1 Then lf1 = .binControl.Left + .binControl.Width i1 = i End If ElseIf .pos = 3 Then If .binControl.Left + .binControl.Width > lf2 Then lf2 = .binControl.Left + .binControl.Width i2 = i End If End If End With Next i Else ’水平分割 找到最底部的控件 左邊為i1,右邊為i2 For i = 0 To numControls - 1 With myBindControls(i) If .pos = 0 Then If .binControl.Top + .binControl.Height > lf1 Then lf1 = .binControl.Top + .binControl.Height i1 = i End If ElseIf .pos = 1 Then If .binControl.Top + .binControl.Height > lf2 Then lf2 = .binControl.Top + .binControl.Height i2 = i End If End If End With Next i End If ’遍歷控件數組進行位置計算 For i = 0 To numControls - 1 With myBindControls(i) .binControl Select Case myBindControls(i).pos Case 0 ’左側控件 .Width = SplitBar.Left - .Left - 10 If i = i1 Then ’如果是最底部的控件 .Height = SplitBar.Top + SplitBar.Height - .Top End If Case 1 ’右側控件 .Left = SplitBar.Left + SplitBar.Width + 10 .Width = mForm.ScaleWidth - SplitBar.Left - SplitBar.Width - 10 If i = i2 Then ’如果是最底部的控件 .Height = SplitBar.Top + SplitBar.Height - .Top End If Case 2 ’上方控件 .Height = SplitBar.Top - .Top - 10 If i = i1 Then ’如果是最右側的控件 .Width = SplitBar.Left + SplitBar.Width - .Left End If Case 3 ’下方控件 .Top = SplitBar.Top + SplitBar.Height + 10 .Height = mForm.ScaleHeight - SplitBar.Top- SplitBar.Height - 10 If i = i2 Then ’如果是最右側的控件 .Width = SplitBar.Left + SplitBar.Width - .Left End If End Select End With Next i err: End Sub |
’類模塊初始化 Private Sub Class_Initialize() numControls = 0 ’控件數設為0 Resizing = False ’鼠標調整設為假 End Sub ’鼠標在Label控件上按下左鍵,開始調整 Private Sub SplitBar_MouseDown(Button As Integer, Shift As Integer, X As Single, Y As Single) If Button = vbLeftButton Then Resizing = True End Sub ’鼠標在Label控件上抬起左鍵,結束調整 Private Sub SplitBar_MouseUp(Button As Integer, Shift As Integer, X As Single, Y As Single) If Button = vbLeftButton Then Resizing = False End Sub ’鼠標移動事件 Private Sub SplitBar_MouseMove(Button As Integer, Shift As Integer, X As Single, Y As Single) ’得到鼠標位置 GetCursorPos pot ’屏幕坐標轉為窗體坐標 ScreenToClient mForm.hwnd, pot ’如果鼠標不在調整則退出 If Not Resizing Then Exit Sub If HorV = 0 Then ’如果是水平分割條 ’如果鼠標在窗體上的水平位置超過最小值 If pot.X * Screen.TwipsPerPixelX < iMin Then ’設置鼠標位置為窗體上水平位置最小值 退出 pot.X = iMin / Screen.TwipsPerPixelX ClientToScreen mForm.hwnd, pot SetCursorPos pot.X, pot.Y Exit Sub ’如果鼠標在窗體上的水平位置超過最大值 ElseIf pot.X * Screen.TwipsPerPixelX > iMax Then ’設置鼠標位置為窗體上水平位置最大值 退出 pot.X = iMax / Screen.TwipsPerPixelX ClientToScreen mForm.hwnd, pot SetCursorPos pot.X, pot.Y Exit Sub Else ’設置分割條的左側位置為鼠標水平位置減去 ’分割條寬度的二分之一 SplitBar.Left = pot.X * Screen.TwipsPerPixelXSplitBar.Width / 2 End If Else ’如果是垂直分割條 ’如果鼠標在窗體上的水平位置超過最小值 If pot.Y * Screen.TwipsPerPixelY < iMin Then ’設置鼠標位置為窗體上水平位置最小值 退出 pot.Y = iMin / Screen.TwipsPerPixelY ClientToScreen mForm.hwnd, pot SetCursorPos pot.X, pot.Y Exit Sub ’如果鼠標在窗體上的水平位置超過最大值 ElseIf pot.Y * Screen.TwipsPerPixelY > iMax Then ’設置鼠標位置為窗體上水平位置最大值 退出 pot.Y = iMax / Screen.TwipsPerPixelY ClientToScreen mForm.hwnd, pot SetCursorPos pot.X, pot.Y Exit Sub Else ’設置分割條的頂部位置為鼠標垂直位置 ’減去分割條高度的二分之一 SplitBar.Top = pot.Y * Screen.TwipsPerPixelY - SplitBar.Height / 2 End If End If ’調用子程序計算控件位置 ArrangePosition End Sub |
![]() 圖4 測試分隔條 |
Dim sp As New clsSplitBar |
Private Sub Form_Load() sp.Attach Me, Label1, 0, 1000, 5000 sp.SetLeftBind Text1 sp.SetRightBind Text2 End Sub |
Private Sub Form_Resize() sp.ArrangePosition End Sub |
原文轉自:http://www.anti-gravitydesign.com