Mugen Posted February 18, 2020 Share Posted February 18, 2020 Hi, I wonder how to create a list view like windows explorer. It seems SetWindowTheme() is need to get selection and hover items displayed correctly. But this now causes a thin vertical border between all columns. Any idea on how to remove it? expandcollapse popup#include <GUIConstantsEx.au3> #include <GuiListView.au3> #include <GuiImageList.au3> #include <WindowsConstants.au3> Global $hListView _Main() Func _Main() Local $GUI, $hImage $GUI = GUICreate("(UDF Created) ListView Create", 400, 300) $hListView = _GUICtrlListView_Create($GUI, "", 2, 2, 394, 268) _GUICtrlListView_SetExtendedListViewStyle($hListView, BitOR($LVS_EX_FULLROWSELECT, $LVS_EX_DOUBLEBUFFER )) DllCall("UxTheme.dll", "int", "SetWindowTheme", "hwnd", $hListView, "wstr", "Explorer", "ptr", 0) ; Set "Vista" Style GUISetState() ; Load images $hImage = _GUIImageList_Create() _GUIImageList_Add($hImage, _GUICtrlListView_CreateSolidBitMap($hListView, 0xFF0000, 16, 16)) _GUIImageList_Add($hImage, _GUICtrlListView_CreateSolidBitMap($hListView, 0x00FF00, 16, 16)) _GUIImageList_Add($hImage, _GUICtrlListView_CreateSolidBitMap($hListView, 0x0000FF, 16, 16)) _GUICtrlListView_SetImageList($hListView, $hImage, 1) ; Add columns _GUICtrlListView_InsertColumn($hListView, 0, "Column 1", 100) _GUICtrlListView_InsertColumn($hListView, 1, "Column 2", 100) _GUICtrlListView_InsertColumn($hListView, 2, "Column 3", 100) ; Add items _GUICtrlListView_AddItem($hListView, "Row 1: Col 1", 0) _GUICtrlListView_AddSubItem($hListView, 0, "Row 1: Col 2", 1) _GUICtrlListView_AddSubItem($hListView, 0, "Row 1: Col 3", 2) _GUICtrlListView_AddItem($hListView, "Row 2: Col 1", 1) _GUICtrlListView_AddSubItem($hListView, 1, "Row 2: Col 2", 1) _GUICtrlListView_AddItem($hListView, "Row 3: Col 1", 2) ; Loop until user exits Do Until GUIGetMsg() = $GUI_EVENT_CLOSE GUIDelete() EndFunc ;==>_Main Link to comment Share on other sites More sharing options...
LarsJ Posted February 20, 2020 Share Posted February 20, 2020 The only easy way to remove the blue vertical grid lines between the columns is, as far as I know, to overwrite the lines with new lines of the same color as the background color of the listview cells: expandcollapse popup#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 <GuiImageList.au3> #include <WindowsConstants.au3> Global $idListView, $hListView _Main() Func _Main() Local $hImage GUICreate("(Not UDF Created because of speed) ListView Create", 400, 300) $idListView = GUICtrlCreateListView("", 2, 2, 394, 268) $hListView = GUICtrlGetHandle( $idListView ) _GUICtrlListView_SetExtendedListViewStyle($idListView, BitOR($LVS_EX_FULLROWSELECT, $LVS_EX_DOUBLEBUFFER )) DllCall("UxTheme.dll", "int", "SetWindowTheme", "hwnd", $hListView, "wstr", "Explorer", "ptr", 0) ; Set "Vista" Style GUIRegisterMsg( $WM_NOTIFY, "WM_NOTIFY" ) GUISetState() ; Load images $hImage = _GUIImageList_Create() _GUIImageList_Add($hImage, _GUICtrlListView_CreateSolidBitMap($idListView, 0xFF0000, 16, 16)) _GUIImageList_Add($hImage, _GUICtrlListView_CreateSolidBitMap($idListView, 0x00FF00, 16, 16)) _GUIImageList_Add($hImage, _GUICtrlListView_CreateSolidBitMap($idListView, 0x0000FF, 16, 16)) _GUICtrlListView_SetImageList($idListView, $hImage, 1) ; Add columns _GUICtrlListView_InsertColumn($idListView, 0, "Column 1", 100) _GUICtrlListView_InsertColumn($idListView, 1, "Column 2", 100) _GUICtrlListView_InsertColumn($idListView, 2, "Column 3", 100) ; Add items _GUICtrlListView_AddItem($idListView, "Row 1: Col 1", 0) _GUICtrlListView_AddSubItem($idListView, 0, "Row 1: Col 2", 1) _GUICtrlListView_AddSubItem($idListView, 0, "Row 1: Col 3", 2) _GUICtrlListView_AddItem($idListView, "Row 2: Col 1", 1) _GUICtrlListView_AddSubItem($idListView, 1, "Row 2: Col 2", 1) _GUICtrlListView_AddItem($idListView, "Row 3: Col 1", 2) ; Loop until user exits Do Until GUIGetMsg() = $GUI_EVENT_CLOSE GUIDelete() EndFunc ;==>_Main Func WM_NOTIFY( $hWnd, $iMsg, $wParam, $lParam ) Local Static $hDC, $hPen = _WinAPI_CreatePen( $PS_SOLID, 1, 0xFFFFFF ), $iHot = -1, $iSel = -1 Local Static $tRect = DllStructCreate( $tagRECT ), $pRect = DllStructGetPtr( $tRect ) Local $tNMHDR = DllStructCreate( $tagNMHDR, $lParam ), $iItem Switch HWnd( DllStructGetData( $tNMHDR, "hWndFrom" ) ) ; $hWndFrom Case $hListView Switch DllStructGetData( $tNMHDR, "Code" ) ; $iCode Case $NM_CUSTOMDRAW Local $tCustDraw = DllStructCreate( $tagNMLVCUSTOMDRAW, $lParam ) Switch DllStructGetData( $tCustDraw, "dwDrawStage" ) ; Specifies the drawing stage Case $CDDS_PREPAINT ; Before the paint cycle begins $hDC = DllStructGetData( $tCustDraw, "hdc" ) DllCall( "gdi32.dll", "handle", "SelectObject", "handle", $hDC, "handle", $hPen ) ; _WinAPI_SelectObject ; Get hot item under mouse $iHot = GUICtrlSendMsg( $idListView, $LVM_GETHOTITEM, 0, 0 ) ; Get selected item For $iItem = 0 To 2 If GUICtrlSendMsg( $idListView, $LVM_GETITEMSTATE, $iItem, $LVIS_SELECTED ) Then ExitLoop Next $iSel = $iItem < 3 ? $iItem : -1 ; Update empty space below last item, item 2 For $iSubItem = 0 To 2 ; For each subitem (column) DllStructSetData( $tRect, "Top", $iSubItem ) DllStructSetData( $tRect, "Left", $LVIR_LABEL ) GUICtrlSendMsg( $idListView, $LVM_GETSUBITEMRECT, 2, $pRect ) ; 2 = last item DllCall( "gdi32.dll", "bool", "MoveToEx", "handle", $hDC, "int", DllStructGetData( $tRect, "Right" )-1, "int", DllStructGetData( $tRect, "Bottom" )+1, "ptr", 0 ) ; _WinAPI_MoveTo ; Just below last item DllCall( "gdi32.dll", "bool", "LineTo", "handle", $hDC, "int", DllStructGetData( $tRect, "Right" )-1, "int", DllStructGetData( $tRect, "Bottom" )+268 ) ; _WinAPI_LineTo ; 268 = height/bottom of LV Next Return $CDRF_NOTIFYITEMDRAW Case $CDDS_ITEMPREPAINT ; Before an item is painted Return $CDRF_NOTIFYPOSTPAINT Case $CDDS_ITEMPOSTPAINT ; After an item has been painted $iItem = DllStructGetData( $tCustDraw, "dwItemSpec" ) Switch $iItem Case $iHot, $iSel ; Hot and selected items Return $CDRF_NEWFONT ; Skip these items Case Else ; Other items For $iSubItem = 0 To 2 ; For each subitem (column) DllStructSetData( $tRect, "Top", $iSubItem ) DllStructSetData( $tRect, "Left", $LVIR_LABEL ) GUICtrlSendMsg( $idListView, $LVM_GETSUBITEMRECT, $iItem, $pRect ) DllCall( "gdi32.dll", "bool", "MoveToEx", "handle", $hDC, "int", DllStructGetData( $tRect, "Right" )-1, "int", DllStructGetData( $tRect, "Top" ), "ptr", 0 ) ; _WinAPI_MoveTo DllCall( "gdi32.dll", "bool", "LineTo", "handle", $hDC, "int", DllStructGetData( $tRect, "Right" )-1, "int", DllStructGetData( $tRect, "Bottom" ) ) ; _WinAPI_LineTo Next Return $CDRF_NEWFONT ; $CDRF_NEWFONT must be returned after changing font or colors EndSwitch EndSwitch EndSwitch EndSwitch Return $GUI_RUNDEFMSG #forceref $hWnd, $iMsg, $wParam EndFunc Note that when using GDI functions in custom draw code, you must be very careful about the performance of the code to avoid executing more code than there is time for. This is the reason why the listview is created with GUICtrlCreateListView() that returns a controlId, so it's possible to use GUICtrlSendMsg() (fast internal function implemented in real compiled C++ code) instead of _SendMessage() (relatively time-consuming UDF function implemented in AutoIt code), which is necessary to use if you only have a control handle. And that's also the reason why only the DLLCall() function is executed for the GDI functions instead of the entire UDF function. argumentum 1 Controls, File Explorer, ROT objects, UI Automation, Windows Message MonitorCompiled code: Accessing AutoIt variables, DotNet.au3 UDF, Using C# and VB codeShell menus: The Context menu, The Favorites menu. Shell related: Control Panel, System Image ListsGraphics related: Rubik's Cube, OpenGL without external libraries, Navigating in an image, Non-rectangular selectionsListView controls: Colors and fonts, Multi-line header, Multi-line items, Checkboxes and icons, Incremental searchListView controls: Virtual ListViews, Editing cells, Data display functions Link to comment Share on other sites More sharing options...
argumentum Posted February 20, 2020 Share Posted February 20, 2020 I use other colors so "$hPen = _WinAPI_CreatePen( $PS_SOLID, 1, _WinAPI_SwitchColor(_WinAPI_GetSysColor($COLOR_WINDOW)) )" is better. ...is there a way around the bar in the selected selected ?. Follow the link to my code contribution ( and other things too ). FAQ - Please Read Before Posting. Link to comment Share on other sites More sharing options...
Mugen Posted February 20, 2020 Author Share Posted February 20, 2020 @LarsJThanks for these information about GUICtrlSendMsg() and especially for this CUSTOMDRAW example. I'll play with this with some more windows themes, maybe even draw it all with NM_CUSTOMDRAW and DrawThemeBackground(). Link to comment Share on other sites More sharing options...
LarsJ Posted February 20, 2020 Share Posted February 20, 2020 argumentum, You do the same for selected items. Split Case $iHot, $iSel in the $CDDS_ITEMPOSTPAINT section this way: Case $iHot ; Hot item Return $CDRF_NEWFONT ; Skip this item Case $iSel ; Selected item DllCall( "gdi32.dll", "handle", "SelectObject", "handle", $hDC, "handle", $hPenSel ) ; _WinAPI_SelectObject For $iSubItem = 0 To 2 ; For each subitem (column) DllStructSetData( $tRect, "Top", $iSubItem ) DllStructSetData( $tRect, "Left", $LVIR_LABEL ) GUICtrlSendMsg( $idListView, $LVM_GETSUBITEMRECT, $iItem, $pRect ) DllCall( "gdi32.dll", "bool", "MoveToEx", "handle", $hDC, "int", DllStructGetData( $tRect, "Right" )-1, "int", DllStructGetData( $tRect, "Top" ), "ptr", 0 ) ; _WinAPI_MoveTo DllCall( "gdi32.dll", "bool", "LineTo", "handle", $hDC, "int", DllStructGetData( $tRect, "Right" )-1, "int", DllStructGetData( $tRect, "Bottom" ) ) ; _WinAPI_LineTo Next Return $CDRF_NEWFONT ; $CDRF_NEWFONT must be returned after changing font or colors Add this line as the very first line in the Case Else section so you can switch between the two pens: DllCall( "gdi32.dll", "handle", "SelectObject", "handle", $hDC, "handle", $hPen ) ; _WinAPI_SelectObject Create $hPenSel as a Local Static pen of the right color at the top of the WM_NOTIFY function. argumentum 1 Controls, File Explorer, ROT objects, UI Automation, Windows Message MonitorCompiled code: Accessing AutoIt variables, DotNet.au3 UDF, Using C# and VB codeShell menus: The Context menu, The Favorites menu. Shell related: Control Panel, System Image ListsGraphics related: Rubik's Cube, OpenGL without external libraries, Navigating in an image, Non-rectangular selectionsListView controls: Colors and fonts, Multi-line header, Multi-line items, Checkboxes and icons, Incremental searchListView controls: Virtual ListViews, Editing cells, Data display functions Link to comment Share on other sites More sharing options...
Recommended Posts
Create an account or sign in to comment
You need to be a member in order to leave a comment
Create an account
Sign up for a new account in our community. It's easy!
Register a new accountSign in
Already have an account? Sign in here.
Sign In Now