kjuenke

Multi-line listview column headings

15 posts in this topic

Is it possible to create multi-line column headings like this graphic image represents?

Thanks much for any assistance.

Capture.JPG

Share this post


Link to post
Share on other sites



I don't know if it is possible at all, but did you ever see a Windows program with multiline headers?


My UDFs and Tutorials:

Spoiler

UDFs:
Active Directory (NEW 2017-04-18 - Version 1.4.8.0) - Download - General Help & Support - Example Scripts - Wiki
OutlookEX (NEW 2017-02-27 - Version 1.3.1.0) - Download - General Help & Support - Example Scripts - Wiki
ExcelChart (2015-04-01 - Version 0.4.0.0) - Download - General Help & Support - Example Scripts
Excel - Example Scripts - Wiki
Word - Wiki
PowerPoint (2015-06-06 - Version 0.0.5.0) - Download - General Help & Support

Tutorials:
ADO - Wiki

 

Share this post


Link to post
Share on other sites

Hi water,

Yes, we work with an ERP application that does what I'm asking. Here is a screenshot......

 

Capture.JPG

Share this post


Link to post
Share on other sites

I'm on a business trip right now, so can't test. 

Have you played with @crlf, @cr and @lf to start a new line?


My UDFs and Tutorials:

Spoiler

UDFs:
Active Directory (NEW 2017-04-18 - Version 1.4.8.0) - Download - General Help & Support - Example Scripts - Wiki
OutlookEX (NEW 2017-02-27 - Version 1.3.1.0) - Download - General Help & Support - Example Scripts - Wiki
ExcelChart (2015-04-01 - Version 0.4.0.0) - Download - General Help & Support - Example Scripts
Excel - Example Scripts - Wiki
Word - Wiki
PowerPoint (2015-06-06 - Version 0.0.5.0) - Download - General Help & Support

Tutorials:
ADO - Wiki

 

Share this post


Link to post
Share on other sites

I did play with @CRLF, @CR and @LF like this....

