Leaderboard
Popular Content
Showing content with the highest reputation on 01/23/2020 in all areas
-
CryptoNG UDF - Cryptography API: Next Gen
Network_Guy and one other reacted to TheXman for a topic
You're welcome. Currently, the UDF library only implements the following Cryptographic Primitives: Hashing (i.e. SHA/MD5/PBKDF2) Symmetric Encryption (i.e. RC4/DES/3DES/AES) I will certainly add your request to extend the library's functionality to have the ability to do Asymmetric (public key) Encryption, using RSA, to the UDF library's To Do list.2 points -
CryptoNG UDF - Cryptography API: Next Generation
Stormgrade reacted to TheXman for a file
Version v2.2.0
1,424 downloads
Encryption / Decryption / Hashing / Signing Purpose Cryptography API: Next Generation (CNG) is Microsoft's long-term replacement for their CryptoAPI. Microsoft's CNG is designed to be extensible at many levels and cryptography agnostic in behavior. Although the Crypt.au3 UDF lib that is installed with AutoIt3 still works well, the advapi32.dll functions that it uses have been deprecated. In addition the Crypt.au3 UDF lib, as it is currently written, has a very limited ability to decrypt AES data that was not encrypted using Crypt.au3 functions. That is because Crypt.au3 functions do not allow you to specify an actual key or initialization vector (IV). It only lets you specify data to be used to derive a key and uses a static IV. This UDF was created to offer a replacement for the deprecated functions used by Crypt.au3. According to Microsoft, deprecated functions may be removed in future release. It was also created to allow more flexibility and functionality in encryption/decryption/hashing/signing and to expand the ability for users to implement cryptography in their scripts. Description This UDF implements some of Microsoft's Cryptography API: Next Generation (CNG) Win32 API functions. It implements functions to encrypt/decrypt text and files, generate hashes, derive keys using Password-Based Key Derivation Function 2 (PBKDF2), create and verify signatures, and has several cryptography-related helper functions. The UDF can implement any encryption/decryption algorithms and hashing algorithms that are supported by the installed cryptography providers on the PC in which it is running. Most, if not all, of the "magic number" values that you would commonly use to specify that desired algorithms, key bit lengths, and other magic number type values, are already defined as constants or enums in the UDF file. To flatten the learning curve, there is an example file that shows examples of all of the major functionality. This example file is not created to be an exhaustive set of how to implement each feature and parameter. It is designed to give you a template or guide to help you hit the ground running in terms of using the functions. I have tried to fully document the headers of all of the functions as well as the code within the functions themselves. As of v1.4.0, there is also a Help file that includes all of the functions, with examples. Current UDF Functions Algorithm-Specific Symmetric Encryption/Decryption Functions _CryptoNG_AES_CBC_EncryptData _CryptoNG_AES_CBC_DecryptData _CryptoNG_AES_CBC_EncryptFile _CryptoNG_AES_CBC_DecryptFile _CryptoNG_AES_ECB_EncryptData _CryptoNG_AES_ECB_DecryptData _CryptoNG_AES_GCM_EncryptData _CryptoNG_AES_GCM_DecryptData _CryptoNG_3DES_CBC_EncryptData _CryptoNG_3DES_CBC_DecryptData _CryptoNG_3DES_CBC_EncryptFile _CryptoNG_3DES_CBC_DecryptFile Generic Symmetric Encryption/Decryption Functions _CryptoNG_EncryptData _CryptoNG_DecryptData _CryptoNG_EncryptFile _CryptoNG_DecryptFile Hashing Functions _CryptoNG_HashData _CryptoNG_HashFile _CryptoNG_PBKDF2 Asymmetric (Public/Private Key) Cryptography Functions _CryptoNG_ECDSA_CreateKeyPair _CryptoNG_ECDSA_SignHash _CryptoNG_ECDSA_VerifySignature _CryptoNG_RSA_CreateKeyPair _CryptoNG_RSA_EncryptData _CryptoNG_RSA_DecryptData _CryptoNG_RSA_SignHash _CryptoNG_RSA_VerifySignature Misc / Helper Functions _CryptoNG_CryptBinaryToString _CryptoNG_CryptStringToBinary _CryptoNG_GenerateRandom _CryptoNG_EnumAlgorithms _CryptoNG_EnumRegisteredProviders _CryptoNG_EnumKeyStorageProviders _CryptoNG_LastErrorMessage _CryptoNG_Version Related Links Cryptography API: Next Generation - Main Page Cryptography API: Next Generation - Reference Cryptography API: Next Generation - Primitives Cryptography API: Next Generation - Cryptographic Algorithm Providers1 point -
Multi-line items in custom drawn ListView
pixelsearch reacted to LarsJ for a topic
Items in a standard listview in details/report view (this example deals only with listviews in details/report view) can display a single line of text. There seems not to be any options to change this. There is no word wrap option. If you search the forums, it's possible to find examples of listviews with multiple lines of text in each row. The multi-line items are implemented as owner drawn items through LVS_OWNERDRAWFIXED control style and WM_DRAWITEM messages. A problem with the owner drawn technique is that you are forced to draw everything yourself. Besides item texts and the background behind texts (white for non-selected items, dark blue for selected items with focus, button face for selected items without focus) you also have to draw checkboxes, images, icons and the background behind these elements yourself. Another technique is custom drawn listview items. Custom drawn items are implemented through NM_CUSTOMDRAW notifications included in WM_NOTIFY messages. NM_CUSTOMDRAW notifications are generated automatically by the code in ComCtl32.dll when the listview is updated. Implementing custom drawn items is a matter of responding to these messages or not. The great advantage of custom drawn items is that the drawing process is divided into several stages. For a listview up to six different stages. Some of these stages can be used for default drawing without any additional code at all. Other stages can be used for custom drawing with your own code. Multi-line text items fits perfectly with the custom drawn technique. Item texts and the background is drawn by custom code. Checkboxes, images, icons and the background is drawn by default code. Increase height of listview items The usual way to increase the height of listview items is to respond to WM_MEASUREITEM messages. But this method can only be used for owner drawn listviews. In a custom drawn listview the height can be increased by defining a text font with a suitable height: Func _GUICtrlListView_SetItemHeightByFont( $hListView, $iHeight ) ; Get font of ListView control ; Copied from _GUICtrlGetFont example by KaFu ; See https://www.autoitscript.com/forum/index.php?showtopic=124526 Local $hDC = _WinAPI_GetDC( $hListView ), $hFont = _SendMessage( $hListView, $WM_GETFONT ) Local $hObject = _WinAPI_SelectObject( $hDC, $hFont ), $lvLOGFONT = DllStructCreate( $tagLOGFONT ) _WinAPI_GetObject( $hFont, DllStructGetSize( $lvLOGFONT ), DllStructGetPtr( $lvLOGFONT ) ) Local $hLVfont = _WinAPI_CreateFontIndirect( $lvLOGFONT ) ; Original ListView font _WinAPI_SelectObject( $hDC, $hObject ) _WinAPI_ReleaseDC( $hListView, $hDC ) _WinAPI_DeleteObject( $hFont ) ; Set height of ListView items by applying text font with suitable height $hFont = _WinAPI_CreateFont( $iHeight, 0 ) _WinAPI_SetFont( $hListView, $hFont ) _WinAPI_DeleteObject( $hFont ) ; Restore font of Header control Local $hHeader = _GUICtrlListView_GetHeader( $hListView ) If $hHeader Then _WinAPI_SetFont( $hHeader, $hLVfont ) ; Return original ListView font Return $hLVfont EndFunc Large images will also increase the height of listview items. See example E. Height of listview If the height of the listview does not fit an integer number of rows, you can see empty space below last row in the bottom of the listview. This issue is exacerbated by tall items. The following function is used to calculate the height of the listview to match a given number of rows: Func _GUICtrlListView_GetHeightToFitRows( $hListView, $iRows ) ; Get height of Header control Local $tRect = _WinAPI_GetClientRect( $hListView ) Local $hHeader = _GUICtrlListView_GetHeader( $hListView ) Local $tWindowPos = _GUICtrlHeader_Layout( $hHeader, $tRect ) Local $iHdrHeight = DllStructGetData( $tWindowPos , "CY" ) ; Get height of ListView item 0 (item 0 must exist) Local $aItemRect = _GUICtrlListView_GetItemRect( $hListView, 0, 0 ) ; Return height of ListView to fit $iRows items ; Including Header height and 8 pixels of additional room Return ( $aItemRect[3] - $aItemRect[1] ) * $iRows + $iHdrHeight + 8 EndFunc The calculation includes the height of the header. This means that the function works for a multi-line header with tall items (example A and B). Reference example WM_NOTIFY messages and NM_CUSTOMDRAW notifications are send to the parent of the listview control. The parent is the AutoIt GUI and messages can be handled by a function registered with GUIRegisterMsg. Example 1 is a reference example which shows the different stages of the custom drawing process. None of the stages contains any code except for ConsoleWrite statements. This is code for the reference example: #include <GUIConstants.au3> #include <GuiListView.au3> #include "GuiListViewEx.au3" Opt( "MustDeclareVars", 1 ) Global $hGui, $idListView, $hListView, $fListViewHasFocus = 0, $iItems = 3, $bAutoItMsgLoop = False Example() Func Example() ; Create GUI $hGui = GUICreate( "Custom draw stages", 420, 200 ) ; Create ListView $idListView = GUICtrlCreateListView( "", 10, 10, 400, 180, $GUI_SS_DEFAULT_LISTVIEW-$LVS_SINGLESEL, $WS_EX_CLIENTEDGE+$LVS_EX_FULLROWSELECT+$LVS_EX_GRIDLINES ) $hListView = GUICtrlGetHandle( $idListView ) ; Add columns to ListView _GUICtrlListView_AddColumn( $hListView, "Column 1", 94 ) _GUICtrlListView_AddColumn( $hListView, "Column 2", 94 ) _GUICtrlListView_AddColumn( $hListView, "Column 3", 94 ) _GUICtrlListView_AddColumn( $hListView, "Column 4", 94 ) ; Fill ListView For $i = 0 To $iItems - 1 GUICtrlCreateListViewItem( $i & "/Column 1|" & $i & "/Column 2|" & $i & "/Column 3|" & $i & "/Column 4", $idListView ) Next ; Adjust height of GUI and ListView to fit ten rows Local $iLvHeight = _GUICtrlListView_GetHeightToFitRows( $hListView, 10 ) WinMove( $hGui, "", Default, Default, Default, WinGetPos( $hGui )[3] - WinGetClientSize( $hGui )[1] + $iLvHeight + 20 ) WinMove( $hListView, "", Default, Default, Default, $iLvHeight ) ; Register WM_NOTIFY message handler ; To handle NM_CUSTOMDRAW notifications ; And to check when ListView receives/loses focus GUIRegisterMsg( $WM_NOTIFY, "WM_NOTIFY" ) ; Register WM_ACTIVATE message handler ; If GUI loses focus selected listview items are drawn with a button face background color. ; To check when GUI receives/loses focus ; When GUI receives focus selected items are redrawn with the dark blue background color. GUIRegisterMsg( $WM_ACTIVATE, "WM_ACTIVATE" ) ; Detection of received focus is faster through the WM_ACTIVATE message than directly ; through the listview. This provides a faster and smoother redraw of selected items. ; Show GUI GUISetState( @SW_SHOW ) ; Message loop While 1 Switch GUIGetMsg() Case $GUI_EVENT_CLOSE ExitLoop EndSwitch If Not $bAutoItMsgLoop Then _ ; We want to see only one message at a time $bAutoItMsgLoop = ( ConsoleWrite( "AutoIt message loop <<<<<<<<<<<<<<<<<<<<<" & @CRLF ) > 0 ) WEnd ; Cleanup GUIDelete() EndFunc ; WM_NOTIFY message handler Func WM_NOTIFY( $hWnd, $iMsg, $wParam, $lParam ) #forceref $hWnd, $iMsg, $wParam Local $tNMHDR = DllStructCreate( $tagNMHDR, $lParam ) Local $hWndFrom = HWnd( DllStructGetData( $tNMHDR, "hWndFrom" ) ) Local $iCode = DllStructGetData( $tNMHDR, "Code" ) Switch $hWndFrom Case $hListView Switch $iCode Case $NM_CUSTOMDRAW $bAutoItMsgLoop = False Local $tNMLVCustomDraw = DllStructCreate( $tagNMLVCUSTOMDRAW, $lParam ) Local $dwDrawStage = DllStructGetData( $tNMLVCustomDraw, "dwDrawStage" ) Switch $dwDrawStage ; Specifies the drawing stage ; Stage 1 Case $CDDS_PREPAINT ; Before the paint cycle begins ConsoleWrite( "Stage 1: CDDS_PREPAINT" & @CRLF ) Return $CDRF_NOTIFYITEMDRAW + _ ; Stage 2 will be carried out $CDRF_NOTIFYPOSTPAINT ; Stage 6 will be carried out Return $CDRF_NOTIFYITEMDRAW ; Notify the parent window before an item is painted Return $CDRF_NOTIFYPOSTPAINT ; Notify the parent window after the paint cycle is complete ; Stage 2 Case $CDDS_ITEMPREPAINT ; Before an item is painted ConsoleWrite( "Stage 2: CDDS_ITEMPREPAINT" & @CRLF ) Return $CDRF_NOTIFYSUBITEMDRAW + _ ; Stage 3 will be carried out $CDRF_NOTIFYPOSTPAINT ; Stage 5 will be carried out Return $CDRF_NOTIFYSUBITEMDRAW ; Notify the parent window before a subitem is painted Return $CDRF_NOTIFYPOSTPAINT ; Notify the parent window after an item is painted ; Stage 3 Case BitOR( $CDDS_ITEMPREPAINT, _ $CDDS_SUBITEM ) ; Before a subitem is painted ConsoleWrite( "Stage 3: CDDS_ITEMPREPAINT, CDDS_SUBITEM" & @CRLF ) Return $CDRF_NOTIFYPOSTPAINT ; Stage 4 will be carried out Return $CDRF_NOTIFYPOSTPAINT ; Notify the parent window after a subitem is painted ; Stage 4 Case BitOR( $CDDS_ITEMPOSTPAINT, _ $CDDS_SUBITEM ) ; After a subitem has been painted ConsoleWrite( "Stage 4: CDDS_ITEMPOSTPAINT, CDDS_SUBITEM" & @CRLF ) ; Stage 5 Case $CDDS_ITEMPOSTPAINT ; After an item has been painted ConsoleWrite( "Stage 5: CDDS_ITEMPOSTPAINT" & @CRLF ) ; Stage 6 Case $CDDS_POSTPAINT ; After the paint cycle is complete ConsoleWrite( "Stage 6: CDDS_POSTPAINT" & @CRLF ) EndSwitch Case $NM_KILLFOCUS If $fListViewHasFocus Then GUICtrlSendMsg( $idListView, $LVM_REDRAWITEMS, 0, $iItems - 1 ) $fListViewHasFocus = 0 EndIf Case $NM_SETFOCUS If Not $fListViewHasFocus Then _ GUICtrlSendMsg( $idListView, $LVM_REDRAWITEMS, 0, $iItems - 1 ) $fListViewHasFocus = 2 EndSwitch EndSwitch Return $GUI_RUNDEFMSG EndFunc ; WM_ACTIVATE message handler Func WM_ACTIVATE( $hWnd, $iMsg, $wParam, $lParam ) #forceref $iMsg, $lParam If $hWnd = $hGui Then _ $fListViewHasFocus = BitAND( $wParam, 0xFFFF ) ? 1 : 0 Return $GUI_RUNDEFMSG EndFunc Code is added to check when GUI and listview receives and loses focus. This is important in the other examples. Output in SciTE console immediately after example is opened: Stage 1: CDDS_PREPAINT Stage 2: CDDS_ITEMPREPAINT Stage 3: CDDS_ITEMPREPAINT, CDDS_SUBITEM Stage 4: CDDS_ITEMPOSTPAINT, CDDS_SUBITEM Stage 3: CDDS_ITEMPREPAINT, CDDS_SUBITEM Stage 4: CDDS_ITEMPOSTPAINT, CDDS_SUBITEM Stage 3: CDDS_ITEMPREPAINT, CDDS_SUBITEM Stage 4: CDDS_ITEMPOSTPAINT, CDDS_SUBITEM Stage 3: CDDS_ITEMPREPAINT, CDDS_SUBITEM Stage 4: CDDS_ITEMPOSTPAINT, CDDS_SUBITEM Stage 5: CDDS_ITEMPOSTPAINT Stage 2: CDDS_ITEMPREPAINT Stage 3: CDDS_ITEMPREPAINT, CDDS_SUBITEM Stage 4: CDDS_ITEMPOSTPAINT, CDDS_SUBITEM Stage 3: CDDS_ITEMPREPAINT, CDDS_SUBITEM Stage 4: CDDS_ITEMPOSTPAINT, CDDS_SUBITEM Stage 3: CDDS_ITEMPREPAINT, CDDS_SUBITEM Stage 4: CDDS_ITEMPOSTPAINT, CDDS_SUBITEM Stage 3: CDDS_ITEMPREPAINT, CDDS_SUBITEM Stage 4: CDDS_ITEMPOSTPAINT, CDDS_SUBITEM Stage 5: CDDS_ITEMPOSTPAINT Stage 2: CDDS_ITEMPREPAINT Stage 3: CDDS_ITEMPREPAINT, CDDS_SUBITEM Stage 4: CDDS_ITEMPOSTPAINT, CDDS_SUBITEM Stage 3: CDDS_ITEMPREPAINT, CDDS_SUBITEM Stage 4: CDDS_ITEMPOSTPAINT, CDDS_SUBITEM Stage 3: CDDS_ITEMPREPAINT, CDDS_SUBITEM Stage 4: CDDS_ITEMPOSTPAINT, CDDS_SUBITEM Stage 3: CDDS_ITEMPREPAINT, CDDS_SUBITEM Stage 4: CDDS_ITEMPOSTPAINT, CDDS_SUBITEM Stage 5: CDDS_ITEMPOSTPAINT Stage 6: CDDS_POSTPAINT AutoIt message loop <<<<<<<<<<<<<<<<<<<<< Note that the entire custom draw process from stage 1 to 6 is not interrupted by the AutoIt message loop. The other examples are all based on the reference example. Examples This is common to all examples. First line in item texts is stored directly in the listview. Additional lines are stored in a global array named $aLines. Index in the array is item ID as returned by GUICtrlCreateListViewItem and stored in ItemParam internally in listview memory. Item texts and background is drawn with custom code. Other item elements and background is drawn with default code. In all examples LVS_SINGLESEL style is removed to be able to select multiple items. This is a picture of example E: Example 2, 3 and 4 are simple examples. Example 5 and 6 deals with subitem icons and colors. Example 7 about listview notifications shows a way to catch double click and Enter key. A dummy control is used to forward the double click event to AutoIt main message loop to avoid lengthy or blocking code in WM_NOTIFY function. Example 8 and 9 shows how to respond to header notifications and how to rearrange columns by dragging header items with the mouse. In both examples LVS_EX_HEADERDRAGDROP extended style is added to the listview. When columns are rearranged, header item index and listview subitem index is always the same independent of column position, while header item order changes depending on column position. Because the header is a child control of the listview, the listview must be subclassed to catch header notifications. Subclassing is implemented with the four functions SetWindowSubclass, GetWindowSubclass, RemoveWindowSubclass and DefSubclassProc (all implemented in WinAPIShellEx.au3). Since we are subclassing a header control contained in a listview this issue must be taking into account. Note that the subclass callback function is only running while the primary mouse button is pressed on the header. This means no performance impact on the listview eg. when you are dragging the scroll bar. This is important for a custom drawn listview. Quite a lot of extra code is added (most easily seen in example 9) to fix an issue due to column 0 and other columns have different left margins. When first column is moved to another position there is a white gap between columns for selected rows (Windows XP), or the text is painted too close to the left edge of the item (Windows 7). The problem is seen in the picture to the right where the two first columns are swapped: LVS_EX_HEADERDRAGDROP style is only used in example 8 and 9. Usage of a multi-line header is demonstrated in example A and B. See Custom/owner drawn multi-line header in ListView for more information. Example C shows a method to deal with focus issues when more controls (here just a single button) are added to the GUI. When the listview has focus selected items are drawn with the dark blue background color. The problem arises if the listview and GUI loses focus eg. to Calculator. When focus is lost selected items are drawn with the button face background color. If GUI receives focus again by clicking the button (and not the listview), selected items are first very briefly redrawn with the dark blue background color (it seems like a blink) and then with the correct button face background color. To avoid this issue a hidden label control is added to the GUI. Immediately before the GUI loses focus, focus is moved from the listview to the label. In example D items are added with the commands _GUICtrlListView_AddItem and _GUICtrlListView_AddSubItem. In all examples an array is used to store the multi-line item texts. The array contains all lines except the first line which is stored directly in the listview. This example shows how to manually store array row index in ItemParam when items are added with _GUICtrlListView_AddItem and _GUICtrlListView_AddSubItem. Inspiration for example E about large images in first column (see picture above) comes from this thread. In example E the images are used to increase the height of the listview items instead of a text font. Because it's large 128x128 pixel images there is plenty of room in subitems in second and third column. In all examples 15 lines of code is used to repaint the first line item text. The text that was painted by default code in middle of the item is first deleted by filling the item with the background color. Then the text is extracted from the listview and repainted in top of item. This code can be avoided by storing all text lines in the array. This is demonstrated in example F. This makes the custom draw code faster. Performance considerations In a custom drawn (or owner drawn or virtual) listview performance considerations are important because the custom drawing (or owner drawing or data display) is performed by AutoIt code. In a normal listview drawing and data display is performed by compiled C++ code in ComCtl32.dll. Lengthy and slow code in NM_CUSTOMDRAW Case statements (or WM_DRAWITEM functions or LVN_GETDISPINFO Case statements) should be avoided. Perform as many calculations as possible before the repetitive and fast executions of these code blocks. Use static variables to avoid repeating the same calculation again and again. Executing a function directly with DllCall or GUICtrlSendMsg is faster than executing the same function through an implementation in an UDF. Simple GDI functions are faster than more advanced GDI+ functions. Use different drawing stages to optimize custom drawing. The CDDS_PREPAINT stage is only performed once for the entire drawing process. The CDDS_ITEMPREPAINT stage is performed once per item. The stage given by BitOR( CDDS_ITEMPREPAINT, CDDS_SUBITEM ) is performed once per subitem including subitem 0. Default drawing should be used as much as possible, because the code is running in ComCtl32.dll. In a listview the time it takes to update all visible rows is proportional to the number of visible rows. Reducing the height of the list view and thus the number of visible rows improves performance. Especially in a custom drawn (or owner drawn or virtual) listview. ListviewMultilineItems.7z 1) Custom draw stages.au3 2) Two-line listview items.au3 3) Three-line listview items.au3 4) First column checkbox and icon.au3 5) Check boxes and icons.au3 6) Background and text colors.au3 7) ListView notifications.au3 8) Header notifications.au3 9) Rearrange columns.au3 A) Multi-line header 1.au3 A) Multi-line header 2.au3 C) Button control.au3 D) _GUICtrlListView_AddItem.au3 E) Large images in first column.au3 F) Storing all lines in array.au3 GuiHeaderEx.au3 GuiListViewEx.au3 ListViewCustomDraw.au3 Images\ 8 images for example E You need AutoIt 3.3.10 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.) ListviewMultilineItems.7z1 point -
Virtual listviews are lightning fast and can handle millions of rows. Virtual listviews are of interest when you have to insert more than 10,000 rows. When there are less than 10,000 rows, the standard listviews are sufficiently rapid. See the section "Using standard listviews" below. In a virtual listview data are not stored directly in the listview. Data are stored in an array, a structure (DllStructCreate), a flat fixed-length record file, a database or similar. The listview only contains the rows which are visible depending on the height of the listview. See About List-View Controls in the MicroSoft documentation for more information. An array or a structure can be used for listviews with 10,000 - 100,000 rows. If there are more than 100,000 rows a fixed-length record file or a database seems to be the best solution, because they have low impact on memory usage. But you get nothing for free. The costs is that a part of the built-in features does not work, and you will have to implement these features yourself. Because data isn't stored in the listview the Set- and Get-functions to manipulate data doesn't work. You have to manipulate the data source directly. And sorting is not supported at all by virtual listviews. If you need sorting, a database seems to be the best solution in all cases, because sorting can be handled by the database. Below you'll find the following sections: Data stored in arrays Data stored in databases Data stored in fixed-length record files Sorting rows in a virtual listview $LVN_ODFINDITEM notifications Using standard listviews Updates Zip file Examples The next two sections shows how to use virtual listviews, when data are stored in arrays or databases. In first section data are stored in 3 arrays with 10,000/50,000/100,000 rows and 10 columns. In second section data are stored in 3 databases with 100,000/1,000,000/10,000,000 rows and 10 columns. Data stored in arrays For a virtual listview rows are displayed with $LVN_GETDISPINFO notifications and the $tagNMLVDISPINFO structure. Code for $LVN_GETDISPINFO messages in the WM_NOTIFY function can be implemented in this manner: Case $LVN_GETDISPINFOW Local $tNMLVDISPINFO = DllStructCreate( $tagNMLVDISPINFO, $lParam ) If BitAND( DllStructGetData( $tNMLVDISPINFO, "Mask" ), $LVIF_TEXT ) Then Local $sItem = $aItems[DllStructGetData($tNMLVDISPINFO,"Item")][DllStructGetData($tNMLVDISPINFO,"SubItem")] DllStructSetData( $tText, 1, $sItem ) DllStructSetData( $tNMLVDISPINFO, "Text", $pText ) DllStructSetData( $tNMLVDISPINFO, "TextMax", StringLen( $sItem ) ) EndIf Run LvVirtArray.au3. It takes some time to create the arrays. But when the arrays are created, switching from one array to another (which means updating the listview) is instantaneous. Data stored in databases When data are stored in a database, $LVN_ODCACHEHINT notifications and the $tagNMLVCACHEHINT structure is used to insert the rows in an array cache before they are displayed with $LVN_GETDISPINFO messages. The $tagNMLVCACHEHINT structure is defined in this way: Global Const $tagNMLVCACHEHINT = $tagNMHDR & ";int iFrom;int iTo" Note that $tagNMLVCACHEHINT is not included in GuiListView.au3 or StructureConstants.au3. Code for $LVN_ODCACHEHINT messages in the WM_NOTIFY function can be implemented in this manner: Case $LVN_ODCACHEHINT Local $tNMLVCACHEHINT = DllStructCreate( $tagNMLVCACHEHINT, $lParam ), $iColumns $iFrom = DllStructGetData( $tNMLVCACHEHINT, "iFrom" ) Local $sSQL = "SELECT * FROM lvdata WHERE item_id >= " & $iFrom & _ " AND item_id <= " & DllStructGetData( $tNMLVCACHEHINT, "iTo" ) & ";" _SQLite_GetTable2d( -1, $sSQL, $aResult, $iRows, $iColumns ) $aResult is the array cache. The purpose of the cache is to limit the number of SELECT statements. When the listview is displayed for the first time, all visible rows (in this example about 20) have to be updated. In this case $aResult will contain 20 rows and 10 columns. 20 rows is also the maximum number of rows in $aResult. A virtual listview will never update more than the visible number of rows at one time. Code for $LVN_GETDISPINFO messages can be implemented in this way: Case $LVN_GETDISPINFOW Local $tNMLVDISPINFO = DllStructCreate( $tagNMLVDISPINFO, $lParam ) If BitAND( DllStructGetData( $tNMLVDISPINFO, "Mask" ), $LVIF_TEXT ) Then Local $iIndex = DllStructGetData( $tNMLVDISPINFO, "Item" ) - $iFrom + 1 If $iIndex > 0 And $iIndex < $iRows + 1 Then Local $sItem = $aResult[$iIndex][DllStructGetData($tNMLVDISPINFO,"SubItem")] DllStructSetData( $tText, 1, $sItem ) DllStructSetData( $tNMLVDISPINFO, "Text", $pText ) DllStructSetData( $tNMLVDISPINFO, "TextMax", StringLen( $sItem ) ) EndIf EndIf The zip below contains a small GUI, CreateDB.au3, to create 3 SQLite databases with 100,000/1,000,000/10,000,000 rows. The databases will use about 10/100/1000 MB of diskspace, and the creation will take about ½/5/40 minutes (on an old XP). You must select a database and click a button to start the creation. If you get tired of waiting, you can cancel (checked for every 10,000 rows) the process and continue another time. The process will continue where it stopped. You can run the examples even though the databases might only contain 30,000/200,000/1,500,000 rows. You do not have to create all three databases. Run LvVirtDB.au3. Data stored in fixed-length record files (update 2015-04-01) Extracting data directly from a fixed-length record file by setting the file pointer to the current record and reading the required number of bytes is another example, where $LVN_ODCACHEHINT messages should be used to insert records in an array cache before they are displayed. Code for $LVN_ODCACHEHINT and $LVN_GETDISPINFO messages can be implemented as shown: Case $LVN_ODCACHEHINT Local $tNMLVCACHEHINT = DllStructCreate( $tagNMLVCACHEHINT, $lParam ) $iFrom = DllStructGetData( $tNMLVCACHEHINT, "iFrom" ) $iRows = DllStructGetData( $tNMLVCACHEHINT, "iTo" ) - $iFrom + 1 FileSetPos( $hFile, $iFrom * 12, 0 ) ; Each line is 10 chars + CR + LF $aCache = StringSplit( FileRead( $hFile, $iRows * 12 - 2 ), @CRLF, 3 ) The purpose of the cache is to limit the number of FileRead statements. Case $LVN_GETDISPINFOW Local $tNMLVDISPINFO = DllStructCreate( $tagNMLVDISPINFO, $lParam ) If BitAND( DllStructGetData( $tNMLVDISPINFO, "Mask" ), $LVIF_TEXT ) Then Local $iIndex = DllStructGetData( $tNMLVDISPINFO, "Item" ) - $iFrom If -1 < $iIndex And $iIndex < $iRows Then DllStructSetData( $tText, 1, $aCache[$iIndex] ) DllStructSetData( $tNMLVDISPINFO, "Text", $pText ) DllStructSetData( $tNMLVDISPINFO, "TextMax", 10 ) ; Each line is 10 chars EndIf EndIf Run LvVirtFile.au3. A fixed-length record file with 10,000 records (LvVirtFile.txt) is included in the zip. I have tested this example on a 1,1 GB file and 100,000,000 rows. The listview responds immediately. The solution with a flat fixed-length record file is extremely fast. Much faster than a database. But also with very much limited functionality compared to a database. Sorting rows in a virtual listview (update 2015-04-01) Sorting is not supported at all by virtual listviews. If you want rows to be sorted, you have to feed the listview with the rows in sorted order. If the rows are stored in an array, you have to sort the array before you feed the listview. If you want to sort the rows by two or more columns, you have to store the rows in two or more arrays which are sorted for the current column. Or you have to create two or more indexes to handle the sorting. Sorting arrays and creating indexes is time consuming. If you need sorting, a database seems to be the best solution, because sorting can be handled by the database. Nevertheless, here's an example that stores 10,000/20,000/30,000 rows and 3 columns in arrays, and creates indexes to handle the sorting. The columns are strings, integers and floating point numbers, and indexes are calculated for all 3 columns. To be able to create the indexes as fast as possible, structures (DllStructCreate) are used to create the indexes. This is the function to create indexes for integers and floating point numbers. The function for strings is equivalent. $tIndex = DllStructCreate( "uint[" & $iRows & "]" ) Func SortNumbers( ByRef $aItems, $iRows, $iCol, $pIndex, $tIndex ) Local $k, $n, $lo, $hi, $mi, $gt HourglassCursor( True ) WinSetTitle( $hGui, "", "Virtual ListViews. Sort numbers: 0 rows" ) For $i = 0 To $iRows / 10000 - 1 $k = $i * 10000 For $j = 0 To 9999 $n = $aItems[$k+$j][$iCol] ; Binary search $lo = 0 $hi = $k + $j - 1 While $lo <= $hi $mi = Int( ( $lo + $hi ) / 2 ) If $n < $aItems[DllStructGetData($tIndex,1,$mi+1)][$iCol] Then $gt = 0 $hi = $mi - 1 Else $gt = 1 $lo = $mi + 1 EndIf WEnd ; Make space for the new value DllCall( $hKernel32Dll, "none", "RtlMoveMemory", "struct*", $pIndex+($mi+1)*4, "struct*", $pIndex+$mi*4, "ulong_ptr", ($k+$j-$mi)*4 ) ; Insert new value DllStructSetData( $tIndex, 1, $k+$j, $mi+1+$gt ) Next WinSetTitle( $hGui, "", "Virtual ListViews. Sort numbers: " & $k + 10000 & " rows" ) Next HourglassCursor( False ) WinSetTitle( $hGui, "", "Virtual ListViews (sorted)" ) EndFunc Run LvVirtArraySort.au3. It takes some time to create the arrays and indexes. But when everything is created, sorting by different columns and switching from one array to another is instantaneous. Because it's easy and fast to save/load a structure to/from a binary file, it may be advantageous to calculate the arrays and indexes in another script before the GUI is opened. $LVN_ODFINDITEM notifications (update 2015-04-01) Three notifications are important for virtual listviews. $LVN_GETDISPINFO (to get information about the rows to display in the listview) and $LVN_ODCACHEHINT (to store rows from a file or database in an array cache before they are displayed with $LVN_GETDISPINFO messages) are already mentioned above. The last is $LVN_ODFINDITEM, which is used to find a row when you press one or a few keys on the keyboard. Information from $LVN_ODFINDITEM is stored in the $tagNMLVFINDITEM structure. The codebox shows the code for $LVN_ODFINDITEM notifications: Case $LVN_ODFINDITEMW Local $tNMLVFINDITEM = DllStructCreate( $tagNMLVFINDITEM, $lParam ) If BitAND( DllStructGetData( $tNMLVFINDITEM, "Flags" ), $LVFI_STRING ) Then Return SearchText( DllStructGetData( $tNMLVFINDITEM, "Start" ), _ ; Start DllStructGetData( DllStructCreate( "wchar[20]", DllStructGetData( $tNMLVFINDITEM, "Text" ) ), 1 ) ) ; Text EndIf Start is the row where you start the search. Text contains the key presses to search for. You have to implement the search function (here SearchText) yourself. If the function finds a row, it should return the index of the row. If not, it should return -1. Run LvVirtArrayFind.au3. Using standard listviews (update 2015-04-01) If not more than 10,000 rows have to be inserted in a listview, a standard listview is sufficiently rapid. Because of speed you should use native (built-in) functions to fill the listview and not functions in GuiListView.au3 UDF. When the listview is filled, you can use all the functions in the UDF. This code shows how to quickly fill a listview with native functions: Func FillListView( $idLV, ByRef $aItems, $iRows ) Local $tLVITEM = DllStructCreate( $tagLVITEM ) Local $pLVITEM = DllStructGetPtr( $tLVITEM ), $k, $s DllStructSetData( $tLVITEM, "Mask", $LVIF_IMAGE ) ; Icon (or image) DllStructSetData( $tLVITEM, "SubItem", 0 ) ; First column HourglassCursor( True ) For $i = 0 To $iRows / 10000 - 1 $k = $i * 10000 For $j = 0 To 9999 ; Text $s = $aItems[$k+$j][0] For $l = 1 To 9 $s &= "|" & $aItems[$k+$j][$l] Next GUICtrlCreateListViewItem( $s, $idLV ) ; Add item and all texts ; Icon Select Case Mod( $k + $j, 3 ) = 0 DllStructSetData( $tLVITEM, "Image", 2 ) ; Icon index Case Mod( $k + $j, 2 ) = 0 DllStructSetData( $tLVITEM, "Image", 1 ) Case Else DllStructSetData( $tLVITEM, "Image", 0 ) EndSelect DllStructSetData( $tLVITEM, "Item", $k + $j ) ; Row GUICtrlSendMsg( $idLV, $LVM_SETITEMW, 0, $pLVITEM ) ; Add icon Next WinSetTitle( $hGui, "", "GUICtrlCreateListViewItem ListViews. Fills listview: " & $k + 10000 & " rows" ) Next HourglassCursor( False ) WinSetTitle( $hGui, "", "GUICtrlCreateListViewItem ListViews" ) EndFunc Run LvStandard.au3. LvStandardIni.au3 shows how to quickly load an inifile (LvStandardIni.ini, created with IniWriteSection) into a listview. Because an inifile is a small file (only the first 32767 chars are read) it should always be loaded into a standard listview. Updates Update 2015-03-24 Added two array-examples. An example (LvVirtArrayIcons.au3) that shows how to use checkboxes and icons, and an example (LvVirtArrayColors.au3) that shows how to draw every second row with a different background color. In this post you can find an example where all items are drawn with a random background color. Update 2015-04-01 Cleaned up code in previous examples. Added more examples as described above. Zip updated. UDF versions (2018-04-27) Over the past weeks, new display functions have been added to Data display functions based on virtual listviews, and new functions have been added to use the listviews as embedded GUI controls. All the functions work and are used in much the same way. Apart from the data source, the function parameters are the same for all functions. The display functions support a wide range of features, all specified via a single function parameter $aFeatures, which is the last parameter. The central code to handle $LVN_ODCACHEHINT and $LVN_GETDISPINFO notifications is very optimized code. First of all, the code is implemented through the subclassing technique. This means that messages are received directly from the operating system and not from AutoIt's internal message management code. Messages are returned again directly to the operating system and again without interference with AutoIt's internal message handling code. Next, the code is divided into different include files each taking care of a particular feature. That way, it's avoided that a lot of control statements makes the code slow. And it's enough to include the code that's actually used. One reason why so much work has been done in optimizing code and developing features is that these functions will also work as UDF versions for the examples here. It's far from a trivial task to develop UDF versions of examples like these. Since the first version of the display functions was created in this thread 2½ years ago and then has been continuously developed, it's obvious to use the functions as UDF versions of these examples. The following examples are implemented as UDF versions: Data stored in arrays Data stored in CSV files Data stored in SQLite databases Zip file Examples in zip: LvVirtArray.au3 - Data stored in arrays LvVirtArrayColors.au3 - Alternating row colors LvVirtArrayFind.au3 - $LVN_ODFINDITEM notifications LvVirtArrayIcons.au3 - Checkboxes and icons LvVirtArraySort.au3 - Sorting rows in a virtual listview LvVirtDB.au3 - Data stored in databases (use CreateDB.au3 to create DBs) LvVirtFile.au3 - Data stored in fixed-length record files LvStandard.au3 - Using standard listviews LvStandardIni.au3 - Load inifile into a listview The size of the zip is caused by a 118 KB txtfile, LvVirtFile.txt, used by LvVirtFile.au3, and a 28 KB inifile, LvStandardIni.ini, used by LvStandardIni.au3. Tested with AutoIt 3.3.10 on Windows 7 64 bit and Windows XP 32 bit. Should work on all AutoIt versions from 3.3.10 and all Windows versions. Virtual ListViews.7z Examples Examples based on virtual listviews. Array examples: A lot of rows and random background colors for each cell - This post in another thread Incremental search (update as you type) in a virtual listview - Post 29 Sorting arrays: Rows can be sorted by strings, integers, floats and checkboxes, checked rows in top - Post 48 File sources: A CSV-file with 100,000 rows and 10 columns is data source - Post 56 SQLite examples: Various issues related to the use of a database - Post 34, 35, 43 An example that shows a way to implement a search box - Post 411 point
-
Incremental search in owner and custom drawn ListViews
pixelsearch reacted to LarsJ for a topic
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.7z1 point -
This works for hard drives (not removable) : #include <Constants.au3> Local $aDisk = DriveGetDrive($DT_FIXED) For $i = 1 To $aDisk[0] ConsoleWrite (_DiskManufacturer(StringUpper($aDisk[$i])) & @CRLF) Next Func _DiskManufacturer($sDisk) Local $objWMIService = ObjGet("winmgmts:\\" & @ComputerName & "\root\CIMV2") Local $col = $objWMIService.ExecQuery("SELECT * from Win32_LogicalDiskToPartition") Local $sDiskNumber = "", $sDiskPhys = "" For $objItem In $col If StringRegExp($objItem.Dependent, 'DeviceID="(.+?)"', $STR_REGEXPARRAYMATCH)[0] = $sDisk Then $sDiskNumber = StringRegExp($objItem.Antecedent, 'DeviceID="(.+?),', $STR_REGEXPARRAYMATCH)[0] ExitLoop EndIf Next If $sDiskNumber = "" Then Return SetError(1, 0, "") ConsoleWrite($sDiskNumber & @CRLF) $col = $objWMIService.ExecQuery("SELECT * from Win32_DiskDriveToDiskPartition") For $objItem In $col If StringRegExp($objItem.Dependent, 'DeviceID="(.+?),', $STR_REGEXPARRAYMATCH)[0] = $sDiskNumber Then $sDiskPhys = StringReplace(StringRegExp($objItem.Antecedent, 'DeviceID="(.+?)"', $STR_REGEXPARRAYMATCH)[0], "\\", "\") ExitLoop EndIf Next If $sDiskPhys = "" Then Return SetError(2, 0, "") ConsoleWrite($sDiskPhys & @CRLF) $col = $objWMIService.ExecQuery("SELECT * from Win32_DiskDrive") For $objItem In $col If $objItem.DeviceId = $sDiskPhys Then Return $objItem.caption EndIf Next Return SetError(3, 0, "") EndFunc ;==>_DiskManufacturer1 point
-
OutlookEX UDF - Help & Support (IV)
seadoggie01 reacted to water for a topic
That‘s a bug. It has already been fixed but no new version of the UDF has been released since. I think I have posted the solution on the forum lately. Let me know if you can’t find it. I’m not at my computer right now.1 point -
@svenjatzu Suggest that you take a look at wd_demo.au3 and use it as a tutorial for writing your own script. Come back once you've done that, show us your code, and then we can address any issues that still remain.1 point
-
You're simply using a wrong technique. When detecting events in a Windows message handler (right-click in a WM_NOTIFY message handler) and the corresponding code must be executed in the AutoIt message handler (so the context menu does not block the WM_NOTIFY message handler), you must ensure that all events are sent on to the AutoIt message handler and in proper order. And you need to make sure that the events can consistently wait for the AutoIt message handler to execute the corresponding code. There are many situations that can temporarily interrupt the AutoIt message handler, eg. a pile of Windows messages. The best way to meet all these requirements (all events, proper order, wait systematically) is to use AutoIt's built-in message handler system, which implements an actual message queue. Ie. use two Dummy controls to send events from the Windows message handler to the AutoIt message handler: #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 <GUIConstantsEx.au3> #include <GuiListView.au3> #include <GuiMenu.au3> #include <WindowsConstants.au3> Global $g_hListView, $g_hHeader, $g_idHeaderMenu, $g_idCellMenu Example() ;============================================ Func Example() Local $hGUI = GUICreate("Right-click on headers or cells", 400, 200) Local $idListView = GUICtrlCreateListView _ (" Col 0 | Col 1| Col 2| Col 3", 10, 10, 380, 180) $g_hListView = GuiCtrlGetHandle($idListView) $g_hHeader = _GUICtrlListView_GetHeader($idListView) $g_idHeaderMenu = GUICtrlCreateDummy() $g_idCellMenu = GUICtrlCreateDummy() For $iRow = 0 To 9 GUICtrlCreateListViewItem( _ "Row " & $iRow & " / Col 0 |" & _ "Row " & $iRow & " / Col 1 |" & _ "Row " & $iRow & " / Col 2 |" & _ "Row " & $iRow & " / Col 3", $idListView) Next GUIRegisterMsg($WM_NOTIFY, "WM_NOTIFY") GUISetState(@SW_SHOW) While 1 Switch GUIGetMsg() Case $g_idHeaderMenu Header_menu() Case $g_idCellMenu Cell_menu() Case $GUI_EVENT_CLOSE GUIDelete($hGUI) Exit EndSwitch Wend EndFunc ;==>Example ;============================================ Func WM_NOTIFY($hWnd, $iMsg, $wParam, $lParam) #forceref $hWnd, $iMsg, $wParam Local $tNMHDR, $hWndFrom, $iCode ; $iIDFrom $tNMHDR = DllStructCreate($tagNMHDR, $lParam) $hWndFrom = DllStructGetData($tNMHDR, "hWndFrom") $iCode = DllStructGetData($tNMHDR, "Code") Switch $hWndFrom Case $g_hListView Switch $iCode Case $NM_RCLICK GUICtrlSendToDummy( $g_idCellMenu ) EndSwitch Case $g_hHeader Switch $iCode Case $NM_RCLICK GUICtrlSendToDummy( $g_idHeaderMenu ) EndSwitch EndSwitch Return $GUI_RUNDEFMSG EndFunc ;==>WM_NOTIFY ;============================================ Func Header_menu() ; called by right click on header Local $iMenu_Choice = 0 Local $hMenu = _GUICtrlMenu_CreatePopup() _GUICtrlMenu_InsertMenuItem($hMenu, 10, "Header menu", 10) _GUICtrlMenu_InsertMenuItem($hMenu, 15, "", 0) _GUICtrlMenu_InsertMenuItem($hMenu, 20, "Option 1", 20) _GUICtrlMenu_InsertMenuItem($hMenu, 30, "Option 2", 30) $iMenu_Choice = _GUICtrlMenu_TrackPopupMenu($hMenu, $g_hHeader, -1, -1, 1, 1, 2) _GUICtrlMenu_DestroyMenu($hMenu) Switch $iMenu_Choice Case 0, 10 Case 20 Case 30 EndSwitch EndFunc ;==>Header_menu ;============================================ Func Cell_menu() ; called by right click on any cell Local $iMenu_Choice = 0 Local $hMenu = _GUICtrlMenu_CreatePopup() _GUICtrlMenu_InsertMenuItem($hMenu, 10, "Cell menu", 10) _GUICtrlMenu_InsertMenuItem($hMenu, 15, "", 0) _GUICtrlMenu_InsertMenuItem($hMenu, 20, "Option 3", 20) _GUICtrlMenu_InsertMenuItem($hMenu, 30, "Option 4", 30) $iMenu_Choice = _GUICtrlMenu_TrackPopupMenu($hMenu, $g_hListView, -1, -1, 1, 1, 2) ; $g_hHeader -> g_hListView _GUICtrlMenu_DestroyMenu($hMenu) ; However, has nothing to do with the issues Switch $iMenu_Choice Case 0, 10 Case 20 Case 30 EndSwitch EndFunc ;==>Cell_menu This code is the default code for such tasks. It's easy, simple and straightforward code that works well. Why use different code? (The code above can be optimized a lot, but it's probably not that important here.) Your code is incorrect because it does not implement a proper message handler system that guarantees that all events are handled and in proper order when there is time for it. The issues in your code show this. The two situations are probably different because there are many more listview notifications than header notifications. The many listview notifications mean that the listview code in the WM_NOTIFY message handler is in poor sync with the code in the AutoIt message handler. The few header notifications mean that the header code is better synchronized between the WM_NOTIFY message handler and the AutoIt message handler. A piece of coherent code should either be executed in the Windows message handler or in the AutoIt message handler. If the code is split between both message handlers, there is no guarantee that the code will run correctly. The code in the two message handlers is not synchronized in any way. Therefore, an actual queue system that guarantees that events are executed correctly is necessary to send events from the Windows message handler to the AutoIt message handler.1 point
-
Hello LarsJ, Your ListView controls Functions/Files/Codes are just great. Thank you for sharing these files/codes. If you've ListView groups functions, Can you Please also share those functions ? ListView Group Functions:- Set/GetLVGroupFont (Size,Color,Style,....) of any ListView Set/GetLVGroupHandle Set/GetLVGroupPosition Set/GetLVGroupEnable/Disable Set/GetLVGroupAdd/RemoveFromArray Set/GetLVGroupAdd/Remove Set/GetLVGroupNameHyperlink Set/GetLVGroupCollapse/ExpandState Set/GetLVGroupItemCount Set/GetLVGroupSort .....1 point
-
My UDFs
argumentum reacted to AOK for a topic
Found it here. Here you everyone after me - looking for it 😉 ControlSendPlus.au31 point -
objcreate("VisualFoxPro.Application") objcreate("VisualFoxPro.Application.9") With above you can probably create an object within AutoIt to control VFP. Although I feel thats a weird way of doing it. Don't know ,much about dbf files (last time I used them was more then 15 years ago) Just within foxpro you could use append from https://fox.wikis.com/wc.dll?Wiki~APPENDFROM1 point
-
I believe it would be less complicated and potentially more reliable if you used Foxpro to automate this process instead of Autoit. If you stored the changes in a DBF table, then you could write a simple PRG to perform the update. If you insist on using Excel, this could still be done within Foxpro. FWIW, I've used this library to pull data from Excel into a cursor and then manipulated the data within Foxpro.1 point
-
My fine tuned High Contrast theme
Professor_Bernd reacted to argumentum for a file
Version 0.2019.12.12
789 downloads
My fine tuned High Contrast theme, came from the need of a better "Dark Mode", that is still not there yet. Okay, let's use a "High Contrast Theme", but then again, the available colors to tweak are quite limited. So I'm like But since we can code: Behold !, an expanded theme color chooser 😁 And none of the changes, add or remove anything to the OS. Is just color tweaking. ...is incomplete as far as I would like it to be but, fully functional at this stage. ( I'll continue as time permits )1 point -
In the forums you can find several questions about how to edit the text in a ListView cell with a standard control eg. an Edit control or a ComboBox. The zip below contains three examples with an Edit control, a ComboBox and a DateTimePicker. How? A description from MicroSoft of how to edit a ListView cell with a ComboBox can be found here. When you click a cell the position and size is calculated, and the ComboBox is created on top of the cell. The text is shown in the Edit box. You can edit the text or select a value in the Listbox. Press Enter to save the text in the ListView cell and close the ComboBox. The ComboBox exists only while the text is edited. Code issues Especially because the control to edit the ListView cell is created on top of the ListView and is not part of the ListView, there are some issues you should be aware of. To get everything to look as good as possible most actions should be carried out when a mouse button is pressed and not when it's released. You should also be aware that the new code you add, does not conflict with existing functionality for example multiple selections. The examples consists of small but fairly many pieces of code to respond to events and messages. Keyboard support To edit a text value you are more or less forced to use the keyboard to type in the text. It would be nice if you could also select the current cell in the ListView with the keyboard. Cell selection with the keyboard is not too hard to implement with custom draw code. The current cell is drawn with a specific background color. It looks like this. You can select the current cell with the arrow keys. Open the control There must be a way to initiate the creation of the control. This is typically done with a single or double click in the ListView. Or with Enter or Space key in the examples with keyboard support. Default in the examples is double click and Enter key. You can change this in global variables in top of the scripts. A WM_NOTIFY message handler created with GUIRegisterMsg is used to watch for single and double click in the ListView. This message handler is also used to handle custom draw messages for keyboard support. Because the control is created on top of the ListView cell, it's very important that the ListView is set as the parent window. This ensures that mouse clicks and key presses are captured by the control and not by the ListView. Events in the control In a ComboBox and a DateTimePicker an additional control (Listbox and MonthCal, respectively) is opened if you click the Dropdown arrow (or press <Alt+Down arrow> on the keyboard). Click the Dropdown arrow again to close the control (or press <Alt+Up arrow> on the keyboard). The interesting messages (DROPDOWN, SELECTION, CLOSEUP) from such an additional control are usually contained in WM_COMMAND or WM_NOTIFY messages which are sent to the parent window. The parent window is the ListView. To catch the messages the ListView must be subclassed. Messages from the Edit control, the Edit box of the ComboBox, or the client area of the DateTimePicker are catched by subclassing the controls (Edit control, Edit box and DateTimePicker) directly. The interesting information here is dialog codes to accept (Enter) or cancel (Esc) the value and close the control. Dialog codes are sent as $WM_GETDLGCODE messages. In all examples the value in the control can also be accepted and saved with a double click. Close the control A mouse click in the ListView outside the control should close the control and cancel editing of the current cell. Because the control is not part of the ListView in particular mouse clicks on the Scrollbars should close the control immediately. The control will not be repainted properly on scrolling. Mouse clicks in the ListView and on Scrollbars can be identified by WM_LBUTTONDOWN and WM_NCLBUTTONDOWN messages. The area which is filled by Scrollbars in a ListView is non-client area. Mouse clicks in non-client area generates WM_NCLBUTTONDOWN messages. To catch the messages you have to subclass the ListView. A mouse click in the GUI outside the ListView and in non-client GUI area (eg. the Titlebar) should also close the control. Mouse clicks in GUI are catched through GUI_EVENT_PRIMARYDOWN messages. Mouse clicks in non-client GUI area are catched through WM_NCLBUTTONDOWN messages by subclassing the GUI. Finish the code A great part of the code is running in message handlers created with GUIRegisterMsg or created by subclassing a window. Lengthy code to open or close the control should not be executed in these message handlers. Instead of a message is sent to the AutoIt main loop where the control is opened or closed. Some of the message handlers are only needed while the control is open. They are created and deleted as part of the control open and close code. In the context of the updates May 26 the $LVS_EX_HEADERDRAGDROP extended style (rearranging columns by dragging Header items with the mouse) is added to all ListViews. See post 20 and 21. A few lines of code are added to better support usage of the keyboard. See image above. The code provides for horizontal scrolling of the ListView to make sure that a subitem (or column) is fully visible when it's selected with left or right arrow. Among other things, the code takes into account rearranging and resizing of columns as well as resizing of the GUI and ListView. A new example EditControlKeyboardTenCols.au3 demonstrates the features. See post 22. A few lines of code is added to handle multiple selections. Multiple selections is enabled in all examples. Pressing the Tab key in the control closes the control. The image shows a DateTimePicker control. Zip file The zip contains three examples with an Edit control, a ComboBox and a DateTimePicker. For each control there are two scripts with and without keyboard support. In the script with keyboard support you can select the current cell in the ListView with the arrow keys and open the control with the Enter (default) or the Space key. You need AutoIt 3.3.10 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.) ListViewEditingCells.7z1 point
-
This is a continuation of Custom drawn TreeViews and ListViews. However, only with respect to listviews. The crucial difference between the new and the old code is that the new code is a complete UDF and therefore much easier to use. Because the UDF is about colors and fonts in listview items and subitems, it's only for listviews in Details or Report view. Main features The UDF supports the following main features. Colors and fonts: 1 Single items/subitems Back colors Fore colors Fonts and styles 2 Colors/fonts for entire columns 3 Alternating colors (entire listview) Alternating colors for rows, columns or both Both default and alternating color can be set Number of rows/columns between color change can be set 4 Custom default colors/font instead of standard default colors/font Custom default back and fore colors can be set for Normal listview items (instead of white and black) Selected listview items (instead of dark blue and white) Unfocused selected items (instead of button face and black) 5 Colors for selected listview items Back and fore colors for selected items when listview has focus Back and fore colors for selected items when listview has not focus Features 1, 2 and 3 cannot be mixed together. 4 and 5 can be mixed with the previous features. 5 extends the functionality of the previous features by adding colors to selected items. 5 cannot be used alone. Listviews: Multiple listviews Native and non-native listviews Native and non-native listview items The UDF can be used with existing listviews WM_NOTIFY message handlers: WM_NOTIFY message handlers can be used completely as usual The UDF can be used with existing WM_NOTIFY message handlers Colors and fonts for single listview items/subitems are stored in an array. The index in this array for a given listview item is stored in ItemParam. Except for this usage of ItemParam nothing in the UDF assumes that listviews or items/subitems are created in a certain way, or that any WM_NOTIFY handlers exists or are designed in a certain way. It should be easy to use the UDF with existing listviews with or without a WM_NOTIFY message handler or other message handlers. WM_NOTIFY message handlers Colors and fonts in listviews are implemented through custom draw notifications in the form of WM_NOTIFY messages. A WM_NOTIFY message handler is needed to implement colors/fonts. If a listview is included in a GUI and a little more than just very basic functionality is wanted, another WM_NOTIFY handler is soon needed to implement this functionality. To register a WM_NOTIFY handler you use the function GUIRegisterMsg. This function can register only one message handler at a time for the same message type. The result of code like this is that only WM_NOTIFY2 message handler is working: GUIRegisterMsg( $WM_NOTIFY, "WM_NOTIFY1" ) ; Register WM_NOTIFY1 GUIRegisterMsg( $WM_NOTIFY, "WM_NOTIFY2" ) ; Register WM_NOTIFY2 (unregisters WM_NOTIFY1) This makes it difficult to implement colors/fonts in a UDF, if you at the same time want to implement advanced functionality in your own code. A solution is to register the WM_NOTIFY message handler, that takes care of custom draw notifications, in a different way. This can be done by a technique called subclassing, which is implemented through the four functions SetWindowSubclass, GetWindowSubclass, RemoveWindowSubclass and DefSubclassProc (coded in WinAPIShellEx.au3). Subclassing Subclassing a window (or control) means to create a message handler for the window, that will receive messages to the window before the original message handler for the window. This section is information on the implementation of a WM_NOTIFY message handler through subclassing: The UDF The UDF is implemented in UDFs\ListViewColorsFonts.au3. This is a list of the most important functions copied from the UDF (around line 200): ; Initiating and exiting ; ---------------------- ; ListViewColorsFonts_Init ; ListViewColorsFonts_Exit ; ; Set colors/fonts for items/subitems ; ----------------------------------- ; ListViewColorsFonts_SetItemColors ; ListViewColorsFonts_SetItemFonts ; ListViewColorsFonts_SetItemColorsFonts ; ; Set colors/fonts for entire listview ; ------------------------------------ ; ListViewColorsFonts_SetColumnColorsFonts ; ListViewColorsFonts_SetAlternatingColors ; ListViewColorsFonts_SetDefaultColorsFonts ; ; Maintenance functions ; --------------------- ; ListViewColorsFonts_Redraw Some of the functions in the complete list in the file are not coded in this version. To use the UDF you first calls ListViewColorsFonts_Init which stores information about the listview and the parent window, and creates the subclass that takes care of the actual drawing of the colors and fonts. Then you call one or more of the ListViewColorsFonts_Set-functions to define the colors and fonts. Depending on the functions you might also need to call ListViewColorsFonts_Redraw. And that's all. Finally you can call ListViewColorsFonts_Exit to remove the subclass before the script exits. If you don't call ListViewColorsFonts_Exit it's called automatically by the UDF. This is the syntax for ListViewColorsFonts_Init and the information about $fColorsFonts flag also copied from ListViewColorsFonts.au3: ; ListViewColorsFonts_Init( $idListView, $fColorsFonts = 7, $iAddRows = 100, $bNative = False ) ; $idListView - Listview control ID or handle ; $fColorsFonts - Specifies options for usage of colors and fonts in the listview. Add required options together. ; 1: Back colors for items/subitems ; Can not be specified separately in this version ; 2: Fore colors for items/subitems ; Can not be specified separately in this version ; 4: Fonts and styles for items/subitems ; Can not be specified separately in this version ; 7: Back and fore colors, fonts and styles ; Flags 1/2/4 are combined in flag 7 in this version ; ; 8: Colors/fonts for entire columns ; ; 16: Alternating row colors (for entire listview) ; 32: Alternating column colors (for entire listview) ; ; 64: Custom default colors and font (for entire listview) ; Custom default back and fore colors can be set for ; - Normal listview items (instead of white and black) ; - Selected listview items (instead of dark blue and white) ; - Unfocused selected listview items (instead of button face and black) ; ; 128: Colors for selected items when listview has focus ; 256: Colors for selected items when listview has not focus The limitations with respect to flags 1, 2 and 4 in this version is only a matter of optimizations. It has nothing to do with features. Drawing of selected items is largely controlled by Windows. A lot of extra code is needed to implement custom colors for selected items through flags 128 and 256. For $fColorsFonts flag is further noted that: ; - Flags 1/2/4 can be combined in a total of seven different ways ; - Flags 1/2/4 (items/subitems), flag 8 (columns) and flags 16/32 (listview) cannot be combined ; - Flag 64 is used to replace the standard default colors/font by custom default colors/font ; Flag 64 can be used alone or in combination with flags 1-32 ; Custom default colors/font must be set before all other colors/fonts ; Flag 64 leads to some restrictions on the features for items/subitems (flags 1/2/4) ; - Flags 128/256 extends the functionality of flags 1-64 by adding colors to selected items ; Flags 128/256 cannot be used alone An array $aListViewColorsFontsInfo is used to store information about the listview, the parent window and the usage of colors/fonts in the listview. For flags 1/2/4 about single items/subitems another array $aListViewColorsFonts is used to store the colors and fonts for the items and subitems. The number of columns in this array depends on whether the flags 128/256 are set or not. The first 160 lines in the UDF contains information about these arrays. For flags 1/2/4 ItemParam field in the listview is used to store the zero based row index in $aListViewColorsFonts for a given listview item. For native listview items created with GUICtrlCreateListViewItem the existing value of ItemParam (control ID) is used as index in an intermediate array $aListViewColorsFonts_Index, and $aListViewColorsFonts_Index holds the index in $aListViewColorsFonts stored as index+1. For non-native listview items the index in $aListViewColorsFonts is stored in ItemParam as -index-20. For non-native listview items an existing value of ItemParam is overwritten. The best way to add colors and fonts to listviews is to put each listview in its own child window. The child window should not contain any other controls, and it should have the same size as the listview. However, this is not a requirement. See the UDF for documentation of the other functions. The implementation of the functions starts in line 230 and onwards. The UDF also contains a group of internal functions. Among other the subclass callback functions to draw the colors and fonts in response to NM_CUSTOMDRAW notifications from the listview. So far the UDF contains seven callback functions which starts around line 2100 and runs over the next 1300 lines nearly to the bottom of the file. The code This section is about some code details related partly to the subclass callback functions and partly to drawing of selected items. Subclass callback functions: Drawing of selected items: In the current version of the UDF the callback function that is implemented to draw single items/subitems ($fColorsFonts = 1/2/4) is the function that can handle all features ($fColorsFonts = 1+2+4 = 7). If only a part of the features is needed, it's possible to create smaller and faster functions, which only implements this part of the features. These functions (six functions in total) are postponed to next version. Features A few comments on the features. The main features in terms of colors and fonts are (a repeat of the list in top of post): 1 Single items/subitems 2 Colors/fonts for entire columns 3 Alternating colors (entire listview) 4 Custom default colors/font instead of standard default colors/font 5 Colors for selected listview items 1, 2 and 3 are features for different kind of elements in the listview and cannot be mixed together. 4 can be used either as an independent feature or mixed with 1, 2 or 3. 5 cannot be used as an independent feature but can only be used together with 1, 2, 3 or 4. 5 extends the functionality of these features by adding colors to selected items. When features 1, 4 and 5 are mixed together, it may look as shown in the following illustrations (screen dumps of examples 3.1 and 4.1 in folder \Examples\5) Selected items\). The first illustration shows how it looks when colors for single items/subitems are mixed with colors for selected items: In the upper picture rows 3-6 are provided with back and fore colors. All subitems in row 3 and 4. Only a few subitems in row 5 and 6. The rows are normal (unselected) rows. In the middle picture rows 2-7 are selected and the listview has focus. Rows 3-6 are also provided with back and fore colors for selected items. In the lower picture rows 2-7 are selected but the listview has not focus. Rows 3-6 are also provided with back and fore colors for selected but unfocused items. In the second illustration the standard default colors are replace with custom default colors. The standard default back and fore colors are: Normal (unselected) items: White and black Selected items in focused listview: Dark blue and white Selected items in unfocused listview: Button face and black These custom default colors are used in the illustration: Normal (unselected) items: Light green and brown Selected items in focused listview: Shiny green (chartreuse) and black Selected items in unfocused listview: Dark green and black Examples Two folders with examples is included in the zip below. The first folder is named Examples and contains examples about the usage of the functions in the UDF. The second folder is named UDF topics and contains examples related to the implementation of the UDF. It's about the use of the subclassing technique as a substitute for a WM_NOTIFY message handler. Particularly about the message flow and performance issues. These examples are addressed in next section. The Examples folder contains these subfolders and files: 0) UDF examples\ - The small examples from the documentation of the functions in the UDF 1) Items-subitems\ - Colors and fonts for single items/subitems 2) Entire columns\ - Colors and fonts for entire columns 3) Alternating colors\ - Alternating row/column colors in an entire listview 4) Custom defaults\ - Replace standard default colors/font with custom defaults 5) Selected items\ - Colors for selected items when listview has focus and has not focus 6) Help file examples\ - Shows how to add colors to a few examples from AutoIt Help file 7) Original examples\ - An implementation of the examples in the old thread with this UDF Listview templates\ - A collection of listview templates ready to add colors/fonts Features demo.au3 - A brief demonstration of all features No colors or fonts.au3 - Reference example All examples runs on Windows XP and later without any performance issues. Folder 1 - 5 demonstrates the five main color/font features listed in top of post. In most of the subfolders you can find a _Readme.txt file with a brief description of the examples. Multiple selections is enabled in most listviews. A few examples will not pass an Au3Check. In particular the examples in subfolder 1 and 2 and the examples in UDF topics folder (see next section) were used to test the subclassing technique as a substitute for a WM_NOTIFY message handler. More information about some of the examples: Examples\0) UDF examples\0) ListViewColorsFonts_Init\Example 1.au3: #include <GUIConstantsEx.au3> #include "..\..\..\UDFs\ListViewColorsFonts.au3" #include "..\..\..\UDFs\GuiListViewEx.au3" Opt( "MustDeclareVars", 1 ) Example() Func Example() ; Create GUI Local $hGui = GUICreate( "ListViewColorsFonts_Init\Example 1", 420, 200, -1, -1, $GUI_SS_DEFAULT_GUI-$WS_MINIMIZEBOX ) ; Create ListView Local $idListView = GUICtrlCreateListView( "", 10, 10, 400, 180, $GUI_SS_DEFAULT_LISTVIEW-$LVS_SINGLESEL, $WS_EX_CLIENTEDGE ) _GUICtrlListView_SetExtendedListViewStyle( $idListView, $LVS_EX_DOUBLEBUFFER+$LVS_EX_FULLROWSELECT ) Local $hListView = GUICtrlGetHandle( $idListView ) ; Reduces flicker ; Add columns to ListView _GUICtrlListView_AddColumn( $idListView, "Column 1", 94 ) _GUICtrlListView_AddColumn( $idListView, "Column 2", 94 ) _GUICtrlListView_AddColumn( $idListView, "Column 3", 94 ) _GUICtrlListView_AddColumn( $idListView, "Column 4", 94 ) ; Fill ListView Local $iItems = 100 For $i = 0 To $iItems - 1 GUICtrlCreateListViewItem( $i & "/Column 1|" & $i & "/Column 2|" & $i & "/Column 3|" & $i & "/Column 4", $idListView ) Next ; Perform initializations to add colors/fonts to single items/subitems ListViewColorsFonts_Init( $idListView, 7 ) ; $fColorsFonts = 7, ( $iAddRows = 100, $bNative = False ) ; Set a green back color for an entire item and a yellow back color for a single cell ListViewColorsFonts_SetItemColors( $idListView, 3, -1, 0xCCFFCC ) ; Green back color for entire item ListViewColorsFonts_SetItemColors( $idListView, 3, 2, 0xFFFFCC ) ; Yellow back color for cell 2 in item ; Force an update of local variables in drawing function ListViewColorsFonts_Redraw( $idListView ) ; Adjust height of GUI and ListView to fit ten rows Local $iLvHeight = _GUICtrlListView_GetHeightToFitRows( $hListView, 10 ) WinMove( $hGui, "", Default, Default, Default, WinGetPos( $hGui )[3] - WinGetClientSize( $hGui )[1] + $iLvHeight + 20 ) WinMove( $hListView, "", Default, Default, Default, $iLvHeight ) ; Show GUI GUISetState( @SW_SHOW ) ; Message loop While 1 Switch GUIGetMsg() Case $GUI_EVENT_CLOSE ExitLoop EndSwitch WEnd ; Delete color/font info for listview ListViewColorsFonts_Exit( $idListView ) GUIDelete() EndFunc UDF topics The examples in UDF topics folder is about the use of subclassing as a substitute for a WM_NOTIFY message handler. Particularly about the message flow and performance issues. These examples illustrates some of the issues, that was discussed in the Subclassing section above, with code. The UDF topics folder contains these subfolders: 1) Subclassing\ - Creating listviews in GUI or child windows? 2) Performance\ - How many listviews can you create in GUI? More information about the examples: Next version In The code section above is already mentioned a number of subclass callback functions which are postponed to next version. The purpose of these additional functions is merely to optimize the code in terms of speed. A number of ListViewColorsFonts_Get-functions to complement the corresponding ListViewColorsFonts_Set-functions are also deferred to next version. For single items/subitems ($fColorsFonts = 1/2/4) colors and fonts are stored in $aListViewColorsFonts array which again is stored in $aListViewColorsFontsInfo. The three functions ListViewColorsFonts_SetItemColors / SetItemFonts / SetItemColorsFonts are used to update $aListViewColorsFonts item by item or subitem by subitem. It would be much faster to update $aListViewColorsFonts directly. Two functions are needed to get a copy of the array from $aListViewColorsFontsInfo and store the array again after the updates. And there is also a need for a couple of examples to illustrate the technique. Examples to dynamically update colors and fonts are missing in this version. Perhaps there is also a need for a few functions to support dynamically updates. For non-native listviews created with _GUICtrlListView_Create it's not uncommon to use ItemParam to store a user defined value. If index in $aListViewColorsFonts is stored in ItemParam, it's no longer possible to use ItemParam for such purposes. A couple of functions to give the user an opportunity to still be able to store a user defined value would be nice. Several global variables are defined in this version. They will be removed in the next version except for a few variables which probably will need to be global in performance terms. If there will be reported any issues or problems in this version, they of course also need to be addressed. The next version should be ready in 2-3 months, and it should also be the final version. Zip file The zip is structured in this way Examples\ UDF topics\ UDFs\ ListViewColorsFonts.au3 GuiImageListEx.au3 GuiListViewEx.au3 NamedColors.au3 OtherColors.au3 NamedColors.au3 contains global constants of named colors copied from .NET Framework Colors Class. You need AutoIt 3.3.10 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.) ListViewColorsFonts.7z1 point
-
This project implements data display functions based on _ArrayDisplay and _ArrayDisplayEx (virtual listview). Four functions are planned and maybe there’ll also come a fifth function. First post contains documentation common to all functions. In order to avoid first post being too long, posts 2 - 5 are reserved for documentation that's specific to the four planned functions. The first two functions _ArrayDisplayEx and CSVfileDisplay are presented below. The other functions will be presented in the coming weeks. Data display functions: _ArrayDisplayEx - Displays a 1D or 2D array in a virtual ListView CSVfileDisplay - Displays a CSV file in a virtual ListView _SQLite_Display - Displays data from a table, view or SELECT statement in a virtual ListView SafeArrayDisplay - Displays a 1D/2D safearray of variants (equivalent to an AutoIt array) in a virtual ListView The functions are mainly intended for large amounts of data with a large number of rows. The GUI and listview are implemented for this purpose. Thus, the left column in the listview is a row-number column. This is convenient when there are many rows. Through an input control at bottom of the GUI, you can focus on a specific row. When there are many rows it's difficult to scroll to a specific row with the mouse. The primary purpose of the functions is testing and debugging. Secondary to display data for end users. Therefore, features that are directly available in the function definition through parameters and flags are reduced to a minimum, while additional features that are especially interesting for end users must be specified in a single parameter which is the last parameter in the function definition. The definition of _ArrayDisplayEx looks like this: ; Displays a 1D or 2D array in a virtual ListView Func _ArrayDisplayEx( _ $aArray, _ ; 1D/2D array eg. StringSplit("Mo,Tu,We,Th,Fr,Sa,Su", ",") $sTitle = "", _ ; GUI title bar text, default title is set to "ArrayDisplayEx" $sHeader = "", _ ; ListView header column names, default is "Col0|Col1|Col2|...|ColN" $iFlags = 0x0000, _ ; Set additional options through flag values $aFeatures = "" ) ; 2D array of feature type/info pairs All functions uses a virtual listview to display data. A normal listview has two main features: Data storage and data display. A virtual listview has only one main feature: Data display. Data is stored in a data source outside the listview. Because data does not have to be inserted into the rows of a virtual listview, the listview shows up instantly. The number of rows is limited only to the data source. Data display in the virtual listview is implemented through subclassing. This means that the code will not interfere with WM_NOTIFY message handlers in your own code. And because there are a lot of messages involved in updating the cell texts in a virtual listview, the subclassing technique is also performance optimizing. The first parameter in the function definition is the data source. The data source is the main difference between the display functions. Depending on the function more than one parameter can be used to support the data source. After one or more data source parameters follows title, header and flag parameters. The last parameter is an array of additional features. It's discussed in a section below. These four parameters are common to all display functions. Flag values ; $iFlags values ; Add required values together ; 0x0000 => Left aligned text ; 0x0002 => Right aligned text ; 0x0004 => Centered text ; 0x0008 => Verbose mode ; 0x0010 => Half-height ListView ; 0x0020 => No grid lines in ListView ; 0x0040 => No bottom controls Not all flags can be used in all functions. See documentation for the actual function just below the function definition. Embedded controls (2018-04-14) Instead of creating the listview in a stand-alone main GUI, it's possible to create the listview in a child window of a user GUI, thereby creating an embedded control. A separate function is used to create the embedded control. This is the definition for _ArrayDisplayCtrl (the embedded control corresponding to _ArrayDisplayEx): ; Displays a 1D or 2D array in a virtual ListView as an embedded GUI control Func _ArrayDisplayCtrl( $hUserGui, $x, $y, $w, $h, _ $aArray, _ ; 1D/2D array eg. StringSplit("Mo,Tu,We,Th,Fr,Sa,Su", ",") $sTitle = "", _ ; GUI title bar text, default title is set to "ArrayDisplayEx" ; <<<< Not used >>>> $sHeader = "", _ ; ListView header column names, default is "Col0|Col1|Col2|...|ColN" $iFlags = 0x0000, _ ; Set additional options through flag values $aFeatures = "" ) ; 2D array of feature type/info pairs The embedded control is created with the code in Common\4)CreateAutoItGUICtrl.au3. Handle messages Messages from the embedded control must be identified in the user GUI. For this purpose, _ArrayDisplayCtrl (the embedded control corresponding to _ArrayDisplayEx) returns an array of information. The information and usage of the information is shown here through a part of the code in Examples\ArrayDisplayCtrl\1) Simple.au3: ; Create GUI Local $hGui = GUICreate( "Simple", 820, 660 ) ; Create ArrayDisplay control Local $aDisplay = _ArrayDisplayCtrl( $hGui, 10, 10, 800, 600, $aArray ) ; Get info about ArrayDisplay control Local $hDisplay = $aDisplay[0] ; Elem 0: Child window handle to show and resize window Local $idDisplay_FirstCtrl = $aDisplay[1] ; Elem 1: First controlID in child window (ListView control) Local $idDisplay_LastCtrl = $aDisplay[2] ; Elem 2: Last controlID in child window (last bottom ctrl) Local $hDisplay_MsgHandler = $aDisplay[3] ; Elem 3: Message handler for AutoIt events in child window Local $iDisplay_MsgHandlerIdx = $aDisplay[4] ; Elem 4: Message handler index GUISetState() GUISetState( @SW_SHOWNOACTIVATE, $hDisplay ) ; Show ArrayDisplay control Local $iMsg While 1 $iMsg = GUIGetMsg() Switch $iMsg ; Handle messages for AutoIt events in ArrayDisplay control Case $idDisplay_FirstCtrl To $idDisplay_LastCtrl $hDisplay_MsgHandler( $iMsg, $iDisplay_MsgHandlerIdx ) You can use a shorter notation this way: ; Create GUI Local $hGui = GUICreate( "Simple", 820, 660 ) ; Create ArrayDisplay control Local $aDisplay = _ArrayDisplayCtrl( $hGui, 10, 10, 800, 600, $aArray ) GUISetState() GUISetState( @SW_SHOWNOACTIVATE, $aDisplay[0] ) ; Show ArrayDisplay control Local $iMsg While 1 $iMsg = GUIGetMsg() Switch $iMsg ; Handle messages for AutoIt events in ArrayDisplay control Case $aDisplay[1] To $aDisplay[2] $aDisplay[3]( $iMsg, $aDisplay[4] ) As can be seen from the two Case statements, it's only tested if a message corresponds to a control in the range from the first controlId to the last controlId. A prerequisite for this to work is that the controlIds is an uninterrupted continuous sequence of integers. This is tested at the bottom of Common\4)CreateAutoItGUICtrl.au3. If the requirement is not met, @error is set to 5. The issue is demonstrated in an example: "a) Demonstration of @error = 5.au3". The message handler function $hDisplay_MsgHandler or $aDisplay[3] is implemented in Functions\ArrayDisplayEx\Internal\9)MessageLoopCtrl.au3 (for _ArrayDisplayCtrl). What happens if you forget to implement message handler code for the embedded control in your user GUI? Nothing. The embedded control will work anyway. However, you do not get any response to events that generate messages in the embedded control. Cleanup and release memory If the script with the embedded display function exits when the GUI closes, you do not have to worry about cleanup. It's done automatically by AutoIt. However, if you want to run more code after the GUI is closed, it may be useful to clean up and release memory used by the display function. Especially if it's a large data source. To release memory, take into account 3 types of variables: Variables created in your own script Variables passed to display function and stored as globals Variables passed to display function and stored as statics In order to release memory used by the last two types of variables, a new element has been added to the array returned from the display function (illustrated for _ArrayDisplayCtrl): $aDisplay[4] = $iIdx: Index in global array $aDataDisplay_Info (existing element) $aDisplay[5] = ArrayDisplay_Cleanup(): Performs cleanup, takes $iIdx and $hNotifyFunc as input parameters ArrayDisplay_Cleanup() that performs cleanup and releases memory is coded this way: ; Cleanup and release memory Func ArrayDisplay_Cleanup( $iIdx ) ; Remove $WM_COMMAND and $WM_SYSCOMMAND event handler If $aDataDisplay_Info[$iIdx][15] = 3 Then _ ; Remove WM_COMMAND, WM_SYSCOMMAND message handler (DataDisplayMult_MsgHandler) used to handle events from multiple concurrent and responsive GUIs DllCall( "comctl32.dll", "bool", "RemoveWindowSubclass", "hwnd", $aDataDisplay_Info[$iIdx][21], "ptr", $aDataDisplay_Info[$iIdx][40], "uint_ptr", $iIdx ) ; WM_COMMAND, WM_SYSCOMMAND ; Remove $WM_COMMAND event handler If $aDataDisplay_Info[$iIdx][15] = 2 Then _ ; Remove WM_COMMAND message handler (DataDisplayCtrl_WM_COMMAND) used to handle events from embedded GUI controls DllCall( "comctl32.dll", "bool", "RemoveWindowSubclass", "hwnd", $aDataDisplay_Info[$iIdx][21], "ptr", $aDataDisplay_Info[$iIdx][18], "uint_ptr", $iIdx ) ; WM_COMMAND ; Remove WM_NOTIFY message handler used to fill the virtual listview DllCall( "comctl32.dll", "bool", "RemoveWindowSubclass", "hwnd", $aDataDisplay_Info[$iIdx][21], "ptr", $aDataDisplay_Info[$iIdx][2], "uint_ptr", $iIdx ) ; WM_NOTIFY ; Delete ListView header background color resources If IsArray( $aDataDisplay_Info[$iIdx][16] ) Then Local $aTmp = $aDataDisplay_Info[$iIdx][16] ; [ $hListView, $pHeaderColor, $oHdr_Colors_Dict ] ; Remove WM_NOTIFY message handler (DataDisplay_HeaderColor) used to draw colors in listview header items DllCall( "comctl32.dll", "bool", "RemoveWindowSubclass", "hwnd", $aTmp[0], "ptr", $aTmp[1], "uint_ptr", 9999 ) For $hBrush In $aTmp[2].Items() DllCall( "gdi32.dll", "bool", "DeleteObject", "handle", $hBrush ) ; _WinAPI_DeleteObject Next $aDataDisplay_Info[$iIdx][16] = 0 EndIf ; Delete AutoIt GUI If $aDataDisplay_Info[$iIdx][15] <> 2 Then _ GUIDelete( $aDataDisplay_Info[$iIdx][21] ) ; Release memory $aDataDisplay_Info[$iIdx][0] = 0 $aDataDisplay_Info[$iIdx][3] = 0 $aDataDisplay_Info[$iIdx][4] = 0 $aDataDisplay_Info[$iIdx][5] = 0 $aDataDisplay_Info[$iIdx][6] = 0 ; Release local static memory $aDataDisplay_Info[$iIdx][1]( 0, 0x004E, 0, 0, $iIdx, 0 ) ; 0x004E = $WM_NOTIFY If $aDataDisplay_Info[$iIdx][15] = 2 Then DataDisplayCtrl_MsgHandler( 99999, $iIdx ) $aDataDisplay_Info[$iIdx][10] = 0 EndIf ; Release row in $aDataDisplay_Info $aDataDisplay_Info[$iIdx][20] = 0 ; $iIdx EndFunc And it's called this way: ; Cleanup and release memory $aDisplay[5]( $aDisplay[4] ) A new example, "b) Cleanup and release memory.au3", demonstrates the technique. Embedded control functions: _ArrayDisplayCtrl - Displays a 1D or 2D array in a virtual ListView as an embedded GUI control CSVfileDisplayCtrl - Displays a CSV file in a virtual ListView as an embedded GUI control _SQLite_DisplayCtrl - Displays data from a table, view or SELECT statement in a virtual ListView as an embedded GUI control SafeArrayDisplayCtrl - Displays a 1D/2D safearray of variants (equivalent to an AutoIt array) in a virtual ListView as an embedded GUI control Four new folders are created under Examples\ with similar examples. Multiple GUIs (2018-05-21) Both in the official _ArrayDisplay and in the data display functions here, it's possible to open multiple GUIs at the same time via user supplied functions and "Run User Func" buttons. An unfortunate consequence of this technique is that the message loop in the last created GUI blocks the message loop in a previously created GUI. This means that only the last created GUI is responsive to AutoIt messages eg. mouse clicks (all listviews are, however, fully functional because they are not depending on any AutoIt messages). As demonstrated in Unblocking a Blocked Message Handler and in Way to close AU3 Script with a button? it's possible to detect Windows messages (not AutoIt messages) in such blocked message loops by using window subclassing or GUIRegisterMsg functions. In case of _ArrayDisplay and the data display functions, it's enough to detect $WM_COMMAND messages for button click events and $WM_SYSCOMMAND messages for window close events. In the data display functions $WM_COMMAND messages are also used to detect input control events and keyboard accelerator events. By using these methods, four new data display functions are implemented with a new message handler, so that multiple simultaneous open GUIs are all responsive: _ArrayDisplayMult - Displays a 1D or 2D array in a virtual ListView, support for multiple GUIs CSVfileDisplayMult - Displays a CSV file in a virtual ListView, support for multiple GUIs _SQLite_DisplayMult - Displays data from a table, view or SELECT statement in a virtual ListView, support for multiple GUIs SafeArrayDisplayMult - Displays a 1D/2D safearray of variants (equivalent to an AutoIt array) in a virtual ListView, support for multiple GUIs Four new folders are created under Examples\ with similar examples. Note that at the top of Common\0)GlobalArray.au3, the number of simultaneous open data display GUIs is limited to 10: $aDataDisplay_Info[0][21] = 10 ; Max number of data display GUIs You can change the number to the value you want. Additional features Only basic functionality used for testing and debugging is implemented directly in the display functions. It's possible to use a wide range of additional features that are especially interesting when the display functions are used to display data for end users. Usually only a few features are used at a time. To avoid adding a lot of parameters to each display function of which only a few are used, additional features must be specified through a single $aFeatures parameter, which is the last parameter in the function definition. Also in order to avoid adding a lot of extra code to the functions that are rarely used, most of the features are implemented in separate include files. These files must be included in order to use the features. $aFeatures parameter is checked for errors under function initializing. In most cases, an error just means that the feature is skipped. Only in case of serious mistakes eg. a missing include file the function will return with an error code in @error. If verbose mode is turned on ($iFlags = 8), the error will be displayed in a MsgBox. The following additional features can be used: Features implemented through Common\ files (always usable) End user features: "ColAlign" - Column alignment "ColWidthMin" - Min. column width "ColWidthMax" - Max. column width "BackColor" - Listview background color "HdrColors" - Listview header background colors "UserFunc" - User supplied function Features implemented through include files End user features: Include file: "ColFormats" - Column text formats <Display function>_ColumnFormats.au3 "ColColors" - Column background colors <Display function>_ColumnColors.au3 "SortRows" - Sort rows in data source by index <Display function>_SortFuncs.au3 "SortCols" - Sort columns in data source by index <Display function>_SortFuncs.au3 "SortByCols" - Sort rows by multiple columns <Display function>_SortFuncs.au3 Debugging features: "DataTypes" - Data types info <Display function>_DataTypesInfo.au3 Not all features can be used in all functions. See documentation for the actual function just below the function definition. See HelpFiles\DisplayFeatures.txt in zip-file for documentation of each feature. See Examples\ for examples. Missing features Compared to the official _ArrayDisplay and the old version of _ArrayDisplayEx some features are omitted in the new functions. It's not possible to specify a data range to only display a small section of data. But rows and columns can be sorted by row and column indices which can replace the range feature. This is demonstrated in examples. Data copying that could be performed through two GUI buttons is omitted. Because the listviews are virtual listviews, potentially millions of cells can be selected and copied. Copying such large amounts of data can take a long time. Since data may in any case be copied directly from the data source, the copying functionality is omitted to avoid long-term copying. It's also not possible to change rows and columns. No transpose functionality. Function examples The zip-file is organized this way: DataDisplay\ - Top folder Common\ - Code common to all functions Examples\ - Examples for each function Functions\ - Implements the functions HelpFiles\ - Docu of additional features Resources\ - Resources used in examples Common\ and Functions\ contains all the code used to implement the display functions. Common\ is used to implement functionality and features. Functions\ is further divided into subfolders for each display function. The subfolders contains WM_NOTIFY message handlers that handles LVN_GETDISPINFOW, LVN_ODCACHEHINT, and NM_CUSTOMDRAW notifications, and displays data in the virtual list view. These functions are critical in terms of performance. Examples\ is also divided into subfolders for each display function. For each function the features are demonstrated one by one. If more parameters are used in relation to the data source, the utilization of the parameters is demonstrated in "Examples\<Display function>\0) Data source\". For most examples the data source is created on the fly. For this purpose, a few small UDFs are used. These UDFs are stored in Resources\. Using functions To use a display function in your own project copy the entire DataDisplay\ to the project folder. You can rename DataDisplay to Display or similar if you want a shorter name. You can delete Examples\, HelpFiles\ and Resources\. You can also delete display functions in Functions\ that you're not using. Then include the function you need in your code. Usage of the display functions is demonstrated in "Examples\<Display function>\3) Using function\". Here the code in "Examples\ArrayDisplayEx\3) Using function\My Project\Script1.au3": #AutoIt3Wrapper_Au3Check_Parameters=-d -w- 1 -w 2 -w 3 -w 4 -w 5 -w 6 #include "Display\Functions\ArrayDisplayEx\ArrayDisplayEx.au3" Opt( "MustDeclareVars", 1 ) Example() Func Example() Local $iRows = 10000, $iCols = 10 Local $aArray[$iRows][$iCols] For $i = 0 To $iRows - 1 For $j = 0 To $iCols - 1 $aArray[$i][$j] = $i & "/" & $j Next Next _ArrayDisplayEx( $aArray ) EndFunc And in "Examples\ArrayDisplayEx\3) Using function\My Project\Script2.au3": #AutoIt3Wrapper_Au3Check_Parameters=-d -w- 1 -w 2 -w 3 -w 4 -w 5 -w 6 #include "Display\Display.au3" Opt( "MustDeclareVars", 1 ) Example() Func Example() Local $iRows = 10000, $iCols = 10 Local $aArray[$iRows][$iCols] For $i = 0 To $iRows - 1 For $j = 0 To $iCols - 1 $aArray[$i][$j] = $i & "/" & $j Next Next _ArrayDisplayEx( $aArray, "", "", 0, GetDisplayFeatures() ) EndFunc Display\Display.au3: #include-once #include "Functions\ArrayDisplayEx\ArrayDisplayEx.au3" #include "Functions\ArrayDisplayEx\ArrayDisplayEx_ColumnColors.au3" Func GetDisplayFeatures() ; ArrayDisplayEx features Local $aAlignment = [ [ -1, "R" ], [ 0, "C" ], [ 1, "L" ] ] Local $aColColors = [ [ 1, 0xCCFFCC ], [ 3, 0xFFFFCC ] ] Local $aFeatures = [ [ "ColAlign", $aAlignment ], _ [ "ColColors", $aColColors ] ] Return $aFeatures EndFunc v3.3.10.2 If you're using this UDF in AutoIt v3.3.10.2 you should be aware of an Au3Check issue as described in this post. Zip-file The organization of the zip-file is described in the section above. You need AutoIt 3.3.10 or later. Tested on Windows 10, Windows 7 and Windows XP. Comments are welcome. Let me know if there are any issues. DataDisplay.7z1 point
-
Checkboxes If LVS_EX_CHECKBOXES extended style is applied to a listview, two images are automatically added to the state image list: An unchecked checkbox (index 0) and a checked checkbox (index 1). You can get a handle for the state image list with $hStateImageList = _GUICtrlListView_GetImageList( $hListView, 2 ) ; 2 = Image list with state images Then you can set the state image list as a normal small icon image list: _GUICtrlListView_SetImageList( $hListView, $hStateImageList, 1 ) ; 1 = Image list with small icons If you apply this code line to all listview items the result is two checkboxes in first column: _GUICtrlListView_SetItemImage( $hListView, $iItem, 0 ) ; Unchecked checkbox (index 0) for $iItem Use this code line to add subitem checkboxes (requires LVS_EX_SUBITEMIMAGES extended style) to fourth column: _GUICtrlListView_SetItemImage( $hListView, $iItem, 0, 3 ) ; 3 is the zero based index of fourth column Another consequence of LVS_EX_CHECKBOXES extended style is that the image is automatically switched between the unchecked and checked ckeckbox when you click the icon. You have to implement this functionality yourself for the checkboxes added through the normal image list. This is easily done by responding to NM_CLICK events in a WM_NOTIFY message handler: Case $NM_CLICK Local $aHit = _GUICtrlListView_SubItemHitTest( $hListView ) If $aHit[6] Then ; On item? If $aHit[3] Then ; On icon? If $aHit[1] = 0 Or $aHit[1] = 3 Then ; On subitem 0 or 3? Local $iImage = _GUICtrlListView_GetItemImage( $hListView, $aHit[0], $aHit[1] ) ; Image index 0 or 1 _GUICtrlListView_SetItemImage( $hListView, $aHit[0], $iImage ? 0 : 1, $aHit[1] ) ; Switch index value EndIf ; $iItem $iImage $iSubItem EndIf EndIf The above is demonstrated in example 1) Subitem checkboxes.au3. If you don't want checkboxes for all of the listview items example 2) Remove some checkboxes.au3 shows how to remove some of the checkboxes. This is a picture of example 2: In example 1 and 2 the selected and focused states are removed from the listview items. Overlay icons In this picture of example 3) Overlay icons.au3 you can see cyan, green and yellow overlay icons on top of the original item icons: Overlay icons are stored in the small and large image lists. The function ImageList_SetOverlayImage implemented in GuiImageListEx.au3 tells the image list that this is a special image that is used as an overlay icon. Overlay icons must be stored among the first 15 images in the image list. To apply an overlay icon to a listview item the one based image index of the overlay icon must be stored in bits 8 - 11 in the state member of the LVITEM structure. Because 4 bits are used to store the image index you can only use 15 overlay icons. If all 4 bits are zero, it means that there is no overlay icon. Use these commands to add cyan, green and yellow overlay icons as the first three images in the image list: _GUIImageList_AddIcon( $hImageList, "icons\Cyan.ico" ) ; Index 0 _GUIImageList_AddIcon( $hImageList, "icons\Green.ico" ) ; Index 1 _GUIImageList_AddIcon( $hImageList, "icons\Yellow.ico" ) ; Index 2 Tell the imagelist that this is overlay icons: ImageList_SetOverlayImage( $hImageList, 0, 1 ) ; First overlay icon ImageList_SetOverlayImage( $hImageList, 1, 2 ) ; Second overlay icon ImageList_SetOverlayImage( $hImageList, 2, 3 ) ; Third overlay icon Add overlay icons to listview items A, B, C (256 = 2^8 is the value of bit 8): _GUICtrlListView_SetItemState( $hListView, $iItemA, 1 * 256 , $LVIS_OVERLAYMASK ) ; First overlay icon, cyan _GUICtrlListView_SetItemState( $hListView, $iItemB, 2 * 256 , $LVIS_OVERLAYMASK ) ; Second overlay icon, green _GUICtrlListView_SetItemState( $hListView, $iItemC, 3 * 256 , $LVIS_OVERLAYMASK ) ; Third overlay icon, yellow _GUICtrlListView_SetItemState( $hListView, $iItemD, 0 * 256 , $LVIS_OVERLAYMASK ) ; Remove an overlay icon State images If you want to use your own custom state images eg. green, yellow and red images (to signal ok, warning and error) instead of checkboxes, apply the LVS_EX_CHECKBOXES extended style to the listview, get a handle to the state image list, delete the images of the unchecked (index 0) and checked (index 1) checkboxes and add the green, yellow and red images to the state image list. Add custom state images to listview items A, B, C: _GUICtrlListView_SetItemStateImage( $hListView, $iItemA, 1 ) ; First state image, green _GUICtrlListView_SetItemStateImage( $hListView, $iItemB, 2 ) ; Second state image, yellow _GUICtrlListView_SetItemStateImage( $hListView, $iItemC, 3 ) ; Third state image, red _GUICtrlListView_SetItemStateImage( $hListView, $iItemD, 0 ) ; Remove a state image If you click a green state image, the image switches to yellow. If you click a yellow state image, it switches to red. If you click a red state image, it switches to green again. No code is needed for the image switching. It's a consequence of the LVS_EX_CHECKBOXES extended style. This is demonstrated in example 4) State images.au3. CheckboxesAndIcons.7z icons\ - Overlay icons 1) Subitem checkboxes.au3 2) Remove some checkboxes.au3 3) Overlay icons.au3 4) State images.au3 GuiImageListEx.au3 GuiListViewEx.au3 You need AutoIt 3.3.10 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.) CheckboxesAndIcons.7z1 point
-
_ArrayDisplayEx This is copied from the top of ArrayDisplayEx.au3: ; Displays a 1D or 2D array in a virtual ListView Func _ArrayDisplayEx( _ $aArray, _ ; 1D/2D array eg. StringSplit("Mo,Tu,We,Th,Fr,Sa,Su", ",") $sTitle = "", _ ; GUI title bar text, default title is set to "ArrayDisplayEx" $sHeader = "", _ ; ListView header column names, default is "Col0|Col1|Col2|...|ColN" $iFlags = 0x0000, _ ; Set additional options through flag values $aFeatures = "" ) ; 2D array of feature type/info pairs ; $iFlags values ; Add required values together ; 0x0000 => Left aligned text ; 0x0002 => Right aligned text ; 0x0004 => Centered text ; 0x0008 => Verbose mode ; 0x0010 => Half-height ListView ; 0x0020 => No grid lines in ListView ; $aFeatures parameter ; Features available in _ArrayDisplayEx: ; ; Features implemented through Common\ files (always usable): ; "ColAlign" => Column alignment ; "ColWidthMin" => Min. column width ; "ColWidthMax" => Max. column width ; "BackColor" => Listview background color ; "HdrColors" => Listview header background colors ; "UserFunc" => User supplied function ; ; Features implemented through include files ; End user features: ; Include file: ; "ColFormats" => Column text formats ; <Display function>_ColumnFormats.au3 ; "ColColors" => Column background colors ; <Display function>_ColumnColors.au3 ; "SortRows" => Sort rows in data source by index ; <Display function>_SortFuncs.au3 ; "SortCols" => Sort columns in data source by index ; <Display function>_SortFuncs.au3 ; "SortByCols" => Sort rows by multiple columns ; <Display function>_SortFuncs.au3 ; ; Debugging features: ; Include file: ; "DataTypes" => Data types info ; <Display function>_DataTypesInfo.au3 ; ; See DisplayFeatures.txt for docu of features ; Error codes in @error ; 1 => No array variable passed to function ; 2 => Larger than 2D array passed to function ; 3 => Missing include file ; 4 => Unsupported feature ; 6 => Too many GUIs Usage of additional features is demonstrated in Examples\ArrayDisplayEx\1) Single features\. How to use _ArrayDisplayEx in your own project is demonstrated in Examples\ArrayDisplayEx\3) Using function\.1 point
-
From time to time questions arise about listviews with multi-line headers or headers with increased height. Eg. these two questions: Multi-line listview column headings and Listview header height. To use a multi-line header in a listview the height of the header must be increased to make room for multiple lines, and it must be possible to display multiple text lines in the header items. Increase height of header control Because the header control is contained in a listview, the height of the header must be increased in such a way that the listview will be aware of the increased height. An easy and common method of increasing the height is to define a text font for the header with a suitable height. Increasing the height in this way requires that the header is not provided with any themes. However, it is possible to restore themes after the height is increased. A better but slightly more cumbersome method is based on HDM_LAYOUT messages. A HDM_LAYOUT message (implemented in _GUICtrlHeader_Layout) is used to retrieve information about the size of a header control. To use this message to define the height, the header control must be subclassed. The HDM_LAYOUT method is preferred in the examples. Two examples with the font height method are added in "Using font height" folder. Whichever method is chosen, the header height must be increased before rows are added to the listview. Subclassing controls After Windows XP the recommended way to subclass controls is to use the four functions SetWindowSubclass, GetWindowSubclass, RemoveWindowSubclass and DefSubclassProc (all implemented in WinAPIShellEx.au3). These functions are used in the examples. And they are much easier to use than the old SetWindowLong (_WinAPI_SetWindowLong) function. Since we are subclassing a header control contained in a listview this issue must be taking into account. I have verified that this is also an issue for _WinAPI_DefSubclassProc. The solution is the same as the solution in the link: ;Return _WinAPI_DefSubclassProc( ... ) ; Not so good Return DllCall( "comctl32.dll", "lresult", "DefSubclassProc", ... )[0] ; Much better Responding to HDM_LAYOUT messages HDM_LAYOUT messages are generated when columns are added to the listview with _GUICtrlListView_AddColumn. To respond to these messages the header control must be subclassed before columns are added: Local $pHeaderProc = DllCallbackGetPtr( DllCallbackRegister( "HeaderProc", "lresult", "hwnd;uint;wparam;lparam;uint_ptr;dword_ptr" ) ) _WinAPI_SetWindowSubclass( $hHeader, $pHeaderProc, 9999, $iHeaderHeight ) ; SubclassId = 9999, $pData = $iHeaderHeight If columns are added directly in GUICtrlCreateListView command, this code snippet (copied from _GUICtrlHeader_Create) can be used to generate a HDM_LAYOUT message: Local $tRect = _WinAPI_GetClientRect( $hListView ) Local $tWindowPos = _GUICtrlHeader_Layout( $hHeader, $tRect ) _WinAPI_SetWindowPos( $hHeader, DllStructGetData( $tWindowPos , "InsertAfter" ), _ DllStructGetData( $tWindowPos , "X" ), DllStructGetData( $tWindowPos , "Y" ), _ DllStructGetData( $tWindowPos , "CX" ), DllStructGetData( $tWindowPos , "CY" ), _ DllStructGetData( $tWindowPos , "Flags" ) ) This is the subclass callback function: Func HeaderProc( $hWnd, $iMsg, $wParam, $lParam, $iSubclassId, $iHeaderHeight ) #forceref $iSubclassId Switch $iMsg Case $HDM_LAYOUT Local $tHdLayout = DllStructCreate( $tagHDLAYOUT, $lParam ) Local $tRect = DllStructCreate( $tagRECT, DllStructGetData( $tHdLayout, "Rect" ) ) Local $tWindowPos = DllStructCreate( $tagWINDOWPOS, DllStructGetData( $tHdLayout, "WindowPos" ) ) ; Modify $tRect and $tWindowPos in $tHdLayout to increase Header height DllStructSetData( $tRect, "Top", $iHeaderHeight ) DllStructSetData( $tWindowPos, "X", DllStructGetData( $tRect, "Left" ) ) DllStructSetData( $tWindowPos, "Y", 0 ) DllStructSetData( $tWindowPos, "CX", DllStructGetData( $tRect, "Right" ) - DllStructGetData( $tRect, "Left" ) ) DllStructSetData( $tWindowPos, "CY", $iHeaderHeight ) DllStructSetData( $tWindowPos, "Flags", 0x0020 ) ; 0x0020 = $SWP_FRAMECHANGED Return True EndSwitch ; Call next function in subclass chain Return DllCall( "comctl32.dll", "lresult", "DefSubclassProc", "hwnd", $hWnd, "uint", $iMsg, "wparam", $wParam, "lparam", $lParam )[0] EndFunc Multiple text lines in header items The items in a standard header control can display a single line of text. There seems not to be any options to change this. There is no word wrap option. Fortunately the header control supports both custom and owner drawn items. Custom drawn items are implemented through NM_CUSTOMDRAW notifications included in WM_NOTIFY messages. NM_CUSTOMDRAW notifications are generated automatically by the code in ComCtl32.dll when the header control is updated. Implementing custom drawn items is a matter of responding to these messages or not. Owner drawn items are implemented through WM_DRAWITEM messages. The HDF_OWNERDRAW flag must be set for the header items to generate WM_DRAWITEM messages. Custom drawn items are preferred in the examples. An example with owner drawn items is added in "Owner drawn" folder. Custom drawn items WM_NOTIFY (and WM_DRAWITEM) messages are send to the parent of the header control. The parent is usually an AutoIt GUI, and messages can be handled by a function registered with GUIRegisterMsg. In this case the listview is the parent of the header control. To catch header messages from the listview, the listview must be subclassed. Implement subclassing for the listview: Local $pListViewProc = DllCallbackGetPtr( DllCallbackRegister( "ListViewProc", "lresult", "hwnd;uint;wparam;lparam;uint_ptr;dword_ptr" ) ) _WinAPI_SetWindowSubclass( $hListView, $pListViewProc, 9999, 0 ) The subclass callback function looks like this: Func ListViewProc( $hWnd, $iMsg, $wParam, $lParam, $iSubclassId, $pData ) #forceref $iSubclassId, $pData Switch $iMsg Case $WM_NOTIFY Local $tNMHDR = DllStructCreate( $tagNMHDR, $lParam ) Local $hWndFrom = HWnd( DllStructGetData( $tNMHDR, "hWndFrom" ) ) Local $iCode = DllStructGetData( $tNMHDR, "Code" ) Switch $hWndFrom Case $hHeader Switch $iCode Case $NM_CUSTOMDRAW Local $tNMCustomDraw = DllStructCreate( $tagNMCUSTOMDRAW, $lParam ) Local $dwDrawStage = DllStructGetData( $tNMCustomDraw, "dwDrawStage" ) Switch $dwDrawStage ; Holds a value that specifies the drawing stage Case $CDDS_PREPAINT ; Before the paint cycle begins Return $CDRF_NOTIFYITEMDRAW ; Notify parent window of any item related drawing operations Case $CDDS_ITEMPREPAINT ; Before an item is drawn: Default painting (frames and background) Return $CDRF_NOTIFYPOSTPAINT ; Notify parent window of any post item related drawing operations Case $CDDS_ITEMPOSTPAINT ; After an item is drawn: Custom painting (item texts) Local $iIndex = DllStructGetData( $tNMCustomDraw, "dwItemSpec" ) ; Item index Local $hDC = DllStructGetData( $tNMCustomDraw, "hdc" ) ; Device context _WinAPI_SetBkMode( $hDC, $TRANSPARENT ) ; Transparent background DllStructSetData( $tNMCustomDraw, "Left", DllStructGetData( $tNMCustomDraw, "Left" ) + $aHdrInfo[$iIndex][1] ) ; Left margin DllStructSetData( $tNMCustomDraw, "Right", DllStructGetData( $tNMCustomDraw, "Right" ) - $aHdrInfo[$iIndex][1] ) ; Right margin DllStructSetData( $tNMCustomDraw, "Top", DllStructGetData( $tNMCustomDraw, "Top" ) + 2 ) ; 2 pixel top margin DllStructSetData( $tNMCustomDraw, "Bottom", DllStructGetData( $tNMCustomDraw, "Bottom" ) - 4 ) ; 4 pixel bottom margin DllCall( "user32.dll", "int", "DrawTextW", "handle", $hDC, "wstr", $aHdrInfo[$iIndex][0], "int", StringLen( $aHdrInfo[$iIndex][0] ), "struct*", DllStructGetPtr( $tNMCustomDraw, "Left" ), "uint", $aHdrInfo[$iIndex][2] ) ; _WinAPI_DrawText Return $CDRF_NEWFONT ; $CDRF_NEWFONT must be returned after changing font or colors EndSwitch EndSwitch EndSwitch EndSwitch ; Call next function in subclass chain Return DllCall( "comctl32.dll", "lresult", "DefSubclassProc", "hwnd", $hWnd, "uint", $iMsg, "wparam", $wParam, "lparam", $lParam )[0] EndFunc Default code in the $CDDS_ITEMPREPAINT stage draws the item frames and background. Code is added to the $CDDS_ITEMPOSTPAINT stage to draw the multi-line item texts. Since we are forced to use custom drawn (or owner drawn) items in any case, we might as well take the opportunity to use some of the options which custom drawn (or owner drawn) items offers. This includes various text styles and fonts, colored text and background, item icons or bitmaps and item frames. The picture shows some of the possibilities: Examples The examples are divided into four folders: Custom drawn contains the examples based on custom drawing. In these examples there is only added code to the $CDDS_ITEMPOSTPAINT stage to fill the inside of the item frames. Owner drawn folder contains an example that shows how to use an owner drawn header control. Two examples in Using font height shows how to use a font to increase the height of the header. Themes are disabled for the header control while the height is increased. Items are custom drawn. The first example restores the theme and draws multi-line texts in the $CDDS_ITEMPOSTPAINT stage. The second example draws entire header items including frames in the $CDDS_ITEMPREPAINT stage. Frames are drawn with _WinAPI_DrawFrameControl. Two examples in Using HDM_LAYOUT shows how to use HDM_LAYOUT messages to increase the height of the header when columns are added with _GUICtrlListView_AddColumn and directly with GUICtrlCreateListView. In all examples LVS_EX_HEADERDRAGDROP extended style is defined for the listview to be able to rearrange columns by drag-and-drop of header items. ListviewHeader.7z Custom drawn\ 1) Simple multi-line header.au3 2) Simple formatted text.au3 3) Styles, fonts, colors.au3 4) Icons and bitmaps.au3 Pattern.bmp Owner drawn\ 1) Simple multi-line header.au3 DrawItem.au3 Using font height\ 1) Restore header theme.au3 2) Drawing everything.au3 Using HDM_LAYOUT\ 1) Columns added with _GUICtrlListView_AddColumn.au3 2) Columns added with GUICtrlCreateListView.au3 ListviewHeader.7z Update 2015-11-24 I have made some tests with real listviews with more than 10 rows. It turns out that the method for increasing the height of the header has a significant impact on performance when rows are inserted in the listview. Increasing the height by responding to HDM_LAYOUT messages is a slow method. Each row inserted generates a HDM_LAYOUT message. This makes insertion slow if there are many rows. (HDM_LAYOUT method can still be used. But it should not be used when the header is contained in a listview.) Using a font to increase the height of the header does not have this negative effect on performance. The purpose of the examples is to be able to use multi-line headers in real listviews. I have updated the examples to use the faster font method to increase the height. A small UDF (GuiHeaderEx.au3) with one function is added to the zip: #include-once #include <WinAPITheme.au3> Func _GUICtrlHeader_SetItemHeightByFont( $hHeader, $iHeight, $bRestoreTheme = True ) ; Remove Header theme _WinAPI_SetWindowTheme( $hHeader, "", "" ) ; Get font of Header control ; Copied from _GUICtrlGetFont example by KaFu ; See https://www.autoitscript.com/forum/index.php?showtopic=124526 Local $hDC = _WinAPI_GetDC( $hHeader ), $hFont = _SendMessage( $hHeader, $WM_GETFONT ) Local $hObject = _WinAPI_SelectObject( $hDC, $hFont ), $lvLogFont = DllStructCreate( $tagLOGFONT ) _WinAPI_GetObject( $hFont, DllStructGetSize( $lvLogFont ), DllStructGetPtr( $lvLogFont ) ) Local $hHdrfont = _WinAPI_CreateFontIndirect( $lvLogFont ) ; Original Header font _WinAPI_SelectObject( $hDC, $hObject ) _WinAPI_ReleaseDC( $hHeader, $hDC ) ; Set height of Header items by applying text font with suitable height $hFont = _WinAPI_CreateFont( $iHeight, 0 ) _WinAPI_SetFont( $hHeader, $hFont ) _WinAPI_DeleteObject( $hFont ) ; Restore Header theme If $bRestoreTheme Then _ _WinAPI_SetWindowTheme( $hHeader ) ; Return original Header font Return $hHdrfont EndFunc ListviewHeader 2015-11-24.7z Custom drawn\ 1) Simple multi-line header.au3 2) Simple formatted text.au3 3) Styles, fonts, colors.au3 4) Icons and bitmaps.au3 5) Drawing everything.au3 GuiHeaderEx.au3 Pattern.bmp Owner drawn\ 1) Simple multi-line header.au3 GuiHeaderEx.au3 DrawItem.au3 You need AutoIt 3.3.10 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) ListviewHeader 2015-11-24.7z1 point
-
Need Help for injecting script for a game - (Locked)
KRIa reacted to JLogan3o13 for a topic
Welcome to the AutoIt forum. Unfortunately you appear to have missed the Forum rules on your way in. Please read them now - particularly the bit about not discussing game automation - and then you will understand why you will get no help and this thread will now be locked. See you soon with a legitimate question I hope. The Moderation team0 points