Sign in to follow this  
Followers 0
simbo

Capturing paste commands

8 posts in this topic

Hello All, and Happy New Year

I've written a program with a number of input boxes that the user can type into.

They may wish to paste something in from the clipboard.

The challenge is that I don't want the user to be able to paste straight in, I want to first check the clipboard and possibly format it in some way before either letting it be pasted straight in or using guictrlsetdata to put the formatted version into the input box they've just tried to paste into.

How do I capture the paste command? I'm guessing it's something to do with GUIRegisterMsg and $WM_PASTE, but I can't seem to work it out

I'm thinking something like this:-

#include <GUIConstants.au3>

$my_gui=GUICreate("Type or paste some stuff",700,500,-1,-1,$WS_THICKFRAME,-1)

guisetstate (@SW_SHOW)

$my_input=GUICtrlCreateInput("",20,20,400,250)

GUIRegisterMsg($WM_PASTE, 'do_clever_stuff_with_clipboard')

While 1

$gm = GUIGetMsg()

Switch $gm

Case -3; $GUI_EVENT_CLOSE

ExitLoop

EndSwitch

WEnd

Func do_clever_stuff_with_clipboard()

$clipboard=ClipGet()

;generally fiddle about with $clipboard

; then either send("^v") or GUICtrlSetData($my_input,$clipboard)

EndFunc

Many thanks in advance

Simbo

Share this post


Link to post
Share on other sites



perhaps just monitor the input controls and compare to current clipboard contents

so if content of one of the inputs is same as clipboard then reformat the text and guictrlsetdata the input.

The $WM_PASTE message I think has to be sifted out of WM_COMMAND messages

maybe someone will jump in here and give a more informed answer.

#include <GUIConstants.au3>

$gui = GUICreate("GUI input", 320, 120, @DesktopWidth / 2 - 160, @DesktopHeight / 2 - 45)
$ret = GUICtrlCreateInput("", 10, 35, 300, 20)
$btn = GUICtrlCreateButton("Ok", 40, 75, 60, 20)
GUISetState()


$Timer = TimerInit()
While 1
    $msg = GUIGetMsg()
    Switch $msg
        Case $btn
            MsgBox(0, "", GUICtrlRead($ret))
            Exit
        Case $GUI_EVENT_CLOSE
            Exit
    EndSwitch
    If TimerDiff($Timer) >= 100 Then
        $intext = GUICtrlRead($ret)
        $cliptext = ClipGet()
        If $intext = $cliptext Then
            ; do string manipulation here
            GUICtrlSetData($ret, "Info: " & $intext) ; pasting into message box will append text 'Info:'
        EndIf
        $Timer = TimerInit()
    EndIf
WEnd

I see fascists...

Share this post


Link to post
Share on other sites

#3 ·  Posted (edited)

GuiRegisterMsg lets you work with messages of the main window. To work with messages of controls (such as in your case WM_PASTE to edit control), you need to subclass that control.

#include <GUIConstants.au3>
#Include <GuiEdit.au3>
    
$hGui = GUICreate("Type or paste some stuff",400,200,-1,-1,$WS_THICKFRAME,-1)
$cInput = GUICtrlCreateInput("",20,20,360,20)
$cInput2 = GUICtrlCreateInput("",20,50,360,20)

$wProcNew = DllCallbackRegister("_MyWindowProc", "ptr", "hwnd;uint;long;ptr")
$wProcOld = _WinSubclass(GUICtrlGetHandle($cInput), DllCallbackGetPtr($wProcNew))
_WinSubclass(GUICtrlGetHandle($cInput2), DllCallbackGetPtr($wProcNew))
;_WinSubclass(GUICtrlGetHandle($cInput3), DllCallbackGetPtr($wProcNew)) and so on

GUISetState(@SW_SHOW)
While 1
    Switch GUIGetMsg()
        Case $GUI_EVENT_CLOSE
            ExitLoop
    EndSwitch
WEnd

Func do_clever_stuff_with_clipboard($hWnd)
    $sData = ClipGet()
    If @error Then Return 0;clip data is not text or clip empty
;do whatever
    $sData = StringUpper($sData)
;set text
    GUICtrlSetData(_WinAPI_GetDlgCtrlID($hWnd), $sData);or _GUICtrlEdit_SetText($hWnd, $sData)
    Return 1
EndFunc

Func _MyWindowProc($hWnd, $uiMsg, $wParam, $lParam)
    Switch $uiMsg
        Case $WM_PASTE
            Return do_clever_stuff_with_clipboard($hWnd)
    EndSwitch
    
;pass the unhandled messages to default WindowProc
    Return _CallWindowProc($wProcOld, $hWnd, $uiMsg, $wParam, $lParam)
EndFunc

Func _CallWindowProc($lpPrevWndFunc, $hWnd, $Msg, $wParam, $lParam)
    Local $aRet = DllCall('user32.dll', 'int', 'CallWindowProc', 'ptr', $lpPrevWndFunc, 'hwnd', $hWnd, 'uint', $Msg, 'wparam', $wParam, 'lparam', $lParam)
    Return $aRet[0]
EndFunc

;-- Wrapper for SetWindowLong API
Func _WinSubclass($hWnd, $lpNewWindowProc)
;#define GWL_WNDPROC (-4)
    Local $aTmp, $sFunc = "SetWindowLong"
    If @Unicode Then $sFunc &= "W"
    $aTmp = DllCall("user32.dll", "ptr", $sFunc, "hwnd", $hWnd, "int", -4, "ptr", $lpNewWindowProc)
    If @error Then Return SetError(1, 0, 0)
    If $aTmp[0] = 0 Then Return SetError(1, 0, 0)
    Return $aTmp[0]
