Announcement

Collapse
No announcement yet.

how to insert a blank row into a Listview speedily

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

  • how to insert a blank row into a Listview speedily

    Hi all,

    I have the below code for a listview which has a large number of rows (10,000) and partially populated by 6,000 rows of data.
    The question is when I did a blank row insertion into this listview, it takes about 5 to 6 secs to complete and this is very slow and users
    will be annoyed.

    Can someone suggest something to speed up the process of a blank row insertion into a huge listview ?

    Code:
    ' LV Insert row.bas
    ' https://forum.powerbasic.com/forum/user-to-user-discussions/programming/754993-listview-full-row-select?p=755071#post755071
            ' thanks to Peter Lameijn and Dave Biggs
    
    
    #COMPILER PBWIN 10
    #COMPILE EXE
    #DIM ALL
    
     GLOBAL OldLVProc, hDlg, hLv AS LONG
     GLOBAL DataLV()  AS STRING
    
     GLOBAL MaxRow , MaxCol  AS LONG
    
    ' current selected row and column
     GLOBAL CurRow, CurCol AS LONG
    
    %USEMACROS = 1
    #INCLUDE ONCE "WIN32API.INC"
    #INCLUDE ONCE "COMMCTRL.INC"
    
    '--------------------------------------------------------------------------------------------------
       %IDC_ListView   = 102
       %IDC_BtnInsRow        = 103
    
    
    
    
    '--------------------------------------------------------------------------------------------------
    FUNCTION PBMAIN()
    
      DIALOG NEW 0,"Listview with colored fields", , ,350, 300, %WS_POPUP OR _
            %WS_BORDER OR %WS_DLGFRAME OR %WS_SYSMENU 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 LISTVIEW, hDlg, %IDC_ListView, "Listview1",_
                         25, 25, 300, 200, %LVS_REPORT OR _
                        %WS_TABSTOP OR %WS_GROUP
    
        CONTROL ADD BUTTON, hDlg, %IDC_BtnInsRow, _
                   "Insert A Blank Row", 105, 270, 90, 15
    
         hLv = GetDlgItem(hDlg, %IDC_ListView)
    
    
       ' Partially populate the list view with data
          MaxRow = 10000
          MaxCol = 6
          PopListView hDlg
    
    
        DIALOG SHOW MODAL hDlg, CALL DialogProc
    END FUNCTION
    
    
    '-----------------------------------------------------------------
    CALLBACK FUNCTION DialogProc()         'Dialog callback
    
      LOCAL  pnmh AS NMHDR PTR
      LOCAL pLVDI AS LV_DispInfo PTR, lplvcd AS NMLVCUSTOMDRAW PTR
    
      LOCAL colj , jrow , wrt,hrt AS LONG
      LOCAL rtr AS Rect
    
    
      SELECT CASE AS LONG CB.MSG
        CASE %WM_INITDIALOG
          OldLVProc = SetWindowLong(GetDlgItem(CB.HNDL, %IDC_ListView), _
                     %GWL_WNDPROC, BYVAL CODEPTR(LVProc))
          CONTROL REDRAW CB.HNDL,%IDC_ListView
    
        CASE %WM_COMMAND
          SELECT CASE AS LONG CB.CTL
    
            CASE %IDC_BtnInsRow
              IF CB.CTLMSG = %BN_CLICKED THEN
                 IF CurRow > 0 AND CurCol > 0 THEN
                  ' Inserting a blank row at Row CurRow and at Column  CurCol
                    FOR colj = 1 TO MaxCol
                       ' blank off the data array at the current row
                        ARRAY INSERT DataLV(colj, CurRow), ""
                    NEXT colj
                  '  CONTROL SEND hDlg, %IDC_ListView ,%WM_SETREDRAW ,%false,0
                   ' Need to preset to MaxRow here to allocate the memory
                  '  CONTROL SEND hDlg, %IDC_ListView ,%LVM_SETITEMCOUNT ,MaxRow,0
                    FOR jrow = 1 TO MaxRow
                        FOR  colj = 1 TO MaxCol
                             LISTVIEW SET TEXT hDlg, %IDC_ListView, jrow  , colj, DataLV(colj,jrow)
                        NEXT colj
                    NEXT jrow
                   ' CONTROL SEND hDlg, %IDC_ListView ,%WM_SETREDRAW ,%true,0
    
                   '  the below code for redrawing the listview makes it even slower!
                     ' Refresh the entire grid view
                      ' CONTROL GET CLIENT hDlg, %IDC_ListView TO wrt,hrt
                     '  rtr.nLeft = 0
                     '  rtr.nTop = 0
                     '  rtr.nRight = wrt
                     '  rtr.nBottom = hrt
                     '  InvalidateRect hLv , rtr, %False
    
                 END IF
              END IF
          END SELECT
    
        CASE %WM_NOTIFY
          SELECT CASE CB.NMID
            CASE %IDC_ListView
              SELECT CASE CB.NMCODE
                CASE %NM_CUSTOMDRAW
                  lplvcd = CB.LPARAM
    
                  SELECT CASE @lplvcd.nmcd.dwDrawStage
                    CASE %CDDS_PREPaint , %CDDS_ITEMPREPAINT
                      FUNCTION = %CDRF_NOTIFYITEMDRAW
                      EXIT FUNCTION
    
                    CASE %CdDS_ItemPrePaint  OR %CDDS_SUBITEM
                      IF (@lplvcd.nmcd.dwitemspec MOD 2) = 0 THEN
                        @lplvcd.clrTextBk =  GetSysColor(%COLOR_INFOBK)
                      ELSE
                        @lplvcd.clrTextBk = GetSysColor(%COLOR_MENU)
                      END IF
    
                      @lplvcd.clrText   = GetSysColor(%COLOR_INFOTEXT)
                      FUNCTION = %CDRF_NewFont
                      EXIT FUNCTION
    
                  END SELECT
              END SELECT
          END SELECT
    
        CASE %WM_DESTROY
          SetWindowLong(GetDlgItem(CB.HNDL, %IDC_ListView), %GWL_WNDPROC, OldLVProc)
      END SELECT
    
    END FUNCTION
    
    
    
    '--------------------------------------------------------------
    ' populate the listview with some data
    FUNCTION PopListView(BYVAL hDlg AS DWORD)AS LONG
    
      LOCAL lCol, lRow, lStyle AS LONG
      LOCAL jr , jc AS LONG
    
      LISTVIEW GET STYLEXX hDlg, %IDC_ListView TO lStyle
      LISTVIEW SET STYLEXX hDlg, %IDC_ListView, lStyle OR %WS_BORDER OR _
          %LVS_REPORT OR %LVS_EX_FULLROWSELECT OR %LVS_EX_GRIDLINES
    
    'display the headers
        LISTVIEW INSERT COLUMN hDlg, %IDC_ListView, 1, "Header 1 ", 50,0
        LISTVIEW INSERT COLUMN hDlg, %IDC_ListView, 2, "Header 2 ", 40,0
        LISTVIEW INSERT COLUMN hDlg, %IDC_ListView, 3, "Header 3 ", 40,0
        LISTVIEW INSERT COLUMN hDlg, %IDC_ListView, 4, "Header 4 ", 40,0
        LISTVIEW INSERT COLUMN hDlg, %IDC_ListView, 5, "Header 5 ", 40,0
        LISTVIEW INSERT COLUMN hDlg, %IDC_ListView, 6, "Header 6 ", 40,0
    
    
      ' prepare the LV data array
        REDIM DataLV( 1 TO MaxCol, 1 TO MaxRow)
    
      ' create 6000 rows of data
      FOR jr = 1 TO 6000
          FOR jc = 1 TO 6
              DataLV( jc, jr) = FORMAT$(jr) & " , " & FORMAT$(jc)
          NEXT jc
      NEXT jr
    
     ' display the data in the listview
       FOR lRow = 1 TO MaxRow
           ' set up each row
          LISTVIEW INSERT ITEM hDlg, %IDC_ListView, lRow, 0, DataLV(1,lRow)
          ' set up the elements for that row lRow
            LISTVIEW SET TEXT hDlg, %IDC_ListView,lRow  , 2  ,DataLV(2,lRow)
            LISTVIEW SET TEXT hDlg, %IDC_ListView,lRow  , 3  ,DataLV(3,lRow)
            LISTVIEW SET TEXT hDlg, %IDC_ListView,lRow  , 4  ,DataLV(4,lRow)
            LISTVIEW SET TEXT hDlg, %IDC_ListView,lRow  , 5  ,DataLV(5,lRow)
            LISTVIEW SET TEXT hDlg, %IDC_ListView,lRow  , 6  ,DataLV(6,lRow)
       NEXT lRow
    
    
    END FUNCTION
    
    
    '-------------------------------------------------------------
    FUNCTION LVProc(BYVAL hWnd AS LONG,BYVAL wMsg AS LONG,_
               BYVAL wParam AS LONG,BYVAL lParam AS LONG)AS LONG
    
    
      LOCAL  NewR, NewC AS LONG
      LOCAL  LVHT AS LVHITTESTINFO
    
      SELECT CASE AS LONG wMsg
    
        CASE %WM_RBUTTONDOWN
             EXIT FUNCTION
    
        CASE %WM_LBUTTONDOWN
          lvht.pt.x = LO(WORD, lparam)                                          'X-coord mouse left butt dwn
          lvht.pt.y = HI(WORD, lparam)                                          'Y-coord mouse left butt dwn
          SendMessageW(hwnd, %LVM_SUBITEMHITTEST, BYVAL 0, BYVAL VARPTR(LVHT))  'Find lvitem and subitem
          IF lVHT.iItem <> -1 THEN                                              'Did we find item at coords?
            NewR = LVHT.iItem+1    : NewC = LVHT.iSubItem+1                     'Test bounds
            IF NewR < 1 THEN
                NewR = 1
               IF NewR > MaxRow THEN
                    NewR = MaxRow
               END IF
            END IF
    
    
            IF NewC < 1 THEN
                NewC = 1
                IF NewC > MaxCol THEN
                     NewC = MaxCol
                END IF
             END IF
            IF (CurRow <> NewR) OR (CurCol <> NewC) THEN                            'Unselect prev select,
              LISTVIEW UNSELECT hDlg, %IDC_ListView, CurRow                      'req'd on subitems
              CurRow = NewR
              CurCol = NewC                                         'Update Row Column vars
              LISTVIEW SELECT hDlg, %IDC_ListView, CurRow                        'Select new ListView item
              LISTVIEW VISIBLE hDlg, %IDC_ListView, CurRow                             'Ensure new LVitem visible
            END IF                                                              '
          END IF
                                                                         '
         ' SetFocus getdlgItem(hDlg,%IDC_ListView)
          SetFocus hLv
          FUNCTION = 0                                                          'Handled msg, return zero
          EXIT FUNCTION                                                         'don't call org lv callb
       END SELECT
      DIALOG SET TEXT hDlg, "You clicked: " & FORMAT$(CurRow) & ", " & FORMAT$(CurCol)
      FUNCTION = CallWindowProcW(OldLVProc, hWnd, wMsg, wParam, lParam)         'Unhandled; pass to org lvcb
    END FUNCTION

    the slow or problematic code portion is located as shown below
    Code:
    CASE %WM_COMMAND
          SELECT CASE AS LONG CB.CTL
    
            CASE %IDC_BtnInsRow
              IF CB.CTLMSG = %BN_CLICKED THEN
                 IF CurRow > 0 AND CurCol > 0 THEN
                  ' Inserting a blank row at Row CurRow and at Column  CurCol
                    FOR colj = 1 TO MaxCol
                       ' blank off the data array at the current row
                        ARRAY INSERT DataLV(colj, CurRow), ""
                    NEXT colj
                  '  CONTROL SEND hDlg, %IDC_ListView ,%WM_SETREDRAW ,%false,0
                   ' Need to preset to MaxRow here to allocate the memory
                  '  CONTROL SEND hDlg, %IDC_ListView ,%LVM_SETITEMCOUNT ,MaxRow,0
                    FOR jrow = 1 TO MaxRow
                        FOR  colj = 1 TO MaxCol
                             LISTVIEW SET TEXT hDlg, %IDC_ListView, jrow  , colj, DataLV(colj,jrow)
                        NEXT colj
                    NEXT jrow
                   ' CONTROL SEND hDlg, %IDC_ListView ,%WM_SETREDRAW ,%true,0
    
                   '  the below code for redrawing the listview makes it even slower!
                     ' Refresh the entire grid view
                      ' CONTROL GET CLIENT hDlg, %IDC_ListView TO wrt,hrt
                     '  rtr.nLeft = 0
                     '  rtr.nTop = 0
                     '  rtr.nRight = wrt
                     '  rtr.nBottom = hrt
                     '  InvalidateRect hLv , rtr, %False
    
                 END IF
              END IF
          END SELECT

    all help is much appreciated

  • #2
    Note that PB has the ARRAY INSERT statement which is very fast, hence is there an equivalent winapi statement that we can insert
    rows faster into a listview ?

    using the below code to rewrite the listview using an array is very very inefficient
    and painfully slow ?

    Code:
         FOR jrow = 1 TO MaxRow
             FOR  colj = 1 TO MaxCol
                     LISTVIEW SET TEXT hDlg, %IDC_ListView, jrow  , colj, DataLV(colj,jrow)
             NEXT colj
         NEXT jrow

    Comment


    • #3
      How about https://forum.powerbasic.com/forum/u...iew#post774843

      Comment


      • #4
        LISTVIEW INSERT ITEM maybe?
        Dale

        Comment


        • #5
          Originally posted by Dale Yarker View Post
          LISTVIEW INSERT ITEM maybe?
          Aw, gee - you're no fun

          Comment


          • #6
            Thank you Dale, how do you code LISTVIEW INSERT ITEM ? any sample code ?

            Comment


            • #7
              I replace the code in #2 by

              Code:
              LISTVIEW INSERT ITEM hDlg, %IDC_ListView,CurRow , 1, DataLV(1,Currow)
              and it works instantaneosly but the cursor is out --> gotten some multiple cursors in the Listview ?

              Comment


              • #8
                Tim,

                Try this..
                Code:
                                        ListView UnSelect hDlg, %IDC_ListView, CurRow
                                        LISTVIEW INSERT ITEM hDlg, %IDC_ListView, CurRow , 1, DataLV(1,Currow)
                Rgds, Dave

                Comment


                • #9
                  RE:
                  Code:
                     FOR jrow = 1 TO MaxRow
                        FOR colj = 1 TO MaxCol
                             LISTVIEW SET TEXT hDlg, %IDC_ListView, jrow , colj, DataLV(colj,jrow)
                        NEXT colj
                  NEXT jrow
                  Why are you resetting the text for all the rows when you are owner-drawing anyway?

                  Besides, I'll bet a lot 'LISTVIEW INSERT' is implemented using the LVM_INSERTITEM message, meaning the text of the existing items (rows) is not altered by the insert.

                  At least in my experience,, doing stuff you don't need to do often slows down program execution.

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

                  Comment


                  • #10
                    Thank you Sir Dave Biggs, whew I was struggling the whole day yesterday to fix this

                    Here's the final code version for any one who might need this

                    Code:
                    ' LV Insert row.bas
                    ' https://forum.powerbasic.com/forum/user-to-user-discussions/programming/754993-listview-full-row-select?p=755071#post755071
                            ' thanks to Peter Lameijn and Dave Biggs
                    
                    
                    #COMPILER PBWIN 10
                    #COMPILE EXE
                    #DIM ALL
                    
                     GLOBAL OldLVProc, hDlg, hLv AS LONG
                     GLOBAL DataLV()  AS STRING
                    
                     GLOBAL MaxRow , MaxCol  AS LONG
                     GLOBAL AMrw AS LONG
                    
                    ' current selected row and column
                     GLOBAL CurRow, CurCol AS LONG
                    
                    %USEMACROS = 1
                    #INCLUDE ONCE "WIN32API.INC"
                    #INCLUDE ONCE "COMMCTRL.INC"
                    
                    '--------------------------------------------------------------------------------------------------
                       %IDC_ListView   = 102
                       %IDC_BtnInsRow        = 103
                    
                    
                    
                    
                    '--------------------------------------------------------------------------------------------------
                    FUNCTION PBMAIN()
                    
                      DIALOG NEW 0,"Listview with colored fields", , ,350, 300, %WS_POPUP OR _
                            %WS_BORDER OR %WS_DLGFRAME OR %WS_SYSMENU 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 LISTVIEW, hDlg, %IDC_ListView, "Listview1",_
                                         25, 25, 300, 200, %LVS_REPORT OR _
                                        %WS_TABSTOP OR %WS_GROUP
                    
                        CONTROL ADD BUTTON, hDlg, %IDC_BtnInsRow, _
                                   "Insert A Blank Row", 105, 270, 90, 15
                    
                         hLv = GetDlgItem(hDlg, %IDC_ListView)
                    
                    
                       ' Partially populate the list view with data
                          MaxRow = 10000
                          MaxCol = 6
                          PopListView hDlg
                    
                    
                        DIALOG SHOW MODAL hDlg, CALL DialogProc
                    END FUNCTION
                    
                    
                    '-----------------------------------------------------------------
                    CALLBACK FUNCTION DialogProc()         'Dialog callback
                    
                      LOCAL  pnmh AS NMHDR PTR
                      LOCAL pLVDI AS LV_DispInfo PTR, lplvcd AS NMLVCUSTOMDRAW PTR
                    
                      LOCAL colj , jrow , wrt,hrt AS LONG
                      LOCAL rtr AS Rect
                    
                    
                      SELECT CASE AS LONG CB.MSG
                        CASE %WM_INITDIALOG
                          OldLVProc = SetWindowLong(GetDlgItem(CB.HNDL, %IDC_ListView), _
                                     %GWL_WNDPROC, BYVAL CODEPTR(LVProc))
                          CONTROL REDRAW CB.HNDL,%IDC_ListView
                    
                        CASE %WM_COMMAND
                          SELECT CASE AS LONG CB.CTL
                    
                            CASE %IDC_BtnInsRow
                              IF CB.CTLMSG = %BN_CLICKED THEN
                                 IF CurRow > 0 AND CurCol > 0 THEN
                                  ' Inserting a blank row at Row CurRow and at Column  CurCol
                                    FOR colj = 1 TO MaxCol
                                       ' blank off the data array at the current row
                                        ARRAY INSERT DataLV(colj, CurRow), ""
                                    NEXT colj
                       ' https://forum.powerbasic.com/forum/user-to-user-discussions/powerbasic-for-windows/801846-how-to-insert-a-blank-row-into-a-listview-speedily?p=801856#post801856
                                '   set listview to the unselected state
                                    LISTVIEW UNSELECT hDlg, %IDC_ListView, CurRow
                                '   blank off the current row in the listview with the new data
                                    LISTVIEW INSERT ITEM hDlg, %IDC_ListView, CurRow , 1, DataLV(1,Currow)
                    
                                   '  the below code for redrawing the listview makes it even slower!
                                     ' Refresh the entire grid view
                                      ' CONTROL GET CLIENT hDlg, %IDC_ListView TO wrt,hrt
                                     '  rtr.nLeft = 0
                                     '  rtr.nTop = 0
                                     '  rtr.nRight = wrt
                                     '  rtr.nBottom = hrt
                                     '  InvalidateRect hLv , rtr, %False
                    
                                 END IF
                              END IF
                          END SELECT
                    
                        CASE %WM_NOTIFY
                          SELECT CASE CB.NMID
                            CASE %IDC_ListView
                              SELECT CASE CB.NMCODE
                                CASE %NM_CUSTOMDRAW
                                  lplvcd = CB.LPARAM
                    
                                  SELECT CASE @lplvcd.nmcd.dwDrawStage
                                    CASE %CDDS_PREPaint , %CDDS_ITEMPREPAINT
                                      FUNCTION = %CDRF_NOTIFYITEMDRAW
                                      EXIT FUNCTION
                    
                                    CASE %CdDS_ItemPrePaint  OR %CDDS_SUBITEM
                                      IF (@lplvcd.nmcd.dwitemspec MOD 2) = 0 THEN
                                        @lplvcd.clrTextBk =  GetSysColor(%COLOR_INFOBK)
                                      ELSE
                                        @lplvcd.clrTextBk = GetSysColor(%COLOR_MENU)
                                      END IF
                    
                                      @lplvcd.clrText   = GetSysColor(%COLOR_INFOTEXT)
                                      FUNCTION = %CDRF_NewFont
                                      EXIT FUNCTION
                    
                                  END SELECT
                              END SELECT
                          END SELECT
                    
                        CASE %WM_DESTROY
                          SetWindowLong(GetDlgItem(CB.HNDL, %IDC_ListView), %GWL_WNDPROC, OldLVProc)
                      END SELECT
                    
                    END FUNCTION
                    
                    
                    
                    '--------------------------------------------------------------
                    ' populate the listview with some data
                    FUNCTION PopListView(BYVAL hDlg AS DWORD)AS LONG
                    
                      LOCAL lCol, lRow, lStyle AS LONG
                      LOCAL jr , jc AS LONG
                    
                      LISTVIEW GET STYLEXX hDlg, %IDC_ListView TO lStyle
                      LISTVIEW SET STYLEXX hDlg, %IDC_ListView, lStyle OR %WS_BORDER OR _
                          %LVS_REPORT OR %LVS_EX_FULLROWSELECT OR %LVS_EX_GRIDLINES
                    
                    'display the headers
                        LISTVIEW INSERT COLUMN hDlg, %IDC_ListView, 1, "Header 1 ", 50,0
                        LISTVIEW INSERT COLUMN hDlg, %IDC_ListView, 2, "Header 2 ", 40,0
                        LISTVIEW INSERT COLUMN hDlg, %IDC_ListView, 3, "Header 3 ", 40,0
                        LISTVIEW INSERT COLUMN hDlg, %IDC_ListView, 4, "Header 4 ", 40,0
                        LISTVIEW INSERT COLUMN hDlg, %IDC_ListView, 5, "Header 5 ", 40,0
                        LISTVIEW INSERT COLUMN hDlg, %IDC_ListView, 6, "Header 6 ", 40,0
                    
                    
                      ' prepare the LV data array
                        REDIM DataLV( 1 TO MaxCol, 1 TO MaxRow)
                    
                      ' create 6000 rows of data
                      FOR jr = 1 TO 6000
                          FOR jc = 1 TO 6
                              DataLV( jc, jr) = FORMAT$(jr) & " , " & FORMAT$(jc)
                          NEXT jc
                      NEXT jr
                    
                    
                     ' determine the last blank row by adding a additional buffer of 100 rows
                     ' this will indicate the last row to be written  and also
                     ' ensure that AMrw does not exceed MaxRow
                        AMrw = 6000 + 100
                        IF AMrw > MaxRow THEN
                            AMrw = MaxRow
                        END IF
                    
                    
                    
                     ' display the data in the listview
                       FOR lRow = 1 TO MaxRow
                           ' set up each row
                          LISTVIEW INSERT ITEM hDlg, %IDC_ListView, lRow, 0, DataLV(1,lRow)
                          ' set up the elements for that row lRow
                            LISTVIEW SET TEXT hDlg, %IDC_ListView,lRow  , 2  ,DataLV(2,lRow)
                            LISTVIEW SET TEXT hDlg, %IDC_ListView,lRow  , 3  ,DataLV(3,lRow)
                            LISTVIEW SET TEXT hDlg, %IDC_ListView,lRow  , 4  ,DataLV(4,lRow)
                            LISTVIEW SET TEXT hDlg, %IDC_ListView,lRow  , 5  ,DataLV(5,lRow)
                            LISTVIEW SET TEXT hDlg, %IDC_ListView,lRow  , 6  ,DataLV(6,lRow)
                       NEXT lRow
                    
                    
                    END FUNCTION
                    
                    
                    '-------------------------------------------------------------
                    FUNCTION LVProc(BYVAL hWnd AS LONG,BYVAL wMsg AS LONG,_
                               BYVAL wParam AS LONG,BYVAL lParam AS LONG)AS LONG
                    
                    
                      LOCAL  NewR, NewC AS LONG
                      LOCAL  LVHT AS LVHITTESTINFO
                    
                      SELECT CASE AS LONG wMsg
                    
                        CASE %WM_RBUTTONDOWN
                             EXIT FUNCTION
                    
                        CASE %WM_LBUTTONDOWN
                          lvht.pt.x = LO(WORD, lparam)                                          'X-coord mouse left butt dwn
                          lvht.pt.y = HI(WORD, lparam)                                          'Y-coord mouse left butt dwn
                          SendMessageW(hwnd, %LVM_SUBITEMHITTEST, BYVAL 0, BYVAL VARPTR(LVHT))  'Find lvitem and subitem
                          IF lVHT.iItem <> -1 THEN                                              'Did we find item at coords?
                            NewR = LVHT.iItem+1    : NewC = LVHT.iSubItem+1                     'Test bounds
                            IF NewR < 1 THEN
                                NewR = 1
                               IF NewR > MaxRow THEN
                                    NewR = MaxRow
                               END IF
                            END IF
                    
                    
                            IF NewC < 1 THEN
                                NewC = 1
                                IF NewC > MaxCol THEN
                                     NewC = MaxCol
                                END IF
                             END IF
                            IF (CurRow <> NewR) OR (CurCol <> NewC) THEN                            'Unselect prev select,
                              LISTVIEW UNSELECT hDlg, %IDC_ListView, CurRow                      'req'd on subitems
                              CurRow = NewR
                              CurCol = NewC                                         'Update Row Column vars
                              LISTVIEW SELECT hDlg, %IDC_ListView, CurRow                        'Select new ListView item
                              LISTVIEW VISIBLE hDlg, %IDC_ListView, CurRow                             'Ensure new LVitem visible
                            END IF                                                              '
                          END IF
                                                                                         '
                         ' SetFocus getdlgItem(hDlg,%IDC_ListView)
                          SetFocus hLv
                          FUNCTION = 0                                                          'Handled msg, return zero
                          EXIT FUNCTION                                                         'don't call org lv callb
                       END SELECT
                      DIALOG SET TEXT hDlg, "You clicked: " & FORMAT$(CurRow) & ", " & FORMAT$(CurCol)
                      FUNCTION = CallWindowProcW(OldLVProc, hWnd, wMsg, wParam, lParam)         'Unhandled; pass to org lvcb
                    END FUNCTION

                    Comment

                    Working...
                    X