Jump to content

Func _Caret_


Recommended Posts

Referring to my topic about the Solid Block Caret (http://www.autoitscript.com/forum/index.php?showtopic=94323), I am now trying to create a general function that everybody can use in AutoIt to change the caret type in input fields.

The function Caret Mode 2 does not work well, the underscore does not remain an underscore while typing. I hope that someone has the solution!

Enjoy!

#include <GUIConstantsEx.au3>
#include <WindowsConstants.au3>
#include <EditConstants.au3>
#include <WinAPI.au3>
$hWnd = GUICreate("Input with a selected Caret", 400, 300)
GUISetFont(12, 400, 1, "Courier")

$btnOK = GUICtrlCreateButton("&OK", 260, 248, 80, 30, 0)
$input1 = GUICtrlCreateInput("input1", 20, 24, 200, 21)
$input2 = GUICtrlCreateInput("input2", 20, 80, 200, 21)
$input3 = GUICtrlCreateInput("input3", 20, 136, 200, 21)
$input4 = GUICtrlCreateInput("input4", 20, 192, 200, 21)
$input5 = GUICtrlCreateInput("input5", 20, 248, 200, 21)
GUISetState()

_Caret_(4)
GUICtrlSetState($input2, $GUI_FOCUS); here we focus to the second input

While 1
    $nMsg = GUIGetMsg()
    Switch $nMsg
        Case -3, $GUI_EVENT_CLOSE, $btnOK
            Exit
    EndSwitch
WEnd




#==================================================================================================
; Function Name .....:  _Caret_
; Description .......:  Caret Setup
; Syntax ............:  _Caret_($i_CaretMode)
; Parameters ........:  $i_CaretMode            0 = invisible
;                                               1 = blinking vertical line caret
;                                               2 = DOS blinking underscore
;                                               3 = immobile solid block caret
;                                               4 = blinking solid block caret
; Return values .....:  None
; Creation Date .....:  2009-05-09
; Version ...........:  0.0.0.1
; Version Date ......:  2009-05-09
; Remarks ...........:  For blinking underscore like MS-DOS, try $i_CaretW = 10, $i_CaretH = 2, $i_CaretX = 0, $i_CaretY = 18
;                       The caret size to be used depends of the size of the used font and its size.
#==================================================================================================
Func _Caret_($i_CaretMode)
    Global $i_CaretX, $i_CaretY, $i_CaretW, $i_CaretH, $i_CaretSpeed, $hBitmap
    Switch $i_CaretMode
        Case 0; invisible
            $i_CaretX = 0
            $i_CaretY = 0
            $i_CaretW = 0
            $i_CaretH = 0
            $i_CaretSpeed = -1
        Case 1; blinking vertical line caret
            $i_CaretX = 0
            $i_CaretY = 0
            $i_CaretW = 1
            $i_CaretH = 18
            $i_CaretSpeed = 500
        Case 2; DOS blinking underscore
            $i_CaretX = 0
            $i_CaretY = 18
            $i_CaretW = 10
            $i_CaretH = 2
            $i_CaretSpeed = 500
        Case 3; immobile solid block caret
            $i_CaretX = 0
            $i_CaretY = 0
            $i_CaretW = 10
            $i_CaretH = 18
            $i_CaretSpeed = -1
        Case 4; blinking solid block caret
            $i_CaretX = 0
            $i_CaretY = 0
            $i_CaretW = 10
            $i_CaretH = 18
            $i_CaretSpeed = 500
;EndCase
    EndSwitch
    GUIRegisterMsg($WM_COMMAND, "_Caret_WM_COMMAND_"); Set the Function
EndFunc;==>_Caret_

Func _Caret_WM_COMMAND_($hWnd, $iMsg, $wParam, $lParam)
    If $hBitmap = "" Then $hBitmap = _WinAPI_CreateSolidBitmap(0, 0xffffff, $i_CaretW, $i_CaretH); color ori was 0x66FFFF
    Local $nNotifyCode = BitShift($wParam, 16)
    Switch $nNotifyCode; Edit control event messages only
        Case $EN_SETFOCUS; Edit (Input) control has focus
            DllCall('user32.dll', 'int', 'CreateCaret', 'hwnd', $lParam, 'ptr', $hBitmap, 'int', 0, 'int', 0)
            Sleep(10)
            DllCall("User32.dll", 'int', 'SetCaretPos', 'int', $i_CaretX, 'int', $i_CaretY)
            DllCall('user32.dll', 'int', 'SetCaretBlinkTime', 'uint', $i_CaretSpeed)
            DllCall('user32.dll', 'int', 'ShowCaret', 'hwnd', $lParam)
        Case $EN_KILLFOCUS; Edit (Input) control lost focus
            DllCall('user32.dll', 'int', 'HideCaret', 'hwnd', $lParam)
            DllCall('user32.dll', 'int', 'DestroyCaret')
    EndSwitch
    Return $GUI_RUNDEFMSG
EndFunc;==>_Caret_WM_COMMAND_
Edited by charvi
Link to comment
Share on other sites

I come to the conclusion that you do not know what to do and how it works. Look closely at the examples in your previous topic.

EDIT: You have not done anything new here, just added a lot of mistakes.

Edited by Yashied
Link to comment
Share on other sites

I come to the conclusion that you do not know what to do and how it works. Look closely at the examples in your previous topic.

Valuater is right, I forgot to add some credits. Apologies!

Yashied, indeed, I do not know exactly why the mode 2 is not working well, I am not an WinAPI specialist. I am collecting the elements that seem the easiest to use and hope they work. Experts like you can perhaps tell us what is missing in the code.

Edited by charvi
Link to comment
Share on other sites

  • If you change the value of SetCaretBlinkTime, then in the future you must restore the original value of this parameter. It is a global parameter that can be changed in Control Panel ("Cursor Blink Rate").
  • If you use _WinAPI_CreateSolidBitmap(), it would be a good idea to call _WinAPI_DeleteObject() to release the object, especially if you plan to provide this function as a UDF.
  • For each input field you need to designate a personal caret, and not to use one value for all.
  • Width, height and position of the caret should depend on the size of the input field.
  • Why only black color? Maybe somebody wants to caret of another color.
  • Why only _WinAPI_CreateSolidBitmap()? In my example I used this function only for the fact that you may better understand the working principle. You can do the following.

    #Include <Constants.au3>
    #Include <WinAPI.au3>
    #Include <WindowsConstants.au3>
    
    Opt('MustDeclareVars', 1)
    
    global $Button, $Input, $hInput, $hBitmap1, $hBitmap2, $pHook, $hProc, $Msg, $BlinkTime = default
    
    GUICreate('Test', 400, 100)
    $Input = GUICtrlCreateInput("", 20, 20, 360, 22)
    $hInput = GUICtrlGetHandle($Input)
    $Button = GUICtrlCreateButton('Exit', 165, 60, 70, 23)
    
    $hBitmap1 = _CreateBitmapFromIcon('shell32.dll', 43, 16, 16)
    $hBitmap2 = _CreateBitmapFromIcon('shell32.dll', 130, 16, 16)
    
    $pHook = DllCallbackRegister('_InputProc', 'ptr', 'hwnd;uint;long;ptr')
    $hProc = _WinAPI_SetWindowLong($hInput, $GWL_WNDPROC, DllCallbackGetPtr($pHook))
    GUISetState()
    
    while 1
        $Msg = GUIGetMsg()
        switch $Msg
            case -3, $Button
                exit
        endswitch
    wend
    
    func _InputProc($hWnd, $uiMsg, $wParam, $lParam)
        
        local $Res = _WinAPI_CallWindowProc($hProc, $hWnd, $uiMsg, $wParam, $lParam)
        
        switch $uiMsg
            case $WM_SETFOCUS, $WM_KEYUP
                _CreateCaret($hWnd, $hBitmap1)
            case $WM_KILLFOCUS
                _DestroyCaret($hWnd)
            case $WM_KEYDOWN
                _CreateCaret($hWnd, $hBitmap2)
        endswitch
        return $Res
    endfunc; _InputProc
    
    func _CreateBitmapFromIcon($sIcon, $iIndex, $iWidth, $iHeight)
        
        local $hBitmap, $hDC, $hBackDC, $hFrontDC, $hBackSv, $hFrontSv, $hIcon, $hInv
        
        $hDC = _WinAPI_GetDC(0)
        $hBackDC = _WinAPI_CreateCompatibleDC($hDC)
        $hBitmap = _WinAPI_CreateSolidBitmap(0, 0x000000, $iWidth, $iHeight)
        $hBackSv = _WinAPI_SelectObject($hBackDC, $hBitmap)
        $hIcon = _WinAPI_PrivateExtractIcon($sIcon, $iIndex, $iWidth, $iHeight)
        $hFrontDC = _WinAPI_CreateCompatibleDC($hDC)
        $hInv = _WinAPI_CreateSolidBitmap(0, 0xFFFFFF, $iWidth, $iHeight)
        $hFrontSv = _WinAPI_SelectObject($hFrontDC, $hInv)
        
        _WinAPI_DrawIconEx($hFrontDC, 0, 0, $hIcon, 0, 0, 0, 0, $DI_NORMAL)
        _WinAPI_BitBlt($hBackDC, 0, 0, $iWidth, $iHeight, $hFrontDC, 0, 0, $MERGEPAINT)
        
        _WinAPI_SelectObject($hFrontDC, $hFrontSv)
        _WinAPI_SelectObject($hBackDC, $hBackSv)
        _WinAPI_ReleaseDC(0, $hDC)
        _WinAPI_DeleteDC($hFrontDC)
        _WinAPI_DeleteDC($hBackDC)
        _WinAPI_DeleteObject($hIcon)
        _WinAPI_DeleteObject($hInv)
        
        return $hBitmap
    endfunc; _CreateBitmapFromIcon
    
    func _CreateCaret($hWnd, $hBitmap)
        DllCall('user32.dll', 'int', 'CreateCaret', 'hwnd', $hWnd, 'ptr', $hBitmap, 'int', 0, 'int', 0)
        DllCall('user32.dll', 'int', 'ShowCaret', 'hwnd', $hWnd)
        $BlinkTime = DllCall('user32.dll', 'int', 'GetCaretBlinkTime')
        $BlinkTime = $BlinkTime[0]
        DllCall('user32.dll', 'int', 'SetCaretBlinkTime', 'uint', -1)
    endfunc; _CreateCaret
    
    func _DestroyCaret($hWnd)
        DllCall('user32.dll', 'int', 'HideCaret', 'hwnd', $hWnd)
        DllCall('user32.dll', 'int', 'DestroyCaret')
        DllCall('user32.dll', 'int', 'SetCaretBlinkTime', 'uint', $BlinkTime)
    endfunc; _DestroyCaret
        
    func _WinAPI_PrivateExtractIcon($sIcon, $iIndex, $iWidth, $iHeight)
        
        local $hIcon, $tIcon = DllStructCreate('hwnd'), $tID = DllStructCreate('hwnd')
        local $ret = DllCall('user32.dll', 'int', 'PrivateExtractIcons', 'str', $sIcon, 'int', $iIndex, 'int', $iWidth, 'int', $iHeight, 'ptr', DllStructGetPtr($tIcon), 'ptr', DllStructGetPtr($tID), 'int', 1, 'int', 0)
        
        if (@error) or ($ret[0] = 0)then
            return SetError(1, 0, 0)
        endif
        
        $hIcon = DllStructGetData($tIcon, 1)
        
        if ($hIcon = Ptr(0)) or (not IsPtr($hIcon)) then
            return SetError(1, 0, 0)
        endif
        return SetError(0, 0, $hIcon)
    endfunc; _WinAPI_PrivateExtractIcon
    
    func OnAutoItExit()
        _WinAPI_SetWindowLong($hInput, $GWL_WNDPROC, $hProc)
        DllCallBackFree($pHook)
        _WinAPI_DeleteObject($hBitmap1)
        _WinAPI_DeleteObject($hBitmap2)
        if $BlinkTime <> default then
            DllCall('user32.dll', 'int', 'SetCaretBlinkTime', 'uint', $BlinkTime)
        endif
    endfunc; OnAutoItExit
Edited by Yashied
Link to comment
Share on other sites

  • If you change the value of SetCaretBlinkTime, then in the future you must restore the original value of this parameter. It is a global parameter that can be changed in Control Panel ("Cursor Blink Rate").
  • If you use _WinAPI_CreateSolidBitmap(), it would be a good idea to call _WinAPI_DeleteObject() to release the object, especially if you plan to provide this function as a UDF.
  • For each input field you need to designate a personal caret, and not to use one value for all.
  • Width, height and position of the caret should depend on the size of the input field.
  • Why only black color? Maybe somebody wants to caret of another color.
  • Why only _WinAPI_CreateSolidBitmap()? In my example I used this function only for the fact that you may better understand the working principle. You can do the following.

    #Include <Constants.au3>
    #Include <WinAPI.au3>
    #Include <WindowsConstants.au3>
    
    Opt('MustDeclareVars', 1)
    
    global $Button, $Input, $hInput, $hBitmap1, $hBitmap2, $pHook, $hProc, $Msg, $BlinkTime = default
    
    GUICreate('Test', 400, 100)
    $Input = GUICtrlCreateInput("", 20, 20, 360, 22)
    $hInput = GUICtrlGetHandle($Input)
    $Button = GUICtrlCreateButton('Exit', 165, 60, 70, 23)
    
    $hBitmap1 = _CreateBitmapFromIcon(@SystemDir & 'shell32.dll', 43, 16, 16)
    $hBitmap2 = _CreateBitmapFromIcon(@SystemDir & 'shell32.dll', 130, 16, 16)
    
    $pHook = DllCallbackRegister('_InputProc', 'ptr', 'hwnd;uint;long;ptr')
    $hProc = _WinAPI_SetWindowLong($hInput, $GWL_WNDPROC, DllCallbackGetPtr($pHook))
    GUISetState()
    
    while 1
        $Msg = GUIGetMsg()
        switch $Msg
            case -3, $Button
                exit
        endswitch
    wend
    
    func _InputProc($hWnd, $uiMsg, $wParam, $lParam)
        
        local $Res = _WinAPI_CallWindowProc($hProc, $hWnd, $uiMsg, $wParam, $lParam)
        
        switch $uiMsg
            case $WM_SETFOCUS, $WM_KEYUP
                _CreateCaret($hWnd, $hBitmap1)
            case $WM_KILLFOCUS
                _DestroyCaret($hWnd)
            case $WM_KEYDOWN
                _CreateCaret($hWnd, $hBitmap2)
        endswitch
        return $Res
    endfunc; _InputProc
    
    func _CreateBitmapFromIcon($sIcon, $iIndex, $iWidth, $iHeight)
        
        local $hBitmap, $hDC, $hBackDC, $hFrontDC, $hBackSv, $hFrontSv, $hIcon, $hInv
        
        $hDC = _WinAPI_GetDC(0)
        $hBackDC = _WinAPI_CreateCompatibleDC($hDC)
        $hBitmap = _WinAPI_CreateSolidBitmap(0, 0x000000, $iWidth, $iHeight)
        $hBackSv = _WinAPI_SelectObject($hBackDC, $hBitmap)
        $hIcon = _WinAPI_PrivateExtractIcon($sIcon, $iIndex, $iWidth, $iHeight)
        $hFrontDC = _WinAPI_CreateCompatibleDC($hDC)
        $hInv = _WinAPI_CreateSolidBitmap(0, 0xFFFFFF, $iWidth, $iHeight)
        $hFrontSv = _WinAPI_SelectObject($hFrontDC, $hInv)
        
        _WinAPI_DrawIconEx($hFrontDC, 0, 0, $hIcon, 0, 0, 0, 0, $DI_NORMAL)
        _WinAPI_BitBlt($hBackDC, 0, 0, $iWidth, $iHeight, $hFrontDC, 0, 0, $MERGEPAINT)
        
        _WinAPI_SelectObject($hFrontDC, $hFrontSv)
        _WinAPI_SelectObject($hBackDC, $hBackSv)
        _WinAPI_ReleaseDC(0, $hDC)
        _WinAPI_DeleteDC($hFrontDC)
        _WinAPI_DeleteDC($hBackDC)
        _WinAPI_DeleteObject($hIcon)
        _WinAPI_DeleteObject($hInv)
        
        return $hBitmap
    endfunc; _CreateBitmapFromIcon
    
    func _CreateCaret($hWnd, $hBitmap)
        DllCall('user32.dll', 'int', 'CreateCaret', 'hwnd', $hWnd, 'ptr', $hBitmap, 'int', 0, 'int', 0)
        DllCall('user32.dll', 'int', 'ShowCaret', 'hwnd', $hWnd)
        $BlinkTime = DllCall('user32.dll', 'int', 'GetCaretBlinkTime')
        $BlinkTime = $BlinkTime[0]
        DllCall('user32.dll', 'int', 'SetCaretBlinkTime', 'uint', -1)
    endfunc; _CreateCaret
    
    func _DestroyCaret($hWnd)
        DllCall('user32.dll', 'int', 'HideCaret', 'hwnd', $hWnd)
        DllCall('user32.dll', 'int', 'DestroyCaret')
        DllCall('user32.dll', 'int', 'SetCaretBlinkTime', 'uint', $BlinkTime)
    endfunc; _DestroyCaret
        
    func _WinAPI_PrivateExtractIcon($sIcon, $iIndex, $iWidth, $iHeight)
        
        local $hIcon, $tIcon = DllStructCreate('hwnd'), $tID = DllStructCreate('hwnd')
        local $ret = DllCall('user32.dll', 'int', 'PrivateExtractIcons', 'str', $sIcon, 'int', $iIndex, 'int', $iWidth, 'int', $iHeight, 'ptr', DllStructGetPtr($tIcon), 'ptr', DllStructGetPtr($tID), 'int', 1, 'int', 0)
        
        if (@error) or ($ret[0] = 0)then
            return SetError(1, 0, 0)
        endif
        
        $hIcon = DllStructGetData($tIcon, 1)
        
        if ($hIcon = Ptr(0)) or (not IsPtr($hIcon)) then
            return SetError(1, 0, 0)
        endif
        return SetError(0, 0, $hIcon)
    endfunc; _WinAPI_PrivateExtractIcon
    
    func OnAutoItExit()
        _WinAPI_SetWindowLong($hInput, $GWL_WNDPROC, $hProc)
        DllCallBackFree($pHook)
        _WinAPI_DeleteObject($hBitmap1)
        _WinAPI_DeleteObject($hBitmap2)
        if $BlinkTime <> default then
            DllCall('user32.dll', 'int', 'SetCaretBlinkTime', 'uint', $BlinkTime)
        endif
    endfunc; OnAutoItExit

Yashied, I'm getting an em when starting your script above: "_WinAPI_DrawIconEx: Invalid cursor handle."

UEZ

Please don't send me any personal message and ask for support! I will not reply!

Selection of finest graphical examples at Codepen.io

The own fart smells best!
Her 'sikim hıyar' diyene bir avuç tuz alıp koşma!
¯\_(ツ)_/¯  ٩(●̮̮̃•̃)۶ ٩(-̮̮̃-̃)۶ૐ

Link to comment
Share on other sites

Yashied, I'm getting an em when starting your script above: "_WinAPI_DrawIconEx: Invalid cursor handle."

UEZ

Me too... so I am unable to test your script. I'm using Vista 32.

Yashied, I must tell you that I am appreciating your immense effort...

Link to comment
Share on other sites

When I put AutoIt code in my post, the char "\" disappears. I corrected it.

Nice work Yashied! It is working properly now :)

