查看單個文章
舊 2016-10-15, 08:33 PM   #1
mini
管理版主
 
mini 的頭像
榮譽勳章
UID - 4144
在線等級: 級別:96 | 在線時長:9665小時 | 升級還需:132小時級別:96 | 在線時長:9665小時 | 升級還需:132小時級別:96 | 在線時長:9665小時 | 升級還需:132小時級別:96 | 在線時長:9665小時 | 升級還需:132小時級別:96 | 在線時長:9665小時 | 升級還需:132小時級別:96 | 在線時長:9665小時 | 升級還需:132小時
註冊日期: 2002-12-07
文章: 13249
精華: 0
現金: 26241 金幣
資產: 3024051 金幣
預設 VB .Net TextBox物件重拾 捲軸事件

由於 MS為了推廣 RichTextBox物件
將 TextBox物件 .VScroll 及 .HScroll 可控制事件取消了

想利用捲軸事件寫功能時
就只能放棄TextBox物件嗎 (使用資源較龐大的RichTextBox物件)?
這裡提供一個最簡單的方法 (WWW上的都蠻麻煩的)

以下範例實踐兩個 TextBox物件(TextBox1 及 TextBox2)
「同步捲動」
先加一段程式碼
PHP 語法:
Protected Overrides Sub WndProc(ByRef m As System.Windows.Forms.Message)
        
'wParam的低16位元為控件的ID。lParam控件句柄(hWnd),wParam的高16位元為 編輯框事件
        Select Case m.Msg
            Case WM_COMMAND
                If (CInt(m.WParam) >> 16) = EN_VSCROLL Then '
垂直捲軸事件
                    Dim Pos 
As IntegerhWnd As IntPtr
                    Pos 
GetScrollPos(m.LParamSBOrientation.SB_VERT'取的Pos
                    Select Case m.LParam
                        Case TextBox1.Handle
                            hWnd = TextBox2.Handle
                        Case TextBox2.Handle
                            hWnd = TextBox1.Handle
                    End Select
                    PostMessage(hWnd, WM_VSCROLL, &H10000 * Pos + SB_THUMBPOSITION, 0) '
Pos是位置改變量
                End 
If
        
End Select
        MyBase
.WndProc(m'前面插入完自己的功能後,須加這一句,才叫「插入」完成,少了他程式會不正常
    End Sub 
使用的Win API如下,請加入一個 模組貼上以下文字 (一些<>符號為屬性條件,不需多問為何如此,就把他當成數學公式看待吧)
PHP 語法:
    Public Enum SBOrientation As Integer
        SB_HORZ 
= &H0
        SB_VERT 
= &H1
        SB_CTL 
= &H2
        SB_BOTH 
= &H3
    End Enum
    
<DllImport("user32.dll"CharSet:=CharSet.Auto)> _
    
Public Function GetScrollPos_
        hWnd 
As IntPtr_
        
<MarshalAs(UnmanagedType.I4)> nBar As SBOrientation) As Integer
    End 
Function

    Public Const 
EM_SETSEL = &HB1
    
Public Const WM_COMMAND = &H111
    
Public Const EN_VSCROLL = &H602
    
Public Const WM_VSCROLL = &H115
    
Public Const SB_THUMBPOSITION 4
    
Public Const WM_USER = &H400
    
Public Const EM_GETSCROLLPOS = (WM_USER 221)
    Public Const 
EM_SETSCROLLPOS = (WM_USER 222)

    <
DllImport("user32.dll"SetLastError:=TrueCharSet:=CharSet.Auto)> _
    
Public Function SendMessage_
        ByVal hWnd 
As IntPtr_
        ByVal Msg 
As UInteger_
        ByVal wParam 
As IntPtr_
        ByVal lParam 
As IntPtr) As IntPtr
    End 
Function
    <
DllImport("user32.dll"SetLastError:=TrueCharSet:=CharSet.Auto)> _
    
Public Function PostMessage_
        ByVal hWnd 
As IntPtr_
        ByVal Msg 
As UInteger_
        ByVal wParam 
As IntPtr_
        ByVal lParam 
As IntPtr) As Boolean
    End 
Function 
原理說明:
使用攔截視窗訊息方式
如果核對符合 垂直捲軸事件
就同時發送訊息給另一個 TextBox同樣的動作

Protected Overrides Sub WndProc 是指覆寫 視窗訊息 處理 (插入自己的處理功能)
m.Msg 是訊息種類,如果是 WM_COMMAND 表示為使用者訊息
接著要分析 .LParam及.WParam參數
規定上就是:.WParam的前16個位元數值 如果是 EN_VSCROLL 表示是 垂直捲軸事件
.WParam有32位元長度往右移16位元就能與EN_VSCROLL比對是否相等,寫成: If (CInt(m.WParam) >> 16) = EN_VSCROLL Then
符合動作條件接著就是用兩個Win API指令來實作
GetScrollPos 及 PostMessage
前面是取得捲軸的數值
後面是將此數值發送給另一個(想要同步)的TextBox
以達到「同步捲動」
至於這些參數為何如此填,其實滿死板的,也不難理解 因此不多作解說
P.S.至於為何用 PostMessage而不用SendMessage 是因為確保訊息一定會給 接收物件給接收

以上~如有疑惑歡迎提問

此帖於 2016-10-15 08:45 PM 被 mini 編輯.
mini 目前離線  
送花文章: 1999, 收花文章: 7957 篇, 收花: 26749 次
回覆時引用此帖