$LogList = GUICtrlCreateListView("CS" & @CRLF & "REP|CUSTOMER NAME|.......   but they don't work.

Share this post


Link to post
Share on other sites

My UDFs and Tutorials:

Spoiler

UDFs:
Active Directory (NEW 2017-04-18 - Version 1.4.8.0) - Download - General Help & Support - Example Scripts - Wiki
OutlookEX (NEW 2017-02-27 - Version 1.3.1.0) - Download - General Help & Support - Example Scripts - Wiki
ExcelChart (2015-04-01 - Version 0.4.0.0) - Download - General Help & Support - Example Scripts
Excel - Example Scripts - Wiki
Word - Wiki
PowerPoint (2015-06-06 - Version 0.0.5.0) - Download - General Help & Support

Tutorials:
ADO - Wiki

 

Share this post


Link to post
Share on other sites

Looks like AutoIt does not support datagrid controls. What comes next to a datagrid is describrd here: https://www.autoitscript.com/forum/topic/146413-can-we-use-autoit3-to-create-a-gui-with-datagrid-table-in-it/#comment-1036185 


My UDFs and Tutorials:

Spoiler

UDFs:
Active Directory (NEW 2017-04-18 - Version 1.4.8.0) - Download - General Help & Support - Example Scripts - Wiki
OutlookEX (NEW 2017-02-27 - Version 1.3.1.0) - Download - General Help & Support - Example Scripts - Wiki
ExcelChart (2015-04-01 - Version 0.4.0.0) - Download - General Help & Support - Example Scripts
Excel - Example Scripts - Wiki
Word - Wiki
PowerPoint (2015-06-06 - Version 0.0.5.0) - Download - General Help & Support

Tutorials:
ADO - Wiki

 

Share this post


Link to post
Share on other sites

Wow, datagridviews looks very useful. That would be a great addition to AutoIT, for sure.

Thanks water. Have a safe trip and if you think of anything else I'd love to hear it.

For now, I'll keep looking at other ways of possibly making the minions happy over here.

Share this post


Link to post
Share on other sites

Header.au3 (run this):

#include <WindowsConstants.au3>
#include <GUIConstants.au3>
#include <WinAPITheme.au3>
#include <GuiListView.au3>
#include <GuiHeader.au3>
#include "DrawItem.au3"

Opt( "MustDeclareVars", 1 )

Global $hHeader, $idHeaderOrder, $hLV, $aOrder = [ 0, 1, 2, 3 ]
Global $aHeader = [ [ "Column 1", "",       ""       ], _
                    [ "Column 2", "Line 2", ""       ], _
                    [ "Column 3", "Line 2", "Line 3" ], _
                    [ "Column 4", "Line 2", ""       ] ]

Example()


Func Example()
  ; Create GUI
  Local $hGui = GUICreate( "ListView with multiple-line header", 400, 300, -1, 300 )

  ; Create child
  Local $hChild = GUICreate( "", 380, 280, 10, 10, $WS_CHILD, -1, $hGui )

  ; Create Header in child
  $hHeader = _GUICtrlHeader_Create( $hChild )
  _GUICtrlHeader_AddItem( $hHeader, "", 95 )
  _GUICtrlHeader_AddItem( $hHeader, "", 95 )
  _GUICtrlHeader_AddItem( $hHeader, "", 95 )
  _GUICtrlHeader_AddItem( $hHeader, "", 95 )

  ; Doesn't work with themes
  _WinAPI_SetWindowTheme( $hHeader, "", "" )

  ; Set all items owner drawn
  Local $tItem = DllStructCreate( $tagHDITEM )
  For $i = 0 To 3
    _GUICtrlHeader_GetItem( $hHeader, $i, $tItem )
    DllStructSetData( $tItem, "Mask", $HDI_FORMAT )
    DllStructSetData( $tItem, "Fmt", $HDF_OWNERDRAW )
    _GUICtrlHeader_SetItem( $hHeader, $i, $tItem )
  Next

  ; Set Header height
  Local $tRect = _WinAPI_GetClientRect( $hChild )
  Local $tPos = _GUICtrlHeader_Layout( $hHeader, $tRect )
  _WinAPI_SetWindowPos( $hHeader, DllStructGetData( $tPos, "InsertAfter" ), _
    DllStructGetData( $tPos, "X" ), DllStructGetData( $tPos, "Y" ), _
    DllStructGetData( $tPos, "CX" ), 54, DllStructGetData( $tPos, "Flags" ) ) ; Height = 54

  ; Create ListView in child
  Local $idLV = GUICtrlCreateListView( "", 0, 54, 380, 280-54, $LVS_NOCOLUMNHEADER )
  $hLV = GUICtrlGetHandle( $idLV )
  _GUICtrlListView_AddColumn( $hLV, "Column 1", 94 )
  _GUICtrlListView_AddColumn( $hLV, "Column 2", 94 )
  _GUICtrlListView_AddColumn( $hLV, "Column 3", 94 )
  _GUICtrlListView_AddColumn( $hLV, "Column 4", 94 )
  For $i = 0 To 9
    GUICtrlCreateListViewItem( $i & "/1|" & $i & "/2|" & $i & "/3|" & $i & "/4", $idLV )
  Next

  ; Show child
  GUISetState()

  ; Switch to GUI
  GUISwitch( $hGui )
  GUICtrlCreateLabel( "", 8, 8, 384, 58, 0x12 ) ; 0x12 = $SS_ETCHEDFRAME
  $idHeaderOrder = GUICtrlCreateDummy()

  GUIRegisterMsg( $WM_DRAWITEM, "WM_DRAWITEM" ) ; Draw Header item texts
  GUIRegisterMsg( $WM_NOTIFY, "WM_NOTIFY" )     ; Header events

  ; Show GUI
  GUISetState()

  Local $aMsg, $aOrderPrev = $aOrder, $aColValues[4], $aColWidths[4]
  While 1
    $aMsg = GUIGetMsg( 1 )
    Switch $aMsg[1]
      Case $hGui
        Switch $aMsg[0]
          Case $idHeaderOrder
            ; Get Header item order
            For $i = 0 To 3
              $aOrder[$i] = _GUICtrlHeader_GetItemOrder( $hHeader, $i )
            Next
            ; New order?
            If $aOrder[0] <> $aOrderPrev[0] Or $aOrder[1] <> $aOrderPrev[1] Or $aOrder[2] <> $aOrderPrev[2] Or $aOrder[3] <> $aOrderPrev[3] Then
              For $i = 0 To 3
                $aColValues[$aOrder[$i]] = $i + 1 ; ListView column values
                $aColWidths[$aOrder[$i]] = _GUICtrlHeader_GetItemWidth( $hHeader, $i ) ; ListView column widths
              Next
              _GUICtrlListView_BeginUpdate( $hLV )
              _GUICtrlListView_DeleteAllItems( $hLV )
              For $i = 0 To 3
                _GUICtrlListView_SetColumnWidth( $hLV, $i, $aColWidths[$i] ) ; Set ListView column widths
              Next
              For $i = 0 To 9 ; Set ListView column values
                GUICtrlCreateListViewItem( $i & "/" & $aColValues[0] & "|" & $i & "/" & $aColValues[1] & "|" & $i & "/" & $aColValues[2] & "|" & $i & "/" & $aColValues[3], $idLV )
              Next
              _GUICtrlListView_EndUpdate( $hLV )
              $aOrderPrev = $aOrder
            EndIf
          Case $GUI_EVENT_CLOSE
            ExitLoop
        EndSwitch
    EndSwitch
  WEnd

EndFunc

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 $hHeader
      Switch $iCode
        Case $HDN_TRACK, $HDN_TRACKW
          ; Header item width change (dragging the delimiter)
          Local $tNMHEADER = DllStructCreate( $tagNMHEADER, $lParam ), $tItem = DllStructCreate( $tagHDITEM, DllStructGetData( $tNMHEADER, "pItem" ) )
          If BitAND( DllStructGetData( $tItem, "Mask" ), $HDI_WIDTH ) Then _GUICtrlListView_SetColumnWidth( $hLV, $aOrder[DllStructGetData( $tNMHEADER, "Item" )], DllStructGetData( $tItem, "XY" ) )
        Case $HDN_ENDDRAG
          ; Dragging Header item finished
          GUICtrlSendToDummy( $idHeaderOrder )
      EndSwitch
  EndSwitch

  Return $GUI_RUNDEFMSG
EndFunc

Func WM_DRAWITEM( $hWnd, $iMsg, $wParam, $lParam )
  #forceref $hWnd, $iMsg, $wParam
  Local $tDRAWITEM = DllStructCreate( $tagDRAWITEM, $lParam )
  If DllStructGetData( $tDRAWITEM, "CtlType" ) <> $ODT_HEADER Then Return $GUI_RUNDEFMSG

  Switch DllStructGetData( $tDRAWITEM, "hwndItem" )
    Case $hHeader
      Switch DllStructGetData( $tDRAWITEM, "itemAction" )
        Case $ODA_DRAWENTIRE
          ; Set Header item texts
          Local $hDC = DllStructGetData( $tDRAWITEM, "hDC" )
          DllStructSetData( $tDRAWITEM, "Left", DllStructGetData($tDRAWITEM, "Left") + 6 ) ; 6 pixel left margin
          DllStructSetData( $tDRAWITEM, "Top", DllStructGetData($tDRAWITEM, "Top") + 6 )   ; 6 pixel top margin
          Switch DllStructGetData( $tDRAWITEM, "itemID" )
            Case 0
              DllCall( "user32.dll", "int", "DrawTextW", "handle", $hDC, "wstr", $aHeader[0][0], "int", StringLen( $aHeader[0][0] ), "ptr", DllStructGetPtr($tDRAWITEM, "Left"), "uint", 0 ) ; _WinAPI_DrawText
            Case 1
              DllCall( "user32.dll", "int", "DrawTextW", "handle", $hDC, "wstr", $aHeader[1][0], "int", StringLen( $aHeader[1][0] ), "ptr", DllStructGetPtr($tDRAWITEM, "Left"), "uint", 0 ) ; _WinAPI_DrawText
              DllStructSetData( $tDRAWITEM, "Top", DllStructGetData($tDRAWITEM, "Top") + 14 ) ; 14 pixels between lines
              DllCall( "user32.dll", "int", "DrawTextW", "handle", $hDC, "wstr", $aHeader[1][1], "int", StringLen( $aHeader[1][1] ), "ptr", DllStructGetPtr($tDRAWITEM, "Left"), "uint", 0 ) ; _WinAPI_DrawText
            Case 2
              DllCall( "user32.dll", "int", "DrawTextW", "handle", $hDC, "wstr", $aHeader[2][0], "int", StringLen( $aHeader[2][0] ), "ptr", DllStructGetPtr($tDRAWITEM, "Left"), "uint", 0 ) ; _WinAPI_DrawText
              DllStructSetData( $tDRAWITEM, "Top", DllStructGetData($tDRAWITEM, "Top") + 14 ) ; 14 pixels between lines
              DllCall( "user32.dll", "int", "DrawTextW", "handle", $hDC, "wstr", $aHeader[2][1], "int", StringLen( $aHeader[2][1] ), "ptr", DllStructGetPtr($tDRAWITEM, "Left"), "uint", 0 ) ; _WinAPI_DrawText
              DllStructSetData( $tDRAWITEM, "Top", DllStructGetData($tDRAWITEM, "Top") + 14 ) ; 14 pixels between lines
              DllCall( "user32.dll", "int", "DrawTextW", "handle", $hDC, "wstr", $aHeader[2][2], "int", StringLen( $aHeader[2][2] ), "ptr", DllStructGetPtr($tDRAWITEM, "Left"), "uint", 0 ) ; _WinAPI_DrawText
            Case 3
              DllCall( "user32.dll", "int", "DrawTextW", "handle", $hDC, "wstr", $aHeader[3][0], "int", StringLen( $aHeader[3][0] ), "ptr", DllStructGetPtr($tDRAWITEM, "Left"), "uint", 0 ) ; _WinAPI_DrawText
              DllStructSetData( $tDRAWITEM, "Top", DllStructGetData($tDRAWITEM, "Top") + 14 ) ; 14 pixels between lines
              DllCall( "user32.dll", "int", "DrawTextW", "handle", $hDC, "wstr", $aHeader[3][1], "int", StringLen( $aHeader[3][1] ), "ptr", DllStructGetPtr($tDRAWITEM, "Left"), "uint", 0 ) ; _WinAPI_DrawText
          EndSwitch
      EndSwitch
  EndSwitch
  Return $GUI_RUNDEFMSG
EndFunc

DrawItem.au3 (you need this):

#include-once
#include <StructureConstants.au3>

Global Const $tagDRAWITEM = _
  "uint CtlType;" & _
  "uint CtlID;" & _
  "uint itemID;" & _
  "uint itemAction;" & _
  "uint itemState;" & _
  "hwnd hwndItem;" & _
  "handle hDC;" & _
  $tagRECT & ";" & _ ; longs: Left, Top, Right, Bottom
  "ulong_ptr itemData"

; CtlType constants
Global Const $ODT_MENU      = 1
Global Const $ODT_LISTBOX   = 2
Global Const $ODT_COMBOBOX  = 3
Global Const $ODT_BUTTON    = 4
Global Const $ODT_STATIC    = 5
Global Const $ODT_HEADER    = 100
Global Const $ODT_TAB       = 101
Global Const $ODT_LISTVIEW  = 102

; itemAction constants
Global Const $ODA_DRAWENTIRE = 0x0001
Global Const $ODA_SELECT     = 0x0002
Global Const $ODA_FOCUS      = 0x0004

; itemState constants
Global Const $ODS_SELECTED     = 0x0001
Global Const $ODS_GRAYED       = 0x0002
Global Const $ODS_DISABLED     = 0x0004
Global Const $ODS_CHECKED      = 0x0008
Global Const $ODS_FOCUS        = 0x0010
Global Const $ODS_DEFAULT      = 0x0020
Global Const $ODS_HOTLIGHT     = 0x0040
Global Const $ODS_INACTIVE     = 0x0080
Global Const $ODS_NOACCEL      = 0x0100
Global Const $ODS_NOFOCUSRECT  = 0x0200
Global Const $ODS_COMBOBOXEDIT = 0x1000

 

3 people like this

Share this post


Link to post
Share on other sites

#10 ·  Posted (edited)

:thumbsup:

+5
mLipok

EDIT:
If you find a way to do the same with ListView Item than I can say :    LarsJ magnificent magician

Edited by mLipok

Signature beginning:   Wondering who uses AutoIT and what it can be used for ?
* GHAPI UDF - modest begining - comunication with GitHub REST API *
ADO.au3 UDF     POP3.au3 UDF     XML.au3 UDF    How to use IE.au3  UDF with  AutoIt v3.3.14.x  for other useful stuff click the following button

Spoiler

Any of my own code posted anywhere on the forum is available for use by others without any restriction of any kind. 

My contribution (my own projects): * Debenu Quick PDF Library - UDF * Debenu PDF Viewer SDK - UDF * Acrobat Reader - ActiveX Viewer * UDF for PDFCreator v1.x.x * XZip - UDF * AppCompatFlags UDF * CrowdinAPI UDF * _WinMergeCompare2Files() * _JavaExceptionAdd() * _IsBeta() * Writing DPI Awareness App - workaround * _AutoIt_RequiredVersion() * Chilkatsoft.au3 UDF * TeamViewer.au3 UDF * JavaManagement UDF * VIES over SOAP * WinSCP UDF * GHAPI UDF - modest begining - comunication with GitHub REST API *

My contribution to others projects or UDF based on  others projects: * _sql.au3 UDF  * POP3.au3 UDF *  RTF Printer - UDF * XML.au3 - BETA * ADO.au3 UDF SMTP Mailer UDF *

Useful links: * Forum Rules * Forum etiquette *  Forum Information and FAQs * How to post code on the forum * AutoIt Online Documentation * AutoIt Online Beta Documentation * SciTE4AutoIt3 getting started * Convert text blocks to AutoIt code * Games made in Autoit * Programming related sites * Polish AutoIt Tutorial * DllCall Code Generator * 

Wiki: Expand your knowledge - AutoIt Wiki * Collection of User Defined Functions * How to use HelpFile * Best coding practices * 

IE Related:  * How to use IE.au3  UDF with  AutoIt v3.3.14.x * Why isn't Autoit able to click a Javascript Dialog? * Clicking javascript button with no ID * IE document >> save as MHT file * IETab Switcher (by LarsJ ) * HTML Entities * _IEquerySelectorAll() (by uncommon) * 

I encourage you to read: * Global Vars * Best Coding Practices * Please explain code used in Help file for several File functions * OOP-like approach in AutoIt * UDF-Spec Questions *  EXAMPLE: How To Catch ConsoleWrite() output to a file or to CMD *

"Homo sum; humani nil a me alienum puto" - Publius Terentius Afer
"Program are meant to be read by humans and only incidentally for computers and execute" - Donald Knuth, "The Art of Computer Programming"
:naughty:  :ranting:, be  :) and       \\//_.

