Announcement

Collapse
No announcement yet.

ListView - Fixed column

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

  • ListView - Fixed column

    I need an invisible subscript column in a listview control.

    If the column width is set on zero (ListView_SetColumnWidth (hCtl, col, 0), the column can nevertheless be maximized to the runtime.

    What can I do?

  • #2
    You can intercept HDN_BEGINTRACK notification to header control of the listview and return true, or maybe return false. I know one of those returns prevents further sizing of columns.

    Or, reconsider your 'need' for an invisible subscript column. If that's just a "row specific" value you can store it to and retrieve from LV_ITEM.lparam.

    Here's some free code to help you with that:
    Code:
    FUNCTION Listview_GetRowLparam (BYVAL hwnd AS LONG, BYVAL Rowno AS LONG) AS LONG
        LOCAL lvi AS LVITEM, I AS LONG
    
        lvi.iitem         = RowNo
        lvi.iSubItem      = 0
        lvi.mask          = %LVIF_PARAM
        I                 = SendMessage (hWnd, %LVM_GETITEM, 0, BYVAL VARPTR(Lvi))
        FUNCTION          = lvi.lparam
    END FUNCTION
    I have a "SET" around here somewhere but I can't find it right now. But it looks pretty much like the GET except you use LVM_SETITEM message and you have to pass "new value" as a parameter.

    MCM
    Michael Mattias
    Tal Systems Inc. (retired)
    Racine WI USA
    [email protected]
    http://www.talsystems.com

    Comment


    • #3
      The examples with "BEGINTRACK" are complex for me.

      Is there a small example?

      Comment


      • #4
        Bernhard, maybe you can explain a little more what you are trying to accomplish. Maybe the lParam value can be used to track your subscript in which case you would not need to hide the column?

        Comment


        • #5
          I want to assign only a column a firm width. I would not like the user to be able to change the width.

          Comment


          • #6
            Whoa......

            Do you (believe you) need one (1) "invisible" column used to maintain a value which can't be resized? Or do you want NO columns of the listview to be resizeable?

            Two different things!
            Michael Mattias
            Tal Systems Inc. (retired)
            Racine WI USA
            [email protected]
            http://www.talsystems.com

            Comment


            • #7
              Originally posted by Bernhard Fomm View Post
              I want to assign only a column a firm width. I would not like the user to be able to change the width.
              Bernhard,

              I do this quite often. First create a column (or multiple columns) with a zero length width, then call this function:
              Code:
              FUNCTION LV_NoResizeColumns(BYVAL wParam&, BYVAL lParam&) AS LONG
              '==========================================================
              'Turn-off ListView Column Sizing (to hide columns)
              '----------------------------------------------------------
                  LOCAL H AS EZ_NMHDR PTR, RV&
                  H=lParam&
                  RV&=0
                  SELECT CASE @H.code
                      CASE -306, -326   ' HDN_BEGINTRACK - one for unicode, other for ansi
                          DIM H2 AS HeaderN PTR
                          H2=lParam&
                          SELECT CASE @H2.Index
                              CASE 2  ' column 3 (zero indexed)
                                  RV&=1  ' don't allow tracking
                              CASE ELSE
                                  RV&=0   ' allow tracking
                          END SELECT
                      CASE ELSE
                  END SELECT
                  FUNCTION=RV&
              END FUNCTION
              Software makes Hardware Happen

              Comment


              • #8
                I am confused now too cause if you do not allow resize, then its up to you to account for every resolution of the monitor vs the size you want you physically show to be seen on all monitors/systems/video cards to show vital data

                the original idea was to hide a column and use its data to do some operation on it.

                Either I mis-read, or you mis-spoke when asking the question?

                (no big, just trying to clear up the concept...so we are all on the same page of thought)
                Engineer's Motto: If it aint broke take it apart and fix it

                "If at 1st you don't succeed... call it version 1.0"

                "Half of Programming is coding"....."The other 90% is DEBUGGING"

                "Document my code????" .... "WHYYY??? do you think they call it CODE? "

                Comment


                • #9
                  am confused now too cause if you do not allow resize, then its up to you to account for every resolution of the monitor
                  ???

                  Resizing the columns of a listview control has nothing to do with the monitor resolution.

                  Sizing the entire control and selecting the font used in that control, however, can be important if you need to support a wide range of monitors.
                  Michael Mattias
                  Tal Systems Inc. (retired)
                  Racine WI USA
                  [email protected]
                  http://www.talsystems.com

                  Comment


                  • #10
                    Originally posted by Joe Byrne View Post
                    Bernhard,

                    I do this quite often. First create a column (or multiple columns) with a zero length width, then call this function:
                    Code:
                    FUNCTION LV_NoResizeColumns(BYVAL wParam&, BYVAL lParam&) AS LONG
                    '==========================================================
                    'Turn-off ListView Column Sizing (to hide columns)
                    '----------------------------------------------------------
                        LOCAL H AS EZ_NMHDR PTR, RV&
                        H=lParam&
                        RV&=0
                        SELECT CASE @H.code
                            CASE -306, -326   ' HDN_BEGINTRACK - one for unicode, other for ansi
                                DIM H2 AS HeaderN PTR
                                H2=lParam&
                                SELECT CASE @H2.Index
                                    CASE 2  ' column 3 (zero indexed)
                                        RV&=1  ' don't allow tracking
                                    CASE ELSE
                                        RV&=0   ' allow tracking
                                END SELECT
                            CASE ELSE
                        END SELECT
                        FUNCTION=RV&
                    END FUNCTION

                    I think this it works. But how do I install the code in a program? What is HeaderN and EZ_NMHDR?

                    Comment


                    • #11
                      think this it works. But how do I install the code in a program? What is HeaderN and EZ_NMHDR
                      Start with your documentation on the HDN_BEGINTRACK notification. That will tell you what you need to know.

                      As an extra little hint, you will also need to review the the documentation for the WM_NOTIFY message to know WHEN to call this function.
                      Michael Mattias
                      Tal Systems Inc. (retired)
                      Racine WI USA
                      [email protected]
                      http://www.talsystems.com

                      Comment


                      • #12
                        Code:
                        ' PB/Win8.x
                        #COMPILE EXE
                        #DIM ALL
                        
                        
                        '------------------------------------------------------------------------------
                        '   ** Includes **
                        '------------------------------------------------------------------------------
                        %USEMACROS = 1
                        #IF NOT %DEF(%WINAPI)
                            #INCLUDE "WIN32API.INC"
                        #ENDIF
                        #IF NOT %DEF(%COMMCTRL_INC)
                            #INCLUDE "COMMCTRL.INC"
                        #ENDIF
                        '------------------------------------------------------------------------------
                        
                        
                        '------------------------------------------------------------------------------
                        '   ** Constants **
                        '------------------------------------------------------------------------------
                        %IDC_SYSLISTVIEW32_1 = 1001
                        '------------------------------------------------------------------------------
                        
                        
                        '------------------------------------------------------------------------------
                        '   ** Declarations **
                        '------------------------------------------------------------------------------
                        GLOBAL hListViewCtl       AS DWORD
                        GLOBAL hWndListViewHeader AS LONG
                        GLOBAL lpOldWndProc_LV    AS LONG
                        GLOBAL lpOldWndProc_LVH   AS LONG
                        '------------------------------------------------------------------------------
                        
                        
                        '------------------------------------------------------------------------------
                        '   ** CallBacks **
                        '------------------------------------------------------------------------------
                        FUNCTION ListViewProc(BYVAL hWnd AS LONG, _
                                              BYVAL wMsg AS LONG, _
                                              BYVAL wParam AS LONG, _
                                              BYVAL lParam AS LONG) AS LONG
                        
                        LOCAL hdnptr      AS HD_NOTIFY PTR
                        LOCAL hdiptr      AS HD_ITEM   PTR
                        LOCAL hditem      AS HD_ITEM
                        
                            SELECT CASE wMsg
                            CASE %WM_NOTIFY
                                hdnptr = lParam
                                hdiptr = @hdnptr.pitem
                                SELECT CASE @hdnptr.hdr.code
                                CASE %HDN_BEGINTRACKW
                                    IF @hdnptr.iItem = 1 THEN       ' Column1
                                        FUNCTION = %TRUE            ' don't allow tracking
                                    ELSE
                                        FUNCTION = %FALSE           ' allow tracking
                                    END IF
                                CASE ELSE
                                    FUNCTION = CallWindowProc( lpOldWndProc_LV, hWnd, wMsg, wParam, lParam)
                                END SELECT
                            CASE ELSE
                                FUNCTION = CallWindowProc( lpOldWndProc_LV, hWnd, wMsg, wParam, lParam)
                            END SELECT
                        
                        END FUNCTION
                        '------------------------------------------------------------------------------
                        
                        '------------------------------------------------------------------------------
                        FUNCTION HeaderProc(BYVAL hWnd AS LONG, _
                                            BYVAL wMsg AS LONG, _
                                            BYVAL wParam AS LONG, _
                                            BYVAL lParam AS LONG) AS LONG
                        
                            SELECT CASE wMsg
                           'NOTE: uncomment this message if you don't care about clicking
                           '      the header buttons, in that case, you don't need to subclass
                           '      the Listview control itself, just the header.
                           '
                           'Defeat this message so that mouse clicks do not activate the control
                           'CASE %WM_MOUSEACTIVATE
                           '    Function = %MA_ACTIVATEANDEAT
                        
                           'feature that headers have of resizing a column when a
                           'double click is done on the column separator line.
                            CASE %WM_LBUTTONDBLCLK
                                FUNCTION = %TRUE
                        
                           'Defeat the system changing cursors on us. We do it based on our own hit testing
                            CASE %WM_SETCURSOR
                                FUNCTION = %TRUE
                        
                            CASE ELSE
                                FUNCTION = CallWindowProc( lpOldWndProc_LVH, hWnd, wMsg, wParam, lParam)
                        
                            END SELECT
                        
                        END FUNCTION
                        '------------------------------------------------------------------------------
                        
                        '------------------------------------------------------------------------------
                        CALLBACK FUNCTION ShowDIALOG1Proc()
                        
                            SELECT CASE AS LONG CBMSG
                            CASE %WM_INITDIALOG
                                CONTROL HANDLE CBHNDL, %IDC_SYSLISTVIEW32_1 TO hListViewCtl
                                hWndListViewHeader = GetWindow ( hListViewCtl, %GW_CHILD )
                                lpOldWndProc_LV    = SetWindowLong ( hListViewCtl, %GWL_WNDPROC,BYVAL CODEPTR(ListViewProc) )
                                lpOldWndProc_LVH   = SetWindowLong ( hWndListViewHeader, %GWL_WNDPROC,BYVAL CODEPTR(HeaderProc) )
                        
                            CASE %WM_NCACTIVATE
                                STATIC hWndSaveFocus AS DWORD
                                IF ISFALSE CBWPARAM THEN
                                    hWndSaveFocus = GetFocus()
                                ELSEIF hWndSaveFocus THEN
                                    SetFocus(hWndSaveFocus)
                                    hWndSaveFocus = 0
                                END IF
                        
                            CASE %WM_DESTROY
                                CALL SetWindowLong( hWndListViewHeader, %GWL_WNDPROC, lpOldWndProc_LVH )
                                CALL SetWindowLong( hListViewCtl, %GWL_WNDPROC, lpOldWndProc_LV )
                        
                            CASE %WM_COMMAND
                                SELECT CASE AS LONG CBCTL
                                CASE %IDC_SYSLISTVIEW32_1
                                END SELECT
                            END SELECT
                        
                        END FUNCTION
                        '------------------------------------------------------------------------------
                        
                        '------------------------------------------------------------------------------
                        '   ** Sample Code **
                        '------------------------------------------------------------------------------
                        FUNCTION SampleListView(BYVAL hDlg AS DWORD, BYVAL lID AS LONG, BYVAL lColCnt AS LONG, BYVAL lRowCnt AS LONG) AS LONG
                            LOCAL lCol   AS LONG
                            LOCAL lRow   AS LONG
                            LOCAL hCtl   AS DWORD
                            LOCAL tLVC   AS LV_COLUMN
                            LOCAL tLVI   AS LV_ITEM
                            LOCAL szBuf  AS ASCIIZ * 32
                            LOCAL lStyle AS LONG
                        
                            CONTROL HANDLE hDlg, lID TO hCtl
                        
                            lStyle = ListView_GetExtendedListViewStyle(hCtl)
                            ListView_SetExtendedListViewStyle(hCtl, lStyle OR %LVS_EX_FULLROWSELECT _
                                OR %LVS_EX_GRIDLINES)
                        
                            ' Load column headers.
                            tLVC.mask    = %LVCF_FMT OR %LVCF_TEXT OR %LVCF_SUBITEM
                            tLVC.fmt     = %LVCFMT_LEFT
                            tLVC.pszText = VARPTR(szBuf)
                            FOR lCol = 0 TO lColCnt - 1
                                szBuf       = USING$("Column #", lCol)
                                tLVC.iOrder = lCol
                                ListView_InsertColumn(hCtl, lCol, tLVC)
                            NEXT lCol
                        
                            ' Load sample data.
                            FOR lRow = 0 TO lRowCnt - 1
                                tLVI.stateMask = %LVIS_FOCUSED
                                tLVI.pszText   = VARPTR(szBuf)
                                tLVI.iItem     = lRow
                                FOR lCol = 0 TO lColCnt - 1
                                    szBuf         = USING$("Column # Row #", lCol, lRow)
                                    tLVI.iSubItem = lCol
                                    tLVI.lParam   = lRow
                                    IF lCol = 0 THEN
                                        tLVI.mask = %LVIF_TEXT OR %LVIF_PARAM OR %LVIF_STATE
                                        ListView_InsertItem(hCtl, tLVI)
                                    ELSE
                                        tLVI.mask = %LVIF_TEXT
                                        ListView_SetItem(hCtl, tLVI)
                                    END IF
                                NEXT lCol
                            NEXT lRow
                        
                            ' Auto size columns.
                            FOR lCol = 0 TO lColCnt - 2
                                ListView_SetColumnWidth(hCtl, lCol, %LVSCW_AUTOSIZE)
                            NEXT lCol
                            ListView_SetColumnWidth(hCtl, lColCnt - 1, %LVSCW_AUTOSIZE_USEHEADER)
                        END FUNCTION
                        '------------------------------------------------------------------------------
                        
                        '------------------------------------------------------------------------------
                        '   ** Dialogs **
                        '------------------------------------------------------------------------------
                        FUNCTION ShowDIALOG1(BYVAL hParent AS DWORD) AS LONG
                            LOCAL lRslt AS LONG
                            LOCAL hDlg  AS DWORD
                        
                            DIALOG NEW hParent, "Dialog1", 132, 118, 306, 196, %WS_POPUP OR _
                                %WS_BORDER OR %WS_DLGFRAME OR %WS_CAPTION OR %WS_SYSMENU OR _
                                %WS_MINIMIZEBOX OR %WS_CLIPSIBLINGS OR %WS_VISIBLE OR %DS_MODALFRAME _
                                OR %DS_3DLOOK OR %DS_NOFAILCREATE OR %DS_SETFONT, _
                                %WS_EX_CONTROLPARENT OR %WS_EX_LEFT OR %WS_EX_LTRREADING OR _
                                %WS_EX_RIGHTSCROLLBAR, TO hDlg
                            CONTROL ADD "SysListView32", hDlg, %IDC_SYSLISTVIEW32_1, _
                                "SysListView32_1", 5, 30, 295, 160, %WS_CHILD OR %WS_VISIBLE OR _
                                %WS_TABSTOP OR %LVS_REPORT OR %LVS_SHOWSELALWAYS, %WS_EX_LEFT OR _
                                %WS_EX_CLIENTEDGE OR %WS_EX_RIGHTSCROLLBAR
                        
                            SampleListView hDlg, %IDC_SYSLISTVIEW32_1, 3, 30
                        
                            DIALOG SHOW MODAL hDlg, CALL ShowDIALOG1Proc TO lRslt
                        
                            FUNCTION = lRslt
                        END FUNCTION
                        '------------------------------------------------------------------------------
                        
                        '------------------------------------------------------------------------------
                        '   ** Main Application Entry Point **
                        '------------------------------------------------------------------------------
                        FUNCTION PBMAIN()
                            ShowDIALOG1 %HWND_DESKTOP
                        END FUNCTION
                        '------------------------------------------------------------------------------
                        OK. Here is my simple program.

                        Comment


                        • #13
                          How do I make the mouse pointer is "deactivated" for the hidden column?

                          Comment


                          • #14
                            ???

                            If the column is hidden, there will never be a chance for the cursor to show over it.

                            ???
                            Michael Mattias
                            Tal Systems Inc. (retired)
                            Racine WI USA
                            [email protected]
                            http://www.talsystems.com

                            Comment


                            • #15
                              ...when in HeaderProc...

                              Code:
                                  ' CASE %WM_SETCURSOR
                                  '     FUNCTION = %TRUE
                              ...then the mouse pointer is displayed...(to drag over LV header)...

                              How I can for one column the mouse pointer to deactivate?

                              Comment


                              • #16
                                You mean something like you want to show that you may not click on a particular column header to sort, but on other column headers you want the 'regular' cursor to show indicating the 'regular' action (sort) can occur?

                                If that's the case, I think I'd look to see if I get WM_SETCURSOR message when I moved the mouse over the column headers. (Might need to subclass either the listview or the header control?). If you do, then on WM_SETCURSOR you can test the location of the cursor and if it's in the header area for the column(s) of interest you could set the cursor to LoadCursor (BYVAL %NULL, %IDC_NO) to show the slashed circle meaning 'no.'

                                (If no columns may be sorted, use style LVS_NOSORTHEADER)

                                It's a thought, anyway.
                                Michael Mattias
                                Tal Systems Inc. (retired)
                                Racine WI USA
                                [email protected]
                                http://www.talsystems.com

                                Comment

                                Working...
                                X