• Welcome to Jose's Read Only Forum 2023.
 

Multiline header listview works but header is blank

Started by Chris Chancellor, November 07, 2018, 05:34:40 AM

Previous topic - Next topic

0 Members and 1 Guest are viewing this topic.

Chris Chancellor

Hello All

Finally i was able to get the Multiline header listview working but its header is still blank despite that
it has allocated  vertical space for the multilines

see the screen shot below

appreciate if someone can help me to get the header fill up,  which i notice that in PB  we use WSTRINGZ* 260

but there is no equivalent of WSTRINGZ* 260  in O2 ??

so without the WSTRINGZ* 260  , it cannot display the header

Chris Chancellor

the listing and other files for this program is attached in the zip file

we are very close to resolving this problem, hope someone can help me here

Charles Pegge

#2
Hi Chris,

glad to see you are making headway with this code.

            ASCIIZ*260  szText
         '  WSTRING  szText

wchar szText [260]

Chris Chancellor

Thanxx Charles

i have replace the    string   szText   with   wchar [260]  szText  as shown below in the function ListView_SubclassProc ()


' ========================================================================================
' Processes messages for the subclassed ListView control.
FUNCTION ListView_SubclassProc ( _
   BYVAL hWnd   AS sys, _         
   BYVAL utMsg   AS uint, _             
   BYVAL wParam AS sys, _               
   BYVAL lParam AS sys ) AS sys callback

         
   '  REQUIRED: Get the address of the original window procedure
     sys pOldWndProc
     pOldWndProc = GetProp(hWnd, "OLDWNDPROC")

   SELECT CASE utMsg

      CASE WM_DESTROY
         '  REQUIRED: Remove control subclassing
           RemoveProp(hWnd, "OLDWNDPROC", GetWindowLongPtr(hWnd, GWLP_WNDPROC, @ListView_SubclassProc))


      CASE WM_NOTIFY
            NMHDR PTR  pnmh   
            NMCUSTOMDRAW PTR  pnmcd
          ' string   szText
           wchar [260]  szText
         '  WSTRING  szText

        @pnmh = lParam
        SELECT CASE pnmh.code
            CASE  NM_CUSTOMDRAW
                   @pnmcd = lParam

               '  Check the drawing stage
                       SELECT CASE pnmcd.dwDrawStage
                  '     Prior to painting
              CASE  CDDS_PREPAINT
                     '  Tell Windows we want individual notification
                     '  of each item being drawn
                     FUNCTION = CDRF_NOTIFYITEMDRAW
                     EXIT FUNCTION

                  '  Notification of each item being drawn
                  CASE  CDDS_ITEMPREPAINT

                     sys hLvHeader
                     sys nIndex
                     sys nState

                     nIndex = pnmcd.dwItemSpec
                     nState = pnmcd.uItemState

                  '  Get the header item text...
                     HD_ITEMA hdi
                     hdi.mask = HDI_TEXT
                  hdi.pszText = VARPTR(szText)
                     hdi.cchtextmax = SIZEOF(szText)
                     hLvHeader = ListView_GetHeader(hWnd)
                     Header_GetItemA(hLvHeader, nIndex, hdi)

                  '  Create a new font
                     sys hFont
                     hFont = O2ApiCreateFont("Tahoma", 10, FW_BOLD)
                     ' Select the font into the current devide context
                      sys hOldFont
                      hOldFont = SelectObject(pnmcd.hdc, hFont)

                     ' Draw the button state...
                     IF (nState AND CDIS_SELECTED) THEN
                         DrawFrameControl pnmcd.hdc, pnmcd.rc, _
                             DFC_BUTTON, DFCS_BUTTONPUSH OR DFCS_PUSHED
                     ELSE
                         DrawFrameControl pnmcd.hdc, pnmcd.rc, _
                             DFC_BUTTON, DFCS_BUTTONPUSH
                     END IF

                     '  Color the header background
                     sys hBrush
                     hBrush = CreateSolidBrush(RGB(243,250,5))    ' <------------ Change color
                        InflateRect pnmcd.rc, -2, -2
                        FillRect pnmcd.hdc, pnmcd.rc, hBrush
                       SetBkMode pnmcd.hdc, TRANSPARENT

                     '  Color the header text
                  '       SetTextColor pnmcd.hdc, RGB(40,45,215)      ' <------------ Change color
                         SetTextColor pnmcd.hdc, RGB(0,0,215)

                     '  Offset the text slightly if depressed...
                        IF (nState AND CDIS_SELECTED) THEN
                               InflateRect pnmcd.rc, -2, -2
                         END IF

                     '  Draw multiline, using carriage returns (i.e. szText = "Customer" + CR + "number")
                            DrawText pnmcd.hdc, szText, LEN(szText), pnmcd.rc, DT_CENTER OR DT_VCENTER


                     '  Cleanup
                     IF hBrush THEN
                        DeleteObject hBrush
                     END IF
                     IF hOldFont THEN
                             SelectObject pnmcd.hdc, hOldFont
                     END IF
                     IF hFont THEN
                         DeleteObject hFont
                     END IF

                     ' Tell Windows the item has already been drawn
                     FUNCTION = CDRF_SKIPDEFAULT
                     EXIT FUNCTION

               END SELECT

         END SELECT

   END SELECT

   FUNCTION = CallWindowProc(pOldWndProc, hWnd, utMsg, wParam, lParam)

