Jump to content

Leaderboard

Popular Content

Showing content with the highest reputation since 11/06/2025 in all areas

  1. 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 GitHub
    6 points
  2. MattyD

    Round buttons

    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_DRAWITEM
    3 points
  3. 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] EndFunc
    3 points
  4. Nine

    Round buttons

    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_NOTIFY
    2 points
  5. ioa747

    Round buttons

    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 much
    2 points
  6. Perfect, beautiful, awesome. It all shows and works as advertised 💯
    2 points
  7. 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
  8. 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 Guiscape.zip Downloads: 35
    2 points
  9. 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
  10. 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
  11. ioa747

    GetKeyPress

    #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 EndFunc
    1 point
  12. argumentum

    GetKeyPress

    #include <GUIConstantsEx.au3> #include <MsgBoxConstants.au3> Example() Func Example() GUICreate("Custom MsgBox", 225, 80) GUICtrlCreateLabel("Please select a button.", 10, 10) Local $idButton_Yes = GUICtrlCreateButton("Yes", 10, 50, 65, 25) Local $idButton_No = GUICtrlCreateButton("No", 80, 50, 65, 25) Local $idButton_Exit = GUICtrlCreateButton("Exit", 150, 50, 65, 25) ; Set GUIAccelerators for the button controlIDs, these being Ctrl + y and Ctrl + n Local $aAccelKeys[2][2] = [["^y", $idButton_Yes], ["^n", $idButton_No]] GUISetAccelerators($aAccelKeys) GUISetState(@SW_SHOW) ; Display the GUI. While 1 Switch GUIGetMsg() Case $GUI_EVENT_CLOSE MsgBox($MB_SYSTEMMODAL, "You selected", "Close") ExitLoop Case $idButton_Yes MsgBox($MB_SYSTEMMODAL, "You selected", "Yes") ; Displays if the button was selected or the hotkey combination Ctrl + y was pressed. Case $idButton_No MsgBox($MB_SYSTEMMODAL, "You selected", "No") ; Displays if the button was selected or the hotkey combination Ctrl + n was pressed. Case $idButton_Exit MsgBox($MB_SYSTEMMODAL, "You selected", "Exit") ExitLoop EndSwitch WEnd GUIDelete() ; Delete the GUI. EndFunc ;==>Example ..is in the help file.
    1 point
  13. @Parsix Here is my entire modified code: ;~ https://www.autoitscript.com/forum/topic/154081-avoid-autoit-error-message-box-in-unknown-errors/page/4/#findComment-1547350 #Region - AutoIt3Wrapper directives section ; General section #AutoIt3Wrapper_UseX64=n #AutoIt3Wrapper_UseUpx=n #AutoIt3Wrapper_Compression=4 ; Au3Check section #AutoIt3Wrapper_Au3Check_Parameters=-d -w 1 -w 2 -w 6 -w 7 ; Au3Stripper section #AutoIt3Wrapper_Run_Au3Stripper=y #Au3Stripper_Parameters=/so /pe #AutoIt3Wrapper_Au3Stripper_OnError=C #EndRegion - AutoIt3Wrapper directives section #include <WinApi.au3> #Region - exmaple AddHookApi("user32.dll", "MessageBoxW", "Intercept_MessageBoxW", "int", "hwnd;wstr;wstr;uint") MsgBox(0, 'Test', 'Some normal MsgBox text') DllStructCreate("byte[123456789097]") ; This is a deliberate action intended to display an error, as this script demonstrates how to change error handling - interact with MsgBox's title and text. #EndRegion - exmaple #Region @trancexx - https://www.autoitscript.com/forum/topic/154081-avoid-autoit-error-message-box-in-unknown-errors/#findComment-1111917 Func Intercept_MessageBoxW($hWnd, $sText, $sTitle, $iType) If $sTitle = 'AutoIt' Then $sTitle = 'TESTING: ' & StringReplace($sTitle, "AutoIt", @ScriptName) Local $aCall = DllCall("user32.dll", "int", "MessageBoxW", _ "hwnd", $hWnd, _ "wstr", $sText, _ "wstr", $sTitle, _ "uint", $iType) If @error Or Not $aCall[0] Then Return 0 Return $aCall[0] EndFunc ;==>Intercept_MessageBoxW ; The magic is down below Func AddHookApi($sModuleName, $vFunctionName, $vNewFunction, $sRet = "", $sParams = "") Local Static $pImportDirectory, $hInstance Local Const $IMAGE_DIRECTORY_ENTRY_IMPORT = 1 If Not $pImportDirectory Then $hInstance = _WinAPI_GetModuleHandle(0) $pImportDirectory = ImageDirectoryEntryToData($hInstance, $IMAGE_DIRECTORY_ENTRY_IMPORT) If @error Then Return SetError(1, 0, 0) EndIf Local $iIsInt = IsInt($vFunctionName) Local $iRestore = Not IsString($vNewFunction) Local $tIMAGE_IMPORT_MODULE_DIRECTORY Local $pDirectoryOffset = $pImportDirectory Local $tModuleName Local $iInitialOffset, $iInitialOffset2 Local $iOffset2 Local $tBufferOffset2, $iBufferOffset2 Local $tBuffer, $tFunctionOffset, $pOld, $fMatch, $pModuleName, $pFuncName Local Const $PAGE_READWRITE = 0x04 While 1 $tIMAGE_IMPORT_MODULE_DIRECTORY = DllStructCreate("dword RVAOriginalFirstThunk;" & _ "dword TimeDateStamp;" & _ "dword ForwarderChain;" & _ "dword RVAModuleName;" & _ "dword RVAFirstThunk", _ $pDirectoryOffset) If Not DllStructGetData($tIMAGE_IMPORT_MODULE_DIRECTORY, "RVAFirstThunk") Then ExitLoop $pModuleName = $hInstance + DllStructGetData($tIMAGE_IMPORT_MODULE_DIRECTORY, "RVAModuleName") $tModuleName = DllStructCreate("char Name[" & _WinAPI_StringLenA($pModuleName) & "]", $pModuleName) If DllStructGetData($tModuleName, "Name") = $sModuleName Then ; function from this module $iInitialOffset = $hInstance + DllStructGetData($tIMAGE_IMPORT_MODULE_DIRECTORY, "RVAFirstThunk") $iInitialOffset2 = $hInstance + DllStructGetData($tIMAGE_IMPORT_MODULE_DIRECTORY, "RVAOriginalFirstThunk") If $iInitialOffset2 = $hInstance Then $iInitialOffset2 = $iInitialOffset $iOffset2 = 0 While 1 $tBufferOffset2 = DllStructCreate("dword_ptr", $iInitialOffset2 + $iOffset2) $iBufferOffset2 = DllStructGetData($tBufferOffset2, 1) If Not $iBufferOffset2 Then ExitLoop If $iIsInt Then If BitAND($iBufferOffset2, 0xFFFFFF) = $vFunctionName Then $fMatch = True ; wanted function Else $pFuncName = $hInstance + $iBufferOffset2 + 2 ; 2 is size od "word", see line below... $tBuffer = DllStructCreate("word Ordinal; char Name[" & _WinAPI_StringLenA($pFuncName) & "]", $hInstance + $iBufferOffset2) If DllStructGetData($tBuffer, "Name") == $vFunctionName Then $fMatch = True ; wanted function EndIf If $fMatch Then $tFunctionOffset = DllStructCreate("ptr", $iInitialOffset + $iOffset2) VirtualProtect(DllStructGetPtr($tFunctionOffset), DllStructGetSize($tFunctionOffset), $PAGE_READWRITE) If @error Then Return SetError(3, 0, 0) $pOld = DllStructGetData($tFunctionOffset, 1) If $iRestore Then DllStructSetData($tFunctionOffset, 1, $vNewFunction) Else DllStructSetData($tFunctionOffset, 1, DllCallbackGetPtr(DllCallbackRegister($vNewFunction, $sRet, $sParams))) EndIf Return $pOld EndIf $iOffset2 += DllStructGetSize($tBufferOffset2) WEnd ExitLoop EndIf $pDirectoryOffset += 20 ; size of $tIMAGE_IMPORT_MODULE_DIRECTORY WEnd Return SetError(4, 0, 0) EndFunc ;==>AddHookApi Func VirtualProtect($pAddress, $iSize, $iProtection) Local $aCall = DllCall("kernel32.dll", "bool", "VirtualProtect", "ptr", $pAddress, "dword_ptr", $iSize, "dword", $iProtection, "dword*", 0) If @error Or Not $aCall[0] Then Return SetError(1, 0, 0) Return 1 EndFunc ;==>VirtualProtect Func ImageDirectoryEntryToData($hInstance, $iDirectoryEntry) ; Get pointer to data Local $pPointer = $hInstance ; Start processing passed binary data. 'Reading' PE format follows. Local $tIMAGE_DOS_HEADER = DllStructCreate("char Magic[2];" & _ "word BytesOnLastPage;" & _ "word Pages;" & _ "word Relocations;" & _ "word SizeofHeader;" & _ "word MinimumExtra;" & _ "word MaximumExtra;" & _ "word SS;" & _ "word SP;" & _ "word Checksum;" & _ "word IP;" & _ "word CS;" & _ "word Relocation;" & _ "word Overlay;" & _ "char Reserved[8];" & _ "word OEMIdentifier;" & _ "word OEMInformation;" & _ "char Reserved2[20];" & _ "dword AddressOfNewExeHeader", _ $pPointer) Local $sMagic = DllStructGetData($tIMAGE_DOS_HEADER, "Magic") ; Check if it's valid format If Not ($sMagic == "MZ") Then Return SetError(1, 0, 0) ; MS-DOS header missing. Btw 'MZ' are the initials of Mark Zbikowski in case you didn't know. ; Move pointer $pPointer += DllStructGetData($tIMAGE_DOS_HEADER, "AddressOfNewExeHeader") ; move to PE file header ; In place of IMAGE_NT_SIGNATURE structure Local $tIMAGE_NT_SIGNATURE = DllStructCreate("dword Signature", $pPointer) ; Check signature If DllStructGetData($tIMAGE_NT_SIGNATURE, "Signature") <> 17744 Then ; IMAGE_NT_SIGNATURE Return SetError(2, 0, 0) ; wrong signature. For PE image should be "PE\0\0" or 17744 dword. EndIf ; Move pointer $pPointer += 4 ; size of $tIMAGE_NT_SIGNATURE structure ; In place of IMAGE_FILE_HEADER structure ; Move pointer $pPointer += 20 ; size of $tIMAGE_FILE_HEADER structure ; Determine the type Local $tMagic = DllStructCreate("word Magic;", $pPointer) Local $iMagic = DllStructGetData($tMagic, 1) Local $tIMAGE_OPTIONAL_HEADER If $iMagic = 267 Then ; x86 version ; Move pointer $pPointer += 96 ; size of $tIMAGE_OPTIONAL_HEADER ElseIf $iMagic = 523 Then ; x64 version ; Move pointer $pPointer += 112 ; size of $tIMAGE_OPTIONAL_HEADER Else Return SetError(3, 0, 0) ; unsupported module type EndIf ; Validate input by checking available number of structures that are in the module Local Const $IMAGE_NUMBEROF_DIRECTORY_ENTRIES = 16 ; predefined value that PE modules always use (AutoIt certainly) If $iDirectoryEntry > $IMAGE_NUMBEROF_DIRECTORY_ENTRIES - 1 Then Return SetError(4, 0, 0) ; invalid input ; Calculate the offset to wanted entry (every entry is 8 bytes) $pPointer += 8 * $iDirectoryEntry ; At place of correst directory entry Local $tIMAGE_DIRECTORY_ENTRY = DllStructCreate("dword VirtualAddress; dword Size", $pPointer) ; Collect data Local $pAddress = DllStructGetData($tIMAGE_DIRECTORY_ENTRY, "VirtualAddress") If $pAddress = 0 Then Return SetError(5, 0, 0) ; invalid input ; $pAddress is RVA, add it to base address Return $hInstance + $pAddress EndFunc ;==>ImageDirectoryEntryToData #EndRegion @trancexx - https://www.autoitscript.com/forum/topic/154081-avoid-autoit-error-message-box-in-unknown-errors/#findComment-1111917 Please note that I also modified this line: Func Intercept_MessageBoxW($hWnd, $sText, $sTitle, $iType) If $sTitle = 'AutoIt' Then $sTitle = 'TESTING: ' & StringReplace($sTitle, "AutoIt", @ScriptName) ... ... "wstr", $sTitle, _ ... ... EndIf
    1 point
  14. This is a deliberate action intended to display an error, as this script demonstrates how to change error handling - interact with MsgBox's title and text.
    1 point
  15. MattyD

    WinRT - WinUI3

    sure thing. - yeah, there are no window handles per se - apart from the WinID of the main window. Everything is done on objects. so that colour change would be something like: $pBrush = CreateSolidBrush("Red") IBorder_SetBackground($apBorders[0], $pBrush) IUnknown_Release($pBrush) In the Sept 3rd. example, to keep things tidy I release the border objects once they're created. So you'd need either need to change the background before releasing, or get the border object back by some other means. Via its parent for example - in this case the grid object (before it too is released!). As for triggering the color change - In this example, once we get into the main loop everything is event based. When we hit the following line the script won't continue until the dispatch loop is broken with _WinUI3_PostQuitMessage. IDispatcherQueue3_RunEventLoop($pDispatchQ) The general idea is to create a bunch of handlers with _WinRT_CreateDelegate(). But if you'd rather work within a while loop, it is possible to create your own dispatcher with _WinUI3_GetMsg / _WinUI3_DispatchMessage. I think there are probably examples of this early in the thread!
    1 point
  16. Nine

    FixGibberish

    Yep, that could work well. Only drawback is the true use of the dead key misconverted into an accented characters. But it is less an issue when you know what you are doing...
    1 point
  17. ioa747

    FixGibberish

    To the new approach, (I updated the first post.) I also added the logic of "dead keys", where the accented characters are a combination of 2 keys, a dead key and a vowel.
    1 point
  18. MattyD

    Round buttons

    Hey ioa, just a suggestion - have you tried giving ownerdrawn buttons a go? WM_DRAWITEM triggers, and will tell you the button state so you can draw it accordingly. Basically you can have your button react to changes in focus, checked, depressed, greyed out states etc etc - without the need for manufacturing events via those dummy controls.
    1 point
  19. yeah, I'd imagine if you were going to accommodate for this, you'd want to change $iEnd = 0 meaning "end of array" and make people use the Default keyword. It would be a script breaking change though. And to be consistent you'll also want to check how "0" and "-1" are used throughout other funcs in the UDF... I'd say there'll be quite a bit of "If $iParam < 1" logic! But its not us that you need to persuade - so if you feel strongly enough about it, you can always make the suggestion in the bugtrac .
    1 point
  20. argumentum

    Get SSL ExpiryTime

    Updated the code above. Posting a "bump" type of post because if you are using this, there were 2 entries that needed to FreeMem in _WinHttp_SSL_Info() and didn't in the prior version.
    1 point
  21. 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
  22. Ah, thanks heaps for that. A simple oversight which I should have picked up on since even in the help file it shows the need to get the window handle. Trying to test waaaaay past my bedtime. For reference just in case I need to google this again in future, this now works: $hWnd = WinGetHandle('[CLASS:Ultimate Jukebox Main]') _SendMessage($hWnd, 1024, 400)
    1 point
  23. TheSaint

    Kobo Cover Fixer

    Latest v2.5 update now available, see the first post. It took two days for my Kobo device battery to get flat enough, before I could resume troubleshooting. During that process I discovered some other issues and fixed them too, So see this update as a BUGFIX Update. [Wednesday 5th November 2025] & [Saturday 8th November 2025] (v2.5) As always with this project, testing is a challenge, so only minimal testing has occurred so far. That means it is recommended you play it safe and do your own backups, until sure my program is reliable ... behaves as it should.
    1 point
  24. This is certainly much better. I was jumping through hoops to get the title/text when it was already possible to get it with what you had originally provided. I think that what got me going in that direction initially was that your original example was comparing "Démarrer" as title/text. So I misunderstood and assumed that I had to put the language specific spelling for "Start". And technically, I do have to. But your updated script does it much better than the extra stuff that I did. Thank you for your time. I really do appreciate it. I tend to ask a lot of questions which I always end up learning significantly from. And having different mindsets come together as they do in this forum, it is always intriguing to see that you can often have the same goal, but with many different methods to achieve it the same goal. As they often say, there is "more than one way to skin a cat". Odd phrase, but that is the true outcome (minus the cats) of many threads in this forum and always insightful to learn this way.
    1 point
  25. Yes it does work. But you could have used the code (that I first post) which reads the name of the start button (should be the same as the title of the window). That would gives you something like this : #include "..\UIAutomation\Includes\UIAEH_AutomationEventHandler.au3" #include <Constants.au3> Opt("MustDeclareVars", True) Global $oWinStart, $sStart HotKeySet("{ESC}", Terminate) Example() Func Example() ; Create UI Automation object Local $oUIAutomation = ObjCreateInterface($sCLSID_CUIAutomation, $sIID_IUIAutomation, $dtag_IUIAutomation) If Not IsObj($oUIAutomation) Then Exit ConsoleWrite("$oUIAutomation ERR" & @CRLF) ;ConsoleWrite("$oUIAutomation OK" & @CRLF) ; Get Desktop element Local $pDesktop, $oDesktop $oUIAutomation.GetRootElement($pDesktop) $oDesktop = ObjCreateInterface($pDesktop, $sIID_IUIAutomationElement, $dtag_IUIAutomationElement) If Not IsObj($oDesktop) Then Exit ConsoleWrite("$oDesktop ERR" & @CRLF) ;ConsoleWrite("$oDesktop OK" & @CRLF) ; Get Start button Local $pCondition, $pStart, $oStart $oUIAutomation.CreatePropertyCondition($UIA_AutomationIdPropertyId, "StartButton", $pCondition) $oDesktop.FindFirst($TreeScope_Descendants, $pCondition, $pStart) $oStart = ObjCreateInterface($pStart, $sIID_IUIAutomationElement, $dtag_IUIAutomationElement) If Not IsObj($oStart) Then Exit ConsoleWrite("$oStart ERR" & @CRLF) ;ConsoleWrite("$oStart OK" & @CRLF) $oStart.GetCurrentPropertyValue($UIA_NamePropertyId, $sStart) ConsoleWriteEx($sStart & @CRLF) UIAEH_AutomationEventHandlerCreate() If Not IsObj($oUIAEH_AutomationEventHandler) Then Exit ConsoleWrite("$oUIAEH_AutomationEventHandler ERR" & @CRLF) ;ConsoleWrite("$oUIAEH_AutomationEventHandler OK" & @CRLF) $oUIAutomation.AddAutomationEventHandler($UIA_Window_WindowOpenedEventId, $pDesktop, $TreeScope_Subtree, 0, $oUIAEH_AutomationEventHandler) Local $hWndStart While Sleep(100) If IsObj($oWinStart) Then If Not $hWndStart Then ConsoleWrite("Start Window showed" & @CRLF) $oWinStart.GetCurrentPropertyValue($UIA_NativeWindowHandlePropertyId, $hWndStart) ElseIf Not WinExists($hWndStart) Then $oWinStart.Release() $oWinStart = 0 $hWndStart = 0 ConsoleWrite("Start window closed" & @CRLF) EndIf EndIf WEnd EndFunc ;==>Example Func UIAEH_AutomationEventHandler_HandleAutomationEvent($pSelf, $pSender, $iEventId) Local $oSender = ObjCreateInterface($pSender, $sIID_IUIAutomationElement, $dtag_IUIAutomationElement) $oSender.AddRef() Local $sTitle, $sClass $oSender.GetCurrentPropertyValue($UIA_NamePropertyId, $sTitle) $oSender.GetCurrentPropertyValue($UIA_ClassNamePropertyId, $sClass) If $sTitle = $sStart And $sClass = "Windows.UI.Core.CoreWindow" Then $oWinStart = $oSender EndFunc ;==>UIAEH_AutomationEventHandler_HandleAutomationEvent Func ConsoleWriteEx($sString) ConsoleWrite(BinaryToString(StringToBinary($sString, $SB_UTF8), $SB_ANSI)) EndFunc ;==>ConsoleWriteEx Func Terminate() UIAEH_AutomationEventHandlerDelete() Exit EndFunc ;==>Terminate ps. I removed $bTreated as it is redundant with the $hWinStart
    1 point
  26. 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.zip
    1 point
  27. These functions all work perfectly. These allow more possibilities with your MediaPlayer UDF which is fantastic. Thank you for the update, Matty.
    1 point
  28. yeah I'll have a closer look tonight, but it looks like you need to get this object: Windows.Media.Playback.MediaPlaybackSession So get the MediaPlayer object (NOT the mediaPlayerElement) switch to the IMediaPlayer3 interface (using _WinRT_SwitchInterface()) call IMediaPlayer3_GetPlaybackSession to get the playbackSession obj Presumably that new obj will be on IMediaPlaybackSession, but switch to this if need be! then IMediaPlaybackSession_GetNaturalVideoWidth() and IMediaPlaybackSession_GetNaturalVideoHeight() make sense?
    1 point
  29. Just use a label : #include <GUIConstants.au3> Example() Func Example() Local $hGUI = GUICreate("Example", 300, 200) Local $idBtn = GUICtrlCreateLabel("Exit", 120, 150, 85, 25, BitOR($SS_CENTER, $SS_CENTERIMAGE)) GUICtrlSetBkColor(-1, 0x71A0FF) GUISetState() While True Switch GUIGetMsg() Case $GUI_EVENT_CLOSE ExitLoop Case $idBtn ConsoleWrite("button pressed" & @CRLF) EndSwitch WEnd EndFunc ;==>Example
    1 point
  30. WUUUTTTT? This is AWESOME!!!!
    1 point
  31. I would strongly recommend the GuiFlatButton UDF. It's perfectly square buttons. And it also lets you control colors for all states. You can even color borders of each button. It's a fantastic UDF.
    1 point
  32. Thank you so much for this, Matty. Being able to use string is a bonus as well since I may very well make it so that the user can choose which stretch option in the config file. I haven't had a chance to play around with it much yet since I just got my butt kicked by Au3Stripper for around 2 hours. I finally won that fight! 🤪
    1 point
  33. yep, so it looks like none is native res, cropped to size of player. fill is stretched/squished to player size Uniform is pillar/letter box UniformToFill will maintain aspect and crop whatever doesn't fit.
    1 point
  34. Stretching it would look ugly. I was thinking of proportional by... , any means.
    1 point
  35. yeah no worries.. How's this? You should hopefully be able to get/set the property in both its string and numeric forms. Func _MediaPlayer_GetStretch($iMPIdx, $bAsString = False) Local $vStretch If $iMPIdx < 1 Or $iMPIdx >= UBound($__g_apPlayers) Then Return False _WinRT_SwitchInterface($__g_apMPElements[$iMPIdx], $sIID_IMediaPlayerElement) If Not @error Then $vStretch = IMediaPlayerElement_GetStretch($__g_apMPElements[$iMPIdx]) If @error Then Return SetError(@error, @extended, -1) If $bAsString Then $vStretch = _WinRT_GetEnum($mStretch, $vStretch) Return $vStretch EndFunc Func _MediaPlayer_SetStretch($iMPIdx, $vStretch) If $iMPIdx < 1 Or $iMPIdx >= UBound($__g_apPlayers) Then Return False _WinRT_SwitchInterface($__g_apMPElements[$iMPIdx], $sIID_IMediaPlayerElement) If Not @error Then If IsString($vStretch) Then $vStretch = _WinRT_GetEnum($mStretch, $vStretch) IMediaPlayerElement_SetStretch($__g_apMPElements[$iMPIdx], $vStretch) EndIf Return SetError(@error, @extended, @error = $S_OK) EndFunc ;~ Field : None = 0 (Microsoft.UI.Xaml.Media.Stretch) ;~ Field : Fill = 1 (Microsoft.UI.Xaml.Media.Stretch) ;~ Field : Uniform = 2 (Microsoft.UI.Xaml.Media.Stretch) ;~ Field : UniformToFill = 3 (Microsoft.UI.Xaml.Media.Stretch) _MediaPlayer_SetStretch($hPlayer1, "UniformToFill") ConsoleWrite("stretch = " & _MediaPlayer_GetStretch($hPlayer1, True) & @CRLF)
    1 point
  36. This is something that I definitely will have to look into. The pixel size of all monitors comes directly from _WinAPI_EnumDisplayMonitors and the GUI size for each monitor comes from there. I have a feeling that it might have something to do with MediaPlayerElement.Stretch Property. It has video stretch options such as: None, Fill, UniformToFill and Uniform That is one thing that I struggling with setting with the MediaPlayerElement stuff. No matter what I did, it failed. So it stayed as default. The default option of Uniform can leave the black bars depending on the aspect ratio of the video. @MattyD Do you know much about this? We can talk about it here or in your thread, it's up to you. But I had previously tried the various *SetStretch functions and never had any luck. I could always run the *GetStretch functions and get returns. Setting them never worked for me though.
    1 point
  37. Ok !. Did it and it played in both monitors. Now, one of them is an ultrawide one ( 2560x1080 ) and saw black bars on each side. It would be nice to take that into account and display proportional but with the greater size ( width or height ) into consideration. So how ?!. Well, stand your monitor on it's side ( or just in your head ) and on portrait orientation to test on your side and confirm your math
    1 point
  38. Also compiled to exe is easier than patching the AutoIt binaries, but it does require using the latest AutoIt3Wrapper script from the beta directory.
    1 point
  39. That does sound like a smart investment! I ended up testing it by hooking up my laptop to my TV with an HDMI cable and setting it to extended multi-monitor option. It worked good. But I can't imagine someone running it on 3 or 4 screens. Thank you for testing. Yes, if it's just black screen with no video that just means it needs to be patched, you're right. But that black screen is enough for me to confirm that it went to all screens properly. And as long as all screens were 100% covered black, that means that the GUI measurements were good too. But if there were some gaps that were not black, that means my math is bad again. 😀
    1 point
  40. ... <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
  41. If you can spend some $30 + $80 you too can have one. Call it investment
    1 point
  42. wakillon

    MouseTail revisited

    MouseTail revisited A bit of fun doesn't hurt Look at tray menu for config Only tested on Win 11 MouseTail.v1.0.0.3.au3
    1 point
  43. jchd

    FixGibberish

    The name you choose is a misnomer. "proper case" refers to capitalizing the first letter of each word in a sentence, like this: "Proper Case" Refers To Capitalizing The First Letter Of Each Word In A Sentence
    1 point
  44. Sorry, I meant oopsies in applying the DPI stuff
    1 point
  45. Everything looks sharp on my end.
    1 point
  46. argumentum

    OnDebugMsgBox

    Version 2.2024.1.26

    955 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
  47. I don't know if it works with TIF's but sure it works with PNG's. Edit: Just tested with the welcomefax.tif (the onliest tif i have) and it works: #Region ;**** Directives created by AutoIt3Wrapper_GUI **** #AutoIt3Wrapper_UseX64=y #AutoIt3Wrapper_AU3Check_Parameters=-d -w 1 -w 2 -w 3 -w 4 -w 5 -w 6 #EndRegion ;**** Directives created by AutoIt3Wrapper_GUI **** #include <GUIConstantsEx.au3> #include <StaticConstants.au3> #include <WindowsConstants.au3> #include <GUICtrlPic.au3> #include <Array.au3> Global $hGui = GUICreate("Show Tif",@DesktopWidth, @DesktopHeight) Global $aDim = WinGetClientSize($hGui) Global $sAutoItPath If @Compiled Then $sAutoItPath=RegRead64('HKLM\Software\AutoIt v3\AutoIt', 'InstallDir')&'\' Else $sAutoItPath= StringReplace(@AutoItExe, "autoit3.exe", "")&'\' $sAutoItPath= StringReplace(@AutoItExe, "autoit3_x64.exe", "") EndIf Global $Background = _GUICtrlPic_Create("C:\Users\(len)Bert\Downloads\Documents\Fax\Inbox\WelcomeFax.tif", 0, 0, $aDim[0], $aDim[1], $SS_CENTERIMAGE, Default) GUICtrlSetState(-1, $Gui_DISABLE) GUISetState() While 1 Switch GUIGetMsg() Case $Gui_EVENT_CLOSE Exit EndSwitch WEnd Func RegRead64($sKeyname, $sValue) ;Aus AutoUpdateIt.au3 Local $sRes = RegRead($sKeyname, $sValue) If @error And @AutoItX64 Then $sKeyname = StringReplace($sKeyname, "HKEY_LOCAL_MACHINE", "HKLM") $sKeyname = StringReplace($sKeyname, "HKLM\SOFTWARE\", "HKLM\SOFTWARE\Wow6432Node\") $sRes = RegRead($sKeyname, $sValue) If @error Then SetError(1) Return "" EndIf EndIf SetError(0) Return $sRes EndFunc ;==>RegRead64 GUICtrlPic.au3
    1 point
  48. Here is an example how to translate error message: #include <Array.au3> #include <WinApi.au3> #include <MsgBoxConstants.au3> If $IDYES = MsgBox($MB_YESNO, 'Make a decision', 'Do you want to inercept error ?') Then AddHookApi("user32.dll", "MessageBoxW", "Intercept_MessageBoxW", "int", "hwnd;wstr;wstr;uint") EndIf _Example() Func _Example() ;~ _ErrorTranslator(Default) ; check your translation ; Let's try it ; Usual message box MsgBox(0, 'Test', 'Some text') ; Cause error that would say some AutoIt shit happened, but now it wouldn't say "AutoIt" DllStructCreate("byte[123456789097]") ; The End EndFunc ;==>_Example ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; Func Intercept_MessageBoxW($hWnd, $sText, $sTitle, $iType) Local $aCall = DllCall("user32.dll", "int", "MessageBoxW", _ "hwnd", $hWnd, _ "wstr", _ErrorTranslator($sText), _ "wstr", StringReplace($sTitle, "AutoIt", 'Error occured in ' & @ScriptName), _ "uint", $iType) If @error Or Not $aCall[0] Then Return 0 Return $aCall[0] EndFunc ;==>Intercept_MessageBoxW ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; The magic is down below Func AddHookApi($sModuleName, $vFunctionName, $vNewFunction, $sRet = "", $sParams = "") Local Static $pImportDirectory, $hInstance Local Const $IMAGE_DIRECTORY_ENTRY_IMPORT = 1 If Not $pImportDirectory Then $hInstance = _WinAPI_GetModuleHandle(0) $pImportDirectory = ImageDirectoryEntryToData($hInstance, $IMAGE_DIRECTORY_ENTRY_IMPORT) If @error Then Return SetError(1, 0, 0) EndIf Local $iIsInt = IsInt($vFunctionName) Local $iRestore = Not IsString($vNewFunction) Local $tIMAGE_IMPORT_MODULE_DIRECTORY Local $pDirectoryOffset = $pImportDirectory Local $tModuleName Local $iInitialOffset, $iInitialOffset2 Local $iOffset2 Local $tBufferOffset2, $iBufferOffset2 Local $tBuffer, $tFunctionOffset, $pOld, $fMatch, $pModuleName, $pFuncName Local Const $PAGE_READWRITE = 0x04 While 1 $tIMAGE_IMPORT_MODULE_DIRECTORY = DllStructCreate("dword RVAOriginalFirstThunk;" & _ "dword TimeDateStamp;" & _ "dword ForwarderChain;" & _ "dword RVAModuleName;" & _ "dword RVAFirstThunk", _ $pDirectoryOffset) If Not DllStructGetData($tIMAGE_IMPORT_MODULE_DIRECTORY, "RVAFirstThunk") Then ExitLoop $pModuleName = $hInstance + DllStructGetData($tIMAGE_IMPORT_MODULE_DIRECTORY, "RVAModuleName") $tModuleName = DllStructCreate("char Name[" & _WinAPI_StringLenA($pModuleName) & "]", $pModuleName) If DllStructGetData($tModuleName, "Name") = $sModuleName Then ; function from this module $iInitialOffset = $hInstance + DllStructGetData($tIMAGE_IMPORT_MODULE_DIRECTORY, "RVAFirstThunk") $iInitialOffset2 = $hInstance + DllStructGetData($tIMAGE_IMPORT_MODULE_DIRECTORY, "RVAOriginalFirstThunk") If $iInitialOffset2 = $hInstance Then $iInitialOffset2 = $iInitialOffset $iOffset2 = 0 While 1 $tBufferOffset2 = DllStructCreate("dword_ptr", $iInitialOffset2 + $iOffset2) $iBufferOffset2 = DllStructGetData($tBufferOffset2, 1) If Not $iBufferOffset2 Then ExitLoop If $iIsInt Then If BitAND($iBufferOffset2, 0xFFFFFF) = $vFunctionName Then $fMatch = True ; wanted function Else $pFuncName = $hInstance + $iBufferOffset2 + 2 ; 2 is size od "word", see line below... $tBuffer = DllStructCreate("word Ordinal; char Name[" & _WinAPI_StringLenA($pFuncName) & "]", $hInstance + $iBufferOffset2) If DllStructGetData($tBuffer, "Name") == $vFunctionName Then $fMatch = True ; wanted function EndIf If $fMatch Then $tFunctionOffset = DllStructCreate("ptr", $iInitialOffset + $iOffset2) VirtualProtect(DllStructGetPtr($tFunctionOffset), DllStructGetSize($tFunctionOffset), $PAGE_READWRITE) If @error Then Return SetError(3, 0, 0) $pOld = DllStructGetData($tFunctionOffset, 1) If $iRestore Then DllStructSetData($tFunctionOffset, 1, $vNewFunction) Else DllStructSetData($tFunctionOffset, 1, DllCallbackGetPtr(DllCallbackRegister($vNewFunction, $sRet, $sParams))) EndIf Return $pOld EndIf $iOffset2 += DllStructGetSize($tBufferOffset2) WEnd ExitLoop EndIf $pDirectoryOffset += 20 ; size of $tIMAGE_IMPORT_MODULE_DIRECTORY WEnd Return SetError(4, 0, 0) EndFunc ;==>AddHookApi Func VirtualProtect($pAddress, $iSize, $iProtection) Local $aCall = DllCall("kernel32.dll", "bool", "VirtualProtect", "ptr", $pAddress, "dword_ptr", $iSize, "dword", $iProtection, "dword*", 0) If @error Or Not $aCall[0] Then Return SetError(1, 0, 0) Return 1 EndFunc ;==>VirtualProtect Func ImageDirectoryEntryToData($hInstance, $iDirectoryEntry) ; Get pointer to data Local $pPointer = $hInstance ; Start processing passed binary data. 'Reading' PE format follows. Local $tIMAGE_DOS_HEADER = DllStructCreate("char Magic[2];" & _ "word BytesOnLastPage;" & _ "word Pages;" & _ "word Relocations;" & _ "word SizeofHeader;" & _ "word MinimumExtra;" & _ "word MaximumExtra;" & _ "word SS;" & _ "word SP;" & _ "word Checksum;" & _ "word IP;" & _ "word CS;" & _ "word Relocation;" & _ "word Overlay;" & _ "char Reserved[8];" & _ "word OEMIdentifier;" & _ "word OEMInformation;" & _ "char Reserved2[20];" & _ "dword AddressOfNewExeHeader", _ $pPointer) Local $sMagic = DllStructGetData($tIMAGE_DOS_HEADER, "Magic") ; Check if it's valid format If Not ($sMagic == "MZ") Then Return SetError(1, 0, 0) ; MS-DOS header missing. Btw 'MZ' are the initials of Mark Zbikowski in case you didn't know. ; Move pointer $pPointer += DllStructGetData($tIMAGE_DOS_HEADER, "AddressOfNewExeHeader") ; move to PE file header ; In place of IMAGE_NT_SIGNATURE structure Local $tIMAGE_NT_SIGNATURE = DllStructCreate("dword Signature", $pPointer) ; Check signature If DllStructGetData($tIMAGE_NT_SIGNATURE, "Signature") <> 17744 Then ; IMAGE_NT_SIGNATURE Return SetError(2, 0, 0) ; wrong signature. For PE image should be "PE\0\0" or 17744 dword. EndIf ; Move pointer $pPointer += 4 ; size of $tIMAGE_NT_SIGNATURE structure ; In place of IMAGE_FILE_HEADER structure ; Move pointer $pPointer += 20 ; size of $tIMAGE_FILE_HEADER structure ; Determine the type Local $tMagic = DllStructCreate("word Magic;", $pPointer) Local $iMagic = DllStructGetData($tMagic, 1) Local $tIMAGE_OPTIONAL_HEADER If $iMagic = 267 Then ; x86 version ; Move pointer $pPointer += 96 ; size of $tIMAGE_OPTIONAL_HEADER ElseIf $iMagic = 523 Then ; x64 version ; Move pointer $pPointer += 112 ; size of $tIMAGE_OPTIONAL_HEADER Else Return SetError(3, 0, 0) ; unsupported module type EndIf ; Validate input by checking available number of structures that are in the module Local Const $IMAGE_NUMBEROF_DIRECTORY_ENTRIES = 16 ; predefined value that PE modules always use (AutoIt certainly) If $iDirectoryEntry > $IMAGE_NUMBEROF_DIRECTORY_ENTRIES - 1 Then Return SetError(4, 0, 0) ; invalid input ; Calculate the offset to wanted entry (every entry is 8 bytes) $pPointer += 8 * $iDirectoryEntry ; At place of correst directory entry Local $tIMAGE_DIRECTORY_ENTRY = DllStructCreate("dword VirtualAddress; dword Size", $pPointer) ; Collect data Local $pAddress = DllStructGetData($tIMAGE_DIRECTORY_ENTRY, "VirtualAddress") If $pAddress = 0 Then Return SetError(5, 0, 0) ; invalid input ; $pAddress is RVA, add it to base address Return $hInstance + $pAddress EndFunc ;==>ImageDirectoryEntryToData Func _ErrorTranslator($sText = Default) Local Static $aErrorMessages = _ [ _ [ _ "(Paused) ", _ "" _ ], _ [ _ "AutoIt Error", _ "" _ ], _ [ _ "AutoIt has detected the stack has become corrupt.\n\nStack corruption typically occurs when either the wrong calling convention is used or when the function is called with the wrong number of arguments.\n\nAutoIt supports the __stdcall (WINAPI) and __cdecl calling conventions. The __stdcall (WINAPI) convention is used by default but __cdecl can be used instead. See the DllCall() documentation for details on changing the calling convention.", _ "" _ ], _ [ _ """EndWith"" missing ""With"".", _ "" _ ], _ [ _ "Badly formatted ""Func"" statement.", _ "" _ ], _ [ _ """With"" missing ""EndWith"".", _ "" _ ], _ [ _ "Missing right bracket ')' in expression.", _ "" _ ], _ [ _ "Missing operator in expression.", _ "" _ ], _ [ _ "Unbalanced brackets in expression.", _ "" _ ], _ [ _ "Error in expression.", _ "" _ ], _ [ _ "Error parsing function call.", _ "" _ ], _ [ _ "Incorrect number of parameters in function call.", _ "" _ ], _ [ _ """ReDim"" used without an array variable.", _ "" _ ], _ [ _ "Illegal text at the end of statement (one statement per line).", _ "" _ ], _ [ _ """If"" statement has no matching ""EndIf"" statement.", _ "" _ ], _ [ _ """Else"" statement with no matching ""If"" statement.", _ "" _ ], _ [ _ """EndIf"" statement with no matching ""If"" statement.", _ "" _ ], _ [ _ "Too many ""Else"" statements for matching ""If"" statement.", _ "" _ ], _ [ _ """While"" statement has no matching ""Wend"" statement.", _ "" _ ], _ [ _ """Wend"" statement with no matching ""While"" statement.", _ "" _ ], _ [ _ "Variable used without being declared.", _ "" _ ], _ [ _ "Array variable has incorrect number of subscripts or subscript dimension range exceeded.", _ "" _ ], _ [ _ "Variable subscript badly formatted.", _ "" _ ], _ [ _ "Subscript used on non-accessible variable.", _ "" _ ], _ [ _ "Too many subscripts used for an array.", _ "" _ ], _ [ _ "Missing subscript dimensions in ""Dim"" statement.", _ "" _ ], _ [ _ "No variable given for ""Dim"", ""Local"", ""Global"", ""Struct"" or ""Const"" statement.", _ "" _ ], _ [ _ "Expected a ""="" operator in assignment statement.", _ "" _ ], _ [ _ "Invalid keyword at the start of this line.", _ "" _ ], _ [ _ "Array maximum size exceeded.", _ "" _ ], _ [ _ """Func"" statement has no matching ""EndFunc"".", _ "" _ ], _ [ _ "Duplicate function name.", _ "" _ ], _ [ _ "Unknown function name.", _ "" _ ], _ [ _ "Unknown macro.", _ "" _ ], _ [ _ "Unable to get a list of running processes.", _ "" _ ], _ [ _ "Invalid element in a DllStruct.", _ "" _ ], _ [ _ "Unknown option or bad parameter specified.", _ "" _ ], _ [ _ "Unable to load the internet libraries.", _ "" _ ], _ [ _ """Struct"" statement has no matching ""EndStruct"".", _ "" _ ], _ [ _ "Unable to open file, the maximum number of open files has been exceeded.", _ "" _ ], _ [ _ """ContinueLoop"" statement with no matching ""While"", ""Do"" or ""For"" statement.", _ "" _ ], _ [ _ "Invalid file filter given.", _ "" _ ], _ [ _ "Expected a variable in user function call.", _ "" _ ], _ [ _ """Do"" statement has no matching ""Until"" statement.", _ "" _ ], _ [ _ """Until"" statement with no matching ""Do"" statement.", _ "" _ ], _ [ _ """For"" statement is badly formatted.", _ "" _ ], _ [ _ """Next"" statement with no matching ""For"" statement.", _ "" _ ], _ [ _ """ExitLoop/ContinueLoop"" statements only valid from inside a For/Do/While loop.", _ "" _ ], _ [ _ """For"" statement has no matching ""Next"" statement.", _ "" _ ], _ [ _ """Case"" statement with no matching ""Select""or ""Switch"" statement.", _ "" _ ], _ [ _ """EndSelect"" statement with no matching ""Select"" statement.", _ "" _ ], _ [ _ "Recursion level has been exceeded - AutoIt will quit to prevent stack overflow.", _ "" _ ], _ [ _ "Cannot make existing variables static.", _ "" _ ], _ [ _ "Cannot make static variables into regular variables.", _ "" _ ], _ [ _ "Badly formated Enum statement", _ "" _ ], _ [ _ "This keyword cannot be used after a ""Then"" keyword.", _ "" _ ], _ [ _ """Select"" statement is missing ""EndSelect"" or ""Case"" statement.", _ "" _ ], _ [ _ """If"" statements must have a ""Then"" keyword.", _ "" _ ], _ [ _ "Badly formated Struct statement.", _ "" _ ], _ [ _ "Cannot assign values to constants.", _ "" _ ], _ [ _ "Cannot make existing variables into constants.", _ "" _ ], _ [ _ "Only Object-type variables allowed in a ""With"" statement.", _ "" _ ], _ [ _ """long_ptr"", ""int_ptr"" and ""short_ptr"" DllCall() types have been deprecated. Use ""long*"", ""int*"" and ""short*"" instead.", _ "" _ ], _ [ _ "Object referenced outside a ""With"" statement.", _ "" _ ], _ [ _ "Nested ""With"" statements are not allowed.", _ "" _ ], _ [ _ "Variable must be of type ""Object"".", _ "" _ ], _ [ _ "The requested action with this object has failed.", _ "" _ ], _ [ _ "Variable appears more than once in function declaration.", _ "" _ ], _ [ _ "ReDim array can not be initialized in this manner.", _ "" _ ], _ [ _ "An array variable can not be used in this manner.", _ "" _ ], _ [ _ "Can not redeclare a constant.", _ "" _ ], _ [ _ "Can not redeclare a parameter inside a user function.", _ "" _ ], _ [ _ "Can pass constants by reference only to parameters with ""Const"" keyword.", _ "" _ ], _ [ _ "Can not initialize a variable with itself.", _ "" _ ], _ [ _ "Incorrect way to use this parameter.", _ "" _ ], _ [ _ """EndSwitch"" statement with no matching ""Switch"" statement.", _ "" _ ], _ [ _ """Switch"" statement is missing ""EndSwitch"" or ""Case"" statement.", _ "" _ ], _ [ _ """ContinueCase"" statement with no matching ""Select""or ""Switch"" statement.", _ "" _ ], _ [ _ "Assert Failed!", _ "" _ ], _ [ _ "Obsolete function/parameter.", _ "" _ ], _ [ _ "Invalid Exitcode (reserved for AutoIt internal use).", _ "" _ ], _ [ _ "Variable cannot be accessed in this manner.", _ "" _ ], _ [ _ "Func reassign not allowed.", _ "" _ ], _ [ _ "Func reassign on global level not allowed.", _ "" _ ], _ [ _ "Unable to parse line.", _ "" _ ], _ [ _ "Unable to open the script file.", _ "" _ ], _ [ _ "String missing closing quote.", _ "" _ ], _ [ _ "Badly formated variable or macro.", _ "" _ ], _ [ _ "Missing separator character after keyword.", _ "" _ ], _ [ _ "Error allocating memory.", _ "Błąd allokacji pamięci." _ ] _ ] Local Static $aErrorMessages2 = _ [ _ ["(Paused) ", ""], _ ["AutoIt Error", ""], _ ["AutoIt has detected the stack has become corrupt.\n\nStack corruption typically occurs when either the wrong calling convention is used or when the function is called with the wrong number of arguments.\n\nAutoIt supports the __stdcall (WINAPI) and __cdecl calling conventions. The __stdcall (WINAPI) convention is used by default but __cdecl can be used instead. See the DllCall() documentation for details on changing the calling convention.", ""], _ ["""EndWith"" missing ""With"".", ""], _ ["Badly formatted ""Func"" statement.", ""], _ ["""With"" missing ""EndWith"".", ""], _ ["Missing right bracket ')' in expression.", ""], _ ["Missing operator in expression.", ""], _ ["Unbalanced brackets in expression.", ""], _ ["Error in expression.", ""], _ ["Error parsing function call.", ""], _ ["Incorrect number of parameters in function call.", ""], _ ["""ReDim"" used without an array variable.", ""], _ ["Illegal text at the end of statement (one statement per line).", ""], _ ["""If"" statement has no matching ""EndIf"" statement.", ""], _ ["""Else"" statement with no matching ""If"" statement.", ""], _ ["""EndIf"" statement with no matching ""If"" statement.", ""], _ ["Too many ""Else"" statements for matching ""If"" statement.", ""], _ ["""While"" statement has no matching ""Wend"" statement.", ""], _ ["""Wend"" statement with no matching ""While"" statement.", ""], _ ["Variable used without being declared.", ""], _ ["Array variable has incorrect number of subscripts or subscript dimension range exceeded.", ""], _ ["Variable subscript badly formatted.", ""], _ ["Subscript used on non-accessible variable.", ""], _ ["Too many subscripts used for an array.", ""], _ ["Missing subscript dimensions in ""Dim"" statement.", ""], _ ["No variable given for ""Dim"", ""Local"", ""Global"", ""Struct"" or ""Const"" statement.", ""], _ ["Expected a ""="" operator in assignment statement.", ""], _ ["Invalid keyword at the start of this line.", ""], _ ["Array maximum size exceeded.", ""], _ ["""Func"" statement has no matching ""EndFunc"".", ""], _ ["Duplicate function name.", ""], _ ["Unknown function name.", ""], _ ["Unknown macro.", ""], _ ["Unable to get a list of running processes.", ""], _ ["Invalid element in a DllStruct.", ""], _ ["Unknown option or bad parameter specified.", ""], _ ["Unable to load the internet libraries.", ""], _ ["""Struct"" statement has no matching ""EndStruct"".", ""], _ ["Unable to open file, the maximum number of open files has been exceeded.", ""], _ ["""ContinueLoop"" statement with no matching ""While"", ""Do"" or ""For"" statement.", ""], _ ["Invalid file filter given.", ""], _ ["Expected a variable in user function call.", ""], _ ["""Do"" statement has no matching ""Until"" statement.", ""], _ ["""Until"" statement with no matching ""Do"" statement.", ""], _ ["""For"" statement is badly formatted.", ""], _ ["""Next"" statement with no matching ""For"" statement.", ""], _ ["""ExitLoop/ContinueLoop"" statements only valid from inside a For/Do/While loop.", ""], _ ["""For"" statement has no matching ""Next"" statement.", ""], _ ["""Case"" statement with no matching ""Select""or ""Switch"" statement.", ""], _ ["""EndSelect"" statement with no matching ""Select"" statement.", ""], _ ["Recursion level has been exceeded - AutoIt will quit to prevent stack overflow.", ""], _ ["Cannot make existing variables static.", ""], _ ["Cannot make static variables into regular variables.", ""], _ ["Badly formated Enum statement", ""], _ ["This keyword cannot be used after a ""Then"" keyword.", ""], _ ["""Select"" statement is missing ""EndSelect"" or ""Case"" statement.", ""], _ ["""If"" statements must have a ""Then"" keyword.", ""], _ ["Badly formated Struct statement.", ""], _ ["Cannot assign values to constants.", ""], _ ["Cannot make existing variables into constants.", ""], _ ["Only Object-type variables allowed in a ""With"" statement.", ""], _ ["""long_ptr"", ""int_ptr"" and ""short_ptr"" DllCall() types have been deprecated. Use ""long*"", ""int*"" and ""short*"" instead.", ""], _ ["Object referenced outside a ""With"" statement.", ""], _ ["Nested ""With"" statements are not allowed.", ""], _ ["Variable must be of type ""Object"".", ""], _ ["The requested action with this object has failed.", ""], _ ["Variable appears more than once in function declaration.", ""], _ ["ReDim array can not be initialized in this manner.", ""], _ ["An array variable can not be used in this manner.", ""], _ ["Can not redeclare a constant.", ""], _ ["Can not redeclare a parameter inside a user function.", ""], _ ["Can pass constants by reference only to parameters with ""Const"" keyword.", ""], _ ["Can not initialize a variable with itself.", ""], _ ["Incorrect way to use this parameter.", ""], _ ["""EndSwitch"" statement with no matching ""Switch"" statement.", ""], _ ["""Switch"" statement is missing ""EndSwitch"" or ""Case"" statement.", ""], _ ["""ContinueCase"" statement with no matching ""Select""or ""Switch"" statement.", ""], _ ["Assert Failed!", ""], _ ["Obsolete function/parameter.", ""], _ ["Invalid Exitcode (reserved for AutoIt internal use).", ""], _ ["Variable cannot be accessed in this manner.", ""], _ ["Func reassign not allowed.", ""], _ ["Func reassign on global level not allowed.", ""], _ ["Unable to parse line.", ""], _ ["Unable to open the script file.", ""], _ ["String missing closing quote.", ""], _ ["Badly formated variable or macro.", ""], _ ["Missing separator character after keyword.", ""], _ ["Error allocating memory.", "Błąd allokacji pamięci."] _ ] ConsoleWrite("! $sText= " & $sText & @CRLF) For $iError_idx = 0 To UBound($aErrorMessages) - 1 If $aErrorMessages[$iError_idx][0] = $sText Then $sText = $aErrorMessages[$iError_idx][1] EndIf Next If Not @Compiled And $sText = Default Then _ArrayDisplay($aErrorMessages) If Not @Compiled And $sText = Default Then _ArrayDisplay($aErrorMessages2) Return $sText EndFunc ;==>_ErrorTranslator
    1 point
  49. Here, let me then: #include <WinApi.au3> ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; AddHookApi("user32.dll", "MessageBoxW", "Intercept_MessageBoxW", "int", "hwnd;wstr;wstr;uint") Func Intercept_MessageBoxW($hWnd, $sText, $sTitle, $iType) Local $aCall = DllCall("user32.dll", "int", "MessageBoxW", _ "hwnd", $hWnd, _ "wstr", $sText, _ "wstr", StringReplace($sTitle, "AutoIt", @ScriptName), _ "uint", $iType) If @error Or Not $aCall[0] Then Return 0 Return $aCall[0] EndFunc ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; Let's try it ; Usual message box MsgBox(0, 'Test', 'Some text') ; Cause error that would say some AutoIt shit happened, but now it wouldn't say "AutoIt" DllStructCreate("byte[123456789097]") ; The End ; The magic is down below Func AddHookApi($sModuleName, $vFunctionName, $vNewFunction, $sRet = "", $sParams = "") Local Static $pImportDirectory, $hInstance Local Const $IMAGE_DIRECTORY_ENTRY_IMPORT = 1 If Not $pImportDirectory Then $hInstance = _WinAPI_GetModuleHandle(0) $pImportDirectory = ImageDirectoryEntryToData($hInstance, $IMAGE_DIRECTORY_ENTRY_IMPORT) If @error Then Return SetError(1, 0, 0) EndIf Local $iIsInt = IsInt($vFunctionName) Local $iRestore = Not IsString($vNewFunction) Local $tIMAGE_IMPORT_MODULE_DIRECTORY Local $pDirectoryOffset = $pImportDirectory Local $tModuleName Local $iInitialOffset, $iInitialOffset2 Local $iOffset2 Local $tBufferOffset2, $iBufferOffset2 Local $tBuffer, $tFunctionOffset, $pOld, $fMatch, $pModuleName, $pFuncName Local Const $PAGE_READWRITE = 0x04 While 1 $tIMAGE_IMPORT_MODULE_DIRECTORY = DllStructCreate("dword RVAOriginalFirstThunk;" & _ "dword TimeDateStamp;" & _ "dword ForwarderChain;" & _ "dword RVAModuleName;" & _ "dword RVAFirstThunk", _ $pDirectoryOffset) If Not DllStructGetData($tIMAGE_IMPORT_MODULE_DIRECTORY, "RVAFirstThunk") Then ExitLoop $pModuleName = $hInstance + DllStructGetData($tIMAGE_IMPORT_MODULE_DIRECTORY, "RVAModuleName") $tModuleName = DllStructCreate("char Name[" & _WinAPI_StringLenA($pModuleName) & "]", $pModuleName) If DllStructGetData($tModuleName, "Name") = $sModuleName Then ; function from this module $iInitialOffset = $hInstance + DllStructGetData($tIMAGE_IMPORT_MODULE_DIRECTORY, "RVAFirstThunk") $iInitialOffset2 = $hInstance + DllStructGetData($tIMAGE_IMPORT_MODULE_DIRECTORY, "RVAOriginalFirstThunk") If $iInitialOffset2 = $hInstance Then $iInitialOffset2 = $iInitialOffset $iOffset2 = 0 While 1 $tBufferOffset2 = DllStructCreate("dword_ptr", $iInitialOffset2 + $iOffset2) $iBufferOffset2 = DllStructGetData($tBufferOffset2, 1) If Not $iBufferOffset2 Then ExitLoop If $iIsInt Then If BitAND($iBufferOffset2, 0xFFFFFF) = $vFunctionName Then $fMatch = True; wanted function Else $pFuncName = $hInstance + $iBufferOffset2 + 2 ; 2 is size od "word", see line below... $tBuffer = DllStructCreate("word Ordinal; char Name[" & _WinAPI_StringLenA($pFuncName) & "]", $hInstance + $iBufferOffset2) If DllStructGetData($tBuffer, "Name") == $vFunctionName Then $fMatch = True; wanted function EndIf If $fMatch Then $tFunctionOffset = DllStructCreate("ptr", $iInitialOffset + $iOffset2) VirtualProtect(DllStructGetPtr($tFunctionOffset), DllStructGetSize($tFunctionOffset), $PAGE_READWRITE) If @error Then Return SetError(3, 0, 0) $pOld = DllStructGetData($tFunctionOffset, 1) If $iRestore Then DllStructSetData($tFunctionOffset, 1, $vNewFunction) Else DllStructSetData($tFunctionOffset, 1, DllCallbackGetPtr(DllCallbackRegister($vNewFunction, $sRet, $sParams))) EndIf Return $pOld EndIf $iOffset2 += DllStructGetSize($tBufferOffset2) WEnd ExitLoop EndIf $pDirectoryOffset += 20 ; size of $tIMAGE_IMPORT_MODULE_DIRECTORY WEnd Return SetError(4, 0, 0) EndFunc Func VirtualProtect($pAddress, $iSize, $iProtection) Local $aCall = DllCall("kernel32.dll", "bool", "VirtualProtect", "ptr", $pAddress, "dword_ptr", $iSize, "dword", $iProtection, "dword*", 0) If @error Or Not $aCall[0] Then Return SetError(1, 0, 0) Return 1 EndFunc Func ImageDirectoryEntryToData($hInstance, $iDirectoryEntry) ; Get pointer to data Local $pPointer = $hInstance ; Start processing passed binary data. 'Reading' PE format follows. Local $tIMAGE_DOS_HEADER = DllStructCreate("char Magic[2];" & _ "word BytesOnLastPage;" & _ "word Pages;" & _ "word Relocations;" & _ "word SizeofHeader;" & _ "word MinimumExtra;" & _ "word MaximumExtra;" & _ "word SS;" & _ "word SP;" & _ "word Checksum;" & _ "word IP;" & _ "word CS;" & _ "word Relocation;" & _ "word Overlay;" & _ "char Reserved[8];" & _ "word OEMIdentifier;" & _ "word OEMInformation;" & _ "char Reserved2[20];" & _ "dword AddressOfNewExeHeader", _ $pPointer) Local $sMagic = DllStructGetData($tIMAGE_DOS_HEADER, "Magic") ; Check if it's valid format If Not ($sMagic == "MZ") Then Return SetError(1, 0, 0) ; MS-DOS header missing. Btw 'MZ' are the initials of Mark Zbikowski in case you didn't know. ; Move pointer $pPointer += DllStructGetData($tIMAGE_DOS_HEADER, "AddressOfNewExeHeader") ; move to PE file header ; In place of IMAGE_NT_SIGNATURE structure Local $tIMAGE_NT_SIGNATURE = DllStructCreate("dword Signature", $pPointer) ; Check signature If DllStructGetData($tIMAGE_NT_SIGNATURE, "Signature") <> 17744 Then ; IMAGE_NT_SIGNATURE Return SetError(2, 0, 0) ; wrong signature. For PE image should be "PE\0\0" or 17744 dword. EndIf ; Move pointer $pPointer += 4 ; size of $tIMAGE_NT_SIGNATURE structure ; In place of IMAGE_FILE_HEADER structure ; Move pointer $pPointer += 20 ; size of $tIMAGE_FILE_HEADER structure ; Determine the type Local $tMagic = DllStructCreate("word Magic;", $pPointer) Local $iMagic = DllStructGetData($tMagic, 1) Local $tIMAGE_OPTIONAL_HEADER If $iMagic = 267 Then ; x86 version ; Move pointer $pPointer += 96 ; size of $tIMAGE_OPTIONAL_HEADER ElseIf $iMagic = 523 Then ; x64 version ; Move pointer $pPointer += 112 ; size of $tIMAGE_OPTIONAL_HEADER Else Return SetError(3, 0, 0) ; unsupported module type EndIf ; Validate input by checking available number of structures that are in the module Local Const $IMAGE_NUMBEROF_DIRECTORY_ENTRIES = 16 ; predefined value that PE modules always use (AutoIt certainly) If $iDirectoryEntry > $IMAGE_NUMBEROF_DIRECTORY_ENTRIES - 1 Then Return SetError(4, 0, 0) ; invalid input ; Calculate the offset to wanted entry (every entry is 8 bytes) $pPointer += 8 * $iDirectoryEntry ; At place of correst directory entry Local $tIMAGE_DIRECTORY_ENTRY = DllStructCreate("dword VirtualAddress; dword Size", $pPointer) ; Collect data Local $pAddress = DllStructGetData($tIMAGE_DIRECTORY_ENTRY, "VirtualAddress") If $pAddress = 0 Then Return SetError(5, 0, 0) ; invalid input ; $pAddress is RVA, add it to base address Return $hInstance + $pAddress EndFuncedit: because this is better than before.
    1 point
×
×
  • Create New...