Anticipating Errors :  "Any program that accepts data from a user must include code to validate that data before sending it to the data store. You cannot rely on the data store, ...., or even your programming language to notify you of problems. You must check every byte entered by your users, making sure that data is the correct type for its field and that required fields are not empty."

Signature last update: 2017-06-04

Share this post


Link to post
Share on other sites

LarsJ, that is MOST AWESOME.

Good work!

Share this post


Link to post
Share on other sites

Here another workaround:

#include <GUIConstantsEx.au3>
#include <GuiHeader.au3>
#include <GuiImageList.au3>
#include <GDIPlus.au3>
#include <WindowsConstants.au3>


Global $g_hGUI, $g_idMemo, $g_hHeader

Example()

Func Example()
    Local $g_hGUI, $tRect, $tPos, $iHeight_Column = 40

    _GDIPlus_Startup()
    ; Create GUI
    $g_hGUI = GUICreate("Header", 400, 300)
    $g_hHeader = _GUICtrlHeader_Create($g_hGUI, $HDS_FLAT)
    _GUICtrlHeader_SetUnicodeFormat($g_hHeader, True)
    $g_idMemo = GUICtrlCreateEdit("", 1, 40, 398, 259, 0)
    GUICtrlSetFont($g_idMemo, 9, 400, 0, "Courier New")
    GUISetState(@SW_SHOW)

    $tRect = _WinAPI_GetClientRect( $g_hHeader )
    $tPos = _GUICtrlHeader_Layout( $g_hHeader, $tRect )
    _WinAPI_SetWindowPos( $g_hHeader, DllStructGetData( $tPos, "InsertAfter" ), _
                                      DllStructGetData( $tPos, "X" ), DllStructGetData( $tPos, "Y" ), _
                                      DllStructGetData( $tPos, "CX" ), $iHeight_Column, DllStructGetData( $tPos, "Flags" ) )



    $hImage = _GUIImageList_Create(0, 0, 6)

    ; Add columns
    _GUICtrlHeader_AddItem($g_hHeader, "", 100, 1, 0)
    _GUICtrlHeader_AddItem($g_hHeader, "Column 2", 100, 0, 1)
    _GUICtrlHeader_AddItem($g_hHeader, "Column 3", 100, 0, 2)
    _GUICtrlHeader_AddItem($g_hHeader, "Column 4", 100)

    Local $iBgColor = _WinAPI_GetSysColor($COLOR_MENU) ;I don'T know which color index is the correct one
    ConsoleWrite(Hex($iBgColor, 6) & @CRLF)

    $hHBitmap = _GDIPlus_DrwTxt(" Line 1" & @CRLF & " Line 2", 90, $iHeight_Column, 0xFFFCFCFC)
    _GUICtrlHeader_SetItemBitmap($g_hHeader, 0, $hHBitmap)
    _GUICtrlHeader_SetImageList($g_hHeader, $hImage)


    ; Loop until the user exits.
    Do
    Until GUIGetMsg() = $GUI_EVENT_CLOSE

    _WinAPI_DeleteObject($hHBitmap)
    _GDIPlus_Shutdown()
