Results 1 to 5 of 5

Thread: VB - Intercepting Paste Command on RichTextBoxes

  1. #1

    Thread Starter
    Fanatic Member RealisticGraphics's Avatar
    Join Date
    Jul 1999
    Location
    Arkansas
    Posts
    655

    VB - Intercepting Paste Command on RichTextBoxes

    This code will show you how to intercept the Paste command that is sent to the RichTextBox control (RTB).

    Now you may ask why you would need this... If you create a menu for Pasting and give it a shortcut key of Ctrl+V. Then when you paste to a RTB you get double whatever you had on the clipboard if you used Ctrl+V. The data on the clipboard will also paste as whatever Format it is in instead of plain text (in my case, I needed it to always be in plain text).

    As I discovered, the RTB does NOT except the WM_PASTE message (as well as WM_COPY & WM_CUT). After hours of trying to figure out what message it was receiving, I came up with the code below.

    Module:
    VB Code:
    1. Public Declare Function CallWindowProc Lib "user32" _
    2. Alias "CallWindowProcA" _
    3. (ByVal lpPrevWndFunc As Long, ByVal hwnd As Long, _
    4. ByVal msg As Long, ByVal wParam As Long, _
    5. ByVal lParam As Long) As Long
    6.  
    7. Public Declare Function SetWindowLong Lib "user32" Alias _
    8. "SetWindowLongA" (ByVal hwnd As Long, _
    9. ByVal nIndex As Long, ByVal dwNewLong As Long) As Long
    10.  
    11. Public lOldWinProc As Long
    12.  
    13. Public Const GWL_WNDPROC& = (-4)
    14. Private Const WM_KEYDOWN = &H100
    15. Private Const WM_PASTE = &H302
    16.  
    17. Public Function WndProc(ByVal hwnd As Long, _
    18. ByVal uMsg As Long, ByVal wParam As Long, _
    19. ByVal lParam As Long) As Long
    20.  
    21. Dim bCompleted As Boolean
    22. bCompleted = False
    23.  
    24. Select Case uMsg
    25.     Case WM_KEYDOWN
    26.         Select Case wParam
    27.             Case vbKeyV
    28.                 bCompleted = True
    29.             Case vbKeyC
    30.                 bCompleted = True
    31.             Case vbKeyX
    32.                 bCompleted = True
    33.         End Select
    34.     Case WM_PASTE
    35.         MyPaste
    36.         bCompleted = True
    37. End Select
    38.  
    39. If bCompleted = False Then
    40.     WndProc = CallWindowProc(lOldWinProc, hwnd, uMsg, wParam, lParam)
    41. End If
    42. End Function
    43.  
    44. Public Sub MyCopy()
    45. Clipboard.SetText Form1.RTB.SelText, vbCFText
    46. End Sub
    47.  
    48. Public Sub MyCut()
    49. Clipboard.SetText Form1.RTB.SelText, vbCFText
    50. Form1.RTB.SelText = ""
    51. End Sub
    52.  
    53. Public Sub MyPaste()
    54. Form1.RTB.SelText = Clipboard.GetText(vbCFText)
    55. End Sub

    As you can see I've created my own Cut, Copy, & Paste procedures to take over for the normal ones. In the procedure I'm using to intercept the commands you'll see WM_KEYDOWN. What this message tells us is that the Control key is pressed. If it is pressed, we then check wParam. wParam is the KeyCode for the key that is being pressed along with the Control key.

    If we determine that Ctrl+C, Ctrl+X, or Ctrl+V is being pressed them we set bCompleted = True so that the commands will not be given to the RTB and our new commands will.

    In a Form named Form1 with an RTB named RTB:
    VB Code:
    1. Private Sub Form_Load()
    2. lOldWinProc = SetWindowLong(RTB.hwnd, GWL_WNDPROC, AddressOf WndProc)
    3. End Sub
    4.  
    5. Private Sub Form_QueryUnload(Cancel As Integer, UnloadMode As Integer)
    6. SetWindowLong RTB.hwnd, GWL_WNDPROC, lOldWinProc
    7. End Sub
    8.  
    9. Private Sub mnuCopy_Click()
    10. MyCopy
    11. End Sub
    12.  
    13. Private Sub mnuCut_Click()
    14. MyCut
    15. End Sub
    16.  
    17. Private Sub mnuPaste_Click()
    18. MyPaste
    19. End Sub

    In the Form_Load and Form_QueryUnload event we Hook/Unhook the RTB. This just tells the RTB to use our new procedure instead of the default one first. The menu code should be pretty straight forward.

    I've attached a copy of a project that shows this code in action.
    Attached Files Attached Files
    Last edited by RealisticGraphics; Oct 5th, 2003 at 09:39 AM.
    www.RealisticGraphics.net

    Running VS.Net Enterprise & VB 6

    Other Languages: JavaScript, VBScript, VBA, HTML, CSS, ASP, SQL, XML

    MSN Messenger: kmsheff

  2. #2
    Conquistador
    Join Date
    Dec 1999
    Location
    Australia
    Posts
    4,527
    VB Code:
    1. Public Function WndProc(ByVal hwnd As Long, _
    2. ByVal uMsg As Long, ByVal wParam As Long, _
    3. ByVal lParam As Long) As Long
    4.  
    5.     If uMsg = WM_KEYDOWN And (wParam = vbKeyV Or wParam = vbKeyC Or wParam = vbKeyX) Then Exit Function
    6.     If uMsg = WM_PASTE Then
    7.         MyPaste
    8.         Exit Function
    9.     End If
    10.  
    11.     WndProc = CallWindowProc(lOldWinProc, hwnd, uMsg, wParam, lParam)
    12. End Function

    select case isn't as efficient as if then statements, also it might be better coding practice


  3. #3

    Thread Starter
    Fanatic Member RealisticGraphics's Avatar
    Join Date
    Jul 1999
    Location
    Arkansas
    Posts
    655
    Unless I'm mistaken the Select Case is more memory efficient and if nothing else if is generally easier to go back and add more conditions.

    You may be right but either way works and I like the structure of the select case better when I'm reading code.

    For instance this part of your code:

    wParam = vbKeyV Or wParam = vbKeyC Or wParam = vbKeyX

    Each Or is checked. Even if wParam=vbKeyV I believe that each "or" after it is still checked. Whereas on a select case statement it only checks until it finds a match. I'm sure I read that someplace, I think it was in VSM.
    www.RealisticGraphics.net

    Running VS.Net Enterprise & VB 6

    Other Languages: JavaScript, VBScript, VBA, HTML, CSS, ASP, SQL, XML

    MSN Messenger: kmsheff

  4. #4
    Conquistador
    Join Date
    Dec 1999
    Location
    Australia
    Posts
    4,527
    afaik select case is broken down into effectively multiple if... then statements when compiled


    VB Code:
    1. Private Declare Function GetTickCount Lib "kernel32" () As Long
    2.  
    3. Private Sub Command1_Click()
    4. Dim StartTimeSelect As Long
    5. Dim StartTimeIfThen As Long
    6. Dim rndVal As Long
    7.  
    8. StartTimeIfThen = GetTickCount()
    9.  
    10. For X = 0 To 10000000
    11.     Randomize
    12.     rndVal = Int((100 * Rnd) + 1)
    13.     If rndVal < 10 Then
    14.        
    15.     ElseIf rndVal < 20 Then
    16.        
    17.     ElseIf rndVal < 30 Then
    18.        
    19.     ElseIf rndVal < 40 Then
    20.        
    21.     ElseIf rndVal < 50 Then
    22.        
    23.     ElseIf rndVal < 60 Then
    24.        
    25.     ElseIf rndVal < 70 Then
    26.        
    27.     ElseIf rndVal < 80 Then
    28.        
    29.     ElseIf rndVal < 90 Then
    30.        
    31.     Else
    32.        
    33.     End If
    34. Next
    35.  
    36.  
    37.  
    38. MsgBox GetTickCount() - StartTimeIfThen
    39.  
    40.  
    41.  
    42. StartTimeSelect = GetTickCount()
    43.  
    44. For X = 0 To 10000000
    45.     Randomize
    46.     Select Case Int((100 * Rnd) + 1)
    47.     Case Is < 10
    48.        
    49.     Case Is < 20
    50.        
    51.     Case Is < 30
    52.        
    53.     Case Is < 40
    54.        
    55.     Case Is < 50
    56.        
    57.     Case Is < 60
    58.        
    59.     Case Is < 70
    60.        
    61.     Case Is < 80
    62.        
    63.     Case Is < 90
    64.        
    65.     Case Else
    66.        
    67.     End Select
    68. Next
    69.  
    70. MsgBox GetTickCount() - StartTimeSelect
    71.  
    72. End Sub

  5. #5

    Thread Starter
    Fanatic Member RealisticGraphics's Avatar
    Join Date
    Jul 1999
    Location
    Arkansas
    Posts
    655
    Try running them several times each in their own button. Sometimes one will beat the other one.

    You're probably right though, judging from these numbers. But I still swear that I read an article someplace talking about the speed differences and that Select Case was the better choice.

    Either way, they both run at about the same speed and the time difference is hardly noticable and either way will work.
    www.RealisticGraphics.net

    Running VS.Net Enterprise & VB 6

    Other Languages: JavaScript, VBScript, VBA, HTML, CSS, ASP, SQL, XML

    MSN Messenger: kmsheff

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  



Click Here to Expand Forum to Full Width