Jump to content

Leaderboard

Popular Content

Showing content with the highest reputation on 06/10/2021 in all areas

  1. Hi Norm73 It's not obvious to have both options (your combo "Scroll" and "Filter") in the same script, because it may require to work on different sub-arrays when you choose each option. Also the fact that we can sort on a column while searching in another column makes it hard too. Plus this "All" option in the Combo, all these permanent and temporary indexes etc... LarsJ himself splitted both options in 2 separate scripts (which were both very inspiring), named : 1) Incremental text search.au3 2) Show matching rows only A couple of days ago, I ended a script (named "2s") mixing both options as you will see below, but it still requires some testing. I didn't want to post it because it will be a bit hard to maintain and my health isn't going really well (eyes, ears... you name it) so I won't come on the Forum as frequently as I used to, Times are changing, unfortunately... Anyway, in case it may help you (or other users) here is the most interesting functionality in this version (a context menu allowing to display only matching rows, or all rows) . Pics being better than words : The context menu option "Right-click Headers" is checkable too. When checked, it allows to switch quickly from a search column to another. Now the full script "2s" : #include <ComboConstants.au3> #include <EditConstants.au3> #include <GuiListView.au3> #include <GUIConstantsEx.au3> #include <StaticConstants.au3> #include <WindowsConstants.au3> #include "RandomArray.au3" ; LarsJ #include "DrawItem.au3" ; " Opt("MustDeclareVars", 1) Global $g_iRows = 1000, $g_iCols = 6, $g_hGui, $g_hListView, $g_hHeader, $g_hEdit Global $g_aCols = ["Strings", "Integers", "Floats", "Dates", "Times", "R/C"], $g_aWidths = [230, 61, 124, 70, 60, 60] Global $g_aColAligns[$g_iCols] = [2, 1, 1, 1, 1, 1] ; $HDF_LEFT = 0, $HDF_RIGHT = 1, $HDF_CENTER = 2 Global $g_idListView, $g_idMarker, $g_idComboCol, $g_idComboColDummy, $g_idEditDummy Global $g_sSearch, $g_iSearchCol, $g_iSortDir, $g_iSearch = $g_iRows, $g_iLvItem = -1 Global $g_aArray, $g_aSubArray, $g_aSubArray2, $g_tDefaultIndex, $g_tIndex = DllStructCreate("uint arr[" & $g_iRows & "]") Global $g_aIndex[$g_iCols], $g_aIndexTemp[$g_iCols] ; VarGetType's : $g_aIndex => "Array", $g_aIndex[0] => "String" Global $g_idContextDummy, $g_hContextmenu, $g_iItem = -1, $g_iSubItem = -1, $g_bShowAllRows = False, $g_bRightClickHeaders = True Global $fListViewHasFocus = 1 ; trying this for now, we'll see... Example() Func Example() ; Generate array & one index _Generate_All($g_aArray) $g_aSubArray = $g_aArray $g_aSubArray2 = $g_aArray $g_tDefaultIndex = $g_tIndex ; Compute LV_Height based on 40 full visible rows, no additional vertical pixel. Local $iLV_Height = _ComputeLV_Height(40) ; only 1 param => LV got headers & border ConsoleWrite("Computed LV height = " & $iLV_Height & " pixels" & @crlf) ; Create GUI $g_hGui = GUICreate("Virtual ListView + Incr. Search + Show matching or All rows (2s)", 630 + 20, $iLV_Height + 30 + 20) ; Create Edit control (search) + dummy control Local $idEdit = GUICtrlCreateEdit("", 120, 10, 182, 20, BitXOR($GUI_SS_DEFAULT_EDIT, $WS_HSCROLL, $WS_VSCROLL)) $g_hEdit = GUICtrlGetHandle($idEdit) $g_idEditDummy = GUICtrlCreateDummy() ; Create 2 Search Buttons (Prev / Next) & 2 Accelerator Keys (F3 / Shift+F3) Local $idPrev = GUICtrlCreateButton("Prev", 312, 10, 50, 20) Local $idNext = GUICtrlCreateButton("Next", 370, 10, 50, 20) GUICtrlSetState($idPrev, $GUI_DISABLE) GUICtrlSetState($idNext, $GUI_DISABLE) Local $aAccelKeys[2][2] = [ [ "{F3}", $idNext ], [ "+{F3}", $idPrev ] ] GUISetAccelerators($aAccelKeys) ; Create ComboBox control (how to search : RegEx or Normal ?) Local $idSearchHow = GUICtrlCreateCombo("RegEx search", 11, 9, 100, 20, BitOR($GUI_SS_DEFAULT_COMBO, $CBS_DROPDOWNLIST)) Local $sSearchHow = "RegEx search", $sSearchHowPrev = $sSearchHow ; default way of searching (changeable) GUICtrlSetData($idSearchHow, "Normal search", $sSearchHow) ; Create ComboBox control (column where to search) + dummy control GUICtrlCreateLabel("Col", 429, 10, 20, 20, BitOR($SS_CENTERIMAGE, $SS_CENTER)) $g_idComboCol = GUICtrlCreateCombo("0", 452, 9, 41, 20, BitOR($GUI_SS_DEFAULT_COMBO, $CBS_DROPDOWNLIST)) $g_iSearchCol = 0 ; default column where to search (changeable) Local $iSearchColPrev = $g_iSearchCol For $i = 1 To $g_iCols - 1 GUICtrlSetData($g_idComboCol, $i & "|", $g_iSearchCol) Next $g_idComboColDummy = GUICtrlCreateDummy() ; Create Label control (number of matching results) Local $idResult = GUICtrlCreateLabel(" " & $g_iRows & " rows (no pattern)", 501, 10, 135, 20, BitOR($SS_CENTERIMAGE, $SS_SUNKEN)) ; Create ListView $g_idListView = GUICtrlCreateListView("", 10, 40, 630, $iLV_Height, BitOr($GUI_SS_DEFAULT_LISTVIEW, $LVS_OWNERDATA, $LVS_OWNERDRAWFIXED), $WS_EX_CLIENTEDGE) _GUICtrlListView_SetExtendedListViewStyle($g_idListView, BitOr($LVS_EX_DOUBLEBUFFER, $LVS_EX_FULLROWSELECT)) $g_hListView = GUICtrlGetHandle($g_idListView) $g_hHeader = _GUICtrlListView_GetHeader($g_idListView) For $i = 0 To $g_iCols - 1 _GUICtrlListView_AddColumn($g_idListView, $g_aCols[$i], $g_aWidths[$i]) _GUICtrlHeader_SetItemFormat($g_hHeader, $i, $HDF_STRING + $g_aColAligns[$i]) Next Local $iGetItemSpacingY = _GUICtrlListView_GetItemSpacingY($g_idListView, True) ; No ListView column resizing by dragging header dividers (LarsJ) ;_WinAPI_SetWindowLong( $hHeader, $GWL_STYLE, _WinAPI_GetWindowLong( $hHeader, $GWL_STYLE ) + $HDS_NOSIZING ) ; AutoIt 3.3.14.5 issue DllCall( "user32.dll", "long_ptr", @AutoItX64 ? "SetWindowLongPtrW" : "SetWindowLongW", "hwnd", $g_hHeader, "int", $GWL_STYLE, "long_ptr", _ DllCall( "user32.dll", "long_ptr", @AutoItX64 ? "GetWindowLongPtrW" : "GetWindowLongW", "hwnd", $g_hHeader, "int", $GWL_STYLE )[0] + $HDS_NOSIZING ) ; Create Marker (an orange line placed above the header of the column being searched) $g_idMarker = GUICtrlCreateLabel("", 0, 0) GUICtrlSetBkColor(-1, 0xFFA060) ; orange _MoveMarker($g_iSearchCol) _GUICtrlListView_SetSelectedColumn($g_idListView, $g_iSearchCol) ; Create Context menu $g_idContextDummy = GUICtrlCreateDummy() Local $idContextMenu = GUICtrlCreateContextMenu($g_idContextDummy) Local $idContext_GetText = GUICtrlCreateMenuItem("Get text", $idContextMenu) GUICtrlCreateMenuItem("", $idContextMenu) Local $idContext_ShowAll = GUICtrlCreateMenuItem("Show all rows", $idContextMenu) Local $idContext_RightClickHeaders = GUICtrlCreateMenuItem("Right-click Headers", $idContextMenu) GUICtrlSetState(-1, 1) ; $GUI_CHECKED = 1 $g_hContextMenu = GuiCtrlGetHandle($idContextMenu) ; Sorting information $g_iSortDir = 0x0400 ; $HDF_SORTUP = 0x0400 Local $iSortCol = -1, $iSortColPrev = -1 ; Register message handlers GUIRegisterMsg($WM_DRAWITEM, "WM_DRAWITEM") GUIRegisterMsg($WM_NOTIFY, "WM_NOTIFY") GUIRegisterMsg($WM_COMMAND, "WM_COMMAND") ; Sets the virtual number of items in a virtual list-view control GUICtrlSendMsg($g_idListView, $LVM_SETITEMCOUNT, $g_iRows, 0) GUISetState(@SW_SHOW) ; Message loop Local $aSearch[$g_iRows], $iStart While 1 Switch GUIGetMsg() Case $g_idComboCol, $g_idComboColDummy, $idSearchHow $g_iSearchCol = GUICtrlRead($g_idComboCol) $sSearchHow = GUICtrlRead($idSearchHow) Select Case $g_iSearchCol <> $iSearchColPrev _MoveMarker($g_iSearchCol) ; Search column will be selected below, after ContinueCase $iSearchColPrev = $g_iSearchCol Case $sSearchHow <> $sSearchHowPrev $sSearchHowPrev = $sSearchHow Case Else ; no change in both Combo controls (same search column, same search way) ContinueLoop EndSelect ContinueCase Case $g_idEditDummy _GUICtrlHeader_SetItemFormat($g_hHeader, $iSortCol, $HDF_STRING + ($iSortCol > -1 ? $g_aColAligns[$iSortCol] : 0)) $g_sSearch = GUICtrlRead($idEdit) $g_tIndex = $g_tDefaultIndex ; Sorting information (same as 1st launch, to avoid descending displays when all unsorted rows are shown) $g_iSortDir = 0x0400 ; $HDF_SORTUP = 0x0400 $iSortCol = -1 $iSortColPrev = -1 If $g_sSearch = "" Then ; Empty search string, display all rows $g_aSubArray = $g_aArray $g_aSubArray2 = $g_aArray $g_iSearch = $g_iRows GUICtrlSetState($idPrev, $GUI_DISABLE) GUICtrlSetState($idNext, $GUI_DISABLE) Else ; Find rows matching the search string $g_iSearch = 0 If $sSearchHow = "Normal search" Then ; all searches use RegEx => escape 12 + 1 metacharacters $g_sSearch = StringRegExpReplace($g_sSearch, "(\\|\.|\^|\$|\||\[|\(|\{|\*|\+|\?|\#|\))" , "\\$1") EndIf ; ConsoleWrite("$sSearchHow = " & $sSearchHow & @TAB & "$g_sSearch = " & $g_sSearch & @lf) Dim $aSearch[$g_iRows] For $i = 0 To $g_iRows - 1 If StringRegExp($g_aArray[$i][$g_iSearchCol], "(?i)" & $g_sSearch) Then For $j = 0 To $g_iCols - 1 $g_aSubArray2[$g_iSearch][$j] = $g_aArray[$i][$j] Next $aSearch[$i] = 1 ; include row ($aSearch will serve if user wants to show all rows and click Next / Prec) $g_iSearch += 1 EndIf Next ; Delete eventual temporary subindexes For $i = 0 To $g_iCols - 1 If VarGetType($g_aIndexTemp[$i]) = "DLLStruct" Then $g_aIndexTemp[$i] = "" ; "String" Next $g_aSubArray = $g_bShowAllRows ? $g_aArray : $g_aSubArray2 GUICtrlSetState($idPrev, ($g_bShowAllRows And $g_iSearch And $g_iSearch < $g_iRows) ? $GUI_ENABLE : $GUI_DISABLE) GUICtrlSetState($idNext, ($g_bShowAllRows And $g_iSearch And $g_iSearch < $g_iRows) ? $GUI_ENABLE : $GUI_DISABLE) EndIf GUICtrlSetData($idResult, " " & $g_iSearch & ($g_sSearch = "" ? " rows (no pattern)" : " matching rows")) GUICtrlSendMsg($g_idListView, $LVM_SETITEMCOUNT, $g_bShowAllRows ? $g_iRows : $g_iSearch, 0) _GUICtrlListView_SetSelectedColumn($g_hListView, $g_iSearchCol) ; seems ok here (after $LVM_SETITEMCOUNT) Case $g_idListView ; Sort $iSortCol = GUICtrlGetState($g_idListView) If $iSortCol <> $iSortColPrev Then _GUICtrlHeader_SetItemFormat($g_hHeader, $iSortColPrev, $HDF_STRING + ($iSortColPrev > -1 ? $g_aColAligns[$iSortColPrev] : 0)) EndIf ; Set $g_tIndex + eventual update of $g_aIndex[$iSortCol] OR $g_aIndexTemp[$iSortCol] If $g_bShowAllRows Or $g_sSearch = "" Or $g_iSearch = $g_iRows Then _UpdateIndex($g_aIndex, $iSortCol) Else _UpdateIndex($g_aIndexTemp, $iSortCol) EndIf $g_iSortDir = (($iSortCol = $iSortColPrev) ? ($g_iSortDir = $HDF_SORTUP ? $HDF_SORTDOWN : $HDF_SORTUP) : ($HDF_SORTUP)) _GUICtrlHeader_SetItemFormat($g_hHeader, $iSortCol, $HDF_STRING + $g_aColAligns[$iSortCol] + $g_iSortDir) GUICtrlSendMsg($g_idListView, $LVM_SETSELECTEDCOLUMN, $iSortCol, 0) GUICtrlSendMsg($g_idListView, $LVM_SETITEMCOUNT, $g_bShowAllRows ? $g_iRows : $g_iSearch, 0) $iSortColPrev = $iSortCol ; Update $aSearch (eventually) + automatic display of 1st match (eventually too) If $g_bShowAllRows And $g_sSearch And $g_iSearch And $g_iSearch < $g_iRows Then _Update_aSearch($aSearch, $iSortCol, $idPrev, $idNext) EndIf Case $idNext $iStart = $g_iLvItem = - 1 ? 0 : $g_iLvItem < $g_iRows - 1 ? $g_iLvItem + 1 : 0 While 1 ; The while loop is used to start all over when last row in the listview is reached For $i = $iStart To $g_iRows - 1 If $aSearch[$i] And $i > $g_iLvItem Then ExitLoop Next If $i < $g_iRows Then ExitLoop $g_iLvItem = -1 $iStart = 0 Wend If $g_iLvItem > - 1 Then _GUICtrlListView_SetItemSelected($g_idListView, $g_iLvItem, False, False) _GUICtrlListView_ClickItem($g_idListView, $i) If $iStart = 0 Then Local $iGetTopIndex = _GUICtrlListView_GetTopIndex($g_idListView) _GUICtrlListView_Scroll($g_idListView, 0, ($i - $iGetTopIndex) * $iGetItemSpacingY) EndIf _GUICtrlListView_SetItemSelected($g_idListView, $i, True, True) Case $idPrev $iStart = $g_iLvItem = - 1 ? $g_iRows - 1 : $g_iLvItem > 0 ? $g_iLvItem - 1 : $g_iRows - 1 While 1 ; The while loop is used to start all over when first row in the listview is reached For $i = $iStart To 0 Step -1 If $aSearch[$i] And $i < $g_iLvItem Then ExitLoop Next If $i > -1 Then ExitLoop $g_iLvItem = $g_iRows $iStart = $g_iRows - 1 Wend If $g_iLvItem > - 1 Then _GUICtrlListView_SetItemSelected($g_idListView, $g_iLvItem, False, False) _GUICtrlListView_ClickItem($g_idListView, $i) If $iStart = 0 Then Local $iGetTopIndex = _GUICtrlListView_GetTopIndex($g_idListView) _GUICtrlListView_Scroll($g_idListView, 0, ($i - $iGetTopIndex) * $iGetItemSpacingY) EndIf _GUICtrlListView_SetItemSelected($g_idListView, $i, True, True) Case $g_idContextDummy If $g_iItem > - 1 Then _GUICtrlListView_SetSelectedColumn($g_hListView, $g_iSubItem) GUICtrlSetState($idContext_GetText, $g_iItem = - 1 ? $GUI_DISABLE : $GUI_ENABLE) Local $iMenu_Choice = _TrackPopupMenu($g_hContextMenu, $g_hGui, MouseGetPos(0), MouseGetPos(1)) If $iMenu_Choice Then Switch $iMenu_Choice Case $idContext_GetText ; Get text Local $sGetText = _GetText($g_iItem, $g_iSubItem) MsgBox($MB_TOPMOST, "Context menu", "Row = " & $g_iItem & " Column = " & $g_iSubItem & " Text = " & $sGetText & @lf) Case $idContext_ShowAll ; Show all rows ? If BitAND(GUICtrlRead($idContext_ShowAll), 4) = 4 Then ; $GUI_UNCHECKED = 4 GUICtrlSetState($idContext_ShowAll, 1) ; $GUI_CHECKED = 1 $g_bShowAllRows = True $g_aSubArray = $g_aArray ; Set $g_tIndex + eventual update $g_aIndex[$iSortCol] If $iSortCol > - 1 Then _UpdateIndex($g_aIndex, $iSortCol) ; Update $aSearch (eventually) + automatic display of 1st match (eventually too) If $g_sSearch And $g_iSearch And $g_iSearch < $g_iRows Then _Update_aSearch($aSearch, $iSortCol, $idPrev, $idNext) Else GUICtrlSetState($idContext_ShowAll, 4) ; $GUI_UNCHECKED = 4 $g_bShowAllRows = False $g_aSubArray = $g_aSubArray2 ; Set $g_tIndex + eventual update of $g_aIndexTemp[$iSortCol] If $iSortCol > - 1 Then _UpdateIndex($g_aIndexTemp, $iSortCol) ; No eventual update of $aSearch because $g_bShowAllRows = False (2 buttons Prev & Next are disable in this case) EndIf GUICtrlSetState($idPrev, ($g_bShowAllRows And $g_sSearch And $g_iSearch And $g_iSearch < $g_iRows) ? $GUI_ENABLE : $GUI_DISABLE) GUICtrlSetState($idNext, ($g_bShowAllRows And $g_sSearch And $g_iSearch And $g_iSearch < $g_iRows) ? $GUI_ENABLE : $GUI_DISABLE) GUICtrlSendMsg($g_idListView, $LVM_SETITEMCOUNT, $g_bShowAllRows ? $g_iRows : $g_iSearch, 0) Case $idContext_RightClickHeaders ; Activate headers right-click ? If BitAND(GUICtrlRead($idContext_RightClickHeaders), 4) = 4 Then ; $GUI_UNCHECKED = 4 GUICtrlSetState($idContext_RightClickHeaders, 1) ; $GUI_CHECKED = 1 $g_bRightClickHeaders = True Else GUICtrlSetState($idContext_RightClickHeaders, 4) ; $GUI_UNCHECKED = 4 $g_bRightClickHeaders = False EndIf EndSwitch Endif Case $GUI_EVENT_RESTORE ; needed, or Marker goes back in 0, 0 after Restore (why ?) _MoveMarker($g_iSearchCol) Case $GUI_EVENT_CLOSE ExitLoop EndSwitch WEnd ; Cleanup GUIDelete($g_hGui) EndFunc ;==>Example ;======================================================================== Func WM_DRAWITEM($hWnd, $iMsg, $wParam, $lParam) ; Display items in an owner drawn ListView (called once per item : no separate messages for each subitem +++) Local Static $tRect = DllStructCreate( $tagRECT ), $pRect = DllStructGetPtr( $tRect ), $tSize = DllStructCreate( $tagSIZE ) Local Static $hBrushYellow = _WinAPI_CreateSolidBrush( 0xFFFF00 ), $hBrushCyan = _WinAPI_CreateSolidBrush( 0x00FFFF ) ; Yellow and cyan, BGR Local Static $hBrushHighLight = _WinAPI_GetSysColorBrush( $COLOR_HIGHLIGHT ), $hBrushButtonFace = _WinAPI_GetSysColorBrush( $COLOR_BTNFACE ) Local $tDrawItem = DllStructCreate( $tagDRAWITEM, $lParam ), $itemID = DllStructGetData( $tDrawItem, "itemID" ), $iState = DllStructGetData( $tDrawItem, "itemState" ), $hDC = DllStructGetData( $tDrawItem, "hDC" ), $sItemText ; Loop through columns ($i is the column index) For $i = 0 To $g_iCols - 1 ; Subitem rectangle DllStructSetData( $tRect, 2, $i ) ; Top DllStructSetData( $tRect, 1, $LVIR_BOUNDS ) ; Left GUICtrlSendMsg( $g_idListView, $LVM_GETSUBITEMRECT, $itemID, $pRect ) DllStructSetData( $tRect, 1, DllStructGetData( $tRect, 1 ) + 0 ) ; Left margin ; If $i = 0 (first column), the rectangle is calculated for the entire listview item. ; Compensate for this by setting the width of the rectangle to the width of the first column. ; Before that, if item is selected, fill the entire listview item with the highlight background color. If $i = 0 Then If BitAND( $iState, $ODS_SELECTED ) Then DllCall( "user32.dll", "int", "FillRect", "handle", $hDC, "struct*", $tRect, "handle", $fListViewHasFocus = 1 ? $hBrushHighLight : $hBrushButtonFace ) ; _WinAPI_FillRect DllStructSetData( $tRect, 3, DllStructGetData( $tRect, 1 ) + GUICtrlSendMsg( $g_idListView, $LVM_GETCOLUMNWIDTH, 0, 0 ) ) EndIf ; Retrieve subitem text If $g_iSortDir = 0x0400 Then ; $HDF_SORTUP = 0x0400 $sItemText = $g_aSubArray[$g_tIndex.arr($itemID + 1)][$i] Else $sItemText = $g_aSubArray[$g_tIndex.arr(($g_bShowAllRows ? $g_iRows : $g_iSearch) - $itemID)][$i] EndIf ; Subitem rectangle for right and center aligned columns If $g_aColAligns[$i] Then ; $HDF_LEFT = 0, $HDF_RIGHT = 1, $HDF_CENTER = 2 DllCall( "gdi32.dll", "bool", "GetTextExtentPoint32W", "handle", $hDC, "wstr", $sItemText, "int", StringLen( $sItemText ), "struct*", $tSize ) ; _WinAPI_GetTextExtentPoint32 Switch $g_aColAligns[$i] Case 1 ; $HDF_RIGHT DllStructSetData( $tRect, "Left", DllStructGetData( $tRect, "Right" ) - DllStructGetData( $tSize, "X" ) - 6 ) Case 2 ; $HDF_CENTER DllStructSetData( $tRect, "Left", DllStructGetData( $tRect, "Left" ) + ( DllStructGetData( $tRect, "Right" ) - DllStructGetData( $tRect, "Left" ) - DllStructGetData( $tSize, "X" ) ) / 2 - 3 ) EndSwitch EndIf ; Subitem text color DllCall( "gdi32.dll", "int", "SetTextColor", "handle", $hDC, "int", BitAND( $iState, $ODS_SELECTED ) ? $fListViewHasFocus = 1 ? 0xFFFFFF : 0x000000 : 0x000000 ) ; _WinAPI_SetTextColor ; Draw subitem text DllCall( "user32.dll", "int", "DrawTextW", "handle", $hDC, "wstr", $sItemText, "int", StringLen( $sItemText ), "struct*", $tRect, "uint", 0 ) ; _WinAPI_DrawText ; $i is column index, $g_iSearchCol is the search column ; Mark matching substring only if column index = search column If $i <> $g_iSearchCol Then ContinueLoop ; Matching substring? If $g_sSearch Then Local $sMatch = StringRegExp( $sItemText, "(?i)" & $g_sSearch, 1 ) If Not @error Then ; match found Local $extended = @extended, $iLen = StringLen( $sMatch[0] ) ; Rectangle for matching substring DllCall( "gdi32.dll", "bool", "GetTextExtentPoint32W", "handle", $hDC, "wstr", $sItemText, "int", $extended - $iLen - 1, "struct*", $tSize ) ; _WinAPI_GetTextExtentPoint32 DllStructSetData( $tRect, "Left", DllStructGetData( $tRect, "Left" ) + DllStructGetData( $tSize, "X" ) ) DllCall( "gdi32.dll", "bool", "GetTextExtentPoint32W", "handle", $hDC, "wstr", $sMatch[0], "int", $iLen, "struct*", $tSize ) ; _WinAPI_GetTextExtentPoint32 DllStructSetData( $tRect, "Right", DllStructGetData( $tRect, "Left" ) + DllStructGetData( $tSize, "X" ) ) ; Fill rectangle with yellow or cyan (selected) background color DllStructSetData( $tRect, 2, DllStructGetData( $tRect, 2 ) + 1 ) ; Top margin DllCall( "user32.dll", "int", "FillRect", "handle", $hDC, "struct*", $tRect, "handle", BitAND( $iState, $ODS_SELECTED ) ? $hBrushCyan : $hBrushYellow ) ; _WinAPI_FillRect ; Draw matching substring in rectangle DllStructSetData( $tRect, 2, DllStructGetData( $tRect, 2 ) - 1 ) ; Top margin DllCall( "gdi32.dll", "int", "SetTextColor", "handle", $hDC, "int", 0x000000 ) ; _WinAPI_SetTextColor DllCall( "user32.dll", "int", "DrawTextW", "handle", $hDC, "wstr", $sMatch[0], "int", $iLen, "struct*", $tRect, "uint", 0 ) ; _WinAPI_DrawText EndIf EndIf Next Return $GUI_RUNDEFMSG #forceref $hWnd, $iMsg, $wParam EndFunc ;======================================================================== Func WM_NOTIFY($hWnd, $iMsg, $wParam, $lParam) Local $tNMHDR = DllStructCreate($tagNMHDR, $lParam) Switch HWnd(DllStructGetData($tNMHDR, "hWndFrom")) Case $g_hListView Switch DllStructGetData($tNMHDR, "Code") Case $LVN_ITEMCHANGED Local $tNMListView = DllStructCreate($tagNMLISTVIEW, $lParam) Local $iNewState = DllStructGetData($tNMListView, "NewState") If BitAND($iNewState, $LVIS_FOCUSED) Then $g_iLvItem = DllStructGetData($tNMListView, "Item") Case $NM_RCLICK Local $tInfo = DllStructCreate($tagNMITEMACTIVATE, $lParam) $g_iItem = DllStructGetData($tInfo, "Index") ;~ If $g_iItem > -1 Then ; valid row $g_iSubItem = DllStructGetData($tInfo, "SubItem") GUICtrlSendToDummy($g_idContextDummy) ;~ EndIf EndSwitch Case $g_hHeader Switch DllStructGetData($tNMHDR, "Code") Case $NM_RCLICK If $g_bRightClickHeaders Then Local $aHit = _GUICtrlListView_SubItemHitTest($g_hListView) ; $aHit[1] : 0-based index of the LV subitem... i.e. the column in our case (may be -1 if right click on empty part of header) If $aHit[1] > - 1 Then ; valid column GUICtrlSetData($g_idComboCol, $aHit[1]) GUICtrlSendToDummy($g_idComboColDummy) EndIf EndIf Case $HDN_ENDTRACKW ; keep it, in case someone needs it _MoveMarker(GUICtrlRead($g_idComboCol)) Case $HDN_DIVIDERDBLCLICKW ; keep it, in case someone needs it Local $tNMHEADER = DllStructCreate($tagNMHEADER, $lParam) Local $iCol = DllStructGetData($tNMHEADER, "Item") _GUICtrlListView_SetColumnWidth($g_idListView, $iCol, $g_aWidths[$iCol]) ; initial size _MoveMarker(GUICtrlRead($g_idComboCol)) EndSwitch EndSwitch Return $GUI_RUNDEFMSG EndFunc ;==>WM_NOTIFY ;======================================================================== Func WM_COMMAND($hWnd, $iMsg, $wParam, $lParam) Local $hWndFrom = $lParam Local $iCode = BitShift($wParam, 16) ; High word Switch $hWndFrom Case $g_hEdit Switch $iCode Case $EN_CHANGE GUICtrlSendToDummy($g_idEditDummy) EndSwitch EndSwitch Return $GUI_RUNDEFMSG EndFunc ;==>WM_COMMAND ;======================================================================== Func _Generate_All(ByRef $g_aArray) ConsoleWrite("$g_iRows = " & $g_iRows & " $g_iCols = " & $g_iCols & @CRLF) $g_aArray = FAS_Random2DArrayAu3($g_iRows, "sifdtr", "abcdefghijklmnopqrstuvwxyz") ; $g_aArray = FAS_Random2DArrayAu3($g_iRows, "sifdtr", "abcdefghijklmnopqrstuvwxyz" & "\.^$|[({*+?#)") ; 12 + 1 RegEx metacharacters For $i = 0 To $g_iRows - 1 $g_tIndex.arr($i + 1) = $i Next EndFunc ;==>_Generate_All ;======================================================================== Func _SortArrayStruct(Const ByRef $aArray, $iCol, $iRows) Local $tIndex = DllStructCreate("uint arr[" & $iRows & "]") Local $pIndex = DllStructGetPtr($tIndex) Local Static $hDll = DllOpen("kernel32.dll") Local Static $hDllComp = DllOpen("shlwapi.dll") Local $lo, $hi, $mi, $r ; Sorting by one column For $i = 1 To $iRows - 1 $lo = 0 $hi = $i - 1 Do $mi = Int(($lo + $hi) / 2) $r = DllCall($hDllComp, 'int', 'StrCmpLogicalW', 'wstr', $aArray[$i][$iCol], 'wstr', $aArray[DllStructGetData($tIndex, 1, $mi + 1)][$iCol])[0] Switch $r Case -1 $hi = $mi - 1 Case 1 $lo = $mi + 1 Case 0 ExitLoop EndSwitch Until $lo > $hi DllCall($hDll, "none", "RtlMoveMemory", "struct*", $pIndex + ($mi + 1) * 4, "struct*", $pIndex + $mi * 4, "ulong_ptr", ($i - $mi) * 4) DllStructSetData($tIndex, 1, $i, $mi + 1 + ($lo = $mi + 1)) Next Return $tIndex EndFunc ;==>_SortArrayStruct ;======================================================================== Func _UpdateIndex(ByRef $aIndex, $iCol) If VarGetType($aIndex[$iCol]) = "DLLStruct" Then $g_tIndex = $aIndex[$iCol] Else $g_tIndex = _SortArrayStruct($g_aSubArray, $iCol, $g_bShowAllRows ? $g_iRows : $g_iSearch) $aIndex[$iCol] = $g_tIndex ; "DLLStruct" (or "Int32" when no match found +++) EndIf EndFunc ;==>_UpdateIndex ;======================================================================== Func _Update_aSearch(ByRef $aSearch, $iSortCol, $idPrev, $idNext) $g_iSearch = 0 Dim $aSearch[$g_iRows] For $i = 0 To $g_iRows - 1 If StringRegExp($g_aArray[$g_tIndex.arr($g_iSortDir = 0x0400 ? $i + 1 : $g_iRows - $i)][$g_iSearchCol], "(?i)" & $g_sSearch) Then $aSearch[$i] = 1 ; include row $g_iSearch += 1 EndIf Next If $g_iSearch And $iSortCol = $g_iSearchCol Then GUICtrlSetState($idPrev, $GUI_ENABLE) GUICtrlSetState($idNext, $GUI_ENABLE) $g_iLvItem = - 1 ; comment this line if 1st match not to be displayed on 1st row ControlClick($g_hGui, "", $idNext) EndIf EndFunc ;==>_Update_aSearch ;======================================================================== Func _MoveMarker($iCol) Local $aRect = _GUICtrlHeader_GetItemRect($g_hHeader, $iCol) ControlMove($g_hGui, "", $g_idMarker, 10 + $aRect[0], 40 - 3, $aRect[2] - $aRect[0] + 1, 3) ; 10 / 40 are LV coords EndFunc ;==>_MoveMarker ;======================================================================== Func _TrackPopupMenu($hMenu, $hWnd, $iX, $iY) ; $TPM_RETURNCMD (0x0100) returns the menu item identifier of the user's selection in the return value. Return DllCall("user32.dll", "int", "TrackPopupMenuEx", "hwnd", $hMenu, "int", 0x0100, "int", $iX, "int", $iY, "hwnd", $hWnd, "ptr", 0)[0] EndFunc ;==>_TrackPopupMenu ;======================================================================== Func _GetText($iItem, $iSubItem) Local $sGetText If $g_iSortDir = 0x0400 Then ; $HDF_SORTUP = 0x0400 $sGetText = $g_aSubArray[$g_tIndex.arr($iItem + 1)][$iSubItem] Else $sGetText = $g_aSubArray[$g_tIndex.arr(($g_bShowAllRows ? $g_iRows : $g_iSearch) - $iItem)][$iSubItem] EndIf Return $sGetText EndFunc ;==>_GetText ;======================================================================== Func _ComputeLV_Height($iNb_Rows, $bHeader = True, $bBorder = True) Local $hGui = GUICreate("", 170, 200) ; test values not to be changed Local $idListView = GUICtrlCreateListView("Col 0", 10, 10, 150, 180) ; border $WS_EX_CLIENTEDGE Local $iClient_Height = WinGetClientSize(GUICtrlGetHandle($idListView))[1] Local $iBorder_Height = 180 - $iClient_Height Local $hHeader = GUICtrlSendMsg($idListView, $LVM_GETHEADER, 0, 0) Local $iHeader_Height = _WinAPI_GetWindowHeight($hHeader) Local $iGetItemSpacingY = _GUICtrlListView_GetItemSpacingY($idListView, True) GUIDelete($hGui) Return ($iNb_Rows * $iGetItemSpacingY) + ($bHeader ? $iHeader_Height : 0) + ($bBorder ? $iBorder_Height : 0) EndFunc ;==>_ComputeLV_Height Concerning a new function _ComputeLV_Height() found at the very end of the script, it should deserve explanations in a separate post. Basically, the function computes an accurate ListView height, which will be used during Gui and LV creation. For example, in the script, we want 40 full rows in LV, without having any additional vertical pixels (half rows) at the bottom of the LV. If I'm not mistaken, this is how LarsJ's "788" listview height (40 full rows) is computed : LarsJ's 788 LV height = => 40 rows X 19 = 760 => Header height = 24 => 2 x 2 borders = 4 ($WS_EX_CLIENTEDGE) 760 + 24 + 4 = 788 When we run the script, each one of us will have a different ListView height because of our different OS's (or the modif. we did in Windows parameters). On my computer, it's not 788 but 624 which is returned by _ComputeLV_Height (to have 40 full rows). Here is a pic of my last 40th row, without a single additional or missing pixel (1st row is 0, which explains "39" written at the end of the last row). Let's hope the function will work for any user. By the way, I got rid of the Combo "All" option in the script, as it is already complicated enough. Thanks for not asking new implementations as I won't be here often from now on. Good luck to you all and stay healthy Edit #1 - update June 10th 2021 : disable 2 search buttons (Prev / Next) if number of matched rows = number of initial array rows, when search field is not empty (a . with RegEx search for instance that matches all rows) and "Show all rows" is ticked in context menu.
    3 points
  2. Ever needed C style nested structs, unions or easy pointer references in your DllStruct? Then this may be your solution! It also comes with some quality of life functions for better debugging, like being able to get the original string you used when creating the struct. Download: latest Example: #AutoIt3Wrapper_Change2CUI=Y #NoTrayIcon #include <WinAPIHObj.au3> #include <WinAPIError.au3> #include <WinAPISysWin.au3> #include <WinAPIProc.au3> #include <WinAPIFiles.au3> #include <String.au3> #include "DllStructEx.au3" #include "DllStructEx.debug.au3" #Region Global variables Global Const $tagCONSOLE_CURSOR_INFO = "dword dwSize;int bVisible" Global Const $tagINPUT_RECORD = _ "WORD EventType;"& _ "union {"& _ " KEY_EVENT_RECORD KeyEvent;"& _ " MOUSE_EVENT_RECORD MouseEvent;"& _ " WINDOW_BUFFER_SIZE_RECORD WindowBufferSizeEvent;"& _ " MENU_EVENT_RECORD MenuEvent;"& _ " FOCUS_EVENT_RECORD FocusEvent;"& _ "} Event;" Global Const $EventType_FOCUS_EVENT = 0x0010, $EventType_KEY_EVENT = 0x0001, $EventType_MENU_EVENT = 0x0008, $EventType_MOUSE_EVENT = 0x0002, $EventType_WINDOW_BUFFER_SIZE_EVENT = 0x0004 Global Const $tagKEY_EVENT_RECORD = _ "BOOL bKeyDown;"& _ "WORD wRepeatCount;"& _ "WORD wVirtualKeyCode;"& _ "WORD wVirtualScanCode;"& _ "union {"& _ " WCHAR UnicodeChar;"& _ " CHAR AsciiChar;"& _ "} uChar;"& _ "DWORD dwControlKeyState;" Global Const $tagMOUSE_EVENT_RECORD = _ "COORD dwMousePosition;" & _ "DWORD dwButtonState;" & _ "DWORD dwControlKeyState;" & _ "DWORD dwEventFlags;" Global Const $tagCOORD = _ "SHORT X;"& _ "SHORT Y;" Global Const $tagWINDOW_BUFFER_SIZE_RECORD = _ "COORD dwSize;" Global Const $tagMENU_EVENT_RECORD = _ "UINT dwCommandId;" Global Const $tagFOCUS_EVENT_RECORD = _ "BOOL bSetFocus;" Global Const $tagCONSOLE_SCREEN_BUFFER_INFO = _ "COORD dwSize;"& _ "COORD dwCursorPosition;"& _ "WORD wAttributes;"& _ "SMALL_RECT srWindow;"& _ "COORD dwMaximumWindowSize;" Global Const $tagSMALL_RECT = _ "SHORT Left;"& _ "SHORT Top;"& _ "SHORT Right;"& _ "SHORT Bottom;" #EndRegion Global variables #Region Functions Func AllocConsole() Local $aRet = DllCall("kernel32.dll", "BOOL", "AllocConsole") If @error <> 0 Then Return SetError(@error, 0, False) Return $aRet[0] <> 0 EndFunc Func FreeConsole() Local $aRet = DllCall("kernel32.dll", "BOOL", "FreeConsole") If @error <> 0 Then Return SetError(@error, 0, False) Return $aRet[0] <> 0 EndFunc Func IsDebuggerPresent() Local $aRet = DllCall("kernel32.dll", "BOOL", "IsDebuggerPresent") If @error <> 0 Then Return SetError(@error, 0, False) Return $aRet[0] <> 0 EndFunc Func SetConsoleMode($hConsoleHandle, $dwMode) Local $aRet = DllCall("kernel32.dll", "BOOL", "SetConsoleMode", "HANDLE", $hConsoleHandle, "DWORD", $dwMode) If @error <> 0 Then Return SetError(@error, 0, False) Return $aRet[0] <> 0 EndFunc Func SetStdHandle($nStdHandle, $hHandle) ;returns BOOL ;http://msdn.microsoft.com/en-us/library/windows/desktop/ms686244%28v=vs.85%29.aspx Local $aRet = DllCall("kernel32.dll", "BOOL", "SetStdHandle", "DWORD", $nStdHandle, "HANDLE", $hHandle) If @error <> 0 Then Return SetError(@error, 0, False) Return $aRet[0] <> 0 EndFunc Func CreateFile($lpFileName, $dwDesiredAccess, $dwShareMode, $lpSecurityAttributes, $dwCreationDisposition, $dwFlagsAndAttributes) Local $aResult = DllCall("kernel32.dll", "handle", "CreateFileW", "wstr", $lpFileName, "dword", $dwDesiredAccess, "dword", $dwShareMode, "struct*", $lpSecurityAttributes, "dword", $dwCreationDisposition, "dword", $dwFlagsAndAttributes, "ptr", 0) If @error Or ($aResult[0] = Ptr(-1)) Then Return SetError(@error, @extended, 0) ; $INVALID_HANDLE_VALUE Return $aResult[0] EndFunc Func GetConsoleCursorInfo($hConsole, $lpConsoleCursorInfo) Local $aRet = DllCall("kernel32.dll", "BOOL", "GetConsoleCursorInfo", "hwnd", $hConsole, "STRUCT*", $lpConsoleCursorInfo) If @error <> 0 Then Return SetError(@error, 0, False) Return $aRet[0] <> 0 EndFunc Func SetConsoleCursorInfo($hConsole, $lpConsoleCursorInfo) Local $aRet = DllCall("kernel32.dll", "BOOL", "SetConsoleCursorInfo", "hwnd", $hConsole, "STRUCT*", $lpConsoleCursorInfo) If @error <> 0 Then Return SetError(@error, 0, False) Return $aRet[0] <> 0 EndFunc Func SetConsoleCtrlHandler($HandlerRoutine, $Add) Local $aRet = DllCall("kernel32.dll", "BOOL", "SetConsoleCtrlHandler", "ptr", $HandlerRoutine, "BOOL", $Add) If @error <> 0 Then Return SetError(@error, 0, False) Return $aRet[0] <> 0 EndFunc Func GetConsoleScreenBufferInfo($hConsole, $tScreenBufferInfo) $aRet = DllCall("kernel32.dll", "bool", "GetConsoleScreenBufferInfo", "hwnd", $hConsole, "STRUCT*", $tScreenBufferInfo) If @error <> 0 Then Return SetError(@error, 0, False) Return $aRet[0] <> 0 EndFunc Func GetConsoleCursorPosition($hConsoleOutput, $dwCursorPosition, $tScreenBufferInfo) GetConsoleScreenBufferInfo($hConsoleOutput, $tScreenBufferInfo) If @error <> 0 Then Return SetError(@error, @extended, False) $dwCursorPosition = DllStructCreate($tagCOORD, DllStructGetPtr($tScreenBufferInfo, 2)) $dwCursorPosition.X = $dwCursorPosition.X $dwCursorPosition.Y = $dwCursorPosition.Y Return True EndFunc Func SetConsoleCursorPosition($hConsoleOutput, $dwCursorPosition) Local $aRet = DllCall("kernel32.dll", "BOOL", "SetConsoleCursorPosition", "HANDLE", $hConsoleOutput, "STRUCT", $dwCursorPosition) If @error <> 0 Then Return SetError(@error, 0, False) Return $aRet[0] <> 0 EndFunc Func ReadConsoleInput($hConsoleInput, $lpBuffer, $nLength) Local $aRet = DllCall("kernel32.dll", "BOOL", "ReadConsoleInput", "HANDLE", $hConsoleInput, "STRUCT*", $lpBuffer, "DWORD", $nLength, "DWORD*", 0) If @error <> 0 Then Return SetError(@error, 0, False) Return $aRet[0] <> 0 EndFunc Func FillConsoleOutputCharacter($hConsoleInput, $cCharacter, $nLength, $dwWriteCoord) Local $aRet = DllCall("kernel32.dll", "BOOL", "FillConsoleOutputCharacterW", "HANDLE", $hConsoleInput, "BYTE", $cCharacter, "DWORD", $nLength, "STRUCT", $dwWriteCoord, "DWORD*", 0) If @error <> 0 Then Return SetError(@error, 0, False) Return $aRet[0] <> 0 EndFunc Func SetConsoleScreenBufferSize($hConsoleOutput, $dwSize) Local $aRet = DllCall("kernel32.dll", "BOOL", "SetConsoleScreenBufferSize", "HANDLE", $hConsoleOutput, "STRUCT", $dwSize) If @error <> 0 Then Return SetError(@error, 0, False) Return $aRet[0] <> 0 EndFunc Func _ConsoleWriteCenter($columns, $rows, $hStdOut, $sText) Local $_tCOORD = DllStructCreate($tagCOORD) Local $tCOORD = DllStructCreate($tagCOORD) ;GetConsoleCursorPosition($hStdOut, $_tCOORD, $tScreenBufferInfo) Local $s = $sText Local $l = StringLen($s) $tCOORD.X = Round($columns / 2) - Round($l / 2) $tCOORD.Y = Round($rows / 2) SetConsoleCursorPosition($hStdOut, $tCOORD) _WinAPI_WriteConsole($hStdOut, $s) SetConsoleCursorPosition($hStdOut, $_tCOORD) EndFunc Func _ConsoleHideCursor($hStdOut) Local $tConsoleCursorInfo = DllStructCreate($tagCONSOLE_CURSOR_INFO) GetConsoleCursorInfo($hStdOut, $tConsoleCursorInfo) $tConsoleCursorInfo.bVisible = 0 SetConsoleCursorInfo($hStdOut, $tConsoleCursorInfo) EndFunc #EndRegion Functions $a = AllocConsole() $aRet = DllCall("kernel32.dll", "ptr", "GetConsoleWindow") _WinAPI_ShowWindow($aRet[0], @SW_SHOWNORMAL) $hConOut = CreateFile("CONOUT$", BitOR($GENERIC_READ, $GENERIC_WRITE), BitOR($FILE_SHARE_READ, $FILE_SHARE_WRITE), Null, $OPEN_EXISTING, $FILE_ATTRIBUTE_NORMAL) $hConIn = CreateFile("CONIN$", BitOR($GENERIC_READ, $GENERIC_WRITE), BitOR($FILE_SHARE_READ, $FILE_SHARE_WRITE), Null, $OPEN_EXISTING, $FILE_ATTRIBUTE_NORMAL) Global Const $STD_INPUT_HANDLE = -10 Global Const $STD_OUTPUT_HANDLE = -11 Global Const $STD_ERROR_HANDLE = -12 SetStdHandle($STD_OUTPUT_HANDLE, $hConOut) SetStdHandle($STD_INPUT_HANDLE, $hConIn) $hStdIn = _WinAPI_GetStdHandle(0) $hStdOut = _WinAPI_GetStdHandle(1) _ConsoleHideCursor($hStdOut) Global Const $ENABLE_EXTENDED_FLAGS = 0x0080 ;FIXME: store the original mode and restore on exit, to avoid parent console being affected. SetConsoleMode($hStdIn, $ENABLE_EXTENDED_FLAGS) Global $iRun = 1 Global Const $CTRL_C_EVENT = 0 Global Const $CTRL_BREAK_EVENT = 1 Global Const $CTRL_CLOSE_EVENT = 2 Global Const $CTRL_LOGOFF_EVENT = 5 Global Const $CTRL_SHUTDOWN_EVENT = 6 Func HandlerRoutine($dwCtrlType) ;ConsoleWrite("HandlerRoutine"&@CRLF) $iRun = 0 ;https://stackoverflow.com/a/48190051 DllCall("kernel32.dll", "NONE", "ExitThread", "DWORD", 0) Return True EndFunc $hHandlerRoutine = DllCallbackRegister(HandlerRoutine, "BOOL", "DWORD") $pHandlerRoutine = DllCallbackGetPtr($hHandlerRoutine) SetConsoleCtrlHandler($pHandlerRoutine, 1) Global $tCOORD = DllStructCreate($tagCOORD) GLobal $oScreenBufferInfo = DllStructExCreate($tagCONSOLE_SCREEN_BUFFER_INFO) Global Const $tScreenBufferInfo = DllStructExGetStruct($oScreenBufferInfo) Global Const $tSrWindow = DllStructExGetStruct($oScreenBufferInfo.srWindow) GetConsoleScreenBufferInfo($hStdOut, $tScreenBufferInfo) Global $columns = $tSrWindow.Right - $tSrWindow.Left + 1 Global $rows = $tSrWindow.Bottom - $tSrWindow.Top + 1 ;ConsoleWrite(StringFormat("columns: %d\n", $columns)) ;ConsoleWrite(StringFormat("rows: %d\n", $rows)) ;ConsoleWrite(StringFormat("%s x %s\n", $oScreenBufferInfo.dwSize.X, $oScreenBufferInfo.dwSize.y)) Global $tScreenBufferSize = DllStructCreate($tagCOORD) $tScreenBufferSize.X = $columns $tScreenBufferSize.Y = $rows SetConsoleScreenBufferSize($hStdOut, $tScreenBufferSize) _ConsoleWriteCenter($columns, $rows, $hStdOut, StringFormat("%s x %s", $columns, $rows)) $tCOORD.X = 0 $tCOORD.Y = 0 Global Const $FOCUS_EVENT = 0x0010 Global Const $KEY_EVENT = 0x0001 Global Const $MENU_EVENT = 0x0008 Global Const $MOUSE_EVENT = 0x0002 Global Const $WINDOW_BUFFER_SIZE_EVENT = 0x0004 $oINPUT_RECORD = DllStructExCreate($tagINPUT_RECORD) $tINPUT_RECORD = DllStructExGetStruct($oINPUT_RECORD) $tEvent = DllStructExGetStruct($oINPUT_RECORD.Event) $tFocusEvent = DllStructExGetStruct($oINPUT_RECORD.Event.FocusEvent) $tKeyEvent = DllStructExGetStruct($oINPUT_RECORD.Event.KeyEvent) ConsoleWrite(StringFormat("$tFocusEvent: %s\n", DllStructGetPtr($tFocusEvent))) ConsoleWrite(StringFormat("$tKeyEvent: %s\n", DllStructGetPtr($tKeyEvent))) DllStructExDisplay($oINPUT_RECORD) While $iRun Sleep(10) If DllCall("kernel32.dll", "BOOL", "GetNumberOfConsoleInputEvents", "handle", $hStdIn, "DWORD*", 0)[2] > 0 Then SetConsoleCursorPosition($hStdOut, $tCOORD) _WinAPI_WriteConsole($hStdOut, _StringRepeat(" ", $columns)) $tCOORD.Y = 1 SetConsoleCursorPosition($hStdOut, $tCOORD) _WinAPI_WriteConsole($hStdOut, _StringRepeat(" ", $columns)) $tCOORD.Y = 0 SetConsoleCursorPosition($hStdOut, $tCOORD) ReadConsoleInput($hStdIn, $tINPUT_RECORD, 1) ;_WinAPI_WriteConsole($hStdOut, DllStructGetData($tINPUT_RECORD, 1)) Switch ($oINPUT_RECORD.EventType) Case $EventType_FOCUS_EVENT _WinAPI_WriteConsole($hStdOut, "FOCUS_EVENT") $tCOORD.Y = 1 SetConsoleCursorPosition($hStdOut, $tCOORD) ;_WinAPI_WriteConsole($hStdOut, StringFormat("bSetFocus: %s", $oINPUT_RECORD.Event.FocusEvent.bSetFocus)) _WinAPI_WriteConsole($hStdOut, StringFormat("bSetFocus: %s", $tFocusEvent.bSetFocus)) Case $EventType_KEY_EVENT _WinAPI_WriteConsole($hStdOut, "KEY_EVENT") $tCOORD.Y = 1 SetConsoleCursorPosition($hStdOut, $tCOORD) $oEvent = $oINPUT_RECORD.Event $oKeyEvent = $oEvent.KeyEvent $ouChar = $oKeyEvent.uChar _WinAPI_WriteConsole($hStdOut, StringFormat("uChar: %s", $oINPUT_RECORD.Event.KeyEvent.uChar.AsciiChar)) Case $EventType_MENU_EVENT _WinAPI_WriteConsole($hStdOut, "MENU_EVENT") $tCOORD.Y = 1 SetConsoleCursorPosition($hStdOut, $tCOORD) _WinAPI_WriteConsole($hStdOut, StringFormat("dwCommandId: %s", $oINPUT_RECORD.Event.MenuEvent.dwCommandId)) Case $EventType_MOUSE_EVENT ;ConsoleWrite("MOUSE_EVENT"&@CRLF) _WinAPI_WriteConsole($hStdOut, "MOUSE_EVENT") Case $EventType_WINDOW_BUFFER_SIZE_EVENT _ConsoleHideCursor($hStdOut) $tCOORD.X = 0 $tCOORD.Y = 0 GetConsoleScreenBufferInfo($hStdOut, $tScreenBufferInfo) $columns = $tSrWindow.Right - $tSrWindow.Left + 1 $rows = $tSrWindow.Bottom - $tSrWindow.Top + 1 $tScreenBufferSize.X = $columns $tScreenBufferSize.Y = $rows SetConsoleScreenBufferSize($hStdOut, $tScreenBufferSize) FillConsoleOutputCharacter($hStdOut, " ", $columns * $rows, $tCOORD) SetConsoleCursorPosition($hStdOut, $tCOORD) _WinAPI_WriteConsole($hStdOut, "WINDOW_BUFFER_SIZE_EVENT") $tCOORD.Y = 1 SetConsoleCursorPosition($hStdOut, $tCOORD) _WinAPI_WriteConsole($hStdOut, StringFormat("SIZE: %sx%s", $oINPUT_RECORD.Event.WindowBufferSizeEvent.dwSize.X, $oINPUT_RECORD.Event.WindowBufferSizeEvent.dwSize.Y)) _ConsoleWriteCenter($columns, $rows, $hStdOut, StringFormat("%s x %s", $columns, $rows)) Case Else _WinAPI_WriteConsole($hStdOut, "*UNKNOWN*") EndSwitch EndIf WEnd Exit For debugging, DllStructEx.debug.au3 can be used, and feedback for missing debug features is welcome
    2 points
  3. I cannot really develop, but I am willing to test. If you need anything. Skysnake
    2 points
  4. This is a simple but somewhat tricky to do script, that I whipped up in a few hours due to a need. I share, because it would no doubt be helpful to some others, and one of those might even make improvements. Basically, I sometimes need to save web pages ... for a game etc, so I have something I can check or refer to later, about the game. I store the save(s) in a sub-folder of my game folder, called '_Html'. I backup (archive) my game folders after downloading, to a few external drives. Sometimes, not all that often thankfully, file contents of the saved web page folder result in a too long path ... greater than 255 characters. Usually it is an image file that is the culprit, and clearly web browsers are not smart enough to prevent that. It is a problem however when backing up to another drive, even when you kind of mirror the folder paths. For instance, I download to a folder in My Documents, called Downloads and which contains date folders. i.e. C:\Users\TheSaint\Downloads\2021\02\10 And my backups folders imitate that with a shorter version. i.e. D:\Downloads\2021\02\10 So even though the backup folder path is shorter, the source folder path creates an issue and some files are not backed up. I then have 3 choices. (1) Skip the files, losing them forever. (2) Rename the files to shorter names so they at least exist at the destination. (3) Rename the files and rename the matching file entries in any related htm/html files, so that everything still works. My program does option (3) or at least tries to. It isn't foolproof, as that could get quite complex. Unless you download in a very similar way to me, you will need to modify the script, path wise. A fuller folder download path for me, would be like the following. C:\Users\TheSaint\Downloads\2021\02\10\GoG\Irony Curtain - From Matryoshka with Love - Revolutionary Edition\_Html That last folder name, '_Html' is important to my script. So if you don't use that, you would need to adjust for your scenario. Here is a recent file I had the issue with. This is its shortened version. The fuller version had something like 20 or so more characters to the file name, which made the path too long. C:\Users\TheSaint\Downloads\2021\02\10\GoG\Irony Curtain - From Matryoshka with Love - Revolutionary Edition\_Html\Irony Curtain_ From Matryoshka with Love - Original Soundtrack on GOG.com_files\7ca6665e4e388a8850f76d1a792d47db1abaae3dae7996263fb835d.jpg Most of the files in the same folder were much shorter names. All up though, there was 6 image files that had names too long. There was 7 instances in html files that needed adjusting for the shortened names. My program uses a drop box, and interestingly, the too long file name result (@GUI_DragFile) resulted in a Windows short name, which I then had to cater for. One other thing I should probably make clear. If you discovered the issue after a move process, then you will need to restore web folder contents, from destination to the source folder, that did move successfully, before you use my script. Not an issue with a copy process. Basically you drag & drop the errant file onto my program drop box, and it will start checking and renaming. If an error occurs or renaming isn't needed, you will be told. Result is shown in the drop box. More than one same named problem file somewhere in the folder hierarchy, will cause an error. This is deliberate to prevent internal html path errors, due to _ReplaceStringInFile being used. If someone wants to whip up something smarter, be my guest. Currently for my use, it has been working well enough. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; ;; AutoIt Version: 3.3.14.2 ;; ;; ;; ;; Template AutoIt script. ;; ;; ;; ;; AUTHOR: TheSaint ;; ;; ;; ;; SCRIPT FUNCTION: Rename (shorten) a file name in a too long web folder path ;; ;; ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; GUI FUNCTIONS ; DropboxGUI() #include <Constants.au3> #include <GUIConstantsEx.au3> #include <WindowsConstants.au3> #include <ButtonConstants.au3> #include <EditConstants.au3> #include <StaticConstants.au3> #include <Array.au3> #include <File.au3> #include <Misc.au3> _Singleton("shorten-web-filename-thsaint") Global $inifle, $version, $winpos $inifle = @ScriptDir & "\Settings.ini" $version = "v1.0" DropboxGUI() Exit Func DropboxGUI() Local $Label_drop, $Dropbox Local $attrib, $f, $fext, $file, $files, $fldpth, $flepth, $found, $left, $length, $longpth, $name, $p, $pages Local $part, $path, $relpth, $rename, $rep, $result, $right, $success, $target, $top, $webpage ; $right = @DesktopWidth - 87 $left = IniRead($inifle, "Dropbox Window", "left", $right) $top = IniRead($inifle, "Dropbox Window", "top", 27) $Dropbox = GuiCreate("Dropbox", 82, 70, $left, $top, $WS_OVERLAPPED + $WS_CAPTION + $WS_SYSMENU + $WS_VISIBLE _ + $WS_CLIPSIBLINGS, $WS_EX_ACCEPTFILES + $WS_EX_TOPMOST + $WS_EX_TOOLWINDOW) ; $Label_drop = GUICtrlCreateLabel("", 0, 0, 80, 68, $SS_CENTER + $SS_NOTIFY) GUICtrlSetState($Label_drop, $GUI_DROPACCEPTED) GUICtrlSetFont($Label_drop, 8, 400) GUICtrlSetTip($Label_drop, "Drop a Folder or Drive Here!") ; ; SETTINGS $target = "Drop a Web" & @LF & "File HERE" GUICtrlSetData($Label_drop, @LF & $target) GuiSetState() While 1 $msg = GuiGetMsg() Select Case $msg = $GUI_EVENT_CLOSE ; Close the Dropbox $winpos = WinGetPos($Dropbox, "") $left = $winpos[0] If $left < 0 Then $left = 2 ElseIf $left > @DesktopWidth - $winpos[2] Then $left = @DesktopWidth - $winpos[2] EndIf IniWrite($inifle, "Dropbox Window", "left", $left) $top = $winpos[1] If $top < 0 Then $top = 2 ElseIf $top > @DesktopHeight - $winpos[3] Then $top = @DesktopHeight - $winpos[3] EndIf IniWrite($inifle, "Dropbox Window", "top", $top) ; GUIDelete($Dropbox) ExitLoop Case $msg = $GUI_EVENT_DROPPED ; Folder added as new destination by drag and drop If @GUI_DragId = -1 Then If FileExists(@GUI_DragFile) Then $attrib = FileGetAttrib(@GUI_DragFile) If StringInStr($attrib, "D") > 0 Then MsgBox(262192, "Drag Error", "Needs to be a file not a folder.", 0, $Dropbox) Else GUICtrlSetData($Label_drop, @LF & $target) GUICtrlSetState($Label_drop, $GUI_DISABLE) SplashTextOn("", "Checking File Name!", 180, 80, -1, -1, 33) $path = @GUI_DragFile $longpth = FileGetLongName($path) $file = StringSplit($longpth, "\", 1) $file = $file[$file[0]] $fldpth = StringTrimRight($longpth, StringLen($file)) $length = StringLen($longpth) If $length > 254 Then $pages = "" $rep = "" $result = 0 $fext = StringSplit($file, ".", 1) If $fext[0] > 1 Then $fext = "." & $fext[$fext[0]] Else $fext = "" EndIf $name = StringTrimRight($file, StringLen($fext)) While 1 $name = StringTrimRight($name, 1) If $name > "" Then $rename = $name & $fext $flepth = $fldpth & $rename $length = StringLen($flepth) If $length < 255 Then If Not FileExists($flepth) Then $part = StringSplit($longpth, "\_Html", 1) $part = $part[1] & "\_Html" $files = _FileListToArrayRec($part, "*" & $fext, 1, 1, 0, 0) For $f = 1 To $files[0] $found = $files[$f] If StringInStr($found, $file, 1) > 0 Then $result = $result + 1 EndIf Next ;MsgBox(262192, "Check Results", "Name = " & $file & @LF & "Rename = " & $rename & @LF & "Length = " & $length & @LF & "Files = " & $result, 0, $Dropbox) If $result = 1 Then $result = 0 ;FileCopy($path, @ScriptDir & "\xxxxx.tmp", 1) ;$shortpth = FileGetShortName($flepth) ;$success = FileCopy($path, $flepth, 0) $success = FileMove($path, $flepth, 0) If $success = 1 Then $files = _FileListToArrayRec($part, "*.htm*", 1, 1, 0, 1) For $f = 1 To $files[0] $relpth = $files[$f] If StringRight($relpth, 4) = ".htm" Or StringRight($relpth, 5) = ".html" Then If $pages = "" Then $pages = $relpth Else $pages = $pages & "|" & $relpth EndIf EndIf Next ;MsgBox(262192, "Page Results", "Pages = " & $pages, 0, $Dropbox) $pages = StringSplit($pages, "|", 1) For $p = 1 To $pages[0] $webpage = $part & "\" & $pages[$p] ;MsgBox(262192, "Web Page", $webpage, 0, $Dropbox) $rep = _ReplaceStringInFile($webpage, $file, $rename) $result = $result + $rep Next Else MsgBox(262192, "File Rename Failure", "Original Path = " & $longpth & @LF & "Rename Path = " & $flepth, 0, $Dropbox) EndIf Else MsgBox(262192, "File Rename Failure", "More than one copy of the file exists or is too similar.", 0, $Dropbox) EndIf ExitLoop EndIf EndIf Else MsgBox(262192, "File Rename Failure", "File name became too short (folder name[s] too long).", 0, $Dropbox) ExitLoop EndIf WEnd Else MsgBox(262192, "File Rename Skipped", $longpth & @LF & @LF & "File name & path is short enough = " & $length, 0, $Dropbox) EndIf GUICtrlSetData($Label_drop, @LF & $target & @LF & $result & " && " & $success) SplashOff() GUICtrlSetState($Label_drop, $GUI_ENABLE) EndIf Else MsgBox(262192, "Drag Error", "Drag & Drop path doesn't exist.", 0, $Dropbox) EndIf Else MsgBox(262192, "Drag Error", "Drag & Drop failed.", 0, $Dropbox) EndIf Case Else ;;; EndSelect WEnd EndFunc ;=> DropboxGUI Enjoy!
    1 point
  5. Yes, but even so you care enough to give one, not because you want one, but because it’s a way to show appreciation.
    1 point
  6. I can only second @TheXman advice to first expose all of your precise requirements in unambiguous plain english, being sure to cover all your real-world cases. Providing an exhaustive set of examples data-in and expected data-out is a must have, of course. Yes, Regex is a very powerful language by itself, even if it uses a rather uncommon syntax. The flavor used in AutoIt is even Turing-complete, which means it could (in theory) solve any problem solvable in finite time, albeit with absolutely unmanageable complexity. Staying within relatively simple tasks, you should first examine each different form of input data and decide which processing each must get thru. Expose that and thinks will magically become clearer. In fact it's common to see neophytes explain only part of their regex problem, only to discover later that other cases are not covered by their initial request. It's hard for those people to be both precise and exhaustive in the first place. That's how we all learn. OTOH, it's a little painful for helpers to try to follow what we call such a "moving target".
    1 point
  7. For such simple case I use InetRead() _Example() Func _Example() Local $dData = InetRead("http://time.jsontest.com/") ; Convert the ANSI compatible binary string back into a string. Local $sData = BinaryToString($dData) MsgBox(0, "", $sData) EndFunc ;==>_Example
    1 point
  8. @TheXman My apologies for offending you. It is not my intention to take advantage of your kindness. I simply am trying to understand and I truly appreciate the time you have taken to explain these complex matters. I hope you can understand that while a lot of this syntax seems simple to you, that I am struggling to learn it. I am not a professional working in IT; I am an elementary school teacher. I am trying to learn how to become more proficient at this kind of stuff, so I can spend more time teaching and less time copying and pasting. I am not trying to get someone else to do the work for me. I genuinely want to understand. While I tried my best to plan out my needs in advanced, other ideas came to mind as I continued to dig around. Mostly, I did not know how powerful RegEx could be, so I didn't even think most of this could even be accomplished. As I read more of your posts and looked through articles online, I began to see that RegEx could accomplish even more than I knew and so I set my sights higher. Again, my apologies for upsetting you. I hope this message finds you well.
    1 point
  9. I have no patience for chasing moving targets. If you have an ultimate goal in mind, then explain the whole thing in detail, not a piece at a time. Explaining it a piece at a time makes me think that you don't have a well thought out plan and that you are doing whatever it is you are trying to do on-the-fly. It's also a tactic sometimes used by lazy people that are trying to not-so-slyly get others to do their work for them. In either case, as far as I'm concerned, that would be a waste of my time and theirs. If you would rather do it a piece-at-a-time, that's fine. It just won't be with my continued help because I won't willingly allow anyone to waste my time. Also, as I suggested previously, you should provide comprehensive test data and you should also show what the expected results should be for the data that you supply. Doing so removes some of the guess-work that exists when you don't fully and accurately explain the help that you need It also forces you to better understand and describe what the problem is, the help that you require, and maybe even catch errors before asking for help. First your test data was 9 bytes long, Now your test data is 7 & 8 bytes long, with no 9 byte strings. Some of the patterns that you say you are looking for don't even exist within the supplied test data. i.e. "Replace leading 12 with 2". There are no strings with a leading "12". You also say that you want to "replace 12 with 2" but your regex is looking for "22" and not "12". The last StringRegExpReplace() doesn't even include the pattern! It doesn't even look like you are trying.
    1 point
  10. 1 point
  11. or just enable long pathnames Windows Registry Editor Version 5.00 [HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\FileSystem] "LongPathsEnabled"=dword:00000001
    1 point
  12. Help page entitled “_GDIPlus_BitmapCreateFromMemory” returns as expected. Should I run the function thru a comprehensive stress test in my function simulator and compare the output to the help page, or do you want to indicate what the specific problem is?
    1 point
  13. Skeletor, You copied the main part of the script from this thread: https://www.autoitscript.com/forum/topic/179511-write-or-append-to-txt-file/?do=findComment&comment=1288191 But the _FileWriteToLine line is all your own - so do not try to blame me! M23
    1 point
  14. If you change this line: To: It works as intended, inserting the line. However I'm guessing you want to append text to the end of the text already on that line?
    1 point
  15. Where in the helpfile does it state you can use a FileHandle of an already opened file for _FileWriteToLine()? Just use the original filename! Jos
    1 point
  16. Hello It seems to be It append at the beginning of the line. I just modify the code to append at the end. #include <FileConstants.au3> #include <MsgBoxConstants.au3> #include <File.au3> #include <MsgBoxConstants.au3> #include <WinAPIFiles.au3> ; Create file in same folder as script $sFileName = @ScriptDir &"\Test.txt" ; Open file - deleting any existing content $hFilehandle = FileOpen($sFileName, $FO_OVERWRITE) ; Prove it exists If FileExists($sFileName) Then MsgBox($MB_SYSTEMMODAL, "File", "Exists") Else MsgBox($MB_SYSTEMMODAL, "File", "Does not exist") EndIf ; Write a line FileWrite($hFilehandle, "This is line 1" & @CRLF) FileWrite($hFilehandle, "This is line 2") FileClose($hFilehandle) ; Read it MsgBox($MB_SYSTEMMODAL, "File Content", FileRead($sFileName)) ; Append a line _FileWriteToLine2($sFileName, 1, " and I have appended to line 1.",False) ; read it MsgBox($MB_SYSTEMMODAL, "File Content", FileRead($sFileName)) Func _FileWriteToLine2($sFilePath, $iLine, $sText, $bOverWrite = False, $bFill = False) If $bOverWrite = Default Then $bOverWrite = False If $bFill = Default Then $bFill = False If Not FileExists($sFilePath) Then Return SetError(2, 0, 0) If $iLine <= 0 Then Return SetError(4, 0, 0) If Not (IsBool($bOverWrite) Or $bOverWrite = 0 Or $bOverWrite = 1) Then Return SetError(5, 0, 0) If Not IsString($sText) Then $sText = String($sText) If $sText = "" Then Return SetError(6, 0, 0) EndIf If Not IsBool($bFill) Then Return SetError(7, 0, 0) ; Read current file into array Local $aArray = FileReadToArray($sFilePath) ; Create empty array if empty file If @error Then Local $aArray[0] Local $iUBound = UBound($aArray) - 1 ; If Fill option set If $bFill Then ; If required resize array to allow line to be written If $iUBound < $iLine Then ReDim $aArray[$iLine] $iUBound = $iLine - 1 EndIf Else If ($iUBound + 1) < $iLine Then Return SetError(1, 0, 0) EndIf ; Write specific line - array is 0-based so reduce by 1 - and either replace or insert $aArray[$iLine - 1] = ($bOverWrite ? $sText : $aArray[$iLine - 1] & $sText) ; Concatenate array elements Local $sData = "" For $i = 0 To $iUBound $sData &= $aArray[$i] & @CRLF Next $sData = StringTrimRight($sData, StringLen(@CRLF)) ; Required to strip trailing EOL ; Write data to file Local $hFileOpen = FileOpen($sFilePath, FileGetEncoding($sFilePath) + $FO_OVERWRITE) If $hFileOpen = -1 Then Return SetError(3, 0, 0) FileWrite($hFileOpen, $sData) FileClose($hFileOpen) Return 1 EndFunc ;==>_FileWriteToLine PD: _FileWriteToLine need a file path. not file handle.
    1 point
  17. @Norm73 it's always appropriate when it comes directly from the heart. Thanks a lot Concerning your last script, I found this kind of issue (pic below). Here is a way to reproduct it in 5 steps : * Choose column 1 (combo) i.e Strings-2 got the orange marker above (searched column) * Edit search : type an a * Column string-2 : one left click to sort ascending * Combo : switch from Filter to Scroll * Column string-2 : one left click to sort descending. Display : Maybe the 2 new lines you added 1 hour ago fixed it ? Fingers crossed but I doubt it. I remember having had exactly the same issue sometimes, while scripting version "2s", before using the 2nd set of array $g_aSubArray2, plus the new array $aSearch. If you look at code in "2s" you'll find several additional tests when it comes to sorting or switching from "Filter" to "Scroll" as you name it, (which corresponds to my context menu option "Show all rows" when it's checked / unchecked). Also, I remember this kind of line that fixed the issue. The index sort function Func _UpdateIndex() needs to be updated. In the precedent versions (before "2s") it was : $g_tIndex = _SortArrayStruct($g_aSubArray, $iCol, $g_iSearch) Now in "2s", it becomes : $g_tIndex = _SortArrayStruct($g_aSubArray, $iCol, $g_bShowAllRows ? $g_iRows : $g_iSearch) This kind of ternary test in now found in plenty of lines in "2s", this could explain why you're having the issue. Good luck. @powerofos it's an interesting question but as the data source is an array, then maybe it could work if the array was rearranged internally after you drag a header to another place, not forgetting the sub-arrays and related arrays like these ones : Global $g_aCols = ["Strings", "Integers", "Floats", "Dates", "Times", "R/C"], $g_aWidths = [230, 61, 124, 70, 60, 60] Global $g_aColAligns[$g_iCols] = [2, 1, 1, 1, 1, 1] ; $HDF_LEFT = 0, $HDF_RIGHT = 1, $HDF_CENTER = 2 But I'm not even sure of what I just wrote, it requires tests. I remember having used $LVS_EX_HEADERDRAGDROP in my CSV file editor and it worked really fine (though it wasn't a virtual LV). I wish the solution is to keep the arrays untouched but I don't remember exactly how it worked there ! As you're using the script, may I suggest you download the "2s" version just above because it's the version that could eventually be updated. But please think twice before allowing the draggable header style : wouldn't it be better to create the LV with the headers correctly placed and keep them untouched ? In this link, LarsJ wrote : "A workaround for all these HDN_DIVIDERDBLCLICK issues is to set correct column widths from the start, and then disable column resize through dragging/double-clicking header dividers by adding the HDS_NOSIZING style to the header control" I don't know what LarsJ thinks about the $LVS_EX_HEADERDRAGDROP style when it comes to Virtual ListViews. Maybe he'll tell us. I'll try to test it when I got some time.
    1 point
  18. I formerly learned from a regex master (jchd) that the more accurate is the pattern, the more reliable is the result So it should be [:alpha:] or [A-Z] (as these last 2 letters are always uppercase in the OP's various posts) - with the case insensitivity option if needed Of course \w works, but as you mentioned previously this matches also numbers and underscore which seems improper. If a generic term is allowed, then the dot works too
    1 point
  19. Luke94

    EzMySql error 3

    Check out this and this.
    1 point
  20. Now that’s impressive! Developers can be like electric guitar shredders, producing a dazzling but often ego-driven performance. And everyone wants to be one. Good QA people are like bassists, committed to the groove, listening to the other players. And so hard to find a good one!
    1 point
  21. I dont see a point where you ever exit that function, so I dont see a reason to make it a function at all. Your best friends in this situation are ContinueLoop, ExitLoop, and you can call a function from inside a function so some of your commands or if statements can be part of another function to help break down the logic.
    1 point
  22. Malkey

    autoit calculates date

    This method has more accuracy than a 30 days a month method. #include <Date.au3> Local $sStartDate = "8/4/2021" ; Format is "D/M/YYYY", not US date format. Local $sEndDate = "9/6/2021" ; Format is "D/M/YYYY", not US date format. Local $sStart = _DateConvert($sStartDate, 0) Local $sEnd = _DateConvert($sEndDate, 0) ConsoleWrite("$sStart = " & $sStart & ' in format "YYYY/MM/DD"' & @CRLF) ConsoleWrite("$sEnd = " & $sEnd & ' in format "YYYY/MM/DD"' & @CRLF) Local $iNumMnths = _DateDiff('M', $sStart, $sEnd) ; Number of months between dates. Local $sStartPlusMnths = _DateAdd("M", $iNumMnths, $sStart) ; $sStartDatePlusMnths = Start Date plus number of months between dates. Local $iRemDays = _DateDiff('D', $sStartPlusMnths, $sEnd) ; Number of remaining days. Local $iTotalDays = _DateDiff('D', $sStart, $sEnd) ; Total number of days between dates. ConsoleWrite("(" & $iNumMnths & " month" & ($iNumMnths = 1 ? " " : "s ") & _ $iRemDays & " day" & ($iRemDays = 1 ? ")" : "s)") & " or " & _ $iTotalDays & " days" & @CRLF) ; ============== _DateConvert ================= ; If $US = 1 then format of $Date is in "[M]M/[D]D/YYYY" otherwise, ; If $US = 0 then format of $Date is in "[D]D/[M]M/YYYY" (not US date format) ; The converted Date out has format "YYYY/MM/DD" (for use in _Date...() AutoIt UDFs) ; Func _DateConvert($Date, $US = 1) Local $aTemp = StringSplit($Date, "/") Return StringFormat("%4i/%02i/%02i", $aTemp[3], ($US ? $aTemp[1] : $aTemp[2]), ($US ? $aTemp[2] : $aTemp[1])) EndFunc ;==>_DateConvert #cs ; Returns:- $sStart = 2021/04/08 in format "YYYY/MM/DD" $sEnd = 2021/06/09 in format "YYYY/MM/DD" (2 months 1 day) or 62 days #ce ; Returns:-
    1 point
  23. There is no need to apologize. We are all learners, and always will be. The only difference is, how long someone has been traveling this road . Also using code created by others is not an issue - that' s why this community exists. However, it is always a nice gesture to thank the originator (as you did). You could also use the heart-shaped icon in the lower right corner of a contribution (e.g. the one from @Nine) to leave a reaction. Aside : to the Forum.
    1 point
×
×
  • Create New...