EndFunc   ;==>Example

Func _GDIPlus_DrwTxt($sText, $iW, $iH, $iBgColor = 0xFFF0F0F0, $iFontSize = 8.5, $sFont = "MS Shell Dlg", $iAlign = 0, $iFontColor = 0xFF000000, $bAntiAlias = False)
    Local Const $hBitmap = _GDIPlus_BitmapCreateFromScan0($iW, $iH)
    Local Const $hCtxt = _GDIPlus_ImageGetGraphicsContext($hBitmap)
    _GDIPlus_GraphicsClear($hCtxt, $iBgColor)
    If $bAntiAlias Then
        _GDIPlus_GraphicsSetSmoothingMode($hCtxt, 2)
        _GDIPlus_GraphicsSetTextRenderingHint($hCtxt, 4)
    EndIf
    Local Const $hBrush = _GDIPlus_BrushCreateSolid($iFontColor)
    Local Const $hFormat = _GDIPlus_StringFormatCreate()
    Local Const $hFamily = _GDIPlus_FontFamilyCreate($sFont)
    Local Const $hFont = _GDIPlus_FontCreate($hFamily, $iFontSize)
    _GDIPlus_StringFormatSetAlign($hFormat, $iAlign)
    _GDIPlus_StringFormatSetLineAlign($hFormat, 1)
    Local $tLayout = _GDIPlus_RectFCreate(0, 0, $iW, $iH)
    _GDIPlus_GraphicsDrawStringEx($hCtxt, $sText, $hFont, $tLayout, $hFormat, $hBrush)
    _GDIPlus_FontDispose($hFont)
    _GDIPlus_FontFamilyDispose($hFamily)
    _GDIPlus_StringFormatDispose($hFormat)
    _GDIPlus_BrushDispose($hBrush)
    _GDIPlus_GraphicsDispose($hCtxt)
    Local Const $hHBitmap = _GDIPlus_BitmapCreateHBITMAPFromBitmap($hBitmap)
    _GDIPlus_BitmapDispose($hBitmap)
    Return $hHBitmap
