Jump to content

How to I hook EM_SETSEL


E1M1
 Share

Recommended Posts

Hello. I would like to know if there's anyway to hook control messages. Following code pops up msgbox when I execute this. But when I later select text manually it doesn't pop up. Is there way to make code that would popup msgbox if EM_SETSEL is received (text is selected by user).

#Include <Constants.au3>
#Include <GUIConstants.au3>
#Include <WinAPI.au3>
#Include <WindowsConstants.au3>
#include <GuiEdit.au3>

$hForm = GUICreate('', 400, 400)
$hHook = DllCallbackRegister('_WinProc', 'ptr', 'hwnd;uint;long;ptr')
$pHook = DllCallbackGetPtr($hHook)
$edit = _GUICtrlEdit_Create($hForm,"some text",10,10,300,100)
$hProc = _WinAPI_SetWindowLong($edit, $GWL_WNDPROC, $pHook)
GUISetState()

Do
Until GUIGetMsg() = $GUI_EVENT_CLOSE

_WinAPI_SetWindowLong($hForm, $GWL_WNDPROC, $hProc)
DllCallBackFree($hProc)

Func _WinProc($hWnd, $iMsg, $wParam, $lParam)

    Local $Res = _WinAPI_CallWindowProc($hProc, $hWnd, $iMsg, $wParam, $lParam)
    Local $hDC, $hSv, $oldMsg

    Select
        Case $iMsg = $EM_SETSEL
            MsgBox(0,0,"hooked")
        Case $iMsg = $WM_LBUTTONDOWN
            ConsoleWrite($WM_LBUTTONDOWN & @LF)
        Case $iMsg = $WM_MOUSEMOVE
            ToolTip($WM_MOUSEMOVE)
    EndSelect
;~     Return 0
    Return $Res
EndFunc   ;==>_WinProc

Edit: it pops up messae box when I put _GUICtrlEdit_SetSel($edit,1,2) in loop, but it doesnt when uses selects it manually. Does anyone know how to do this?

Edit: I tried this: but it always say drag, even if mouse doesnt move.

#include <Constants.au3>
#include <GUIConstants.au3>
#include <WinAPI.au3>
#include <WindowsConstants.au3>
#include <GuiEdit.au3>
Opt("GUICloseOnESC", 0)
$hForm = GUICreate('', 400, 400)
$hHook = DllCallbackRegister('_WinProc', 'ptr', 'hwnd;uint;long;ptr')
$pHook = DllCallbackGetPtr($hHook)
$edit = _GUICtrlEdit_Create($hForm, "some text", 10, 10, 300, 100)
$hProc = _WinAPI_SetWindowLong($edit, $GWL_WNDPROC, $pHook)
GUISetState()
$btndown = False
Do
Until GUIGetMsg() = $GUI_EVENT_CLOSE
ProcessClose(@AutoItPID)
_WinAPI_SetWindowLong($hForm, $GWL_WNDPROC, $hProc)
DllCallbackFree($hProc)

Func _WinProc($hWnd, $iMsg, $wParam, $lParam)

    Local $Res = _WinAPI_CallWindowProc($hProc, $hWnd, $iMsg, $wParam, $lParam)
    Local $hDC, $hSv, $oldMsg
;~  ConsoleWrite("msg:" & $iMsg & @CRLF)
    Select
        Case $iMsg = $WM_LBUTTONDOWN
            $btndown = True
            ConsoleWrite($WM_LBUTTONDOWN & @LF)
        Case $iMsg = $WM_LBUTTONUP
            $btndown = True
            ConsoleWrite($WM_LBUTTONUP & @LF)
        Case $iMsg = $WM_MOUSEMOVE
            If $btndown Then
                ConsoleWrite("Drag" & @LF)
;~              MouseClick("left")
                $btndown = False
                Return 0
            EndIf
    EndSelect
    Return $Res
EndFunc   ;==>_WinProc
Edited by E1M1

edited

Link to comment
Share on other sites

Is there way to make code that would popup msgbox if EM_SETSEL is received (text is selected by user).

If you don't have a reason for using _GUICtrlEdit_Create() other than it returns a handle,

use GUICtrlGetHandle(-1)

You need to change the param types for DllCallbackRegister(), your example would hang when I ran it.

EM_SETSEL is only received when sendmessage used, EM_GETSEL is received only when text is selected then focus is lost,

so other messages have to be used.

This example retrieves the current text selection on mouse or key up

and optionally can retrieve realtime selection by mouse drag or shift/arrow keys/end/home/pgup/pgdn

double click word select also added.

There are probably examples of this is already on the forum, but here's my take.

;#AutoIt3Wrapper_Au3Check_Parameters=-d -w 1 -w 2 -w 3 -w 4 -w 5 -w 6
#include <Constants.au3>
#include <GUIConstants.au3>
#include <WinAPI.au3>
#include <WindowsConstants.au3>
#include <GuiEdit.au3>