END FUNCTION



but the program just GPF
maybe at this point ??

hdi.pszText = VARPTR(szText)


this must be a pointer problem here bcos O2 will normally GPF when there is a pointer or
out of dimension array problems


Chris Chancellor

Thanxx Charles

with 
  wchar szText [260]

  it is still the same --> blank headers but don't GPF

need some tinkling on 

hdi.pszText = VARPTR(szText)

José Roca

You're returning a pointer to a local string. Make it global or static.

Chris Chancellor

Thanxx Jose

i had changed sztext to global but still the headers are blank

Charles Pegge

Do you need a wchar or is it a char? The header specifies psztxt as asciiz ptr.

varptr is not needed but it resolves correctly


TYPE HD_ITEM
   Mask       AS  uint          ' UINT    mask
   cxy        AS LONG         ' int     cxy
   pszText    AS ASCIIZ PTR   ' LPSTR   pszText
   hbm        AS sys                ' HBITMAP hbm
   cchTextMax AS LONG         ' int     cchTextMax
   fmt        AS LONG            ' int     fmt
   lParam     AS sys         ' LPARAM  lParam
   iImage     AS LONG         ' int     iImage  // index of bitmap in ImageList
   iOrder     AS LONG         ' int     iOrder  // where to draw this item
   pvFilter   AS sys        ' void *  pvFilter  // [in] fillter data see above
   state      AS sys
END TYPE



Chris Chancellor

i also tried using global char*260  szText  but without success


'Header text     
' wchar szText[260]
char*260  szText



Charles Pegge

#9
try:
static char szText[260]

and remove the varptr

Chris Chancellor


Thanxx Charles but this did not work

as you see i'm now using  type HD_ITEMA  instead of HD_ITEM
and Header_GetItemA()  instead of Header_GetItem()


listing for ColorListView_MH.o2bas

'====================================================================
' Color Listview example  modified Nov 4 2018
'  which you can change fonts and color of text and background
' with Multi Line Header
'====================================================================
$ filename "ColorListView_MH.exe"
use rtl64

#lookahead
% review

uses dialogs
uses O2Common


'Identifier for ListView
#define IDC_LSV1  3801


'  The program logo icon  is obtained from the resource file
'  the 400 must corespondence to the 400 in the rc file
   #define IDI_LOGO     400
   % ICON_BIG=1
   % WM_SETICON=0x80

' control ID of statusbar
% IDC_Statusbar  420