EndFunc

 

3 people like this

Please don't send me any personal message and ask for support! I will not reply!

Selection of finest graphical examples at Codepen.io

The own fart smells best!
Her 'sikim hıyar' diyene bir avuç tuz alıp koşma!
¯\_(ツ)_/¯  ٩(●̮̮̃•̃)۶ ٩(-̮̮̃-̃)۶ૐ

Share this post


Link to post
Share on other sites

Thanks UEZ !!

Very cool !

Share this post


Link to post
Share on other sites

Here you are. To use multiple lines in a header control included in a listview it's much easier to use custom drawn header items than owner drawn. And then you must know how to increase the height of the header control so that the listview will be aware of the increased height.

To increase the height of the header control you can set a new font for the header control with the correct height:

$hFont = _WinAPI_CreateFont( 54, 0 ) ; Height = 54
_WinAPI_SetFont( $hHeader, $hFont )

Before you can set the height in this way you must disable themes:

_WinAPI_SetWindowTheme( $hHeader, "", "" )

Custom drawing of the header items is performed through WM_NOTIFY messages. The $CDDS_ITEMPREPAINT part of the drawing stage does the default drawing. And the $CDDS_ITEMPOSTPAINT part does the custom drawing.

So far the code works only as 32-bit. I don't know why it doesn't work as 64 bit. I'll look into it.

#include <GUIConstants.au3>
#include <GuiListView.au3>
#include <WinAPITheme.au3>
#include <WinAPI.au3>

