Jump to content

Recommended Posts

Posted

You could be rigth but I don't want to develop the corresponding StringReplace equivalent to the StringRegExpReplace example

If you have one just postit

Posted (edited)
6 hours ago, jpm said:

If you have one just post it

Hellooo jpm, wishing you a very good year 2026, great timing  :)

I just scripted the following example, it seems to confirm this :

* Case sensitive   : StringReplace is faster than StringRegExpReplace
* Case insensitive : the opposite, StringRegExpReplace is faster, just like written in the help file.

#include <MsgBoxConstants.au3>
#include <StringConstants.au3>

Opt("MustDeclareVars", 1)

Example()

Func Example()
    Local $sSubject

    ; Subject definition
    For $i = 65 To 90
        $sSubject &= Chr($i) & Chr($i + 32) ; "AaBb...YyZz" : 52 chars (26*2)
    Next
    For $i = 1 To 17 ; Do not increase this loop too much, it would quickly generate a very big subject !
        $sSubject &= $sSubject
    Next
    ConsoleWrite("Subject is " & StringLen($sSubject) & " long" & @crlf & @crlf) ; 6,815,744 chars when 17 in For loop

    _CompareSpeed($sSubject, True)  ; case sensitive
    _CompareSpeed($sSubject, False) ; case insensitive
EndFunc   ;==>Example

Func _CompareSpeed(ByRef $sSubject, $bSensitive)
    Local $sSearch, $sReplace, $hTimer, $sOutput1, $sOutput2

    ; Search string and Replace string
    $sSearch = "Aa"
    $sReplace = "12"

    ConsoleWrite("Case " & ($bSensitive ? "" : "in") & "sensitive :" & @crlf)

    ; StringReplace
    $hTimer = TimerInit()
    $sOutput1 = StringReplace($sSubject, $sSearch, $sReplace, 0, ($bSensitive ? $STR_CASESENSE : $STR_NOCASESENSE))
    ConsoleWrite(@extended & " replacements with StringReplace        Timer : " & TimerDiff($hTimer) & @crlf)

    ; StringRegExpReplace
    $hTimer = TimerInit()
    $sOutput2 = StringRegExpReplace($sSubject, ($bSensitive ? "" : "(?i)") & $sSearch, $sReplace)
    ConsoleWrite(@extended & " replacements with StringRegExpReplace  Timer : " & TimerDiff($hTimer) & @crlf & @crlf)

    ; Keep this ?
    If Not ($sOutput1 == $sOutput2) Then
        MsgBox($MB_TOPMOST, "No way", "StringReplace output <> StringRegExpReplace output !")
    EndIf
EndFunc   ;==>_CompareSpeed

Edit: Same script below, one function instead of two :

#include <MsgBoxConstants.au3>
#include <StringConstants.au3>

Opt("MustDeclareVars", 1)

Example()

Func Example()
    Local $sSubject, $sSearch, $sReplace, $hTimer, $sOutput1, $sOutput2

    ; Subject definition
    For $i = 65 To 90
        $sSubject &= Chr($i) & Chr($i + 32) ; "AaBb...YyZz" : 52 chars (26*2)
    Next
    For $i = 1 To 17 ; Do not increase this loop too much, it would quickly generate a very big subject !
        $sSubject &= $sSubject
    Next
    ConsoleWrite("Subject is " & StringLen($sSubject) & " long" & @crlf & @crlf) ; 6,815,744 chars when 17 in For loop

    ; Search string and Replace string
    $sSearch = "Aa"
    $sReplace = "12"

    ; Speed comparison
    For $bSensitive = 1 To 0 Step -1
        ConsoleWrite("Case " & ($bSensitive ? "" : "in") & "sensitive :" & @crlf)

        ; StringReplace
        $hTimer = TimerInit()
        $sOutput1 = StringReplace($sSubject, $sSearch, $sReplace, 0, ($bSensitive ? $STR_CASESENSE : $STR_NOCASESENSE))
        ConsoleWrite(@extended & " replacements with StringReplace        Timer : " & TimerDiff($hTimer) & @crlf)

        ; StringRegExpReplace
        $hTimer = TimerInit()
        $sOutput2 = StringRegExpReplace($sSubject, ($bSensitive ? "" : "(?i)") & $sSearch, $sReplace)
        ConsoleWrite(@extended & " replacements with StringRegExpReplace  Timer : " & TimerDiff($hTimer) & @crlf & @crlf)

        ; Keep this ?
        If Not ($sOutput1 == $sOutput2) Then
            MsgBox($MB_TOPMOST, "No way", "StringReplace output <> StringRegExpReplace output !")
        EndIf
    Next
