Sign in to follow this  
Followers 0
footswitch

Set Row Height in ListView with ownerdraw / WM_DRAWITEM

3 posts in this topic

Hi there,

I've been trying to change the height of my ListView's rows, but still no luck.

Searching the forum only returning results where people are looking for _GUICtrlListView_SetView(), which is not the case, I believe.

Do you have any clues? My knowledge of ownerdraw is very limited...

Here's my code:

#include <GuiListView.au3>
#include <GUIConstantsEx.au3>
#include <WindowsConstants.au3>
Global $default_font = "Arial"
Global $default_font_size = 9
Global $GUI_main = GUICreate("", 300, 300, -1, -1, -1, $WS_EX_ACCEPTFILES)
Global $hGUI_tab_listview[2][10]
$hGUI_tab_listview[0][0] = GUICtrlCreateListView("", 15, 68, 250, 90, _
  $LVS_REPORT + $LVS_SHOWSELALWAYS+ $LVS_OWNERDRAWFIXED, _
  $LVS_EX_FULLROWSELECT + $LVS_EX_GRIDLINES) ; + $LVS_EX_CHECKBOXES + $LVS_SINGLESEL
GUICtrlSetFont(-1, $default_font_size+8, 400, 0, $default_font, 5)
_GUICtrlListView_AddColumn(-1, "Name")
_GUICtrlListView_SetColumnWidth(-1, 0, 155)
_GUICtrlListView_AddColumn(-1, "Count")
_GUICtrlListView_SetColumnWidth(-1, 1, 72)
For $i=0 To 10 ; populate the listview for testing purposes
_GUICtrlListView_AddItem(-1, "test "&$i)
_GUICtrlListView_AddSubItem(-1, $i, $i, 1)
Next
Global Const $ODT_LISTVIEW = 102
Global Const $ODA_DRAWENTIRE = 0x1
Global Const $ODA_SELECT = 0x2
Global Const $ODA_FOCUS = 0x4
Global Const $ODS_SELECTED = 0x0001
GUIRegisterMsg($WM_DRAWITEM, "WM_DRAWITEM")
GUISetState(@SW_SHOW)
While 1
Sleep(100)
WEnd
Exit



Func WM_DRAWITEM($hWnd, $Msg, $wParam, $lParam)
Local $tagDRAWITEMSTRUCT, $iBrushColor, $cID, $itmID, $itmAction, $itmState, $hItm, $hDC, $bSelected
$tagDRAWITEMSTRUCT = DllStructCreate( _
   "uint cType;" & _
   "uint cID;" & _
   "uint itmID;" & _
   "uint itmAction;" & _
   "uint itmState;" & _
   "hwnd hItm;" & _
   "hwnd hDC;" & _
   "int itmRect[4];" & _
   "dword itmData" _
   , $lParam)
If DllStructGetData($tagDRAWITEMSTRUCT, "cType") <> $ODT_LISTVIEW Then Return $GUI_RUNDEFMSG
$cID = DllStructGetData($tagDRAWITEMSTRUCT, "cID")
$itmID = DllStructGetData($tagDRAWITEMSTRUCT, "itmID")
$itmAction = DllStructGetData($tagDRAWITEMSTRUCT, "itmAction")
$itmState = DllStructGetData($tagDRAWITEMSTRUCT, "itmState")
$hItm = DllStructGetData($tagDRAWITEMSTRUCT, "hItm")
$hDC = DllStructGetData($tagDRAWITEMSTRUCT, "hDC")
$bSelected = BitAND($itmState, $ODS_SELECTED)
Switch $cID ; will look for ControlID, not window handle.
  Case $hGUI_tab_listview[0][0]
   Switch $itmAction
    Case $ODA_DRAWENTIRE
     ; don't forget, this is BGR, not RGB
     If $itmState = $bSelected Then ; item is not selected
      $iBrushColor = 0xCCEECC
     Else ; item is selected
      $iBrushColor = 0xEEDDBB
     EndIf
     Local $aBrush = DllCall("gdi32.dll", "hwnd", "CreateSolidBrush", "int", $iBrushColor)
     Local $aBrushOld = _WinAPI_SelectObject($hDC, $aBrush[0])
     Local $iLeft = DllStructGetData($tagDRAWITEMSTRUCT, "itmRect", 1)
     DllStructSetData($tagDRAWITEMSTRUCT, "itmRect", $iLeft + 1, 1) ; rectangle coordinates for coloring
     ; +1 is the left margin
     _WinAPI_FillRect($hDC, DllStructGetPtr($tagDRAWITEMSTRUCT, "itmRect"), $aBrush[0])
     _WinAPI_SelectObject($hDC, $aBrushOld)
     _WinAPI_DeleteObject($aBrush[0])
     ; for all columns of the row:
     $local_alignment = $DT_LEFT
     For $i = 0 To _GUICtrlListView_GetColumnCount($hGUI_tab_listview[0][0]) - 1
      ; 1. get subitem text:
      Local $iSubItmText = _GUICtrlListView_GetItemText($hGUI_tab_listview[0][0], $itmID, $i)
      ; 2. get subitem coordinates for drawing its respective text
      Local $aSubItmRect = _GUICtrlListView_GetSubItemRect($hGUI_tab_listview[0][0], $itmID, $i)
      ; the function above accepts not only subitems (one-based index), but also main item (index=0)
      ; 3. pass the coordinates to a DLL struct
      Local $iSubItmRect = DllStructCreate("int[4]")
      DllStructSetData($iSubItmRect, 1, $aSubItmRect[0] + 6, 1) ; +6 is left margin (X)
      DllStructSetData($iSubItmRect, 1, $aSubItmRect[1] + (-2), 2) ; + (-2) is upper margin (Y)
      DllStructSetData($iSubItmRect, 1, $aSubItmRect[2], 3)
      DllStructSetData($iSubItmRect, 1, $aSubItmRect[3], 4)
      DllCall("user32.dll", "int", "DrawText", "hwnd", $hDC, "str", $iSubItmText, "int", StringLen($iSubItmText), _
        "ptr", DllStructGetPtr($iSubItmRect), "int", $local_alignment)
     Next
     ;#ce
   EndSwitch
