Jump to content

Leaderboard

Popular Content

Showing content with the highest reputation on 03/16/2021 in all areas

  1. zPlayer is the name I used when I introduced the early version of this player in my blog back in early 2009 and, therefore, has nothing to do with the mobile media player of the same name which started marketing in 2015. After I retired from active duty in 2002 I spent much time listening to music. First I started with CD's and LP's, then quickly moved on to mp3 files. I converted many of my CD's to mp3 and I collected many more from various sources which were freely available at the time. As the number of my mp3 files grew, I put them in folders according to their genres and my favorite classifications. I mainly used Windows Media Player to listen to them and I slowly began to dislike wmp because it had massive user interface while I just wanted to listen to music in the background while I was doing other work in the foreground, hopping between folders from time to time. It was the time I was beginning to learn AutoIt and I thought I should make my own player with AutoIt. Coming from a sales career with no experience in programming, it was not an easy task. Somehow, after about 2 years of learning and trying, I had my own audio player which worked with only hotkeys without any graphical interface. I gave it to some of my friends who were not as computer-savvy as I. They liked it but definitely wanted something to clcik with mouse. So I came up with very rude gui which took a form similar to what it is now. The attached source files include one au3 file, one icon file and 14 jpg files. The jpg files are used for drawing a graphical player and are fileinstalled in @DocumentsCommonDir folder. This player uses WMPlayer.OCX as its engine and supports all audio file formats supported by wmp and additional codecs installed. I would like to thank many forum members for kind answers to my questions and would appreciate it if anyone could review the code and give me any suggestion. This player works for me, but I don't know whether the code is presentable as an example. I am posting this here with a hope to learn much from AutoIt community. Edit: August 4, 2020: Video function was added. July 23, 2023: 1. Changed playback engine from IE-embdded WMPlayer.ocx to Winmm.dll. 2. Further reduced main GUI to bare minimum. 3. Eliminated fileinstalls. Media control icon files were replaced with unicode characters Please see Downloads section of this forum for the latest version of this player.
    1 point
  2. OverviewFirst part First part of this example was published March/April 2021 and contains these main sections: Simple implementation of a virtual treeview created from data in a source file Multi-line treeview items and a discussion of an example in the help file Other sections about Item images, Performance tests and Treeview structure Second part Second part of the example has started up in January 2023: Updated all first part examples (item param offset, performance optimizations) Short summary of first part and further development of Real virtual treeviews TreeView posts Other posts and examples regarding treeviews: Saving/reading item levels and texts is the starting point for this example Use of colors and fonts in treeview items through custom draw code Virtual treeviews The basic idea behind implementing both a virtual treeview and a virtual listview is to store as much data as possible in the data source and as little data as possible in the treeview and listview. The purpose is especially to performance optimize creation of the treeview and listview. A virtual listview is created with the LVS_OWNERDATA style. To populate listview items and subitems, you respond to LVN_GETDISPINFO notifications contained in WM_NOTIFY messages. A virtual treeview isn't created based on a particular style of the treeview. A virtual treeview is created by setting LPSTR_TEXTCALLBACK and I_CHILDRENCALLBACK values in the TVITEM structure used to create the treeview items. The LPSTR_TEXTCALLBACK and I_CHILDRENCALLBACK values cause TVN_GETDISPINFO notifications (also contained in WM_NOTIFY messages) to be generated. To populate treeview items and child items, you respond to these TVN_GETDISPINFO notifications. Create treeview from data sourceIn the attempt to implement a virtual treeview, the first step is to create the treeview based on a data source e.g. a simple text file. This post demonstrates how to uniquely store a treeview in a text file and then uniquely restore the same treeview. It's sufficient to store treeview item levels and texts. This is a slightly modified version of TreeView.txt: 0|0 0|1 0|2 1|3 1|This 1|is 2|6 2|a 2|very 2|nice 3|10 3|TreeView 0|, (comma) 1|13 1|indeed. 0|15 And a slightly modified version of the code to recreate the treeview (1) Conventional TreeView.au3) #AutoIt3Wrapper_Au3Check_Parameters=-d -w- 1 -w 2 -w 3 -w 4 -w 5 -w 6 -w 7 #AutoIt3Wrapper_UseX64=Y Opt( "MustDeclareVars", 1 ) #include <GUIConstants.au3> #include <WindowsConstants.au3> #include <GuiTreeView.au3> Global $hTreeView Example() Func Example() ; Create GUI Local $hGui = GUICreate( "Create Conventional TreeView From File", 400, 300, 600, 300, $GUI_SS_DEFAULT_GUI ) ; Create TreeView Local $idTreeView = GUICtrlCreateTreeView( 4, 4, 392, 292, $GUI_SS_DEFAULT_TREEVIEW, $WS_EX_CLIENTEDGE ) $hTreeView = GUICtrlGetHandle( $idTreeView ) ; Read level and text of TreeView items and create TreeView CreateTreeView( FileReadToArray( "TreeView.txt" ) ) ; Show GUI GUISetState( @SW_SHOW, $hGui ) ; Loop While 1 Switch GUIGetMsg() Case $GUI_EVENT_CLOSE ExitLoop EndSwitch WEnd ; Cleanup GUIDelete( $hGui ) EndFunc ; Create conventional TreeView Func CreateTreeView( $aItems ) ; TreeView item information Local $aItem, $hItem ; TreeView level information Local $aLevels[100], $iLevel = 0, $iLevelPrev = 0 ; $aLevels[$iLevel] contains the last item of that level ; Add TreeView root $aItem = StringSplit( $aItems[0], "|", 2 ) $hItem = _GUICtrlTreeView_Add( $hTreeView, 0, $aItem[1] ) $aLevels[$iLevel] = $hItem ; Add TreeView items For $i = 1 To UBound( $aItems ) - 1 $aItem = StringSplit( $aItems[$i], "|", 2 ) $iLevel = $aItem[0] If $iLevel <> $iLevelPrev Then $hItem = $iLevel > $iLevelPrev ? _GUICtrlTreeView_AddChild( $hTreeView, $aLevels[$iLevelPrev], $aItem[1] ) _ ; A child of the previous level : _GUICtrlTreeView_Add( $hTreeView, $aLevels[$iLevel], $aItem[1] ) ; A sibling of the level $iLevelPrev = $iLevel Else ; $iLevel = $iLevelPrev $hItem = _GUICtrlTreeView_Add( $hTreeView, $aLevels[$iLevel], $aItem[1] ) ; A sibling of the level EndIf $aLevels[$iLevel] = $hItem Next ; $aLevels[$iLevel] contains the last item of that level ; Expand all child items _GUICtrlTreeView_Expand( $hTreeView ) EndFunc Reduced and optimized functionIn the CreateTreeView() function at bottom of the code above, the treeview is created using _GUICtrlTreeView_Add() and _GUICtrlTreeView_AddChild() from GuiTreeView.au3. Both of these functions executes __GUICtrlTreeView_AddItem(), which is an internal function. This internal function fills the TVITEM structures where you can set the LPSTR_TEXTCALLBACK and I_CHILDRENCALLBACK values. The second step is to reduce and optimize the code in CreateTreeView() so that the TVITEM structure is filled in directly in this function. This is the reduced and optimized function (2) Optimized TreeView.au3) ; Create TreeView with optimized code Func CreateTreeView( $aItems ) ; TreeView item information Local $aItem ; TreeView level information Local $aLevels[100][2], $iLevel = 0, $iLevelPrev = 0 ; $aLevels[$iLevel][0]/[1] contains the last item/parent of that level ; TreeView text buffer Local $iBuffer, $tBuffer = DllStructCreate( "wchar Text[50]" ), $pBuffer = DllStructGetPtr( $tBuffer ) ; TreeView insert structure Local $tInsert = DllStructCreate( $tagTVINSERTSTRUCT ), $pInsert = DllStructGetPtr( $tInsert ) DllStructSetData( $tInsert, "InsertAfter", $TVI_LAST ) DllStructSetData( $tInsert, "Mask", $TVIF_TEXT ) DllStructSetData( $tInsert, "Text", $pBuffer ) ; Add TreeView root $aItem = StringSplit( $aItems[0], "|", 2 ) $iBuffer = 2 * StringLen( $aItem[1] ) + 2 DllStructSetData( $tBuffer, "Text", $aItem[1] ) DllStructSetData( $tInsert, "TextMax", $iBuffer ) $aLevels[$iLevel][1] = NULL DllStructSetData( $tInsert, "Parent", $aLevels[$iLevel][1] ) $aLevels[$iLevel][0] = GUICtrlSendMsg( $idTreeView, $TVM_INSERTITEMW, 0, $pInsert ) ; Add TreeView items For $i = 1 To UBound( $aItems ) - 1 $aItem = StringSplit( $aItems[$i], "|", 2 ) $iBuffer = 2 * StringLen( $aItem[1] ) + 2 DllStructSetData( $tBuffer, "Text", $aItem[1] ) DllStructSetData( $tInsert, "TextMax", $iBuffer ) $iLevel = $aItem[0] If $iLevel <> $iLevelPrev Then $aLevels[$iLevel][1] = $iLevel > $iLevelPrev ? $aLevels[$iLevelPrev][0] _ ; A child of the previous level : GUICtrlSendMsg( $idTreeView, $TVM_GETNEXTITEM, $TVGN_PARENT, $aLevels[$iLevel][0] ) ; A sibling of the level $iLevelPrev = $iLevel EndIf DllStructSetData( $tInsert, "Parent", $aLevels[$iLevel][1] ) $aLevels[$iLevel][0] = GUICtrlSendMsg( $idTreeView, $TVM_INSERTITEMW, 0, $pInsert ) Next ; $aLevels[$iLevel][0]/[1] contains the last item/parent of that level ; Expand all child items _GUICtrlTreeView_Expand( $hTreeView ) EndFunc Semi-virtual treeviewThe third step is to implement a semi-virtual treeview, where only the tree structure itself but not the item texts are created in CreateTreeView(). Instead of filling in the texts, we set the LPSTR_TEXTCALLBACK value in the TVITEM structure. And then we fill in the texts as needed through a WM_NOTIFY message handler and TVN_GETDISPINFO notifications (3) Semi-Virtual TreeView.au3) ; Create TreeView structure Func CreateTreeView( $aItems ) ; TreeView level information Local $aLevels[100][2], $iLevel = 0, $iLevelPrev = 0 ; $aLevels[$iLevel][0]/[1] contains the last item/parent of that level ; TreeView insert structure Local $tInsert = DllStructCreate( $tagTVINSERTSTRUCT ), $pInsert = DllStructGetPtr( $tInsert ) DllStructSetData( $tInsert, "InsertAfter", $TVI_LAST ) DllStructSetData( $tInsert, "Mask", $TVIF_HANDLE+$TVIF_PARAM+$TVIF_TEXT ) DllStructSetData( $tInsert, "Text", -1 ) ; $LPSTR_TEXTCALLBACK ; Add TreeView root $aLevels[$iLevel][1] = Ptr(0) DllStructSetData( $tInsert, "Param", 0 ) DllStructSetData( $tInsert, "Parent", $aLevels[$iLevel][1] ) $aLevels[$iLevel][0] = GUICtrlSendMsg( $idTreeView, $TVM_INSERTITEMW, 0, $pInsert ) ; Add TreeView items For $i = 1 To UBound( $aItems ) - 1 $iLevel = StringSplit( $aItems[$i], "|", 2 )[0] If $iLevel <> $iLevelPrev Then $aLevels[$iLevel][1] = $iLevel > $iLevelPrev ? $aLevels[$iLevelPrev][0] _ ; A child of the previous level : GUICtrlSendMsg( $idTreeView, $TVM_GETNEXTITEM, $TVGN_PARENT, $aLevels[$iLevel][0] ) ; A sibling of the level $iLevelPrev = $iLevel EndIf DllStructSetData( $tInsert, "Param", $i ) DllStructSetData( $tInsert, "Parent", $aLevels[$iLevel][1] ) $aLevels[$iLevel][0] = GUICtrlSendMsg( $idTreeView, $TVM_INSERTITEMW, 0, $pInsert ) Next ; $aLevels[$iLevel][0]/[1] contains the last item/parent of that level ; Expand all child items _GUICtrlTreeView_Expand( $hTreeView ) EndFunc Func WM_NOTIFY( $hWnd, $iMsg, $wParam, $lParam ) Local $tNMHDR = DllStructCreate( $tagNMHDR, $lParam ) Switch HWnd( DllStructGetData( $tNMHDR, "hWndFrom" ) ) Case $hTreeView Switch DllStructGetData( $tNMHDR, "Code" ) Case $TVN_GETDISPINFOW ; Display TreeView item text Local Static $tBuffer = DllStructCreate( "wchar Text[50]" ), $pBuffer = DllStructGetPtr( $tBuffer ) Local $tDispInfo = DllStructCreate( $tagNMTVDISPINFO, $lParam ), $sText = StringSplit( $aItems[DllStructGetData($tDispInfo,"Param")], "|", 2 )[1] DllStructSetData( $tBuffer, "Text", $sText ) DllStructSetData( $tDispInfo, "Text", $pBuffer ) DllStructSetData( $tDispInfo, "TextMax", 2 * StringLen( $sText ) + 2 ) EndSwitch EndSwitch #forceref $hWnd, $iMsg, $wParam EndFunc Note that this reduces and optimizes the code in CreateTreeView() even more because the buffer for text strings is no longer needed. Instead, the buffer is populated in the WM_NOTIFY message handler. This technique has the great advantage that only visible treeview items are filled with text strings. Because item texts are only filled in when the items are visible in the treeview, it's necessary to establish a connection between the treeview items and the data source that contains the texts. The data source, which is a simple text file, is loaded into an array. The connection between a treeview item and the data source is the index in this array. Therefore, the array index is stored in the Param field of the TVITEM structure. Virtual treeviewTo make the treeview completely virtual, the fourth and final step is to create and display child items only when required. That is, when an end user clicks the expand button to the left of a treeview item that actually contains child items. And only direct children of this item will be created. If an end user doesn't click an expand button (because these child items are not the ones he's looking for), the child items in question will not be created in the tree structure at all. To make the treeview completely virtual only first level (level-0) items are created in CreateTreeView(). Instead of creating child items, we set the I_CHILDRENCALLBACK value in the TVITEM structure. And then we create child items as needed through a WM_NOTIFY message handler and TVN_GETDISPINFO and TVN_ITEMEXPANDING notifications (4) Virtual TreeView.au3) ; Create TreeView structure Func CreateTreeView( $aLevel0 ) ; TreeView insert structure Local $tInsert = DllStructCreate( $tagTVINSERTSTRUCT ), $pInsert = DllStructGetPtr( $tInsert ) DllStructSetData( $tInsert, "InsertAfter", $TVI_LAST ) DllStructSetData( $tInsert, "Mask", $TVIF_CHILDREN+$TVIF_HANDLE+$TVIF_PARAM+$TVIF_TEXT ) DllStructSetData( $tInsert, "Parent", NULL ) DllStructSetData( $tInsert, "Children", -1 ) ; $I_CHILDRENCALLBACK DllStructSetData( $tInsert, "Text", -1 ) ; $LPSTR_TEXTCALLBACK ; Add TreeView items For $i = 0 To UBound( $aLevel0 ) - 1 DllStructSetData( $tInsert, "Param", $aLevel0[$i] ) GUICtrlSendMsg( $idTreeView, $TVM_INSERTITEMW, 0, $pInsert ) Next EndFunc Func WM_NOTIFY( $hWnd, $iMsg, $wParam, $lParam ) Local $tNMHDR = DllStructCreate( $tagNMHDR, $lParam ) Switch HWnd( DllStructGetData( $tNMHDR, "hWndFrom" ) ) Case $hTreeView Switch DllStructGetData( $tNMHDR, "Code" ) Case $TVN_GETDISPINFOW ; Display TreeView item text Local Static $tBuffer = DllStructCreate( "wchar Text[50]" ), $pBuffer = DllStructGetPtr( $tBuffer ) Local $tDispInfo = DllStructCreate( $tagNMTVDISPINFO, $lParam ), $iIndex = DllStructGetData( $tDispInfo, "Param" ), $sText = StringSplit( $aItems[$iIndex], "|", 2 )[3] DllStructSetData( $tBuffer, "Text", $sText ) DllStructSetData( $tDispInfo, "Text", $pBuffer ) DllStructSetData( $tDispInfo, "TextMax", 2 * StringLen( $sText ) + 2 ) DllStructSetData( $tDispInfo, "Children", StringSplit( $aItems[$iIndex], "|", 2 )[1] = 0 ? 0 : 1 ) Case $TVN_ITEMEXPANDINGW ; Create TreeView structure for childs Local $tTreeView = DllStructCreate( $tagNMTREEVIEW, $lParam ) If BitAND( DllStructGetData( $tTreeView, "Action" ), $TVE_EXPAND ) <> $TVE_EXPAND _ Or Int( StringSplit( $aItems[DllStructGetData($tTreeView,"NewParam")], "|", 2 )[2] ) Then Return ; TreeView insert structure Local $tInsert = DllStructCreate( $tagTVINSERTSTRUCT ), $pInsert = DllStructGetPtr( $tInsert ) DllStructSetData( $tInsert, "InsertAfter", $TVI_LAST ) DllStructSetData( $tInsert, "Mask", $TVIF_CHILDREN+$TVIF_HANDLE+$TVIF_PARAM+$TVIF_TEXT ) DllStructSetData( $tInsert, "Parent", DllStructGetData( $tTreeView, "NewhItem" ) ) DllStructSetData( $tInsert, "Children", -1 ) ; $I_CHILDRENCALLBACK DllStructSetData( $tInsert, "Text", -1 ) ; $LPSTR_TEXTCALLBACK ; Add TreeView children Local $iNewIndex = DllStructGetData( $tTreeView, "NewParam" ) + 1 For $i = 0 To StringSplit( $aItems[$iNewIndex-1], "|", 2 )[1] - 1 DllStructSetData( $tInsert, "Param", $iNewIndex + $i ) GUICtrlSendMsg( $idTreeView, $TVM_INSERTITEMW, 0, $pInsert ) Next ; Indicate that children have been added $aItems[$iNewIndex-1] = StringReplace( $aItems[$iNewIndex-1], 7, "1" ) EndSwitch EndSwitch #forceref $hWnd, $iMsg, $wParam EndFunc Creating only first level (level-0) items in CreateTreeView() is the crucial step that truly optimizes creation of the treeview. CreateTreeView() in this version is very simple and fast. $aLevel0 is an index of first level (level-0) items. To handle TVN_GETDISPINFO and TVN_ITEMEXPANDING notifications regarding child items, more information is needed in the source file (TreeView-4.txt) 0|000|0|0 0|000|0|1 0|003|0|2 1|000|0|3 1|000|0|This 1|004|0|is 2|000|0|6 2|000|0|a 2|000|0|very 2|002|0|nice 3|000|0|10 3|000|0|TreeView 0|002|0|, (comma) 1|000|0|13 1|000|0|indeed. 0|000|0|15 It's the number of child items in the second field, and a flag to indicate whether child items have already been created in the third field. At top of the TVN_ITEMEXPANDING code section, it's checked if a treeview item with child items is expanded or collapsed and if these child items are already created: Case $TVN_ITEMEXPANDINGW ; Create TreeView structure for childs Local $tTreeView = DllStructCreate( $tagNMTREEVIEW, $lParam ) If BitAND( DllStructGetData( $tTreeView, "Action" ), $TVE_EXPAND ) <> $TVE_EXPAND _ Or Int( StringSplit( $aItems[DllStructGetData($tTreeView,"NewParam")], "|", 2 )[2] ) Then Return The rest of the code in the TVN_ITEMEXPANDING section creates the child items. This code is again very simple and fast. 100,000 items5) 100,000 Items.au3 creates a virtual treeview with 100,000 items based on the 100,000.txt source file. Of course, creating the treeview is lightning fast. 7z-fileThe 7z-file contains source code for UDFs and examples. You need AutoIt 3.3.12 or later. Tested on Windows 7 and Windows 10. Comments are welcome. Let me know if there are any issues. VirtualTreeView.7z
    1 point
  3. Incremental search is usually implemented by drawing the background of the substrings that matches the search string with a specific color eg. yellow. Incremental in this context means that the search is performed dynamically after each character while the search string is typed. In a listview this can be implemented by owner drawing through the LVS_OWNERDRAWFIXED flag and WM_DRAWITEM messages. (A custom drawn listview supports coloring of fields. However, the coloring works best for whole fields. This doesn't make it applicable to incremental search.) Inspiration for the example is found in these two questions: Search box for names and Search In ListView (Redraw with matching string). Examples The zip file below contains three examples. Listview items are strings of random characters with different lengths. In all examples a global $iItems = 1000 in top of script specifies the number of rows. There are no performance issues up till 10,000 rows. Note that the search is performed in an array and not directly in the listview. A regular expression can be entered in the search box. Search strings like "m........." with a varying number of dots will result in a varying number of matches. To keep it simple only one occurrence of the search string in each item is tested. As soon as one occurrence is found the search loop moves on to next item. 1) Incremental text search.au3 The first example is a simple demonstration of basic functionality: F3 and Shift+F3 can be used instead of Next and Prev buttons. 2) Show matching rows only.au3 An owner drawn listview can easily be combined with a virtual listview to extend the functionality of the incremental search. A virtual listview is especially interesting if you want to dynamically update the listview to only display the rows that matches the search string. Such an update is very fast in a virtual listview. This example is useful if the listview contains a set of file names and you are searching for a specific file eg. to open the file. In this situation you are probably not interested in the files that doesn't match. Because the listview only contains matching rows "Next match" and "Prev match" buttons are disabled. Clear the search field to display all items. 3) Standard search dialog.au3 The last example is a demonstration of a standard search dialog as the search box in Notepad. FindText function in comdlg32.dll creates the standard search box. The function is implemented as _WinAPI_FindTextDlg in WinAPIDlg.au3. In the Microsoft documentation you can read: Note that the FINDREPLACE structure and the buffer for the search string should be a global or static variable so it does not go out of scope before the dialog box closes. Because the FINDREPLACE structure is created as a local variable in _WinAPI_FindTextDlg it goes out of scope as soon as the function returns. This implementation of FindText is used in the example: ;Func _WinAPI_FindTextDlg($hOwner, $sFindWhat = '', $iFlags = 0, $pFindProc = 0, $lParam = 0) Func _WinAPI_FindTextDlgEx(ByRef $tFR, $hOwner, $sFindWhat = '', $iFlags = 0, $pFindProc = 0, $lParam = 0) $__g_pFRBuffer = __HeapReAlloc($__g_pFRBuffer, 2 * $__g_iFRBufferSize) If @error Then Return SetError(@error + 20, @extended, 0) DllStructSetData(DllStructCreate('wchar[' & $__g_iFRBufferSize & ']', $__g_pFRBuffer), 1, StringLeft($sFindWhat, $__g_iFRBufferSize - 1)) ;Local $tFR = DllStructCreate($tagFINDREPLACE) $tFR = DllStructCreate($tagFINDREPLACE) DllStructSetData($tFR, 'Size', DllStructGetSize($tFR)) DllStructSetData($tFR, 'hOwner', $hOwner) DllStructSetData($tFR, 'hInstance', 0) DllStructSetData($tFR, 'Flags', $iFlags) DllStructSetData($tFR, 'FindWhat', $__g_pFRBuffer) DllStructSetData($tFR, 'ReplaceWith', 0) DllStructSetData($tFR, 'FindWhatLen', $__g_iFRBufferSize * 2) DllStructSetData($tFR, 'ReplaceWithLen', 0) DllStructSetData($tFR, 'lParam', $lParam) DllStructSetData($tFR, 'Hook', $pFindProc) DllStructSetData($tFR, 'TemplateName', 0) Local $Ret = DllCall('comdlg32.dll', 'hwnd', 'FindTextW', 'struct*', $tFR) If @error Or Not $Ret[0] Then Local $Error = @error + 30 __HeapFree($__g_pFRBuffer) If IsArray($Ret) Then Return SetError(10, _WinAPI_CommDlgExtendedErrorEx(), 0) Else Return SetError($Error, @extended, 0) EndIf EndIf Return $Ret[0] EndFunc Then it's ensured that the local variable that is used for $tFR in the script, does not go out of scope, while the search box is open. ListviewIncrSearch.7z 1) Incremental text search.au3 2) Show matching rows only.au3 3) Standard Find text dialog.au3 DrawItem.au3 GuiListViewEx.au3 WinAPIDlgEx.au3 You need AutoIt 3.3.14 or later. Tested on Windows 7 32/64 bit and Windows XP 32 bit. Comments are welcome. Let me know if there are any issues. (Set tab width = 2 in SciTE to line up comments by column.) ListviewIncrSearch.7z
    1 point
  4. CognitiveReasoning, Welcome to the AutoIt forums. That sounds like a very interesting and worthwhile project. I have little experience with image recognition in AutoIt, but there certainly are a number of libraries available to do that - although there seems to be a varying degree of success with all of them. However, if you are creating a single composite image from a number of separate images, it would not be difficult to determine which of the images was under the cursor at any time, nor which had been clicked upon. Given that you would already know which image was which, would that be sufficient to allow you to do what you require? Rather then being too verbose, I think you need to explain in a little more detail what you envisage happening once you have this composite image - then we can offer suggestions as to how you might go about both generating it and reacting to user interaction with it. M23
    1 point
  5. All is well with this new release, from my point of view.
    1 point
  6. Just uploaded the "Final" release candidate v21.316.1639.0 which will be move to production when there aren't any real issues in it. For those that downloaded the AV fixed installer uploaded yesterday evening: Make sure you reinstall with this one as that version created a wrong "SCITE_USERHOME" environment settings as the new NSIS used the "%ProgramData%" variable in stead of the "%LocalAppData%" variable!
    1 point
  7. I would very strongly suggest that you put error handling after each statement, so you can know if there is something not working as expected....
    1 point
  8. You can't delete a file that is currently open, and you aren't closing it correctly. Try this -- $path=@AppDataDir & "\etc\Isproblem.txt" $hFile = FileOpen($path) FileClose($hFile) ;some code here FileDelete($path) ;some code here _FileCreate($path) P.S. Welcome to the forum!
    1 point
  9. Thanks I include it in the doc Cheers
    1 point
  10. there is no example for _WinAPI_GetParentProcess() or for _WinAPI_GetProcessName(). So maybe this would be a good one: #include <Debug.au3> #include <WinAPIProc.au3> _DebugArrayDisplay(_GetParentProcessTree(), "_GetParentProcessTree", "", 0, Default, "PID|Name|CommandLine") Func _GetParentProcessTree($iPID = @AutoItPID) Local $n, $iParentPID = $iPID, $aList[100][3] $aList[0][0] = $iPID $aList[0][1] = _WinAPI_GetProcessName($iPID) $aList[0][2] = _WinAPI_GetProcessCommandLine($iPID) For $n = 1 To 99 $iParentPID = _WinAPI_GetParentProcess($iParentPID) If $iParentPID = 0 Then ExitLoop $aList[$n][0] = $iParentPID $aList[$n][1] = _WinAPI_GetProcessName($iParentPID) $aList[$n][2] = _WinAPI_GetProcessCommandLine($iParentPID) Next ReDim $aList[$n][3] Return $aList EndFunc ;==>_GetParentProcessTree
    1 point
  11. Your solution is great and simpler too, because it will interfere much less with other applications. If you do that, then you will "free" Ctrl+Arrows for all your users who need Ctrl+Arrows in their other windows apps, while listening to music in zPlayer. Ctrl+Arrows are often required in Apps, much more than Ctrl+Alt+Arrows. So I think your idea is fine, please revert to the 4 Ctrl+Alt+Arrows instead of Ctrl+Arrows whenever you can, especially your patch will only take a few seconds to be active : HotKeySet("^!{RIGHT}", "MyNext") ; play next file HotKeySet("^!{LEFT}", "MyPrevious") ; play previous file HotKeySet("^!{UP}", "VolumeUp") ; increase system volume level HotKeySet("^!{DOWN}", "VolumeDown") ; decrease system volume level instead of the actual HotKeySet("^{RIGHT}", "MyNext") ; play next file HotKeySet("^{LEFT}", "MyPrevious") ; play previous file HotKeySet("^{UP}", "VolumeUp") ; increase system volume level HotKeySet("^{DOWN}", "VolumeDown") ; decrease system volume level Not forgetting the 4 labels in main menu and elsewhere if required, for example : Global $label1a = GUICtrlCreateLabel("Ctrl+Alt+Right Arrow", ... Global $label2a = GUICtrlCreateLabel("Ctrl+Alt+Left Arrow", ... Global $label3a = GUICtrlCreateLabel("Ctrl+Alt+Up Arrow", ... Global $label4a = GUICtrlCreateLabel("Ctrl+Alt+Down Arrow", ... ... Func MyNext() ; Ctrl+Alt+Right Arrow to play the next file Func MyPrevious() ; Ctrl+Alt+Left Arrow to play the previous file Func VolumeUp() ; Ctrl+Alt+Up arrow Func VolumeDown() ; Ctrl+Alt+Down arrow Also your solution will harmonize your hotkeys, which will all need Ctrl+Alt+key to be triggered. Well done CYCho... I just patched my version of zPlayer Edit: I had to modify one line in the script ( Global $menuWidth = 150 ) because 2 labels were cropped on my computer (probably not same fonts). Modifying it from 150 to 154 solved it (153 wasn't enough) . In case someone else got the same minor issue... ; Global $menuWidth = 150 ; original line Global $menuWidth = 154 ; 150 to 153 not enough for me (2 labels were cropped) What I like is that all labels in the pic above are clickable (both columns) : you don't have to remember what combination of keys to type, a click will be enough when main gui is visible
    1 point
  12. > My example takes care of all the scenarios, including IF YOU ARE RUNNING IN SCITE OR NOT! Not what I asked. >> How to tell when being run from SciTE? IDGAF whether it was what you asked or not! If you took the time to understand the script and read the help file, you would see that your question was answered in my example script. I'm out!
    1 point
  13. @pixelsearch, Thanks a lot. As I said in my first post, this was conceived to run with hotkeys only, because I didn't like the overwhelming guis offered by existing players. Now it is clad with some guis, but I would like to keep it runnable with with all the windows hidden, except for video window for an obvious reason. I believe persons like Xandy can tweak my code to suit their particular environment. Initially, all my hotkeys, including those combined with arrows, had Ctrl+Alt. But my first Windows 10 used Ctrl+Alt+Arrows to change screen orientation, so I changed them to Ctrl+Arrows. Now that Windows 10 does not seem to use them any more, I can go back to Ctrl+Alt+Arrows.
    1 point
  14. That’s him begging nicely lol He was spoiled and once he even grabbed a sandwich out of my hands and ate the rest of it He was loved very much
    1 point
  15. Thanks. My son’s first dog. He took that picture years ago with his phone. He was a great little cockapoo.
    1 point
  16. He looks afraid of something
    1 point
  17. Earthshine

    Oracle SQL db queries

    First get one that works. Then learn how to construct the string programmatically i can’t be arsed to do it for you just because you don’t feel like doing development. You need to learn and nobody has your Oracle instance installed either
    1 point
  18. _Excel_RangeFind returns a 2D array holding all found cells (from top to bottom) meeting the search criteria. Just process the returned array from bottom to top
    1 point
  19. One way : #include <Excel.au3> Local $oExcel = _Excel_Open() Local $oWorkbook = _Excel_BookOpen($oExcel, @ScriptDir & "\Test.xls") ;get last row Local $LastRow = $oWorkbook.ActiveSheet.Range("H1").SpecialCells($xlCellTypeLastCell).Row Local $sSearchrange = "H1:H" & $LastRow Local $aResult = _Excel_RangeRead($oWorkbook, Default, $sSearchrange) Local $aList = _ArrayFindAll($aResult, 45) MsgBox ($MB_SYSTEMMODAL, "Last found in", $aList[UBound($aList)-1]+1)
    1 point
  20. It doesn't seem to work on Win7. The tooltip appears normal for a fraction of a sec, and then disappears. That is what I was experimenting in my first attempts. @pixelsearch There is a way to reduce delay of WinWait : Opt("WinWaitDelay", 10) Or in case anyone would be interested...
    1 point
  21. Sorry to hear you have lost 8 fingers...
    1 point
  22. Here is an example of search in several columns: #AutoIt3Wrapper_Au3Check_Parameters=-d -w 1 -w 2 -w 3 -w 4 -w 5 -w 6 -w 7 #AutoIt3Wrapper_UseX64=y Opt( "MustDeclareVars", 1 ) #include <WindowsConstants.au3> #include <GUIConstants.au3> #include <Array.au3> #include "DrawItem.au3" #include "GuiListViewEx.au3" Global Const $tagMSG = "hwnd hwnd;uint message;wparam wParam;lparam lParam;dword time;int X;int Y" Global $hGui, $idListView, $hListView, $fListViewHasFocus = 0, $iItems = 1000, $iCols = 4, $iCol = 0, $aItems[$iItems][$iCols] Global $idSearch, $hSearch, $idSearchAction, $aSearch[$iItems], $iSearch = 0, $sSearch = "" Example() Func Example() ; Create GUI $hGui = GUICreate( "Show matching rows only - multiple columns", 1060, 330 ) ; Create search group GUICtrlCreateGroup( "Search", 10, 5, 1060-20, 120 ) ; Create Checkbox Local $idRegExp = GUICtrlCreateCheckbox( "Use regular expression as search string", 20, 25, 260, 20 ) GUICtrlSetState( $idRegExp, $GUI_CHECKED ) ; Create Edit control $idSearch = GUICtrlCreateEdit( "", 20, 55, 200, 20, $GUI_SS_DEFAULT_EDIT-$ES_AUTOVSCROLL-$WS_HSCROLL-$WS_VSCROLL ) GUICtrlSetData( $idSearch, "Enter search string - possibly as reg. exp." ) $hSearch = GUICtrlGetHandle( $idSearch ) $idSearchAction = GUICtrlCreateDummy() ; Create read only Edit control for number of matches Local $idCount = GUICtrlCreateEdit( "0", 230, 55, 50, 20, $GUI_SS_DEFAULT_EDIT+$ES_READONLY+$ES_RIGHT-$WS_HSCROLL-$WS_VSCROLL ) GUICtrlSetBkColor( $idCount, 0xFFFFFF ) ; Create Buttons Local $idNext = GUICtrlCreateButton( "Next match", 20, 85, 125, 25 ) Local $idPrev = GUICtrlCreateButton( "Prev match", 155, 85, 125, 25 ) GUICtrlSetState( $idNext, $GUI_DISABLE ) GUICtrlSetState( $idPrev, $GUI_DISABLE ) ; Search column Local $idComboBox = GUICtrlCreateCombo( "Search column 0", 350, 25, 200, 20 ) GUICtrlSetData( $idComboBox, "Search column 1|Search column 2|Search column 3" ) ; Close group GUICtrlCreateGroup( "", -99, -99, 1, 1 ) ; Create ListView $idListView = GUICtrlCreateListView( "", 10, 140, 1060-20, 180, $GUI_SS_DEFAULT_LISTVIEW+$LVS_OWNERDATA+$LVS_OWNERDRAWFIXED, $WS_EX_CLIENTEDGE+$LVS_EX_DOUBLEBUFFER ) $hListView = GUICtrlGetHandle( $idListView ) ; Virtual Owner drawn Reduces flicker _GUICtrlListView_AddColumn( $hListView, "Column 0", 250 ) _GUICtrlListView_AddColumn( $hListView, "Column 1", 250 ) _GUICtrlListView_AddColumn( $hListView, "Column 2", 250 ) _GUICtrlListView_AddColumn( $hListView, "Column 3", 250 ) ; Fill array FillArray( $aItems ) _ArraySort( $aItems, 0, 0, 0, $iCol ) ; $iCol is the search column ; Set search array to display all items For $i = 0 To $iItems - 1 $aSearch[$i] = $i Next $iSearch = $iItems ; Initialize ListView GUICtrlSendMsg( $idListView, $LVM_SETITEMCOUNT, $iSearch, 0 ) ; Adjust height of GUI and ListView to fit 15 rows Local $iLvHeight = _GUICtrlListView_GetHeightToFitRows( $hListView, 15 ) WinMove( $hGui, "", Default, Default, Default, WinGetPos( $hGui )[3] - WinGetClientSize( $hGui )[1] + $iLvHeight + 150 ) WinMove( $hListView, "", Default, Default, Default, $iLvHeight ) ; Register WM_ACTIVATE message handler ; To check when GUI receives/loses focus GUIRegisterMsg( $WM_ACTIVATE, "WM_ACTIVATE" ) ; Register WM_COMMAND message handler ; To read search string from Edit control while it's typed in GUIRegisterMsg( $WM_COMMAND, "WM_COMMAND" ) ; Register WM_DRAWITEM message handler ; To display items in an owner drawn ListView GUIRegisterMsg( $WM_DRAWITEM, "WM_DRAWITEM" ) ; Register message handler to test ListView focus Local $hMessageHandler = DllCallbackRegister( "MessageHandler", "long", "int;wparam;lparam" ) Local $hMessageHook = _WinAPI_SetWindowsHookEx( $WH_MSGFILTER, DllCallbackGetPtr( $hMessageHandler ), 0, _WinAPI_GetCurrentThreadId() ) ; Show GUI GUISetState( @SW_SHOW ) ; Message loop While 1 Switch GUIGetMsg() Case $idSearchAction, $idRegExp $sSearch = GUICtrlRead( $idSearch ) If $sSearch = "" Then ; Empty search string, display all items For $i = 0 To $iItems - 1 $aSearch[$i] = $i Next $iSearch = $iItems GUICtrlSetData( $idCount, 0 ) Else ; Find rows matching search string $iSearch = 0 If GUICtrlRead( $idRegExp ) = $GUI_CHECKED Then For $i = 0 To $iItems - 1 If StringRegExp( $aItems[$i][$iCol], $sSearch ) Then ; Reg. exp. search $aSearch[$iSearch] = $i $iSearch += 1 EndIf Next Else For $i = 0 To $iItems - 1 If StringInStr( $aItems[$i][$iCol], $sSearch ) Then ; Normal search $aSearch[$iSearch] = $i $iSearch += 1 EndIf Next EndIf GUICtrlSetData( $idCount, $iSearch ) EndIf GUICtrlSendMsg( $idListView, $LVM_SETITEMCOUNT, $iSearch, 0 ) Case $idComboBox ; New search column $iCol = Int( StringRight( GUICtrlRead( $idComboBox ), 1 ) ) _ArraySort( $aItems, 0, 0, 0, $iCol ) GUICtrlSetData( $idSearch, "" ) GUICtrlSendToDummy( $idSearchAction ) Case $GUI_EVENT_CLOSE ExitLoop EndSwitch WEnd ; Cleanup _WinAPI_UnhookWindowsHookEx( $hMessageHook ) GUIDelete() EndFunc ; Check when GUI receives/loses focus Func WM_ACTIVATE( $hWnd, $iMsg, $wParam, $lParam ) #forceref $iMsg, $lParam If $hWnd = $hGui Then _ $fListViewHasFocus += BitAND( $wParam, 0xFFFF ) ? 1 : -1 Return $GUI_RUNDEFMSG EndFunc ; Read search string from Edit control while it's typed in Func WM_COMMAND( $hWnd, $iMsg, $wParam, $lParam ) #forceref $hWnd, $iMsg Local Static $bEditClear = True Local $hWndFrom = $lParam Local $iCode = BitShift( $wParam, 16 ) ; High word Switch $hWndFrom Case $hSearch Switch $iCode Case $EN_CHANGE GUICtrlSendToDummy( $idSearchAction ) Case $EN_SETFOCUS If $bEditClear Then GUICtrlSetData( $idSearch, "" ) $bEditClear = False EndIf EndSwitch EndSwitch Return $GUI_RUNDEFMSG EndFunc ; Display items in an owner drawn ListView Func WM_DRAWITEM( $hWnd, $iMsg, $wParam, $lParam ) Local Static $tRect = DllStructCreate( $tagRECT ), $pRect = DllStructGetPtr( $tRect ), $tSize = DllStructCreate( $tagSIZE ) Local Static $hBrushYellow = _WinAPI_CreateSolidBrush( 0x00FFFF ), $hBrushCyan = _WinAPI_CreateSolidBrush( 0xFFFF00 ) ; Yellow and cyan, BGR Local Static $hBrushHighLight = _WinAPI_GetSysColorBrush( $COLOR_HIGHLIGHT ), $hBrushButtonFace = _WinAPI_GetSysColorBrush( $COLOR_BTNFACE ) ; We can optimize code by removing Switch statements because the ListView is the only ownerdrawn control and only $ODA_DRAWENTIRE actions are present 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 $iCols - 1 ; Subitem rectangle DllStructSetData( $tRect, 2, $i ) ; Top DllStructSetData( $tRect, 1, $LVIR_BOUNDS ) ; Left GUICtrlSendMsg( $idListView, $LVM_GETSUBITEMRECT, $itemID, $pRect ) DllStructSetData( $tRect, 1, DllStructGetData( $tRect, 1 ) + 6 ) ; Left margin DllStructSetData( $tRect, 2, DllStructGetData( $tRect, 2 ) + 2 ) ; Top margin ; Subitem background and text color If BitAND( $iState, $ODS_SELECTED ) Then _ DllCall( "user32.dll", "int", "FillRect", "handle", $hDC, "struct*", $tRect, "handle", $fListViewHasFocus = 1 ? $hBrushHighLight : $hBrushButtonFace ) ; _WinAPI_FillRect DllCall( "gdi32.dll", "int", "SetTextColor", "handle", $hDC, "int", BitAND( $iState, $ODS_SELECTED ) ? $fListViewHasFocus = 1 ? 0xFFFFFF : 0x000000 : 0x000000 ) ; _WinAPI_SetTextColor ; Draw subitem text $sItemText = $aItems[$aSearch[$itemID]][$i] DllCall( "user32.dll", "int", "DrawTextW", "handle", $hDC, "wstr", $sItemText, "int", StringLen( $sItemText ), "struct*", $tRect, "uint", 0 ) ; _WinAPI_DrawText ; $i is column index ; $iCol is the search column ; Mark matching substring only if column index = search column If $i <> $iCol Then ContinueLoop ; Matching substring? If $sSearch Then Local $sMatch = StringRegExp( $sItemText, $sSearch, 1 ), $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 DllCall( "user32.dll", "int", "FillRect", "handle", $hDC, "struct*", $tRect, "handle", BitAND( $iState, $ODS_SELECTED ) ? $hBrushCyan : $hBrushYellow ) ; _WinAPI_FillRect ; Draw matching substring in rectangle 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 Next Return $GUI_RUNDEFMSG #forceref $hWnd, $iMsg, $wParam EndFunc ; Message handler to test ListView focus Func MessageHandler( $nCode, $wParam, $lParam ) #forceref $nCode, $wParam Local $tMsg = DllStructCreate( $tagMSG, $lParam ), $iMsg = DllStructGetData( $tMsg, "message" ) If $iMsg = $WM_LBUTTONDOWN Or $iMsg = $WM_RBUTTONDOWN Then $fListViewHasFocus = DllStructGetData( $tMsg, "hwnd" ) = $hListView ? 1 : 0 EndFunc ; Fill array with random strings Func FillArray( ByRef $aItems ) Local $aLetters[26] = [ 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', _ 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z' ], $s For $i = 0 To $iCols - 1 For $j = 0 To $iItems - 1 $s = $aLetters[Random(0,25,1)] For $k = 1 To Random(10,30,1) $s &= $aLetters[Random(0,25,1)] Next $aItems[$j][$i] = $s Next Next EndFunc 2.2) Show matching rows only - multiple columns.au3 The include files in the zip in first post are needed.
    1 point
×
×
  • Create New...