EndFunc   ;==>Example

 

Edited by pixelsearch
added same 2nd script (one function instead of 2)

"I think you are searching a bug where there is no bug... don't listen to bad advice."

Posted (edited)
1 hour ago, pixelsearch said:

* Case sensitive   : StringReplace is faster than StringRegExpReplace
* Case insensitive : the opposite, StringRegExpReplace is faster, just like written in the help file.

No big surprise here: when comparing raw codepoints AutoIt internals can make use of very fast machine instructions, while any regex engine has to dissect and compile the pattern and loop over the string & pattern.

On the contrary, when it comes to process codepoints in any non-raw way or when the pattern isn't a bare string compare, regexes use very fast code using internal tables while AutoIt relies on Windows low-level primitives in a loop.

Just tried a third compare run with regex including (*UCP) and the outcome is almost identical.

Edited by jchd

This wonderful site allows debugging and testing regular expressions (many flavors available). An absolute must have in your bookmarks.
Another excellent RegExp tutorial. Don't forget downloading your copy of up-to-date pcretest.exe and pcregrep.exe here
RegExp tutorial: enough to get started
PCRE v8.33 regexp documentation latest available release and currently implemented in AutoIt beta.

SQLitespeed is another feature-rich premier SQLite manager (includes import/export). Well worth a try.
SQLite Expert (freeware Personal Edition or payware Pro version) is a very useful SQLite database manager.
An excellent eBook covering almost every aspect of SQLite3: a must-read for anyone doing serious work.
SQL tutorial (covers "generic" SQL, but most of it applies to SQLite as well)
A work-in-progress SQLite3 tutorial. Don't miss other LxyzTHW pages!
SQLite official website with full documentation (may be newer than the SQLite library that comes standard with AutoIt)

Posted

@jchd how great, you're here too. So a very good year 2026 to you and best wishes :)
Thanks for your explanation & confirmation of the preceding speed comparison results.

By the way, I'd like to ask you : here is the list of the 12 RegEx metacharacters found in AutoIt help file, topic StringRegExp ?

\ . ^ $ | [ ( { * + ? #

If we look at this original pcre doc, they also indicate 12 metacharacters but :
1) they exclude the # which (I guess) needs to be escaped only when the option (?x) is used in the pattern (to be confirmed)
2) Most important, they include the closing parenthesis ==> )

Here is a short example showing that the closing parenthesis must be escaped, which should mean it is a metacharacter :

Subject :  123)456
Pättern1:  )
Pättern2:  \)

Pattern1 will fail, when pattern2 will retrieve the closing parenthesis, because it is escaped in the pattern.

So my question is : shouldn't the closing parenthesis be added to the list of metacharacters in AutoIt help file ?
Thanks !

"I think you are searching a bug where there is no bug... don't listen to bad advice."

Posted
9 hours ago, pixelsearch said:

1) they exclude the # which (I guess) needs to be escaped only when the option (?x) is used in the pattern (to be confirmed)
2) Most important, they include the closing parenthesis ==> )

@pixelsearch you're right on 2)

About 1) and (*X), that PCRE_EXTRA option is something you can ever use only after digging deep in PCRE code, only helpful in very VERY dark corner cases you should avoid at any rate. Hence # should be removed from the list in help.

