Here is the solution from an old source code. I think it will work for you.
Code: Select all
#include <hmg.ch>
Function Main
private aArray := { { '001', 'One', 'January' },;
{ '002', 'Two', 'February' },;
{ '003', 'Three', 'March' },;
{ '004', 'Four', 'April' },;
{ '005', 'Five', 'May' },;
{ '006', 'Six', 'June' },;
{ '007', 'Six', 'June' },;
{ '008', 'Six', 'June' },;
{ '009', 'Six', 'June' },;
{ '010', 'Six', 'June' },;
{ '011', 'Six', 'June' },;
{ '012', 'Six', 'June' },;
{ '013', 'Six', 'June' },;
{ '014', 'Six', 'June' },;
{ '015', 'Six', 'June' },;
{ '016', 'Six', 'June' },;
{ '017', 'Six', 'June' },;
{ '018', 'Six', 'June' },;
{ '019', 'Six', 'June' },;
{ '020', 'Six', 'June' },;
{ '021', 'Six', 'June' },;
{ '022', 'Six', 'June' },;
{ '007', 'Seven', 'July' },;
{ '008', 'Eight', 'August' },;
{ '009', 'Nine', 'September' },;
{ '010', 'Ten', 'October' },;
{ '011', 'Eleven', 'November' },;
{ '012', 'Twelve', 'December' } }
define window vgrid at 0, 0 width 500 height 400 main
define textbox tbox1
row 10
col 10
width 100
end textbox
define grid vgrid1
row 40
col 10
width 350
height 100
widths { 60, 100, 150 }
virtual .t.
items aArray
onQueryData getvgriddata()
onheadclick { { || headclick1() }, { || headclick2() }, { || headclick3() } }
headers { 'Number', 'Name', 'Month' }
end grid
define button addsomeitems
row 150
col 10
caption 'Add Items'
action AddItemToVGrid()
end button
define button setvalue
row 150
col 200
caption 'Set Value'
action setnewvalue()
end button
end window
vgrid.vgrid1.value := 1
vgrid.center
vgrid.activate
Return
function getvgriddata
local i := this.queryrowindex
local j := this.querycolindex
this.querydata := aArray[ i, j ]
return nil
function headclick1
vgrid.vgrid1.visible := .f.
asort( aArray, , , { |x, y| x[ 1 ] < y[ 1 ] } )
vgrid.vgrid1.visible := .t.
return nil
function headclick2
vgrid.vgrid1.visible := .f.
asort( aArray, , , { |x, y| x[ 2 ] < y[ 2 ] } )
vgrid.vgrid1.visible := .t.
return nil
function headclick3
vgrid.vgrid1.visible := .f.
asort( aArray, , , { |x, y| x[ 3 ] < y[ 3 ] } )
vgrid.vgrid1.visible := .t.
return nil
function AddItemToVGrid()
vgrid.vgrid1.visible := .f.
aadd( aArray, { '0' + alltrim( str( len( aArray ) + 1 ) ), 'New Item' + str( len( aArray ) + 1 ), 'New Item' + str( len( aArray ) + 1 ) } )
vgrid.vgrid1.itemcount := len( aArray )
vgrid.vgrid1.visible := .t.
return nil
function setnewvalue
vgrid.vgrid1.visible := .f.
vgrid.vgrid1.value := 14
GridMakeVisible( 'vgrid', 'vgrid1', 14 )
GridMakeFirstItem( 'vgrid', 'vgrid1', 14 )
vgrid.vgrid1.visible := .t.
return nil
function GridMakeFirstItem( cParent, cControl, nValue )
local nHandle := GetControlHandle( cControl, cParent )
GridMakeFirst( nHandle, nValue )
return nil
function GridMakeVisible( cParent, cControl, nValue )
local nHandle := GetControlHandle( cControl, cParent )
GridEnsureVisible( nHandle, nValue )
return nil
#pragma BEGINDUMP
#include <windows.h>
#include <commctrl.h>
#include "hbapi.h"
HB_FUNC ( GRIDMAKEFIRST )
{
HWND hWnd1;
int value1,scroll1,top1;
POINT pt1,pt2;
hWnd1 = (HWND) hb_parnl (1);
value1 = (int) hb_parni (2);
top1 = SendMessage((HWND) hWnd1,LVM_GETTOPINDEX,(WPARAM) (int) 0,(LPARAM) (int) 0);
top1++;
SendMessage((HWND) hWnd1,LVM_GETITEMPOSITION,(WPARAM) (int) top1,(LPARAM) &pt1);
SendMessage((HWND) hWnd1,LVM_GETITEMPOSITION,(WPARAM) (int) value1,(LPARAM) &pt2);
scroll1 = pt2.y - pt1.y;
SendMessage((HWND) hWnd1,LVM_SCROLL,(WPARAM)(int) 0,(LPARAM)(int) scroll1);
}
HB_FUNC ( GRIDENSUREVISIBLE )
{
HWND hWnd1;
int value1;
hWnd1 = (HWND) hb_parnl (1);
value1 = (int) hb_parni (2);
value1--;
SendMessage((HWND) hWnd1,LVM_ENSUREVISIBLE,(WPARAM) (int) value1,(LPARAM) FALSE);
}
#pragma ENDDUMP
It is working well for ordinary grid (by commenting out line nos 46 and 48). For virtual grids, at least the item is ensured to be visible if not be the first item.