macro ListView_InsertColumn(hwnd,iCol,pcol) (SendMessage(hwnd, LVM_INSERTCOLUMN, iCol, pcol))
macro ListView_SetColumnWidth(hwnd,iCol,cx) (SendMessage(hwnd, LVM_SETCOLUMNWIDTH, iCol, cx))
macro ListView_InsertItem(hwnd,pitem) (SendMessage(hwnd, LVM_INSERTITEM,0, pitem))
macro ListView_SetItem(hwnd,pitem) (SendMessage(hwnd, LVM_SETITEM,0, pitem))



% DS_CENTER=0x0800
% DS_MODALFRAME=0x80
% SS_CENTERIMAGE=0x200
% LVS_LIST  0x0003
% LVS_REPORT  0x0001
% LVS_EX_GRIDLINES 1
% LVS_EX_CHECKBOXES 4
% LVS_EX_FULLROWSELECT  0x0020

%  LVS_SINGLESEL = 0x0004
%  LVS_EX_DOUBLEBUFFER = 0x0010000

% LVSCW_AUTOSIZE  -1
% LVSCW_AUTOSIZE_USEHEADER  -2

' % LVM_INSERTCOLUMN=4123
' % LVM_SETCOLUMNWIDTH=4126
' % LVM_INSERTITEM=4103
' % LVM_SETITEM=4102

% LVCF_FMT 1
% LVCF_WIDTH 2
% LVCF_TEXT=4
% LVCF_SUBITEM 8
% LVCF_ORDER = 20
% LVIF_TEXT=1
% LVM_SETEXTENDEDLISTVIEWSTYLE 0x1036
% LVN_COLUMNCLICK = -108
% LVN_ITEMCHANGED = -101
% NM_CLICK -2

% LR_LOADFROMFILE=0x0010
% IMAGE_ICON=1
% STM_SETIMAGE=0x172
% SWP_NOZORDER=4

' Statusbar
% SB_SETPARTS 0x404
% SB_SETTEXT 0x401
% SBS_SIZEGRIP 16
% CCS_BOTTOM 3



' ListView messages
%  LVM_FIRST = &H1000
%  LVM_SETBKCOLOR = LVM_FIRST + 1
%  LVM_SETTEXTCOLOR       = LVM_FIRST + 36
%  LVM_GETHEADER          =  LVM_FIRST + 31

% LVM_INSERTCOLUMN=  LVM_FIRST + 27
% LVM_SETCOLUMNWIDTH=LVM_FIRST + 30
% LVM_INSERTITEM=%LVM_FIRST + 7
% LVM_SETITEM=LVM_FIRST + 6




%  CLR_NONE = &HFFFFFFFF&
% GWLP_WNDPROC= -4



type LVCOLUMN
  uint  mask
  int   fmt
  int   cx
  char* pszText
  int   cchTextMax
  int   iSubItem
  int   iImage
  int   iOrder
  int   cxMin
  int   cxDefault
  int   cxIdeal 
end type
typedef LVCOLUMN LV_COLUMN

type LVITEM 
  uint   mask
  int    iItem
  int    iSubItem
  uint   state
  uint   stateMask
  char*  pszText
  int    cchTextMax
  int    iImage       // index of the list view item's icon
  sys    lParam       // 32-bit value to associate with item
  int    iIndent
  int    iGroupId
  uint   cColumns
  uint   *puColumns
  int    *piColFmt
  int    iGroup
end type

typedef LVITEM LV_ITEM


type NMLISTVIEW
  NMHDR hdr
  int   iItem
  int   iSubItem
  uint  uNewState
  uint  uOldState
  uint  uChanged
  POINT ptAction
  sys   lParam
end type

typedef NMLISTVIEW NM_LISTVIEW



' Number of rows in the ListView
   % NumRow = 200
'  Number of columns in the ListView  meaning 3 +1 = 4 columns
   % NumCol = 3   



! GetDlgItem lib "user32.dll" (sys hDlg, int nIDDlgItem) as sys
! IsDialogMessage lib "user32.dll" alias"IsDialogMessageA" (sys hDlg, sys lpMsg) as bool
! IsWindow lib "user32.dll" (sys hWnd) as bool