Omitting ) is a much bigger mistake, one which will haunt me for the rest of the year!

BTW, I whish a peaceful 2026 to everyone in and, most importantly, outside the AutoIt community.

This wonderful site allows debugging and testing regular expressions (many flavors available). An absolute must have in your bookmarks.
Another excellent RegExp tutorial. Don't forget downloading your copy of up-to-date pcretest.exe and pcregrep.exe here
RegExp tutorial: enough to get started
PCRE v8.33 regexp documentation latest available release and currently implemented in AutoIt beta.

SQLitespeed is another feature-rich premier SQLite manager (includes import/export). Well worth a try.
SQLite Expert (freeware Personal Edition or payware Pro version) is a very useful SQLite database manager.
An excellent eBook covering almost every aspect of SQLite3: a must-read for anyone doing serious work.
SQL tutorial (covers "generic" SQL, but most of it applies to SQLite as well)
A work-in-progress SQLite3 tutorial. Don't miss other LxyzTHW pages!
SQLite official website with full documentation (may be newer than the SQLite library that comes standard with AutoIt)

Posted

@jpm thanks for adding the 2nd example to the StringReplace topic.

So In his post above, jchd just confirmed  that the list of 12 metacharacters should be changed in the AutoIt help file, removing # and adding )
This list is found in 2 different topics : StringRegExp (of course) and StringReplace (remarks section)

jpm, if you don't mind, I got 2 other points I'd like to discuss with you, then I promise to set you free as soon as 2026 starts :)

1) Three missing constants in AutoIt : SB_LEFT (6) SB_RIGHT (7) SB_ENDSCROLL (8) . When I needed them, I found their values in WinUser.h  .  Could we add them to the include file ScrollBarsConstants.au3 ?

2) Please have a look at this post. OP is right, the documentation is confusing and I got caught myself a few days ago for the same reason : the help file shouldn't state this in the ControlGetPos topic :

ControlGetPos
Retrieves the position and size of a control relative to its window.

As shown in his example, a control placed in a child window doesn't have its ControlGetPos "relative to its window" (the child window in his case), it's relative to its top level window (the GUI in his case). So could we please amend the help file like the following, or any other sentence that you'd find more accurate :

ControlGetPos
Retrieves the position and size of a control relative to its top level window.

Thanks

1 hour ago, jchd said:

Omitting ) is a much bigger mistake, one which will haunt me for the rest of the year!

This made me laugh so much. I should have posted this tomorrow so you'd be haunted 365 days instead of 12 hours :D

1 hour ago, jchd said:

I wish a peaceful 2026 to everyone in and, most importantly, outside the AutoIt community.

"outside" is the keyword in your wishes. Great thoughts & nicely expressed :thumbsup:

"I think you are searching a bug where there is no bug... don't listen to bad advice."

Posted
19 minutes ago, pixelsearch said:

I should have posted this tomorrow so you'd be haunted 365 days instead of 12 hours :D

Then I'd have said: "... for the rest of the day". 71 now, but I still can count for some time!

This wonderful site allows debugging and testing regular expressions (many flavors available). An absolute must have in your bookmarks.
Another excellent RegExp tutorial. Don't forget downloading your copy of up-to-date pcretest.exe and pcregrep.exe here
RegExp tutorial: enough to get started
PCRE v8.33 regexp documentation latest available release and currently implemented in AutoIt beta.

SQLitespeed is another feature-rich premier SQLite manager (includes import/export). Well worth a try.
SQLite Expert (freeware Personal Edition or payware Pro version) is a very useful SQLite database manager.
An excellent eBook covering almost every aspect of SQLite3: a must-read for anyone doing serious work.
SQL tutorial (covers "generic" SQL, but most of it applies to SQLite as well)
A work-in-progress SQLite3 tutorial. Don't miss other LxyzTHW pages!
SQLite official website with full documentation (may be newer than the SQLite library that comes standard with AutoIt)

Posted

@pixelsearch about 2  I agree to update the doc

