Announcement

Collapse
No announcement yet.

Parallel scrolling problem in ListView windows

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

  • Parallel scrolling problem in ListView windows

    Frequently large amounts of data are organized in spreadsheet
    format, each line representing the data of one individual and
    each column representing a specific variable or characteristic.
    Visual orientation and comparison is facilitated by looking at
    the data in two windows which can be scrolled in parallel in a
    synchronized way (with the same steps) in the two windows.
    E.g. if you have a left and right window, vertical scrolling
    should be synchronized to maintain the same relative line
    position in the two windows at any time. Similarly, if you have
    an upper and lower window, horizontal scrolling should be
    synchronized so that the column positions in the upper window
    always are the same as in the lower window.

    How do you make the windows scroll in parallel in a synchronized
    way?

    In the example below presenting a left and right window with the
    same data, vertical scrolling should be synchronized. When you
    scroll one of the windows vertically, the other should
    automatically scroll in exactly the same way so that the
    corresponding lines always are at the same horizontal level.
    This would imply that the amount and direction of scrolling of
    a window should be detected and the information used to make
    the other window scroll similarly. As you can see I have tried
    to implement stuff found in the forum, but it is not working.
    Can you help me?.

    Regards,

    Erik
    Code:
    'Unsolved "Parallel" scrolling problem.
    '======================================
    'Listview example. Inspired by code provided to the PowerBasic FORUM
    'by Peter Redei, David L Morris and Aisin Geuru Suen Yue.
    '
    'Erik Christensen, Copenhagen, Denmark.   [email protected]
    '
    ' ** Eliminate unnecessary macros
    %NOANIMATE = 1
    %NODRAGLIST = 1
    %NOHEADER = 1
    %NOIMAGELIST = 1
    '%NOLISTVIEW = 1
    %NOTABCONTROL = 1
    %NOTRACKBAR = 1
    %NOTREEVIEW = 1
    %NOUPDOWN = 1
    #COMPILE EXE
    #INCLUDE "WIN32API.INC"
    #INCLUDE "COMMCTRL.INC"
    
    ' some supplementary listview styles that you may not have in your
    ' commctrl.inc file
    ' they are not all used in this program
    %LVM_FIRST = &H1000
    %LVM_SETEXTENDEDLISTVIEWSTYLE = %LVM_FIRST + 54
    %LVM_GETEXTENDEDLISTVIEWSTYLE = %LVM_FIRST + 55
    %LVS_EX_FULLROWSELECT = &H20
    %LVS_EX_GRIDLINES = &H1
    %LVS_EX_CHECKBOXES = &H4
    %LVS_EX_TRACKSELECT = &H8
    %LVS_EX_HEADERDRAGDROP = &H10
    %LVM_GETITEMSTATE = (%LVM_FIRST + 44)
    %LVM_GETITEMTEXT = (%LVM_FIRST + 45)
    %LVIS_STATEIMAGEMASK = &HF000
    %LVBKIF_SOURCE_NONE = &H0
    %LVBKIF_SOURCE_HBITMAP = &H1
    %LVBKIF_SOURCE_URL = &H2
    %LVBKIF_SOURCE_MASK = &H3
    %LVBKIF_STYLE_NORMAL = &H0
    %LVBKIF_STYLE_TILE = &H10
    %LVBKIF_STYLE_MASK = &H10
    %LVM_SETBKIMAGEA = %LVM_FIRST + 68
    %LVM_SETBKIMAGE = %LVM_SETBKIMAGEA
    %LVM_SETTEXTBKCOLOR = %LVM_FIRST + 38
    %LVM_SETBKIMAGEA = %LVM_FIRST + 68
    %LVM_SETBKIMAGE = %LVM_SETBKIMAGEA
    %CLR_NONE = &HFFFFFFFF
    
    %IDC_TEXT =105
    %IDLISTVIEW1 = 101
    %IDLISTVIEW2 = 102
    %My_MIN           =    20
    %My_MAX           =  3000
    %My_STEP          =    10
    %My_INITIAL       =   440
    
    GLOBAL hsb1 AS LONG
    GLOBAL hsb2 AS LONG
    
    DECLARE CALLBACK FUNCTION DlgProc
    
    '------------------------------------------------------------------------------
    ' Global variable to recieve the user name
    GLOBAL hListView AS LONG
    
    TYPE dField
      fName AS ASCIIZ * 80
      SIZE AS INTEGER
      Alignment AS INTEGER
    END TYPE
    
    TYPE ListData
      Columns AS INTEGER
      Fields(0 TO 80) AS dField
    END TYPE
    
    GLOBAL LPsi AS SCROLLINFO
    
    'DECLARE FUNCTION GetScrollInfo LIB "USER32.DLL" ALIAS _
    '  "GetScrollInfo" (BYVAL hWnd AS LONG, BYVAL n AS LONG, _
    '  lpScrollInfo AS SCROLLINFO) AS LONG
    'TYPE SCROLLINFO
    '  cbSize AS DWORD
    '  fMask AS DWORD
    '  nMin AS LONG
    '  nMax AS LONG
    '  nPage AS DWORD
    '  nPos AS LONG
    '  nTrackPos AS LONG
    'END TYPE
    
    SUB AppendListView (hList AS LONG, Rec() AS STRING )
      DIM z AS INTEGER
      DIM iStatus AS INTEGER
      DIM szStr AS ASCIIZ * 300
      DIM lvi AS LV_ITEM
      LOCAL x AS LONG
      'this will be the next record
      lvi.iItem = ListView_GetItemCount(hList) '+ 1
      lvi.mask = %LVIF_TEXT
      lvi.stateMask = %LVIS_FOCUSED '%LVIS_SELECTED
      lvi.pszText = VARPTR(szStr)
      FOR z = 0 TO UBOUND(Rec)
        szStr = Rec(z)
        lvi.iSubItem = z
        lvi.lParam = lvi.iItem
        IF z = 0 THEN
          lvi.mask = %LVIF_TEXT OR %LVIF_PARAM OR %LVIF_STATE
          iStatus = ListView_InsertItem (hList, lvi)
        ELSE
          lvi.mask = %LVIF_TEXT
          iStatus = ListView_SetItem (hList, lvi)
        END IF
      NEXT
    END SUB
    
    FUNCTION PBMAIN () AS LONG
      $REGISTER NONE
      LOCAL hDlg AS LONG
      LOCAL result AS LONG, zText AS ASCIIZ * 255
      LOCAL icc AS INIT_COMMON_CONTROLSEX
      LOCAL LVC AS LV_COLUMN, i AS LONG,r AS LONG, c AS LONG, lStyle AS LONG
      LOCAL LVI AS LV_ITEM
    
      %NumCols = 21:%NumRows = 50
      DIM Rec(%NumCols)AS STRING
      icc.dwICC = %ICC_DATE_CLASSES OR %ICC_BAR_CLASSES OR %ICC_LISTVIEW_CLASSES
      icc.dwSize = SIZEOF(icc)
    
      InitCommonControlsEx icc
      ' ** Create a new dialog template
      DIALOG NEW 0, "ListView parallel scrolling proplem", ,, 342, 210, _
         %WS_POPUP OR %DS_MODALFRAME OR %WS_CAPTION OR %WS_MINIMIZEBOX OR _
         %WS_SYSMENU OR %WS_MAXIMIZEBOX OR %DS_CENTER, 0 TO hDlg
      ' ** Add controls to it
      '$WC_LISTVIEW
      CONTROL ADD "SysListView32", hDlg, %IDLISTVIEW1,"",4,5,57,194, _
         %WS_border OR %WS_Child OR %WS_visible OR _
         %LVS_Report OR %LVS_SHOWSELALWAYS, _
         %WS_EX_CLIENTEDGE
    
      CONTROL ADD "SysListView32", hDlg, %IDLISTVIEW2,"",58,5,280,194, _
         %WS_border OR %WS_Child OR %WS_visible OR _
         %LVS_Report OR %LVS_SHOWSELALWAYS, _
         %WS_EX_CLIENTEDGE
    
    
      CONTROL ADD LABEL, hDlg, %IDC_TEXT, "", 4,200,27,9, %SS_CENTERIMAGE OR %SS_SUNKEN
    
    
      CONTROL HANDLE hDlg,%IDLISTVIEW1 TO hListView
      lStyle = SendMessage(hListView, _
               %LVM_GETEXTENDEDLISTVIEWSTYLE, 0, 0)
      lStyle = lStyle OR %LVS_EX_GRIDLINES ' OR %LVS_EX_FULLROWSELECT OR %LVS_EX_TRACKSELECT
      CALL SendMessage(hListView, %LVM_SETEXTENDEDLISTVIEWSTYLE, _
           0, BYVAL lStyle)
    
      CONTROL HANDLE hDlg,%IDLISTVIEW2 TO hListView
      lStyle = SendMessage(hListView, _
               %LVM_GETEXTENDEDLISTVIEWSTYLE, 0, 0)
      lStyle = lStyle OR %LVS_EX_GRIDLINES ' OR %LVS_EX_FULLROWSELECT OR %LVS_EX_TRACKSELECT
      CALL SendMessage(hListView, %LVM_SETEXTENDEDLISTVIEWSTYLE, _
           0, BYVAL lStyle)
    
      lvC.mask = %LVCF_FMT OR %LVCF_WIDTH OR %LVCF_TEXT OR %LVCF_SUBITEM
      lvC.fmt = %LVCFMT_CENTER '%LVCFMT_LEFT '%LVCFMT_RIGHT
      lvC.cx = 90
      LVC.cchTextMax = 255
    
      zText = "Identification "  ' text for first (identification) column
      LVC.pszText = VARPTR(zText)
      CONTROL SEND hDlg,%IDLISTVIEW1,%LVM_INSERTCOLUMN, 1, VARPTR(lvc) ' to ListView 1
      CONTROL SEND hDlg,%IDLISTVIEW2,%LVM_INSERTCOLUMN, 1, VARPTR(lvc) ' to ListView 2
    
    
      ' fill ListView 1 with remaining data
    
      FOR c = 2 TO %NumCols
        zText = "Variable " + FORMAT$(c - 1) ' column variable labels 1-20
        LVC.pszText = VARPTR(zText)
        CONTROL SEND hDlg,%IDLISTVIEW1,%LVM_INSERTCOLUMN, c, VARPTR(lvc)
      NEXT
      CONTROL HANDLE hDlg,%IDLISTVIEW1 TO hListView
      RANDOMIZE 1.5
      FOR r = 1 TO %NumRows
        rec(0) = "Individual " + FORMAT$(r)  ' data for idendification column
        FOR c = 2 TO %NumCols
          rec(c-1) = FORMAT$(RND(100,999))   ' data for variable column 1-20
        NEXT c
        AppendListView hListView, Rec()
      NEXT r
    
    
      ' fill ListView 2 with remaining data
    
      FOR c = 2 TO %NumCols
        zText = "Variable " + FORMAT$(c - 1) ' column variable labels 1-20
        LVC.pszText = VARPTR(zText)
        CONTROL SEND hDlg,%IDLISTVIEW2,%LVM_INSERTCOLUMN, c, VARPTR(lvc)
      NEXT
      CONTROL HANDLE hDlg,%IDLISTVIEW2 TO hListView
      RANDOMIZE 1.5
      FOR r = 1 TO %NumRows
        rec(0) = "Individual " + FORMAT$(r)  ' data for idendification column
        FOR c = 2 TO %NumCols
          rec(c-1) = FORMAT$(RND(100,999))   ' data for variable column 1-20
        NEXT c
        AppendListView hListView, Rec()
      NEXT r
    
      ' ** Display the dialog
      DIALOG SHOW MODAL hDlg CALL DlgProc
    END FUNCTION
    
    CALLBACK FUNCTION DlgProc   '  This function is not working
    
        STATIC hwndScroll1 AS LONG
        STATIC hwndScroll2 AS LONG
        STATIC X AS SINGLE
    
        LOCAL iDummy AS LONG
        LOCAL i AS LONG
    
        SELECT CASE CBMSG
        CASE %WM_INITDIALOG
            CONTROL HANDLE CBHNDL, %IDLISTVIEW1 TO hwndScroll1
            CONTROL HANDLE CBHNDL, %IDLISTVIEW2 TO hwndScroll2
            hsb1 = hwndscroll1
            hsb2 = hwndscroll2
    
            SetScrollRange hwndScroll1, %SB_VERT, %My_MIN*%My_STEP, %My_MAX*%My_STEP, %FALSE
            SetScrollPos hwndScroll1,   %SB_VERT, %My_INITIAL*%My_STEP, %TRUE
            SetScrollRange hwndScroll2, %SB_VERT, %My_MIN*%My_STEP, %My_MAX*%My_STEP, %FALSE
            SetScrollPos hwndScroll2,   %SB_VERT, %My_INITIAL*%My_STEP, %TRUE
            CONTROL SET TEXT CBHNDL, %IDC_TEXT, FORMAT$(%My_INITIAL)
            X = %My_INITIAL
    
    
        CASE %WM_VSCROLL
    
           SELECT CASE CBLPARAM
    
             CASE hsb1 '%IDC_SCROLL
    
    '%SB_LINEUP                                   = 0
    '%SB_LINELEFT                                 = 0
    '%SB_LINEDOWN                                 = 1
    '%SB_LINERIGHT                                = 1
    '%SB_PAGEUP                                   = 2
    '%SB_PAGELEFT                                 = 2
    '%SB_PAGEDOWN                                 = 3
    '%SB_PAGERIGHT                                = 3
    '%SB_THUMBPOSITION                            = 4
    '%SB_THUMBTRACK                               = 5
    '%SB_TOP                                      = 6
    '%SB_LEFT                                     = 6
    '%SB_BOTTOM                                   = 7
    '%SB_RIGHT                                    = 7
    '%SB_ENDSCROLL                                = 8
    
    
                SELECT CASE LOWRD(CBWPARAM)
                  CASE %SB_LINEUP     : X = 2 ^ (-1 / 12  ) * X
                  CASE %SB_LINEDOWN   : X = 2 ^ ( 1 / 12 ) * X
                  CASE %SB_PAGEUP     : X = X / 2
                  CASE %SB_PAGEDOWN   : X = X * 2
                  CASE %SB_THUMBTRACK : X = HIWRD(CBWPARAM)/%My_STEP
                  CASE %SB_TOP        : GetScrollRange hwndScroll1, %SB_VERT, CLNG(X*%My_STEP), iDummy
                  CASE %SB_BOTTOM     : GetScrollRange hwndScroll1, %SB_VERT, CLNG(X*%My_STEP), iDummy
                END SELECT
    
                 X = MAX(%My_MIN, MIN(%My_MAX, X))
                SetScrollPos hwndScroll1, %SB_VERT, CLNG(X*%My_STEP), %TRUE
                SetScrollPos hwndScroll2, %SB_VERT, CLNG(X*%My_STEP), %TRUE
                CONTROL SET TEXT CBHNDL, %IDC_TEXT, FORMAT$( X,"#.#")
    
    
            CASE hsb2 '%IDC_SCROLL2
    
                SELECT CASE LOWRD(CBWPARAM)
                  CASE %SB_LINEUP     : X = 2 ^ (-1 / 12  ) * X
                  CASE %SB_LINEDOWN   : X = 2 ^ ( 1 / 12 ) * X
                  CASE %SB_PAGEUP     : X = X / 2
                  CASE %SB_PAGEDOWN   : X = X * 2
                  CASE %SB_THUMBTRACK : X = HIWRD(CBWPARAM)/%My_STEP
                  CASE %SB_TOP        : GetScrollRange hwndScroll2, %SB_VERT, CLNG(X*%My_STEP), iDummy
                  CASE %SB_BOTTOM     : GetScrollRange hwndScroll2, %SB_VERT, CLNG(X*%My_STEP), iDummy
                END SELECT
    
                X = MAX(%My_MIN, MIN(%My_MAX, X))
                SetScrollPos hwndScroll1, %SB_VERT, CLNG(X*%My_STEP), %TRUE
                SetScrollPos hwndScroll2, %SB_VERT, CLNG(X*%My_STEP), %TRUE
                CONTROL SET TEXT CBHNDL, %IDC_TEXT, FORMAT$( X,"#.#")
    
          END SELECT
    
        END SELECT
    END FUNCTION
    ------------------




    [This message has been edited by Erik Christensen (edited December 30, 2000).]

  • #2
    Without having tested it myself, I would say you probably need to
    subclass the listview controls in order to be able to trap their
    individual %WM_SCROLL messages. Maybe you can use ListView_GetTopIndex
    in combination with ListView_Scroll to set the second listview,
    without having to handle all the scrolling positions by code?
    Just some wild ideas..


    ------------------

    Comment


    • #3
      Borje is correct, you need to subclass your main Listview control and
      trap the WM_SCROLL API message.

      Here is a NOT so wild Idea...

      Inside your Subclassed procedure for the main Listview control...

      Code:
              Select Case msg
         
                'message of interest
                 Case %WM_VSCROLL
                  
                   'The actual scrolling method - a one-liner!
                   'On entering this routine, wParam contains one of the SB_xxx messages.
                   'By passing it directly to the mirrored listview, the mirror
                   'tracks as the subclassed listview is scrolled.
                     
                    Call SendMessage(hListView2, %WM_VSCROLL, wParam, 0)
      Because the scrollbar of interest is a child of a parent window, another
      ListView, the lParam member of the call is left null.

      HTH
      Regards,
      Jules

      Best regards
      Jules
      www.rpmarchildon.com

      Comment


      • #4
        Borje, Jules,
        Thanks very much for the suggestions. I have tried subclassing
        the main listview control as you can see in this revised version.
        It is still not working. Furthermore, the lines marked with *******
        in the DlgCallBack function causes the listview controls to be
        blanked out. What am I doing wrong? Can you solve the problem?
        Regards,
        Erik
        Code:
        'Unsolved "Parallel" scrolling problem.
        '======================================
        'Listview example. Inspired by code provided to the PowerBasic FORUM
        'by Peter Redei, David L Morris and Aisin Geuru Suen Yue.
        '
        'Erik Christensen, Copenhagen, Denmark.   [email protected]
        '
        ' ** Eliminate unnecessary macros
        %NOANIMATE = 1
        %NODRAGLIST = 1
        %NOHEADER = 1
        %NOIMAGELIST = 1
        '%NOLISTVIEW = 1
        %NOTABCONTROL = 1
        %NOTRACKBAR = 1
        %NOTREEVIEW = 1
        %NOUPDOWN = 1
        #COMPILE EXE
        #INCLUDE "WIN32API.INC"
        #INCLUDE "COMMCTRL.INC"
        
        ' some supplementary listview styles that you may not have in your
        ' commctrl.inc file
        ' they are not all used in this program
        %LVM_FIRST = &H1000
        %LVM_SETEXTENDEDLISTVIEWSTYLE = %LVM_FIRST + 54
        %LVM_GETEXTENDEDLISTVIEWSTYLE = %LVM_FIRST + 55
        %LVS_EX_FULLROWSELECT = &H20
        %LVS_EX_GRIDLINES = &H1
        %LVS_EX_CHECKBOXES = &H4
        %LVS_EX_TRACKSELECT = &H8
        %LVS_EX_HEADERDRAGDROP = &H10
        %LVM_GETITEMSTATE = (%LVM_FIRST + 44)
        %LVM_GETITEMTEXT = (%LVM_FIRST + 45)
        %LVIS_STATEIMAGEMASK = &HF000
        %LVBKIF_SOURCE_NONE = &H0
        %LVBKIF_SOURCE_HBITMAP = &H1
        %LVBKIF_SOURCE_URL = &H2
        %LVBKIF_SOURCE_MASK = &H3
        %LVBKIF_STYLE_NORMAL = &H0
        %LVBKIF_STYLE_TILE = &H10
        %LVBKIF_STYLE_MASK = &H10
        %LVM_SETBKIMAGEA = %LVM_FIRST + 68
        %LVM_SETBKIMAGE = %LVM_SETBKIMAGEA
        %LVM_SETTEXTBKCOLOR = %LVM_FIRST + 38
        %LVM_SETBKIMAGEA = %LVM_FIRST + 68
        %LVM_SETBKIMAGE = %LVM_SETBKIMAGEA
        %CLR_NONE = &HFFFFFFFF
        
        %IDC_TEXT =105
        %IDLISTVIEW1 = 101
        %IDLISTVIEW2 = 102
        
        GLOBAL hDlg AS LONG
        GLOBAL hListView1 AS LONG
        GLOBAL hListView2 AS LONG
        GLOBAL hListView AS LONG
        
        DECLARE CALLBACK FUNCTION DlgCallBack
        
        TYPE dField
          fName AS ASCIIZ * 80
          SIZE AS INTEGER
          Alignment AS INTEGER
        END TYPE
        
        TYPE ListData
          Columns AS INTEGER
          Fields(0 TO 80) AS dField
        END TYPE
        
        SUB AppendListView (hList AS LONG, Rec() AS STRING )
          DIM z AS INTEGER
          DIM iStatus AS INTEGER
          DIM szStr AS ASCIIZ * 300
          DIM lvi AS LV_ITEM
          LOCAL x AS LONG
          'this will be the next record
          lvi.iItem = ListView_GetItemCount(hList) '+ 1
          lvi.mask = %LVIF_TEXT
          lvi.stateMask = %LVIS_FOCUSED '%LVIS_SELECTED
          lvi.pszText = VARPTR(szStr)
          FOR z = 0 TO UBOUND(Rec)
            szStr = Rec(z)
            lvi.iSubItem = z
            lvi.lParam = lvi.iItem
            IF z = 0 THEN
              lvi.mask = %LVIF_TEXT OR %LVIF_PARAM OR %LVIF_STATE
              iStatus = ListView_InsertItem (hList, lvi)
            ELSE
              lvi.mask = %LVIF_TEXT
              iStatus = ListView_SetItem (hList, lvi)
            END IF
          NEXT
        END SUB
        
        FUNCTION PBMAIN () AS LONG
          $REGISTER NONE
          LOCAL result AS LONG, zText AS ASCIIZ * 255
          LOCAL icc AS INIT_COMMON_CONTROLSEX
          LOCAL LVC AS LV_COLUMN, i AS LONG,r AS LONG, c AS LONG, lStyle AS LONG
          LOCAL LVI AS LV_ITEM
        
          GLOBAL fnOld() AS LONG
          DIM fnOld(2)
        
          %NumCols = 21:%NumRows = 50
          DIM Rec(%NumCols)AS STRING
          icc.dwICC = %ICC_DATE_CLASSES OR %ICC_BAR_CLASSES OR %ICC_LISTVIEW_CLASSES
          icc.dwSize = SIZEOF(icc)
        
          InitCommonControlsEx icc
          ' ** Create a new dialog template
          DIALOG NEW 0, "ListView parallel scrolling problem", ,, 342, 210, _
             %WS_POPUP OR %DS_MODALFRAME OR %WS_CAPTION OR %WS_MINIMIZEBOX OR _
             %WS_SYSMENU OR %WS_MAXIMIZEBOX OR %DS_CENTER, 0 TO hDlg
          ' ** Add controls to it
          '$WC_LISTVIEW
          CONTROL ADD "SysListView32", hDlg, %IDLISTVIEW1,"",4,5,57,194, _
             %WS_border OR %WS_Child OR %WS_visible OR _
             %LVS_Report OR %LVS_SHOWSELALWAYS, _
             %WS_EX_CLIENTEDGE
        
        
          CONTROL ADD "SysListView32", hDlg, %IDLISTVIEW2,"",58,5,280,194, _
             %WS_border OR %WS_Child OR %WS_visible OR _
             %LVS_Report OR %LVS_SHOWSELALWAYS, _
             %WS_EX_CLIENTEDGE
        
          CONTROL ADD LABEL, hDlg, %IDC_TEXT, "", 4,200,27,9, %SS_CENTERIMAGE OR %SS_SUNKEN
        
        
          CONTROL HANDLE hDlg,%IDLISTVIEW1 TO hListView
          lStyle = SendMessage(hListView, _
                   %LVM_GETEXTENDEDLISTVIEWSTYLE, 0, 0)
          lStyle = lStyle OR %LVS_EX_GRIDLINES ' OR %LVS_EX_FULLROWSELECT OR %LVS_EX_TRACKSELECT
          CALL SendMessage(hListView, %LVM_SETEXTENDEDLISTVIEWSTYLE, _
               0, BYVAL lStyle)
        
          CONTROL HANDLE hDlg,%IDLISTVIEW2 TO hListView
          lStyle = SendMessage(hListView, _
                   %LVM_GETEXTENDEDLISTVIEWSTYLE, 0, 0)
          lStyle = lStyle OR %LVS_EX_GRIDLINES ' OR %LVS_EX_FULLROWSELECT OR %LVS_EX_TRACKSELECT
          CALL SendMessage(hListView, %LVM_SETEXTENDEDLISTVIEWSTYLE, _
               0, BYVAL lStyle)
        
          lvC.mask = %LVCF_FMT OR %LVCF_WIDTH OR %LVCF_TEXT OR %LVCF_SUBITEM
          lvC.fmt = %LVCFMT_CENTER '%LVCFMT_LEFT '%LVCFMT_RIGHT
          lvC.cx = 90
          LVC.cchTextMax = 255
        
          zText = "Identification "  ' text for first (identification) column
          LVC.pszText = VARPTR(zText)
          CONTROL SEND hDlg,%IDLISTVIEW1,%LVM_INSERTCOLUMN, 1, VARPTR(lvc) ' to ListView 1
          CONTROL SEND hDlg,%IDLISTVIEW2,%LVM_INSERTCOLUMN, 1, VARPTR(lvc) ' to ListView 2
        
        
          ' fill ListView 1 with remaining data
        
          FOR c = 2 TO %NumCols
            zText = "Variable " + FORMAT$(c - 1) ' column variable labels 1-20
            LVC.pszText = VARPTR(zText)
            CONTROL SEND hDlg,%IDLISTVIEW1,%LVM_INSERTCOLUMN, c, VARPTR(lvc)
          NEXT
          CONTROL HANDLE hDlg,%IDLISTVIEW1 TO hListView
          RANDOMIZE 1.5
          FOR r = 1 TO %NumRows
            rec(0) = "Individual " + FORMAT$(r)  ' data for idendification column
            FOR c = 2 TO %NumCols
              rec(c-1) = FORMAT$(RND(100,999))   ' data for variable column 1-20
            NEXT c
            AppendListView hListView, Rec()
          NEXT r
        
        
          ' fill ListView 2 with remaining data
        
          FOR c = 2 TO %NumCols
            zText = "Variable " + FORMAT$(c - 1) ' column variable labels 1-20
            LVC.pszText = VARPTR(zText)
            CONTROL SEND hDlg,%IDLISTVIEW2,%LVM_INSERTCOLUMN, c, VARPTR(lvc)
          NEXT
          CONTROL HANDLE hDlg,%IDLISTVIEW2 TO hListView
          RANDOMIZE 1.5
          FOR r = 1 TO %NumRows
            rec(0) = "Individual " + FORMAT$(r)  ' data for idendification column
            FOR c = 2 TO %NumCols
              rec(c-1) = FORMAT$(RND(100,999))   ' data for variable column 1-20
            NEXT c
            AppendListView hListView, Rec()
          NEXT r
        
          ' ** Display the dialog
          DIALOG SHOW MODAL hDlg CALL DlgCallBack
        END FUNCTION
        
        
        CALLBACK FUNCTION DlgCallBack
            SELECT CASE CBMSG
                CASE %WM_INITDIALOG
                    ' Subclass the edit control
                     CONTROL HANDLE CBHNDL,%IDLISTVIEW1 TO hListView1
        
        
        '*********** this line blanks out the left window *********************
                     fnOld(1) = SetWindowLong(hListView1, %GWL_WNDPROC, CODEPTR(SubClassProc))
        
        
                     CONTROL HANDLE CBHNDL,%IDLISTVIEW2 TO hListView2
        
        
        '*********** this line blanks out the right window ********************
                     fnOld(2) = SetWindowLong(hListView2, %GWL_WNDPROC, CODEPTR(SubClassProc))
        
                CASE %WM_DESTROY
                    ' Important! Remove the subclassing
                     SetWindowLong hListView1, %GWL_WNDPROC, fnOld(1)
                     SetWindowLong hListView2, %GWL_WNDPROC, fnOld(2)
            END SELECT
        END FUNCTION
        
        FUNCTION SubClassProc(BYVAL hWnd&, BYVAL wMsg&, BYVAL wParam&, BYVAL lParam&) AS LONG
            ' Process our messages in this subclass procedure
            SELECT CASE wMsg&
               CASE %WM_VSCROLL
                  SELECT CASE hWnd& 'LOWRD(WPARAM)
                     CASE hListView1 '%IDLISTVIEW
                          CALL SendMessage(hListView2,%WM_VSCROLL,wParam&,0)
                          FUNCTION = CallWindowProc(fnOld(1), hWnd&, wMsg&, wParam&, lParam&)
                     CASE hListView2 '%IDLISTVIEW
                          CALL SendMessage(hListView1,%WM_VSCROLL,wParam&,0)
                          FUNCTION = CallWindowProc(fnOld(2), hWnd&, wMsg&, wParam&, lParam&)
                  END SELECT
               CASE ELSE
            END SELECT
            ' Pass the message on to the original window procedure... the DDT engine!
        END FUNCTION
        ------------------


        [This message has been edited by Erik Christensen (edited December 30, 2000).]

        Comment


        • #5
          Erik;

          Sorry I don't know DDT all that well...

          Take a look at your SubClass procedure again, it does not look
          correct. The two calls to setwindowlong are fine. And also be
          careful, you are going to rack up the GPF points by sending the
          same Scroll-bar messages back and forth from each Listview control.
          My previous suggestion is for only one subclassed Listview.

          Regards,
          Jules


          Added later...
          Erik, I broke down your generic subclass to two seperate callbacks.
          This should get you back on track again.

          Code:
          FUNCTION SubClassProc2(BYVAL hWnd&, BYVAL wMsg&, BYVAL wParam&, BYVAL lParam&) AS LONG
              ' Process our messages in this subclass procedure
              SELECT CASE wMsg&
                 CASE %WM_VSCROLL           
                     'CALL SendMessage(hListView1,%WM_VSCROLL,wParam&,0)      
              END SELECT
              ' Pass the message on to the original window procedure... the DDT engine!
              FUNCTION = CallWindowProc(fnOld(2), hWnd&, wMsg&, wParam&, lParam&)
          END FUNCTION
              
          FUNCTION SubClassProc1(BYVAL hWnd&, BYVAL wMsg&, BYVAL wParam&, BYVAL lParam&) AS LONG
              ' Process our messages in this subclass procedure
              SELECT CASE wMsg&
                 CASE %WM_VSCROLL
                      CALL SendMessage(hListView2,%WM_VSCROLL,wParam&,0)        
              END SELECT    
              ' Pass the message on to the original window procedure... the DDT engine!
              FUNCTION = CallWindowProc(fnOld(1), hWnd&, wMsg&, wParam&, lParam&)
          END FUNCTION

          [This message has been edited by Jules Marchildon (edited December 30, 2000).]
          Best regards
          Jules
          www.rpmarchildon.com

          Comment


          • #6
            Here is not important, listview or something else.
            Simple "multiplication" works fine (for simmetrical controls).
            Code:
               #Compile Exe
               #Dim All
               #Register None
               #Include "WIN32API.INC"
               
               %ID_TEXT1 = 101
               %ID_TEXT2 = 102
               
               Global hWnd1 As Long, hWnd2 As Long, OldProc1 As Long, OldProc2 As Long, Redirected As Long
            
               CallBack Function WndProc1
                  Select Case CbMsg
                     Case %WM_VSCROLL: If IsFalse(Redirected) Then Redirected = %True: _
                                       SendMessage hWnd2, CbMsg, CbWparam, CbLparam: Redirected = %False
                  End Select
                  Function = CallWindowProc(OldProc1, CbHndl, CbMsg, CbWparam, CbLparam)
               End Function
            
               CallBack Function WndProc2
                  Select Case CbMsg
                     Case %WM_VSCROLL: If IsFalse(Redirected) Then Redirected = %True: _
                                       SendMessage hWnd1, CbMsg, CbWparam, CbLparam: Redirected = %False
                  End Select
                  Function = CallWindowProc(OldProc2, CbHndl, CbMsg, CbWparam, CbLparam)
               End Function
            
            
               CallBack Function DlgProc
                  Select Case CbMsg
                     Case %WM_INITDIALOG
                        Dim s As String, i As Long
            
                        s = "": For i = 1 To 100: s = s + "TextBox 1 Line" + Str$(i) + $CRLF: Next
                        Control Add TextBox, CbHndl, %ID_TEXT1, s, 10, 10, 100, 180, _
                           %ES_AUTOHSCROLL Or %ES_MULTILINE Or %ES_WANTRETURN Or %WS_VSCROLL, %WS_EX_CLIENTEDGE
                           
                        s = "": For i = 1 To 100: s = s + "TextBox 2 Line" + Str$(i) + $CRLF: Next
                        Control Add TextBox, CbHndl, %ID_TEXT2, s, 130, 10, 260, 180, _
                           %ES_AUTOHSCROLL Or %ES_MULTILINE Or %ES_WANTRETURN Or %WS_VSCROLL, %WS_EX_CLIENTEDGE
            
                        hWnd1 = GetDlgItem(CbHndl, %ID_TEXT1): OldProc1 = SetWindowLong (hWnd1, %GWL_WNDPROC, CodePtr(WndProc1))
                        hWnd2 = GetDlgItem(CbHndl, %ID_TEXT2): OldProc2 = SetWindowLong (hWnd2, %GWL_WNDPROC, CodePtr(WndProc2))
            
                        SetFocus hWnd2: SetFocus hWnd1
                  End Select
               End Function
            
               Function PbMain
            
                  Local hDlg As Long
                  Dialog New 0,"Scroll Bar",,, 400, 200, %WS_CAPTION Or %WS_SYSMENU Or %WS_CLIPCHILDREN Or %WS_CLIPSIBLINGS To hdlg
                  Dialog Show Modal hdlg Call DlgProc
            
               End Function
            ------------------
            E-MAIL: [email protected]

            Comment


            • #7
              Jules,
              Thank you. You have helped to produce progress. Although
              thumb-(slider box)-tracking is no longer effective (!!) in the
              left window, vertical scrolling of that window produces parallel
              scrolling in the right window. This is fine. The effect is
              produced by SubClassProc1 which works fine in isolation i.e.
              when the key statement: “CALL SendMessage (hListView1, %WM_VSCROLL, wParam&,0)”
              in SubClassProc2 is commented away. However, when you include
              this statement (by taking the comment single quote away) fatal
              errors occur when vertical scrolling is attempted in either
              window!!! Thus a serious conflict is produced.

              Semen,
              Thank you very much. Your solution is indeed very elegant and
              efficient and solves the conflict. I will implement your principle
              in my program and will post the result when it is ready. Thank you.

              Best regards and Happy New Year to both of you and to the fine
              PowerBasic Forum,
              Erik

              ------------------


              [This message has been edited by Erik Christensen (edited December 31, 2000).]

              Comment


              • #8
                Semen, great work!

                Erick,

                I used slightly same aproach, but no global used...
                Code:
                If lParam& = 0 Then 
                    CALL PostMessage(hListView2,%WM_VSCROLL,wParam&,100)
                End If
                Only takes action if message came from itself. Sending a value
                with lParam to other control behaves like Semen's solution. I used
                PostMessage so SB_ThumbTrack works correctly.

                Still more problems to come when using the Keyboard to scroll using the
                up/down arrows. Also, to keep the highlight bar syncronized.

                I'm off, Happy New Year!
                Best regards,
                Jules

                Best regards
                Jules
                www.rpmarchildon.com

                Comment


                • #9
                  Semen, Jules, Borje

                  Semen’s solution works fine except when using arrow up or down.
                  I enclose a revised version of Semen’s program without subclassing
                  but relying entirely %EM_GETFIRSTVISIBLELINE and %EM_LINESCROLL
                  in analogy with the original idea of Borje. This works satisfactory
                  in all aspects (including all keyboard and mouse input) when using
                  CASE ELSE. Not an entirely satisfactory (or even illegal?) solution.
                  If you could identify the relevant control messages to be used, this
                  case problem could be solved. Please let me know your opinion
                  about this perhaps wild approach?

                  Regards,
                  Erik
                  Code:
                     #COMPILE EXE
                     #DIM ALL
                     #REGISTER NONE
                     #INCLUDE "WIN32API.INC"
                  
                     %ID_TEXT1 = 101
                     %ID_TEXT2 = 102
                  
                     GLOBAL hWnd1 AS LONG, hWnd2 AS LONG, OldProc1 AS LONG, OldProc2 AS LONG, Redirected AS LONG
                     GLOBAL TopVisLine1 AS LONG, TopVisLine2 AS LONG, PrevTopVisLine12 AS LONG, Dif AS LONG
                     GLOBAL Result AS LONG
                  
                     CALLBACK FUNCTION DlgProc
                        LOCAL cm AS LONG
                        SELECT CASE CBMSG
                           CASE %WM_INITDIALOG
                              DIM s AS STRING, i AS LONG
                              s = "": FOR i = 1 TO 100: s = s + "TextBox 1 Line" + STR$(i) + $CRLF: NEXT
                              CONTROL ADD TEXTBOX, CBHNDL, %ID_TEXT1, s, 10, 10, 100, 180, _
                                 %ES_AUTOHSCROLL OR %ES_MULTILINE OR %ES_WANTRETURN OR %WS_VSCROLL, %WS_EX_CLIENTEDGE
                  
                              s = "": FOR i = 1 TO 100: s = s + "TextBox 2 Line" + STR$(i) + $CRLF: NEXT
                              CONTROL ADD TEXTBOX, CBHNDL, %ID_TEXT2, s, 130, 10, 260, 180, _
                                 %ES_AUTOHSCROLL OR %ES_MULTILINE OR %ES_WANTRETURN OR %WS_VSCROLL, %WS_EX_CLIENTEDGE
                              hWnd1 = GetDlgItem(CBHNDL, %ID_TEXT1)
                              hWnd2 = GetDlgItem(CBHNDL, %ID_TEXT2)
                              SetFocus hWnd2: SetFocus hWnd1
                  
                           'this CASE ELSE is perhaps too wild. Can it be narrowed a bit?
                           CASE ELSE '%WM_COMMAND 'OR %WM_VSCROLL OR %EM_LINESCROLL OR %EM_SCROLL
                              TopVisLine1 = SendMessage(hWnd1, %EM_GETFIRSTVISIBLELINE, 0, 0)
                              TopVisLine2 = SendMessage(hWnd2, %EM_GETFIRSTVISIBLELINE, 0, 0)
                              IF TopVisLine1 <> TopVisLine2 THEN
                                 IF PrevTopVisLine12 = TopVisLine1 THEN ' TopVisLine2 changed
                                    Dif = TopVisLine2 - PrevTopVisLine12
                                    PrevTopVisLine12 = TopVisLine2
                                    Result = SendMessage(hWnd1, %EM_LINESCROLL, 0, Dif)
                                    TopVisLine1 = TopVisLine2
                                 ELSE                                   ' TopVisLine1 changed
                                    Dif = TopVisLine1 - PrevTopVisLine12
                                    PrevTopVisLine12 = TopVisLine1
                                    Result = SendMessage(hWnd2, %EM_LINESCROLL, 0, Dif)
                                    TopVisLine2 = TopVisLine1
                                 END IF
                              END IF
                        END SELECT
                     END FUNCTION
                  
                     FUNCTION PBMAIN
                        LOCAL hDlg AS LONG
                        DIALOG NEW 0,"Scroll Bar",,, 400, 200, %WS_CAPTION OR %WS_SYSMENU OR %WS_CLIPCHILDREN OR %WS_CLIPSIBLINGS TO hdlg
                        DIALOG SHOW MODAL hdlg CALL DlgProc
                     END FUNCTION


                  ------------------

                  Comment


                  • #10
                    Semen, Jules, Borje,

                    This is the ListView parallel scrolling version using
                    %LVM_GETTOPINDEX and %LVM_SCROLL as the sole means of scrolling
                    (no subclassing). It seems to be working except for some occational
                    blank spots (probably an updating problem).
                    Even though the %LVS_REPORT style is specified, this seems to be
                    overruled by some of the other styles used. Therefore the scrolling
                    unit is pixels. The program needs to be improved by an explicit
                    determination of the number of pixels per line (vertically).
                    In my system this number is 9 but it could be different in other
                    systems. Your further comments for improvement are most welcome.
                    Thanks again for your inspiration and guidance.

                    Regards,
                    Erik
                    Code:
                    ' "Parallel" scrolling.
                    '======================
                    'Listview example. Inspired by code provided to the PowerBasic FORUM
                    'by Peter Redei, David L Morris and Lance Edmonds
                    '
                    'Finished with the help in the PowerBasic FORUM
                    'from Semen Matusovski, Jules Marchildon and Borje Hagsten.
                    '
                    'Erik Christensen, Copenhagen, Denmark.   [email protected]
                    '
                    ' ** Eliminate unnecessary macros
                    %NOANIMATE = 1
                    %NODRAGLIST = 1
                    %NOHEADER = 1
                    %NOIMAGELIST = 1
                    '%NOLISTVIEW = 1
                    %NOTABCONTROL = 1
                    %NOTRACKBAR = 1
                    %NOTREEVIEW = 1
                    %NOUPDOWN = 1
                    #COMPILE EXE
                    #INCLUDE "WIN32API.INC"
                    #INCLUDE "COMMCTRL.INC"
                    
                    ' some supplementary listview styles that you may not have in your
                    ' commctrl.inc file
                    ' they are not all used in this program
                    %LVM_FIRST = &H1000
                    %LVM_SETEXTENDEDLISTVIEWSTYLE = %LVM_FIRST + 54
                    %LVM_GETEXTENDEDLISTVIEWSTYLE = %LVM_FIRST + 55
                    %LVS_EX_FULLROWSELECT = &H20
                    %LVS_EX_GRIDLINES = &H1
                    %LVS_EX_CHECKBOXES = &H4
                    %LVS_EX_TRACKSELECT = &H8
                    %LVS_EX_HEADERDRAGDROP = &H10
                    %LVM_GETITEMSTATE = (%LVM_FIRST + 44)
                    %LVM_GETITEMTEXT = (%LVM_FIRST + 45)
                    %LVIS_STATEIMAGEMASK = &HF000
                    %LVBKIF_SOURCE_NONE = &H0
                    %LVBKIF_SOURCE_HBITMAP = &H1
                    %LVBKIF_SOURCE_URL = &H2
                    %LVBKIF_SOURCE_MASK = &H3
                    %LVBKIF_STYLE_NORMAL = &H0
                    %LVBKIF_STYLE_TILE = &H10
                    %LVBKIF_STYLE_MASK = &H10
                    %LVM_SETBKIMAGEA = %LVM_FIRST + 68
                    %LVM_SETBKIMAGE = %LVM_SETBKIMAGEA
                    %LVM_SETTEXTBKCOLOR = %LVM_FIRST + 38
                    %LVM_SETBKIMAGEA = %LVM_FIRST + 68
                    %LVM_SETBKIMAGE = %LVM_SETBKIMAGEA
                    %CLR_NONE = &HFFFFFFFF
                    
                    %IDC_TEXT =105
                    %IDLISTVIEW1 = 101
                    %IDLISTVIEW2 = 102
                    
                    GLOBAL hDlg AS LONG
                    GLOBAL hListView AS LONG
                    GLOBAL hListView1 AS LONG
                    GLOBAL hListView2 AS LONG
                    GLOBAL Redirected AS LONG
                    GLOBAL fnOld1 AS LONG
                    GLOBAL fnOld2 AS LONG
                    GLOBAL TopVisLine1 AS INTEGER, TopVisLine2 AS INTEGER, PrevTopVisLine12 AS INTEGER, Dif AS INTEGER
                    GLOBAL Result AS LONG
                    
                    DECLARE CALLBACK FUNCTION DlgCallBack
                    
                    TYPE dField
                      fName AS ASCIIZ * 80
                      SIZE AS INTEGER
                      Alignment AS INTEGER
                    END TYPE
                    
                    TYPE ListData
                      Columns AS INTEGER
                      Fields(0 TO 80) AS dField
                    END TYPE
                    
                    SUB AppendListView (hList AS LONG, Rec() AS STRING )
                      DIM z AS INTEGER
                      DIM iStatus AS INTEGER
                      DIM szStr AS ASCIIZ * 300
                      DIM lvi AS LV_ITEM
                      LOCAL x AS LONG
                      'this will be the next record
                      lvi.iItem = ListView_GetItemCount(hList)
                      lvi.mask = %LVIF_TEXT
                      lvi.stateMask = %LVIS_FOCUSED '%LVIS_SELECTED
                      lvi.pszText = VARPTR(szStr)
                      FOR z = 0 TO UBOUND(Rec)
                        szStr = Rec(z)
                        lvi.iSubItem = z
                        lvi.lParam = lvi.iItem
                        IF z = 0 THEN
                          lvi.mask = %LVIF_TEXT OR %LVIF_PARAM OR %LVIF_STATE
                          iStatus = ListView_InsertItem (hList, lvi)
                        ELSE
                          lvi.mask = %LVIF_TEXT
                          iStatus = ListView_SetItem (hList, lvi)
                        END IF
                      NEXT
                    END SUB
                    
                    FUNCTION PBMAIN () AS LONG
                      $REGISTER NONE
                      LOCAL result AS LONG, zText AS ASCIIZ * 255
                      LOCAL icc AS INIT_COMMON_CONTROLSEX
                      LOCAL LVC AS LV_COLUMN, i AS LONG,r AS LONG, c AS LONG, lStyle AS LONG
                      LOCAL LVI AS LV_ITEM
                    
                      %NumCols = 21:%NumRows = 50
                      DIM Rec(%NumCols)AS STRING
                      icc.dwICC = %ICC_DATE_CLASSES OR %ICC_BAR_CLASSES OR %ICC_LISTVIEW_CLASSES
                      icc.dwSize = SIZEOF(icc)
                    
                      InitCommonControlsEx icc
                      ' ** Create a new dialog template
                      DIALOG NEW 0, "ListView parallel scrolling", ,, 342, 204, _
                         %WS_POPUP OR %DS_MODALFRAME OR %WS_CAPTION OR %WS_MINIMIZEBOX OR _
                         %WS_SYSMENU OR %WS_MAXIMIZEBOX OR %DS_CENTER, 0 TO hDlg
                      ' ** Add controls to it
                      CONTROL ADD "SysListView32", hDlg, %IDLISTVIEW1,"",4,5,57,194, _
                         %WS_border OR %WS_Child OR %WS_visible OR _
                         %LVS_Report OR %LVS_SHOWSELALWAYS, _
                         %WS_EX_CLIENTEDGE
                    
                      CONTROL ADD "SysListView32", hDlg, %IDLISTVIEW2,"",58,5,280,194, _
                         %WS_border OR %WS_Child OR %WS_visible OR _
                         %LVS_Report OR %LVS_SHOWSELALWAYS, _
                         %WS_EX_CLIENTEDGE
                    
                      CONTROL HANDLE hDlg,%IDLISTVIEW1 TO hListView
                      lStyle = SendMessage(hListView, _
                               %LVM_GETEXTENDEDLISTVIEWSTYLE, 0, 0)
                      lStyle = lStyle OR %LVS_EX_GRIDLINES OR %LVS_REPORT ' OR %LVS_EX_FULLROWSELECT OR %LVS_EX_TRACKSELECT
                      ' even though the %LVS_REPORT style is specified, the scrolling unit used is pixels
                      ' other styles may overrule %LVS_REPORT
                    
                      CALL SendMessage(hListView, %LVM_SETEXTENDEDLISTVIEWSTYLE, _
                           0, BYVAL lStyle)
                    
                      CONTROL HANDLE hDlg,%IDLISTVIEW2 TO hListView
                      lStyle = SendMessage(hListView, _
                               %LVM_GETEXTENDEDLISTVIEWSTYLE, 0, 0)
                      lStyle = lStyle OR %LVS_EX_GRIDLINES OR %LVS_REPORT ' OR %LVS_EX_FULLROWSELECT OR %LVS_EX_TRACKSELECT
                      ' even though the %LVS_REPORT style is specified, the scrolling unit used is pixels
                      ' other styles may overrule %LVS_REPORT
                    
                      CALL SendMessage(hListView, %LVM_SETEXTENDEDLISTVIEWSTYLE, _
                           0, BYVAL lStyle)
                    
                      lvC.mask = %LVCF_FMT OR %LVCF_WIDTH OR %LVCF_TEXT OR %LVCF_SUBITEM
                      lvC.fmt = %LVCFMT_CENTER '%LVCFMT_LEFT '%LVCFMT_RIGHT
                      lvC.cx = 90
                      LVC.cchTextMax = 255
                    
                      zText = "Identification "  ' text for first (identification) column
                      LVC.pszText = VARPTR(zText)
                      CONTROL SEND hDlg,%IDLISTVIEW1,%LVM_INSERTCOLUMN, 1, VARPTR(lvc) ' to ListView 1
                      CONTROL SEND hDlg,%IDLISTVIEW2,%LVM_INSERTCOLUMN, 1, VARPTR(lvc) ' to ListView 2
                    
                      ' fill ListView 1 with remaining data
                      FOR c = 2 TO %NumCols
                        zText = "Variable " + FORMAT$(c - 1) ' column variable labels 1-20
                        LVC.pszText = VARPTR(zText)
                        CONTROL SEND hDlg,%IDLISTVIEW1,%LVM_INSERTCOLUMN, c, VARPTR(lvc)
                      NEXT
                      CONTROL HANDLE hDlg,%IDLISTVIEW1 TO hListView
                      RANDOMIZE 1.5
                      FOR r = 1 TO %NumRows
                        rec(0) = "Individual " + FORMAT$(r)  ' data for idendification column
                        FOR c = 2 TO %NumCols
                          rec(c-1) = FORMAT$(RND(100,999))   ' data for variable column 1-20
                        NEXT c
                        AppendListView hListView, Rec()
                      NEXT r
                    
                      ' fill ListView 2 with remaining data
                      FOR c = 2 TO %NumCols
                        zText = "Variable " + FORMAT$(c - 1) ' column variable labels 1-20
                        LVC.pszText = VARPTR(zText)
                        CONTROL SEND hDlg,%IDLISTVIEW2,%LVM_INSERTCOLUMN, c, VARPTR(lvc)
                      NEXT
                      CONTROL HANDLE hDlg,%IDLISTVIEW2 TO hListView
                      RANDOMIZE 1.5
                      FOR r = 1 TO %NumRows
                        rec(0) = "Individual " + FORMAT$(r)  ' data for idendification column
                        FOR c = 2 TO %NumCols
                          rec(c-1) = FORMAT$(RND(100,999))   ' data for variable column 1-20
                        NEXT c
                        AppendListView hListView, Rec()
                      NEXT r
                    
                      CONTROL HANDLE hDlg,%IDLISTVIEW1 TO hListView1
                      CONTROL HANDLE hDlg,%IDLISTVIEW2 TO hListView2
                    
                      ' ** Display the dialog
                      DIALOG SHOW MODAL hDlg CALL DlgCallBack
                    END FUNCTION
                    
                    CALLBACK FUNCTION DlgCallBack
                      SELECT CASE CBMSG
                         CASE %WM_INITDIALOG
                         CASE %WM_DESTROY
                         CASE ELSE
                                TopVisLine1 = SendMessage(hListView1, %LVM_GETTOPINDEX, 0, 0)
                                TopVisLine2 = SendMessage(hListView2, %LVM_GETTOPINDEX, 0, 0)
                                IF TopVisLine1 <> TopVisLine2 THEN
                                   IF PrevTopVisLine12 = TopVisLine1 THEN ' TopVisLine2 changed
                    
                                      Dif = (TopVisLine2 - PrevTopVisLine12)*9 ' 9=PIXELS PER LINE
                                                                               ' SHOULD BE FOUND EXPLICITLY
                                                                               ' BY SOME METHOD
                                      PrevTopVisLine12 = TopVisLine2
                                      Result = SendMessage(hListView1, %LVM_SCROLL, 0, Dif)
                                      TopVisLine1 = TopVisLine2
                                   ELSE                                   ' TopVisLine1 changed
                    
                                      Dif = (TopVisLine1 - PrevTopVisLine12)*9 ' 9=PIXELS PER LINE
                                                                               ' SHOULD BE FOUND EXPLICITLY
                                                                               ' BY SOME METHOD
                                      PrevTopVisLine12 = TopVisLine1
                                      Result = SendMessage(hListView2, %LVM_SCROLL, 0, Dif)
                                      TopVisLine2 = TopVisLine1
                                   END IF
                                END IF
                      END SELECT
                    END FUNCTION



                    ------------------

                    Comment


                    • #11
                      Erik,

                      I favour your first test using the edit controls. The second still
                      has a bouncy thumbtrack. To cure the repaint problem use the PostMessage
                      instead of the SendMessage call.

                      Regards,
                      Jules
                      Best regards
                      Jules
                      www.rpmarchildon.com

                      Comment


                      • #12
                        Erik --
                        If you will use Borje's suggestion (unlike it possible to redirect arrows too), I hope that it will be enough to test after %WM_NOTIFY only.
                        I also corrected a method to reset a row (on my PC under Win2000 it works).
                        Code:
                        CallBack Function DlgCallBack
                          Dim rc As RECT
                          Select Case CbMsg
                             Case %WM_NOTIFY
                                If LoWrd(CbWparam) = %IDLISTVIEW1 Or LoWrd(CbWparam) = %IDLISTVIEW2 Then _
                                   PostMessage CbHndl, %WM_USER + 401, 0, 0
                             Case %WM_USER + 401
                                TopVisLine1 = SendMessage(hListView1, %LVM_GETTOPINDEX, 0, 0)
                                TopVisLine2 = SendMessage(hListView2, %LVM_GETTOPINDEX, 0, 0)
                                If TopVisLine1 <> TopVisLine2 Then
                                   If PrevTopVisLine12 = TopVisLine1 Then ' TopVisLine2 changed
                                      SendMessage(hListView1, %LVM_GETITEMPOSITION, TopVisLine2, VarPtr(rc)
                                      Dif = rc.nTop
                                      SendMessage(hListView1, %LVM_GETITEMPOSITION, PrevTopVisLine12, VarPtr(rc)
                                      Dif = Dif - rc.nTop
                                      PrevTopVisLine12 = TopVisLine2
                                      Result = SendMessage(hListView1, %LVM_SCROLL, 0, Dif)
                                      TopVisLine1 = TopVisLine2
                                   Else                                   ' TopVisLine1 changed
                                      SendMessage(hListView2, %LVM_GETITEMPOSITION, TopVisLine1, VarPtr(rc)
                                      Dif = rc.nTop
                                      SendMessage(hListView2, %LVM_GETITEMPOSITION, PrevTopVisLine12, VarPtr(rc)
                                      Dif = Dif - rc.nTop
                                      PrevTopVisLine12 = TopVisLine1
                                      Result = SendMessage(hListView2, %LVM_SCROLL, 0, Dif)
                                      TopVisLine2 = TopVisLine1
                                    End If
                                 End If
                          End Select
                        End Function

                        ------------------
                        E-MAIL: [email protected]

                        Comment


                        • #13
                          Erik,

                          I am interested to know why you want to use two listviews in this
                          manor in the first place?.

                          Regards,
                          Jules
                          Best regards
                          Jules
                          www.rpmarchildon.com

                          Comment


                          • #14

                            Semen,
                            You have certainly improved the callback function considerably
                            and thereby also remedied the bouncing thumbtrack and the pixels
                            per line problem. Thank you! The performance is improving markedly.
                            Up and down arrows work fine including moving the current cell.
                            The horizontal arrows move the current window, but not the
                            current cell which is locked in the first column. This could
                            perhaps be explained by the styles used. Mouse function seems
                            complete. You can change between windows using the mouse and TAB
                            does also work if you include the %WS_TABSTOP style in the
                            definition of the ListView controls. HOME an END keys move to
                            the top and bottom, respectively, maintaining the same visible
                            column(s) in both windows, – not to the first or last column,
                            respectively, as might be expected – possibly also a style
                            problem. I need to study ListView (among other things!) in more
                            detail, but where is the best source?.

                            Jules,
                            I have tried to use PostMessage, but the windows go wild on my
                            system when keeping the up and down arrows pressed. The SendMessage
                            seems to work well enough in Semen’s callback function. Why I want
                            to use ListView: see my initial posting on this subject. For some
                            purposes I want to produce spreadsheet like screen output.

                            Best Regards,

                            Erik



                            ------------------

                            Comment


                            • #15
                              Erik,

                              ListView control info...

                              http://www.mvps.org/vbnet/_vti_bin/s...ain/index.html

                              http://zeus.eed.usv.ro/misc/doc/prog...tview_toc.html

                              Regards,
                              Jules

                              [This message has been edited by Jules Marchildon (edited January 03, 2001).]
                              Best regards
                              Jules
                              www.rpmarchildon.com

                              Comment


                              • #16
                                Thanks Jules,
                                I will study these links.
                                Regards, Erik

                                ------------------


                                [This message has been edited by Erik Christensen (edited January 04, 2001).]

                                Comment


                                • #17
                                  in the code referred to below you can see a new technique for
                                  parallel scrolling of listview controls. this technique utilizes
                                  the %lvm_getitemrect message, which gives the coordinates of a
                                  certain listview item in relation to the current view port of the
                                  control. very handy.
                                  http://www.powerbasic.com/support/pb...ad.php?t=24702

                                  ------------------

                                  Comment


                                  • #18
                                    I forgot to mention that you may also use the %LVM_GETSUBITEMRECT
                                    message to scroll to a specific subitem if necessary.
                                    You should do it this way:
                                    Code:
                                        rc.nLeft = %LVIR_BOUNDS
                                        rc.nTop = iSubItem
                                        SendMessage hwnd, %LVM_GETSUBITEMRECT, iItem, VARPTR(rc)
                                    and then apply the %LVM_SCROLL message to do the scrolling.

                                    The ListView_GetSubItemRect macro in the COMMCTRL.INC is not working.


                                    ------------------




                                    [This message has been edited by Erik Christensen (edited August 14, 2005).]

                                    Comment


                                    • #19
                                      win/98
                                      pb/win 7.02

                                      compile/run "as is"

                                      click on row 5 (the one-based row 5, actual row 4) in upper left window
                                      full row becomes selected
                                      a couple of up and down scrolls using the v-scroll bar. ok, window in upper right scrolls along with it.

                                      take mouse to h-scroll bar at bottom of upper left window. do a couple of h-scrolls with mouse, back and forth, all the way to the end and back. all ok.

                                      put mouse on h-scroll bar of upper right window, drag thumb to right...

                                      stack fault gpf.

                                      otherwise looked nice.

                                      [later]
                                      i thought i'd look for you but...

                                      select row in upper left window.

                                      do nothing else.

                                      click on any other window. stack fault gpf.

                                      i think you are missing an edit somewhere.

                                      this code here is suspect...
                                      Code:
                                              case %wm_notify
                                                  if lowrd(cbwparam) = %idc_syslistview32_1 then
                                                      if timer - prevtime > 0.15 then setfocus h1
                                                      prevtime = timer : postmessage cbhndl, %wm_user + 401, 0, 0
                                                  end if
                                      on wm_notify, cwbwparam does not necessarily tell you what you want to know:
                                      idctrl identifier of the common control sending the message. this identifier is not guaranteed to be unique. an application should use the hwndfrom or idfrom member of the nmhdr structure (passed as the lparam parameter) to identify the control
                                      and without getting a whole lot deeper into it, you sure you want <u>every</u> wm_notify to do this? maybe you should pick off nmhdr.code to isolate which notifications you really want to process.

                                      mcm



                                      [this message has been edited by michael mattias (edited august 14, 2005).]
                                      Michael Mattias
                                      Tal Systems (retired)
                                      Port Washington WI USA
                                      [email protected]
                                      http://www.talsystems.com

                                      Comment


                                      • #20
                                        Thanks Michael for your feed-back. Sorry to hear about the
                                        problem. I have Windows XP and PBWIN80 and I cannot reproduce
                                        your findings on my system. Do you have any suggestion about
                                        how to improve the code to solve the problem you describe?
                                        Is it a matter of how big the stack is? Should the stack be
                                        increased or should the problem be solved another way. Can you
                                        or anyone suggest how to proceed. Thanks a lot in advance.

                                        Later: I will look more closely on the point you describe to see
                                        if I can find a solution. Thanks.

                                        ------------------


                                        [This message has been edited by Erik Christensen (edited August 14, 2005).]

                                        Comment

                                        Working...
                                        X