Opt( "MustDeclareVars", 1 )

Global Const $tagNMCUSTOMDRAW = "struct;" & $tagNMHDR & ";dword dwDrawStage;handle hdc;" & $tagRECT & _
  ";dword_ptr dwItemSpec;uint uItemState;lparam lItemlParam;endstruct"

Global $hHeader, $hHeaderfont
Global $aHeaderTexts = [ [ "Column 1", "",       ""       ], _
                         [ "Column 2", "Line 2", ""       ], _
                         [ "Column 3", "Line 2", "Line 3" ], _
                         [ "Column 4", "Line 2", ""       ] ]

Example()


Func Example()
  ; Create GUI
  Local $hGui = GUICreate( "ListView with multiple-line header", 400, 300, -1, 300 )

  ; Create ListView
  Local $idLV = GUICtrlCreateListView( "", 10, 10, 380, 280 )
  Local $hLV = GUICtrlGetHandle( $idLV )
  _GUICtrlListView_AddColumn( $hLV, "", 94 )
  _GUICtrlListView_AddColumn( $hLV, "", 94 )
  _GUICtrlListView_AddColumn( $hLV, "", 94 )
  _GUICtrlListView_AddColumn( $hLV, "", 94 )

  ; ListView Header
  $hHeader = _GUICtrlListView_GetHeader( $hLV )

  ; Get the font of the Header control
  ; Copied from the _GUICtrlGetFont example by KaFu
  ; See http://www.autoitscript.com/forum/index.php?showtopic=124526
  Local $hDC = _WinAPI_GetDC( $hHeader ), $hFont = _SendMessage( $hHeader, $WM_GETFONT ), $hObject = _WinAPI_SelectObject( $hDC, $hFont ), $lvLOGFONT = DllStructCreate( $tagLOGFONT )
  DllCall( "gdi32.dll", "int", "GetObjectW", "ptr", $hFont, "int", DllStructGetSize( $lvLOGFONT ), "struct*", $lvLOGFONT )
  _WinAPI_SelectObject( $hDC, $hObject )
  _WinAPI_ReleaseDC( $hHeader, $hDC )
  $hHeaderfont = _WinAPI_CreateFontIndirect( $lvLOGFONT )

  ; Remove Header themes
  _WinAPI_SetWindowTheme( $hHeader, "", "" )

  ; Set Header font
  ; To set the height of the Header control
  $hFont = _WinAPI_CreateFont( 54, 0 ) ; Height = 54
  _WinAPI_SetFont( $hHeader, $hFont )

  ; Fill ListView
  For $i = 0 To 9
    GUICtrlCreateListViewItem( $i & "/1|" & $i & "/2|" & $i & "/3|" & $i & "/4", $idLV )
  Next

  ; WM_NOTIFY message handler
  ; For custom draw of Header items
  GUIRegisterMsg( $WM_NOTIFY, "WM_NOTIFY" )

  ; Show GUI
  GUISetState()

  While 1
    Switch GUIGetMsg()
      Case $GUI_EVENT_CLOSE
        ExitLoop
    EndSwitch
  WEnd

  GUIDelete( $hGui )
EndFunc

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 $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        ; Performs default painting
              Return $CDRF_NOTIFYPOSTPAINT     ; Notify parent window of any post item related drawing operations

            Case $CDDS_ITEMPOSTPAINT
              ; After an item is drawn         ; Performs custom painting
              Local $dwItemSpec = DllStructGetData( $tNMCUSTOMDRAW, "dwItemSpec" )                          ; Item index
              Local $hDC = DllStructGetData( $tNMCUSTOMDRAW, "hdc" )
              _WinAPI_SelectObject( $hDC, $hHeaderfont )
              DllStructSetData( $tNMCUSTOMDRAW, "Left", DllStructGetData( $tNMCUSTOMDRAW, "Left" ) + 6 )    ; 6 pixel left margin
              DllStructSetData( $tNMCUSTOMDRAW, "Top", DllStructGetData( $tNMCUSTOMDRAW, "Top" ) + 6 )      ; 6 pixel top margin
              DllCall( "user32.dll", "int", "DrawTextW", "handle", $hDC, "wstr", $aHeaderTexts[$dwItemSpec][0], "int", StringLen( $aHeaderTexts[$dwItemSpec][0] ), "ptr", DllStructGetPtr( $tNMCUSTOMDRAW, "Left" ), "uint", 0 ) ; _WinAPI_DrawText
              If $aHeaderTexts[$dwItemSpec][1] Then
                DllStructSetData( $tNMCUSTOMDRAW, "Top", DllStructGetData( $tNMCUSTOMDRAW, "Top" ) + 14 )   ; 14 pixels between lines
                DllCall( "user32.dll", "int", "DrawTextW", "handle", $hDC, "wstr", $aHeaderTexts[$dwItemSpec][1], "int", StringLen( $aHeaderTexts[$dwItemSpec][1] ), "ptr", DllStructGetPtr( $tNMCUSTOMDRAW, "Left" ), "uint", 0 ) ; _WinAPI_DrawText
                If $aHeaderTexts[$dwItemSpec][2] Then
                  DllStructSetData( $tNMCUSTOMDRAW, "Top", DllStructGetData( $tNMCUSTOMDRAW, "Top" ) + 14 ) ; 14 pixels between lines
                  DllCall( "user32.dll", "int", "DrawTextW", "handle", $hDC, "wstr", $aHeaderTexts[$dwItemSpec][2], "int", StringLen( $aHeaderTexts[$dwItemSpec][2] ), "ptr", DllStructGetPtr( $tNMCUSTOMDRAW, "Left" ), "uint", 0 ) ; _WinAPI_DrawText
                EndIf
              EndIf
              Return $CDRF_NEWFONT             ; $CDRF_NEWFONT must be returned after changing font or colors
          EndSwitch
      EndSwitch
  EndSwitch

  Return $GUI_RUNDEFMSG