at least it is coherent with the usage in MoveMove()

#include <GUIConstantsEx.au3>
#include <WindowsConstants.au3>

Local $hWndParent = GUICreate("ControlGetPos in a child GUI")
Local $idInfo = GUICtrlCreateLabel("", 20, 150, 300, 100)
Local $hWndChild = GUICreate("Child", 100, 100, 5, 5, BitOR($WS_BORDER, $WS_CHILD, $WS_VISIBLE), -1, $hWndParent)
Local $idBtn = GUICtrlCreateButton("BTN", 10, 10, 60, 40)

Local $aPOS = ControlGetPos($hWndChild, '', $idBtn)

Local $sText = "BTN in Child Window" & @CRLF & @CRLF & "     relative to parent window" & @CRLF & "Position: " & $aPos[0] & ", " & $aPos[1] & @CRLF & "Size: " & $aPos[2] & ", " & $aPos[3]
GUICtrlSetData($idInfo, $sText)

GUISetState(@SW_SHOW, $hWndParent)

ControlClick($hWndChild, "", $idBtn, "left", 1, $aPOS[0], $aPOS[1])

Opt("MouseCoordMode", 2) ; coord in client area
MouseMove($aPOS[0], $aPOS[1])

While 1
    Switch (GUIGetMsg())
        Case $idBtn
            GUICtrlSetData($idInfo, $sText & @CRLF & @CRLF & " >>>>>>>>> BTN clicked <<<<<<<<<<<<<<<")

        Case $GUI_EVENT_CLOSE
            Exit

    EndSwitch

    Sleep(10)
WEnd

 

Posted
3 hours ago, jpm said:

about 2  I agree to update the doc [of ControlGetPos]
at least it is coherent with the usage in MouseMove()

Thanks for your example ! So we just need a better way to rephrase this in the help file (ControlGetPos topic), avoiding the term "relative to its window".

