Jump to content

Listview just like Windows Explorer


Mugen
 Share

Recommended Posts

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?

 

#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

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:

#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.

Link to comment
Share on other sites

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.

Link to comment
Share on other sites

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 account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...