EndFunc

 

Share this post


Link to post
Share on other sites

#15 ·  Posted (edited)

When the header control is included in the listview it's a child of the listview. To be able to read messages from the header the listview must be subclassed like this:

Local $hOldListViewWndProc = _WinAPI_SetWindowLong( $hLV, $GWL_WNDPROC, DllCallbackGetPtr( DllCallbackRegister( "NewListViewProc", "lresult", "hwnd;uint;wparam;lparam" ) ) )

Then the owner drawn header is working on both 32 and 64 bit. I have not tested the custom drawn header, but I think it's working. This is code for the owner drawn header.

LvHeader.au3 (run this)

#include <GUIConstants.au3>
#include <GuiListView.au3>
#include <WinAPITheme.au3>
#include <WinAPI.au3>
#include "DrawItem.au3"

Opt( "MustDeclareVars", 1 )

Global $hHeader
Global $aHeaderTexts = [ [ "Column 1", "",       ""       ], _
                         [ "Column 2", "Line 2", ""       ], _
                         [ "Column 3", "Line 2", "Line 3" ], _
                         [ "Column 4", "Line 2", ""       ] ]

Example()


Func Example()
  ; Create GUI
  Local $hGui = GUICreate( "ListView with multiple-line header", 400, 300, -1, 300 )

  ; Create ListView
  Local $idLV = GUICtrlCreateListView( "", 10, 10, 380, 280 )
  Local $hLV = GUICtrlGetHandle( $idLV )

  ; ListView Header
  $hHeader = _GUICtrlListView_GetHeader( $hLV )

  ; Remove Header themes
  _WinAPI_SetWindowTheme( $hHeader, "", "" )

  ; Get the font of the Header control
  ; Copied from the _GUICtrlGetFont example by KaFu
  ; See http://www.autoitscript.com/forum/index.php?showtopic=124526
  Local $hDC = _WinAPI_GetDC( $hHeader ), $hFont = _SendMessage( $hHeader, $WM_GETFONT ), $hObject = _WinAPI_SelectObject( $hDC, $hFont ), $lvLOGFONT = DllStructCreate( $tagLOGFONT )
  DllCall( "gdi32.dll", "int", "GetObjectW", "ptr", $hFont, "int", DllStructGetSize( $lvLOGFONT ), "struct*", $lvLOGFONT )
  _WinAPI_SelectObject( $hDC, $hObject )
  _WinAPI_ReleaseDC( $hHeader, $hDC )
  Local $hHeaderfont = _WinAPI_CreateFontIndirect( $lvLOGFONT )

  ; Set Header font
  ; To set the height of the Header control
  $hFont = _WinAPI_CreateFont( 54, 0 ) ; Height = 54
  _WinAPI_SetFont( $hHeader, $hFont )

  ; Add ListView columns
  _GUICtrlListView_AddColumn( $hLV, "", 94 )
  _GUICtrlListView_AddColumn( $hLV, "", 94 )
  _GUICtrlListView_AddColumn( $hLV, "", 94 )
  _GUICtrlListView_AddColumn( $hLV, "", 94 )

  ; Set all Header items owner drawn
  Local $tItem = DllStructCreate( $tagHDITEM )
  DllStructSetData( $tItem, "Mask", $HDI_FORMAT )
  For $i = 0 To 3
    _GUICtrlHeader_GetItem( $hHeader, $i, $tItem )
    DllStructSetData( $tItem, "Fmt", $HDF_OWNERDRAW )
    _GUICtrlHeader_SetItem( $hHeader, $i, $tItem )
  Next

  ; Fill ListView
  For $i = 0 To 9
    GUICtrlCreateListViewItem( $i & "/1|" & $i & "/2|" & $i & "/3|" & $i & "/4", $idLV )
  Next

  ; Subclass ListView control
  ; Required to be able to read messages from the Header control which is a child of the ListView control
  Local $hOldListViewWndProc = _WinAPI_SetWindowLong( $hLV, $GWL_WNDPROC, DllCallbackGetPtr( DllCallbackRegister( "NewListViewProc", "lresult", "hwnd;uint;wparam;lparam" ) ) )
  NewListViewProc( 0, 0, $hHeaderfont, $hOldListViewWndProc ) ; $hHeaderfont and $hOldListViewWndProc are stored in local statics to avoid globals

  ; Show GUI
  GUISetState()

  While 1
    Switch GUIGetMsg()
      Case $GUI_EVENT_CLOSE
        ExitLoop
    EndSwitch
  WEnd

  GUIDelete( $hGui )