Opt("MustDeclareVars", 1)

Global $iDLLUser32 = DllOpen("user32.dll") ;open a library handle for CallWindowProcW DllCall()
Global $fSel = False, $cEditEvent, $hProc

_Main()

Func _Main()
    Local $hForm, $cEdit, $hEdit, $iMsg, $aPos, $sText, $hHook, $pHook
    $hForm = GUICreate('', 400, 400)

    ;$hEdit = _GUICtrlEdit_Create($hForm, FileRead(@ScriptFullPath), 10, 10, 380, 300)

    $cEdit = GUICtrlCreateEdit(FileRead(@ScriptFullPath), 10, 10, 380, 300)
    $hEdit = GUICtrlGetHandle(-1)

    $cEditEvent = GUICtrlCreateDummy()
    $hHook = DllCallbackRegister('_WinProc', 'ptr', 'hwnd;uint;wparam;lparam')
    $pHook = DllCallbackGetPtr($hHook)
    $hProc = _WinAPI_SetWindowLong($hEdit, $GWL_WNDPROC, $pHook)
    GUISetState()

    While 1
        $iMsg = GUIGetMsg()
        Switch $iMsg
            Case 0
            Case $GUI_EVENT_CLOSE
                ExitLoop
            Case $cEditEvent
                $aPos = _GUICtrlEdit_GetSel($hEdit)
                If $aPos[0] <> $aPos[1] Then
                    ;$sText = StringMid(_GUICtrlEdit_GetText($hEdit), $aPos[0] + 1, $aPos[1] - $aPos[0])
                    $sText = StringMid(GUICtrlRead($cEdit), $aPos[0] + 1, $aPos[1] - $aPos[0])
                    If StringIsSpace($sText) Then $sText = "<SPACE - Count: " & ($aPos[1] - $aPos[0]) & ">"
                    ConsoleWrite('>Text Selected: ' & $sText & @CRLF & "!Count: " & ($aPos[1] - $aPos[0]) & @CRLF & '+From:' & @TAB & $aPos[0] & @CRLF & '-To:' & @TAB & $aPos[1] & @CRLF & @CRLF)
                EndIf
        EndSwitch
    WEnd

    If $hProc Then _WinAPI_SetWindowLong($hEdit, $GWL_WNDPROC, $hProc)
    DllCallbackFree($hHook)
    DllClose($iDLLUser32)
    GUIDelete($hForm)
    Exit
EndFunc   ;==>_Main


Func _WinProc($hWnd, $iMsg, $wParam, $lParam)
    ;do not run blocking functions from here.
    ;Use global vars or event set by a dummy control in msg loop or event mode
    Switch $iMsg
        ;optionally get realtime update of selected text by mouse drag or shift/arrow keys/end/home/pgup/pgdn
        Case $WM_MOUSEMOVE, $WM_GETDLGCODE
            If $fSel = True Then
                GUICtrlSendToDummy($cEditEvent)
            EndIf
        Case $WM_LBUTTONDOWN, $WM_KEYDOWN, $WM_LBUTTONDBLCLK ;WM_LBUTTONDBLCLK for mouse word select
            $fSel = True
        Case $WM_LBUTTONUP, $WM_KEYUP
            If $fSel = True Then
                GUICtrlSendToDummy($cEditEvent)
                $fSel = False
            EndIf
    EndSwitch

    Local $aResult = DllCall($iDLLUser32, "lresult", "CallWindowProcW", "ptr", $hProc, _
            "hwnd", $hWnd, "uint", $iMsg, "wparam", $wParam, "lparam", $lParam)
    If @error Then Return -1
    Return $aResult[0]
EndFunc   ;==>_WinProc

I see fascists...

Link to comment
Share on other sites

Thank you for this very good example. I didn't know you can do Case $WM_MOUSEMOVE, $WM_GETDLGCODE

does this mean that it can be $WM_MOUSEMOVE or $WM_GETDLGCODE ... or does it mean it must be $WM_MOUSEMOVE and $WM_GETDLGCODE

edited

Link to comment
Share on other sites

Thank you for this very good example. I didn't know you can do Case $WM_MOUSEMOVE, $WM_GETDLGCODE

does this mean that it can be $WM_MOUSEMOVE or $WM_GETDLGCODE ... or does it mean it must be $WM_MOUSEMOVE and $WM_GETDLGCODE

Hi E1M1

value OR value

something I learned from the forum

In the help file it is not clearly stated, but is implied by the comma between the value To value statements.

I wonder if this is on the list for the ongoing help file update?

I don't think it's unsupported, just undocumented, but I could be wrong.

I've used this for some time now, perhaps it's time to refresh my memory on this with a search of the forum.

Edit: The help file example for ContinueCase uses commas between values.

Edited by rover

I see fascists...

Link to comment
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
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...