'Header text   --  did NOT work 
' wchar szText[260]
'  char*260  szText

uses MultiLineHDO2




   '  Handle for the Main Dialog
     sys hDlg

   ' Fonts handle
     sys  hFont
   
   '  Handle for the ListView
     sys hListview

'    Handle for status bar
    sys hStatus

   '  Row and column number of current cell
    Long CurrentCol, CurrentRow


'==========================================
' create and display the Listview
  SUB  DispListView

            int i , j
            string   txtStr

           LV_COLUMN     lvc
           LV_ITEM            lvi
         ' Setup the fonts for the ListView
           SendMessage(hListview,%WM_SETFONT,hFont,0)

  '  Subclass the ListView
     SetProp hListView, "OLDWNDPROC", _
        SetWindowLongPtr(hListView, GWLP_WNDPROC, @ListView_SubclassProc)

   '  Get the handle of the ListView header control and subclass it
     sys hLvHeader
    hLvHeader = ListView_GetHeader(hListView)
     IF hLvHeader = 0 THEN
         EXIT FUNCTION
      end if
 
     IF hLvHeader THEN
         SetProp hLvHeader, "OLDWNDPROC", _
         SetWindowLongPtr(hLvHeader, GWLP_WNDPROC, @LVHeader_SubclassProc)
      END IF       


        'Setup the  ListView Column Headers
      '        The  first column must have a wider width to accomodate the checkbox
               lvc.mask =    LVCF_WIDTH  or  LVCF_ORDER
           '    Need to add some blanks behind the header string label
         '    inorder to get a wider column
               txtStr="Column #" & str(1) +  "                      " +cr
              lvc.pszText = txtStr   
              lvc.iorder = 0     
              ListView_InsertColumn(hListview, 0, &lvc)

     '   All the other columns to have a narrower width
        For i = 1  To  NumCol 
              lvc.mask = LVCF_FMT OR   LVCF_WIDTH   OR  LVCF_TEXT  OR LVCF_SUBITEM
            If  i =  NumCol then
                   '   Leave the last column header blank as we are NOT putting data
                  '   into this last column ( it act like a buffer )
                      txtStr = ""
            Else
                  txtStr="Column #" & str(i+1) + cr + " level2  "
                  txtStr =  Trim(txtStr)
           End if
               lvc.pszText =  txtStr   
               lvc.iorder = i 
                ListView_InsertColumn(hListview, i, &lvc)
        Next i

 
        ' Setup the Listview  data Rows
        For i=1 To NumRow
              'First column
              lvi.mask      =  LVIF_TEXT
              txtStr = "Row #" & str(200-i+1) ", Col # 1"
             lvi.pszText   = txtStr
             lvi.iSubItem  =  0
             ListView_InsertItem(hListview, &lvi)

           'Remaining columns
           for j=2 to NumCol
                 txtStr = "Row #" & str(200-i+1) ", Col # " & str(j)
                lvi.pszText   = txtStr
                lvi.iSubItem  =  j-1
                ListView_SetItem(hListview, &lvi)
           next j
        Next i

   '   Set the column widths according to width of  each column header
       for i = 0 to NumCol -1
              ListView_SetColumnWidth(hListview,i,LVSCW_AUTOSIZE_USEHEADER)
        next i
   '  make the last column a very narrow width as it is only a buffer column
   '  this would display as a double line
       ListView_SetColumnWidth(hListview,NumCol,3)
 

  '    Place in the extended style for the listview
        SendMessage(hListview, LVM_SETEXTENDEDLISTVIEWSTYLE, 0, 
                       LVS_EX_FULLROWSELECT or LVS_EX_CHECKBOXES or LVS_EX_GRIDLINES )



    '  Shade those unused background portions of the main ListView to Alice Blue
'     while the text color is Navy
          SendMessage(hListView, LVM_SETTEXTCOLOR, 0,RGB(0,0,128))
          SendMessage(hListView, LVM_SETBKCOLOR, 0,RGB(240,248,255))
     