UEZ

Please don't send me any personal message and ask for support! I will not reply!

Selection of finest graphical examples at Codepen.io

The own fart smells best!
Her 'sikim hıyar' diyene bir avuç tuz alıp koşma!
¯\_(ツ)_/¯  ٩(●̮̮̃•̃)۶ ٩(-̮̮̃-̃)۶ૐ

Link to comment
Share on other sites

When I put AutoIt code in my post, the char "\" disappears. I corrected it.

Very impressive WinAPI scripting, this is still far away of my programming knowledge. Good that you made them all in separate functions, so they can be used without too much knowledge.

Thank you very much, Yashied.

Link to comment
Share on other sites

Very impressive WinAPI scripting, this is still far away of my programming knowledge. Good that you made them all in separate functions, so they can be used without too much knowledge.

Thank you very much, Yashied.

Charvi, write Caret UDF is a good idea. But you must take into account the many nuances, so that the UDF could use the majority of interested people for their needs. This is not a trivial work. Look at Hotkeys Input Control UDF Library from my signature. This will be a good example for you.

Good luck.

EDIT: Charvi, I AM NOT THE AUTHOR OF YOUR (SEE FIRST POST) FUNCTION, PLEASE REMOVE MY NICKNAME FROM THERE.

Edited by Yashied
Link to comment
Share on other sites

EDIT: Charvi, I AM NOT THE AUTHOR OF YOUR (SEE FIRST POST) FUNCTION, PLEASE REMOVE MY NICKNAME FROM THERE.

@charvi,

Likewise there is no need to credit me in that function, as in your other thread I only pointed you to Kip's function.

Remove my name also. Thanks.

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...