Announcement

Collapse
No announcement yet.

ListView's header columns with sort arrows ?

Collapse
X
 
  • Filter
  • Time
  • Show
Clear All
new posts

  • ListView's header columns with sort arrows ?

    Hi,

    Is-there a way to dynamically update a sortable ListView's header columns so that an up or down arrow image would appear next to the sorted column name depending on whether the column was sorted ascendingly or descendingly ?

    If not could it be done with other Grids (Egrid32, SiGrid, MLG, ...) ?

    Thanks,
    Jean-Pierre
    Jean-Pierre LEROY

  • #2
    Search here:
    Keywords listview sort
    Search Titles only
    Forum Source Code
    All dates

    =>>> http://www.powerbasic.com/support/pb...ad.php?t=23690
    Michael Mattias
    Tal Systems (retired)
    Port Washington WI USA
    [email protected]
    http://www.talsystems.com

    Comment


    • #3
      Thank Michael for your answer.

      Unfortunately the file lvdemo.zip is no longer accessible on the website !
      Jean-Pierre LEROY

      Comment


      • #4
        Wow, I don't have it either.

        Maybe someone downloaded it a long time ago and would be so good as to post it as an attachment to a reply to the original?

        (This was originally posted before attachments were supported).
        Michael Mattias
        Tal Systems (retired)
        Port Washington WI USA
        [email protected]
        http://www.talsystems.com

        Comment


        • #5
          Maybe this will help:
          Code:
          Sub ShowHeaderIcon(ColNo As Long, ImageNo As Long)
            Local hHeader As Dword
            Local lvHndl As Dword
            Local HDI As HD_ITEM
            Local s As Asciiz * 32
            Local fmt As Integer
          
            lvHndl = GetDlgItem(hdlg, %IDC_LV_TASKS)
            hHeader = SendMessage(lvHndl, %LVM_GetHeader, 0, ByVal 0)
          
            ' Get current header information
            HDI.mask = %HDI_FORMAT Or %HDI_TEXT Or %HDI_BITMAP
            HDI.pszText = VarPtr(s)
            HDI.cchTextMax = 32
            Header_GetItem(hHeader, colNo, HDI)
          
            ' Get Text Alignement (left or centered)
            If Bit(HDI.fmt, %HDF_CENTER-1) Then
              fmt = %HDF_CENTER
            Else
              fmt = %HDF_LEFT
            End If
          
            ' Add or remove image from header
            Select Case ImageNo
              Case 0:
                HDI.fmt = %HDF_STRING Or fmt
          
              Case 1:
                HDI.fmt = %HDF_STRING Or %HDF_BITMAP Or %HDF_BITMAP_ON_RIGHT Or fmt
                HDI.hbm = hBmpUp
          
              Case 2:
                HDI.fmt = %HDF_STRING Or %HDF_BITMAP Or %HDF_BITMAP_ON_RIGHT Or fmt
                HDI.hbm = hBmpDown
            End Select
          
            Header_SetItem(hHeader, ColNo, HDI)
          End Sub
                           
          
          ...
          
                    Case %LVN_ColumnClick
                      lvHndl = GetDlgItem(hdlg, %IDC_LV_TASKS)
                      pNMLV = CbLParam
                      If @pNMLV.iSubItem <> -1 Then
                        ShowHeaderIcon(Sortinfo.Column, 0)
          
                        If SortInfo.Column = @pNMLV.iSubItem Then
                          SortInfo.Direction = SortInfo.Direction * -1
                        Else
                          SortInfo.Direction = 1
                          SortInfo.Column = @pNMLV.iSubItem
                        End If
          
                        If SortInfo.Direction = -1 Then
                          ShowHeaderIcon(Sortinfo.Column, 1)
                        Else
                          ShowHeaderIcon(Sortinfo.Column, 2)
                        End If
          
                        ListView_SortItemsEx(lvHndl, CodePtr(Sort_ListView), @pNMLV.iSubItem)
          
                        CurrentRow = ListView_GetNextItem(lvHndl, -1, %LVNI_Selected)
                      End If
          Sincerely,

          Steve Rossell
          PowerBASIC Staff

          Comment


          • #6
            I probably have the lvdemo.zip on one of my archive CDs/DVDs but I can't get at them right now. Looking at some source code I have from working with my brother years ago, it looks like you need to do the following:

            In the WM_INITDIALOG of the callback procedure with the listview do the following:
            - Create an ImageList with an icon for ascending and descending sorts (usually just a triangle pointing either up or down. You can use the ImageList_Create macro for this.
            - Use the TabCtrl_SetImageList macro to attach the ImageList you created to the tab control.

            When your callback procedure receives a WM_NOTIFTY message from the ListView control with a code of LVN_COLUMNCLICK do the following:
            - Use the ListView_GetHeader macro to get the handle of the header control associated with the ListView.
            - You will need a variable defined of type HD_ITEM that you can set the mask to HDI_FORMAT OR HDI_IMAGE.
            - Then use the Header_GetItem macro to get the current values for fmt and iImage. (Keep in mind that headers are one based while listview columns are zero based.)
            - Set the HD_ITEM.fmt to HD_ITEM.fmt OR HDF_STRING OR HDF_IMAGE OR HDF_BITMAP_ON_RIGHT.
            - Set the HD_ITEM.iImage to the proper icon for the way you are sorting. (In my case I had 0 for the icon for ascending sort and 1 for the icon for descending sort.)
            - Use the Header_SetItem macro to apply the changes.

            I've started writing a sample program to demonstrate this but I see Steve has already posted some. Perhaps I'll finish off my demo and post it here when I'm done.
            Jeff Blakeney

            Comment


            • #7
              Steve and Jeff thank you for the snippet and the explanation; It works !

              Ps: in the meantime, Ian posted the missing file lvdemo.zip in the source code forum.
              Jean-Pierre LEROY

              Comment


              • #8
                Steve and Jeff,

                I spent some times on MSDN and found than now starting with Windows XP with Comctl32.dll version 6 there is even a simpler method to draw up-arrow or down-arrow.

                Here is a link to the MSDN website http://msdn.microsoft.com/en-us/libr...47(VS.85).aspx

                So I propose below a new version of the sub ShowHeaderIcon() :

                Code:
                Sub ListView_DrawHeaderArrow(hWndControl As Dword, ByVal pColumn As Long, ByVal pSortOrder As Long)
                
                    Local hHeader As Dword
                    Local HDI As HD_ITEM
                    
                    hHeader = SendMessage(hWndControl, %LVM_GetHeader, 0, ByVal 0)    
                    HDI.mask = %HDI_FORMAT
                    Header_GetItem(hHeader, pColumn, HDI)
                    
                    ' depending on the sort order (%SO_NONE, %SO_ASCENDING, %SO_DESCENDING) 
                    Select Case pSortOrder
                    
                        Case %SO_NONE:
                            ' remove down-arrow or up-arrow
                            HDI.fmt = HDI.fmt And Not (%HDF_SORTDOWN Or %HDF_SORTUP)       
                        
                        Case %SO_ASCENDING:
                            ' Draws an up-arrow on this item
                            HDI.fmt = HDI.fmt And Not %HDF_SORTDOWN
                            HDI.fmt = HDI.fmt Or      %HDF_SORTUP                       
                                     
                        Case %SO_DESCENDING
                            'Draws a down-arrow On this item 
                            HDI.fmt = HDI.fmt And Not %HDF_SORTUP
                            HDI.fmt = HDI.fmt Or      %HDF_SORTDOWN                             
                    
                    End Select
                    
                    Header_SetItem(hHeader, pColumn, HDI)
                    
                End Sub
                I hope it could be useful to other PowerBASIC users.
                Last edited by Jean-Pierre LEROY; 27 Jun 2009, 10:09 AM. Reason: Change the name of the SUB
                Jean-Pierre LEROY

                Comment


                • #9
                  Originally posted by Jean-Pierre LEROY View Post
                  Steve and Jeff,

                  I spent some times on MSDN and found than now starting with Windows XP with Comctl32.dll version 6 there is even a simpler method to draw up-arrow or down-arrow.
                  If you don't want to support earlier operating systems, your routine may be a little simpler since you don't need to create an image list and attach it to the header control.

                  However, there could be a problem with your routine. If the sort icon is on column zero and the user clicks on column one to sort by that column instead, your routine won't erase the current icon on column zero but will add one to column one. The MSDN page didn't seem to say whether only one sort icon was allowed or not. You could call your routine twice to clear the icon on the old column then put the icon on the new column.

                  I suppose having the option to have sort icons on multiple columns would be kind of nice if you were going to sort on multiple columns but I usually don't do that. I tend to only sort on a single column.

                  The code I had originally written was SDK so when I started working on a stand alone demo the other day, I decided to try it with all DDT. However, there are no Header DDT commands so I had to do all the Header code using SDK. This made it kind of weird to pick which icon to use as the DDT commands added the ascending icon at index 1 and descending icon at index 2 but the image number had to be set to 0 or 1 and for some reason 1 was ascending and 0 was descending.

                  Here is the code I came up with. It currently doesn't preserve the other flags in the fmt member, it just overwrites it. I also combined the column number and sort order into a single variable. I keep the column number one based and if the column number is positive it gets sorted in ascending order but if it is negative, it gets sorted in descending order.

                  Code:
                  #COMPILE EXE
                  #DIM ALL
                  
                  #INCLUDE "COMMCTRL.INC"
                  
                  %TestLV = 1000
                  
                  SUB SetHeaderIcons(hDlg AS DWORD, lCtrlID AS DWORD, lSortCol AS LONG)
                  
                      LOCAL hCtrl     AS DWORD
                      LOCAL lIndex    AS LONG
                      LOCAL tHDItem   AS HD_ITEM
                  
                      ' get handle of list view so we can then get handle of header
                      CONTROL HANDLE hDlg, lCtrlID TO hCtrl
                      hCtrl = ListView_GetHeader(hCtrl)
                  
                      ' set the format and image for each header
                      FOR lIndex = 0 TO Header_GetItemCount(hCtrl) - 1
                          tHDItem.mask = %HDI_FORMAT OR %HDI_IMAGE
                          IF lIndex = ABS(lSortCol) - 1 THEN
                              ' this is the column being sorted on so set it to use an image
                              tHDItem.fmt = %HDF_STRING OR %HDF_IMAGE OR %HDF_BITMAP_ON_RIGHT
                          ELSE
                              ' this isn't the column being sorted on so set it to text only
                              tHDItem.fmt = %HDF_STRING
                          END IF
                          ' set the image index from the imagelist attached to the header
                          tHDItem.iImage = IIF&(lSortCol < 0, 1, 0)
                          ' apply changes
                          Header_SetItem hCtrl, lIndex, tHDItem
                      NEXT lIndex
                  
                  END SUB
                  
                  CALLBACK FUNCTION DialogProc()
                  
                      STATIC lSortCol AS LONG
                  
                      LOCAL hCtrl     AS DWORD
                      LOCAL hList     AS DWORD
                      LOCAL lIndex    AS LONG
                      LOCAL lNumCols  AS LONG
                      LOCAL lRow      AS LONG
                      LOCAL pNMLV     AS NM_LISTVIEW POINTER
                      LOCAL sTemp     AS STRING
                      LOCAL tLVC      AS LV_ITEM
                  
                      SELECT CASE CB.MSG
                          CASE %WM_INITDIALOG
                              ' add columns to the listview
                              lNumCols = VAL(READ$(1))
                              FOR lIndex = 1 TO lNumCols
                                  LISTVIEW INSERT COLUMN CB.HNDL, %TestLV, lIndex, _
                                           READ$(lIndex + 1), 400 / lNumCols, 0
                              NEXT lIndex
                              ' add data to the columns
                              lRow = 1
                              WHILE READ$(lRow * 3 + 2) <> ""
                                  LISTVIEW INSERT ITEM CB.HNDL, %TestLV, lRow, 0, _
                                           READ$(lRow * 3 + 2)
                                  IF lNumCols > 1 THEN
                                      FOR lIndex = 2 TO lNumCols
                                          LISTVIEW SET TEXT CB.HNDL, %TestLV, lRow, lIndex, _
                                                   READ$(lRow * 3 + lIndex + 1)
                                      NEXT lIndex
                                  END IF
                                  INCR lRow
                              WEND
                              ' get the list view's header handle
                              CONTROL HANDLE CB.HNDL, %TestLV TO hCtrl
                              hCtrl = ListView_GetHeader(hCtrl)
                              ' create the image list
                              IMAGELIST NEW ICON 16, 16, 32, 2 TO hList
                              IMAGELIST ADD ICON hList, "SortAscending.ico" TO lIndex
                              IMAGELIST ADD ICON hList, "SortDescending.ico" TO lIndex
                  '            ' attach the image list to the header
                              Header_SetImageList hCtrl, hList
                              ' set the intial column number to sort and the way to sort it
                              ' (the absolute value of this number is the column to sort on,
                              ' if the number is postive then sort in ascending order,
                              ' if the number is negative then sort in descending order)
                              lSortCol = 1
                              ' set the sort order icon in the header
                              SetHeaderIcons CB.HNDL, %TestLV, lSortCol
                              ' data for populating the list view - first line is number of
                              ' columns followed by multiple rows of that many columns
                              DATA 3
                              DATA "First name", "Last name",  "E-mail address"
                              DATA "John",       "Smith",      "[email protected]"
                              DATA "Sam",        "Peters",     "[email protected]"
                              DATA "Fred",       "Flintstone", "[email protected]"
                  
                          CASE %WM_NOTIFY
                              IF CB.NMID = %TestLV AND CB.NMCODE = %LVN_COLUMNCLICK THEN
                                  ' set busy pointer
                                  MOUSEPTR 11
                                  ' get the extra NMHDR fields for list views
                                  pNMLV = CB.NMHDR
                                  ' set the sort column based on where the user clicked
                                  IF @pNMLV.iSubItem + 1 = ABS(lSortCol) THEN
                                      ' the user clicked the column that is currently being
                                      ' sorted by so just changed the sort direction
                                      lSortCol = lSortCol * -1
                                  ELSE
                                      ' the user clicked a column that isn't being sorted so set
                                      ' it to sort ascending on that column
                                      lSortCol = @pNMLV.iSubItem + 1
                                  END IF
                                  ' sort the data
                                  IF lSortCol > 0 THEN
                                      ' ascending sort
                                      LISTVIEW SORT CB.HNDL, %TestLV, ABS(lSortCol), ASCEND
                                  ELSE
                                      ' descending sort
                                      LISTVIEW SORT CB.HNDL, %TestLV, ABS(lSortCol), DESCEND
                                  END IF
                                  ' set the sort order icon in the header
                                  SetHeaderIcons CB.HNDL, %TestLV, lSortCol
                                  ' set the normal pointer
                                  MOUSEPTR 1
                              END IF
                  
                      END SELECT
                  
                  END FUNCTION
                  
                  FUNCTION PBMAIN () AS LONG
                  
                      LOCAL hDlg  AS DWORD
                  
                      DIALOG NEW %HWND_DESKTOP, "Listview icon test", , , 400, 300, %DS_3DLOOK _
                          OR %DS_MODALFRAME OR %DS_NOFAILCREATE OR %DS_SETFONT OR %WS_BORDER OR _
                          %WS_CAPTION OR %WS_CLIPSIBLINGS OR %WS_DLGFRAME OR %WS_POPUP OR _
                          %WS_SYSMENU, , TO hDlg
                      ' add a listview in report mode
                      CONTROL ADD LISTVIEW, hDlg, %TestLV, "", 0, 0, 400, 300, %LVS_REPORT
                      DIALOG SHOW MODAL hDlg, CALL DialogProc
                  
                  END FUNCTION
                  I've attached the icons I used as well.

                  SortIcons.zip
                  Jeff Blakeney

                  Comment


                  • #10
                    Right justified does not work with headericons

                    In the code below I've remarked out the code associated with setting the header icons to prove that the right justified last column works.

                    Now remark out the END SUB that comes just after the SUB and uncomment the rest of the routine and re-run. You will see that the right most column is no longer right justified. Anyone have any ideas.

                    As Jeff said, he did not preserve the fmt justification value and I'm at a loss as to how to preserve it.

                    Thanks,

                    Bob Mechler

                    Code:
                    #COMPILE EXE
                    #DIM ALL
                    
                    #INCLUDE "COMMCTRL.INC"
                    
                    %TestLV = 1000
                    
                    SUB SetHeaderIcons(hDlg AS DWORD, lCtrlID AS DWORD, lSortCol AS LONG)
                    END SUB
                    '    LOCAL hCtrl     AS DWORD
                    '    LOCAL lIndex    AS LONG
                    '    LOCAL tHDItem   AS HD_ITEM
                    '
                    '    ' get handle of list view so we can then get handle of header
                    '    CONTROL HANDLE hDlg, lCtrlID TO hCtrl
                    '    hCtrl = ListView_GetHeader(hCtrl)
                    '
                    '    ' set the format and image for each header
                    '    FOR lIndex = 0 TO Header_GetItemCount(hCtrl) - 1
                    '        tHDItem.mask = %HDI_FORMAT OR %HDI_IMAGE
                    '        IF lIndex = ABS(lSortCol) - 1 THEN
                    '            ' this is the column being sorted on so set it to use an image
                    '            tHDItem.fmt = %HDF_STRING OR %HDF_IMAGE OR %HDF_BITMAP_ON_RIGHT
                    '        ELSE
                    '            ' this isn't the column being sorted on so set it to text only
                    '            tHDItem.fmt = %HDF_STRING
                    '        END IF
                    '        ' set the image index from the imagelist attached to the header
                    '        tHDItem.iImage = IIF&(lSortCol < 0, 1, 0)
                    '        ' apply changes
                    '        Header_SetItem hCtrl, lIndex, tHDItem
                    '    NEXT lIndex
                    '
                    'END SUB
                    
                    CALLBACK FUNCTION DialogProc()
                    
                        STATIC lSortCol AS LONG
                    
                        LOCAL hCtrl     AS DWORD
                        LOCAL hList     AS DWORD
                        LOCAL lIndex    AS LONG
                        LOCAL lNumCols  AS LONG
                        LOCAL lRow      AS LONG
                        LOCAL pNMLV     AS NM_LISTVIEW POINTER
                        LOCAL sTemp     AS STRING
                        LOCAL tLVC      AS LV_ITEM
                    
                        SELECT CASE CB.MSG
                            CASE %WM_INITDIALOG
                                ' add columns to the listview
                                lNumCols = VAL(READ$(1))
                                FOR lIndex = 1 TO lNumCols - 1
                                    LISTVIEW INSERT COLUMN CB.HNDL, %TestLV, lIndex, _
                                             READ$(lIndex + 1), 400 / lNumCols, 0
                                NEXT lIndex
                                LISTVIEW INSERT COLUMN CB.HNDL, %TestLV, lNumCols, _
                                             READ$(lIndex + 1), 400 / lNumCols, 1
                    '            ' add data to the columns
                                lRow = 1
                                WHILE READ$(lRow * 4 + 3) <> ""
                                    LISTVIEW INSERT ITEM CB.HNDL, %TestLV, lRow, 0, _
                                             READ$(lRow * 4 + 3)
                                    IF lNumCols > 1 THEN
                                        FOR lIndex = 2 TO lNumCols
                                            LISTVIEW SET TEXT CB.HNDL, %TestLV, lRow, lIndex, _
                                                     READ$(lRow * 4 + lIndex + 1)
                                        NEXT lIndex
                                    END IF
                                    INCR lRow
                                WEND
                                ' get the list view's header handle
                                CONTROL HANDLE CB.HNDL, %TestLV TO hCtrl
                                hCtrl = ListView_GetHeader(hCtrl)
                                ' create the image list
                                IMAGELIST NEW ICON 16, 16, 32, 2 TO hList
                                IMAGELIST ADD ICON hList, "SortAscending.ico" TO lIndex
                                IMAGELIST ADD ICON hList, "SortDescending.ico" TO lIndex
                    '            ' attach the image list to the header
                                Header_SetImageList hCtrl, hList
                                ' set the intial column number to sort and the way to sort it
                                ' (the absolute value of this number is the column to sort on,
                                ' if the number is postive then sort in ascending order,
                                ' if the number is negative then sort in descending order)
                                lSortCol = 1
                                ' set the sort order icon in the header
                                SetHeaderIcons CB.HNDL, %TestLV, lSortCol
                                ' data for populating the list view - first line is number of
                                ' columns followed by multiple rows of that many columns
                                DATA 4
                                DATA "First name", "Last name",  "E-mail address", "Owing"
                                DATA "John",       "Smith",      "[email protected]","12930.02"
                                DATA "Sam",        "Peters",     "[email protected]","930.02"
                                DATA "Fred",       "Flintstone", "[email protected]","30.02"
                    
                            CASE %WM_NOTIFY
                                IF CB.NMID = %TestLV AND CB.NMCODE = %LVN_COLUMNCLICK THEN
                                    ' set busy pointer
                                    MOUSEPTR 11
                                    ' get the extra NMHDR fields for list views
                                    pNMLV = CB.NMHDR
                                    ' set the sort column based on where the user clicked
                                    IF @pNMLV.iSubItem + 1 = ABS(lSortCol) THEN
                                        ' the user clicked the column that is currently being
                                        ' sorted by so just changed the sort direction
                                        lSortCol = lSortCol * -1
                                    ELSE
                                        ' the user clicked a column that isn't being sorted so set
                                        ' it to sort ascending on that column
                                        lSortCol = @pNMLV.iSubItem + 1
                                    END IF
                                    ' sort the data
                                    IF lSortCol > 0 THEN
                                        ' ascending sort
                                        LISTVIEW SORT CB.HNDL, %TestLV, ABS(lSortCol), ASCEND
                                    ELSE
                                        ' descending sort
                                        LISTVIEW SORT CB.HNDL, %TestLV, ABS(lSortCol), DESCEND
                                    END IF
                                    ' set the sort order icon in the header
                                    SetHeaderIcons CB.HNDL, %TestLV, lSortCol
                                    ' set the normal pointer
                                    MOUSEPTR 1
                                END IF
                    
                        END SELECT
                    
                    END FUNCTION
                    
                    FUNCTION PBMAIN () AS LONG
                    
                        LOCAL hDlg  AS DWORD
                    
                        DIALOG NEW %HWND_DESKTOP, "Listview icon test", , , 400, 300, %DS_3DLOOK _
                            OR %DS_MODALFRAME OR %DS_NOFAILCREATE OR %DS_SETFONT OR %WS_BORDER OR _
                            %WS_CAPTION OR %WS_CLIPSIBLINGS OR %WS_DLGFRAME OR %WS_POPUP OR _
                            %WS_SYSMENU, , TO hDlg
                        ' add a listview in report mode
                        CONTROL ADD LISTVIEW, hDlg, %TestLV, "", 0, 0, 400, 300, %LVS_REPORT
                        DIALOG SHOW MODAL hDlg, CALL DialogProc
                    
                    END FUNCTION
                    Bob Mechler

                    Comment


                    • #11
                      OR 'ing in the %LVCFMT_RIGHT fixes the issue for those columns that must be right justified.

                      BOB MECHLER

                      Code:
                      SUB SetHeaderIcons(hDlg AS DWORD, lCtrlID AS DWORD, lSortCol AS LONG)
                      
                          LOCAL hCtrl     AS DWORD
                          LOCAL lIndex    AS LONG
                          LOCAL tHDItem   AS HD_ITEM
                      
                          ' get handle of list view so we can then get handle of header
                          CONTROL HANDLE hDlg, lCtrlID TO hCtrl
                          hCtrl = ListView_GetHeader(hCtrl)
                      
                          ' set the format and image for each header
                          FOR lIndex = 0 TO Header_GetItemCount(hCtrl) - 1
                              tHDItem.mask = %HDI_FORMAT OR %HDI_IMAGE
                              IF lIndex = ABS(lSortCol) - 1 THEN
                                  ' this is the column being sorted on so set it to use an image
                                  IF lIndex = 3 THEN
                                    tHDItem.fmt = %HDF_STRING OR %HDF_IMAGE OR %HDF_BITMAP_ON_RIGHT OR %LVCFMT_RIGHT
                                  ELSE
                                    tHDItem.fmt = %HDF_STRING OR %HDF_IMAGE OR %HDF_BITMAP_ON_RIGHT
                                  END IF
                                  
                              ELSE
                                  ' this isn't the column being sorted on so set it to text only
                                  IF lIndex = 3 THEN 'this column needs right-justification
                                    tHDItem.fmt = %HDF_STRING OR %LVCFMT_RIGHT
                                  ELSE
                                    tHDItem.fmt = %HDF_STRING
                                  END IF  
                              END IF
                              ' set the image index from the imagelist attached to the header
                              tHDItem.iImage = IIF&(lSortCol < 0, 1, 0)
                              ' apply changes
                              Header_SetItem hCtrl, lIndex, tHDItem
                          NEXT lIndex
                      
                      END SUB

                      Comment


                      • #12
                        Originally posted by Steve Rossell View Post
                        Maybe this will help:
                        Code:
                        Sub ShowHeaderIcon(ColNo As Long, ImageNo As Long)
                          Local hHeader As Dword
                          Local lvHndl As Dword
                          Local HDI As HD_ITEM
                          Local s As Asciiz * 32
                          Local fmt As Integer
                        
                          lvHndl = GetDlgItem(hdlg, %IDC_LV_TASKS)
                          hHeader = SendMessage(lvHndl, %LVM_GetHeader, 0, ByVal 0)
                        
                          ' Get current header information
                          HDI.mask = %HDI_FORMAT Or %HDI_TEXT Or %HDI_BITMAP
                          HDI.pszText = VarPtr(s)
                          HDI.cchTextMax = 32
                          Header_GetItem(hHeader, colNo, HDI)
                        
                          ' Get Text Alignement (left or centered)
                          If Bit(HDI.fmt, %HDF_CENTER-1) Then
                            fmt = %HDF_CENTER
                          Else
                            fmt = %HDF_LEFT
                          End If
                        
                          ' Add or remove image from header
                          Select Case ImageNo
                            Case 0:
                              HDI.fmt = %HDF_STRING Or fmt
                        
                            Case 1:
                              HDI.fmt = %HDF_STRING Or %HDF_BITMAP Or %HDF_BITMAP_ON_RIGHT Or fmt
                              HDI.hbm = hBmpUp
                        
                            Case 2:
                              HDI.fmt = %HDF_STRING Or %HDF_BITMAP Or %HDF_BITMAP_ON_RIGHT Or fmt
                              HDI.hbm = hBmpDown
                          End Select
                        
                          Header_SetItem(hHeader, ColNo, HDI)
                        End Sub
                                         
                        
                        ...
                        
                                  Case %LVN_ColumnClick
                                    lvHndl = GetDlgItem(hdlg, %IDC_LV_TASKS)
                                    pNMLV = CbLParam
                                    If @pNMLV.iSubItem <> -1 Then
                                      ShowHeaderIcon(Sortinfo.Column, 0)
                        
                                      If SortInfo.Column = @pNMLV.iSubItem Then
                                        SortInfo.Direction = SortInfo.Direction * -1
                                      Else
                                        SortInfo.Direction = 1
                                        SortInfo.Column = @pNMLV.iSubItem
                                      End If
                        
                                      If SortInfo.Direction = -1 Then
                                        ShowHeaderIcon(Sortinfo.Column, 1)
                                      Else
                                        ShowHeaderIcon(Sortinfo.Column, 2)
                                      End If
                        
                                      ListView_SortItemsEx(lvHndl, CodePtr(Sort_ListView), @pNMLV.iSubItem)
                        
                                      CurrentRow = ListView_GetNextItem(lvHndl, -1, %LVNI_Selected)
                                    End If
                        Can't get the icon to show using this. I'm working with the DDT Listview in the samples directory of PBWin 10.02. These are the changed areas:


                        Code:
                        ' Add the XP Manifest resrouce file
                        #RESOURCE MANIFEST, 1, "XPTheme.xml"
                        #RESOURCE ICON ,101,"sortAscending.ICO"
                        #RESOURCE ICON ,102,"sortDescending.ico"
                        Code:
                        %ID_Button = 1002 'bae
                        Code:
                          CONTROL ADD BUTTON, hdlg, %ID_Button,"Sort",1,1,18,13
                          CONTROL ADD LABEL, hDlg, %ID_LABEL, _
                            "Use the Mouse, Arrow keys, PgUp, PgDn, Home, and End keys to navigate the ListView.", _
                            19, 1, 300, 8, %SS_CENTER
                        Code:
                        ' Dialog box callback procedure
                        CALLBACK FUNCTION DlgProc
                          STATIC dir AS LONG 'bae
                          STATIC dbhlist AS LONG
                          STATIC hInst AS LONG
                          LOCAL d AS ASCIIZ*255
                          STATIC hiconup,hicondn AS LONG
                          SELECT CASE AS LONG CB.MSG
                            CASE %WM_INITDIALOG
                              ' Subclass the listview control so we can receive %WM_LButtonDown and %WM_KeyDown messages
                                  OldLVProc = SetWindowLongW(GetDlgItem(CB.HNDL, %ID_LISTVIEW), %GWL_WNDPROC, BYVAL CODEPTR(LVProc))
                            CASE %WM_DESTROY
                              ' Restore the listview controls original callback procedure
                              SetWindowLongW(GetDlgItem(CB.HNDL, %ID_LISTVIEW), %GWL_WNDPROC, OldLVProc)
                            CASE %WM_COMMAND      'bae
                                SELECT CASE AS LONG CB.WPARAM
                                    CASE %ID_BUtton
                                        hInst = GetModuleHandle(BYVAL 0)
                                        hiconUp = LoadIcon(hInst,"#101")
                                        hIconDn = LoadIcon(hInst,"#102")
                        
                                        IF dir = 0 THEN
                                            ShowHeaderIcon CB.HNDL,1,2,hIconUp, hIconDn
                                            LISTVIEW SORT CB.HNDL, %ID_LISTVIEW,1,ASCEND,UCASE
                                        ELSE
                                            LISTVIEW SORT CB.HNDL, %ID_LISTVIEW,1,DESCEND,UCASE
                                            ShowHeaderIcon CB.HNDL,1,1,hIconUp, hIconDn
                        
                                        END IF
                                        dir = NOT dir
                                END SELECT
                          END SELECT
                        END FUNCTION
                        And in the sub showHeaderIcons, I changed the mask (and did try it as is) to:
                        Code:
                            'add or remove image from header
                            SELECT CASE ImageNo
                                CASE 0
                                    HDI.fmt = %HDF_String OR fmt
                                CASE 1
                                    HDI.fmt = %HDF_STRING OR %HDF_image OR %HDF_BITMAP_ON_RIGHT OR fmt
                                    HDI.hbm= hBMPUp
                                CASE 2
                                    HDI.fmt = %HDF_STRING OR %HDF_image OR %HDF_BITMAP_ON_RIGHT OR fmt
                                    HDI.hbm= hBMPDown
                            END SELECT
                        
                            Header_SetItem(hHeader, ColNum,HDI)
                        END SUB
                        (%HDF_BITMAP changed to %HDF_BITMAP)
                        I do not get any errors from loading the icon, but I have to be missing something.
                        Barry

                        Comment


                        • #13
                          can't speak to specific problem but....
                          Code:
                          CASE %ID_BUtton
                                          hInst = GetModuleHandle(BYVAL 0)
                                          hiconUp = LoadIcon(hInst,"#101")
                                          hIconDn = LoadIcon(hInst,"#102")
                          You need to delete those icons when you are done with them (after the 'set header" call) **OR** make sure you only "LoadIcon()" once (eg on WM_INITDIALOG. Since the vars are STATIC that would make sense). Each LoadICon() call uses GDI resources, they are finite and you can run out.
                          Michael Mattias
                          Tal Systems (retired)
                          Port Washington WI USA
                          [email protected]
                          http://www.talsystems.com

                          Comment


                          • #14
                            I do have them in InitDialog, but moved them here to put all the code in one spot for posting. I always do that for anything that is a repeat item.
                            Barry

                            Comment


                            • #15
                              Originally posted by Jeff Blakeney View Post

                              Here is the code I came up with. It currently doesn't preserve the other flags in the fmt member, it just overwrites it. I also combined the column number and sort order into a single variable. I keep the column number one based and if the column number is positive it gets sorted in ascending order but if it is negative, it gets sorted in descending order.
                              A.S. I have Windows XP and PBWIN9

                              I tried this example, and, as a standalone Demo it works. Perfect.

                              I Cut & pasted this code on my program and I get the following errors:
                              Error 605 in C:\POWERB~1\SOURCE~1\SETFIL~2\SetFile Database (1280:013): Macro parameter mismatch
                              Line 1280: Header_SetImageList hCtrl, hList


                              Error 605 in C:\POWERB~1\SOURCE~1\SETFIL~2\SetFile Database (1455:009): Macro parameter mismatch
                              Line 14550: Header_SetItem hCtrl, lIndex, tHDItem


                              If I comment these two lines, the Sort works, but not the Image Icon (naturaly, I commented them out!)

                              What I don't understand is the Macro parameter mismatch: The parameter declarations are the same between my program and the demo!
                              Andrea Mariani
                              AS/400 expert
                              Basic programmer @ Home

                              Comment


                              • #16
                                I'm leaving my message as an example: After bashing my head for the whole moring, I posted this HELP message.

                                Then I look at the top of my program and I see a %USEMACROS = 1

                                Took that off, now it works.

                                2 minutes after I posted!
                                Andrea Mariani
                                AS/400 expert
                                Basic programmer @ Home

                                Comment

                                Working...
                                X