Leaderboard
Popular Content
Showing content with the highest reputation since 11/03/2025 in all areas
-
AutoIt Extension for Visual Studio Code
SOLVE-SMART and 5 others reacted to LoganCH for a topic
Released v1.3.0! Added COM object syntax highlighting for properties and methods using dot notation Distinct token scopes for COM identifiers (support.class.com.autoit) to enable theme-specific styling Contributors section to README.md with auto-updating contrib.rocks integration Added missing AutoIt macros: @exitMethod, @GUI_DropId, and @SW_ENABLE to completions and hovers AU3Check parameter parsing support with corresponding tests to improve syntax check behavior Parameter validation and improved status messages in OutputChannelManager (#230) WinNet API completions added to IntelliSense Fixed Function pattern incorrectly matching COM object methods (e.g., $obj.Method() now correctly identified as COM, not function) Incorrect documentation for @GUI_CtrlId macro (now correctly states "Last click GUI Control identifier" instead of "Drag GUI Control identifier") Duplicate WinNet signature removed and WinAPI COM signatures added to signature/hover data Incorrect CRLF constant definition corrected Duplicate parameter documentation entries removed in signature help provider Removed stray duplicate (misspelled) Clibpoard completion entry Improved parameter checks in runCheckProcess for more reliable regex matching Changed Consolidated macro data into single source of truth (src/completions/macrosData.js) to eliminate duplication and ensure consistency between completions and hovers Converted src/hovers/macros.json to src/hovers/macros.js to import from unified macro data source Rate and View on VS Code Marketplace Rate and View on OpenVSX Star & Submit Issues on GitHub6 points -
Control Splitter - window Splitters for controls
ioa747 and 2 others reacted to musicstashall for a topic
I present to your attention an alternative version of the window dividers CtrlSplitter. The Static element is used as a splitter separator, and the functioning of the separators is fully implemented in their window procedure. Example.au3 CtrlSplitNotify.au3 CtrlSplit.au3 ApiDPI.au33 points -
AutoIt Snippets
CYCho and 2 others reacted to argumentum for a topic
How do you translate "Desktop" to the user's language ? #include <WinAPIRes.au3> Exit ConsoleWrite(@CRLF & '>' & _LoadString_shell32(4162) & '<' & @CRLF & @CRLF) Func _LoadString_shell32($iID) ; 4162 = "Desktop" Local $sText = "", $hInstance = _WinAPI_LoadLibraryEx("shell32.dll", $LOAD_LIBRARY_AS_DATAFILE) If $hInstance Then $sText = _WinAPI_LoadString($hInstance, $iID) _WinAPI_FreeLibrary($hInstance) EndIf Return SetError(@error, @extended, $sText) EndFunc ;==>_LoadString_shell32 If your GUI is simple, you may just find all the strings you use in shell32.dll3 points -
I was before retiring in Basic software development as Windows Core So I can tell you that the solution comes with generating an assembly code based on a run time implementing the AutoIt builtin functions That need to defined something as as C compiler, that's a tremending job at least for me Today Autoit is based on a interpreting byte code corresponding to AutoIt builtin functions which is not too bad from my point of view Cheers3 points
-
Guiscape -- A new GUI builder project!
n3wbie and 2 others reacted to jaberwacky for a topic
Hello! I'm working on a new GUI builder that I have been making great progress on! A helpful forum member ioa747 answered a question I had which started me on my journey, and now I'd like to present to you an alpha version of the software. As of now only Form and Button works in a rudimentary fashion. To run this, open Guiscape.au3 and go from there! I'd love to hear your feedback and suggestions. 🙂 Latest versions will be on Github from now on. https://github.com/matthewrg/Guiscape/archive/refs/heads/main.zip Downloads: 873 points -
Guiscape -- A new GUI builder project!
ioa747 and 2 others reacted to jaberwacky for a topic
Hello! Just letting everyone know that I'm still hard at work on this. Decided to make some major changes to the structure once again. Now I can continue to lay out the GUI. Now it is based on an event queue. Any time an action is performed or information is requested, the object pushes it to a queue which announces to other objects that have subscribed to the queue. I'm hoping this will allow me to implement an undo/redo!3 points -
Walking a .json ( and failing )
ioa747 and 2 others reacted to AspirinJunkie for a topic
Wow, that looks wild. To be honest, I haven't delved deep enough into your script to really understand how the path strings for _JSON_Get() are constructed there. As I understand it, you want to map this highly hierarchical structure to a 2D array—is that correct? From my point of view, neither manual fixed loops nor the use of _JSON_Get() are the ideal way to do this. Instead of manual nested loops, the format here literally cries out for recursion. And since _JSON_Get starts from the beginning again with each call and you can quickly get confused with the path string, you don't really need it here. You have the structure available as AutoIt data structures. So you can also process it directly to access it – you don't need _JSON_Get() for that. That is more for conveniently accessing certain values whose path you know in advance. On the other hand, first putting together a path and then using _JSON_Get to retrieve the element is artificially cumbersome, since you basically already have the element when you put the path together. So I simply implemented the whole thing recursively, and from my point of view, it seems to make sense: #include <JSON.au3> #include <Array.au3> ; extract array of devices from the json structure Global $aDevices = _extractDevices(_JSON_Parse(FileRead('Argumentum.json'))) ; display the result _ArrayDisplay($aDevices, "Devices", "", 64, "|", "Index|JSON-Path|ID|Text|Min|Value|Max|SensorID|Type|ImageURL") Func _extractDevices($mDevice, $bMaster = True, $sIndex = 0) Local Static $aDevices[0][0], $iElements Local Enum $eIdx, $ePath, $eID, $eText, $eMin, $eValue, $eMax, $eSensorID, $eType, $eImg ; check Input validity If Not IsMap($mDevice) Then Return SetError(1, 0, Null) ; first recursion level has to initialize things If $bMaster Then Redim $aDevices[8][$eImg + 1] $iElements = 0 EndIf ; add current device to result array If UBound($aDevices) <= $iElements Then Redim $aDevices[UBound($aDevices) * 2][$eImg + 1] ; resize array if necessary $aDevices[$iElements][$eIdx] = $sIndex $aDevices[$iElements][$ePath] = StringReplace(StringRegExpReplace(StringTrimLeft($sIndex, 2), "(\d+)", 'Children[$1]'), ',', '.') $aDevices[$iElements][$eID] = $mDevice["id"] $aDevices[$iElements][$eText] = $mDevice["Text"] $aDevices[$iElements][$eMin] = $mDevice["Min"] $aDevices[$iElements][$eValue] = $mDevice["Value"] $aDevices[$iElements][$eMax] = $mDevice["Max"] $aDevices[$iElements][$eSensorID] = $mDevice["SensorId"] $aDevices[$iElements][$eType] = $mDevice["Type"] $aDevices[$iElements][$eImg] = $mDevice["ImageURL"] $iElements += 1 ; process the childrens Local $aChildren = $mDevice["Children"] If IsArray($aChildren) And UBound($aChildren, 1) > 0 And UBound($aChildren, 0) = 1 Then For $i = 0 To UBound($aChildren) - 1 _extractDevices($aChildren[$i], False, $sIndex & "," & $i) Next EndIf If $bMaster Then Redim $aDevices[$iElements][$eImg + 1] Return $aDevices EndIf EndFunc I am therefore unable to assess where the problem lies in your script or whether there may even be a bug in the JSON UDF. In my script, I have therefore generated the query string for _JSON_Get() for each element in parallel, and when I use these with _JSON_Get(), it works as desired. Yes, that was highly unprofessional of me - I agree with you there. To me, it seemed logical to adjust the function to return a null instead of an empty string in the event of an error, so I simply changed it without further ado. Of course, I completely ignored the fact that this was a script-breaking change and didn't even mention it in the commit message. That's really not acceptable - sorry! I have therefore rolled it back in the GitHub repo.3 points -
Added this UDF to the Wiki3 points
-
Round buttons
argumentum and 2 others reacted to MattyD for a topic
Perhaps a starting point with the ownerdrawn approach if you wanted to have a crack! take or leave it #include <GUIConstants.au3> #include <guibutton.au3> #include <WinAPIGdi.au3> #include <WinAPISysWin.au3> #include <WindowsSysColorConstants.au3> #include <WinAPIGdiDC.au3> #include <FrameConstants.au3> #include <SendMessage.au3> _WinAPI_SetUDFColorMode($UDF_RGB) ;So _WinAPI_RGB works as expected. ;By default the UDF swaps the colour values around - presumably so you can represent a RGB value with hex notation without endian issues. i.e. 0x00RRGGBB Global Const $ODT_MENU = 1 Global Const $ODT_LISTBOX = 2 Global Const $ODT_COMBOBOX = 3 Global Const $ODT_BUTTON = 4 Global Const $ODT_STATIC = 5 Global Const $ODA_DRAWENTIRE = 1 Global Const $ODA_FOCUS = 2 Global Const $ODA_SELECT = 4 Global Const $ODS_SELECTED = 0x0001 Global Const $ODS_GRAYED = 0x0002 Global Const $ODS_DISABLED = 0x0004 Global Const $ODS_CHECKED = 0x0008 Global Const $ODS_FOCUS = 0x0010 Global Const $ODS_DEFAULT = 0x0020 Global Const $ODS_COMBOBOXEDIT = 0x1000 Global Const $ODS_HOTLIGHT = 0x0040 Global Const $ODS_INACTIVE = 0x0080 Global Const $ODS_NOACCEL = 0x0100 Global Const $ODS_NOFOCUSRECT = 0x0200 Global $tagDRAWITEMSTRUCT = StringFormat("struct;uint ctlType;uint CtlID;uint itemID;uint itemAction;uint itemState;hwnd hwndItem;handle hDC;%s;ulong_ptr itemData;endstruct", $tagRect) Local $hGUI = GUICreate("", 200, 50) GUIRegisterMsg($WM_DRAWITEM, "WM_DRAWITEM") Local $hBtn = _GUICtrlButton_Create($hGUI, "test", 10, 10, 80, 25, $BS_OWNERDRAW) Local $idBtn2 = GUICtrlCreateButton("Disable", 100, 10, 80, 25) GUISetState() While 1 $iMsg = GUIGetMsg() Switch $iMsg Case $idBtn2 If BitAnd(WinGetState($hBtn), $WIN_STATE_ENABLED) Then WinSetState($hBtn, "", @SW_DISABLE) GUICtrlSetData($idBtn2, "Enable") Else WinSetState($hBtn, "", @SW_ENABLE) GUICtrlSetData($idBtn2, "Disable") EndIf Case $GUI_EVENT_CLOSE ExitLoop EndSwitch WEnd Func WM_DRAWITEM($hWnd, $iMsg, $wParam, $lParam) Local $tDRAWITEMSTRUCT = DllStructCreate($tagDRAWITEMSTRUCT, $lParam) Local $hDC = $tDRAWITEMSTRUCT.hDC Local $tWinRect = DllStructCreate($tagRect, DllStructGetPtr($tDRAWITEMSTRUCT, "Left")) Local $iTextLen = _SendMessage($tDRAWITEMSTRUCT.hwndItem, $WM_GETTEXTLENGTH) Local $tText = DllStructCreate(StringFormat("wchar text[%d]", $iTextLen + 1)) _SendMessage($tDRAWITEMSTRUCT.hwndItem, $WM_GETTEXT, DllStructGetSize($tText), $tText, 0, "wparam", "struct*") Local $iFaceCol = BitAND($tDRAWITEMSTRUCT.itemState, $ODS_DISABLED) ? _WinAPI_RGB(0xE0, 0xE0, 0xE0) : _WinAPI_RGB(0xE0, 0xE0, 0xFF) Switch $tDRAWITEMSTRUCT.ctlType Case $ODT_BUTTON If BitAND($tDRAWITEMSTRUCT.itemAction, $ODA_DRAWENTIRE) Then If BitAND($tDRAWITEMSTRUCT.itemState, $ODS_SELECTED) Then _WinAPI_DrawFrameControl($hDC, $tWinRect, $DFC_BUTTON, BitOR($DFCS_BUTTONPUSH, $DFCS_PUSHED)) $iFaceCol = _WinAPI_RGB(0xC0, 0xC0, 0xEF) Else _WinAPI_DrawFrameControl($hDC, $tWinRect, $DFC_BUTTON, $DFCS_BUTTONPUSH) EndIf _WinAPI_InflateRect($tWinRect, -3, -3) $hSelBrush = _WinAPI_CreateSolidBrush($iFaceCol) _WinAPI_SelectObject($hDC, $hSelBrush) _WinAPI_FillRect($hDC, $tWinRect, $hSelBrush) _WinAPI_DeleteObject($hSelBrush) _WinAPI_InflateRect($tWinRect, 3, 3) _WinAPI_SetBkColor($hDC, $iFaceCol) _WinAPI_DrawText($hDC, $tText.Text, $tWinRect, BitOR($DT_CENTER, $DT_VCENTER, $DT_SINGLELINE)) EndIf If BitAND($tDRAWITEMSTRUCT.itemState, $ODS_FOCUS) Then _WinAPI_InflateRect($tWinRect, -3, -3) $hSelBrush = _WinAPI_GetStockObject($HOLLOW_BRUSH) $hSelPen = _WinAPI_CreatePen($PS_DOT, 1, _WinAPI_RGB(0, 0xAA, 0xAA)) _WinAPI_SelectObject($hDC, $hSelPen) _WinAPI_SelectObject($hDC, $hSelBrush) _WinAPI_Rectangle($hDC, $tWinRect) _WinAPI_DeleteObject($hSelPen) _WinAPI_DeleteObject($hSelBrush) EndIf EndSwitch Return 1 EndFunc ;==>WM_DRAWITEM3 points -
A bit more progress with this subclassing stuff.. Multiselect with shift key down, and some very rough alignment code. ;~ #AutoIt3Wrapper_UseX64=N ;TODO: snap always rounds down, so you can't drag all the way right/bottom if you run out of window. ;Need to change the tipping point to 1/2 way between points. #include <WindowsSysColorConstants.au3> #include <guiConstants.au3> #include <winapi.au3> #include <guiButton.au3> #include <guiEdit.au3> #include <WinAPIvkeysConstants.au3> #include <BorderConstants.au3> Global Const $tagMINMAXINFO = "long Reserved[2]; long MaxSize[2]; long MaxPosition[2]; long MinTrackSize[2]; long MaxTrackSize[2]" Global Const $MK_LBUTTON = 0x0001 Global Const $MK_RBUTTON = 0x0002 Global Const $MK_SHIFT = 0x0004 Global Const $MK_CONTROL = 0x0008 Global Const $MK_MBUTTON = 0x0010 Global Const $MK_XBUTTON1 = 0x0020 Global Const $MK_XBUTTON2 = 0x0040 Global $iSnap = 15, $iMinCtrlW = 15, $iMinCtrlH = 15 Global $mh_SelCtrls[] Global $hCursor_Cross = _WinAPI_LoadCursor(0, $IDC_CROSS) Global $hGui = GUICreate("", 300, 200, 100, 100, BitOR($WS_SIZEBOX, $WS_MINIMIZEBOX)) GUISetState() Global $hGui2 = GUICreate("", 200, 300, 450, 100) Global $idAlignTop = GUICtrlCreateButton("Align Top", 100, 10, 80, 25) Global $idButton = GUICtrlCreateRadio("Button", 10, 10, 80, 25) GUICtrlSetState(-1, $GUI_CHECKED) Global $idCheck = GUICtrlCreateRadio("Checkbox", 10, 40, 80, 25) Global $idRadio = GUICtrlCreateRadio("Radio", 10, 70, 80, 25) Global $idEdit = GUICtrlCreateRadio("Edit", 10, 100, 80, 25) Global $idInput = GUICtrlCreateRadio("Input", 10, 130, 80, 25) ;~ Global $idList = GUICtrlCreateRadio("List", 10, 160, 80, 25) Global $hCtrlProc = DllCallbackRegister("CtrlProc", "lresult", "hwnd;uint;wparam;lparam;uint_ptr;dword_ptr") Global $pCtrlProc = DllCallbackGetPtr($hCtrlProc) Global $hWndProc = DllCallbackRegister("WndProc", "lresult", "hwnd;uint;wparam;lparam;uint_ptr;dword_ptr") Global $pWndProc = DllCallbackGetPtr($hWndProc) _WinAPI_SetWindowSubclass($hGui, $pWndProc, 1000) GUISetState() Local $iMsg, $aKeys, $tWinPos, $tParPos, $iTop While WinExists($hGui) $iMsg = GUIGetMsg() Switch $iMsg Case $GUI_EVENT_CLOSE ExitLoop Case $idAlignTop $tParPos = _WinAPI_GetClientRect($hGui) $iTop = $tParPos.Bottom $aKeys = MapKeys($mh_SelCtrls) For $hWnd In $aKeys If $mh_SelCtrls[$hWnd] Then $tWinPos = _WinAPI_GetWindowRect($hWnd) _WinAPI_ScreenToClient($hGUI, $tWinPos) If $tWinPos.Top < $iTop Then $iTop = $tWinPos.Top EndIf Next For $hWnd In $aKeys If $mh_SelCtrls[$hWnd] Then $tWinPos = _WinAPI_GetWindowRect($hWnd) _WinAPI_ScreenToClient($hGUI, $tWinPos) _WinAPI_ScreenToClient($hGUI, DllStructGetPtr($tWinPos, 3)) _WinAPI_MoveWindow($hWnd, $tWinPos.Left, $iTop, $tWinPos.Right - $tWinPos.Left, $tWinPos.Bottom - $tWinPos.Top) EndIf Next EndSwitch WEnd _WinAPI_RemoveWindowSubclass($hGui, $pWndProc, 1000) Func WndProc($hWnd, $iMsg, $wParam, $lParam, $iIdSubclass, $dwRefData) #forceref $hWnd, $iMsg, $wParam, $lParam, $iIdSubclass, $dwRefData Local $iRet Local Static $bDrawRect, $tPaintRect = DllStructCreate($tagRect) Switch $iMsg Case $WM_SETCURSOR Local $iSrc = _WinAPI_LoWord($lParam);, $iEvent = _WinAPI_HiWord($lParam) If $iSrc = $HTCLIENT Then _WinAPI_SetCursor($hCursor_Cross) $iRet = 1 Else $iRet = _WinAPI_DefSubclassProc($hWnd, $iMsg, $wParam, $lParam) EndIf Case $WM_LBUTTONDOWN Local $tPoint = _WinAPI_MakePoints($lParam) $tPaintRect.Left = $tPoint.X $tPaintRect.Top = $tPoint.Y $tPaintRect.Left -= Mod($tPaintRect.Left, $iSnap) $tPaintRect.Top -= Mod($tPaintRect.Top, $iSnap) $bDrawRect = True ;~ _WinAPI_TrackMouseEvent($hWnd, $TME_LEAVE) $iRet = _WinAPI_DefSubclassProc($hWnd, $iMsg, $wParam, $lParam) Case $WM_MOUSEMOVE Local $tPoint = _WinAPI_MakePoints($lParam) If BitAND($wParam, $MK_LBUTTON) = $MK_LBUTTON Then _WinAPI_InvalidateRect($hWnd, $tPaintRect, True) $tPaintRect.Right = $tPoint.X $tPaintRect.Bottom = $tPoint.Y $tPaintRect.Right -= Mod($tPaintRect.Right, $iSnap) $tPaintRect.Bottom -= Mod($tPaintRect.Bottom, $iSnap) _WinAPI_InvalidateRect($hWnd, $tPaintRect, True) $iRet = 0 Else If $bDrawRect Then _WinAPI_InvalidateRect($hWnd, $tPaintRect, True) $bDrawRect = False $iRet = _WinAPI_DefSubclassProc($hWnd, $iMsg, $wParam, $lParam) EndIf Case $WM_PAINT If $bDrawRect Then Local $tPaintStruct = $tagPAINTSTRUCT Local $hDC = _WinAPI_BeginPaint($hWnd, $tPaintStruct) Local $hPen = _WinAPI_CreatePen($PS_DOT, 1, _WinAPI_RGB(0, 0, 0)) Local $hBrush = _WinAPI_GetStockObject($WHITE_BRUSH) _WinAPI_SelectObject($hDC, $hPen) _WinAPI_SelectObject($hDC, $hBrush) _WinAPI_Rectangle($hDC, $tPaintRect) _WinAPI_DeleteObject($hPen) _WinAPI_DeleteObject($hBrush) _WinAPI_EndPaint($hWnd, $tPaintStruct) $iRet = 0 Else $iRet = _WinAPI_DefSubclassProc($hWnd, $iMsg, $wParam, $lParam) EndIf Case $WM_LBUTTONUP Local $tPoint = _WinAPI_MakePoints($lParam) If $bDrawRect Then $bDrawRect = False $tPaintRect.Right = $tPoint.X $tPaintRect.Bottom = $tPoint.Y $tPaintRect.Right -= Mod($tPaintRect.Right, $iSnap) $tPaintRect.Bottom -= Mod($tPaintRect.Bottom, $iSnap) _WinAPI_InvalidateRect($hWnd, $tPaintRect, True) If Abs($tPaintRect.Left - $tPaintRect.Right) >= $iMinCtrlW _ ;MinWidth & Height. And Abs($tPaintRect.Top - $tPaintRect.Bottom) >= $iMinCtrlH Then ;Yes, this can be done better - too lazy right now! Select Case GUICtrlRead($idButton) = $GUI_CHECKED ;Need border & clipsiblings to paint custom frame. using UDF for button to avoid any surprises in autoit's default btn proc Local $hCtrl = _GUICtrlButton_Create($hWnd, "", _ ($tPaintRect.Left < $tPaintRect.Right) ? $tPaintRect.Left : $tPaintRect.Right, _ ($tPaintRect.Top < $tPaintRect.Bottom) ? $tPaintRect.Top : $tPaintRect.Bottom, _ Abs($tPaintRect.Left - $tPaintRect.Right), _ Abs($tPaintRect.Top - $tPaintRect.Bottom), _ BitOR($BS_PUSHLIKE, $WS_BORDER, $WS_CLIPSIBLINGS)) _WinAPI_SetWindowSubclass($hCtrl, $pCtrlProc, _WinAPI_GetDlgCtrlID($hCtrl)) Case GUICtrlRead($idCheck) = $GUI_CHECKED Local $hCtrl = _GUICtrlButton_Create($hWnd, "Checkbox", _ ($tPaintRect.Left < $tPaintRect.Right) ? $tPaintRect.Left : $tPaintRect.Right, _ ($tPaintRect.Top < $tPaintRect.Bottom) ? $tPaintRect.Top : $tPaintRect.Bottom, _ Abs($tPaintRect.Left - $tPaintRect.Right), _ Abs($tPaintRect.Top - $tPaintRect.Bottom), _ BitOR($BS_AUTOCHECKBOX, $WS_BORDER, $WS_CLIPSIBLINGS)) _WinAPI_SetWindowSubclass($hCtrl, $pCtrlProc, _WinAPI_GetDlgCtrlID($hCtrl)) Case GUICtrlRead($idRadio) = $GUI_CHECKED Local $hCtrl = _GUICtrlButton_Create($hWnd, "Radio", _ ($tPaintRect.Left < $tPaintRect.Right) ? $tPaintRect.Left : $tPaintRect.Right, _ ($tPaintRect.Top < $tPaintRect.Bottom) ? $tPaintRect.Top : $tPaintRect.Bottom, _ Abs($tPaintRect.Left - $tPaintRect.Right), _ Abs($tPaintRect.Top - $tPaintRect.Bottom), _ BitOR($BS_AUTORADIOBUTTON, $WS_BORDER, $WS_CLIPSIBLINGS)) _WinAPI_SetWindowSubclass($hCtrl, $pCtrlProc, _WinAPI_GetDlgCtrlID($hCtrl)) Case GUICtrlRead($idEdit) = $GUI_CHECKED Local $hCtrl = _GUICtrlEdit_Create($hWnd, "", _ ($tPaintRect.Left < $tPaintRect.Right) ? $tPaintRect.Left : $tPaintRect.Right, _ ($tPaintRect.Top < $tPaintRect.Bottom) ? $tPaintRect.Top : $tPaintRect.Bottom, _ Abs($tPaintRect.Left - $tPaintRect.Right), _ Abs($tPaintRect.Top - $tPaintRect.Bottom), _ BitOR($ES_WANTRETURN, $WS_VSCROLL, $WS_HSCROLL, $ES_AUTOVSCROLL, $ES_AUTOHSCROLL, $WS_BORDER, $WS_CLIPSIBLINGS)) _WinAPI_SetWindowSubclass($hCtrl, $pCtrlProc, _WinAPI_GetDlgCtrlID($hCtrl)) Case GUICtrlRead($idInput) = $GUI_CHECKED Local $hCtrl = _GUICtrlEdit_Create($hWnd, "", _ ($tPaintRect.Left < $tPaintRect.Right) ? $tPaintRect.Left : $tPaintRect.Right, _ ($tPaintRect.Top < $tPaintRect.Bottom) ? $tPaintRect.Top : $tPaintRect.Bottom, _ Abs($tPaintRect.Left - $tPaintRect.Right), _ Abs($tPaintRect.Top - $tPaintRect.Bottom), _ BitOR($ES_LEFT, $ES_AUTOHSCROLL, $WS_BORDER, $WS_CLIPSIBLINGS)) _WinAPI_SetWindowSubclass($hCtrl, $pCtrlProc, _WinAPI_GetDlgCtrlID($hCtrl)) EndSelect EndIf EndIf $iRet = _WinAPI_DefSubclassProc($hWnd, $iMsg, $wParam, $lParam) Case $WM_SIZE ;This prevents autoit's docking logic from moving controls around on window restore. ;if we ony use the udf functions to create ctrls this is not needed. $iRet = _WinAPI_DefWindowProcW($hWnd, $iMsg, $wParam, $lParam) ;~ Case $WM_MOUSELEAVE ;TODO: trap mouse in window while left button is down. Case Else $iRet = _WinAPI_DefSubclassProc($hWnd, $iMsg, $wParam, $lParam) EndSwitch Return $iRet EndFunc ;==>WndProc Func CtrlProc($hWnd, $iMsg, $wParam, $lParam, $iIdSubclass, $dwRefData) Local $iRet Local Static $hHasFocus Switch $iMsg Case $WM_GETMINMAXINFO, $WM_SIZING, $WM_MOVING, $WM_SIZE, $WM_MOVE, $WM_EXITSIZEMOVE $iRet = _Ctrl_MoveSizeCtrlProc($hWnd, $iMsg, $wParam, $lParam) Case $WM_NCHITTEST $iRet = _Ctrl_MoveSizeCtrlProc($hWnd, $iMsg, $wParam, $lParam) Case $WM_SETCURSOR $iRet = _Ctrl_MoveSizeCtrlProc($hWnd, $iMsg, $wParam, $lParam) Case $WM_MOUSEACTIVATE ;"Selected" control logic. If Not BitAND(0x8000, _WinAPI_GetAsyncKeyState($VK_SHIFT)) Then Local $aKeys = MapKeys($mh_SelCtrls) For $i = 0 To UBound($aKeys) - 1 If $aKeys[$i] Then $mh_SelCtrls[$aKeys[$i]] = False _WinAPI_RedrawWindow($aKeys[$i], 0, 0, BitOR($RDW_FRAME, $RDW_INVALIDATE)) EndIf Next $mh_SelCtrls[$hWnd] = True Else $mh_SelCtrls[$hWnd] = MapExists($mh_SelCtrls, $hWnd) ? Not $mh_SelCtrls[$hWnd] : True EndIf ;NCL_LBUTTONDOWN doesn't retrigger if ctrl already has focus. If _WinAPI_GetFocus() = $hWnd Then _WinAPI_RedrawWindow($hWnd, 0, 0, BitOR($RDW_FRAME, $RDW_INVALIDATE)) $iRet = _WinAPI_DefSubclassProc($hWnd, $iMsg, $wParam, $lParam) Case $WM_NCLBUTTONDOWN $iRet = _WinAPI_DefSubclassProc($hWnd, $iMsg, $wParam, $lParam) If $mh_SelCtrls[$hWnd] Then _WinAPI_SetFocus($hWnd) Case $WM_SETFOCUS $hHasFocus = $hWnd _SendMessage($wParam, $WM_KILLFOCUS, $hWnd) $iRet = _WinAPI_DefSubclassProc($hWnd, $iMsg, $wParam, $lParam) _WinAPI_RedrawWindow($hWnd, 0, 0, BitOR($RDW_FRAME, $RDW_INVALIDATE)) Case $WM_KILLFOCUS _WinAPI_RedrawWindow($hWnd, 0, 0, BitOR($RDW_FRAME, $RDW_INVALIDATE)) $iRet = _WinAPI_DefSubclassProc($hWnd, $iMsg, $wParam, $lParam) Case $WM_NCLBUTTONDBLCLK ;Prevent double-click maximizing in "caption" - also now set caption. If $wParam = $HTCAPTION Then ;Set text If Not BitAND(0x8000, _WinAPI_GetAsyncKeyState($VK_SHIFT)) Then Local $iCaptionLen = _SendMessage($hWnd, $WM_GETTEXTLENGTH) Local $tCaption = DllStructCreate(StringFormat("wchar text[%d]", $iCaptionLen + 1)) _SendMessage($hWnd, $WM_GETTEXT, DllStructGetSize($tCaption), $tCaption, 0, "wparam", "struct*") Local $sCaption = InputBox("Edit Caption", " ", $tCaption.Text, "", 150, 60, BitAND($lParam, 0xFFFF), BitShift($lParam, 16)) If Not @error Then _SendMessage($hWnd, $WM_SETTEXT, 0, $sCaption, 0, "wparam", "wstr") EndIf Else $iRet = _WinAPI_DefSubclassProc($hWnd, $iMsg, $wParam, $lParam) EndIf Case $WM_NCPAINT _WinAPI_DefWindowProc($hWnd, $iMsg, $wParam, $lParam) Local $hDC = _WinAPI_GetWindowDC($hWnd) Local $tRect = _WinAPI_GetWindowRect($hWnd) $tRect.Right = $tRect.Right - $tRect.Left $tRect.Bottom = $tRect.Bottom - $tRect.Top $tRect.Left = 0 $tRect.Top = 0 Local $iCol = _WinAPI_GetSysColor($COLOR_3DFACE) If MapExists($mh_SelCtrls, $hWnd) Then If $mh_SelCtrls[$hWnd] Then _ $iCol = ($hHasFocus = $hWnd) ? _WinAPI_RGB(0, 0xAA, 0) : _WinAPI_RGB(0, 0xAA, 0xAA) EndIf Local $hBrush = _WinAPI_CreateSolidBrush($iCol) _WinAPI_SelectObject($hDC, $hBrush) _WinAPI_FrameRect($hDC, $tRect, $hBrush) _WinAPI_DeleteObject($hBrush) _WinAPI_ReleaseDC($hWnd, $hDC) $iRet = 0 Case $WM_KEYDOWN If $wParam = $VK_DELETE Then _WinAPI_PostMessage($hWnd, $WM_DESTROY, 0, 0) Else $iRet = _WinAPI_DefSubclassProc($hWnd, $iMsg, $wParam, $lParam) EndIf Case $WM_DESTROY _WinAPI_RemoveWindowSubclass($hWnd, $pCtrlProc, $iIdSubclass) $iRet = _WinAPI_DefWindowProcW($hWnd, $iMsg, $wParam, $lParam) Switch _WinAPI_GetClassName($hWnd) Case "Button" _GUICtrlButton_Destroy($hWnd) Case "Edit" _GUICtrlEdit_Destroy($hWnd) EndSwitch MapRemove($mh_SelCtrls, $hWnd) Case Else ;~ ConsoleWrite(Hex($iMsg) & @CRLF) $iRet = _WinAPI_DefSubclassProc($hWnd, $iMsg, $wParam, $lParam) EndSwitch Return $iRet EndFunc ;==>CtrlProc Func _Ctrl_MoveSizeCtrlProc($hWnd, $iMsg, $wParam, $lParam) Local $iRetVal Local $tMsePoints, $tWinRect, $tMinMaxInfo, $tTgtRect Local $iSource, $iEvent Local $iFrameHitSize = 10 Local Static $iXOffset, $iYOffset Switch $iMsg Case $WM_NCHITTEST $tMsePoints = _WinAPI_MakePoints($lParam) $tWinRect = _WinAPI_GetWindowRect($hWnd) $iRetVal = $HTCLIENT ;only in caption bar if left button is down. (no kb input availabe in caption!) Local $iTestKey = _WinAPI_GetSystemMetrics($SM_SWAPBUTTON) ? $VK_RBUTTON : $VK_LBUTTON If BitAnd(0x8000, _WinAPI_GetAsyncKeyState($iTestKey)) Then $iRetVal = $HTCAPTION If $tMsePoints.X - $tWinRect.Left < $iFrameHitSize Then $iRetVal = $HTLEFT If $tMsePoints.X > ($tWinRect.Right - $iFrameHitSize) Then $iRetVal = $HTRIGHT If $tMsePoints.Y - $tWinRect.Top < $iFrameHitSize Then Switch $iRetVal Case $HTLEFT $iRetVal = $HTTOPLEFT Case $HTRIGHT $iRetVal = $HTTOPRIGHT Case Else $iRetVal = $HTTOP EndSwitch ElseIf $tMsePoints.Y > ($tWinRect.Bottom - $iFrameHitSize) Then Switch $iRetVal Case $HTLEFT $iRetVal = $HTBOTTOMLEFT Case $HTRIGHT $iRetVal = $HTBOTTOMRIGHT Case Else $iRetVal = $HTBOTTOM EndSwitch EndIf If $tMsePoints.X < 0 Then $iRetVal = _WinAPI_DefSubclassProc($hWnd, $iMsg, $wParam, $lParam) If $tMsePoints.Y < 0 Then $iRetVal = _WinAPI_DefSubclassProc($hWnd, $iMsg, $wParam, $lParam) _WinAPI_RedrawWindow($hWnd) Case $WM_GETMINMAXINFO ;Min width jumps to ~150 with WS_BORDER - I guess it gets min window size: SM_CYMINTRACK $tMinMaxInfo = DllStructCreate($tagMINMAXINFO, $lParam) $tMinMaxInfo.MinTrackSize(1) = $iMinCtrlW $tMinMaxInfo.MinTrackSize(2) = $iMinCtrlH $iRetVal = 0 Case $WM_SIZING $tWinRect = _WinAPI_GetWindowRect($hWnd) $tTgtRect = DllStructCreate($tagRect, $lParam) $tTgtRect.Left += Mod($tWinRect.Left - $tTgtRect.Left, $iSnap) $tTgtRect.Top += Mod($tWinRect.Top - $tTgtRect.Top, $iSnap) $tTgtRect.Right += Mod($tWinRect.Right - $tTgtRect.Right, $iSnap) $tTgtRect.Bottom += Mod($tWinRect.Bottom - $tTgtRect.Bottom, $iSnap) $iRetVal = True Case $WM_MOVING $tWinRect = _WinAPI_GetWindowRect($hWnd) $tTgtRect = DllStructCreate($tagRect, $lParam) $iXOffset += $tTgtRect.Left - $tWinRect.Left $iYOffset += $tTgtRect.Top - $tWinRect.Top Local $iSnapH = Floor($iXOffset / $iSnap) * $iSnap Local $iSnapV = Floor($iYOffset / $iSnap) * $iSnap $iXOffset -= $iSnapH $iYOffset -= $iSnapV $tTgtRect.Left = $tWinRect.Left + $iSnapH $tTgtRect.Right = $tWinRect.Right + $iSnapH $tTgtRect.Top = $tWinRect.Top + $iSnapV $tTgtRect.Bottom = $tWinRect.Bottom + $iSnapV $iRetVal = 0 Case $WM_EXITSIZEMOVE $iXOffset = 0 $iYOffset = 0 $iRetVal = _WinAPI_DefSubclassProc($hWnd, $iMsg, $wParam, $lParam) Case $WM_SETCURSOR $iSource = _WinAPI_WordToShort(_WinAPI_LoWord($lParam)) $iEvent = _WinAPI_HiWord($lParam) If $iSource = $HTCAPTION And $iEvent = $WM_LBUTTONDOWN Then _WinAPI_SetCursor($hCursor_Cross) $iRetVal = 1 Else $iRetVal = _WinAPI_DefSubclassProc($hWnd, $iMsg, $wParam, $lParam) EndIf Case Else $iRetVal = _WinAPI_DefSubclassProc($hWnd, $iMsg, $wParam, $lParam) EndSwitch Return $iRetVal EndFunc Func _WinAPI_MakePoints($iValue) Local $tPoints = DllStructCreate("struct;short X;short Y;endstruct") DllStructSetData($tPoints, 1, _WinAPI_LoWord($iValue)) DllStructSetData($tPoints, 2, _WinAPI_HiWord($iValue)) Return $tPoints EndFunc Func _WinAPI_SetCursorPos($iX, $iY) Local $aCall = DllCall("user32.dll", "bool", "SetCursorPos", "int", $iX, "int", $iY) If @error Then Return SetError(@error, @extended, 0) Return $aCall[0] EndFunc Func _WinAPI_MapWindowPoints($hWndFrom, $hWndTo, $pPoints, $iNumPoints) Local $aCall = DllCall("user32.dll", "int", "MapWindowPoints", "hwnd", $hWndFrom, "hwnd", $hWndTo, "ptr", $pPoints, "uint", $iNumPoints) If @error Then Return SetError(@error, @extended, 0) Return $aCall[0] EndFunc3 points
-
AutoIt v3.3.18.0 has been released - mainly a UDF release. Thanks to @jpm and the MVPs who were responsible for the majority of code in this version. Download it here. Complete list of changes: History3 points
-
DarkMode UDF for AutoIt's Win32GUIs
WildByDesign and one other reacted to jpm for a topic
2 points -
DarkMode UDF for AutoIt's Win32GUIs
NoNameCode and one other reacted to argumentum for a topic
2 points -
Flat Custom Buttons with NM_CUSTOMDRAW
WildByDesign and one other reacted to Nine for a topic
But you could hack the NM_CUSTOMDRAW. Not so great but it is working : ; From Nine #include <GUIConstants.au3> #include <WindowsConstants.au3> #include <StructureConstants.au3> #include <WinAPI.au3> #include <FrameConstants.au3> Global Const $tagNMCUSTOMDRAWINFO = $tagNMHDR & ";dword DrawStage;handle hdc;" & $tagRECT & ";dword_ptr ItemSpec;uint ItemState;lparam lItemParam;" Global $idBut Example() Func Example() Local $hGUI = GUICreate("Example") $idBut = GUICtrlCreateButton("Test", 10, 10, 100, 30) GUICtrlCreateButton("Standard", 10, 50, 100, 30) GUIRegisterMsg($WM_NOTIFY, WM_NOTIFY) GUISetState() While True Switch GUIGetMsg() Case $GUI_EVENT_CLOSE ExitLoop Case $idBut ConsoleWrite("Button was pressed" & @CRLF) EndSwitch WEnd EndFunc ;==>Example Func WM_NOTIFY($hWnd, $iMsg, $wParam, $lParam) Local $tInfo = DllStructCreate($tagNMCUSTOMDRAWINFO, $lParam) If $tInfo.IDFrom = $idBut And $tInfo.Code = $NM_CUSTOMDRAW Then Local $tRECT = DllStructCreate($tagRECT, DllStructGetPtr($tInfo, "left")) Switch $tInfo.DrawStage Case $CDDS_PREPAINT _WinAPI_DrawFrameControl($tInfo.hDC, $tRECT, $DFC_BUTTON, (BitAND($tInfo.ItemState, $CDIS_SELECTED) ? $DFCS_PUSHED : 0) + $DFCS_BUTTONPUSH) _WinAPI_InflateRect($tRECT, -3, -3) Local $hBrush = _WinAPI_CreateSolidBrush(BitAND($tInfo.ItemState, $CDIS_HOT) ? 0xCDEF : 0xAAAA) _WinAPI_FillRect($tInfo.hDC, $tRECT, $hBrush) _WinAPI_DeleteObject($hBrush) Return $CDRF_NOTIFYPOSTPAINT Case $CDDS_POSTPAINT _WinAPI_InflateRect($tRECT, -6, -6) _WinAPI_SetTextColor($tInfo.hDC, 0xFFFFFF) _WinAPI_SetBkColor($tInfo.hDC, BitAND($tInfo.ItemState, $CDIS_HOT) ? 0xCDEF : 0xAAAA) _WinAPI_DrawText($tInfo.hDC, GUICtrlRead($tInfo.IDFrom), $tRECT, BitOR($DT_CENTER, $DT_VCENTER)) EndSwitch EndIf Return $GUI_RUNDEFMSG EndFunc ;==>WM_NOTIFY2 points -
Version 1.2
28 downloads
JsonC UDF Enhanced - AutoIt JSON Library An enhanced JSON library for AutoIt using the JSON-C library, featuring a high-level API, path-based queries, and powerful utility functions. 📋 Table of Contents Features Requirements Installation Quick Start API Documentation Core Functions High-Level API Path-Based Queries Utility Functions Examples Error Handling Performance Credits License ✨ Features 1. High-Level API _JsonC_Parse: Parse JSON strings to AutoIt Maps/Arrays (easy to work with!) _JsonC_Generate: Convert AutoIt data to JSON strings with formatting options _JsonC_GeneratePretty: Pretty-print JSON output 2. Path-Based Queries _JsonC_Get: Get values by path (e.g., "user.address.city" or "items[0].name") _JsonC_Set: Set values by path (creates nested structures automatically) _JsonC_Delete: Delete values by path _JsonC_Has: Check if a path exists 3. Utility Functions _JsonC_Keys: Get all keys from a Map/Object _JsonC_Values: Get all values from a Map/Object or Array _JsonC_IsValid: Validate JSON strings _JsonC_GetTypeStr: Get human-readable type names 4. Optimizations Auto-loading DLL on first use Improved error handling with meaningful error codes Better memory management Support for both x86 and x64 architectures 📦 Requirements AutoIt: Version 3.3.16.0 or higher DLL Files: json-c.dll (for x64 systems) json-c_x86.dll (for x86 systems) JSON-C Library: Based on version 0.18-20240915 🚀 Installation Download the UDF: Copy JSONc_UDF.au3 to your AutoIt includes directory or project folder. Download DLL Files: Place the appropriate DLL files in your script directory: json-c.dll (64-bit) json-c_x86.dll (32-bit) Include in Your Script: #include "JSONc_UDF.au3" Architecture Setup (Optional): #AutoIt3Wrapper_UseX64=y ; Use 64-bit version 🎯 Quick Start Parse JSON String #include "JSONc_UDF.au3" ; Parse JSON Local $sJson = '{"name":"John","age":30,"email":"john@example.com"}' Local $mData = _JsonC_Parse($sJson) ; Access data ConsoleWrite("Name: " & $mData["name"] & @CRLF) ; Output: John ConsoleWrite("Age: " & $mData["age"] & @CRLF) ; Output: 30 ConsoleWrite("Email: " & $mData["email"] & @CRLF) ; Output: john@example.com ; Cleanup _JsonC_Shutdown() Generate JSON String #include "JSONc_UDF.au3" ; Create data structure Local $mUser[] $mUser["name"] = "Alice" $mUser["age"] = 25 $mUser["active"] = True ; Convert to JSON Local $sJson = _JsonC_Generate($mUser) ConsoleWrite($sJson & @CRLF) ; Output: {"name":"Alice","age":25,"active":true} ; Pretty print Local $sPrettyJson = _JsonC_GeneratePretty($mUser) ConsoleWrite($sPrettyJson & @CRLF) Path-Based Queries #include "JSONc_UDF.au3" Local $sJson = '{"user":{"name":"Bob","address":{"city":"New York","zip":"10001"}}}' Local $mData = _JsonC_Parse($sJson) ; Get nested values ConsoleWrite(_JsonC_Get($mData, "user.name") & @CRLF) ; Output: Bob ConsoleWrite(_JsonC_Get($mData, "user.address.city") & @CRLF) ; Output: New York ; Set nested values _JsonC_Set($mData, "user.phone", "555-1234") ; Check if path exists If _JsonC_Has($mData, "user.email") Then ConsoleWrite("Email exists!" & @CRLF) Else ConsoleWrite("Email not found!" & @CRLF) EndIf 📖 API Documentation Core Functions _JsonC_Startup($sDll_Filename = "") Loads the json-c.dll library. Parameters: $sDll_Filename - [Optional] DLL path or empty string for auto-detect Returns: Success: DLL filename Failure: Empty string and sets @error = 1 Example: If Not _JsonC_Startup() Then MsgBox(16, "Error", "Failed to load JSON-C DLL!") Exit EndIf _JsonC_Shutdown() Unloads json-c.dll and performs cleanup. Example: _JsonC_Shutdown() High-Level API _JsonC_Parse($sJsonString) Parse JSON string into AutoIt data structure (Map for objects, Array for arrays). Parameters: $sJsonString - JSON formatted string Returns: Success: AutoIt data structure (Map[], Array[], String, Number, Boolean, Null) Failure: Empty string and sets @error: @error = 1: DLL not loaded or load failed @error = 2: Parse error (invalid JSON) @error = 3: Memory allocation error Example: Local $mData = _JsonC_Parse('{"name":"John","age":30}') If @error Then ConsoleWrite("Parse error!" & @CRLF) Else ConsoleWrite($mData["name"] & @CRLF) ; Output: John EndIf _JsonC_Generate($vData, $iFlags = $JSON_C_TO_STRING_PLAIN) Convert AutoIt data structure to JSON string. Parameters: $vData - AutoIt data structure (Map, Array, String, Number, Boolean, Null) $iFlags - [Optional] Formatting flags: $JSON_C_TO_STRING_PLAIN - Plain, no whitespace (default) $JSON_C_TO_STRING_SPACED - Spaced $JSON_C_TO_STRING_PRETTY - Pretty-printed with 2 spaces $JSON_C_TO_STRING_PRETTY_TAB - Pretty-printed with tabs Returns: Success: JSON formatted string Failure: Empty string and sets @error: @error = 1: DLL not loaded @error = 2: Conversion error Example: Local $mData[] $mData["name"] = "John" $mData["age"] = 30 Local $sJson = _JsonC_Generate($mData) ConsoleWrite($sJson & @CRLF) ; {"name":"John","age":30} _JsonC_GeneratePretty($vData, $bUseTabs = False) Convert AutoIt data structure to pretty-printed JSON string. Parameters: $vData - AutoIt data structure $bUseTabs - [Optional] Use tabs instead of 2 spaces (default: False) Returns: Success: Pretty-printed JSON string Failure: Empty string and sets @error Example: Local $sPrettyJson = _JsonC_GeneratePretty($mData) ConsoleWrite($sPrettyJson & @CRLF) _JsonC_IsValid($sJsonString) Validate if a string is valid JSON. Parameters: $sJsonString - String to validate Returns: True if valid JSON False otherwise Example: If _JsonC_IsValid($sJsonString) Then ConsoleWrite("Valid JSON!" & @CRLF) Else ConsoleWrite("Invalid JSON!" & @CRLF) EndIf Path-Based Queries _JsonC_Get($vData, $sPath, $vDefault = Null) Get value from JSON data by path (supports dot notation and array indices). Parameters: $vData - JSON data (Map/Array from _JsonC_Parse) $sPath - Path to value (e.g., "user.address.city" or "items[0].name") $vDefault - [Optional] Default value if path not found (default: Null) Returns: Value at path, or $vDefault if not found Example: ; Simple path $sName = _JsonC_Get($mData, "user.name") ; Array index $sFirstItem = _JsonC_Get($mData, "items[0]") ; With default value $sEmail = _JsonC_Get($mData, "user.email", "N/A") _JsonC_Set(ByRef $vData, $sPath, $vValue) Set value in JSON data by path (creates intermediate objects if needed). Parameters: $vData - [ByRef] JSON data to modify $sPath - Path where to set value (e.g., "user.name" or "items[0].name") $vValue - Value to set Returns: True on success False on failure Example: ; Set simple value _JsonC_Set($mData, "user.name", "John") ; Set nested value (auto-creates structure) _JsonC_Set($mData, "user.address.city", "New York") ; Set array element _JsonC_Set($mData, "items[0].price", 19.99) _JsonC_Delete(ByRef $vData, $sPath) Delete value from JSON data by path. Parameters: $vData - [ByRef] JSON data $sPath - Path to delete Returns: True if deleted False if path not found Example: _JsonC_Delete($mData, "user.email") _JsonC_Has($vData, $sPath) Check if path exists in JSON data. Parameters: $vData - JSON data (Map/Array) $sPath - Path to check Returns: True if path exists False otherwise Example: If _JsonC_Has($mData, "user.email") Then ConsoleWrite("Email exists!" & @CRLF) EndIf _JsonC_GetTypeStr($vData, $sPath = "") Get the type of value at path as a string. Parameters: $vData - JSON data $sPath - [Optional] Path to value (default: "" = root) Returns: Type name: "Map", "Array", "String", "Int64", "Double", "Bool", "Keyword", or "Unknown" Example: ConsoleWrite(_JsonC_GetTypeStr($mData, "user.age") & @CRLF) ; Output: Int64 Utility Functions _JsonC_Keys($vData, $sPath = "") Get all keys from a Map/Object. Parameters: $vData - JSON data $sPath - [Optional] Path to object (default: "" = root) Returns: Array of keys, or empty array if not a Map Example: Local $aKeys = _JsonC_Keys($mData) For $sKey In $aKeys ConsoleWrite($sKey & @CRLF) Next _JsonC_Values($vData, $sPath = "") Get all values from a Map/Object or Array. Parameters: $vData - JSON data $sPath - [Optional] Path to object/array (default: "" = root) Returns: Array of values, or empty array if not a Map/Array Example: Local $aValues = _JsonC_Values($mData, "user") For $vValue In $aValues ConsoleWrite($vValue & @CRLF) Next 💡 Examples Example 1: Working with Hardware Data #include "JSONc_UDF.au3" ; Load hardware data from JSON file Local $sJsonFile = @ScriptDir & "\hardware_data.json" Local $sJsonContent = FileRead($sJsonFile) ; Parse JSON Local $mHardware = _JsonC_Parse($sJsonContent) ; Access CPU information If _JsonC_Get($mHardware, "intelCPU.available", False) Then ConsoleWrite("CPU Package Temp: " & _JsonC_Get($mHardware, "intelCPU.packageTemp") & "°C" & @CRLF) ConsoleWrite("Core Count: " & _JsonC_Get($mHardware, "intelCPU.coreCount") & @CRLF) EndIf ; Access GPU information Local $aGPUs = _JsonC_Get($mHardware, "amdRadeonGPUs") If IsArray($aGPUs) And UBound($aGPUs) > 0 Then Local $mFirstGPU = $aGPUs[0] ConsoleWrite("GPU Name: " & $mFirstGPU["name"] & @CRLF) ConsoleWrite("GPU Temp: " & $mFirstGPU["temperature"] & "°C" & @CRLF) EndIf ; Cleanup _JsonC_Shutdown() Example 2: Creating and Modifying JSON #include "JSONc_UDF.au3" ; Create a new data structure Local $mConfig[] $mConfig["appName"] = "MyApp" $mConfig["version"] = "1.0.0" ; Add nested settings _JsonC_Set($mConfig, "settings.theme", "dark") _JsonC_Set($mConfig, "settings.language", "en") _JsonC_Set($mConfig, "settings.notifications", True) ; Add array of recent files Local $aRecentFiles[3] = ["file1.txt", "file2.txt", "file3.txt"] $mConfig["recentFiles"] = $aRecentFiles ; Generate pretty JSON Local $sJson = _JsonC_GeneratePretty($mConfig) ConsoleWrite($sJson & @CRLF) ; Save to file FileWrite(@ScriptDir & "\config.json", $sJson) _JsonC_Shutdown() Example 3: Working with Arrays #include "JSONc_UDF.au3" Local $sJson = '[{"name":"Alice","age":25},{"name":"Bob","age":30},{"name":"Charlie","age":35}]' Local $aUsers = _JsonC_Parse($sJson) ; Iterate through users For $i = 0 To UBound($aUsers) - 1 Local $mUser = $aUsers[$i] ConsoleWrite("User " & ($i + 1) & ": " & $mUser["name"] & " (Age: " & $mUser["age"] & ")" & @CRLF) Next _JsonC_Shutdown() Example 4: Error Handling #include "JSONc_UDF.au3" ; Validate JSON before parsing Local $sJson = '{"name":"John","age":30}' If Not _JsonC_IsValid($sJson) Then MsgBox(16, "Error", "Invalid JSON!") Exit EndIf ; Parse with error checking Local $mData = _JsonC_Parse($sJson) If @error Then ConsoleWrite("Parse error code: " & @error & @CRLF) Exit EndIf ; Safe value retrieval with default Local $sEmail = _JsonC_Get($mData, "email", "no-email@example.com") ConsoleWrite("Email: " & $sEmail & @CRLF) _JsonC_Shutdown() ⚠️ Error Handling The UDF uses AutoIt's @error macro for error reporting: Common Error Codes @error = 1: DLL not loaded or DLL call failed @error = 2: Parse error (invalid JSON) or conversion error @error = 3: Memory allocation error Best Practices Always check return values: Local $mData = _JsonC_Parse($sJson) If @error Then ConsoleWrite("Error: " & @error & @CRLF) EndIf Use _JsonC_IsValid() before parsing: If _JsonC_IsValid($sJson) Then $mData = _JsonC_Parse($sJson) EndIf Provide default values with _JsonC_Get(): Local $sValue = _JsonC_Get($mData, "path", "default") Always call _JsonC_Shutdown() when done: _JsonC_Shutdown() ⚡ Performance Benchmarks Parse: ~0.5ms for 1KB JSON Generate: ~0.3ms for 1KB data Path Query: ~0.05ms per query Tips for Optimal Performance Reuse parsed data instead of parsing repeatedly Use plain format ($JSON_C_TO_STRING_PLAIN) for faster generation Cache path queries if accessing the same paths multiple times Batch modifications before generating JSON 🙏 Credits Original Author: Sean Griffin (JSON_C.au3) Enhanced By: Dao Van Trong - TRONG.PRO JSON-C Library: json-c/json-c (v0.18-20240915) Special Thanks The AutoIt community for continuous support JSON-C developers for the robust C library 📄 License This UDF is provided "as-is" without warranty of any kind. You are free to use, modify, and distribute this code in your projects. The underlying JSON-C library is licensed under the MIT License. See the JSON-C repository for details. 🔗 Links JSON-C GitHub: https://github.com/json-c/json-c Author Website: TRONG.PRO 📞 Support If you encounter any issues or have questions: Check the Examples section Review the API Documentation Examine the included example file: EG_hardware_data.au3 Made with ❤️ for the AutoIt Community2 points -
WinSockUDF - TCP/UDP Networking Library for AutoIt Version: 1.1 | Author: Dao Van Trong - TRONG.PRO | AutoIt: 3.3.14.2+ 📖 Overview WinSockUDF is a powerful, production-ready TCP/UDP networking library for AutoIt that brings enterprise-level networking capabilities to your scripts. Built on top of the Windows Sockets API (Winsock2), it provides asynchronous, event-driven communication with advanced features that go far beyond AutoIt's built-in networking functions. This library is designed for developers who need reliable, high-performance network communication in their AutoIt applications - whether you're building chat systems, file transfer utilities, remote administration tools, or IoT device controllers. ⚡ Key Features Core Networking ✅ Asynchronous Event-Driven Architecture - True non-blocking I/O with elegant callback system ✅ Full Winsock2 API Access - Direct Windows Sockets implementation for maximum performance ✅ TCP Server & Client - Production-ready server with multi-client support ✅ UDP Support - Connectionless datagram communication (SendTo/RecvFrom) ✅ Multiple Simultaneous Connections - Handle hundreds of clients with ease Advanced Features 🔒 Binary Data Transfer - Safe transmission with automatic Base64 encoding/decoding 🎯 Smart Connection Management - Automatic reconnection, timeouts, and error recovery 📡 Broadcasting - Send messages to all connected clients instantly 🔍 Client Management - Track, query, and control individual client connections ⚙️ Flexible Event System - Register custom callbacks for all network events Developer Experience 📚 Comprehensive Error Handling - Detailed @error/@extended codes for debugging 🎨 Clean API Design - Intuitive function names and consistent parameter patterns 📝 Well Documented - Complete function reference with examples 🚀 Production Ready - Battle-tested in real-world applications 📦 Installation Method 1: Quick Start Download WinSockUDF.au3 from this repository Place it in your AutoIt include directory (usually C:\Program Files (x86)\AutoIt3\Include) Include it in your script: #include <WinSockUDF.au3> Method 2: Project-Local Copy WinSockUDF.au3 to your project folder Include with relative path: #include "WinSockUDF.au3" Requirements: AutoIt v3.3.14.2 or higher Windows OS (XP or later) No external dependencies required Quick Start TCP Server Example #include "WinSockUDF.au3" _TCP_Startup() ; Create server on port 8080 $hServer = _TCP_Server_Create(8080) ; Register event callbacks _TCP_Server_OnNewClient($hServer, "OnNewClient") _TCP_Server_OnReceive($hServer, "OnReceive") _TCP_Server_OnDisconnect($hServer, "OnDisconnect") ; Event loop While 1 Sleep(10) WEnd Func OnNewClient($hClient, $iError) ConsoleWrite("New client connected: " & $hClient & @CRLF) _TCP_Send($hClient, "Welcome to server!" & @CRLF) EndFunc Func OnReceive($hClient, $sData, $iError) ConsoleWrite("Received: " & $sData & @CRLF) _TCP_Send($hClient, "Echo: " & $sData) EndFunc Func OnDisconnect($hClient, $iError) ConsoleWrite("Client disconnected: " & $hClient & @CRLF) EndFunc TCP Client Example #include "WinSockUDF.au3" _TCP_Startup() ; Connect to server $hClient = _TCP_Client_Create("127.0.0.1", 8080) ; Register event callbacks _TCP_Client_OnConnect($hClient, "OnConnect") _TCP_Client_OnReceive($hClient, "OnReceive") _TCP_Client_OnDisconnect($hClient, "OnDisconnect") ; Event loop While 1 Sleep(10) WEnd Func OnConnect($hSocket, $iError) If $iError Then ConsoleWrite("Connection failed: " & $iError & @CRLF) Else ConsoleWrite("Connected successfully!" & @CRLF) _TCP_Send($hSocket, "Hello Server!") EndIf EndFunc Func OnReceive($hSocket, $sData, $iError) ConsoleWrite("Received: " & $sData & @CRLF) EndFunc Func OnDisconnect($hSocket, $iError) ConsoleWrite("Disconnected from server" & @CRLF) EndFunc Function Reference Initialization Functions Function Description _TCP_Startup() Initialize Winsock and async system _TCP_Shutdown() Close all connections and free resources TCP Server Functions Function Description _TCP_Server_Create($iPort[, $sIP = "0.0.0.0"[, $iMaxPending = 5]]) Create TCP server _TCP_Server_Stop($hSocket) Stop server and close all clients _TCP_Server_ClientList() Get array of connected clients _TCP_Server_ClientIP($hSocket) Get client IP address _TCP_Server_DisconnectClient($hSocket) Disconnect specific client _TCP_Server_Broadcast($vData) Send data to all clients _TCP_Server_OnNewClient($hServer, $sCallback) Register new client callback _TCP_Server_OnReceive($hServer, $sCallback) Register receive callback _TCP_Server_OnSend($hServer, $sCallback) Register send ready callback _TCP_Server_OnDisconnect($hServer, $sCallback) Register disconnect callback TCP Client Functions Function Description _TCP_Client_Create($sIP, $iPort[, $sSourceIP = ""[, $iSourcePort = 0[, $iTimeout = 0]]]) Create TCP client connection _TCP_Client_Stop($hSocket) Close client connection _TCP_Client_OnConnect($hClient, $sCallback) Register connect callback _TCP_Client_OnReceive($hClient, $sCallback) Register receive callback _TCP_Client_OnSend($hClient, $sCallback) Register send ready callback _TCP_Client_OnDisconnect($hClient, $sCallback) Register disconnect callback Common TCP Functions Function Description _TCP_Send($hSocket, $vData[, $iFlag = 0]) Send data through socket _TCP_Recv($hSocket, $iMaxLen[, $iFlag = 0]) Receive data from socket _TCP_Send_Ex($hSocket, $vData[, $iFlag = 0]) Send with automatic Base64 encoding _TCP_Recv_Ex($hSocket, $iMaxLen[, $iFlag = 0]) Receive with automatic Base64 decoding _TCP_NameToIP($sName) Convert hostname to IP address _TCP_GetIPs([$sServerName = ""]) Get local and public IP addresses UDP Functions Function Description _UDP_Startup() Initialize UDP system _UDP_Shutdown() Shutdown UDP system _UDP_Bind([$sSourceIP = ""[, $iSourcePort = 0]]) Create and bind UDP socket _UDP_SendTo($sIP, $iPort, $vData[, $hSocket = 0]) Send UDP packet _UDP_RecvFrom($hSocket, $iMaxLen[, $iFlag = 0]) Receive UDP packet _UDP_CloseSocket($vSocket) Close UDP socket Base64 Functions Function Description _Base64Encode($bInput[, $bNoCRLF = True]) Encode binary data to Base64 string _Base64Decode($sInput[, $bReturnBinary = False[, $iDecodeType = 1]]) Decode Base64 string _Base64EncodeStr($sInput[, $iEncodeType = 4[, $bNoCRLF = True]]) Encode string to Base64 _Base64DecodeStr($sInput[, $iDecodeType = 4]) Decode Base64 to string Path Utility Functions Function Description _PathWithSlash($sPath) Add trailing backslash to path _PathRemoveTrail($sPath) Remove trailing backslashes from path Constants Data Flags $TCP_DEFAULT_DATA = 0 ; Default string data $TCP_BINARY_DATA = 1 ; Binary data mode $TCP_EOT_DATA = 2 ; End-of-transmission marker Event Types $TCP_EVENT_SEND = 1 ; Send ready event $TCP_EVENT_RECEIVE = 2 ; Data received event $TCP_EVENT_CONNECT = 4 ; Connection established $TCP_EVENT_DISCONNECT = 8 ; Connection closed $TCP_EVENT_NEWCLIENT = 16 ; New client connected (server) Advanced Features Binary File Transfer Use _TCP_Send_Ex() and _TCP_Recv_Ex() for automatic Base64 encoding/decoding of binary data: ; Send binary file Local $bData = FileRead("image.jpg") _TCP_Send_Ex($hSocket, $bData) ; Receive binary file Local $bData = _TCP_Recv_Ex($hSocket, 8192, $TCP_BINARY_DATA) FileWrite("received.jpg", $bData) Multiple Server Support The library supports running multiple servers on different ports simultaneously with independent callback handlers. Connection Timeout Client connections support timeout parameter: ; Wait up to 5 seconds for connection $hClient = _TCP_Client_Create("192.168.1.100", 8080, "", 0, 5000) Error Handling All functions set @error on failure: -1 = General error (check @extended for WSA error code) -2 = Failed to load Winsock DLL -4 = Invalid parameters or socket not found -5 = Connection failed -6 = Timeout Example: $hServer = _TCP_Server_Create(8080) If @error Then ConsoleWrite("Failed to create server. Error: " & @error & ", Extended: " & @extended & @CRLF) Exit EndIf 📚 Example Applications This repository includes three complete, production-ready example applications: TCP Chat System - Full-featured chat room with authentication, private messaging, and user management UDP Chat Application - Lightweight UDP-based chat demonstrating connectionless communication Lab Manager System - Professional client-server remote administration tool with system monitoring Each example includes both client and server implementations with complete source code. 💡 Use Cases 💬 Chat Applications - Real-time messaging systems with multi-user support 📁 File Transfer Tools - Binary file sharing with Base64 encoding 🖥️ Remote Administration - Control and monitor computers over network 🎮 Game Servers - Multiplayer game networking and matchmaking 🌐 IoT Communication - Device-to-device communication and control 🔌 API Servers - Custom protocol implementations and microservices 📊 Data Collection - Sensor data aggregation and monitoring systems 🔔 Notification Systems - Push notification and alert distribution Note: This library uses direct Winsock API calls for advanced networking features. Make sure to call _TCP_Startup() before using any TCP/UDP functions and _TCP_Shutdown() when done. UDF: ; #INDEX# ======================================================================================================================= ; Title .........: WinSockUDF ; AutoIt Version : 3.3.14.2+ ; Language ......: English ; Description ...: Advanced TCP/UDP networking library with async events, error handling, full Winsock2 API support ; Author(s) .....: Dao Van Trong - TRONG.PRO ; Version .......: 1.1 ; =============================================================================================================================== #include-once ; #CONSTANTS# =================================================================================================================== Global Const $TCP_DEFAULT_DATA = 0 Global Const $TCP_BINARY_DATA = 1 Global Const $TCP_EOT_DATA = 2 ; Async Events Global Const $TCP_EVENT_SEND = 1 Global Const $TCP_EVENT_RECEIVE = 2 Global Const $TCP_EVENT_CONNECT = 4 Global Const $TCP_EVENT_DISCONNECT = 8 Global Const $TCP_EVENT_NEWCLIENT = 16 ; Winsock Events (internal) Global Const $FD_READ = 1 Global Const $FD_WRITE = 2 Global Const $FD_OOB = 4 Global Const $FD_ACCEPT = 8 Global Const $FD_CONNECT = 16 Global Const $FD_CLOSE = 32 ; =============================================================================================================================== ; #VARIABLES# =================================================================================================================== Global $__TCP_hWs2_32 = -1 Global $__TCP_AsyncWindow = 0 Global $__TCP_Sockets[1][11] ; [socket, msgID, onRecv, onSend, onConnect, onDisconnect, onNewClient, ip, port, isServer, parentServer] Global $__TCP_Initialized = False ; =============================================================================================================================== ; #CURRENT# ===================================================================================================================== ; Initialization ; _TCP_Startup ; _TCP_Shutdown ; ; Server Functions ; _TCP_Server_Create ; _TCP_Server_Stop ; _TCP_Server_ClientList ; _TCP_Server_ClientIP ; _TCP_Server_DisconnectClient ; _TCP_Server_Broadcast ; _TCP_Server_OnNewClient ; _TCP_Server_OnReceive ; _TCP_Server_OnSend ; _TCP_Server_OnDisconnect ; ; Client Functions ; _TCP_Client_Create ; _TCP_Client_Stop ; _TCP_Client_OnConnect ; _TCP_Client_OnReceive ; _TCP_Client_OnSend ; _TCP_Client_OnDisconnect ; ; Common Functions ; _TCP_Send ; _TCP_Recv ; _TCP_Send_Ex ; _TCP_Recv_Ex ; _TCP_RegisterEvent ; _TCP_NameToIP ; _TCP_GetIPs ; _TCP_OnConnect (alias for Client) ; _TCP_OnDisconnect (universal) ; _TCP_OnReceive (universal) ; _TCP_OnSend (universal) ; ; UDP Functions ; _UDP_Startup ; _UDP_Shutdown ; _UDP_Bind ; _UDP_SendTo ; _UDP_RecvFrom ; _UDP_CloseSocket ; ; Base64 Functions ; _Base64Encode ; _Base64Decode ; _Base64EncodeStr ; _Base64DecodeStr ; ; Path Functions ; _PathWithSlash ; _PathRemoveTrail ; ; =============================================================================================================================== ; #FUNCTION# ==================================================================================================================== ; Name ..........: _TCP_Startup ; Description ...: Initialize Winsock and async system ; Syntax ........: _TCP_Startup() ; Return values .: Success - 1, Failure - 0 and sets @error ; =============================================================================================================================== Func _TCP_Startup() If $__TCP_Initialized Then Return 1 Local $iResult = TCPStartup() If @error Then Return SetError(@error, 0, 0) $__TCP_hWs2_32 = DllOpen("Ws2_32.dll") If $__TCP_hWs2_32 = -1 Then Return SetError(-2, 0, 0) $__TCP_AsyncWindow = GUICreate("TCP_AsyncWindow_" & Random(1000, 9999, 1)) $__TCP_Initialized = True Return SetError(0, 0, 1) EndFunc ;==>_TCP_Startup ; #FUNCTION# ==================================================================================================================== ; Name ..........: _TCP_Shutdown ; Description ...: Close all connections and free resources ; Syntax ........: _TCP_Shutdown() ; Return values .: Success - 1 ; =============================================================================================================================== Func _TCP_Shutdown() If Not $__TCP_Initialized Then Return 1 ; Close all sockets For $i = UBound($__TCP_Sockets) - 1 To 0 Step -1 If $__TCP_Sockets[$i][0] Then ___TCP_CloseSocket($__TCP_Sockets[$i][0]) EndIf Next ReDim $__TCP_Sockets[1][11] If $__TCP_hWs2_32 <> -1 Then DllClose($__TCP_hWs2_32) $__TCP_hWs2_32 = -1 TCPShutdown() $__TCP_Initialized = False Return 1 EndFunc ;==>_TCP_Shutdown ; #FUNCTION# ==================================================================================================================== ; Name ..........: _TCP_Server_Create ; Description ...: Create TCP server with async support ; Syntax ........: _TCP_Server_Create($iPort[, $sIP = "0.0.0.0"[, $iMaxPending = 5]]) ; Parameters ....: $iPort - Port to listen on ; $sIP - [optional] IP address (default = "0.0.0.0" - all interfaces) ; $iMaxPending - [optional] Max pending connections (default = 5) ; Return values .: Success - Socket handle ; Failure - -1 and sets @error ; =============================================================================================================================== Func _TCP_Server_Create($iPort, $sIP = "0.0.0.0", $iMaxPending = 5) If Not $__TCP_Initialized Then If Not _TCP_Startup() Then Return SetError(@error, 0, -1) EndIf Local $hSocket = ___TCP_Socket() If @error Then Return SetError(@error, 0, -1) ; Bind socket Local $tSockAddr = ___TCP_SockAddr($sIP, $iPort) If @error Then ___TCP_CloseSocket($hSocket) Return SetError(@error, 0, -1) EndIf Local $aRet = DllCall($__TCP_hWs2_32, "int", "bind", "uint", $hSocket, "ptr", DllStructGetPtr($tSockAddr), "int", DllStructGetSize($tSockAddr)) If @error Or $aRet[0] <> 0 Then ___TCP_CloseSocket($hSocket) Return SetError(-1, ___TCP_WSAGetLastError(), -1) EndIf ; Listen $aRet = DllCall($__TCP_hWs2_32, "int", "listen", "uint", $hSocket, "int", $iMaxPending) If @error Or $aRet[0] <> 0 Then ___TCP_CloseSocket($hSocket) Return SetError(-1, ___TCP_WSAGetLastError(), -1) EndIf ; Setup async Local $iMsgID = 0x0400 + UBound($__TCP_Sockets) If Not ___TCP_AsyncSelect($hSocket, $__TCP_AsyncWindow, $iMsgID, $FD_ACCEPT) Then ___TCP_CloseSocket($hSocket) Return SetError(@error, @extended, -1) EndIf GUIRegisterMsg($iMsgID, "___TCP_Server_OnAccept") ; Store socket info ReDim $__TCP_Sockets[UBound($__TCP_Sockets) + 1][11] Local $idx = UBound($__TCP_Sockets) - 1 $__TCP_Sockets[$idx][0] = $hSocket $__TCP_Sockets[$idx][1] = $iMsgID $__TCP_Sockets[$idx][7] = $sIP $__TCP_Sockets[$idx][8] = $iPort $__TCP_Sockets[$idx][9] = True ; isServer $__TCP_Sockets[$idx][10] = 0 ; parentServer Return $hSocket EndFunc ;==>_TCP_Server_Create ; #FUNCTION# ==================================================================================================================== ; Name ..........: _TCP_Server_Stop ; Description ...: Stop server and close all client connections ; Syntax ........: _TCP_Server_Stop($hSocket) ; Parameters ....: $hSocket - Server socket handle ; Return values .: Success - 1 ; Failure - 0 and sets @error ; =============================================================================================================================== Func _TCP_Server_Stop($hSocket) Local $iServerIdx = ___TCP_FindSocket($hSocket) If $iServerIdx < 0 Then Return SetError(-4, 0, 0) ; Close all clients of this server For $i = UBound($__TCP_Sockets) - 1 To 0 Step -1 If $i <> $iServerIdx And $__TCP_Sockets[$i][0] Then If Not $__TCP_Sockets[$i][9] Then ; Not a server ___TCP_CloseSocket($__TCP_Sockets[$i][0]) ___TCP_ArrayDelete($__TCP_Sockets, $i) EndIf EndIf Next ; Close server socket ___TCP_CloseSocket($hSocket) ___TCP_ArrayDelete($__TCP_Sockets, $iServerIdx) Return 1 EndFunc ;==>_TCP_Server_Stop ; #FUNCTION# ==================================================================================================================== ; Name ..........: _TCP_Client_Create ; Description ...: Create TCP client connection with timeout and async support ; Syntax ........: _TCP_Client_Create($sIP, $iPort[, $sSourceIP = ""[, $iSourcePort = 0[, $iTimeout = 0]]]) ; Parameters ....: $sIP - Server IP address ; $iPort - Server port ; $sSourceIP - [optional] Local IP to bind (default = "") ; $iSourcePort - [optional] Local port to bind (default = 0) ; $iTimeout - [optional] Connection timeout in ms (0 = async without waiting) ; Return values .: Success - Socket handle ; Failure - -1 and sets @error ; =============================================================================================================================== Func _TCP_Client_Create($sIP, $iPort, $sSourceIP = "", $iSourcePort = 0, $iTimeout = 0) If Not $__TCP_Initialized Then If Not _TCP_Startup() Then Return SetError(@error, 0, -1) EndIf ; Validate parameters If Not ($iPort > 0 And $iPort < 65535) Then Return SetError(-4, 0, -1) If Not ($iSourcePort >= 0 And $iSourcePort < 65535) Then Return SetError(-4, 0, -1) Local $hSocket = ___TCP_Socket() If @error Then Return SetError(@error, 0, -1) ; Bind source if specified If $sSourceIP <> "" Or $iSourcePort > 0 Then Local $tSockAddr = ___TCP_SockAddr($sSourceIP <> "" ? $sSourceIP : "0.0.0.0", $iSourcePort) If @error Then ___TCP_CloseSocket($hSocket) Return SetError(@error, 0, -1) EndIf Local $aRet = DllCall($__TCP_hWs2_32, "int", "bind", "uint", $hSocket, "ptr", DllStructGetPtr($tSockAddr), "int", DllStructGetSize($tSockAddr)) If @error Or $aRet[0] <> 0 Then ___TCP_CloseSocket($hSocket) Return SetError(-1, ___TCP_WSAGetLastError(), -1) EndIf EndIf ; Store socket info BEFORE async setup ReDim $__TCP_Sockets[UBound($__TCP_Sockets) + 1][11] Local $idx = UBound($__TCP_Sockets) - 1 $__TCP_Sockets[$idx][0] = $hSocket $__TCP_Sockets[$idx][7] = $sIP $__TCP_Sockets[$idx][8] = $iPort $__TCP_Sockets[$idx][9] = False ; isClient $__TCP_Sockets[$idx][10] = 0 ; parentServer ; Setup async - IMPORTANT: Do this before connect Local $iMsgID = 0x0400 + $idx $__TCP_Sockets[$idx][1] = $iMsgID If Not ___TCP_AsyncSelect($hSocket, $__TCP_AsyncWindow, $iMsgID, BitOR($FD_READ, $FD_WRITE, $FD_CONNECT, $FD_CLOSE)) Then ___TCP_CloseSocket($hSocket) ___TCP_ArrayDelete($__TCP_Sockets, $idx) Return SetError(@error, @extended, -1) EndIf GUIRegisterMsg($iMsgID, "___TCP_Client_OnSocketEvent") ; Connect Local $tSockAddr = ___TCP_SockAddr($sIP, $iPort) If @error Then ___TCP_CloseSocket($hSocket) ___TCP_ArrayDelete($__TCP_Sockets, $idx) Return SetError(@error, 0, -1) EndIf Local $aRet = DllCall($__TCP_hWs2_32, "int", "connect", "uint", $hSocket, "ptr", DllStructGetPtr($tSockAddr), "int", DllStructGetSize($tSockAddr)) ; For async sockets, connect() returns SOCKET_ERROR with WSAEWOULDBLOCK Local $iError = ___TCP_WSAGetLastError() ; Check if connected immediately (rare for TCP) If Not @error And $aRet[0] = 0 Then ; Connected immediately - call connect callback if set Return $hSocket EndIf ; WSAEWOULDBLOCK (10035) is normal for async connect If $iError <> 10035 And $iError <> 0 Then ___TCP_CloseSocket($hSocket) ___TCP_ArrayDelete($__TCP_Sockets, $idx) Return SetError(-1, $iError, -1) EndIf ; Wait for connection if timeout specified If $iTimeout > 0 Then Local $hTimer = TimerInit() Local $bConnected = False While TimerDiff($hTimer) < $iTimeout Sleep(10) ; Check if socket still exists (might have been connected via callback) Local $iCheckIdx = ___TCP_FindSocket($hSocket) If $iCheckIdx >= 0 Then ; Try to check connection status Local $tErr = DllStructCreate("int") Local $aCheck = DllCall($__TCP_hWs2_32, "int", "getsockopt", _ "uint", $hSocket, "int", 0xFFFF, "int", 0x1007, _ "ptr", DllStructGetPtr($tErr), "int*", DllStructGetSize($tErr)) ; SOL_SOCKET, SO_ERROR If Not @error And $aCheck[0] = 0 Then Local $iSockErr = DllStructGetData($tErr, 1) If $iSockErr = 0 Then ; Connected successfully $bConnected = True ExitLoop ElseIf $iSockErr <> 10035 Then ; Not WSAEWOULDBLOCK ; Connection error ___TCP_CloseSocket($hSocket) ___TCP_ArrayDelete($__TCP_Sockets, $iCheckIdx) Return SetError(-1, $iSockErr, -1) EndIf EndIf Else ; Socket was removed (probably connected and then disconnected) ExitLoop EndIf WEnd ; Check timeout If Not $bConnected And TimerDiff($hTimer) >= $iTimeout Then Local $iCheckIdx = ___TCP_FindSocket($hSocket) If $iCheckIdx >= 0 Then ___TCP_CloseSocket($hSocket) ___TCP_ArrayDelete($__TCP_Sockets, $iCheckIdx) EndIf Return SetError(-6, 0, -1) ; Timeout EndIf EndIf Return $hSocket EndFunc ;==>_TCP_Client_Create ; #FUNCTION# ==================================================================================================================== ; Name ..........: _TCP_Client_Stop ; Description ...: Close client connection ; Syntax ........: _TCP_Client_Stop($hSocket) ; Parameters ....: $hSocket - Client socket handle ; Return values .: Success - 1 ; Failure - 0 and sets @error ; =============================================================================================================================== Func _TCP_Client_Stop($hSocket) Local $idx = ___TCP_FindSocket($hSocket) If $idx < 0 Then Return SetError(-4, 0, 0) ___TCP_Shutdown($hSocket) ___TCP_CloseSocket($hSocket) ___TCP_ArrayDelete($__TCP_Sockets, $idx) Return 1 EndFunc ;==>_TCP_Client_Stop ; #FUNCTION# ==================================================================================================================== ; Name ..........: _TCP_Send ; Description ...: Send data through socket ; Syntax ........: _TCP_Send($hSocket, $vData[, $iFlag = 0]) ; Parameters ....: $hSocket - Socket handle ; $vData - Data to send (string or binary) ; $iFlag - [optional] $TCP_DEFAULT_DATA (0) or $TCP_EOT_DATA (2) ; Return values .: Success - Number of bytes sent ; Failure - -1 and sets @error ; =============================================================================================================================== Func _TCP_Send($hSocket, $vData, $iFlag = 0) If BitAND($iFlag, $TCP_EOT_DATA) Then $vData = String($vData) & Chr(3) Local $iResult = TCPSend($hSocket, $vData) Return SetError(@error, 0, $iResult) EndFunc ;==>_TCP_Send ; #FUNCTION# ==================================================================================================================== ; Name ..........: _TCP_Recv ; Description ...: Receive data from socket ; Syntax ........: _TCP_Recv($hSocket, $iMaxLen[, $iFlag = 0]) ; Parameters ....: $hSocket - Socket handle ; $iMaxLen - Max bytes to receive ; $iFlag - [optional] $TCP_DEFAULT_DATA (0), $TCP_BINARY_DATA (1), or $TCP_EOT_DATA (2) ; Return values .: Success - Data received ; Failure - "" and sets @error/@extended ; Remarks .......: @extended = 1 if connection closed, = 2 if EOT reached ; =============================================================================================================================== Func _TCP_Recv($hSocket, $iMaxLen, $iFlag = 0) If Not $__TCP_Initialized Then Return SetError(-1, 0, "") Local $tBuf If BitAND($iFlag, $TCP_BINARY_DATA) Then $tBuf = DllStructCreate("byte[" & $iMaxLen & "]") Else $tBuf = DllStructCreate("char[" & $iMaxLen & "]") EndIf If Not ___TCP_SetNonBlocking($hSocket) Then Return SetError(@error, 0, "") Local $aRet = DllCall($__TCP_hWs2_32, "int", "recv", "uint", $hSocket, "ptr", DllStructGetPtr($tBuf), "int", $iMaxLen, "int", 0) If @error Then Return SetError(-1, 0, "") If $aRet[0] = -1 Or $aRet[0] = 4294967295 Then Local $iError = ___TCP_WSAGetLastError() If $iError = 0 Or $iError = 10035 Then Return SetError(0, 0, "") ; WSAEWOULDBLOCK - no data Return SetError($iError, 0, "") EndIf If $aRet[0] = 0 Then Return SetError(0, 1, "") ; Connection closed Local $sResult = DllStructGetData($tBuf, 1) If BitAND($iFlag, $TCP_EOT_DATA) Then If StringRight($sResult, 1) = Chr(3) Then $sResult = StringTrimRight($sResult, 1) Return SetError(0, 2, $sResult) ; EOT reached EndIf EndIf Return SetError(0, 0, $sResult) EndFunc ;==>_TCP_Recv ; #FUNCTION# ==================================================================================================================== ; Name ..........: _TCP_Server_OnNewClient ; Description ...: Register callback when new client connects ; Syntax ........: _TCP_Server_OnNewClient($hServerSocket, $sFunction) ; Parameters ....: $hServerSocket - Server socket handle ; $sFunction - Callback function name: Func OnNewClient($hClientSocket, $iError) ; Return values .: Success - 1 ; Failure - 0 and sets @error ; Example .......: _TCP_Server_OnNewClient($hServer, "OnNewClient") ; Func OnNewClient($hClient, $iError) ; If $iError Then ConsoleWrite("Accept error: " & $iError & @CRLF) ; Else ConsoleWrite("New client: " & $hClient & @CRLF) ; EndFunc ; =============================================================================================================================== Func _TCP_Server_OnNewClient($hServerSocket, $sFunction) Return _TCP_RegisterEvent($hServerSocket, $TCP_EVENT_NEWCLIENT, $sFunction) EndFunc ;==>_TCP_Server_OnNewClient ; #FUNCTION# ==================================================================================================================== ; Name ..........: _TCP_Server_OnReceive ; Description ...: Register callback when server receives data from client ; Syntax ........: _TCP_Server_OnReceive($hServerSocket, $sFunction) ; Parameters ....: $hServerSocket - Server socket handle ; $sFunction - Callback function name: Func OnReceive($hClientSocket, $sData, $iError) ; Return values .: Success - 1 ; Failure - 0 and sets @error ; Example .......: _TCP_Server_OnReceive($hServer, "OnReceive") ; Func OnReceive($hClient, $sData, $iError) ; If Not $iError Then _TCP_Send($hClient, "Echo: " & $sData) ; EndFunc ; =============================================================================================================================== Func _TCP_Server_OnReceive($hServerSocket, $sFunction) Return _TCP_RegisterEvent($hServerSocket, $TCP_EVENT_RECEIVE, $sFunction) EndFunc ;==>_TCP_Server_OnReceive ; #FUNCTION# ==================================================================================================================== ; Name ..........: _TCP_Server_OnSend ; Description ...: Register callback when server is ready to send data ; Syntax ........: _TCP_Server_OnSend($hServerSocket, $sFunction) ; Parameters ....: $hServerSocket - Server socket handle ; $sFunction - Callback function name: Func OnSend($hClientSocket, $iError) ; Return values .: Success - 1 ; Failure - 0 and sets @error ; Example .......: _TCP_Server_OnSend($hServer, "OnSend") ; Func OnSend($hClient, $iError) ; If Not $iError Then ConsoleWrite("Ready to send on: " & $hClient & @CRLF) ; EndFunc ; =============================================================================================================================== Func _TCP_Server_OnSend($hServerSocket, $sFunction) Return _TCP_RegisterEvent($hServerSocket, $TCP_EVENT_SEND, $sFunction) EndFunc ;==>_TCP_Server_OnSend ; #FUNCTION# ==================================================================================================================== ; Name ..........: _TCP_Server_OnDisconnect ; Description ...: Register callback when client disconnects ; Syntax ........: _TCP_Server_OnDisconnect($hServerSocket, $sFunction) ; Parameters ....: $hServerSocket - Server socket handle ; $sFunction - Callback function name: Func OnDisconnect($hClientSocket, $iError) ; Return values .: Success - 1 ; Failure - 0 and sets @error ; Example .......: _TCP_Server_OnDisconnect($hServer, "OnDisconnect") ; Func OnDisconnect($hClient, $iError) ; ConsoleWrite("Client disconnected: " & $hClient & @CRLF) ; EndFunc ; =============================================================================================================================== Func _TCP_Server_OnDisconnect($hServerSocket, $sFunction) Return _TCP_RegisterEvent($hServerSocket, $TCP_EVENT_DISCONNECT, $sFunction) EndFunc ;==>_TCP_Server_OnDisconnect ; #FUNCTION# ==================================================================================================================== ; Name ..........: _TCP_Client_OnConnect ; Description ...: Register callback when client connection succeeds/fails ; Syntax ........: _TCP_Client_OnConnect($hClientSocket, $sFunction) ; Parameters ....: $hClientSocket - Client socket handle ; $sFunction - Callback function name: Func OnConnect($hSocket, $iError) ; Return values .: Success - 1 ; Failure - 0 and sets @error ; Example .......: _TCP_Client_OnConnect($hClient, "OnConnect") ; Func OnConnect($hSocket, $iError) ; If $iError Then ConsoleWrite("Connect failed: " & $iError & @CRLF) ; Else ConsoleWrite("Connected successfully!" & @CRLF) ; EndFunc ; =============================================================================================================================== Func _TCP_Client_OnConnect($hClientSocket, $sFunction) Return _TCP_RegisterEvent($hClientSocket, $TCP_EVENT_CONNECT, $sFunction) EndFunc ;==>_TCP_Client_OnConnect ; #FUNCTION# ==================================================================================================================== ; Name ..........: _TCP_Client_OnReceive ; Description ...: Register callback when client receives data from server ; Syntax ........: _TCP_Client_OnReceive($hClientSocket, $sFunction) ; Parameters ....: $hClientSocket - Client socket handle ; $sFunction - Callback function name: Func OnReceive($hSocket, $sData, $iError) ; Return values .: Success - 1 ; Failure - 0 and sets @error ; Example .......: _TCP_Client_OnReceive($hClient, "OnReceive") ; Func OnReceive($hSocket, $sData, $iError) ; If Not $iError Then ConsoleWrite("Received: " & $sData & @CRLF) ; EndFunc ; =============================================================================================================================== Func _TCP_Client_OnReceive($hClientSocket, $sFunction) Return _TCP_RegisterEvent($hClientSocket, $TCP_EVENT_RECEIVE, $sFunction) EndFunc ;==>_TCP_Client_OnReceive ; #FUNCTION# ==================================================================================================================== ; Name ..........: _TCP_Client_OnSend ; Description ...: Register callback when client is ready to send data ; Syntax ........: _TCP_Client_OnSend($hClientSocket, $sFunction) ; Parameters ....: $hClientSocket - Client socket handle ; $sFunction - Callback function name: Func OnSend($hSocket, $iError) ; Return values .: Success - 1 ; Failure - 0 and sets @error ; Example .......: _TCP_Client_OnSend($hClient, "OnSend") ; Func OnSend($hSocket, $iError) ; If Not $iError Then ConsoleWrite("Ready to send" & @CRLF) ; EndFunc ; =============================================================================================================================== Func _TCP_Client_OnSend($hClientSocket, $sFunction) Return _TCP_RegisterEvent($hClientSocket, $TCP_EVENT_SEND, $sFunction) EndFunc ;==>_TCP_Client_OnSend ; #FUNCTION# ==================================================================================================================== ; Name ..........: _TCP_Client_OnDisconnect ; Description ...: Register callback when client disconnects ; Syntax ........: _TCP_Client_OnDisconnect($hClientSocket, $sFunction) ; Parameters ....: $hClientSocket - Client socket handle ; $sFunction - Callback function name: Func OnDisconnect($hSocket, $iError) ; Return values .: Success - 1 ; Failure - 0 and sets @error ; Example .......: _TCP_Client_OnDisconnect($hClient, "OnDisconnect") ; Func OnDisconnect($hSocket, $iError) ; ConsoleWrite("Disconnected from server" & @CRLF) ; EndFunc ; =============================================================================================================================== Func _TCP_Client_OnDisconnect($hClientSocket, $sFunction) Return _TCP_RegisterEvent($hClientSocket, $TCP_EVENT_DISCONNECT, $sFunction) EndFunc ;==>_TCP_Client_OnDisconnect ; #FUNCTION# ==================================================================================================================== ; Name ..........: _TCP_OnConnect ; Description ...: Alias of _TCP_Client_OnConnect for simpler syntax ; Syntax ........: _TCP_OnConnect($hSocket, $sFunction) ; Parameters ....: $hSocket - Socket handle ; $sFunction - Callback function name ; Return values .: Success - 1 ; Failure - 0 and sets @error ; =============================================================================================================================== Func _TCP_OnConnect($hSocket, $sFunction) Return _TCP_Client_OnConnect($hSocket, $sFunction) EndFunc ;==>_TCP_OnConnect ; #FUNCTION# ==================================================================================================================== ; Name ..........: _TCP_OnReceive ; Description ...: Universal callback for both client and server ; Syntax ........: _TCP_OnReceive($hSocket, $sFunction) ; Parameters ....: $hSocket - Socket handle (client or server) ; $sFunction - Callback function name ; Return values .: Success - 1 ; Failure - 0 and sets @error ; Remarks .......: Can be used for both client and server sockets ; =============================================================================================================================== Func _TCP_OnReceive($hSocket, $sFunction) Return _TCP_RegisterEvent($hSocket, $TCP_EVENT_RECEIVE, $sFunction) EndFunc ;==>_TCP_OnReceive ; #FUNCTION# ==================================================================================================================== ; Name ..........: _TCP_OnSend ; Description ...: Universal callback for both client and server ; Syntax ........: _TCP_OnSend($hSocket, $sFunction) ; Parameters ....: $hSocket - Socket handle (client or server) ; $sFunction - Callback function name ; Return values .: Success - 1 ; Failure - 0 and sets @error ; =============================================================================================================================== Func _TCP_OnSend($hSocket, $sFunction) Return _TCP_RegisterEvent($hSocket, $TCP_EVENT_SEND, $sFunction) EndFunc ;==>_TCP_OnSend ; #FUNCTION# ==================================================================================================================== ; Name ..........: _TCP_OnDisconnect ; Description ...: Universal callback for both client and server ; Syntax ........: _TCP_OnDisconnect($hSocket, $sFunction) ; Parameters ....: $hSocket - Socket handle (client or server) ; $sFunction - Callback function name ; Return values .: Success - 1 ; Failure - 0 and sets @error ; =============================================================================================================================== Func _TCP_OnDisconnect($hSocket, $sFunction) Return _TCP_RegisterEvent($hSocket, $TCP_EVENT_DISCONNECT, $sFunction) EndFunc ;==>_TCP_OnDisconnect ; #FUNCTION# ==================================================================================================================== ; Name ..........: _TCP_RegisterEvent ; Description ...: Internal function to register event callbacks ; Syntax ........: _TCP_RegisterEvent($hSocket, $iEvent, $sFunction) ; Parameters ....: $hSocket - Socket handle ; $iEvent - Event type constant ; $sFunction - Callback function name ; Return values .: Success - 1 ; Failure - 0 and sets @error ; Remarks .......: This is an internal function. Use specific _TCP_*_On* functions instead ; =============================================================================================================================== Func _TCP_RegisterEvent($hSocket, $iEvent, $sFunction) Local $idx = ___TCP_FindSocket($hSocket) If $idx < 0 Then Return SetError(-4, 0, 0) Switch $iEvent Case $TCP_EVENT_SEND $__TCP_Sockets[$idx][3] = $sFunction Case $TCP_EVENT_RECEIVE $__TCP_Sockets[$idx][2] = $sFunction Case $TCP_EVENT_CONNECT $__TCP_Sockets[$idx][4] = $sFunction Case $TCP_EVENT_DISCONNECT $__TCP_Sockets[$idx][5] = $sFunction Case $TCP_EVENT_NEWCLIENT $__TCP_Sockets[$idx][6] = $sFunction Case Else Return SetError(-4, 0, 0) EndSwitch Return 1 EndFunc ;==>_TCP_RegisterEvent ; #FUNCTION# ==================================================================================================================== ; Name ..........: _TCP_Server_ClientList ; Description ...: Get list of client sockets ; Syntax ........: _TCP_Server_ClientList() ; Return values .: Array of client sockets, [0] = count ; =============================================================================================================================== Func _TCP_Server_ClientList() Local $aClients[1] = [0] For $i = 0 To UBound($__TCP_Sockets) - 1 If $__TCP_Sockets[$i][0] And Not $__TCP_Sockets[$i][9] Then ; Not a server socket ReDim $aClients[UBound($aClients) + 1] $aClients[UBound($aClients) - 1] = $__TCP_Sockets[$i][0] $aClients[0] += 1 EndIf Next Return $aClients EndFunc ;==>_TCP_Server_ClientList ; #FUNCTION# ==================================================================================================================== ; Name ..........: _TCP_Server_ClientIP ; Description ...: Get IP address of client ; Syntax ........: _TCP_Server_ClientIP($hSocket) ; Parameters ....: $hSocket - Client socket handle ; Return values .: Success - IP address string ; Failure - "" and sets @error ; =============================================================================================================================== Func _TCP_Server_ClientIP($hSocket) Local $tSockAddr = DllStructCreate("short;ushort;uint;char[8]") Local $aRet = DllCall($__TCP_hWs2_32, "int", "getpeername", "int", $hSocket, "ptr", DllStructGetPtr($tSockAddr), "int*", DllStructGetSize($tSockAddr)) If @error Or $aRet[0] <> 0 Then Return SetError(-1, 0, "") $aRet = DllCall($__TCP_hWs2_32, "str", "inet_ntoa", "int", DllStructGetData($tSockAddr, 3)) If @error Then Return SetError(-1, 0, "") Return $aRet[0] EndFunc ;==>_TCP_Server_ClientIP ; #FUNCTION# ==================================================================================================================== ; Name ..........: _TCP_Server_Broadcast ; Description ...: Send data to all clients ; Syntax ........: _TCP_Server_Broadcast($vData) ; Parameters ....: $vData - Data to broadcast ; Return values .: Number of clients sent to ; =============================================================================================================================== Func _TCP_Server_Broadcast($vData) Local $iCount = 0 For $i = 0 To UBound($__TCP_Sockets) - 1 If $__TCP_Sockets[$i][0] And Not $__TCP_Sockets[$i][9] Then TCPSend($__TCP_Sockets[$i][0], $vData) $iCount += 1 EndIf Next Return $iCount EndFunc ;==>_TCP_Server_Broadcast ; #FUNCTION# ==================================================================================================================== ; Name ..........: _TCP_Server_DisconnectClient ; Description ...: Disconnect a client ; Syntax ........: _TCP_Server_DisconnectClient($hSocket) ; Parameters ....: $hSocket - Client socket handle ; Return values .: Success - 1 ; Failure - 0 and sets @error ; =============================================================================================================================== Func _TCP_Server_DisconnectClient($hSocket) Return _TCP_Client_Stop($hSocket) EndFunc ;==>_TCP_Server_DisconnectClient ; #FUNCTION# ==================================================================================================================== ; Name ..........: _TCP_NameToIP ; Description ...: Convert hostname to IP address ; Syntax ........: _TCP_NameToIP($sName) ; Parameters ....: $sName - Hostname ; Return values .: Success - IP address ; Failure - "" and sets @error ; =============================================================================================================================== Func _TCP_NameToIP($sName) Local $sIP = TCPNameToIP($sName) Return SetError(@error, 0, $sIP) EndFunc ;==>_TCP_NameToIP ; #FUNCTION# ==================================================================================================================== ; Name ..........: _TCP_GetIPs ; Description ...: Get local and public IP addresses ; Syntax ........: _TCP_GetIPs([$sServerName = ""]) ; Parameters ....: $sServerName - [optional] Server to check public IP ; Return values .: Success - Array [localIP, publicIP] ; Failure - -1 and sets @error ; =============================================================================================================================== Func _TCP_GetIPs($sServerName = "") If Not $__TCP_Initialized Then If Not _TCP_Startup() Then Return SetError(@error, 0, -1) EndIf Local $aServers[][2] = [["www.myexternalip.com/raw"], ["checkip.dyndns.org/"], ["bot.whatismyipaddress.com/"]] If $sServerName <> "" Then ReDim $aServers[UBound($aServers) + 1][2] $aServers[UBound($aServers) - 1][0] = $sServerName EndIf Local $sLocalIP = "", $sPublicIP = "" Local $hSocket = ___TCP_Socket() If @error Then Return SetError(@error, 0, -1) For $i = 0 To UBound($aServers) - 1 Local $sHost = StringRegExp($aServers[$i][0], "^([^/]+)", 1) If @error Then ContinueLoop $sHost = $sHost[0] Local $sServerIP = TCPNameToIP($sHost) If $sServerIP = "" Then ContinueLoop ; Connect Local $tSockAddr = ___TCP_SockAddr($sServerIP, 80) If @error Then ContinueLoop ___TCP_SetNonBlocking($hSocket) DllCall($__TCP_hWs2_32, "int", "connect", "uint", $hSocket, "ptr", DllStructGetPtr($tSockAddr), "int", DllStructGetSize($tSockAddr)) ; Wait for connection If Not ___TCP_WaitForConnect($hSocket, 2000) Then ___TCP_CloseSocket($hSocket) $hSocket = ___TCP_Socket() ContinueLoop EndIf ; Get local IP If $sLocalIP = "" Then Local $tLocalAddr = DllStructCreate("short;ushort;uint;char[8]") Local $aRet = DllCall($__TCP_hWs2_32, "int", "getsockname", "uint", $hSocket, "ptr", DllStructGetPtr($tLocalAddr), "int*", DllStructGetSize($tLocalAddr)) If Not @error And $aRet[0] = 0 Then $aRet = DllCall($__TCP_hWs2_32, "ptr", "inet_ntoa", "ulong", DllStructGetData($tLocalAddr, 3)) If Not @error And $aRet[0] <> Null Then $sLocalIP = DllStructGetData(DllStructCreate("char[15]", $aRet[0]), 1) EndIf EndIf EndIf ; Get public IP Local $sRequest = "GET /" & StringRegExpReplace($aServers[$i][0], "^[^/]+/?", "") & " HTTP/1.1" & @CRLF & _ "Host: " & $sHost & @CRLF & _ "Connection: close" & @CRLF & @CRLF TCPSend($hSocket, $sRequest) Sleep(500) Local $sRecv = "" Local $hTimer = TimerInit() While TimerDiff($hTimer) < 3000 Local $sChunk = _TCP_Recv($hSocket, 2048) If @extended = 1 Then ExitLoop ; Connection closed $sRecv &= $sChunk If $sChunk = "" Then Sleep(10) WEnd Local $aIP = StringRegExp($sRecv, "((?:\d{1,3}\.){3}\d{1,3})", 3) If Not @error And UBound($aIP) > 0 Then $sPublicIP = $aIP[0] ExitLoop EndIf ___TCP_CloseSocket($hSocket) $hSocket = ___TCP_Socket() Next ___TCP_CloseSocket($hSocket) If $sLocalIP = "" Or $sPublicIP = "" Then Return SetError(-6, 0, -1) Local $aResult[2] = [$sLocalIP, $sPublicIP] Return $aResult EndFunc ;==>_TCP_GetIPs ; #UDP FUNCTIONS# =============================================================================================================== ; #FUNCTION# ==================================================================================================================== ; Name ..........: _UDP_Startup ; Description ...: Initialize UDP system ; Syntax ........: _UDP_Startup() ; Return values .: Success - 1 ; Failure - 0 and sets @error ; =============================================================================================================================== Func _UDP_Startup() Local $iResult = UDPStartup() Return SetError(@error, 0, $iResult) EndFunc ;==>_UDP_Startup ; #FUNCTION# ==================================================================================================================== ; Name ..........: _UDP_Shutdown ; Description ...: Shutdown UDP system ; Syntax ........: _UDP_Shutdown() ; Return values .: Success - 1 ; Failure - 0 and sets @error ; =============================================================================================================================== Func _UDP_Shutdown() Local $iResult = UDPShutdown() Return SetError(@error, 0, $iResult) EndFunc ;==>_UDP_Shutdown ; #FUNCTION# ==================================================================================================================== ; Name ..........: _UDP_Bind ; Description ...: Create and bind UDP socket ; Syntax ........: _UDP_Bind([$sSourceIP = ""[, $iSourcePort = 0]]) ; Parameters ....: $sSourceIP - [optional] Local IP to bind (default = "") ; $iSourcePort - [optional] Local port to bind (default = 0) ; Return values .: Success - Socket handle ; Failure - -1 and sets @error ; =============================================================================================================================== Func _UDP_Bind($sSourceIP = "", $iSourcePort = 0) If Not $__TCP_Initialized Then If Not _TCP_Startup() Then Return SetError(@error, 0, -1) EndIf If Not ($iSourcePort >= 0 And $iSourcePort < 65535) Then Return SetError(-4, 0, -1) Local $aRet = DllCall($__TCP_hWs2_32, "uint", "socket", "int", 2, "int", 2, "int", 17) ; AF_INET, SOCK_DGRAM, IPPROTO_UDP If @error Then Return SetError(-1, 0, -1) If $aRet[0] = 4294967295 Or $aRet[0] = -1 Then Return SetError(-1, ___TCP_WSAGetLastError(), -1) Local $hSocket = $aRet[0] ; Bind if IP or port specified If $sSourceIP <> "" Or $iSourcePort > 0 Then Local $tSockAddr = ___TCP_SockAddr($sSourceIP <> "" ? $sSourceIP : "0.0.0.0", $iSourcePort) If @error Then ___TCP_CloseSocket($hSocket) Return SetError(@error, 0, -1) EndIf $aRet = DllCall($__TCP_hWs2_32, "int", "bind", "uint", $hSocket, "ptr", DllStructGetPtr($tSockAddr), "int", DllStructGetSize($tSockAddr)) If @error Or $aRet[0] <> 0 Then ___TCP_CloseSocket($hSocket) Return SetError(-1, ___TCP_WSAGetLastError(), -1) EndIf EndIf Return $hSocket EndFunc ;==>_UDP_Bind ; #FUNCTION# ==================================================================================================================== ; Name ..........: _UDP_SendTo ; Description ...: Send UDP packet to specified address ; Syntax ........: _UDP_SendTo($sIP, $iPort, $vData[, $hSocket = 0]) ; Parameters ....: $sIP - Destination IP address ; $iPort - Destination port ; $vData - Data to send (string or binary) ; $hSocket - [optional] Socket handle (0 = create temporary socket) ; Return values .: Success - Array [bytes_sent, socket_handle] ; Failure - -1 and sets @error ; =============================================================================================================================== Func _UDP_SendTo($sIP, $iPort, $vData, $hSocket = 0) If Not $__TCP_Initialized Then If Not _TCP_Startup() Then Return SetError(@error, 0, -1) EndIf If Not ($iPort > 0 And $iPort < 65535) Then Return SetError(-4, 0, -1) Local $bCloseAfter = False If $hSocket = 0 Then $hSocket = _UDP_Bind() If @error Then Return SetError(@error, 0, -1) $bCloseAfter = True EndIf Local $tSockAddr = ___TCP_SockAddr($sIP, $iPort) If @error Then If $bCloseAfter Then ___TCP_CloseSocket($hSocket) Return SetError(@error, 0, -1) EndIf Local $tBuf, $iLen If IsBinary($vData) Then $iLen = BinaryLen($vData) $tBuf = DllStructCreate("byte[" & $iLen & "]") DllStructSetData($tBuf, 1, $vData) Else $vData = String($vData) $iLen = StringLen($vData) $tBuf = DllStructCreate("char[" & $iLen & "]") DllStructSetData($tBuf, 1, $vData) EndIf ___TCP_SetNonBlocking($hSocket) Local $aRet = DllCall($__TCP_hWs2_32, "int", "sendto", _ "uint", $hSocket, "ptr", DllStructGetPtr($tBuf), "int", $iLen, "int", 0, _ "ptr", DllStructGetPtr($tSockAddr), "int", DllStructGetSize($tSockAddr)) If @error Or $aRet[0] = -1 Or $aRet[0] = 4294967295 Then Local $iError = ___TCP_WSAGetLastError() If $bCloseAfter Then ___TCP_CloseSocket($hSocket) Return SetError($iError, 0, -1) EndIf Local $aResult[2] = [$aRet[0], $hSocket] If $bCloseAfter Then ___TCP_CloseSocket($hSocket) Return $aResult EndFunc ;==>_UDP_SendTo ; #FUNCTION# ==================================================================================================================== ; Name ..........: _UDP_RecvFrom ; Description ...: Receive UDP packet ; Syntax ........: _UDP_RecvFrom($hSocket, $iMaxLen[, $iFlag = 0]) ; Parameters ....: $hSocket - Socket handle ; $iMaxLen - Max bytes to receive ; $iFlag - [optional] 0 = string, 1 = binary ; Return values .: Success - Array [data, source_ip, source_port] ; Failure - -1 and sets @error ; =============================================================================================================================== Func _UDP_RecvFrom($hSocket, $iMaxLen, $iFlag = 0) If Not $__TCP_Initialized Then Return SetError(-1, 0, -1) If $iMaxLen < 1 Then Return SetError(-4, 0, -1) If $iFlag <> 0 And $iFlag <> 1 Then Return SetError(-4, 0, -1) ___TCP_SetNonBlocking($hSocket) Local $tSockAddr = DllStructCreate("short;ushort;uint;char[8]") Local $tBuf If $iFlag = 1 Then $tBuf = DllStructCreate("byte[" & $iMaxLen & "]") Else $tBuf = DllStructCreate("char[" & $iMaxLen & "]") EndIf Local $aRet = DllCall($__TCP_hWs2_32, "int", "recvfrom", _ "uint", $hSocket, "ptr", DllStructGetPtr($tBuf), "int", $iMaxLen, "int", 0, _ "ptr", DllStructGetPtr($tSockAddr), "int*", DllStructGetSize($tSockAddr)) If @error Then Return SetError(-1, 0, -1) If $aRet[0] = -1 Or $aRet[0] = 4294967295 Then Local $iError = ___TCP_WSAGetLastError() If $iError = 0 Or $iError = 10035 Then Return SetError(0, 0, -1) ; WSAEWOULDBLOCK Return SetError($iError, 0, -1) EndIf Local $aResult[3] $aResult[0] = DllStructGetData($tBuf, 1) $aRet = DllCall($__TCP_hWs2_32, "ptr", "inet_ntoa", "ulong", DllStructGetData($tSockAddr, 3)) If @error Or $aRet[0] = Null Then Return SetError(-1, 0, -1) $aResult[1] = DllStructGetData(DllStructCreate("char[15]", $aRet[0]), 1) $aRet = DllCall($__TCP_hWs2_32, "ushort", "ntohs", "ushort", DllStructGetData($tSockAddr, 2)) If @error Then Return SetError(-1, 0, -1) $aResult[2] = $aRet[0] Return $aResult EndFunc ;==>_UDP_RecvFrom ; #FUNCTION# ==================================================================================================================== ; Name ..........: _UDP_CloseSocket ; Description ...: Close UDP socket ; Syntax ........: _UDP_CloseSocket($vSocket) ; Parameters ....: $vSocket - Socket handle or array from _UDP_SendTo ; Return values .: Success - 1 ; Failure - 0 and sets @error ; =============================================================================================================================== Func _UDP_CloseSocket($vSocket) Local $hSocket If IsArray($vSocket) And UBound($vSocket) = 2 Then $hSocket = $vSocket[1] Else $hSocket = $vSocket EndIf If $hSocket < 1 Then Return SetError(-4, 0, 0) Local $aRet = DllCall($__TCP_hWs2_32, "int", "closesocket", "uint", $hSocket) If @error Or $aRet[0] <> 0 Then Return SetError(___TCP_WSAGetLastError(), 0, 0) EndIf Return 1 EndFunc ;==>_UDP_CloseSocket ; #INTERNAL FUNCTIONS# ========================================================================================================== Func ___TCP_Socket() Local $aRet = DllCall($__TCP_hWs2_32, "uint", "socket", "int", 2, "int", 1, "int", 6) ; AF_INET, SOCK_STREAM, IPPROTO_TCP If @error Then Return SetError(-1, 0, -1) If $aRet[0] = 4294967295 Or $aRet[0] = -1 Then Return SetError(-1, ___TCP_WSAGetLastError(), -1) Return $aRet[0] EndFunc ;==>___TCP_Socket Func ___TCP_CloseSocket($hSocket) DllCall($__TCP_hWs2_32, "int", "closesocket", "uint", $hSocket) Return TCPCloseSocket($hSocket) EndFunc ;==>___TCP_CloseSocket Func ___TCP_Shutdown($hSocket) DllCall($__TCP_hWs2_32, "int", "shutdown", "uint", $hSocket, "int", 2) ; SD_BOTH EndFunc ;==>___TCP_Shutdown Func ___TCP_SockAddr($sIP, $iPort) Local $tAddr = DllStructCreate("short sin_family;ushort sin_port;uint S_addr;char sin_zero[8]") If @error Then Return SetError(-1, 0, False) DllStructSetData($tAddr, "sin_family", 2) ; AF_INET Local $aRet = DllCall($__TCP_hWs2_32, "ushort", "htons", "ushort", $iPort) If @error Then Return SetError(-1, 0, False) DllStructSetData($tAddr, "sin_port", $aRet[0]) If $sIP = "" Or $sIP = "0.0.0.0" Then DllStructSetData($tAddr, "S_addr", 0x00000000) Else $aRet = DllCall($__TCP_hWs2_32, "ulong", "inet_addr", "str", $sIP) If @error Or $aRet[0] = -1 Or $aRet[0] = 4294967295 Then Return SetError(-4, 0, False) DllStructSetData($tAddr, "S_addr", $aRet[0]) EndIf Return $tAddr EndFunc ;==>___TCP_SockAddr Func ___TCP_SetNonBlocking($hSocket) Local $aRet = DllCall($__TCP_hWs2_32, "int", "ioctlsocket", "uint", $hSocket, "long", 0x8004667e, "ulong*", 1) ; FIONBIO If @error Or $aRet[0] <> 0 Then Return SetError(-1, ___TCP_WSAGetLastError(), False) Return True EndFunc ;==>___TCP_SetNonBlocking Func ___TCP_AsyncSelect($hSocket, $hWnd, $iMsg, $iEvents) ; WSAAsyncSelect automatically sets socket to non-blocking mode Local $aRet = DllCall($__TCP_hWs2_32, "int", "WSAAsyncSelect", _ "uint", $hSocket, "hwnd", $hWnd, "uint", $iMsg, "int", $iEvents) If @error Or $aRet[0] <> 0 Then Return SetError(-1, ___TCP_WSAGetLastError(), False) Return True EndFunc ;==>___TCP_AsyncSelect Func ___TCP_WaitForConnect($hSocket, $iTimeout) Local $tFdWrite = DllStructCreate("uint fd_count;uint fd_array[64]") Local $tFdExcept = DllStructCreate("uint fd_count;uint fd_array[64]") Local $tTimeval = DllStructCreate("long tv_sec;long tv_usec") DllStructSetData($tFdWrite, "fd_count", 1) DllStructSetData($tFdWrite, "fd_array", $hSocket, 1) DllStructSetData($tFdExcept, "fd_count", 1) DllStructSetData($tFdExcept, "fd_array", $hSocket, 1) DllStructSetData($tTimeval, "tv_sec", Floor($iTimeout / 1000)) DllStructSetData($tTimeval, "tv_usec", Mod($iTimeout, 1000) * 1000) Local $aRet = DllCall($__TCP_hWs2_32, "int", "select", _ "int", 0, "ptr", 0, "ptr", DllStructGetPtr($tFdWrite), _ "ptr", DllStructGetPtr($tFdExcept), "ptr", DllStructGetPtr($tTimeval)) If @error Then Return SetError(-1, 0, False) If $aRet[0] = 0 Then Return SetError(-6, 0, False) ; Timeout If $aRet[0] = -1 Then Return SetError(-1, ___TCP_WSAGetLastError(), False) ; Check if connected or error If DllStructGetData($tFdWrite, "fd_count") = 1 Then Return True If DllStructGetData($tFdExcept, "fd_count") = 1 Then Local $tErr = DllStructCreate("int") $aRet = DllCall($__TCP_hWs2_32, "int", "getsockopt", _ "uint", $hSocket, "int", 0xFFFF, "int", 0x1007, _ "ptr", DllStructGetPtr($tErr), "int*", DllStructGetSize($tErr)) ; SOL_SOCKET, SO_ERROR If Not @error And $aRet[0] = 0 Then Return SetError(DllStructGetData($tErr, 1), 0, False) EndIf EndIf Return SetError(-5, 0, False) ; Not connected EndFunc ;==>___TCP_WaitForConnect Func ___TCP_WSAGetLastError() Local $aRet = DllCall($__TCP_hWs2_32, "int", "WSAGetLastError") If @error Then Return 0 Return $aRet[0] EndFunc ;==>___TCP_WSAGetLastError Func ___TCP_FindSocket($hSocket) For $i = 0 To UBound($__TCP_Sockets) - 1 If $__TCP_Sockets[$i][0] = $hSocket Then Return $i Next Return -1 EndFunc ;==>___TCP_FindSocket Func ___TCP_LoWord($iValue) Return BitAND($iValue, 0xFFFF) EndFunc ;==>___TCP_LoWord Func ___TCP_HiWord($iValue) Return BitShift($iValue, 16) EndFunc ;==>___TCP_HiWord Func ___TCP_ArrayDelete(ByRef $aArray, $iElement) If Not IsArray($aArray) Then Return SetError(1, 0, 0) Local $iUBound = UBound($aArray, 1) - 1 If $iUBound < 0 Then Return 0 If $iElement < 0 Then $iElement = 0 If $iElement > $iUBound Then $iElement = $iUBound Switch UBound($aArray, 0) Case 1 For $i = $iElement To $iUBound - 1 $aArray[$i] = $aArray[$i + 1] Next ReDim $aArray[$iUBound] Case 2 Local $iSubMax = UBound($aArray, 2) - 1 For $i = $iElement To $iUBound - 1 For $j = 0 To $iSubMax $aArray[$i][$j] = $aArray[$i + 1][$j] Next Next ReDim $aArray[$iUBound][$iSubMax + 1] Case Else Return SetError(3, 0, 0) EndSwitch Return $iUBound EndFunc ;==>___TCP_ArrayDelete ; #ASYNC EVENT HANDLERS# ======================================================================================================== Func ___TCP_Server_OnAccept($hWnd, $iMsgID, $wParam, $lParam) Local $hSocket = $wParam Local $iError = ___TCP_HiWord($lParam) Local $iEvent = ___TCP_LoWord($lParam) Abs($hWnd) ; Suppress AU3Check warning ; Find server socket Local $iServerIdx = -1 For $i = 0 To UBound($__TCP_Sockets) - 1 If $__TCP_Sockets[$i][1] = $iMsgID Then $iServerIdx = $i ExitLoop EndIf Next If $iServerIdx < 0 Then Return If $iEvent = $FD_ACCEPT Then If Not $iError Then Local $hClient = TCPAccept($hSocket) If $hClient < 0 Then Return ; Setup client async Local $iClientMsgID = 0x0400 + UBound($__TCP_Sockets) ___TCP_AsyncSelect($hClient, $__TCP_AsyncWindow, $iClientMsgID, BitOR($FD_READ, $FD_WRITE, $FD_CLOSE)) GUIRegisterMsg($iClientMsgID, "___TCP_Server_OnClientEvent") ; Store client ReDim $__TCP_Sockets[UBound($__TCP_Sockets) + 1][11] Local $idx = UBound($__TCP_Sockets) - 1 $__TCP_Sockets[$idx][0] = $hClient $__TCP_Sockets[$idx][1] = $iClientMsgID $__TCP_Sockets[$idx][7] = _TCP_Server_ClientIP($hClient) $__TCP_Sockets[$idx][9] = False ; isClient $__TCP_Sockets[$idx][10] = $hSocket ; parentServer ; Call callback If $__TCP_Sockets[$iServerIdx][6] <> "" Then Call($__TCP_Sockets[$iServerIdx][6], $hClient, $iError) EndIf Else ; Error accepting If $__TCP_Sockets[$iServerIdx][6] <> "" Then Call($__TCP_Sockets[$iServerIdx][6], 0, $iError) EndIf EndIf EndIf EndFunc ;==>___TCP_Server_OnAccept Func ___TCP_Server_OnClientEvent($hWnd, $iMsgID, $wParam, $lParam) Local $hSocket = $wParam Local $iError = ___TCP_HiWord($lParam) Local $iEvent = ___TCP_LoWord($lParam) Abs($hWnd) Local $iClientIdx = -1 For $i = 0 To UBound($__TCP_Sockets) - 1 If $__TCP_Sockets[$i][1] = $iMsgID Then $iClientIdx = $i ; BUG FIX: Don't override the actual socket handle from $wParam ; $hSocket = $__TCP_Sockets[$i][0] ; This was causing socket mismatch! ExitLoop EndIf Next If $iClientIdx < 0 Then Return ; Find parent server for this client - CRITICAL FIX for multi-server support Local $iServerIdx = -1 Local $hParentServer = $__TCP_Sockets[$iClientIdx][10] If $hParentServer > 0 Then ; Find the parent server by socket handle For $i = 0 To UBound($__TCP_Sockets) - 1 If $__TCP_Sockets[$i][0] = $hParentServer And $__TCP_Sockets[$i][9] Then $iServerIdx = $i ExitLoop EndIf Next EndIf If $iServerIdx < 0 Then Return Switch $iEvent Case $FD_READ Local $sData = TCPRecv($hSocket, 4096) If $__TCP_Sockets[$iServerIdx][2] <> "" Then Call($__TCP_Sockets[$iServerIdx][2], $hSocket, $sData, $iError) EndIf Case $FD_WRITE If $__TCP_Sockets[$iServerIdx][3] <> "" Then Call($__TCP_Sockets[$iServerIdx][3], $hSocket, $iError) EndIf Case $FD_CLOSE If $__TCP_Sockets[$iServerIdx][5] <> "" Then Call($__TCP_Sockets[$iServerIdx][5], $hSocket, $iError) EndIf ___TCP_Shutdown($hSocket) ___TCP_CloseSocket($hSocket) ___TCP_ArrayDelete($__TCP_Sockets, $iClientIdx) EndSwitch EndFunc ;==>___TCP_Server_OnClientEvent Func ___TCP_Client_OnSocketEvent($hWnd, $iMsgID, $wParam, $lParam) Local $hSocket = $wParam Local $iError = ___TCP_HiWord($lParam) Local $iEvent = ___TCP_LoWord($lParam) Abs($hWnd) Local $iClientIdx = -1 For $i = 0 To UBound($__TCP_Sockets) - 1 If $__TCP_Sockets[$i][1] = $iMsgID Then $iClientIdx = $i ; BUG FIX: Don't override the actual socket handle from $wParam ; $hSocket = $__TCP_Sockets[$i][0] ; This was causing socket mismatch! ExitLoop EndIf Next If $iClientIdx < 0 Then Return Switch $iEvent Case $FD_CONNECT ; Connection completed (success or failure) If $__TCP_Sockets[$iClientIdx][4] <> "" Then Call($__TCP_Sockets[$iClientIdx][4], $hSocket, $iError) EndIf Case $FD_READ Local $sData = TCPRecv($hSocket, 4096) If $__TCP_Sockets[$iClientIdx][2] <> "" Then Call($__TCP_Sockets[$iClientIdx][2], $hSocket, $sData, $iError) EndIf Case $FD_WRITE If $__TCP_Sockets[$iClientIdx][3] <> "" Then Call($__TCP_Sockets[$iClientIdx][3], $hSocket, $iError) EndIf Case $FD_CLOSE If $__TCP_Sockets[$iClientIdx][5] <> "" Then Call($__TCP_Sockets[$iClientIdx][5], $hSocket, $iError) EndIf ___TCP_Shutdown($hSocket) ___TCP_CloseSocket($hSocket) ___TCP_ArrayDelete($__TCP_Sockets, $iClientIdx) EndSwitch EndFunc ;==>___TCP_Client_OnSocketEvent ; #FUNCTION# ==================================================================================================================== ; Name ..........: _TCP_Send_Ex ; Description ...: Send data through socket with automatic Base64 encoding ; Syntax ........: _TCP_Send_Ex($hSocket, $vData[, $iFlag = 0]) ; Parameters ....: $hSocket - Socket handle ; $vData - Data to send (string or binary) - auto Base64 encoded ; $iFlag - [optional] $TCP_DEFAULT_DATA (0) or $TCP_EOT_DATA (2) ; Return values .: Success - Number of bytes sent ; Failure - -1 and sets @error ; =============================================================================================================================== Func _TCP_Send_Ex($hSocket, $vData, $iFlag = 0) ; Auto encode to Base64 Local $sEncoded = _Base64Encode($vData) If @error Then Return SetError(@error, 0, -1) If BitAND($iFlag, $TCP_EOT_DATA) Then $sEncoded = $sEncoded & Chr(3) Local $iResult = TCPSend($hSocket, $sEncoded) Return SetError(@error, 0, $iResult) EndFunc ;==>_TCP_Send_Ex ; #FUNCTION# ==================================================================================================================== ; Name ..........: _TCP_Recv_Ex ; Description ...: Receive data from socket with automatic Base64 decoding ; Syntax ........: _TCP_Recv_Ex($hSocket, $iMaxLen[, $iFlag = 0]) ; Parameters ....: $hSocket - Socket handle ; $iMaxLen - Max bytes to receive (after decoding) ; $iFlag - [optional] $TCP_DEFAULT_DATA (0), $TCP_BINARY_DATA (1), or $TCP_EOT_DATA (2) ; Return values .: Success - Data received (decoded from Base64) ; Failure - "" and sets @error/@extended ; Remarks .......: @extended = 1 if connection closed, = 2 if EOT reached ; Data is automatically decoded from Base64 ; =============================================================================================================================== Func _TCP_Recv_Ex($hSocket, $iMaxLen, $iFlag = 0) If Not $__TCP_Initialized Then Return SetError(-1, 0, "") ; Calculate buffer size for Base64 (encoded is ~33% larger) Local $iBase64MaxLen = Int($iMaxLen * 1.35) + 100 Local $tBuf = DllStructCreate("char[" & $iBase64MaxLen & "]") If Not ___TCP_SetNonBlocking($hSocket) Then Return SetError(@error, 0, "") Local $aRet = DllCall($__TCP_hWs2_32, "int", "recv", "uint", $hSocket, "ptr", DllStructGetPtr($tBuf), "int", $iBase64MaxLen, "int", 0) If @error Then Return SetError(-1, 0, "") If $aRet[0] = -1 Or $aRet[0] = 4294967295 Then Local $iError = ___TCP_WSAGetLastError() If $iError = 0 Or $iError = 10035 Then Return SetError(0, 0, "") ; WSAEWOULDBLOCK - no data Return SetError($iError, 0, "") EndIf If $aRet[0] = 0 Then Return SetError(0, 1, "") ; Connection closed Local $sBase64Result = DllStructGetData($tBuf, 1) ; Check for EOT marker Local $bHasEOT = False If BitAND($iFlag, $TCP_EOT_DATA) Then If StringRight($sBase64Result, 1) = Chr(3) Then $sBase64Result = StringTrimRight($sBase64Result, 1) $bHasEOT = True EndIf EndIf ; Auto decode from Base64 Local $sDecoded = _Base64Decode($sBase64Result, True) ; Convert to binary if requested If BitAND($iFlag, $TCP_BINARY_DATA) Then $sDecoded = Binary($sDecoded) EndIf If $bHasEOT Then Return SetError(0, 2, $sDecoded) ; EOT reached EndIf Return SetError(0, 0, $sDecoded) EndFunc ;==>_TCP_Recv_Ex ; #FUNCTION# ==================================================================================================================== ; Name ..........: _Base64Encode ; Description ...: Encode binary data to Base64 string ; Syntax ........: _Base64Encode($bInput[, $bNoCRLF = True]) ; Parameters ....: $bInput - Binary data to encode (can also accept ASCII string directly) ; $bNoCRLF - [optional] True: no line breaks, False: add CRLF every 76 chars (default = True) ; Return values .: Success - Base64 encoded string ; Failure - "" and sets @error ; Remarks .......: For ASCII strings, you can use this function directly. For UTF-8 strings, use _Base64EncodeStr() instead ; Author ........: Dao Van Trong - TRONG.PRO ; =============================================================================================================================== Func _Base64Encode($bInput, $bNoCRLF = True) $bInput = Binary($bInput) Local $iFlags = 1 ; CRYPT_STRING_BASE64 If $bNoCRLF Then $iFlags = 0x40000001 ; CRYPT_STRING_BASE64 | CRYPT_STRING_NOCRLF Local $tInput = DllStructCreate("byte[" & BinaryLen($bInput) & "]") DllStructSetData($tInput, 1, $bInput) ; Get required buffer size Local $aResult = DllCall("Crypt32.dll", "bool", "CryptBinaryToStringW", _ "struct*", $tInput, _ "dword", DllStructGetSize($tInput), _ "dword", $iFlags, _ "ptr", 0, _ "dword*", 0) If @error Or Not $aResult[0] Then Return SetError(1, 0, "") Local $iSize = $aResult[5] Local $tOutput = DllStructCreate("wchar[" & $iSize & "]") ; Perform encoding $aResult = DllCall("Crypt32.dll", "bool", "CryptBinaryToStringW", _ "struct*", $tInput, _ "dword", DllStructGetSize($tInput), _ "dword", $iFlags, _ "struct*", $tOutput, _ "dword*", $iSize) If @error Or Not $aResult[0] Then Return SetError(2, 0, "") Return DllStructGetData($tOutput, 1) EndFunc ;==>_Base64Encode ; #FUNCTION# ==================================================================================================================== ; Name ..........: _Base64Decode ; Description ...: Decode Base64 string to binary or string ; Syntax ........: _Base64Decode($sInput[, $bReturnBinary = False[, $iDecodeType = 1]]) ; Parameters ....: $sInput - Base64 string to decode ; $bReturnBinary - [optional] False: return string, True: return binary (default = False) ; $iDecodeType - [optional] 1: ASCII, 4: UTF-8 (default = 1, only used when $bReturnBinary = False) ; Return values .: Success - Binary data or string ; Failure - Binary("") and sets @error ; Remarks .......: For ASCII-only data, use default parameters. For UTF-8 data, use $iDecodeType = 4. For binary data, use $bReturnBinary = True ; Author ........: Dao Van Trong - TRONG.PRO ; =============================================================================================================================== Func _Base64Decode($sInput, $bReturnBinary = False, $iDecodeType = 1) If ($iDecodeType > 4) Or ($iDecodeType < 1) Then $iDecodeType = 4 ; Remove all whitespace and CRLF $sInput = StringRegExpReplace($sInput, "\s", "") If ($sInput = "") Then Return SetError(1, 0, ($bReturnBinary ? Binary("") : "")) Local $iFlags = 1 ; CRYPT_STRING_BASE64 ; Get required buffer size Local $aResult = DllCall("Crypt32.dll", "bool", "CryptStringToBinaryW", _ "wstr", $sInput, _ "dword", StringLen($sInput), _ "dword", $iFlags, _ "ptr", 0, _ "dword*", 0, _ "ptr", 0, _ "ptr", 0) If @error Or Not $aResult[0] Then Return SetError(2, 0, ($bReturnBinary ? Binary("") : "")) Local $iSize = $aResult[5] Local $tOutput = DllStructCreate("byte[" & $iSize & "]") ; Perform decoding $aResult = DllCall("Crypt32.dll", "bool", "CryptStringToBinaryW", _ "wstr", $sInput, _ "dword", StringLen($sInput), _ "dword", $iFlags, _ "struct*", $tOutput, _ "dword*", $iSize, _ "ptr", 0, _ "ptr", 0) If @error Or Not $aResult[0] Then Return SetError(3, 0, ($bReturnBinary ? Binary("") : "")) Local $bBinary = DllStructGetData($tOutput, 1) If $bReturnBinary Then Return $bBinary Else ; Convert binary to string with specified encoding Return BinaryToString($bBinary, $iDecodeType) EndIf EndFunc ;==>_Base64Decode ; #FUNCTION# ==================================================================================================================== ; Name ..........: _Base64EncodeStr ; Description ...: Encode string to Base64 ; Syntax ........: _Base64EncodeStr($sInput[, $iEncodeType = 4[, $bNoCRLF = True]]) ; Parameters ....: $sInput - String to encode ; $iEncodeType - [optional] 1: ASCII, 4: UTF-8 (default = 4) ; $bNoCRLF - [optional] True: no line breaks, False: add CRLF (default = True) ; Return values .: Success - Base64 encoded string ; Failure - "" and sets @error ; Author ........: Dao Van Trong - TRONG.PRO ; =============================================================================================================================== Func _Base64EncodeStr($sInput, $iEncodeType = 4, $bNoCRLF = True) If ($iEncodeType > 4) Or ($iEncodeType < 1) Then $iEncodeType = 4 Local $bBinary = StringToBinary($sInput, $iEncodeType) Return _Base64Encode($bBinary, $bNoCRLF) EndFunc ;==>_Base64EncodeStr ; #FUNCTION# ==================================================================================================================== ; Name ..........: _Base64DecodeStr ; Description ...: Decode Base64 string to text string ; Syntax ........: _Base64DecodeStr($sInput[, $iDecodeType = 4]) ; Parameters ....: $sInput - Base64 string to decode ; $iDecodeType - [optional] 1: ASCII, 4: UTF-8 (default = 4) ; Return values .: Success - Text string ; Failure - "" and sets @error ; Author ........: Dao Van Trong - TRONG.PRO ; =============================================================================================================================== Func _Base64DecodeStr($sInput, $iDecodeType = 4) Return _Base64Decode($sInput, False, $iDecodeType) EndFunc ;==>_Base64DecodeStr ; #FUNCTION# ==================================================================================================================== ; Name ..........: _PathWithSlash ; Description ...: Add single backslash to path if not present ; Syntax ........: _PathWithSlash($sPath) ; Parameters ....: $sPath - Path string ; Return values .: Path with trailing backslash ; Author ........: Dao Van Trong - TRONG.PRO ; =============================================================================================================================== Func _PathWithSlash($sPath) Return _PathRemoveTrail($sPath) & '\' EndFunc ;==>_PathWithSlash ; #FUNCTION# ==================================================================================================================== ; Name ..........: _PathRemoveTrail ; Description ...: Remove trailing backslashes from path ; Syntax ........: _PathRemoveTrail($sPath) ; Parameters ....: $sPath - Path string ; Return values .: Path without trailing backslashes ; Author ........: Dao Van Trong - TRONG.PRO ; =============================================================================================================================== Func _PathRemoveTrail($sPath) $sPath = StringStripWS($sPath, 3) While (StringRight($sPath, 1) == '\') $sPath = StringTrimRight($sPath, 1) WEnd Return $sPath EndFunc ;==>_PathRemoveTrail2 points
-
WinSockUDF - TCP/UDP Networking Library for AutoIt
argumentum and one other reacted to Trong for a topic
It was all my fault, I fixed it! I didn't know that the dark theme of the forum didn't invert the text colors (it seems unintelligent) Thank you all for your feedback2 points -
Avoid "AutoIt Error" message box in unknown errors
argumentum and one other reacted to Jos for a topic
I am just supporting the au3stripper questions in this thread. So without looking at the details it is pretty simple to me: Does the original script work?: if Yes: Does au3stripper run cleanly without any warnings? if Yes: The stripped script should work as the original if No: You are responsible and "don't come crying to me" when you override the default to continue with force! 😉2 points -
WinCred UDF - Windows Credential Management API
argumentum and one other reacted to DonChunior for a topic
Description WinCred is a User Defined Function (UDF) library for AutoIt that provides a complete interface to the Windows Credential Management API. This UDF allows you to create, read, update, and delete credentials stored in the Windows Credential Manager, which is the same secure storage system used by Windows itself for storing passwords and other sensitive information. Features Create and modify credentials using _WinCred_CredWrite Read credentials from the user's credential set with _WinCred_CredRead Delete credentials using _WinCred_CredDelete Support for all credential types (Generic, Domain Password, Certificates, etc.) Configurable persistence options (Session, Local Machine, Enterprise) Full Unicode support Comprehensive error handling with detailed error codes Complete example scripts for all functions Fully documented following AutoIt UDF standards Functions The UDF provides three main functions: _WinCred_CredWrite - Creates a new credential or modifies an existing credential in the user's credential set _WinCred_CredRead - Reads a credential from the user's credential set and returns an array with all credential information _WinCred_CredDelete - Deletes a credential from the user's credential set All functions follow AutoIt's standard error handling mechanism. For detailed syntax, parameters, and return values, please refer to the function documentation in the UDF file. Constants All constants are defined in WinCredConstants.au3, including credential types ($CRED_TYPE_*), persistence options ($CRED_PERSIST_*), and flags ($CRED_PRESERVE_CREDENTIAL_BLOB). See the constants file for a complete list. Quick Start Example #include "WinCred.au3" ; Create a credential Local $sTargetName = "MyApp-Credential" Local $sUserName = "MyUsername" Local $vPassword = Binary("MySecretPassword") If _WinCred_CredWrite($sTargetName, $CRED_TYPE_GENERIC, $sUserName, $vPassword) Then ConsoleWrite("Credential created successfully!" & @CRLF) Else ConsoleWrite("Error creating credential: " & @error & @CRLF) EndIf ; Read the credential Local $aCredential = _WinCred_CredRead($sTargetName, $CRED_TYPE_GENERIC) If Not @error Then ConsoleWrite("TargetName: " & $aCredential[0] & @CRLF) ConsoleWrite("UserName: " & $aCredential[2] & @CRLF) ConsoleWrite("Blob Size: " & BinaryLen($aCredential[3]) & " bytes" & @CRLF) EndIf ; Delete the credential _WinCred_CredDelete($sTargetName, $CRED_TYPE_GENERIC) Example Scripts The UDF includes complete example scripts in the Examples directory: _WinCred_CredWrite.au3 - Demonstrates creating credentials with different persistence settings _WinCred_CredRead.au3 - Shows how to read credentials and display all available information _WinCred_CredDelete.au3 - Demonstrates deleting credentials and verifying deletion All examples are fully commented and follow AutoIt best practices. Security Notes Credentials are stored securely in the Windows Credential Manager The CredentialBlob should contain binary data (use Binary() function) For sensitive data, consider encrypting the blob before storing Documentation Full function documentation is included in the UDF file following AutoIt UDF standards. The UDF is compatible with AutoIt's built-in help file system. License This UDF is released under the MIT License. See the LICENSE file for details. Changelog See CHANGELOG.md for a complete list of changes. Links GitHub Repository: https://github.com/DonChunior/WinCred-UDF Microsoft Documentation: https://learn.microsoft.com/en-us/windows/win32/api/wincred/2 points -
Bug in map ( and how to avoid it )
Musashi and one other reacted to AspirinJunkie for a topic
It seems that this is less about index collisions. The real problem is obviously that memory areas are being used across multiple map instances. Whether this occurs exclusively when using string indices in conjunction with integer indices or in other cases as well, we cannot know here and now. Without having the source code for the implementation, we can only speculate about what is happening in the background based on the behavior. And so far, it seems to me that the memory areas for the buckets of the hash table are not completely cleaned up when dereferencing the map variable, and on the other hand, these areas are used when initializing a map variable without being fully prepared for use (e.g., memory area zeros or something like that). There may well be a clever idea behind this, for example, to increase performance or something like that—we don't know. However, the current implementation is undoubtedly a bug, and worse still, a bug whose consequences cannot really be assessed at present. Therefore, we cannot simply dismiss the issue with blanket statements such as “don't use integer keys” or something similar. This naturally raises the question of how to deal with it. It has been clearly stated that bug reports should not be created for maps. Nevertheless, the bug tracker is full of tickets for maps, and they are being processed as normal. That's why I would have liked to discuss the whole thing in advance in the forum, preferably with the developers involved (actually, I wanted to do just that in the German forum first, but you had already posted the thread here...). In my opinion, the “AutoIt General Help and Support” forum is not the right place for this, but rather “AutoIt Technical Discussion.” However, it may well be that the bug has already been fixed and has been resolved in the course of the following ticket: https://www.autoitscript.com/trac/autoit/ticket/3948 The phenomenon described there is quite similar.2 points -
WinRT - UI Gallery (Xaml Islands)
argumentum and one other reacted to MattyD for a topic
In order not to pollute other threads, here's one dedicated to Windows.UI controls and examples. These are for use with Xaml Islands, NOT WinUI3 - although porting them across shouldn't be too demanding. Both methods have their pros and cons - but I'd say the XAML Island approach is bit more robust at this point in time. Don't forget to update your manifests to make this work! (background/details in this thread) Download PS. More than happy for this to be a community thing if anyone else wishes to contribute2 points -
It was mentioned here how AI bots are intensively hitting the site. I suppose they also grab all the codes they can take...2 points
-
WinRT - WinUI3
WildByDesign and one other reacted to MattyD for a topic
Hi all, Updated libraries based on the new Version 1.8 of WindowsAppSDK are here. Until now we've been on 1.7.x The v1.8 runtime can be installed from here: (Remembering that we require the x64 version.) A copy of the latest bootstrapper dll is included in the zip - but if you need to manually update it later for whatever reason, it has moved. So you'll now find it here: https://www.nuget.org/packages/Microsoft.WindowsAppSdk.Foundation/ download package (on the right) > extract contents > then you'll find it under .\runtimes\win-x64\native2 points -
Fun thread. Another option would be to use custom draw which allows you to use part of the standard functionality, check for hovering and draw part of the control. #include <GUIConstants.au3> #include <WindowsConstants.au3> #include <StructureConstants.au3> #include <WinAPI.au3> #include <FrameConstants.au3> Global Const $tagNMCUSTOMDRAWINFO = $tagNMHDR & ";dword DrawStage;handle hdc;" & $tagRECT & ";dword_ptr ItemSpec;uint ItemState;lparam lItemParam;" Global $idBut Example() Func Example() Local $hGUI = GUICreate("Example") $idBut = GUICtrlCreateButton("Test", 10, 10, 100, 30) GUICtrlCreateButton("Standard", 10, 50, 100, 30) GUIRegisterMsg($WM_NOTIFY, WM_NOTIFY) GUISetState() While True Switch GUIGetMsg() Case $GUI_EVENT_CLOSE ExitLoop Case $idBut ConsoleWrite("Button was pressed" & @CRLF) EndSwitch WEnd EndFunc ;==>Example Func WM_NOTIFY($hWnd, $iMsg, $wParam, $lParam) Local $tInfo = DllStructCreate($tagNMCUSTOMDRAWINFO, $lParam) If $tInfo.IDFrom = $idBut And $tInfo.Code = $NM_CUSTOMDRAW And $tInfo.DrawStage = $CDDS_PREPAINT Then Local $tRECT = DllStructCreate($tagRECT, DllStructGetPtr($tInfo, "left")) _WinAPI_DrawFrameControl($tInfo.hDC, $tRECT, $DFC_BUTTON, (BitAND($tInfo.ItemState, $CDIS_SELECTED) ? $DFCS_PUSHED : 0) + $DFCS_BUTTONPUSH) _WinAPI_InflateRect($tRECT, -3, -3) Local $hBrush = _WinAPI_CreateSolidBrush(BitAND($tInfo.ItemState, $CDIS_HOT) ? 0xFFFF : 0xAAAA) _WinAPI_FillRect($tInfo.hDC, $tRECT, $hBrush) _WinAPI_DeleteObject($hBrush) EndIf Return $GUI_RUNDEFMSG EndFunc ;==>WM_NOTIFY2 points
-
Round buttons
argumentum and one other reacted to ioa747 for a topic
Another approach (improved), in the collection with colored buttons, with 3D appearance, and toggle capability ; https://www.autoitscript.com/forum/topic/211721-round-buttons/ ;---------------------------------------------------------------------------------------- ; Title...........: 3DRectButton.au3 ; Description.....: Creates colored buttons, with 3D appearance, and toggle capability. ; AutoIt Version..: 3.3.18.0 Author: ioa747 Script Version: 0.1 ; Note............: Testet in Windows 11 Pro 24H2 Date:9/11/2025 ;---------------------------------------------------------------------------------------- #AutoIt3Wrapper_Au3Check_Parameters=-d -w 1 -w 2 -w 3 -w 4 -w 5 -w 6 -w 7 #include <GUIConstantsEx.au3> #include <ButtonConstants.au3> #include <StaticConstants.au3> #include <WindowsStylesConstants.au3> #include <WinAPIGdi.au3> ; maps to hold buttons data Global $mButtons[], $mBtn[] Example() Func Example() ; Create a GUI with various controls. Local $hGUI = GUICreate("Example", 300, 270) GUISetFont(10, 800) ; Create a button control. Local $idButton_1 = _Button("Darck", 20, 20, 85, 30, 0xFF720E) GUICtrlSetTip(-1, "Long press to togle") Local $idButton_2 = _Button("Button 2", 20, 70, 85, 30, 0x36BB48) Local $idButton_3 = _Button("Button 3", 20, 120, 85, 30, 0x3BADFF) Local $idButton_4 = _Button("Button 4", 20, 170, 85, 30, 0xD980FF) Local $idButton_5 = GUICtrlCreateButton("Button 5", 20, 220, 85, 30) ; Display the GUI. GUISetState(@SW_SHOW, $hGUI) ; Loop until the user exits. While 1 Switch GUIGetMsg() Case $GUI_EVENT_CLOSE ExitLoop Case $idButton_1 ConsoleWrite("$idButton_1 Down" & @CRLF) Case $idButton_2 ConsoleWrite("$idButton_2 Down" & @CRLF) Case $idButton_3 ConsoleWrite("$idButton_3 Down" & @CRLF) Case $idButton_4 ConsoleWrite("$idButton_4 Down" & @CRLF) Case $mButtons[$idButton_1].event ConsoleWrite("$idButton_1 Up" & @CRLF) If $mButtons[$idButton_1].togle Then GUISetBkColor(0x33373A, $hGUI) Else GUISetBkColor(0xF0F0F0, $hGUI) EndIf ConsoleWrite("$mButtons[$idButton_1].togle=" & $mButtons[$idButton_1].togle & @CRLF) Case $mButtons[$idButton_2].event ConsoleWrite("$idButton_2 Up" & @CRLF) ConsoleWrite("$mButtons[$idButton_2].togle=" & $mButtons[$idButton_2].togle & @CRLF) Case $mButtons[$idButton_3].event ConsoleWrite("$idButton_3 Up" & @CRLF) Case $mButtons[$idButton_4].event ConsoleWrite("$idButton_4 Up" & @CRLF) Case $idButton_5 ConsoleWrite("$idButton_5 Up" & @CRLF) EndSwitch _Hover($hGUI) WEnd ; Delete the previous GUI and all controls. GUIDelete($hGUI) EndFunc ;==>Example ;--------------------------------------------------------------------------------------- Func _Hover($hGUI, $iHighlight = 20) Local Static $iActive If Not WinActive($hGUI) Then Return SetError(1, 0, False) Local $ActiveCtrl, $mBtn Local $aCtrl = GUIGetCursorInfo($hGUI) $ActiveCtrl = IsArray($aCtrl) ? $aCtrl[4] : 0 If Not (MapExists($mButtons, $ActiveCtrl) Or $ActiveCtrl = 0) Then Return If $iActive <> $ActiveCtrl Then ; Reset Highlight If $iActive > 0 Then $mBtn = $mButtons[$iActive] GUICtrlSetBkColor($mBtn.id, $mBtn.BkColor) $iActive = 0 Return SetError(2, 0, False) EndIf If Not $ActiveCtrl Then Return ; Highlight $iActive = $ActiveCtrl $mBtn = $mButtons[$iActive] GUICtrlSetBkColor($mBtn.id, ColorLight($mBtn.BkColor, $iHighlight)) EndIf ; Click efect If $aCtrl[2] And $ActiveCtrl Then $mBtn = $mButtons[$iActive] ; Move the button based on current toggle state If Not $mBtn.togle Then GUICtrlSetPos($mBtn.id, $mBtn.X + 2, $mBtn.Y + 2) ; If not toggled, move down Else GUICtrlSetPos($mBtn.id, $mBtn.X, $mBtn.Y) ; If toggled, move up EndIf Local $iStartTime = TimerInit() Do $aCtrl = GUIGetCursorInfo($hGUI) Sleep(10) If TimerDiff($iStartTime) > 1500 Then ToolTip("Togle Locked") Until $aCtrl[2] = 0 ; *** Long press > 1.5 sec -> enable togle If TimerDiff($iStartTime) > 1500 Then $mBtn.togle = True Else $mBtn.togle = False EndIf ToolTip("") ; If is toggled, stay down If $mBtn.togle Then GUICtrlSetPos($mBtn.id, $mBtn.X + 2, $mBtn.Y + 2) Else GUICtrlSetPos($mBtn.id, $mBtn.X, $mBtn.Y) EndIf $mButtons[$mBtn.id] = $mBtn ; Update the button's data in the global map GUICtrlSendToDummy($mBtn.event) ; Send the dummy event to trigger the Up event EndIf Sleep(10) EndFunc ;==>_Hover ;--------------------------------------------------------------------------------------- Func _Button($Text, $Left, $Top, $Width, $Height, $hBkColor = 0xF0F0F0, $hTxtColor = 0x000000, $iShadow = 30) Local $hShColor = ColorLight($hBkColor, -$iShadow) Local $idEvent = GUICtrlCreateDummy() Local $idShadow = GUICtrlCreateLabel("", $Left - 1, $Top - 1, $Width + 4, $Height + 4) GUICtrlSetBkColor(-1, $hShColor) GUICtrlSetState(-1, $GUI_DISABLE) Local $id = GUICtrlCreateLabel($Text, $Left, $Top, $Width, $Height, BitOR($SS_CENTERIMAGE, $SS_CENTER)) GUICtrlSetBkColor(-1, $hBkColor) GUICtrlSetColor(-1, $hTxtColor) $mBtn.id = $id $mBtn.event = $idEvent $mBtn.text = $Text $mBtn.X = $Left $mBtn.Y = $Top $mBtn.W = $Width $mBtn.H = $Height $mBtn.BkColor = $hBkColor $mBtn.TxtColor = $hTxtColor $mBtn.shadow = $idShadow $mBtn.ShColor = $hShColor $mBtn.togle = False $mButtons[$id] = $mBtn Return $id EndFunc ;==>_Button ;-------------------------------------------------------------------------------------------------------------------------------- Func ColorLight($HexColor, $Lightness = 30) Local $iHue, $iLuminance, $iSaturation _WinAPI_ColorRGBToHLS($HexColor, $iHue, $iLuminance, $iSaturation) Local $hColor = Hex(_WinAPI_ColorHLSToRGB($iHue, $iLuminance + $Lightness, $iSaturation), 6) Return '0x' & $hColor EndFunc ;==>ColorLight ;--------------------------------------------------------------------------------------- have fun Thank you very much2 points -
AutoIt Live Wallpaper
SOLVE-SMART and one other reacted to argumentum for a topic
Perfect, beautiful, awesome. It all shows and works as advertised 💯2 points -
AutoIt Live Wallpaper
SOLVE-SMART and one other reacted to WildByDesign for a topic
I updated the script in the first post. On a per-monitor basis, I made it so that if the monitor aspect ratio is equal to the aspect ratio for the video, it will use the default Uniform value. If the aspect ratio is not equal, it will set the UniformToFill value. This should deal with the issue of black bars (letterboxing) being added on the top/bottom or sides of the video. It will simply crop some parts of the video and not stretch it. I also fixed an issue where the screen would be black briefly before the video started playing. I just had to ensure that the video was fully loaded before showing the GUI(s). @argumentum I know that you are not a fan of moving wallpapers, but if you have a moment, would you be willing to test this latest script? The reason why I ask is because your ultrawide secondary monitor is a different aspect ratio and therefore a good example to test whether or not UniformToFill is the better option for mismatching aspect ratios between video and monitor. I think that it makes sense but I don't have another monitor that is a different ratio. EDIT: And I also made sure that the Start button (and Win key) trigger should play the video on any OS language. It was likely only working with English OS before.2 points -
AutoIt Live Wallpaper
SOLVE-SMART and one other reacted to argumentum for a topic
No it wouldn't. ( nor a live wallpaper ) My screen is always with all kinds of windows open. Never get to see the wallpaper 🤷♂️2 points -
Guiscape -- A new GUI builder project!
argumentum and one other reacted to jaberwacky for a topic
Thank you! 🥰 It's a problem I'm in the middle of working on. I got side quested with this DPI stuff. 😂 I learned a lot and now I have something to bring into my future projects! Updated at GitHub because I made some oopsies!2 points -
REMOVED the Kobo Cover Fixer v2-4.zip update download, due to a serious bug. It will be replaced soon as, but right now I am still testing, which isn't easy in my circumstances, which is no doubt how the issue slipped through. Basically the Restore feature worked in the wrong direction copy wise, and probably the Clone feature did too. I am presuming they originally worked in the right directions or I would have noticed before now. So likely this is the result of a recent new feature I added, and which I might have been interrupted in when implementing. Due to the flaky nature of the USB connection to my Kobo device, which may be a device hardware issue or just driver related, testing and troubleshooting for me, are a challenge. In essence, I only get a small window of time to operate in. Basically my device needs to be flat, and I get roughly an hour before it is charged after connecting to my PC. Once the device battery is charged, the Kobo device gets stuck in a connect/disconnect loop, so almost impossible to work with. You might think an hour would be sufficient time, and it is if all goes to plan. However it doesn't leave much leeway for testing latest changes or troubleshooting. This is chiefly because I have a lot of ebooks on my Kobo device ... just shy of a thousand, of which somewhat less than a hundred are side-loaded ebooks. It takes a good while checking the images for all those ebooks, especially when doing visual comparison, as happens when a mismatch between the clone folder on my PC and the images folder on the Kobo device. Anyway, BIG APOLOGIES to the six downloaders of v2.4, who may have been or might be, impacted by the wrong direction copy issue ... hopefully their cover sources remain. I discovered this issue a couple of hours ago and are already working on a fix, perhaps already fixed. Luckily right now, I am just about to start reading a physical trade paperback, so my Kobo device won't be needed for reading for a couple of days or so. In an effort to deal with this more quickly, I have temporarily set my Kobo device to never go to sleep, so the battery can get flatter quicker, and I can do some final testing, hopefully in a few hours or tomorrow. P.S. I'd been following my latest instructions to ensure I didn't miss anything in regard to them, so the good news is they passed up to where I needed to troubleshoot the copy issue, so up until just before I needed to run the Clone feature ... after restoring the cover images in my Clone folder from my Images Backup folder ... so glad I had that. NOTE TO SELF - I should suggest using the BACKUP IMAGES option before running the 'Clone' feature ... certainly on first use. Having that backup has saved my bacon a few times. So I should amend those newly created instructions.2 points
-
Guiscape -- A new GUI builder project!
SOLVE-SMART and one other reacted to argumentum for a topic
...developing GUI stuff is a pain. Mostly because you'd need at least 2 monitors and at least on with scaling as otherwise, you can't clearly see what it looks like. On the other hand, that would be a pain to code without an stablished UDF for it. Therefore, since we don't have a stablish UDF ( that I know of ) forget the HiDPI stuff and make the GUI editor without that into consideration. If "GuiCtrls_HiDpi" (UDF in progress) or another UDF comes along or, "New and improved: AutoIt v3.4.0.0. Now with HiDPI" comes into existence, then patching the editor shouldn't be a big deal. Santa Claus/Saint Nicholas/Saint Nick/Father Christmas/Kris Kringle/bearded dude: I wish for a "dark/light mode, DPI aware" all in one UDF 😇 TIA2 points -
@argumentum I hope you don't mind me doing something similar in parallel. I would like to test the code on different OS, need your support. It would make sense to have 2+ monitors, if possible with > 96 DPI. I don't know from which os it is possible to set different DPIs per monitor (WIn10+?). I tested it on Win11 22H2 and worked properly on 3 monitors with 3 different DPIs (left 100%, middle 125 % (main), right 150%). Just run the code and move the GUI over all your monitors. Theoretically the GUI should be adjusted accordingly. _WinAPI_DPI.au3: ;Coded by UEZ build 2023-08-15 beta #include-once #include <GDIPlus.au3> #include <Misc.au3> #include <WinAPISysWin.au3> #include <WinAPIsysinfoConstants.au3> #Region DPI Constants ;https://learn.microsoft.com/en-us/windows/win32/api/windef/ne-windef-dpi_awareness Global Enum $DPI_AWARENESS_INVALID = -1, $DPI_AWARENESS_UNAWARE = 0, $DPI_AWARENESS_SYSTEM_AWARE = 1, $DPI_AWARENESS_PER_MONITOR_AWARE = 2 ;https://learn.microsoft.com/en-us/windows/win32/hidpi/dpi-awareness-context Global Const $DPI_AWARENESS_CONTEXT_UNAWARE = $DPI_AWARENESS_UNAWARE - 1 Global Const $DPI_AWARENESS_CONTEXT_SYSTEM_AWARE = $DPI_AWARENESS_UNAWARE - 2 Global Const $DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE = $DPI_AWARENESS_UNAWARE - 3 Global Const $DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2 = $DPI_AWARENESS_UNAWARE - 4 Global Const $DPI_AWARENESS_CONTEXT_UNAWARE_GDISCALED = $DPI_AWARENESS_UNAWARE - 5 ; enum _MONITOR_DPI_TYPE Global Enum $MDT_EFFECTIVE_DPI = 0, $MDT_ANGULAR_DPI, $MDT_RAW_DPI Global Const $MDT_DEFAULT = $MDT_EFFECTIVE_DPI ;Windows Message Codes Global Const $WM_DPICHANGED = 0x02E0, $WM_DPICHANGED_BEFOREPARENT = 0x02E2, $WM_DPICHANGED_AFTERPARENT = 0x02E3, $WM_GETDPISCALEDSIZE = 0x02E4 #EndRegion DPI Constants #Region WinAPI DPI ;https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-adjustwindowrectexfordpi Func _WinAPI_AdjustWindowRectExForDpi($dpi, $dwStyle, $dwExStyle, $bMenu = False) Local $tRECT = DllStructCreate($tagRECT) Local $aResult = DllCall("user32.dll", "bool", "AdjustWindowRectExForDpi", "struct*", $tRECT, "dword", $dwStyle, "bool", $bMenu, "dword", $dwExStyle, "int", $dpi) ;requires Win10 v1607+ / no server support If Not IsArray($aResult) Or @error Then Return SetError(1, @extended, 0) If $aResult[0] Then Return SetError(2, @extended, 0) Return $tRECT EndFunc ;==>_WinAPI_AdjustWindowRectExForDpi ;https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-systemparametersinfofordpi Func _WinAPI_SystemParametersInfoForDpi($uiAction, $uiParam, $pvParam, $fWinIni, $dpi) Local $aResult = DllCall("user32.dll", "bool", "SystemParametersInfoForDpi", "uint", $uiAction, "uint", $uiParam, "struct*", $pvParam, "uint", $fWinIni, "uint", $dpi) ;requires Win10 v1607+ / no server support If Not IsArray($aResult) Or @error Then Return SetError(1, @extended, 0) If Not $aResult[0] Then Return SetError(2, @extended, 0) Return $aResult[0] EndFunc ;==>_WinAPI_SystemParametersInfoForDpi ;https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-inheritwindowmonitor Func _WinAPI_InheritWindowMonitor($hWnd, $hWndInherit) Local $aResult = DllCall("user32.dll", "bool", "InheritWindowMonitor", "hwnd", $hWnd, "hwnd", $hWndInherit) ;requires Win10 v1803+ / Windows Server 2016+ If Not IsArray($aResult) Or @error Then Return SetError(1, @extended, 0) If Not $aResult[0] Then Return SetError(2, @extended, 0) Return $aResult[0] EndFunc ;==>_WinAPI_InheritWindowMonitor ;https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-isvaliddpiawarenesscontext Func _WinAPI_IsValidDpiAwarenessContext($DPI_AWARENESS_CONTEXT_value) Local $aResult = DllCall("user32.dll", "bool", "IsValidDpiAwarenessContext", @AutoItX64 ? "int64" : "int", $DPI_AWARENESS_CONTEXT_value) ;requires Win10 v1607+ / no server support If Not IsArray($aResult) Or @error Then Return SetError(1, @extended, 0) If Not $aResult[0] Then Return SetError(2, @extended, 0) Return $aResult[0] EndFunc ;==>_WinAPI_IsValidDpiAwarenessContext ;https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-logicaltophysicalpointforpermonitordpi Func _WinAPI_LogicalToPhysicalPointForPerMonitorDPI($hWnd) Local $tPOINT = DllStructCreate($tagPOINT) Local $aResult = DllCall("user32.dll", "bool", "LogicalToPhysicalPointForPerMonitorDPI", "hwnd", $hWnd, "struct*", $tPOINT) ;requires Win 8.1+ / no server support If Not IsArray($aResult) Or @error Then Return SetError(1, @extended, 0) If Not $aResult[0] Then Return SetError(2, @extended, 0) Return $tPOINT EndFunc ;==>_WinAPI_LogicalToPhysicalPointForPerMonitorDPI ;https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-physicaltologicalpointforpermonitordpi Func _WinAPI_PhysicalToLogicalPointForPerMonitorDPI($hWnd) Local $tPOINT = DllStructCreate($tagPOINT) Local $aResult = DllCall("user32.dll", "bool", "PhysicalToLogicalPointForPerMonitorDPI", "hwnd", $hWnd, "struct*", $tPOINT) ;requires Win 8.1+ / no server support If Not IsArray($aResult) Or @error Then Return SetError(1, @extended, 0) If Not $aResult[0] Then Return SetError(2, @extended, 0) Return $tPOINT EndFunc ;==>_WinAPI_PhysicalToLogicalPointForPerMonitorDPI Func _GDIPlus_GetDPI($hGUI = 0) _GDIPlus_Startup() Local $hGfx = _GDIPlus_GraphicsCreateFromHWND($hGUI) If @error Then Return SetError(1, @extended, 0) Local $aResult = DllCall($__g_hGDIPDll, "int", "GdipGetDpiX", "handle", $hGfx, "float*", 0) If @error Then Return SetError(2, @extended, 0) _GDIPlus_GraphicsDispose($hGfx) _GDIPlus_Shutdown() Return $aResult[2] EndFunc ;==>_GDIPlus_GetDPI Func _WinAPI_GetDPI($hWnd = 0) $hWnd = Not $hWnd ? _WinAPI_GetDesktopWindow() : $hWnd Local Const $hDC = _WinAPI_GetDC($hWnd) If @error Then Return SetError(1, 0, 0) Local Const $iDPI = _WinAPI_GetDeviceCaps($hDC, $LOGPIXELSX) If @error Or Not $iDPI Then _WinAPI_ReleaseDC($hWnd, $hDC) Return SetError(2, 0, 0) EndIf _WinAPI_ReleaseDC($hWnd, $hDC) Return $iDPI EndFunc ;==>_WinAPI_GetDPI ;https://learn.microsoft.com/en-us/windows/win32/api/shellscalingapi/nf-shellscalingapi-getdpiformonitor Func _WinAPI_GetDpiForPrimaryMonitor($hMOnitor = 0, $dpiType = $MDT_DEFAULT) If $hMOnitor = 0 Then Local $aMonitors = _WinAPI_EnumDisplayMonitors() If @error Or Not IsArray($aMonitors) Then Return SetError(1, 0, 0) Local $i For $i = 1 To $aMonitors[0][0] If _WinAPI_GetMonitorInfo($aMonitors[$i][0])[2] = 1 Then $hMOnitor = $aMonitors[$i][0] ExitLoop EndIf Next EndIf Local $tx = DllStructCreate("int dpiX"), $tY = DllStructCreate("int dpiY") Local $aResult = DllCall("Shcore.dll", "long", "GetDpiForMonitor", "handle", $hMOnitor, "long", $dpiType, "struct*", $tx, "struct*", $tY) If @error Or Not IsArray($aResult) Then Return SetError(2, 0, 0) Return $tx.dpiX EndFunc ;==>_WinAPI_GetDpiForPrimaryMonitor ;https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-getdpiforwindow Func _WinAPI_GetDpiForWindow($hWnd) Local $aResult = DllCall("user32.dll", "uint", "GetDpiForWindow", "hwnd", $hWnd) ;requires Win10 v1607+ / no server support If Not IsArray($aResult) Or @error Then Return SetError(1, @extended, 0) If Not $aResult[0] Then Return SetError(2, @extended, 0) Return $aResult[0] EndFunc ;==>_WinAPI_GetDpiForWindow ;https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-getdpiforsystem Func _WinAPI_GetDpiForSystem() Local $aResult = DllCall("user32.dll", "uint", "GetDpiForSystem") ;requires Win10 v1607+ / no server support If Not IsArray($aResult) Or @error Then Return SetError(1, @extended, 0) If Not $aResult[0] Then Return SetError(2, @extended, 0) Return $aResult[0] EndFunc ;==>_WinAPI_GetDpiForSystem ;https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-getthreaddpiawarenesscontext Func _WinAPI_GetThreadDpiAwarenessContext() Local $aResult = DllCall("user32.dll", "uint", "GetThreadDpiAwarenessContext") ;requires Win10 v1607+ / no server support If Not IsArray($aResult) Or @error Then Return SetError(1, @extended, 0) If Not $aResult[0] Then Return SetError(2, @extended, 0) Return $aResult[0] EndFunc ;==>_WinAPI_GetThreadDpiAwarenessContext ;https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-getdpifromdpiawarenesscontext Func _WinAPI_GetDpiFromDpiAwarenessContext($DPI_AWARENESS_CONTEXT_value) Local $aResult = DllCall("user32.dll", "uint", "GetDpiFromDpiAwarenessContext", @AutoItX64 ? "int64" : "int", $DPI_AWARENESS_CONTEXT_value) ;requires Win10 v1803+ / Windows Server 2016+ If Not IsArray($aResult) Or @error Then Return SetError(1, @extended, 0) If Not $aResult[0] Then Return SetError(2, @extended, 0) Return $aResult[0] EndFunc ;==>_WinAPI_GetDpiFromDpiAwarenessContext ;https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-getawarenessfromdpiawarenesscontext Func _WinAPI_GetAwarenessFromDpiAwarenessContext($DPI_AWARENESS_CONTEXT_value) Local $aResult = DllCall("user32.dll", "uint", "GetAwarenessFromDpiAwarenessContext", @AutoItX64 ? "int64" : "int", $DPI_AWARENESS_CONTEXT_value) ;requires Win10 v1607+ / no server support If Not IsArray($aResult) Or @error Then Return SetError(1, @extended, 0) If Not $aResult[0] Then Return SetError(2, @extended, 0) Return $aResult[0] EndFunc ;==>_WinAPI_GetAwarenessFromDpiAwarenessContext ;https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-getdpiawarenesscontextforprocess Func _WinAPI_GetDpiAwarenessContextForProcess($hProcess) Local $aResult = DllCall("user32.dll", "uint", "GetDpiAwarenessContextForProcess", "handle", $hProcess) ;requires Win10 v1803+ / Windows Server 2016+ If Not IsArray($aResult) Or @error Then Return SetError(1, @extended, 0) If Not $aResult[0] Then Return SetError(2, @extended, 0) Return $aResult[0] EndFunc ;==>_WinAPI_GetDpiAwarenessContextForProcess ;https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-getsystemdpiforprocess Func _WinAPI_GetSystemDpiForProcess($hProcess) Local $aResult = DllCall("user32.dll", "uint", "GetSystemDpiForProcess", "handle", $hProcess) ;requires Win10 v1803+ / Windows Server 2016+ If Not IsArray($aResult) Or @error Then Return SetError(1, @extended, 0) If Not $aResult[0] Then Return SetError(2, @extended, 0) Return $aResult[0] EndFunc ;==>_WinAPI_GetSystemDpiForProcess ;https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-getwindowdpiawarenesscontext Func _WinAPI_GetWindowDpiAwarenessContext($hWnd) Local $aResult = DllCall("user32.dll", "uint", "GetWindowDpiAwarenessContext", "hwnd", $hWnd) ;requires Win10 v1607+ / no server support If Not IsArray($aResult) Or @error Then Return SetError(1, @extended, 0) If Not $aResult[0] Then Return SetError(2, @extended, 0) Return $aResult[0] EndFunc ;==>_WinAPI_GetWindowDpiAwarenessContext ;https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-setprocessdpiawarenesscontext Func _WinAPI_SetProcessDpiAwarenessContext($DPI_AWARENESS_CONTEXT_value) Local $aResult = DllCall("user32.dll", "bool", "SetProcessDpiAwarenessContext", @AutoItX64 ? "int64" : "int", $DPI_AWARENESS_CONTEXT_value) ;requires Win10 v1703+ / Windows Server 2016+ If Not IsArray($aResult) Or @error Then Return SetError(1, @extended, 0) If Not $aResult[0] Then Return SetError(2, @extended, 0) Return $aResult[0] EndFunc ;==>_WinAPI_SetProcessDpiAwarenessContext ;https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-setthreaddpiawarenesscontext Func _WinAPI_SetThreadDpiAwarenessContext($DPI_AWARENESS_CONTEXT_value) Local $aResult = DllCall("user32.dll", "uint", "SetThreadDpiAwarenessContext", @AutoItX64 ? "int64" : "int", $DPI_AWARENESS_CONTEXT_value) ;requires Win10 v1703+ / Windows Server 2016+ If Not IsArray($aResult) Or @error Then Return SetError(1, @extended, 0) If Not $aResult[0] Then Return SetError(2, @extended, 0) Return $aResult[0] EndFunc ;==>_WinAPI_SetThreadDpiAwarenessContext ;https://learn.microsoft.com/en-us/windows/win32/api/shellscalingapi/nf-shellscalingapi-setprocessdpiawareness Func _WinAPI_SetProcessDpiAwareness($PROCESS_DPI_AWARENESS = $DPI_AWARENESS_PER_MONITOR_AWARE) Local $aResult = DllCall("Shcore.dll", "long", "SetProcessDpiAwareness", "int", $PROCESS_DPI_AWARENESS) ;requires Win 8.1+ / Server 2012 R2+ If Not IsArray($aResult) Or @error Then Return SetError(1, @extended, 0) If $aResult[0] Then Return SetError(2, $aResult[0], 0) Return $aResult[0] ;0 is S_OK EndFunc ;==>_WinAPI_SetProcessDpiAwareness Func _WinAPI_SetDPIAwareness($DPIAwareContext = $DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE, $iMode = 1) Switch @OSBuild Case 6000 To 9199 Local $aResult = DllCall("user32.dll", "bool", "SetProcessDPIAware") ;requires Vista+ / Server 2008+ If Not $aResult[0] Then Return SetError(1, 0, 0) Case 9200 To 13999 $DPIAwareContext = ($DPIAwareContext < 0) ? 0 : ($DPIAwareContext > 2) ? 2 : $DPIAwareContext _WinAPI_SetProcessDpiAwareness($DPIAwareContext) If @error Then Return SetError(2, @error, 0) Case @OSBuild > 13999 $DPIAwareContext = ($DPIAwareContext < -5) ? -5 : ($DPIAwareContext > -1) ? -1 : $DPIAwareContext $iMode = ($iMode < 1) ? 1 : ($iMode > 2) ? 2 : $iMode Local $iResult Switch $iMode Case 1 $iResult = _WinAPI_SetProcessDpiAwarenessContext($DPIAwareContext) If Not $iResult Or @error Then Return SetError(3, 0, 0) Case 2 #cs Return DPI_AWARENESS_CONTEXT values $DPI_AWARENESS_CONTEXT_UNAWARE = 0x6010 / 24592 $DPI_AWARENESS_CONTEXT_SYSTEM_AWARE = 0x9011 / 36881 $DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE = 0x12 / 18 $DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2 = 0x22 / 34 $DPI_AWARENESS_CONTEXT_UNAWARE_GDISCALED = 0x40006010 / 1073766416 #ce $iResult = _WinAPI_SetThreadDpiAwarenessContext($DPIAwareContext) If Not $iResult Or @error Then Return SetError(4, 0, 0) EndSwitch EndSwitch Local $iDPI If @OSBuild < 9200 Then $iDPI = _WinAPI_GetDPI() If @error Or Not $iDPI Then Return SetError(5, 0, 0) Else $iDPI = _WinAPI_GetDpiForPrimaryMonitor() If @error Or Not $iDPI Then Return SetError(6, 0, 0) EndIf Return $iDPI EndFunc ;==>_WinAPI_SetDPIAwareness #EndRegion WinAPI DPI Example.au3: ; AutoIt GUI Example ; Created: 17/01/2005 - CyberSlug ; Modifed: 05/12/2011 - guinness ; Modifed: 09/06/2014 - mLipok ; Modifed: 15/10/2018 - mLipok ; Modifed: 14/08/2023 - UEZ #AutoIt3Wrapper_Change2CUI=n #AutoIt3Wrapper_Run_Au3Stripper=y #Au3Stripper_Parameters=/so #AutoIt3Wrapper_Res_HiDpi=n ;must be n otherwise _WinAPI_SetDPIAwareness() function will fail! #AutoIt3Wrapper_UseX64=n #Region INCLUDE #include <AVIConstants.au3> #include <GuiConstantsEx.au3> #include <TreeViewConstants.au3> #include <Array.au3> #include <GUIConstantsEx.au3> #include <StaticConstants.au3> #include <WinAPIGdiDC.au3> #include <WindowsConstants.au3> #include "_WinAPI_DPI.au3" #EndRegion INCLUDE #Region INITIALIZATION and EXIT Global $aCtrl[43][6], $ahWnd[2][10], $g_iDPI_ratio1, $g_iDPI_ratio2, $iw = 400, $ih = 200 _Example() ; Finished! #EndRegion INITIALIZATION and EXIT Func _Example() Local $AWARENESS Switch @OSBuild Case 9200 To 13999 $AWARENESS = $DPI_AWARENESS_PER_MONITOR_AWARE Case @OSBuild > 13999 $AWARENESS = $DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2 EndSwitch Local $iDPI = _WinAPI_SetDPIAwareness($AWARENESS, 2), $iDPI_def = 96 If $iDPI = 0 Then Exit MsgBox($MB_ICONERROR, "ERROR", "Unable to set DPI awareness!!!", 10) $g_iDPI_ratio1 = $iDPI / $iDPI_def $g_iDPI_ratio2 = $iDPI_def / $iDPI #Region GUI Local $sPath = RegRead("HKLM\SOFTWARE\" & (@AutoItX64 ? "WOW6432Node\" : "") & "AutoIt v3\AutoIt", "InstallDir") $sPath = ($sPath = "" ? @ProgramFilesDir & "\AutoIt3\" : $sPath & "\") ;assume default path $ahWnd[0][1] = 8.5 * $g_iDPI_ratio1 $ahWnd[0][0] = GUICreate("DPI Sample GUI", 400 * $g_iDPI_ratio1, 400 * $g_iDPI_ratio1) GUISetIcon(@SystemDir & "\mspaint.exe", 0) GUISetFont($ahWnd[0][1], 400, 0, "Arial", $ahWnd[0][0], $CLEARTYPE_QUALITY) #EndRegion GUI #Region MENU $aCtrl[1][0] = GUICtrlCreateMenu("Menu &One") $aCtrl[2][0] = GUICtrlCreateMenu("Menu &Two") $aCtrl[3][0] = GUICtrlCreateMenu("Menu Th&ree") $aCtrl[4][0] = GUICtrlCreateMenu("Menu &Four") GUICtrlCreateMenuItem('SubMenu One &A', $aCtrl[1][0]) GUICtrlCreateMenuItem('SubMenu One &B', $aCtrl[1][0]) #EndRegion MENU #Region CONTEXT MENU $aCtrl[5][0] = GUICtrlCreateContextMenu() GUICtrlCreateMenuItem("Context Menu", $aCtrl[5][0]) GUICtrlCreateMenuItem("", $aCtrl[5][0]) ; Separator GUICtrlCreateMenuItem("&Properties", $aCtrl[5][0]) #EndRegion CONTEXT MENU #Region PIC $aCtrl[6][2] = 0 ;x $aCtrl[6][3] = 0 ;y $aCtrl[6][4] = 169 ;w $aCtrl[6][5] = 68 ;h $aCtrl[6][0] = GUICtrlCreatePic($sPath & "Examples\GUI\logo4.gif", $aCtrl[6][2] * $g_iDPI_ratio1, $aCtrl[6][3] * $g_iDPI_ratio1, $aCtrl[6][4] * $g_iDPI_ratio1, $aCtrl[6][5] * $g_iDPI_ratio1) GUICtrlSetTip(-1, '#Region PIC') $aCtrl[7][2] = 75 $aCtrl[7][3] = 1 $aCtrl[7][4] = 80 $aCtrl[7][5] = 16 $aCtrl[7][1] = 8.5 * $g_iDPI_ratio2 $aCtrl[7][0] = GUICtrlCreateLabel("Sample Pic", $aCtrl[7][2] * $g_iDPI_ratio1, $aCtrl[7][3] * $g_iDPI_ratio1, $aCtrl[7][4] * $g_iDPI_ratio1, $aCtrl[7][5] * $g_iDPI_ratio1) GUICtrlSetBkColor(-1, $GUI_BKCOLOR_TRANSPARENT) GUICtrlSetColor(-1, 0xFFFFFF) GUICtrlSetFont(-1, $aCtrl[7][1] * $g_iDPI_ratio1) #EndRegion PIC #Region AVI $aCtrl[8][2] = 180 $aCtrl[8][3] = 10 $aCtrl[8][4] = 32 $aCtrl[8][5] = 32 $aCtrl[8][0] = GUICtrlCreateAvi($sPath & "Examples\GUI\SampleAVI.avi", 0, $aCtrl[8][2] * $g_iDPI_ratio1, $aCtrl[8][3] * $g_iDPI_ratio1, $aCtrl[8][4] * $g_iDPI_ratio1, $aCtrl[8][5] * $g_iDPI_ratio1, $ACS_AUTOPLAY) GUICtrlSetTip(-1, '#Region AVI') ; TODO $aCtrl[9][2] = 175 $aCtrl[9][3] = 50 $aCtrl[9][4] = 50 $aCtrl[9][5] = 12 $aCtrl[9][1] = 8.5 * $g_iDPI_ratio2 $aCtrl[9][0] = GUICtrlCreateLabel("Sample avi", $aCtrl[9][2] * $g_iDPI_ratio1, $aCtrl[9][3] * $g_iDPI_ratio1, $aCtrl[9][4] * $g_iDPI_ratio1, $aCtrl[9][5] * $g_iDPI_ratio1) GUICtrlSetTip(-1, '#Region AVI - Label') GUICtrlSetFont(-1, $aCtrl[9][1] * $g_iDPI_ratio1) #EndRegion AVI #Region TAB $aCtrl[10][2] = 240 $aCtrl[10][3] = 0 $aCtrl[10][4] = 150 $aCtrl[10][5] = 70 $aCtrl[10][1] = 8.5 * $g_iDPI_ratio2 $aCtrl[10][0] = GUICtrlCreateTab($aCtrl[10][2] * $g_iDPI_ratio1, $aCtrl[10][3] * $g_iDPI_ratio1, $aCtrl[10][4] * $g_iDPI_ratio1, $aCtrl[10][5] * $g_iDPI_ratio1) GUICtrlSetFont(-1, $aCtrl[10][1] * $g_iDPI_ratio1) $aCtrl[11][0] = GUICtrlCreateTabItem("One") GUICtrlSetTip(-1, '#Region TAB1') $aCtrl[12][2] = 244 $aCtrl[12][3] = 35 $aCtrl[12][4] = 140 $aCtrl[12][5] = 24 $aCtrl[12][1] = 8.5 * $g_iDPI_ratio2 $aCtrl[12][0] = GUICtrlCreateLabel("Sample Tab with TabItems", $aCtrl[12][2] * $g_iDPI_ratio1, $aCtrl[12][3] * $g_iDPI_ratio1, $aCtrl[12][4] * $g_iDPI_ratio1, $aCtrl[12][5] * $g_iDPI_ratio1) GUICtrlSetFont(-1, $aCtrl[12][1] * $g_iDPI_ratio1) $aCtrl[13][0] = GUICtrlCreateTabItem("Two") GUICtrlSetTip(-1, '#Region TAB2') $aCtrl[14][0] = GUICtrlCreateTabItem("Three") GUICtrlSetTip(-1, '#Region TAB3') GUICtrlCreateTabItem("") #EndRegion TAB #Region COMBO $aCtrl[15][2] = 250 $aCtrl[15][3] = 80 $aCtrl[15][4] = 120 $aCtrl[15][5] = 100 $aCtrl[15][1] = 8.5 * $g_iDPI_ratio2 $aCtrl[15][0] = GUICtrlCreateCombo("Sample Combo", $aCtrl[15][2] * $g_iDPI_ratio1, $aCtrl[15][3] * $g_iDPI_ratio1, $aCtrl[15][4] * $g_iDPI_ratio1, $aCtrl[15][5] * $g_iDPI_ratio1) GUICtrlSetTip(-1, '#Region COMBO') GUICtrlSetFont(-1, $aCtrl[15][1] * $g_iDPI_ratio1) #EndRegion COMBO #Region PROGRESS $aCtrl[16][2] = 60 $aCtrl[16][3] = 80 $aCtrl[16][4] = 150 $aCtrl[16][5] = 20 $aCtrl[16][0] = GUICtrlCreateProgress($aCtrl[16][2] * $g_iDPI_ratio1, $aCtrl[16][3] * $g_iDPI_ratio1, $aCtrl[16][4] * $g_iDPI_ratio1, $aCtrl[16][5] * $g_iDPI_ratio1) GUICtrlSetTip(-1, '#Region PROGRES') GUICtrlSetData(-1, 60) $aCtrl[17][2] = 5 $aCtrl[17][3] = 82 $aCtrl[17][4] = 50 $aCtrl[17][5] = 18 $aCtrl[17][1] = 8.5 * $g_iDPI_ratio2 $aCtrl[17][0] = GUICtrlCreateLabel("Progress:", $aCtrl[17][2] * $g_iDPI_ratio1, $aCtrl[17][3] * $g_iDPI_ratio1, $aCtrl[17][4] * $g_iDPI_ratio1, $aCtrl[17][5] * $g_iDPI_ratio1) GUICtrlSetTip(-1, '#Region PROGRES - Label') GUICtrlSetFont(-1, $aCtrl[17][1] * $g_iDPI_ratio1) #EndRegion PROGRESS #Region EDIT $aCtrl[18][2] = 10 $aCtrl[18][3] = 110 $aCtrl[18][4] = 150 $aCtrl[18][5] = 70 $aCtrl[18][1] = 8.5 * $g_iDPI_ratio2 $aCtrl[18][0] = GUICtrlCreateEdit(@CRLF & " Sample Edit Control", $aCtrl[18][2] * $g_iDPI_ratio1, $aCtrl[18][3] * $g_iDPI_ratio1, $aCtrl[18][4] * $g_iDPI_ratio1, $aCtrl[18][5] * $g_iDPI_ratio1) GUICtrlSetTip(-1, '#Region EDIT') GUICtrlSetFont(-1, $aCtrl[18][1] * $g_iDPI_ratio1) #EndRegion EDIT #Region LIST $aCtrl[19][2] = 5 $aCtrl[19][3] = 190 $aCtrl[19][4] = 100 $aCtrl[19][5] = 90 $aCtrl[19][1] = 8.5 * $g_iDPI_ratio2 $aCtrl[19][0] = GUICtrlCreateList("", $aCtrl[19][2] * $g_iDPI_ratio1, $aCtrl[19][3] * $g_iDPI_ratio1, $aCtrl[19][4] * $g_iDPI_ratio1, $aCtrl[19][5] * $g_iDPI_ratio1) GUICtrlSetFont(-1, $aCtrl[19][1] * $g_iDPI_ratio1) GUICtrlSetTip(-1, '#Region LIST') GUICtrlSetData(-1, "A.Sample|B.List|C.Control|D.Here", "B.List") #EndRegion LIST #Region ICON $aCtrl[20][2] = 175 $aCtrl[20][3] = 120 $aCtrl[20][4] = 32 $aCtrl[20][5] = 32 $aCtrl[20][0] = GUICtrlCreateIcon("explorer.exe", 0, $aCtrl[20][2] * $g_iDPI_ratio1, $aCtrl[20][3] * $g_iDPI_ratio1, $aCtrl[20][4] * $g_iDPI_ratio1, $aCtrl[20][5] * $g_iDPI_ratio1) GUICtrlSetTip(-1, '#Region ICON') $aCtrl[21][2] = 180 $aCtrl[21][3] = 160 $aCtrl[21][4] = 50 $aCtrl[21][5] = 20 $aCtrl[21][1] = 8.5 * $g_iDPI_ratio2 $aCtrl[21][0] = GUICtrlCreateLabel("Icon", $aCtrl[21][2] * $g_iDPI_ratio1, $aCtrl[21][3] * $g_iDPI_ratio1, $aCtrl[21][4] * $g_iDPI_ratio1, $aCtrl[21][5] * $g_iDPI_ratio1) GUICtrlSetTip(-1, '#Region ICON - Label') GUICtrlSetFont(-1, $aCtrl[21][1] * $g_iDPI_ratio1) #EndRegion ICON #Region LIST VIEW $aCtrl[22][2] = 110 $aCtrl[22][3] = 190 $aCtrl[22][4] = 110 $aCtrl[22][5] = 80 $aCtrl[22][1] = 8.5 * $g_iDPI_ratio2 $aCtrl[22][0] = GUICtrlCreateListView("Sample|ListView|", $aCtrl[22][2] * $g_iDPI_ratio1, $aCtrl[22][3] * $g_iDPI_ratio1, $aCtrl[22][4] * $g_iDPI_ratio1, $aCtrl[22][5] * $g_iDPI_ratio1) GUICtrlSetTip(-1, '#Region LIST VIEW') GUICtrlSetFont(-1, $aCtrl[22][1] * $g_iDPI_ratio1) GUICtrlCreateListViewItem("A|One", $aCtrl[22][0]) GUICtrlCreateListViewItem("B|Two", $aCtrl[22][0]) GUICtrlCreateListViewItem("C|Three", $aCtrl[22][0]) #EndRegion LIST VIEW #Region GROUP WITH RADIO BUTTONS $aCtrl[23][2] = 230 $aCtrl[23][3] = 120 $aCtrl[23][4] = 110 $aCtrl[23][5] = 80 $aCtrl[23][1] = 8.5 * $g_iDPI_ratio2 $aCtrl[23][0] = GUICtrlCreateGroup("Sample Group", $aCtrl[23][2] * $g_iDPI_ratio1, $aCtrl[23][3] * $g_iDPI_ratio1, $aCtrl[23][4] * $g_iDPI_ratio1, $aCtrl[23][5] * $g_iDPI_ratio1) GUICtrlSetFont(-1, $aCtrl[22][1] * $g_iDPI_ratio1) $aCtrl[24][2] = 250 $aCtrl[24][3] = 140 $aCtrl[24][4] = 80 $aCtrl[24][5] = 32 $aCtrl[24][1] = 8.5 * $g_iDPI_ratio2 $aCtrl[24][0] = GUICtrlCreateRadio("Radio One", $aCtrl[24][2] * $g_iDPI_ratio1, $aCtrl[24][3] * $g_iDPI_ratio1, $aCtrl[24][4] * $g_iDPI_ratio1, $aCtrl[24][5] * $g_iDPI_ratio1) GUICtrlSetTip(-1, '#Region GROUP WITH RADIO BUTTONS- RADIO1') GUICtrlSetFont(-1, $aCtrl[24][1] * $g_iDPI_ratio1) GUICtrlSetState(-1, $GUI_CHECKED) $aCtrl[25][2] = 250 $aCtrl[25][3] = 165 $aCtrl[25][4] = 80 $aCtrl[25][5] = 32 $aCtrl[25][1] = 8.5 * $g_iDPI_ratio2 $aCtrl[25][0] = GUICtrlCreateRadio("Radio Two", $aCtrl[25][2] * $g_iDPI_ratio1, $aCtrl[25][3] * $g_iDPI_ratio1, $aCtrl[25][4] * $g_iDPI_ratio1, $aCtrl[25][5] * $g_iDPI_ratio1) GUICtrlSetTip(-1, '#Region GROUP WITH RADIO BUTTONS- RADIO2') GUICtrlSetFont(-1, $aCtrl[25][1] * $g_iDPI_ratio1) GUICtrlCreateGroup("", -99, -99, 1, 1) ;close group #EndRegion GROUP WITH RADIO BUTTONS #Region UPDOWN $aCtrl[26][2] = 350 $aCtrl[26][3] = 113 $aCtrl[26][4] = 40 $aCtrl[26][5] = 12 $aCtrl[26][1] = 8 * $g_iDPI_ratio2 $aCtrl[26][0] = GUICtrlCreateLabel("UpDown", $aCtrl[26][2] * $g_iDPI_ratio1, $aCtrl[26][3] * $g_iDPI_ratio1, $aCtrl[26][4] * $g_iDPI_ratio1, $aCtrl[26][5] * $g_iDPI_ratio1) GUICtrlSetTip(-1, '#Region UPDOWN - Label') GUICtrlSetFont(-1, $aCtrl[26][1] * $g_iDPI_ratio1) $aCtrl[27][2] = 350 $aCtrl[27][3] = 130 $aCtrl[27][4] = 40 $aCtrl[27][5] = 20 $aCtrl[27][1] = 8.5 * $g_iDPI_ratio2 $aCtrl[27][0] = GUICtrlCreateInput("42", $aCtrl[27][2] * $g_iDPI_ratio1, $aCtrl[27][3] * $g_iDPI_ratio1, $aCtrl[27][4] * $g_iDPI_ratio1, $aCtrl[27][5] * $g_iDPI_ratio1) GUICtrlSetTip(-1, '#Region UPDOWN - Input') GUICtrlSetFont(-1, $aCtrl[27][1] * $g_iDPI_ratio1) $aCtrl[28][0] = GUICtrlCreateUpdown(-1) GUICtrlSetTip(-1, '#Region UPDOWN - Updown') #EndRegion UPDOWN #Region LABEL $aCtrl[29][2] = 350 $aCtrl[29][3] = 165 $aCtrl[29][4] = 40 $aCtrl[29][5] = 40 $aCtrl[29][1] = 8.5 * $g_iDPI_ratio2 $aCtrl[29][0] = GUICtrlCreateLabel("Green" & @CRLF & "Label", $aCtrl[29][2] * $g_iDPI_ratio1, $aCtrl[29][3] * $g_iDPI_ratio1, $aCtrl[29][4] * $g_iDPI_ratio1, $aCtrl[29][5] * $g_iDPI_ratio1) GUICtrlSetTip(-1, '#Region LABEL') GUICtrlSetBkColor(-1, 0x00FF00) GUICtrlSetFont(-1, $aCtrl[29][1] * $g_iDPI_ratio1) #EndRegion LABEL #Region SLIDER $aCtrl[30][2] = 235 $aCtrl[30][3] = 215 $aCtrl[30][4] = 40 $aCtrl[30][5] = 16 $aCtrl[30][1] = 8.5 * $g_iDPI_ratio2 $aCtrl[30][0] = GUICtrlCreateLabel("Slider:", $aCtrl[30][2] * $g_iDPI_ratio1, $aCtrl[30][3] * $g_iDPI_ratio1, $aCtrl[30][4] * $g_iDPI_ratio1, $aCtrl[30][5] * $g_iDPI_ratio1) GUICtrlSetTip(-1, '#Region SLIDER - Label') GUICtrlSetFont(-1, $aCtrl[30][1] * $g_iDPI_ratio1) $aCtrl[31][2] = 270 $aCtrl[31][3] = 210 $aCtrl[31][4] = 120 $aCtrl[31][5] = 30 $aCtrl[31][0] = GUICtrlCreateSlider($aCtrl[31][2] * $g_iDPI_ratio1, $aCtrl[31][3] * $g_iDPI_ratio1, $aCtrl[31][4] * $g_iDPI_ratio1, $aCtrl[31][5] * $g_iDPI_ratio1) GUICtrlSetTip(-1, '#Region SLIDER') GUICtrlSetData(-1, 30) #EndRegion SLIDER #Region INPUT $aCtrl[32][2] = 235 $aCtrl[32][3] = 255 $aCtrl[32][4] = 130 $aCtrl[32][5] = 20 $aCtrl[32][1] = 8.5 * $g_iDPI_ratio2 $aCtrl[32][0] = GUICtrlCreateInput("Sample Input Box", $aCtrl[32][2] * $g_iDPI_ratio1, $aCtrl[32][3] * $g_iDPI_ratio1, $aCtrl[32][4] * $g_iDPI_ratio1, $aCtrl[32][5] * $g_iDPI_ratio1) GUICtrlSetTip(-1, '#Region INPUT') GUICtrlSetFont(-1, $aCtrl[32][1] * $g_iDPI_ratio1) #EndRegion INPUT #Region DATE $aCtrl[33][2] = 5 $aCtrl[33][3] = 280 $aCtrl[33][4] = 200 $aCtrl[33][5] = 20 $aCtrl[33][1] = 8.5 * $g_iDPI_ratio2 $aCtrl[33][0] = GUICtrlCreateDate("", $aCtrl[33][2] * $g_iDPI_ratio1, $aCtrl[33][3] * $g_iDPI_ratio1, $aCtrl[33][4] * $g_iDPI_ratio1, $aCtrl[33][5] * $g_iDPI_ratio1) GUICtrlSetTip(-1, '#Region DATE') GUICtrlSetFont(-1, $aCtrl[33][1] * $g_iDPI_ratio1) $aCtrl[34][1] = 8.5 * $g_iDPI_ratio2 $aCtrl[34][2] = 10 $aCtrl[34][3] = 305 $aCtrl[34][4] = 200 $aCtrl[34][5] = 20 $aCtrl[34][0] = GUICtrlCreateLabel("(Date control expands into a calendar)", $aCtrl[34][2] * $g_iDPI_ratio1, $aCtrl[34][3] * $g_iDPI_ratio1, $aCtrl[34][4] * $g_iDPI_ratio1, $aCtrl[34][5] * $g_iDPI_ratio1) GUICtrlSetTip(-1, '#Region DATE - Label') GUICtrlSetFont(-1, $aCtrl[34][1] * $g_iDPI_ratio1) #EndRegion DATE #Region BUTTON $aCtrl[35][2] = 10 $aCtrl[35][3] = 330 $aCtrl[35][4] = 100 $aCtrl[35][5] = 30 $aCtrl[35][1] = 8.5 * $g_iDPI_ratio2 $aCtrl[35][0] = GUICtrlCreateButton("Click me :-)", $aCtrl[35][2] * $g_iDPI_ratio1, $aCtrl[35][3] * $g_iDPI_ratio1, $aCtrl[35][4] * $g_iDPI_ratio1, $aCtrl[35][5] * $g_iDPI_ratio1) GUICtrlSetTip(-1, '#Region BUTTON') GUICtrlSetFont(-1, $aCtrl[35][1] * $g_iDPI_ratio1) #EndRegion BUTTON #Region CHECKBOX $aCtrl[36][2] = 130 $aCtrl[36][3] = 335 $aCtrl[36][4] = 80 $aCtrl[36][5] = 20 $aCtrl[36][1] = 8.5 * $g_iDPI_ratio2 $aCtrl[36][0] = GUICtrlCreateCheckbox("Checkbox", $aCtrl[36][2] * $g_iDPI_ratio1, $aCtrl[36][3] * $g_iDPI_ratio1, $aCtrl[36][4] * $g_iDPI_ratio1, $aCtrl[36][5] * $g_iDPI_ratio1) GUICtrlSetTip(-1, '#Region CHECKBOX') GUICtrlSetState(-1, $GUI_CHECKED) GUICtrlSetFont(-1, $aCtrl[36][1] * $g_iDPI_ratio1) #EndRegion CHECKBOX #Region TREEVIEW ONE $aCtrl[37][2] = 210 $aCtrl[37][3] = 290 $aCtrl[37][4] = 80 $aCtrl[37][5] = 80 $aCtrl[37][1] = 8.5 * $g_iDPI_ratio2 $aCtrl[37][0] = GUICtrlCreateTreeView($aCtrl[37][2] * $g_iDPI_ratio1, $aCtrl[37][3] * $g_iDPI_ratio1, $aCtrl[37][4] * $g_iDPI_ratio1, $aCtrl[37][5] * $g_iDPI_ratio1) GUICtrlSetTip(-1, '#Region TREEVIEW ONE') GUICtrlSetFont(-1, $aCtrl[37][1] * $g_iDPI_ratio1) $aCtrl[38][0] = GUICtrlCreateTreeViewItem("TreeView", $aCtrl[37][0]) GUICtrlCreateTreeViewItem("Item1", $aCtrl[38][0]) GUICtrlCreateTreeViewItem("Item2", $aCtrl[38][0]) GUICtrlCreateTreeViewItem("Foo", -1) GUICtrlSetState($aCtrl[38][0], $GUI_EXPAND) #EndRegion TREEVIEW ONE #Region TREEVIEW TWO $aCtrl[39][2] = 295 $aCtrl[39][3] = 290 $aCtrl[39][4] = 103 $aCtrl[39][5] = 80 $aCtrl[39][1] = 8.5 * $g_iDPI_ratio2 $aCtrl[39][0] = GUICtrlCreateTreeView($aCtrl[39][2] * $g_iDPI_ratio1, $aCtrl[39][3] * $g_iDPI_ratio1, $aCtrl[39][4] * $g_iDPI_ratio1, $aCtrl[39][5] * $g_iDPI_ratio1, $TVS_CHECKBOXES) GUICtrlSetTip(-1, '#Region TREEVIEW TWO') GUICtrlSetFont(-1, $aCtrl[39][1] * $g_iDPI_ratio1) GUICtrlCreateTreeViewItem("TreeView", $aCtrl[39][0]) GUICtrlCreateTreeViewItem("With", $aCtrl[39][0]) GUICtrlCreateTreeViewItem("$TVS_CHECKBOXES", $aCtrl[39][0]) GUICtrlSetState(-1, $GUI_CHECKED) GUICtrlCreateTreeViewItem("Style", $aCtrl[39][0]) #EndRegion TREEVIEW TWO #Region GUI MESSAGE LOOP GUISetState(@SW_SHOW) If @OSBuild > 9599 Then GUIRegisterMsg($WM_DPICHANGED, "WM_DPICHANGED") ;requires Win 8.1+ / Server 2012 R2+ GUIRegisterMsg($WM_GETMINMAXINFO, "WM_GETMINMAXINFO") GUIRegisterMsg($WM_SIZE, "WM_SIZE") Local $hGUI_child, $hImage, $hGDIBitmap, $hGfx, $hPath, $hFamily, $hFormat, $tLayout, $hPen, $hBrush, $hB, $aGUIGetMsg _GDIPlus_Startup() While 1 Switch GUIGetMsg() Case $GUI_EVENT_CLOSE _GDIPlus_PathDispose($hPath) _GDIPlus_PenDispose($hPen) _GDIPlus_BrushDispose($hBrush) _GDIPlus_FontFamilyDispose($hFamily) _GDIPlus_StringFormatDispose($hFormat) _GDIPlus_ImageDispose ($hImage) _GDIPlus_GraphicsDispose($hGfx) _GDIPlus_Shutdown() GUIRegisterMsg($WM_DPICHANGED, "") GUIRegisterMsg(WM_GETMINMAXINFO, "") GUIRegisterMsg(WM_SIZE, "") GUIDelete() Exit Case $aCtrl[35][0] If $hImage Then $hImage = _GDIPlus_ImageDispose($hImage) $hImage = _GDIPlus_BitmapCreateFromScan0($iw * $g_iDPI_ratio1, $ih * $g_iDPI_ratio1) If $hGfx Then _GDIPlus_GraphicsDispose($hGfx) $hGfx = _GDIPlus_ImageGetGraphicsContext($hImage) _GDIPlus_GraphicsSetTextRenderingHint($hGfx, $GDIP_TEXTRENDERINGHINTANTIALIAS) _GDIPlus_GraphicsSetSmoothingMode($hGfx, $GDIP_SMOOTHINGMODE_HIGHQUALITY) _GDIPlus_GraphicsClear($hGfx, 0xFFF0F0F0) If $hPath Then _GDIPlus_PathDispose($hPath) $hPath = _GDIPlus_PathCreate() If $hFamily Then _GDIPlus_FontFamilyDispose($hFamily) $hFamily = _GDIPlus_FontFamilyCreate("Arial") If $hFormat Then _GDIPlus_StringFormatDispose($hFormat) $hFormat = _GDIPlus_StringFormatCreate() _GDIPlus_StringFormatSetAlign($hFormat, 1) _GDIPlus_StringFormatSetLineAlign($hFormat, 1) $tLayout = _GDIPlus_RectFCreate(0, 0, $iw * $g_iDPI_ratio1, $ih * $g_iDPI_ratio1) _GDIPlus_PathAddString($hPath, "Hello World!", $tLayout, $hFamily, 0, 50 * $g_iDPI_ratio1, $hFormat) If $hPen Then _GDIPlus_PenDispose($hPen) $hPen = _GDIPlus_PenCreate(0xFF000000, 8) _GDIPlus_PenSetLineJoin($hPen, 2) _GDIPlus_GraphicsDrawPath($hGfx, $hPath, $hPen) If $hBrush Then _GDIPlus_BrushDispose($hBrush) $hBrush = _GDIPlus_BrushCreateSolid(0xFF00FF00) _GDIPlus_GraphicsFillPath($hGfx, $hPath, $hBrush) If $hGDIBitmap Then _WinAPI_DeleteObject($hGDIBitmap) $hGDIBitmap = _GDIPlus_BitmapCreateHBITMAPFromBitmap($hImage) Local $aGUI_Pos = WinGetPos($ahWnd[0][0]) $ahWnd[1][0] = GUICreate("GDI+ Child Window", $iw * $g_iDPI_ratio1, $ih * $g_iDPI_ratio1, $aGUI_Pos[0] - ($aGUI_Pos[2] - $iw * $g_iDPI_ratio1) / 2, $aGUI_Pos[1] + $ih * $g_iDPI_ratio1 / 2, $WS_SIZEBOX, -1, $ahWnd[0][0]) $aCtrl[40][2] = 0 $aCtrl[40][3] = 0 $aCtrl[40][4] = $iw $aCtrl[40][5] = $ih $aCtrl[40][0] = GUICtrlCreatePic("", $aCtrl[40][2], $aCtrl[40][3], $aCtrl[40][4] * $g_iDPI_ratio1, $aCtrl[40][5] * $g_iDPI_ratio1) _WinAPI_DeleteObject(GUICtrlSendMsg($aCtrl[40][0], $STM_SETIMAGE, $IMAGE_BITMAP, $hGDIBitmap)) GUISetState(@SW_SHOW, $ahWnd[1][0]) While 1 $aGUIGetMsg = GUIGetMsg(1) Switch $aGUIGetMsg[1] Case $ahWnd[1][0] Switch $aGUIGetMsg[0] Case $GUI_EVENT_CLOSE GUIDelete($ahWnd[1][0]) ExitLoop EndSwitch EndSwitch WEnd EndSwitch WEnd #EndRegion GUI MESSAGE LOOP EndFunc ;==>_Example Func WM_SIZE($hWnd, $iMsg, $wParam, $lParam) #forceref $iMsg, $wParam, $lParam Switch $hWnd Case $ahWnd[1][0] Local $aSize = ControlGetPos($ahWnd[1][0], "", $aCtrl[40][0]) $aCtrl[40][2] = $aSize[0] $aCtrl[40][3] = $aSize[1] $aCtrl[40][4] = _WinAPI_LoWord($lParam) $aCtrl[40][5] = _WinAPI_HiWord($lParam) GUICtrlSetPos($aCtrl[40][0], $aCtrl[40][2], $aCtrl[40][3], $aCtrl[40][4], $aCtrl[40][5]) EndSwitch Return $GUI_RUNDEFMSG EndFunc ;==>WM_SIZE Func WM_GETMINMAXINFO($hWnd, $Msg, $wParam, $lParam) If $hWnd = $ahWnd[1][0] Then Local $minmaxinfo = DllStructCreate("long ptReservedX;long ptReservedY;long ptMaxSizeX; long ptMaxSizeY;long ptMaxPositionX;long ptMaxPositionY;long ptMinTrackSizeX;long ptMinTrackSizeY;long ptMaxTrackSizeX;long ptMaxTrackSizeY ", $lParam) $minmaxinfo.ptMinTrackSizeX = $iw / 2 $minmaxinfo.ptMinTrackSizeY = $ih / 2 $minmaxinfo.ptMaxTrackSizeX = $iw * 3 $minmaxinfo.ptMaxTrackSizeY = $ih * 3 EndIf Return "GUI_RUNDEFMSG" EndFunc ;==>WM_GETMINMAXINFO Func WM_DPICHANGED($hWnd, $iMsg, $wParam, $lParam) #forceref $iMsg Local $iDPI = _WinAPI_LoWord($wParam) ConsoleWrite("DPI change triggered! DPI: " & $iDPI & @CRLF) $g_iDPI_ratio1 = $iDPI / 96 $g_iDPI_ratio2 = $g_iDPI_ratio1 ^ -1 Local $tRECT = DllStructCreate($tagRECT, $lParam) Local $iX = $tRECT.left, $iY = $tRECT.top, $iW = $tRECT.right - $iX, $iH = $tRECT.bottom - $iY, $i Switch $hWnd Case $ahWnd[0][0] _WinAPI_SetWindowPos($ahWnd[0][0], 0, $iX, $iY, $iW, $iH, BitOR($SWP_NOZORDER, $SWP_NOACTIVATE)) For $i = 0 To 39 If $aCtrl[$i][1] Then GUICtrlSetFont($aCtrl[$i][0], $aCtrl[$i][1] * $g_iDPI_ratio1) If $aCtrl[$i][4] Then GUICtrlSetPos($aCtrl[$i][0], $aCtrl[$i][2] * $g_iDPI_ratio1, $aCtrl[$i][3] * $g_iDPI_ratio1, $aCtrl[$i][4] * $g_iDPI_ratio1, $aCtrl[$i][5] * $g_iDPI_ratio1) Next _WinAPI_UpdateWindow($ahWnd[0][0]) Case $ahWnd[1][0] $i = 40 _WinAPI_SetWindowPos($ahWnd[1][0], 0, $iX, $iY, $iW, $iH, BitOR($SWP_NOZORDER, $SWP_NOACTIVATE)) GUICtrlSetPos($aCtrl[$i][0], $aCtrl[$i][2], $aCtrl[$i][3], $aCtrl[$i][4], $aCtrl[$i][5]) _WinAPI_UpdateWindow($ahWnd[1][0]) EndSwitch Return 1 EndFunc ;==>WM_DPICHANGED THX.2 points
-
Need help synchronizing MDI (WS_EX_MDICHILD) window with Child Window (WS_CHILD)
WildByDesign reacted to Nine for a topic
Unless there is a specific reason to mix $WS_CHILD and $WS_EX_MDICHILD, you shouldn't do that. All you will get out of it is useless complexity. Now if you want to adapt the child windows to the size of its parent, here one easy way : ; From Nine #include <GUIConstants.au3> #include <WindowsConstants.au3> Opt("MustDeclareVars", True) Global $hChild1, $hChild2, $aPosGUI Example() Func Example() Local $hGUI = GUICreate("Example", 400, 400, Default, Default, $WS_OVERLAPPEDWINDOW, $WS_EX_COMPOSITED) GUISetBkColor(0x202020) GUISetState() $hChild1 = GUICreate("", 200, 200, 100, 100, $WS_POPUP, $WS_EX_MDICHILD, $hGUI) GUISetBkColor(0xFFFFFF) GUISetState() $hChild2 = GUICreate("", 100, 100, 5, 5, $WS_POPUP, $WS_EX_MDICHILD, $hChild1) GUISetBkColor(0xFF00FF) GUISetState() GUIRegisterMsg($WM_SIZE, WM_SIZE) $aPosGUI = WinGetPos($hGUI) While True Switch GUIGetMsg() Case $GUI_EVENT_CLOSE ExitLoop EndSwitch WEnd EndFunc ;==>Example Func WM_SIZE($hWnd, $iMsg, $wParam, $lParam) Local $aPos = WinGetPos($hWnd), $aChild1 = WinGetPos($hChild1), $aChild2 = WinGetPos($hChild2) WinMove($hChild1, "", $aChild1[0], $aChild1[1], $aChild1[2] + $aPos[2] - $aPosGUI[2], $aChild1[3] + $aPos[3] - $aPosGUI[3]) WinMove($hChild2, "", $aChild2[0], $aChild2[1], $aChild2[2] + $aPos[2] - $aPosGUI[2], $aChild2[3] + $aPos[3] - $aPosGUI[3]) $aPosGUI = $aPos EndFunc ;==>WM_SIZE1 point -
Flat Custom Buttons with NM_CUSTOMDRAW
WildByDesign reacted to Nine for a topic
Here my take on it : ; From Nine #include <GUIConstants.au3> #include <WindowsConstants.au3> #include <StructureConstants.au3> #include <WinAPI.au3> #include <FrameConstants.au3> Global Const $tagNMCUSTOMDRAWINFO = $tagNMHDR & ";dword DrawStage;handle hdc;" & $tagRECT & ";dword_ptr ItemSpec;uint ItemState;lparam lItemParam;" Example() Func Example() Local $hGUI = GUICreate("Example") Local $idBut = GUICtrlCreateButton("Test1", 10, 10, 100, 30) GUICtrlCreateButton("Test2", 10, 50, 100, 30) GUICtrlCreateRadio("Radio", 10, 90, 100, 30) GUICtrlCreateCheckbox("Check", 10, 130, 100, 30) GUIRegisterMsg($WM_NOTIFY, WM_NOTIFY) GUISetState() While True Switch GUIGetMsg() Case $GUI_EVENT_CLOSE ExitLoop Case $idBut ConsoleWrite("Button was pressed" & @CRLF) EndSwitch WEnd EndFunc ;==>Example Func WM_NOTIFY($hWnd, $iMsg, $wParam, $lParam) Local $tInfo = DllStructCreate($tagNMCUSTOMDRAWINFO, $lParam) If _WinAPI_GetClassName($tInfo.hWndFrom) = "Button" And IsString(GUICtrlRead($tInfo.IDFrom)) And $tInfo.Code = $NM_CUSTOMDRAW Then Local $tRECT = DllStructCreate($tagRECT, DllStructGetPtr($tInfo, "left")) Switch $tInfo.DrawStage Case $CDDS_PREPAINT _WinAPI_DrawFrameControl($tInfo.hDC, $tRECT, $DFC_BUTTON, (BitAND($tInfo.ItemState, $CDIS_SELECTED) ? $DFCS_PUSHED : 0) + $DFCS_BUTTONPUSH) _WinAPI_InflateRect($tRECT, -3, -3) Local $hBrush = _WinAPI_CreateSolidBrush(BitAND($tInfo.ItemState, $CDIS_HOT) ? 0xDEAD : 0xBEEF) _WinAPI_FillRect($tInfo.hDC, $tRECT, $hBrush) _WinAPI_DeleteObject($hBrush) Return $CDRF_NOTIFYPOSTPAINT Case $CDDS_POSTPAINT _WinAPI_InflateRect($tRECT, -6, -6) _WinAPI_SetTextColor($tInfo.hDC, 0xFFFFFF) _WinAPI_SetBkColor($tInfo.hDC, BitAND($tInfo.ItemState, $CDIS_HOT) ? 0xDEAD : 0xBEEF) _WinAPI_DrawText($tInfo.hDC, GUICtrlRead($tInfo.IDFrom), $tRECT, BitOR($DT_CENTER, $DT_VCENTER)) EndSwitch EndIf Return $GUI_RUNDEFMSG EndFunc ;==>WM_NOTIFY1 point -
save your script with UTF-8 encoding Edit: and change _WinWaitActivate("classname=Shell_TrayWnd","") to _WinWaitActivate("[CLASS:Shell_TrayWnd]","")1 point
-
WinSockUDF - TCP/UDP Networking Library for AutoIt
WildByDesign reacted to water for a topic
Do you run the "AutoIt (Dark)" theme? The dark mode caused the unreadable text.1 point -
Something like this ? #include "Json.au3" ConsoleWrite("- Test8() : " & Test8() & @CRLF) Func Test8() ; Your three JSON strings Local $Json1 = '{"name":"John","age":30,"locations":[]}' Local $Json2 = '{"City":"Paris","Country":"France"}' Local $Json3 = '{"City":"London","Country":"England"}' ; Decode Local $obj1 = Json_Decode($Json1) Json_ObjPut($obj1,"locations", Json_Decode("[" & $Json2 & "," & $Json3 & "]")) Local $final = Json_Encode($obj1, $JSON_PRETTY_PRINT) ConsoleWrite($final & @CRLF) EndFunc ;==>Test81 point
-
Bug in map ( and how to avoid it )
WildByDesign reacted to AspirinJunkie for a topic
First, I pared down the script to the essentials: For $i = 1 To 20 ; create new(!) map, add one element to the string index "c" (which calculated position in the internal list is index 8) Global $m1[] $m1["c"] = 1 ; check if there`s a value at the index 8 (shouldn`t) If $m1[8] Then ConsoleWrite($m1[8] & @CRLF) ; create another map and add value at the same integer index as the one $m1 checked Global $m2[] $m2[8] = 1 Next I made the following observations: 1. It does not occur with all string indexes, but only with some. It is noticeable that each string index has a fixed associated integer index. If you use a different integer index, the phenomenon does not occur. So far, I have found the following combinations in which the phenomenon occurs: | String-Index | Integer-Index | | ------------ | ------------- | | "[" | 0 | | "<" | 1 | | "" | 5 | | "c" | 8 | | "D" | 9 | | "%" | 10 | | "k" | 16 | | "L" | 17 | | "-" | 18 | | "s" | 24 | | "T" | 25 | | "{" | 32 | | "\" | 33 | | "=" | 34 | These relationships can be explained well using hash index collisions. AutoIt uses the DJB2 hash function in its maps. If you use this for the letters and then scale it to the table size using modulo, you get exactly the corresponding integer indices. Only the table size is obviously not fixed, as the index sometimes fits for 32 elements and sometimes for 64. For example: “c” has a DJB2 hash value of 177672. If we assume that the map in AutoIt has 32 elements at that point, the index for “c” is calculated as 177672 % 32 = 8. This also works for the other string indexes. E.g., “D” --> 177641 % 32 = 9 or “” --> 5381 % 32 = 5. Only the size of the hash table is obviously variable, as some fit for a size of 32 elements and some for 64. However, thanks to the bug, we can learn a lot about the internal structure of AutoIt maps. They are DJB2-based hash tables that start with 32 or 64 elements. 2. This behavior only occurs when the map $m2 is created and an element is created with the same integer index as in $m1. If only this index is set, a match is reported very often. If other indexes are also set, the match does not occur as frequently. One possible explanation for this behavior is as follows: A hash table is essentially an array with a specific size. This size is fundamentally independent of the number of elements it contains (resizing makes sense but is not mandatory). In this case, a map is obviously initially populated with either 32 or 64 elements. When a value is added to the hash table, the hash value of the key is calculated and this calculated value is mapped to the array size using modulo. If the key is “c”, for example, the DJB2 hash (the hash algorithm used in AutoIt) is 177672. To obtain an index for our array in the map, we have to reduce this hash value to the range 32 or 64. This is easy to do using the modulo operator. And with 177672 % 32, we get 8 as the result. The value for the key “c” is therefore stored in the internal array at index 8. However, since several keys could end up at index 8, we need to create a way to hold multiple elements there. For each index, a list is created (a “bucket”) that contains all elements whose key matches this index. The key and value of these elements are then simply stored one after the other in the bucket itself. When a value is queried, the index is first calculated and then this bucket is traversed linearly to see if the specific key is contained in it. In AutoIt, these buckets do not necessarily seem to be used only by one map instance. At some point, two maps share a bucket, resulting in a phenomenon like the one we see here. So you would have to take a closer look at the initialization of the map to see exactly where the problem lies.1 point -
AutoIt Snippets
ioa747 reacted to WildByDesign for a topic
System Tray Menu Auto-Light/Dark Mode: If your system theme is a light mode theme, it will make the system tray menu light. Dark theme will show dark tray menu. I used to apply dark mode to the system tray menu before by creating a GUI that was never shown. But now I realized that I don't have to create that GUI and simply get the handle for the hidden AutoIt window and apply to that handle. #NoTrayIcon #include <MsgBoxConstants.au3> #include <StringConstants.au3> #include <TrayConstants.au3> #include <SendMessage.au3> #include <WindowsNotifsConstants.au3> Global $hTray = _GetHwndFromPID(@AutoItPID) Global $bIsDarkMode = _WinAPI_ShouldAppsUseDarkMode() ; DPI Awareness DllCall("User32.dll", "bool", "SetProcessDpiAwarenessContext" , "HWND", "DPI_AWARENESS_CONTEXT" -2) Opt("TrayMenuMode", 3) Example() Func Example() ; Create a tray item with the radio item parameter selected. TrayCreateItem("Radio 1", -1, -1, $TRAY_ITEM_RADIO) TrayItemSetState(-1, $TRAY_CHECKED) TrayCreateItem("Radio 2", -1, -1, $TRAY_ITEM_RADIO) TrayCreateItem("Radio 3", -1, -1, $TRAY_ITEM_RADIO) TrayCreateItem("") ; Create a separator line. Local $idExit = TrayCreateItem("Exit") TraySetState($TRAY_ICONSTATE_SHOW) ; Show the tray menu. If $bIsDarkMode Then DarkMode($hTray, True) While 1 Switch TrayGetMsg() Case $idExit ; Exit the loop. ExitLoop EndSwitch WEnd EndFunc ;==>Example ;-------------------------------------------------------------------------------------------------------------------------------- ; https://www.autoitscript.com/forum/topic/211475-darkmode-udf-for-autoits-win32guis/#comment-1530103 ;-------------------------------------------------------------------------------------------------------------------------------- Func DarkMode($hWnd, $bDarkMode = True) ; DarkMode Local Enum $DWMWA_USE_IMMERSIVE_DARK_MODE = (@OSBuild <= 18985) ? 19 : 20 Local $iRet = _WinAPI_DwmSetWindowAttribute_unr($hWnd, $DWMWA_USE_IMMERSIVE_DARK_MODE, $bDarkMode) If Not $iRet Then Return SetError(1, 0, -1) _SetCtrlColorMode($hWnd, $bDarkMode) EndFunc ;==>DarkMode ;-------------------------------------------------------------------------------------------------------------------------------- Func _SetCtrlColorMode($hWnd, $bDarkMode = True, $sName = Default) ; 'Explorer', 'CFD', 'DarkMode_ItemsView', etc. If $sName = Default Then $sName = $bDarkMode ? 'DarkMode_Explorer' : 'Explorer' $bDarkMode = Not Not $bDarkMode ; https://www.vbforums.com/showthread.php?900444-Windows-10-Dark-Mode-amp-VB6-apps If Not IsHWnd($hWnd) Then $hWnd = GUICtrlGetHandle($hWnd) Local Enum $eDefault, $eAllowDark, $eForceDark, $eForceLight, $eMax ; enum PreferredAppMode DllCall('uxtheme.dll', 'bool', 133, 'hwnd', $hWnd, 'bool', $bDarkMode) ; fnAllowDarkModeForWindow = 133 DllCall('uxtheme.dll', 'int', 135, 'int', ($bDarkMode ? $eForceDark : $eForceLight)) ; fnAllowDarkModeForApp = 135 _WinAPI_SetWindowTheme_unr($hWnd, $sName) ; https://www.autoitscript.com/forum/index.php?showtopic=211475&view=findpost&p=1530103 DllCall('uxtheme.dll', 'none', 104) ; fnRefreshImmersiveColorPolicyState = 104 ; not needed ? _SendMessage($hWnd, $WM_THEMECHANGED, 0, 0) ; not needed ? EndFunc ;==>_SetCtrlColorMode ;-------------------------------------------------------------------------------------------------------------------------------- Func _WinAPI_SetWindowTheme_unr($hWnd, $sName = Null, $sList = Null) ; #include <WinAPITheme.au3> ; unthoughtful unrestricting mod. ;Causes a window to use a different set of visual style information than its class normally uses Local $sResult = DllCall('UxTheme.dll', 'long', 'SetWindowTheme', 'hwnd', $hWnd, 'wstr', $sName, 'wstr', $sList) If @error Then Return SetError(@error, @extended, 0) If $sResult[0] Then Return SetError(10, $sResult[0], 0) Return 1 EndFunc ;==>_WinAPI_SetWindowTheme_unr ;-------------------------------------------------------------------------------------------------------------------------------- Func _WinAPI_DwmSetWindowAttribute_unr($hWnd, $iAttribute, $iData) ; #include <WinAPIGdi.au3> ; unthoughtful unrestricting mod. ;Sets the value of the specified attributes for non-client rendering to apply to the window Local $aCall = DllCall('dwmapi.dll', 'long', 'DwmSetWindowAttribute', 'hwnd', $hWnd, 'dword', $iAttribute, _ 'dword*', $iData, 'dword', 4) If @error Then Return SetError(@error, @extended, 0) If $aCall[0] Then Return SetError(10, $aCall[0], 0) Return 1 EndFunc ;==>_WinAPI_DwmSetWindowAttribute_unr ;-------------------------------------------------------------------------------------------------------------------------------- Func _WinAPI_ShouldAppsUseDarkMode() Local $fnShouldAppsUseDarkMode = 132 Local $aResult = DllCall('UxTheme.dll', 'bool', $fnShouldAppsUseDarkMode) If @error Then Return SetError(@error, @extended, False) Return $aResult[0] EndFunc ;==>_WinAPI_ShouldAppsUseDarkMode ;-------------------------------------------------------------------------------------------------------------------------------- ; Function for getting HWND from PID Func _GetHwndFromPID($PID) $hWnd = 0 $winlist = WinList() For $i = 1 To $winlist[0][0] If $winlist[$i][0] <> "" Then $iPID2 = WinGetProcess($winlist[$i][1]) If $iPID2 = $PID Then $hWnd = $winlist[$i][1] ExitLoop EndIf EndIf Next Return $hWnd EndFunc ;==>_GetHwndFromPID1 point -
#include <AutoItConstants.au3> HotKeySet("{ENTER}", "MouseClickAction") While 1 Sleep(100) WEnd Func MouseClickAction() HotKeySet("{ENTER}") MouseClick($MOUSE_CLICK_LEFT, 134, 163, 2, 0) Sleep(100) HotKeySet("{ENTER}", "MouseClickAction") EndFunc If you want to leave after clicking #include <AutoItConstants.au3> HotKeySet("{ENTER}", "MouseClickAction") Global $bActive = True While $bActive Sleep(100) WEnd Func MouseClickAction() HotKeySet("{ENTER}") MouseClick($MOUSE_CLICK_LEFT, 134, 163, 2, 0) $bActive = False EndFunc1 point
-
Monitor UDF - Advanced monitor management and multi-monitor utilities.
argumentum reacted to Trong for a topic
Added function!1 point -
Nah, that would be even worst. Let say I want to start at position 3 and search until the end. Based on help file, I would use : _ArraySearch($aArray, 5, 3, 0) But on your logic, I would get an error !1 point
-
Hi all, I'll try to keep this succinct... Since windows 10 1903 it has been possible to embed UWP controls (i.e. XAML controls) in win32 apps. The container that holds a XAML control is a XAML Island. For non-legacy media playback, Microsoft tells us to use the WinRT MediaPlayer object with the MediaPlayerElement control. MediaPlayerElement is the UI & video rendering component of the player (the XAML control). The other MediaPlayer object is the bones of the player which you attach to the control. To get this working you annoyingly need to add the maxversiontested element to the application manifest. There's script in the zip which will copy AutoIt.exe (or AutoIt_x64.exe if you're using it) and update its manifest. If you replace the original file with the modified one, you should be able to successfully run the example with the F5 key. Or here's a screenshot if you just want to see the result! PS. As an aside, Another way of approaching modern playback is via MediaEngine which we've recently attempted to get going. This approach doesn't play well with autoit though, and you need to do ungodly things to prevent callbacks from crashing your script! MediaPlayer.zip1 point
-
AutoIt Live Wallpaper
WildByDesign reacted to argumentum for a topic
... <compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1"> <application> <!--The ID below indicates application support for Windows Vista --> <supportedOS Id="{e2011457-1546-43c5-a5fe-008deee3d3f0}"/> <!--The ID below indicates application support for Windows 7 --> <supportedOS Id="{35138b9a-5d96-4fbd-8e2d-a2440225f93a}"/> <!--The ID below indicates application support for Windows 8 --> <supportedOS Id="{4a2f28e3-53b9-4441-ba9c-d69d4a4a6e38}"/> <!--The ID below indicates application support for Windows 8.1 --> <supportedOS Id="{1f676c76-80e1-4239-95bb-83d0f6d0da78}"/> <!--The ID below indicates application support for Windows 10 --> <supportedOS Id="{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}"/> </application> </compatibility> </assembly> ... Runed it with the above. Did black out both monitors and restored the wallpaper just fine. But did not play the included bloom.mp4. Maybe because I need to patch the exe/wrapper ?1 point -
Guiscape -- A new GUI builder project!
WildByDesign reacted to jaberwacky for a topic
Hey! Would someone be willing to try this out please? https://github.com/matthewrg/Guiscape/archive/refs/heads/main.zip1 point -
Ok that works, kinda, it doesnt trigger until I moved the mouse from the start button and into the window.1 point
-
reduce the use of global variables __ExampleA() Func __ExampleA() __Get_Global() __Get_Global('add', 'Msg', 'Is it working?') __Print() __Get_Global('CLose') EndFunc Func __Print() ConsoleWrite('!: ' & __Get_Global('get', 'Msg') & @crlf) EndFunc ; #FUNCTION# ============================================================================= ; Name ..........: __Get_Global ; ======================================================================================== Func __Get_Global($method = -1, $sKey = '', $sValue = '') Local Static $o_SDist If Not IsObj($o_SDist) Then $o_SDist = ObjCreate( "Scripting.Dictionary" ) If Not IsObj($o_SDist) Then Return SetError(1) Endif IF (($method = 'add') AND ($sKey <> '')) Then If $o_SDist.Exists($sKey) Then Return $o_SDist.Add($sKey, $sValue) EndIf IF (($method = 'get') AND ($sKey <> '')) Then Return $o_SDist.Item($sKey) IF $method = 'CLose' Then $o_SDist = 0 EndFunc1 point
-
OnDebugMsgBox
Parsix reacted to argumentum for a file
Version 2.2024.1.26
964 downloads
..a more flexible way to handle a This UDF, declared as the first ( or close to the top ) in a script, will catch the dreaded "AutoIt Error" MsgBox and prettify it, or just plain hide it. Is optional. Also add an EventLog Entry ( or not, is optional ). Add an entry in a log file ( or not, is optional ). Run another program to do something about the mishap ( or not, is optional ). There is an example of usage in the ZIP along with an example of the other program that handles the aftermath.1 point -
I fixed this by using the "Compile script to .exe" tool and setting compatibility mode on the generated executable to run as Administrator. Works in Windows 7 and Windows 10.1 point
-
Can you try this (GDI+ version only): AutoIt version 3.3.10.0 or higher needed! #include <Array.au3> #include <GDIPlus.au3> #include <MsgBoxConstants.au3> _GDIPlus_Startup() Global $hImage1, $hImage2 Global $sImages = FileOpenDialog("Select 2 images", "", "Image (*.bmp;*.jpg;*.png;*.gif)", $FD_MULTISELECT) If @error Then _Exit("Nothing selected") Global $aFiles = StringSplit($sImages, "|", 2) If (UBound($aFiles) < 3) Then _Exit("Select at least 2 images") $hImage1 = _GDIPlus_ImageLoadFromFile($aFiles[1]) If @error Then _Exit("Unable to load " & $aFiles[1]) $hImage2 = _GDIPlus_ImageLoadFromFile($aFiles[2]) If @error Then _Exit("Unable to load " & $aFiles[2]) If (_GDIPlus_ImageGetWidth($hImage1) <> _GDIPlus_ImageGetWidth($hImage2)) Then _Exit("Width of both images are different") If (_GDIPlus_ImageGetHeight($hImage1) <> _GDIPlus_ImageGetHeight($hImage2)) Then _Exit("Height of both images are different") Global $bFastCmp = True Global $aDiff = _GDIPlus_ImageCompare($hImage1, $hImage2, $bFastCmp) If $bFastCmp Then Exit MsgBox($MB_SYSTEMMODAL, "Compared", "Equal: " & $aDiff & " / " & @extended & " ms") Global $iChk = MsgBox(BitOR($MB_SYSTEMMODAL, $MB_YESNO), "Information", "Found " & Round((UBound($aDiff) - 1) / ($aDiff[0][1] * $aDiff[0][2]) * 100, 2) & " % differences in " & Round($aDiff[0][0], 2) & " ms." & _ @CRLF & @CRLF & _ "Display the array with information") If ($iChk = 6) Then _ArrayDisplay($aDiff, "Differences", Default, Default, Default, "Runtime / Coordinate (x,y)|Image1 Color|Image2 Color") Func _GDIPlus_ImageCompare($hImage1, $hImage2, $bFastCmp = True) Local Const $iW = _GDIPlus_ImageGetWidth($hImage1), $iH = _GDIPlus_ImageGetHeight($hImage1) If ($iW <> _GDIPlus_ImageGetWidth($hImage2)) Then Return SetError(1, 0, 0) If ($iH <> _GDIPlus_ImageGetHeight($hImage2)) Then Return SetError(2, 0, 0) Local $t = TimerInit() Local $tBitmapData1 = _GDIPlus_BitmapLockBits($hImage1, 0, 0, $iW, $iH, $GDIP_ILMREAD, $GDIP_PXF32ARGB) Local $tBitmapData2 = _GDIPlus_BitmapLockBits($hImage2, 0, 0, $iW, $iH, $GDIP_ILMREAD, $GDIP_PXF32ARGB) Local $pScan1 = DllStructGetData($tBitmapData1, "Scan0") Local $tPixel1 = DllStructCreate("uint[" & $iW * $iH & "];", $pScan1) Local $iStride = Abs(DllStructGetData($tBitmapData1, "Stride")) Local $pScan2 = DllStructGetData($tBitmapData2, "Scan0") Local $tPixel2 = DllStructCreate("uint[" & $iW * $iH & "];", $pScan2) If $bFastCmp Then $iResult = DllCall("msvcrt.dll", "int:cdecl", "memcmp", "ptr", $pScan1, "ptr", $pScan2, "uint", DllStructGetSize($tPixel1))[0] Else If ($iW * $iH + 1) * 3 > 16 * 1024^2 Then Return SetError(3, 0, 0) Local $iX, $iY, $iRowOffset, $iPixel1, $iPixel2, $c = 1, $aDiff[$iW * $iH + 1][3] For $iY = 0 To $iH - 1 $iRowOffset = $iY * $iW + 1 For $iX = 0 To $iW - 1 $iPixel1 = DllStructGetData($tPixel1, 1, $iRowOffset + $iX) ;get pixel color $iPixel2 = DllStructGetData($tPixel2, 1, $iRowOffset + $iX) ;get pixel color If $iPixel1 <> $iPixel2 Then $aDiff[$c][0] = $iX & ", " & $iY $aDiff[$c][1] = "0x" & Hex($iPixel1, 8) $aDiff[$c][2] = "0x" & Hex($iPixel2, 8) $c += 1 EndIf Next Next $aDiff[0][0] = TimerDiff($t) $aDiff[0][1] = $iW $aDiff[0][2] = $iH EndIf _GDIPlus_BitmapUnlockBits($hImage1, $tBitmapData1) _GDIPlus_BitmapUnlockBits($hImage2, $tBitmapData2) If $bFastCmp Then Return SetError(0, Int(TimerDiff($t)), $iResult = 0) ReDim $aDiff[$c][3] Return $aDiff EndFunc Func _Exit($sError = "") If $sError <> "" Then MsgBox($MB_ICONERROR, "ERROR", $sError) If ($hImage1 <> 0) Then _GDIPlus_ImageDispose($hImage1) If ($hImage2 <> 0) Then _GDIPlus_ImageDispose($hImage2) _GDIPlus_Shutdown() Exit EndFunc Br, UEZ1 point