END SUB





'====================================================================
'   Main callback function
    Function DlgProc( hDlg, uint uMsg, sys wParam, lParam ) as sys callback

 
  '  Obtain the handle for the ListView
     hListview = GetDlgItem(hDlg, IDC_LSV1) 
   
   
 

  select case uMsg

     case WM_INITDIALOG
      ' display the program icon
            sys  hInstance = GetModuleHandle(NULL)
            sys hIcon = LoadIcon(hInstance, IDI_Logo)
           'Set Icon to Main Window
            SendMessage(hDlg, WM_SETICON, ICON_BIG, hIcon)

          ' Create and display the listview
            DispListView

         ' status bar
             CurrentRow = 1
             CurrentCol =  1
              UpdateStatusBar(hDlg)



    case WM_COMMAND

           select case loword(wParam)
                   case IDCANCEL   
         '            exit   
                     DeleteObject(hFont)
                     DestroyWindow( hDlg )
              end select


    case WM_NOTIFY
              NMHDR pnm at lParam
           

                if pnm.hwndFrom = hListview then
                           'ListView   
                     
                          NM_LISTVIEW LpLvNm at lParam

                         select case pnm.code
                         case LVN_COLUMNCLICK
                                   CurrentCol = LpLvNm.iSubItem + 1
                                    mbox "Header clicked at column  "    + str(CurrentCol)
                       
                        case LVN_ITEMCHANGED



                        CASE NM_CLICK     ' click on a cell
                                 NM_LISTVIEW LpLvNm at (lParam)
                                CurrentRow = LpLvNm.iiTem + 1
                                CurrentCol = LpLvNm.iSubItem + 1
                                UpdateStatusBar(hDlg)

                 end select
         end if
 

      case WM_SIZE     
               RECT rcClient
         // Calculate remaining height and size edit
              GetClientRect(hDlg, &rcClient)
              SetWindowPos(hListview, NULL, 0, rcClient.top, rcClient.right, rcClient.bottom, SWP_NOZORDER)
              UpdateStatusBar(hDlg)


    case WM_CLOSE
              DestroyWindow( hDlg )

    case WM_DESTROY
              PostQuitMessage( null )

  end select

  return 0
end function


'=====================
' The status bar displaying the current position of cursor
' and help text for each column
SUB UpdateStatusBar(sys hWnd)

   hStatus=GetDlgItem(hWnd, IDC_Statusbar)
   SendMessage(hStatus, SB_SETTEXT, 0, "Row " & str(CurrentRow) & "  :  " & "Col " & str(CurrentCol))

' Help text for each column when a particular column is clicked
   SELECT CASE CurrentCol
       CASE 1
            SendMessage(hStatus, SB_SETTEXT, 1, "Enter characters only")
       CASE 2
            SendMessage(hStatus, SB_SETTEXT, 1, "Enter numbers only")
       CASE 3
            SendMessage(hStatus, SB_SETTEXT, 1, "Enter Alphanumeric here")
   END SELECT
END SUB






'====================================================================
'  Display the Main Dialog
Function  DispMainDialog
     
         sys lpdt
         MSG wMsg

         dyn::init(lpdt)
   
       Dialog( 1, 10,10,250,200, "Listview example 64bits ", lpdt,
                  WS_OVERLAPPEDWINDOW or DS_CENTER or WS_VISIBLE or WS_CLIPCHILDREN or WS_THICKFRAME,
                                    8,"MS Sans Serif" )

    '   Add in the listview or  WS_BORDER
        CONTROL "",IDC_LSV1,"SysListView32", _
           WS_VISIBLE   or  WS_TABSTOP   or   LVS_REPORT  or  LVS_SINGLESEL or  LVS_EX_DOUBLEBUFFER , _
                             10,10,233,50,   WS_EX_CLIENTEDGE
     
         hFont = O2ApiCreateFont("Arial",9, FW_Bold)

         hDlg = CreateModelessDialog( 0, @DlgProc, 0, lpdt )
   
   hStatus = CreateStatusWindow(WS_CHILD | WS_BORDER | WS_VISIBLE | SBS_SIZEGRIP | CCS_BOTTOM, "", hDlg, IDC_Statusbar)
    'Statusbar set parts
    int statwidths[] = {100, -1}
    SendMessage(hStatus, SB_SETPARTS, 2, &statwidths)
    SendMessage(hStatus, SB_SETTEXT, 0, "Row : Col")
    UpdateStatusBar(hDlg)


       while GetMessage( @wMsg, null, 0, 0 ) <> 0
              if IsDialogMessage( hDlg,  @wMsg ) = 0 then
                            TranslateMessage( @wMsg )
                            DispatchMessage( @wMsg )
               end if
          wend
