Jump to content

Leaderboard

Popular Content

Showing content with the highest reputation on 02/16/2023 in all areas

  1. _WinAPI_SetCurrentProcessExplicitAppUserModelID() will fix that
    4 points
  2. On my Windows 10 system with AutoIt 3.3.16.1 installed, if I have the system taskbar setting 'Combine taskbar buttons' set to 'Always, hide labels', I get the generic AutoIt icon in the taskbar when running an uncompiled script. But if I change that setting to 'Never' or 'When taskbar is full', I see the custom icon.
    2 points
  3. Version v2.2.0

    1,417 downloads

    Encryption / Decryption / Hashing / Signing Purpose Cryptography API: Next Generation (CNG) is Microsoft's long-term replacement for their CryptoAPI. Microsoft's CNG is designed to be extensible at many levels and cryptography agnostic in behavior. Although the Crypt.au3 UDF lib that is installed with AutoIt3 still works well, the advapi32.dll functions that it uses have been deprecated. In addition the Crypt.au3 UDF lib, as it is currently written, has a very limited ability to decrypt AES data that was not encrypted using Crypt.au3 functions. That is because Crypt.au3 functions do not allow you to specify an actual key or initialization vector (IV). It only lets you specify data to be used to derive a key and uses a static IV. This UDF was created to offer a replacement for the deprecated functions used by Crypt.au3. According to Microsoft, deprecated functions may be removed in future release. It was also created to allow more flexibility and functionality in encryption/decryption/hashing/signing and to expand the ability for users to implement cryptography in their scripts. Description This UDF implements some of Microsoft's Cryptography API: Next Generation (CNG) Win32 API functions. It implements functions to encrypt/decrypt text and files, generate hashes, derive keys using Password-Based Key Derivation Function 2 (PBKDF2), create and verify signatures, and has several cryptography-related helper functions. The UDF can implement any encryption/decryption algorithms and hashing algorithms that are supported by the installed cryptography providers on the PC in which it is running. Most, if not all, of the "magic number" values that you would commonly use to specify that desired algorithms, key bit lengths, and other magic number type values, are already defined as constants or enums in the UDF file. To flatten the learning curve, there is an example file that shows examples of all of the major functionality. This example file is not created to be an exhaustive set of how to implement each feature and parameter. It is designed to give you a template or guide to help you hit the ground running in terms of using the functions. I have tried to fully document the headers of all of the functions as well as the code within the functions themselves. As of v1.4.0, there is also a Help file that includes all of the functions, with examples. Current UDF Functions Algorithm-Specific Symmetric Encryption/Decryption Functions _CryptoNG_AES_CBC_EncryptData _CryptoNG_AES_CBC_DecryptData _CryptoNG_AES_CBC_EncryptFile _CryptoNG_AES_CBC_DecryptFile _CryptoNG_AES_ECB_EncryptData _CryptoNG_AES_ECB_DecryptData _CryptoNG_AES_GCM_EncryptData _CryptoNG_AES_GCM_DecryptData _CryptoNG_3DES_CBC_EncryptData _CryptoNG_3DES_CBC_DecryptData _CryptoNG_3DES_CBC_EncryptFile _CryptoNG_3DES_CBC_DecryptFile Generic Symmetric Encryption/Decryption Functions _CryptoNG_EncryptData _CryptoNG_DecryptData _CryptoNG_EncryptFile _CryptoNG_DecryptFile Hashing Functions _CryptoNG_HashData _CryptoNG_HashFile _CryptoNG_PBKDF2 Asymmetric (Public/Private Key) Cryptography Functions _CryptoNG_ECDSA_CreateKeyPair _CryptoNG_ECDSA_SignHash _CryptoNG_ECDSA_VerifySignature _CryptoNG_RSA_CreateKeyPair _CryptoNG_RSA_EncryptData _CryptoNG_RSA_DecryptData _CryptoNG_RSA_SignHash _CryptoNG_RSA_VerifySignature Misc / Helper Functions _CryptoNG_CryptBinaryToString _CryptoNG_CryptStringToBinary _CryptoNG_GenerateRandom _CryptoNG_EnumAlgorithms _CryptoNG_EnumRegisteredProviders _CryptoNG_EnumKeyStorageProviders _CryptoNG_LastErrorMessage _CryptoNG_Version Related Links Cryptography API: Next Generation - Main Page Cryptography API: Next Generation - Reference Cryptography API: Next Generation - Primitives Cryptography API: Next Generation - Cryptographic Algorithm Providers
    1 point
  4. I don't know, Dan. I have to check this. But you knows best I guess 😅 . Best regards Sven Update @Danp2: Not exactly but essentially the same, yes. Case 'hide' $iActionType = 2 $sJavaScript = "arguments[0].style='display: none'; return true;"
    1 point
  5. Here's my modification of your example: Run('Notepad.exe') Sleep(1000) NotePad("[CLASS:Notepad]") Func NotePad($sTitle = '[CLASS:Notepad]') Local $hWnd = WinGetHandle($sTitle) ConsoleWrite('$hWnd: ' & $hWnd & ', ' & VarGetType($hWnd) & @CRLF) If WinExists($hWnd) = 1 Then WinActivate($hWnd) If WinWaitActive($hWnd, 3) = 0 Then MsgBox($MB_SYSTEMMODAL + $MB_ICONERROR, "Error", 'Window exists but failed to activate') Return SetError(1, 0, False) EndIf ;start Timer Local $h_TimeStamp = TimerInit(), $h_TooltipTimestamp = TimerInit() Local $i_TimeToCountDownFromSeconds = 30 ;~ Local $i_OriginalSeconds = $i_TimeToCountDownFromSeconds While TimerDiff($h_TimeStamp) <= $i_TimeToCountDownFromSeconds * 1000 If WinExists($hWnd) = 0 Then MsgBox($MB_SYSTEMMODAL + $MB_ICONERROR, "Error", _ "Window closed early, " & $i_TimeToCountDownFromSeconds - Round(TimerDiff($h_TooltipTimestamp), 0) & 's remaining') Return ; Not sure if you want to return true or false in this condition EndIf If TimerDiff($i_TimeToCountDownFromSeconds) >= 1000 Then ToolTip('Time remaining: ' & $i_TimeToCountDownFromSeconds - Round(TimerDiff($h_TimeStamp) / 1000, 0) & 's') $h_TooltipTimestamp = TimerInit() ;~ If $i_TimeToCountDownFromSeconds = 0 Then ExitLoop ;~ $i_TimeToCountDownFromSeconds -= 1 EndIf Sleep(10) WEnd MsgBox(0, "Done!", "Done counting down from " & $i_TimeToCountDownFromSeconds & ".") ; Close the window if it's still open If WinExists($hWnd) Then SetExtended(1) ; Set @extended to note that the window was still open at the end of the timer Local $hCloseTimer = TimerInit() While WinExists($hWnd) And TimerDiff($hCloseTimer) <= 5 WinClose($hWnd, "") ; Try to close the window gracefully WEnd WinKill($hWnd) ; Force the window to close, process close would also work if you got the ProcessID EndIf Return SetError(0, 0, True) ; Return success Else MsgBox($MB_SYSTEMMODAL + $MB_ICONERROR, "Error", "Window does not exist") EndIf Return SetError(2, 0, False) ; Return failure EndFunc ;==>NotePad
    1 point
  6. I love any and all approaches. I appreciate you. I'm having fun learning AutoIT. Struggling still, but learn more everyday! I will keep your code in my pocket of tools as well.
    1 point
  7. Hi @GeekGirl, this is a different approach which seems to be more easy in my opinion: #AutoIt3Wrapper_AU3Check_Parameters=-d -w 1 -w 2 -w 3 -w 4 -w 5 -w 6 -w 7 #AutoIt3Wrapper_AU3Check_Stop_OnWarning=y #AutoIt3Wrapper_Run_Au3Stripper=y #AutoIt3Wrapper_UseUpx=n #Au3Stripper_Parameters=/sf /sv /mo /rm /rsln _WaitForNotepad() _WaitThirtySeconds() _CloseNotepad() Func _WaitForNotepad() Local Const $sNotepad = '[CLASS:Notepad]' While Not WinExists($sNotepad) Sleep(100) WEnd Return EndFunc Func _WaitThirtySeconds() Local Const $hTimer = TimerInit() Local Const $iTimeoutInSeconds = 30 While TimerDiff($hTimer) < ($iTimeoutInSeconds * 1000) Sleep(500) WEnd EndFunc Func _CloseNotepad() Local Const $sNotepad = '[CLASS:Notepad]' Local Const $sNotepadProcess = 'notepad.exe' If Not WinExists($sNotepad) Then Return EndIf ProcessClose($sNotepadProcess) MsgBox(48, 'Demo', 'You reached the time limit.') EndFunc At the end it does not matter which variant you use, but I hope this helps you to understand another approach 🤞 . Best regards Sven
    1 point
  8. #include <MsgBoxConstants.au3> NotePad() Func NotePad() If Not WinExists("[CLASS:Notepad]") Then Run("Notepad") EndIf Local $Npad = WinWaitActive("[CLASS:Notepad]") ConsoleWrite("Start NotePad timer" & @CRLF) ;start Timer Local $i_TimeStamp = TimerInit() Local $i_TimeToCountDownFromSeconds = 30 Local $i_OriginalSeconds = $i_TimeToCountDownFromSeconds While WinExists($Npad) If TimerDiff($i_TimeStamp) >= 1000 Then ToolTip($i_TimeToCountDownFromSeconds) $i_TimeStamp = TimerInit() If $i_TimeToCountDownFromSeconds = 0 Then ExitLoop $i_TimeToCountDownFromSeconds -= 1 EndIf Sleep(10) WEnd ConsoleWrite("NotePad exit" & @CRLF) If WinExists($Npad) Then WinClose($Npad, "") If WinExists("[TITLE:Notepad; CLASS:#32770]", "&Save") Then Send("!n") EndIf EndIf EndFunc ;==>NotePad
    1 point
  9. https://en.wikipedia.org/wiki/Logical_conjunction $hTimer = TimerInit() While BitAND(WinExists("[CLASS:Notepad]"), TimerDiff($hTimer) < 30000) ;This loop will exit after 30 sec or if you close notepad window earlier Sleep(10) WEnd
    1 point
  10. no need to apologize They are simply easier to read and thus you get faster answers put Send("n") after WinClose("[CLASS:Notepad]", "")
    1 point
  11. AutoIt can find any top-level window. No need to search from desktop. Just use method ElementFromHandle. This method can be used for any controls that have a native handle (found by AutoIt). #AutoIt3Wrapper_UseX64=y Global $_UIA_SMART_AUTOMATION #include <GUIConstantsEx.au3> #include "UIA_Constants.au3" Example() Func Example() Local $hGUI = GUICreate("UIA HWND Example") Local $idOK = GUICtrlCreateButton("OK", 310, 370, 85, 25) GUISetState(@SW_SHOW, $hGUI) ; --------------------------------- ; main window $hWnd = WinWait("UIA HWND Example") _Log("! hWnd = " & $hWnd) $oWindow = _UIASimple_ElementFromHandle($hWnd) Local $hWnd2, $s_Title2 $oWindow.GetCurrentPropertyValue($UIA_NativeWindowHandlePropertyId, $hWnd2) $oWindow.GetCurrentPropertyValue($UIA_NamePropertyId, $s_Title2) _Log("! hWnd2 = 0x" & Hex($hWnd2) & ", $s_Title2 = " & $s_Title2) _Log("----------------") ; button OK $hCtrl = ControlGetHandle("UIA HWND Example", "", "Button1") _Log("! hCtrl = " & $hCtrl) $oBtn = _UIASimple_ElementFromHandle($hCtrl) Local $hCtrl2, $sText $oBtn.GetCurrentPropertyValue($UIA_NativeWindowHandlePropertyId, $hCtrl2) $oBtn.GetCurrentPropertyValue($UIA_NamePropertyId, $sText) _Log("! hCtrl2 = 0x" & Hex($hCtrl2) & ", $sText = " & $sText) ; --------------------------------- While 1 Switch GUIGetMsg() Case $GUI_EVENT_CLOSE, $idOK ExitLoop EndSwitch WEnd GUIDelete($hGUI) EndFunc ;==>Example Func _UIASimple_ElementFromHandle($hHandle) If Not IsHWnd($hHandle) Then Return SetError(1, 0, 0) Local $pElement, $oElement, $oUIA = _UIASimple_InitAutomation() $oUIA.ElementFromHandle($hHandle, $pElement) $oElement = ObjCreateInterface($pElement, $sIID_IUIAutomationElement, $dtag_IUIAutomationElement) $pElement = 0 If Not IsObj($oElement) Then Return SetError(2, 0, 0) Return $oElement EndFunc ;==>_UIASimple_ElementFromHandle Func _UIASimple_InitAutomation() If IsObj($_UIA_SMART_AUTOMATION) Then Return $_UIA_SMART_AUTOMATION Local $oUIA = ObjCreateInterface($sCLSID_CUIAutomation, $sIID_IUIAutomation, $dtag_IUIAutomation) If Not IsObj($oUIA) Then Return _Log(@ScriptLineNumber & " $oUIA ERR") $_UIA_SMART_AUTOMATION = $oUIA Return $_UIA_SMART_AUTOMATION EndFunc ;==>_UIASimple_InitAutomation Func _Log($sData, $iERR = @error, $iEXT = @extended) ConsoleWrite($sData & @CRLF) Return SetError($iERR, $iEXT) EndFunc ;==>_Log
    1 point
  12. ;~ Local $hWnd2 ;~ $hWnd2 = $oWindow.GetCurrentPropertyValue($UIA_NativeWindowHandlePropertyId, False) ;~ Local $s_Title2 = $oWindow.GetCurrentPropertyValue($UIA_NamePropertyId, True) Local $hWnd2, $s_Title2 $oWindow.GetCurrentPropertyValue($UIA_NativeWindowHandlePropertyId, $hWnd2) $oWindow.GetCurrentPropertyValue($UIA_NamePropertyId, $s_Title2)
    1 point
  13. You do it this way. tst00.cmd: start "CmdIdentifierString" /wait tst00.exe tst00.au3: #AutoIt3Wrapper_Change2CUI=Y ;#RequireAdmin ; Maybe you need #RequireAdmin rights? ; Maybe exclude exe/folder from antivirus program? DllCall( "Kernel32.dll", "int", "AttachConsole", "dword", WinGetProcess( "CmdIdentifierString" ) ) Func CmdConsoleWrite( $sStr ) DllCall( "Kernel32.dll", "bool", "WriteConsoleW", "handle", _ DllCall( "Kernel32.dll", "handle", "GetStdHandle", "int", -11 )[0], _ ; -11 = STD_OUTPUT_HANDLE "wstr", $sStr, "dword", StringLen( $sStr ), "dword*", 0, "ptr", 0 ) EndFunc CmdConsoleWrite( @CRLF ) For $i = 1 To 5 CmdConsoleWrite( "This is test number " & $i & @CRLF ) If $i < 5 Then Sleep( 3000 ) Next Exit Run tst00.cmd in a Command Prompt or double-click. Tested on Windows 7 as 32/64 bit code.
    1 point
  14. I will try GuiBuilderPlus by kurtykurtyboy as an update to GUIBuilder. A new an improved version with more to come.
    1 point
  15. @mistersquirrle Local $hTimer in the main script of the body, would be the same as declaring it as a global variable. So while you could use local, imho, it is better to have the scope declared correctly.
    1 point
  16. Thanks for the idea (and your encouragements) A button to generate the whole code would be nice (copying it to ClipBoard) We'll have to think about what to do if the "Replace Pattern" Tab is filled (and then maybe the "Replace count" field too). In this case, a StringRegExpReplace() function should be generated and not a StringRegExp() and its _ArrayDisplay() function etc... I'll think of it when I got some free time (this week being busy)
    1 point
  17. Like Trong said, you're using the variables incorrectly, however you don't need to use Global variables. Local $hTimer in the main script body is fine, your issue was that you were redeclaring the variable in the function scope, which for that function was overriding/ignoring the script local variable. Check out this page: https://www.autoitscript.com/wiki/Best_coding_practices And this one about scope: https://www.autoitscript.com/wiki/Variables_-_using_Global,_Local,_Static_and_ByRef But a quick note about scope: Global - When declared anywhere, it's available to this script and any included files. It's not recommended to declare Globals in functions, as they won't exist until the function runs. Local - When used in a function, it is only available to that function while it's running. Once the function ends, it's no longer available and its values are gone. Declaring a variable here will use that version inside of an already existing variable under that name. Local Static - This can be used in a function to keep the variable and its value between function calls. Normally variables are deleted when a function ends. With a Static variable, it's kept between each call, so it can referenced or changed and persist. Also a quick note about your script: While 1 WEnd This ^ is a bad idea, it'll cause your CPU to be at 100% constantly (though just on one core, since AutoIt is single threaded). As in Trongs example, add a sleep to your loop. Note that the minimum value for Sleep is actually 10, so using 1-9 are = 10: https://www.autoitscript.com/autoit3/docs/functions/Sleep.htm
    1 point
  18. You are wrong to use local variables. Just set it as the global variable the script will fix: HotKeySet('q', '_Exit') HotKeySet('o', 'StartTimer') HotKeySet('p', 'EndTimer') Global $hTimer=0 Func StartTimer() ConsoleWrite ('> TimerInit !' & @CRLF) $hTimer = TimerInit() EndFunc Func EndTimer() Local $fDiff = TimerDiff($hTimer) ConsoleWrite ('- TimerDiff: ' & $fDiff & @CRLF) EndFunc Func _Exit() ConsoleWrite ('! Exit !' & @CRLF) Exit EndFunc While 1 Sleep(1) WEnd
    1 point
  19. UI Automation code and application code simply must not be mixed together in the same executable code. Never ever use UI Automation code to automate an AutoIt application. Apparently the UI Automation code has a very negative impact on the AutoIt code. It can be seen, for example, through very poor UIASpy performance when UIASpy is used on an AutoIt application. If you want to compare AutoIt automation code and UI Automation code, use Notepad as the target application. If you want to automate an AutoIt application it's much much better to use AutoIt code.
    1 point
  20. Latest update just released. See below for change log.
    1 point
  21. You should try _WD_SetElementValue with $_WD_OPTION_Advanced. If you still can't get it to work, then I suggest that you find a website that we can all access for testing. Hint: Try Googling "ngbdatepicker"
    1 point
  22. See _WD_ElementAction and _WD_SetElementValue functions in the help file. There should be examples of usage in wd_demo,
    1 point
  23. Try this instead -- $sElementSelector = "/html/body/app-root/div/div/app-consumption/div[3]/div[2]/div[11]/div[2]/div/table" ; Table $aResult = _WD_GetTable($sSession, $sElementSelector) _ArrayDisplay($aResult) Exit
    1 point
  24. Just a hint @Blaxxun, you will also find help regarding WebDriver in the german forum. In case you're feeling more comfortable in your native language (mal abgesehen vom "Schwitzerdütsch" 😅). Out of your english sentences and grammar behavior, I guess it does not matter to you, but I just want to mention it 🤝 . Besides that you're in good hands (@Danp2, @mLipok and other great guys here) regarding WebDriver. Best regards Sven
    1 point
  25. @BlaxxunHere's a modified version of the GDPR fines example that should work once adjusted for your environment -- ; #AutoIt3Wrapper_Au3Check_Parameters=-q -d -w 1 -w 2 -w 3 -w 4 -w 5 -w 6 -w 7 #include "wd_core.au3" #include "wd_helper.au3" #include "_HtmlTable2Array.au3" ; <== This can be commented out, but the table extraction will be much slower Global $sDesiredCapabilities, $sSession, $sScriptName = "GDPR fines", $aResult_All $_WD_DEBUG = $_WD_DEBUG_Error ; Set debug level: $_WD_DEBUG_None (0) = No logging to console, $_WD_DEBUG_Error (1) = Error logging to console, $_WD_DEBUG_Info (2) = Full logging to console (Default) Global $hSplash = SplashTextOn($sScriptName, "Running ... please be patient!", Default, 45, 0, 0) ; (1, 2) ---------------------------------------------------------------------- ; Automate the website using FireFox. Start FF from a different location ; ----------------------------------------------------------------------------- Global $sDriver = "geckodriver.exe" ; <== Please modify this statement to your environment. Must be a local drive, network drives don't work! ; Setup Firefox _WD_Option("Driver", $sDriver) If @error Then Exit SetError(1, @error) _WD_Option('DriverParams', '--log trace') _WD_Option('Port', 4444) $sDesiredCapabilities = '{"desiredCapabilities":{"javascriptEnabled":true,"nativeEvents":true,"acceptInsecureCerts":true}}' ; (1, 2) End ------------------------------------------------------------------ _WD_Startup() If @error Then Exit SetError(2, @error) $sSession = _WD_CreateSession($sDesiredCapabilities) If @error Then Exit SetError(3, @error) ; (3) ------------------------------------------------------------------------- ; Maximize browser window ; ----------------------------------------------------------------------------- _WD_Window($sSession, "Maximize") If @error Then Exit SetError(4, @error) ; (3) End --------------------------------------------------------------------- RetrieveTable($aResult_All) If @error Then Exit SetError(5, @error) ControlSetText($hSplash, "", "Static1", "Shutting down WebDriver automation") _WD_DeleteSession($sSession) If @error Then Exit SetError(6, @error) _WD_Shutdown() If @error Then Exit SetError(7, @error) SplashOff() _ArrayDisplay($aResult_All) MsgBox($MB_ICONINFORMATION, $sScriptName, "Finished!", 5) Exit Func RetrieveTable(ByRef $aResult_All) Local $aResult, $sElement, $iPage = 0, $sText, $aOptions ControlSetText($hSplash, "", "Static1", "Opening website www.enforcementtracker.com") ; Open website _WD_Navigate($sSession, "http://www.enforcementtracker.com/") If @error Then Return SetError(@error) ; (4) --------------------------------------------------------------------- ; Retrieve the values from the selection list and use the second to last (50) ; ------------------------------------------------------------------------- $sElement = _WD_WaitElement($sSession, $_WD_LOCATOR_ByXPath, "//select[@name='penalties_length']") $aOptions = _WD_ElementSelectAction($sSession, $sElement, 'options') _WD_ElementOptionSelect($sSession, $_WD_LOCATOR_ByXPath, "//select[@name='penalties_length']//option[contains(text(),'" & $aOptions[UBound($aOptions, 1) - 2][0] & "')]") If @error Then Return SetError(@error) ; (4) End ----------------------------------------------------------------- ; Wait for initial appearance of navigation button _WD_WaitElement($sSession, $_WD_LOCATOR_ByXPath, "//a[@class='paginate_button next']") ; (5) --------------------------------------------------------------------- ; Sort table by fine (descending) ; ------------------------------------------------------------------------- $sElement = _WD_FindElement($sSession, $_WD_LOCATOR_ByXPath, "//th[contains(text(),'Fine [')]") ; Find "Fine" header of the table _WD_ElementAction($sSession, $sElement, "click") ; Click twice to sort descending _WD_ElementAction($sSession, $sElement, "click") ; (5) End ----------------------------------------------------------------- While 1 $iPage = $iPage + 1 ControlSetText($hSplash, "", "Static1", "Loading data from website - page " & $iPage) $aResult = _WD_GetTable($sSession, "//table[@id='penalties']") If @error Then Return SetError(@error) If $iPage = 1 Then $aResult_All = $aResult Else _ArrayConcatenate($aResult_All, $aResult, 2) EndIf ; (6, 7) -------------------------------------------------------------- ; Find the "next" button. If found scroll down so the button comes into ; view and click the button. Else exit the function ; --------------------------------------------------------------------- $sElement = _WD_FindElement($sSession, $_WD_LOCATOR_ByXPath, "//a[@class='paginate_button next']") ; Find "Next" button If @error Then ExitLoop _WD_ExecuteScript($sSession, "arguments[0].scrollIntoView(true);", '{"' & $_WD_ELEMENT_ID & '":"' & $sElement & '"}') ; Scroll down to the link If @error Then Return SetError(@error) Else _WD_ElementAction($sSession, $sElement, "click") ; Click on the "Next" button EndIf ; (6, 7) End ---------------------------------------------------------- WEnd EndFunc ;==>RetrieveTable
    1 point
  26. The GDPR fines.au3 was written long time ago. The WebDriver UDF didn't have a _wd_gettable function at that time. Now it has, but I didn't have the time to update the GDPR example script. I suggest to not modify the WebDriver UDF as it constantly gets enhanced. Drop my _WD_GetTable and use the one provided with the WebDriver UDF.
    1 point
  27. Can you post the specific commands you've tried with parameters? Without having access to the window or being able to recreate the situation, it's difficult to provide much help.
    1 point
  28. Confuzzled

    New line in Msgbox

    Cutted and posted directly from the help file: @CR Carriage return, Chr(13); sometimes used for line breaks. @LF Line feed, Chr(10); typically used for line breaks. @CRLF = @CR & @LF ;occasionally used for line breaks. So your code would be Msgbox (0, "title", "text on first line" & @LF & " text on second line")
    1 point
×
×
  • Create New...