If you look at the following example I just scripted (3 Gui's), maybe the "ancestor" word could be clearer, if we're sure it is accurate in all cases ?

Because when it comes to a control created inside a child window, then the terms "parent" or "relative to its window" are wrong and confusing (concerning ControlGetPos) when "ancestor" could be more appropriate, as you'll notice in the MessageBox. Anyway you'll decide.

For the record, imagine how simpler all this would have been if the 3 lines found in the code below returned 3 different results...

Local $aPos = ControlGetPos($hChild_2, "", $idBtn)
; Local $aPos = ControlGetPos($hChild_1, "", $idBtn) : same result :(
; Local $aPos = ControlGetPos($hGUI, "", $idBtn) ; same result :(

...then we won't have to use constantly ScreentoCli, CliToScreen and the whole gang. Well... we can always dream, can't we ? :D

#include <GUIConstantsEx.au3>
#include <MsgBoxConstants.au3>
#include <WinAPISysWin.au3>
#include <WindowsConstants.au3>

Opt("MustDeclareVars", 1)

;==============
Local $hGUI = GUICreate("Main GUI", 300, 200)
;==============
Local $hChild_1 = GUICreate("Child_1", 280, 180, 10, 10, $WS_CHILD, -1, $hGUI) ; 10 pixels inside GUI
GUISetBkColor(0xFFFF00) ; yellow
;==============
Local $hChild_2 = GUICreate("Child_2", 240, 140, 20, 20, $WS_CHILD, -1, $hChild_1) ; + 20 pixels inside $hChild_1
GUISetBkColor(0xC0FFFF) ; light blue
Local $idBtn = GUICtrlCreateButton("Button", 40, 40, 80, 30) ; + 40 pixels inside $hChild_2 (that's 10+20+40 = 70 pixels inside GUI)
Local $hBtn = GUICtrlGetHandle($idBtn)

Local $aPos = ControlGetPos($hChild_2, "", $idBtn)
; Local $aPos = ControlGetPos($hChild_1, "", $idBtn) : same result :(
; Local $aPos = ControlGetPos($hGUI, "", $idBtn) ; same result :(

Local $hAncestor = _WinAPI_GetAncestor($hBtn, $GA_ROOT)
Local $hParent = _WinAPI_GetParent($hBtn)

GUISetState(@SW_SHOW, $hGUI)
GUISetState(@SW_SHOW, $hChild_1)
GUISetState(@SW_SHOW, $hChild_2)

MsgBox($MB_TOPMOST, "Infos 3 GUI's and Button", _
    "$hGUI = " & $hGUI & "   $hChild_1 = " & $hChild_1 & "   $hChild_2 = " & $hChild_2 & @crlf & @crlf & _
    "Button ControlGetPos X / Y  :  $aPos[0] = "& $aPos[0] & "  /  $aPos[1] = " & $aPos[1] & @crlf & @crlf & _
    "Button Ancestor ($GA_ROOT) = " & $hAncestor & "    Button Parent = " & $hParent)

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

Jean-Paul, all the best for 2026, just stay healthy, always alive & kicking :thumbsup:

"I think you are searching a bug where there is no bug... don't listen to bad advice."

Posted (edited)
11 hours ago, jpm said:

I agree ControlGetPos must return different coord according to corresponding the guicreate
I will look at it

Thanks for that :)
You know, I'm not really sure ControlGetPos could ever be amended as it would be script-breaking for many people, who didn't care about its 1st parameter, indicating any window handle in it (Ancestor, parent etc...) for the same result.

But an additional function could be helpful. For example I tried _ControlGetPosEx() in the script below, though I scripted it without error checking and having no idea about the way to handle its 2nd parameter $sTxt . Basically it's just a wrapper for _WinAPI_ScreenToClient (when the window handle passed as 1st parameter is not the Ancestor) to make it easier for the user when calling the function. Anyway, it's a start... as long as the 1st param. is a window handle and the 2nd param stays empty "" , At least I'll start to use it from now on, reporting if something goes bad.

#include <GUIConstantsEx.au3>
#include <MsgBoxConstants.au3>
#include <WinAPIConv.au3>
#include <WinAPISysWin.au3>
#include <WindowsConstants.au3>

Opt("MustDeclareVars", 1)

;==============
Local $hGUI = GUICreate("Main GUI v2", 300, 200)
;==============
Local $hChild_1 = GUICreate("Child_1", 280, 180, 10, 10, $WS_CHILD, -1, $hGUI) ; 10 pixels inside GUI
GUISetBkColor(0xFFFF00) ; yellow
;==============
Local $hChild_2 = GUICreate("Child_2", 240, 140, 20, 20, $WS_CHILD, -1, $hChild_1) ; + 20 pixels inside $hChild_1
GUISetBkColor(0xC0FFFF) ; light blue
Local $idBtn = GUICtrlCreateButton("Button", 40, 40, 80, 30) ; + 40 pixels inside $hChild_2 (that's 10+20+40 = 70 pixels inside GUI)
Local $hBtn = GUICtrlGetHandle($idBtn)

Local $aPos2 = ControlGetPos($hChild_2, "", $idBtn)
Local $aPos1 = ControlGetPos($hChild_1, "", $idBtn) ; same result :(
Local $aPos0 = ControlGetPos($hGUI, "", $idBtn) ; same result :(

Local $aPosEx2 = _ControlGetPosEx($hChild_2, "", $idBtn)
Local $aPosEx1 = _ControlGetPosEx($hChild_1, "", $idBtn)
Local $aPosEx0 = _ControlGetPosEx($hGUI, "", $idBtn)

Local $hAncestor = _WinAPI_GetAncestor($hBtn, $GA_ROOT)
Local $hParent = _WinAPI_GetParent($hBtn)

GUISetState(@SW_SHOW, $hGUI)
GUISetState(@SW_SHOW, $hChild_1)
GUISetState(@SW_SHOW, $hChild_2)

MsgBox($MB_TOPMOST, "Infos 3 GUI's and Button v2", _
    "$hGUI = " & $hGUI & "   $hChild_1 = " & $hChild_1 & "   $hChild_2 = " & $hChild_2 & @crlf & _
    "Button Ancestor ($GA_ROOT) = " & $hAncestor & "    Button Parent = " & $hParent & @crlf & _
    @crlf & _
    "Button ControlGetPos     (Child2)  = " & $aPos2[0]  & "/"  & $aPos2[1]   & "/" & $aPos2[2]   & "/" & $aPos2[3] & @crlf & _
    "Button ControlGetPos     (Child1)  = " & $aPos1[0]  & "/"  & $aPos1[1]   & "/" & $aPos1[2]   & "/" & $aPos1[3] & @crlf & _
    "Button ControlGetPos     (GUI   )  = " & $aPos0[0]  & "/"  & $aPos0[1]   & "/" & $aPos0[2]   & "/" & $aPos0[3] & @crlf & _
    @crlf & _
    "Button _ControlGetPosEx (Child2) = " & $aPosEx2[0] & "/" & $aPosEx2[1] & "/" & $aPosEx2[2] & "/" & $aPosEx2[3] & @crlf & _
    "Button _ControlGetPosEx (Child1) = " & $aPosEx1[0] & "/" & $aPosEx1[1] & "/" & $aPosEx1[2] & "/" & $aPosEx1[3] & @crlf & _
    "Button _ControlGetPosEx (GUI   ) = " & $aPosEx0[0] & "/" & $aPosEx0[1] & "/" & $aPosEx0[2] & "/" & $aPosEx0[3])

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

Func _ControlGetPosEx($hWnd, $sTxt, $hCtrl)
    If Not IsHWnd($hCtrl) Then $hCtrl = GUICtrlGetHandle($hCtrl)
    Local $hAncestor = _WinAPI_GetAncestor($hCtrl, $GA_ROOT)
    If $hAncestor = $hWnd Then
        Local $aRet = ControlGetPos($hWnd, $sTxt, $hCtrl)
    Else
        Local $aPos = WinGetPos($hCtrl, $sTxt)
        Local $tPoint = DllStructCreate("int X;int Y")
        DllStructSetData($tPoint, "X", $aPos[0])
        DllStructSetData($tPoint, "Y", $aPos[1])
        _WinAPI_ScreenToClient($hWnd, $tPoint)
        Local $aRet[4] = [$tPoint.X, $tPoint.Y, $aPos[2], $aPos[3]]
    EndIf
    Return $aRet
EndFunc   ;==>_ControlGetPosEx

 

_ControlGetPosEx.png.eef0c1871ba3ced546e7864e07c50c21.png

Edited by pixelsearch
typo

"I think you are searching a bug where there is no bug... don't listen to bad advice."

Posted

I understand the point but I thing That it is a bug

so I found the same solution inside ControlGetPos()

so I propose the following doc

Quote

###Function###
ControlGetPos

###Description###
Retrieves the position and size of a control relative to its window or control.

###Syntax###
ControlGetPos ( "title", "text", controlID )

###Parameters###
@@ParamTable@@
title
    The title/hWnd/class of the window or control to access. See <a href="../intro/windowsadvanced.htm">Title special definition</a>.
text
    The text of the window to access. See <a href="../intro/windowsbasic.htm#specialtext">Text special definition</a>.
controlID
    The control to interact with. See <a href="../intro/controls.htm">Controls</a>.
@@End@@

###ReturnValue###
@@ReturnTable@@
Success:    an array containing the size and the control's position relative to its client window or control:
        $aArray[0] = X position
        $aArray[1] = Y position
        $aArray[2] = Width
        $aArray[3] = Height
Failure:    sets the @error flag to 1.
@@End@@

###Remarks###
The title/text is referencing the parent window, so be careful with "", which references the active window which may not be the one containing the controlID control.

###Related###
ControlCommand, ControlMove

###Example###
@@IncludeExample@@

 

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
×
×
  • Create New...