End Function



'------------------------------------
'  Start of program
   init_common_controls()
   printl " at start   LVM_GETHEADER  "   LVM_GETHEADER
   DispMainDialog








listing for MultiLineHDO2.inc

' MultiLineHDO2.inc
' MultiLine Header routines for O2

' Updated : Nov 4 2018

Type WINDOWPOS
hwnd As sys
hWndInsertAfter As sys
x As Long
y As Long
cx As Long
cy As Long
flags As Long
End Type




   ' // Size = 8 bytes
TYPE HD_LAYOUT
       RECT  PTR  prc                          ' RECT *prc
       WINDOWPOS PTR     pwpos         ' WINDOWPOS *pwpos
END TYPE




TYPE NMCUSTOMDRAW
   hdr         AS NMHDR   ' NMHDR     hdr
   dwDrawStage AS sys   ' DWORD     dwDrawStage
   hdc         AS sys   ' HDC       hdc
   rc          AS RECT    ' RECT      rc
   dwItemSpec  AS sys   ' DWORD_PTR dwItemSpec  // this is control specific, but it's how to specify an item. valid only with CDDS_ITEM bit set
   uItemState  AS uint     ' UINT      uItemState
   lItemlParam AS sys    ' LPARAM    lItemlParam
END TYPE


TYPE HD_ITEM
   Mask       AS  uint          ' UINT    mask
   cxy        AS LONG         ' int     cxy
   pszText    AS ASCIIZ PTR   ' LPSTR   pszText
   hbm        AS sys                ' HBITMAP hbm
   cchTextMax AS LONG         ' int     cchTextMax
   fmt        AS LONG            ' int     fmt
   lParam     AS sys         ' LPARAM  lParam
   iImage     AS LONG         ' int     iImage  // index of bitmap in ImageList
   iOrder     AS LONG         ' int     iOrder  // where to draw this item
   pvFilter   AS sys        ' void *  pvFilter  // [in] fillter data see above
   state      AS sys
END TYPE





TYPE HD_ITEMA
   Mask       AS sys        ' UINT    mask
   cxy        AS LONG         ' int     cxy
   pszText    AS ASCIIZ PTR   ' LPSTR   pszText
   hbm        AS sys        ' HBITMAP hbm
   cchTextMax AS LONG         ' int     cchTextMax
   fmt        AS LONG         ' int     fmt
   lParam     AS sys         ' LPARAM  lParam
   iImage     AS LONG         ' int     iImage  // index of bitmap in ImageList
   iOrder     AS LONG         ' int     iOrder  // where to draw this item
   pvFilter   AS sys        ' void *  pvFilter  // [in] fillter data see above
   state      AS sys
END TYPE








% SWP_FRAMECHANGED     = &H20
%  CDRF_NOTIFYITEMDRAW = &H20
%  CDRF_SKIPDEFAULT        = &H00000004
%  HDI_TEXT             = &H0002

%  CDDS_PREPAINT       = &H00000001
%  CDDS_ITEM               =  &H00010000
%  CDDS_ITEMPREPAINT       = CDDS_ITEM  OR  CDDS_PREPAINT

%  NM_FIRST = 0
%  NM_CUSTOMDRAW      =  NM_FIRST - 12