EndFunc

Func NewListViewProc( $hWnd, $iMsg, $wParam, $lParam )
  Local Static $hHeaderfont = $wParam, $hOldListViewWndProc = $lParam
  Switch $iMsg
    Case $WM_DRAWITEM
      Local $tDRAWITEM = DllStructCreate( $tagDRAWITEM, $lParam )
      If DllStructGetData( $tDRAWITEM, "CtlType" ) <> $ODT_HEADER Then Return $GUI_RUNDEFMSG

      Switch DllStructGetData( $tDRAWITEM, "hwndItem" )
        Case $hHeader
          Switch DllStructGetData( $tDRAWITEM, "itemAction" )
            Case $ODA_DRAWENTIRE
              ; Set Header item texts
              Local $hDC = DllStructGetData( $tDRAWITEM, "hDC" )
              _WinAPI_SelectObject( $hDC, $hHeaderfont )
              DllStructSetData( $tDRAWITEM, "Left", DllStructGetData($tDRAWITEM, "Left") + 6 ) ; 6 pixel left margin
              DllStructSetData( $tDRAWITEM, "Top", DllStructGetData($tDRAWITEM, "Top") + 6 )   ; 6 pixel top margin
              Local $itemID = DllStructGetData( $tDRAWITEM, "itemID" )
              DllCall( "user32.dll", "int", "DrawTextW", "handle", $hDC, "wstr", $aHeaderTexts[$itemID][0], "int", StringLen( $aHeaderTexts[$itemID][0] ), "ptr", DllStructGetPtr( $tDRAWITEM, "Left" ), "uint", 0 ) ; _WinAPI_DrawText
              If $aHeaderTexts[$itemID][1] Then
                DllStructSetData( $tDRAWITEM, "Top", DllStructGetData( $tDRAWITEM, "Top" ) + 14 )   ; 14 pixels between lines
                DllCall( "user32.dll", "int", "DrawTextW", "handle", $hDC, "wstr", $aHeaderTexts[$itemID][1], "int", StringLen( $aHeaderTexts[$itemID][1] ), "ptr", DllStructGetPtr( $tDRAWITEM, "Left" ), "uint", 0 ) ; _WinAPI_DrawText
                If $aHeaderTexts[$itemID][2] Then
                  DllStructSetData( $tDRAWITEM, "Top", DllStructGetData( $tDRAWITEM, "Top" ) + 14 ) ; 14 pixels between lines
                  DllCall( "user32.dll", "int", "DrawTextW", "handle", $hDC, "wstr", $aHeaderTexts[$itemID][2], "int", StringLen( $aHeaderTexts[$itemID][2] ), "ptr", DllStructGetPtr( $tDRAWITEM, "Left" ), "uint", 0 ) ; _WinAPI_DrawText
                EndIf
              EndIf
          EndSwitch
      EndSwitch
  EndSwitch

  ; To be on the safe side, take this issue into account:
  ; http://www.autoitscript.com/forum/index.php?showtopic=159155
  Return DllCall("user32.dll", "lresult", "CallWindowProc", "ptr", $hOldListViewWndProc, "hwnd", $hWnd, "uint", $iMsg, "wparam", $wParam, "lparam", $lParam)[0]
EndFunc

DrawItem.au3 (included)

#include-once
#include <StructureConstants.au3>

Global Const $tagDRAWITEM = _
  "uint CtlType;" & _
  "uint CtlID;" & _
  "uint itemID;" & _
  "uint itemAction;" & _
  "uint itemState;" & _
  "hwnd hwndItem;" & _
  "handle hDC;" & _
  $tagRECT & ";" & _ ; longs: Left, Top, Right, Bottom
  "ulong_ptr itemData"

; CtlType constants
Global Const $ODT_MENU      = 1
Global Const $ODT_LISTBOX   = 2
Global Const $ODT_COMBOBOX  = 3
Global Const $ODT_BUTTON    = 4
Global Const $ODT_STATIC    = 5
Global Const $ODT_HEADER    = 100
Global Const $ODT_TAB       = 101
Global Const $ODT_LISTVIEW  = 102

; itemAction constants
Global Const $ODA_DRAWENTIRE = 0x0001
Global Const $ODA_SELECT     = 0x0002
Global Const $ODA_FOCUS      = 0x0004

; itemState constants
Global Const $ODS_SELECTED     = 0x0001
Global Const $ODS_GRAYED       = 0x0002
Global Const $ODS_DISABLED     = 0x0004
Global Const $ODS_CHECKED      = 0x0008
Global Const $ODS_FOCUS        = 0x0010
Global Const $ODS_DEFAULT      = 0x0020
Global Const $ODS_HOTLIGHT     = 0x0040
Global Const $ODS_INACTIVE     = 0x0080
Global Const $ODS_NOACCEL      = 0x0100
Global Const $ODS_NOFOCUSRECT  = 0x0200
Global Const $ODS_COMBOBOXEDIT = 0x1000

I'll not add more code here. But I think it is an interesting example. I'll spend some more time to go through it all. Then I'll add an example in the Examples forum.

Edited by LarsJ

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