EndFunc  ;==>_WinSubclass

As for what to do once you get to that WM_PASTE, you can do whichever way you like. Get the clipboard and set the data to control yourself like in the example above, or modify the clipboard directly and proceed with the default handler.

Edited by Siao

"be smart, drink your wine"

Share this post


Link to post
Share on other sites

GuiRegisterMsg lets you work with messages of the main window. To work with messages of controls (such as in your case WM_PASTE to edit control), you need to subclass that control.

#include <GUIConstants.au3>

$hGui = GUICreate("Type or paste some stuff",400,200,-1,-1,$WS_THICKFRAME,-1)
$cInput = GUICtrlCreateInput("",20,20,360,20)
$hInput = GUICtrlGetHandle($cInput)
$wProcNew = DllCallbackRegister("_MyWindowProc", "ptr", "hwnd;uint;long;ptr")
$wProcOld = _WinSubclass($hInput, DllCallbackGetPtr($wProcNew))

GUISetState(@SW_SHOW)
While 1
    Switch GUIGetMsg()
        Case $GUI_EVENT_CLOSE
            ExitLoop
    EndSwitch
WEnd

Func do_clever_stuff_with_clipboard()
    $sData = ClipGet()
    If @error Then Return 0;clip data is not text or clip empty
;do whatever
    $sData = StringUpper($sData)
;set text
    GUICtrlSetData($cInput, $sData)
    Return 1
EndFunc

Func _MyWindowProc($hWnd, $uiMsg, $wParam, $lParam)
    Switch $uiMsg
        Case $WM_PASTE
            Return do_clever_stuff_with_clipboard()
    EndSwitch
    
;pass the unhandled messages to default WindowProc
    Return _CallWindowProc($wProcOld, $hInput, $uiMsg, $wParam, $lParam)
EndFunc

Func _CallWindowProc($lpPrevWndFunc, $hWnd, $Msg, $wParam, $lParam)
    Local $aRet = DllCall('user32.dll', 'int', 'CallWindowProc', 'ptr', $lpPrevWndFunc, 'hwnd', $hWnd, 'uint', $Msg, 'wparam', $wParam, 'lparam', $lParam)
    Return $aRet[0]
EndFunc

;-- Wrapper for SetWindowLong API
Func _WinSubclass($hWnd, $lpNewWindowProc)
;#define GWL_WNDPROC (-4)
    Local $aTmp, $sFunc = "SetWindowLong"
    If @Unicode Then $sFunc &= "W"
    $aTmp = DllCall("user32.dll", "ptr", $sFunc, "hwnd", $hWnd, "int", -4, "ptr", $lpNewWindowProc)
    If @error Then Return SetError(1, 0, 0)
    If $aTmp[0] = 0 Then Return SetError(1, 0, 0)
    Return $aTmp[0]
EndFunc ;==>_WinSubclass

As for what to do once you get to that WM_PASTE, you can do whichever way you like. Get the clipboard and set the data to control yourself like in the example above, or modify the clipboard directly and proceed with the default handler.

Thanks very much for that Siao - you've hit the proverbial nail on the head

I can't pretend to be clever enough to really understand how it works!! (although I've had a good go using the help file)

I perhaps should have put more input boxes in my example as my program uses several. I've tried altering your code to assign the boxes to an array, a bit like this:-

for $i=0 to 9

$cInput[$i] = GUICtrlCreateInput("",20,30*$i,360,20)

$hInput[$i] = GUICtrlGetHandle($cInput[$i])

next

- but I'm in over my head! Is such a thing possible? Any help would be much appreciated as it's the last thing I've got to do on my program (probably because I've been putting it off!)

Thanks again,

Simbo

Share this post


Link to post
Share on other sites

#5 ·  Posted (edited)

Ok, modified example in my post above to work with multiple input controls...

Edited by Siao

"be smart, drink your wine"

Share this post


Link to post
Share on other sites

There is always the simple method

If GUICtrlRead($myInput) == ClipGet() Then
  MsgBox(0, "CHEATER!", "You tried to cheat me by pasting from the clipboard")
   GUICtrlSetData($myInput, "")
   ClipPut("")
   GUICtrlSetState($myInput, 512)
Else
  MsgBox(0, "OK",  "You passed the acid test")
EndIf

George

Question about decompiling code? Read the decompiling FAQ and don't bother posting the question in the forums.

Be sure to read and follow the forum rules. -AKA the AutoIt Reading and Comprehension Skills test.***

The PCRE (Regular Expression) ToolKit for AutoIT - (Updated Oct 20, 2011 ver:3.0.1.13) - Please update your current version before filing any bug reports. The installer now includes both 32 and 64 bit versions. No change in version number.

Visit my Blog .. currently not active but it will soon be resplendent with news and views. Also please remove any links you may have to my website. it is soon to be closed and replaced with something else.

"Old age and treachery will always overcome youth and skill!"

Share this post


Link to post
Share on other sites

Ok, modified example in my post above to work with multiple input controls...

Thanks very much Siao, I'm still not entirely with it, but I've got it to work!

I'd have been there forever trying to figure that out.

Best wishes

Matt

Share this post


Link to post
Share on other sites

There is some API called SetClipboardViewer or something also... worth a research...

Lar.


f_mrcleansmalm_77ce002.jpgAutoIt has helped make me wealthy

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!


Register a new account

Sign in

Already have an account? Sign in here.


Sign In Now
Sign in to follow this  
Followers 0