Announcement

Collapse
No announcement yet.

Preventing Paste in RichEdit Control

Collapse
X
 
  • Filter
  • Time
  • Show
Clear All
new posts

  • Preventing Paste in RichEdit Control

    I thought that subclassing the richedit control to gain access to WM_Char messages would let me prevent using Ctrl-V to paste into a RichEdit control.

    I can detect a Ctrl-V just fine, but when I use the following code in WM_Char, the Ctrl-V pastes information once, then my code pastes it again (in this example, replacing). The WM_Char seems to be received AFTER the paste action has already been completed.

    Can someone suggest a way to prevent Ctrl-V from pasting info from the clipboard? I also tried various other messages, including GetDlgCode, but Ctrl-V seems to take action before the messages come into play.

    My forum search came up empty, although the forum is pretty big and sometimes the keywords I pick aren't the magic words!


    Code:
    #Compile Exe
    #Dim All
    #Include "RichEdit.inc"
    #Include "CommCtrl.inc"
    %ID_RichEdit = 500
    Global hDlg As Dword, hRichEdit As Dword, OldProc&
    Function PBMain() As Long
       Local style&, buf$
       buf$ =  "This is sample" + $CrLf + "text for the" + $CrLf + "edit control."
       style& = %WS_Child Or %WS_Visible Or %ES_MultiLine Or %WS_VScroll Or %ES_AutoHScroll _
                 Or %WS_HScroll Or %ES_AutoVScroll Or %ES_WantReturn Or %ES_NoHideSel Or %WS_TabStop
       Dialog New Pixels, 0, "Test Code",300,300,200,300, %WS_OverlappedWindow To hDlg
       Control Add Button, hDlg, 100,"Paste", 30,10,140,20
       LoadLibrary("riched32.dll") : InitCommonControls
       Control Add "RichEdit", hDlg, %ID_RichEdit, buf$,20,40,160,100, style&
       Control Add ListBox, hDlg, 200,, 20,160,160,100
       Control Add Button, hDlg, 300,"Clear ListBox", 30,270,140,20
       Control Handle hDlg, %ID_RichEdit To hRichEdit
       Dialog Show Modal hDlg Call DlgProc
    End Function
    
    CallBack Function DlgProc() As Long
       Local temp$
       Select Case Cb.Msg
          Case %WM_InitDialog
             OldProc& = SetWindowLong(GetDlgItem(hDlg, %ID_RichEdit), %GWL_WndProc, CodePtr(NewProc))  'subclass
          Case %WM_Destroy
             SetWindowLong hRichEdit, %GWL_WNDPROC, OldProc&   'un-subclass
          Case %WM_Command
             Select Case Cb.Ctl
                Case 100
                   If Cb.CtlMsg = %BN_Clicked Then
                       Clipboard Get Text To temp$
                       Control Set Text hDlg, %ID_RichEdit, "main " + $CrLf + temp$ 'plain text
                   End If
                Case 300
                   If Cb.CtlMsg = %BN_Clicked Then
                       ListBox Reset hDlg, 200
                       Control Set Text hDlg, %ID_RichEdit, ""
                   End If
             End Select
       End Select
    End Function
    
    Function NewProc(ByVal hWnd As Long, ByVal Msg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
       Local temp$
       Select Case Msg
    '      Case %WM_GetDlgCode
    '         If wParam = &H16 Then ' have we been pasted with CTL-V ?
    '         ListBox Insert hDlg, 200, 1, "Subclass-GetDlgCode-Ctrl-V  " + Str$(wParam)
    '            MsgBox temp$
    '            Clipboard Get OEMText To temp$
    '            Control Set Text hDlg, %ID_RichEdit, "subclass " + $CrLf + temp$  'plain text
    '            Function = 1 : Exit Function
    '         End If
          Case %WM_Char
             If wParam = &H16 Then ' have we been pasted with CTL-V ?
                ListBox Insert hDlg, 200, 1, "Subclass-Char-Ctrl-V  " + Str$(wParam)
                Clipboard Get Text To temp$
                MsgBox temp$
                Control Set Text hDlg, %ID_RichEdit, "subclass " + $CrLf + temp$  'plain text
                Function = 1 : Exit Function
             End If
          Case %WM_Command
             Select Case Lo(Word, wParam)
                Case 100
                   If Hi(Word, wParam) = %BN_Clicked Then
                       Clipboard Get Text To temp$
                       Control Set Text hDlg, %ID_RichEdit, "subclass " + $CrLf + temp$  'plain text
                   End If
             End Select
       End Select
       Function = CallWindowProc(OldProc&, hWnd, Msg, wParam, lParam)
    End Function

  • #2
    You could try....

    ... picking up WM_KEYUP on ctrl-v (and shift-insert) and bypassing the default processing in your subclass. (WM_CHAR comes after keyup has been processed)

    ... process WM_NOTIFY/EN_MSGFILTER (no subclass required) and when you get a key of interest, you can return true to have the control ignore it.
    Michael Mattias
    Tal Systems (retired)
    Port Washington WI USA
    [email protected]
    http://www.talsystems.com

    Comment


    • #3
      OR....

      Maybe this would be a good place to create a superclass, which ignores and/or any "naughty" keystrokes?

      I wonder if the control gets WM_PASTE message, and only later (after pasting) sends the notification to the parent? If so, your subclass could pick off and eat the WM_PASTE message! That would be the easiest way (if it works)!

      MCM
      Michael Mattias
      Tal Systems (retired)
      Port Washington WI USA
      [email protected]
      http://www.talsystems.com

      Comment


      • #4
        CONTROL SET TEXT hDlg, %ID_RichEdit, "main " + $CRLF + temp$ 'plain text

        ... is not exactly a WM_PASTE message you are sending.

        SendMessage GetDlgItem(hDlg, %ID_RichEdit), %WM_PASTE, 0,0
        or DDT equivalent.

        try Michael's suggestion, trap the WM_PASTE in the subclass and suppress it.
        CASE %WM_PASTE :EXIT FUNCTION
        Best regards
        Jules
        www.rpmarchildon.com

        Comment


        • #5
          The RE does not provide these messages.
          hellobasic

          Comment


          • #6
            Edwin, seems to work, I just tested above code with changes and the wm_paste is sent to the RE. Maybe I'm special
            Best regards
            Jules
            www.rpmarchildon.com

            Comment


            • #7
              Do you mean this?
              Code:
              Function NewProc(ByVal hWnd As Long, ByVal Msg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
                 Local temp$
                 Select Case Msg
                    Case %WM_PASTE :Exit Function
                    
                 End Select
                 Function = CallWindowProc(OldProc&, hWnd, Msg, wParam, lParam)
              End Function
              I can still paste..
              hellobasic

              Comment


              • #8
                Different versions of richedit control at work?
                Michael Mattias
                Tal Systems (retired)
                Port Washington WI USA
                [email protected]
                http://www.talsystems.com

                Comment


                • #9
                  it's by design, i suspect some luck
                  hellobasic

                  Comment


                  • #10
                    Edwin, did you also change this?
                    Code:
                    Case 100
                                   If Cb.CtlMsg = %BN_Clicked Then
                                       Clipboard Get Text To temp$
                                       'Control Set Text hDlg, %ID_RichEdit, "main " + $CrLf + temp$ 'plain text
                                       'simulate a wm_paste message...
                                       Control Send hDlg, %ID_RichEdit, %WM_PASTE,0,0
                                   End If
                    Best regards
                    Jules
                    www.rpmarchildon.com

                    Comment


                    • #11
                      As is often the case, I'm surprised sometimes when the literature doesn't have a solution to a problem that I'd have thought would have come up a zillion times.

                      Perhaps I presumed an answer to my problem, rather than stating my problem.

                      I have a richedit control which uses a font of my choice. When I paste something into the richedit control, I want the pasted text to be dispalyed using the same font.

                      But the pasted text can carry with it the formatting information from where it was copied. So, to avoid pasting the undesired formatting information, I assumed I should block the Ctrl-V paste and simply add text programatically.

                      Is there a common solution for that?

                      I could paste, then select all (because pasted content isn't automatically selected) and programmatically reformat the whole control content - but that seems a bit kludgy.

                      Comment


                      • #12
                        Actually, I only have to do this:

                        Code:
                              Case %WM_Char
                                 If wParam = &H16 Then      'pasted with CTL-V ?
                                    Control Set Font hDlg, %ID_RichEdit, hFont
                                 End If
                        The Ctrl-V is allowed to happen (well, actually, I don't know how to stop it), but then I just override the result by using Control Set Font. No selecting test is required and fortunately the insertion point is not reset.

                        Still seems inelegant, but works.
                        Last edited by Gary Beene; 7 Aug 2009, 12:44 PM.

                        Comment


                        • #13
                          Originally posted by Jules Marchildon View Post
                          Edwin, did you also change this?
                          Code:
                          Case 100
                                         If Cb.CtlMsg = %BN_Clicked Then
                                             Clipboard Get Text To temp$
                                             'Control Set Text hDlg, %ID_RichEdit, "main " + $CrLf + temp$ 'plain text
                                             'simulate a wm_paste message...
                                             Control Send hDlg, %ID_RichEdit, %WM_PASTE,0,0
                                         End If
                          If you want to do it this way you can equally remove the RTF clipboard part.
                          The text is already present and by using the PB functions you simply clear all formats.
                          hellobasic

                          Comment


                          • #14
                            Hmm, only a short while ago i did this but i can't remember where i put it.
                            It can be done if you set the OLE interface and catch a request.

                            Maybe the GetClipboardData member..
                            I am searching..
                            hellobasic

                            Comment


                            • #15
                              Yuck! My easy approach was less than great. I pasted something that had a large font and it made the RichEdit control flicker. Not a good solution after all!

                              I still need to block the Ctrl-V from happening in the first place.

                              Edwin - yep, with a button push what you showed would work. But I want the user to be allowed to use Ctrl-V, but I don't want the formatting to come with it. Hmm... is there a way to selectively remove clipboard content - remove the formatted text and leave behind text that is not formatted? Even if there is, I still don't know how to stop Ctrl-V from executing.

                              Comment


                              • #16
                                You need to set the OLE interface and then do this:
                                Code:
                                   Method QueryAcceptData ( _                    ' VTable offset = 32
                                     ByVal lpdataobj As IOleObject _             ' LPDATAOBJECT lpdataobj
                                   , ByRef lpcfFormat As Dword _                 ' CLIPFORMAT FAR * lpcfFormat
                                   , ByVal reco As Dword _                       ' DWORD reco
                                   , ByVal fReally As Long _                     ' BOOL fReally
                                   , ByVal hMetaPict As Dword _                  ' HGLOBAL hMetaPict
                                   ) As Long                                     ' HRESULT
                                    
                                     If reco = %RECO_PASTE Then
                                        [B]lpcfFormat =  %CF_TEXT[/B]
                                        Else
                                     End If
                                        Method = %S_OK
                                
                                   End Method
                                This will force to paste plain text and reuse the current font.

                                There are examples of the interface but here is Jose's version

                                http://www.jose.it-berater.org/smffo...p?topic=2804.0
                                hellobasic

                                Comment


                                • #17
                                  On wm_paste,
                                  CLIPBOARD GET TEXT
                                  set temp flag,
                                  CLIPBOARD SET TEXT
                                  CONTROL SEND message wm_paste, this will insert text at the cursor.
                                  allow wm_paste to flow to default handler,
                                  clear flag
                                  block(EXIT FUNCTION) next wm_paste
                                  repeat...
                                  Best regards
                                  Jules
                                  www.rpmarchildon.com

                                  Comment


                                  • #18
                                    There is a EM_SETCHARFORMAT, corresponding EM_SETCHARFORMAT which access the CHARFORMAT structure/type. Perhaps you have to play with these, I never have. This is in the SDK that comes with PB. The online version gave me this lovely:
                                    EM_CANPASTE
                                    The EM_CANPASTE message determines whether a rich edit control can paste a specified clipboard format.
                                    http://msdn.microsoft.com/en-us/libr...05(VS.85).aspx
                                    Rod
                                    In some future era, dark matter and dark energy will only be found in Astronomy's Dark Ages.

                                    Comment


                                    • #19
                                      Hello?
                                      The OLE interface does work..
                                      hellobasic

                                      Comment

                                      Working...
                                      X