%  HDM_FIRST          =  &H1200
%  HDM_LAYOUT       =  HDM_FIRST + 5
%  HDM_GETITEMA    = HDM_FIRST + 3
%  HDM_GETITEMW   =  HDM_FIRST + 11

%  DT_CENTER              = &H00000001
%  DT_VCENTER             = &H00000004

'//   itemState flags
%  CDIS_SELECTED         = &H0001


%  DFC_BUTTON      = 4
%  DFCS_BUTTONPUSH       = &H0010
%  DFCS_PUSHED                = &H00000200

 


' ========================================================================================
' Gets the handle to the header control used by a list-view control.
' ========================================================================================
FUNCTION ListView_GetHeader (BYVAL hwndLV AS sys) AS sys
   FUNCTION = SendMessage(hwndLV, LVM_GETHEADER, 0, 0)
END FUNCTION


' ========================================================================================
FUNCTION Header_GetItemW (BYVAL hwndHD AS sys, BYVAL iItem AS sys, BYREF phdi AS HD_ITEM) AS sys
   FUNCTION = SendMessageW( hwndHD,  HDM_GETITEMW, iItem, VARPTR(phdi))
END FUNCTION


' ========================================================================================
' Gets information about an item in a header control.
' ========================================================================================
FUNCTION Header_GetItemA (BYVAL hwndHD AS sys, BYVAL iItem AS sys, BYREF phdi AS HD_ITEMA ) AS sys
    FUNCTION = SendMessage(hwndHD, HDM_GETITEMA, iItem, VARPTR(phdi))
  END FUNCTION



' ============================================================================
' Processes messages for the subclassed ListView header control.
FUNCTION LVHeader_SubclassProc(   BYVAL hwnd   AS sys   ,  BYVAL usMsg   AS uint , 
  BYVAL   wParam AS sys,   BYVAL lParam  AS sys ) AS sys callback
     
   
   SELECT  CASE  usMsg

      CASE  WM_DESTROY
         '  REQUIRED: Remove control subclassing
         SetWindowLongPtr hWnd, GWLP_WNDPROC, RemoveProp(hWnd, "OLDWNDPROC")

      CASE %HDM_LAYOUT
         '  Fill the WINDOWPOS structure with
         '  the appropriate size and position of the
         '  header control and change the top position
         '  of the rectangle that the header
         '  control will occupy.
         HD_LAYOUT phdl  at (lparam)
         phdl.pwpos.hwnd = hWnd
         phdl.pwpos.flags = SWP_FRAMECHANGED
         phdl.pwpos.x = phdl.prc.Left
         phdl.pwpos.y = 0
         phdl.pwpos.cx = phdl.prc.Right - phdl.prc.Left
         phdl.pwpos.cy = 40   ' --> change me
         phdl.prc.Top = 40   ' --> change me
         FUNCTION = -1
         EXIT FUNCTION

   END SELECT

   FUNCTION = CallWindowProc(GetProp(hWnd, "OLDWNDPROC"), hWnd, usMsg, wParam, lParam)

END FUNCTION