EndSwitch
Return $GUI_RUNDEFMSG
EndFunc   ;==>WM_DRAWITEM

Thanks in advance.

regards,

footswitch


Share this post


Link to post
Share on other sites



You set row height by capturing the WM_MEASUREITEM message

Search forum or read msdn.microsoft.com

WM_MEASUREITEM and MEASUREITEMSTRUCT Structure

#include <GuiListView.au3>
#include <GUIConstantsEx.au3>
#include <WindowsConstants.au3>
Global Const $ODT_LISTVIEW = 102
Global Const $ODA_DRAWENTIRE = 0x1
Global Const $ODA_SELECT = 0x2
Global Const $ODA_FOCUS = 0x4
Global Const $ODS_SELECTED = 0x0001

Global $default_font = "Arial"
Global $default_font_size = 9
Global $GUI_main = GUICreate("", 300, 300, -1, -1, -1, $WS_EX_ACCEPTFILES)
Global $hGUI_tab_listview[2][10]
GUIRegisterMsg($WM_MEASUREITEM, "WM_MEASUREITEM") ;place before listview creation - message sent once for each ownerdrawn control created
$hGUI_tab_listview[0][0] = GUICtrlCreateListView("", 15, 68, 250, 90, _
  BitOR($LVS_REPORT, $LVS_SHOWSELALWAYS, $LVS_OWNERDRAWFIXED), _
  BitOR($LVS_EX_FULLROWSELECT, $LVS_EX_GRIDLINES)) ; + $LVS_EX_CHECKBOXES + $LVS_SINGLESEL
GUICtrlSetFont(-1, $default_font_size + 8, 400, 0, $default_font, 5)
_GUICtrlListView_AddColumn(-1, "Name")
_GUICtrlListView_SetColumnWidth(-1, 0, 155)
_GUICtrlListView_AddColumn(-1, "Count")
_GUICtrlListView_SetColumnWidth(-1, 1, 72)
For $i = 0 To 10 ; populate the listview for testing purposes
_GUICtrlListView_AddItem(-1, "test " & $i)
_GUICtrlListView_AddSubItem(-1, $i, $i, 1)
Next

GUIRegisterMsg($WM_DRAWITEM, "WM_DRAWITEM")
GUISetState(@SW_SHOW)
While 1
Sleep(100)
WEnd
Exit

Func WM_MEASUREITEM($hWnd, $Msg, $wParam, $lParam)
Local $tMEASUREITEMS = DllStructCreate("uint cType;uint cID;uint itmID;uint itmW;uint itmH;ulong_ptr itmData", $lParam)
If DllStructGetData($tMEASUREITEMS, "cType") <> $ODT_LISTVIEW Then Return $GUI_RUNDEFMSG
DllStructSetData($tMEASUREITEMS, "itmH", 20);row height
;GUIRegisterMsg($WM_MEASUREITEM, "") ;call this after last ownerdrawn listview created
Return 1
EndFunc   ;==>WM_MEASUREITEM

