Announcement

Collapse
No announcement yet.

ListView's header columns with sort arrows ?

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

  • Andrea Mariani
    replied
    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!

    Leave a comment:


  • Andrea Mariani
    replied
    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!

    Leave a comment:


  • Barry Erick
    replied
    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.

    Leave a comment:


  • Michael Mattias
    replied
    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.

    Leave a comment:


  • Barry Erick
    replied
    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.

    Leave a comment:


  • BOB MECHLER
    replied
    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

    Leave a comment:


  • BOB MECHLER
    replied
    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

    Leave a comment:


  • Jeff Blakeney
    replied
    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

    Leave a comment:


  • Jean-Pierre LEROY
    replied
    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, 11:09 AM. Reason: Change the name of the SUB

    Leave a comment:


  • Jean-Pierre LEROY
    replied
    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.

    Leave a comment:


  • Jeff Blakeney
    replied
    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.

    Leave a comment:


  • Steve Rossell
    replied
    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

    Leave a comment:


  • Michael Mattias
    replied
    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).

    Leave a comment:


  • Jean-Pierre LEROY
    replied
    Thank Michael for your answer.

    Unfortunately the file lvdemo.zip is no longer accessible on the website !

    Leave a comment:


  • Michael Mattias
    replied
    Search here:
    Keywords listview sort
    Search Titles only
    Forum Source Code
    All dates

    =>>> http://www.powerbasic.com/support/pb...ad.php?t=23690

    Leave a comment:


  • 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
Working...
X