' ========================================================================================
' Processes messages for the subclassed ListView control.
FUNCTION ListView_SubclassProc ( _
   BYVAL hWnd   AS sys, _         
   BYVAL utMsg   AS uint, _             
   BYVAL wParam AS sys, _               
   BYVAL lParam AS sys ) AS sys callback

  ' Header text
   static char szText[260]

         
   '  REQUIRED: Get the address of the original window procedure
     sys pOldWndProc
     pOldWndProc = GetProp(hWnd, "OLDWNDPROC")

   SELECT CASE utMsg

      CASE WM_DESTROY
         '  REQUIRED: Remove control subclassing
           RemoveProp(hWnd, "OLDWNDPROC", GetWindowLongPtr(hWnd, GWLP_WNDPROC, @ListView_SubclassProc))


      CASE WM_NOTIFY
            NMHDR PTR  pnmh   
            NMCUSTOMDRAW PTR  pnmcd
       
       

        @pnmh = lParam
        SELECT CASE pnmh.code
            CASE  NM_CUSTOMDRAW
                   @pnmcd = lParam

               '  Check the drawing stage
                       SELECT CASE pnmcd.dwDrawStage
                  '     Prior to painting
              CASE  CDDS_PREPAINT
                     '  Tell Windows we want individual notification
                     '  of each item being drawn
                     FUNCTION = CDRF_NOTIFYITEMDRAW
                     EXIT FUNCTION

                  '  Notification of each item being drawn
                  CASE  CDDS_ITEMPREPAINT

                     sys hLvHeader
                     sys nIndex
                     sys nState

                     nIndex = pnmcd.dwItemSpec
                     nState = pnmcd.uItemState

                  '  Get the header item text...
                     HD_ITEMA hdi
                     hdi.mask = HDI_TEXT
                     hdi.pszText =  szText     'VARPTR(szText)
                     hdi.cchtextmax = SIZEOF(szText)
                     hLvHeader = ListView_GetHeader(hWnd)
                     Header_GetItemA(hLvHeader, nIndex, hdi)

                  '  Create a new font
                     sys hFont
                     hFont = O2ApiCreateFont("Tahoma", 10, FW_BOLD)
                     ' Select the font into the current devide context
                      sys hOldFont
                      hOldFont = SelectObject(pnmcd.hdc, hFont)

                     ' Draw the button state...
                     IF (nState AND CDIS_SELECTED) THEN
                         DrawFrameControl pnmcd.hdc, pnmcd.rc, _
                             DFC_BUTTON, DFCS_BUTTONPUSH OR DFCS_PUSHED
                     ELSE
                         DrawFrameControl pnmcd.hdc, pnmcd.rc, _
                             DFC_BUTTON, DFCS_BUTTONPUSH
                     END IF

                     '  Color the header background
                     sys hBrush
                     hBrush = CreateSolidBrush(RGB(243,250,5))    ' <------------ Change color
                        InflateRect pnmcd.rc, -2, -2
                        FillRect pnmcd.hdc, pnmcd.rc, hBrush
                       SetBkMode pnmcd.hdc, TRANSPARENT

                     '  Color the header text
                  '       SetTextColor pnmcd.hdc, RGB(40,45,215)      ' <------------ Change color
                         SetTextColor pnmcd.hdc, RGB(0,0,215)

                     '  Offset the text slightly if depressed...
                        IF (nState AND CDIS_SELECTED) THEN
                               InflateRect pnmcd.rc, -2, -2
                         END IF

                     '  Draw multiline, using carriage returns (i.e. szText = "Customer" + CR + "number")
                            DrawText pnmcd.hdc, szText, LEN(szText), pnmcd.rc, DT_CENTER OR DT_VCENTER


                     '  Cleanup
                     IF hBrush THEN
                        DeleteObject hBrush
                     END IF
                     IF hOldFont THEN
                             SelectObject pnmcd.hdc, hOldFont
                     END IF
                     IF hFont THEN
                         DeleteObject hFont
                     END IF

                     ' Tell Windows the item has already been drawn
                     FUNCTION = CDRF_SKIPDEFAULT
                     EXIT FUNCTION

               END SELECT

         END SELECT

   END SELECT

   FUNCTION = CallWindowProc(pOldWndProc, hWnd, utMsg, wParam, lParam)

END FUNCTION
             



Charles Pegge

We had some problems with negative equates sign-extending into 64 bit. You could try forcing them to be dwords.

for instance:

%  CLR_NONE = &HFFFFFFFF&
% GWLP_WNDPROC= -4

---->>

%  CLR_NONE = dword &HFFFFFFFF
% GWLP_WNDPROC= dword -4

https://www.oxygenbasic.org/forum/index.php?topic=1592.msg17568#msg17568

Chris Chancellor

when i use the dword fix

%  CLR_NONE = dword &HFFFFFFFF
% GWLP_WNDPROC= dword -4


the result is still blank headers        :-\