Func WM_DRAWITEM($hWnd, $Msg, $wParam, $lParam)
Local $tagDRAWITEMSTRUCT, $iBrushColor, $cID, $itmID, $itmAction, $itmState, $hItm, $hDC, $bSelected
$tagDRAWITEMSTRUCT = DllStructCreate( _
   "uint cType;" & _
   "uint cID;" & _
   "uint itmID;" & _
   "uint itmAction;" & _
   "uint itmState;" & _
   "hwnd hItm;" & _
   "handle hDC;" & _
   "long itmRect[4];" & _
   "ulong_ptr itmData" _
   , $lParam)
If DllStructGetData($tagDRAWITEMSTRUCT, "cType") <> $ODT_LISTVIEW Then Return $GUI_RUNDEFMSG
$cID = DllStructGetData($tagDRAWITEMSTRUCT, "cID")
$itmID = DllStructGetData($tagDRAWITEMSTRUCT, "itmID")
$itmAction = DllStructGetData($tagDRAWITEMSTRUCT, "itmAction")
$itmState = DllStructGetData($tagDRAWITEMSTRUCT, "itmState")
$hItm = DllStructGetData($tagDRAWITEMSTRUCT, "hItm")
$hDC = DllStructGetData($tagDRAWITEMSTRUCT, "hDC")
$bSelected = BitAND($itmState, $ODS_SELECTED)
Switch $cID ; will look for ControlID, not window handle.
  Case $hGUI_tab_listview[0][0]
   Switch $itmAction
    Case $ODA_DRAWENTIRE
     ; don't forget, this is BGR, not RGB
     If $itmState = $bSelected Then ; item is not selected
      $iBrushColor = 0xCCEECC
     Else ; item is selected
      $iBrushColor = 0xEEDDBB
     EndIf
     Local $aBrush = DllCall("gdi32.dll", "hwnd", "CreateSolidBrush", "int", $iBrushColor)
     Local $aBrushOld = _WinAPI_SelectObject($hDC, $aBrush[0])
     Local $iLeft = DllStructGetData($tagDRAWITEMSTRUCT, "itmRect", 1)
     DllStructSetData($tagDRAWITEMSTRUCT, "itmRect", $iLeft + 1, 1) ; rectangle coordinates for coloring
     ; +1 is the left margin
     _WinAPI_FillRect($hDC, DllStructGetPtr($tagDRAWITEMSTRUCT, "itmRect"), $aBrush[0])
     _WinAPI_SelectObject($hDC, $aBrushOld)
     _WinAPI_DeleteObject($aBrush[0])
     ; for all columns of the row:
     $local_alignment = $DT_LEFT
     For $i = 0 To _GUICtrlListView_GetColumnCount($hGUI_tab_listview[0][0]) - 1
      ; 1. get subitem text:
      Local $iSubItmText = _GUICtrlListView_GetItemText($hGUI_tab_listview[0][0], $itmID, $i)
      ; 2. get subitem coordinates for drawing its respective text
      Local $aSubItmRect = _GUICtrlListView_GetSubItemRect($hGUI_tab_listview[0][0], $itmID, $i)
      ; the function above accepts not only subitems (one-based index), but also main item (index=0)
      ; 3. pass the coordinates to a DLL struct
      Local $iSubItmRect = DllStructCreate("long[4]")
      DllStructSetData($iSubItmRect, 1, $aSubItmRect[0] + 6, 1) ; +6 is left margin (X)
      DllStructSetData($iSubItmRect, 1, $aSubItmRect[1] + (-2), 2) ; + (-2) is upper margin (Y)
      DllStructSetData($iSubItmRect, 1, $aSubItmRect[2], 3)
      DllStructSetData($iSubItmRect, 1, $aSubItmRect[3], 4)
      DllCall("user32.dll", "int", "DrawTextW", "hwnd", $hDC, "wstr", $iSubItmText, "int", StringLen($iSubItmText), _
        "ptr", DllStructGetPtr($iSubItmRect), "int", $local_alignment)
     Next
     ;#ce
   EndSwitch
EndSwitch
Return $GUI_RUNDEFMSG
EndFunc   ;==>WM_DRAWITEM
2 people like this

I see fascists...

Share this post


Link to post
Share on other sites

Really, four lines of code?

Thanks man, you rock ;)


Share this post


Link to post
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
Sign in to follow this  
Followers 0