GRID Scrollbar
Moderator: Rathinagiri
- serge_girard
- Posts: 3166
- Joined: Sun Nov 25, 2012 2:44 pm
- DBs Used: 1 MySQL - MariaDB
2 DBF - Location: Belgium
- Contact:
GRID Scrollbar
Hello,
Is it possible to getproperterty of the scrollbars of a grid?
I have 2 grids and what I want is scrolling in one grid and the second has to 'follow' the same 'movements' as the first grid.
EG: So when I scroll down on the left grid the right grid automatically scrolls with it, keeping the same rows/cols.
Can't find any samples or demo's...
Thanks,
Serge
Is it possible to getproperterty of the scrollbars of a grid?
I have 2 grids and what I want is scrolling in one grid and the second has to 'follow' the same 'movements' as the first grid.
EG: So when I scroll down on the left grid the right grid automatically scrolls with it, keeping the same rows/cols.
Can't find any samples or demo's...
Thanks,
Serge
There's nothing you can do that can't be done...
- Pablo César
- Posts: 4059
- Joined: Wed Sep 08, 2010 1:18 pm
- Location: Curitiba - Brasil
GRID Scrollbar
Hi Serge !
I have nothing developed about you want but I have important tips.
I have not tested and I do not put it in practice following functions/commands, but probably you would have a good start for yourself starting.
At C:\hmg.3.4.0\SOURCE\h_windows.prg you will find this:
Sp := GetScrollPos ( GetFormHandle('SPLITCHILD_1') , SB_HORZ )
Sp := GetScrollPos ( GetFormHandle('SPLITCHILD_1') , SB_VERT )
_HMG_PRINTER_SETVSCROLLVALUE( nWindowHandle , nNewScrollBarPos )
_HMG_PRINTER_SETHSCROLLVALUE( nWindowHandle , nNewScrollBarPos )
And at C:\hmg.3.4.0\SOURCE\h_controlmisc.prg this:
GetVScrollBarWidth()
GetHScrollBarHeight()
At C:\hmg.3.4.0\SOURCE\h_grid.prg you will find this:
ListView_Scroll( _HMG_SYSDATA [3] , xs + xd , 0 )
And also this:
#define SB_HORZ 0
#define SB_VERT 1
#define SB_CTL 2
#define SB_BOTH 3
k := GetScrollRangeMax ( GetControlHandle(cControlName,cParentForm), SB_HORZ )
SETSCROLLRANGE ( GetControlHandle(cControlName,cParentForm), SB_HORZ, 0, k + LISTVIEW_GETCOLUMNWIDTH (GetControlHandle (cControlName, cParentForm), nColIndex-1), .T. )
SHOWSCROLLBAR (GetControlHandle(cControlName,cParentForm), SB_HORZ, .T.)
You also need to check this events at forms:
ON SCROLLUP Your_Function()
ON SCROLLDOWN Your_Function()
ON SCROLLLEFT Your_Function()
ON SCROLLRIGHT Your_Function()
ON HSCROLLBOX Your_Function()
ON VSCROLLBOX Your_Function()
I hope you get a better idea how to start and please share with us any result about it !
Good lucky !
I have nothing developed about you want but I have important tips.
I have not tested and I do not put it in practice following functions/commands, but probably you would have a good start for yourself starting.
At C:\hmg.3.4.0\SOURCE\h_windows.prg you will find this:
Sp := GetScrollPos ( GetFormHandle('SPLITCHILD_1') , SB_HORZ )
Sp := GetScrollPos ( GetFormHandle('SPLITCHILD_1') , SB_VERT )
_HMG_PRINTER_SETVSCROLLVALUE( nWindowHandle , nNewScrollBarPos )
_HMG_PRINTER_SETHSCROLLVALUE( nWindowHandle , nNewScrollBarPos )
And at C:\hmg.3.4.0\SOURCE\h_controlmisc.prg this:
GetVScrollBarWidth()
GetHScrollBarHeight()
At C:\hmg.3.4.0\SOURCE\h_grid.prg you will find this:
ListView_Scroll( _HMG_SYSDATA [3] , xs + xd , 0 )
And also this:
#define SB_HORZ 0
#define SB_VERT 1
#define SB_CTL 2
#define SB_BOTH 3
k := GetScrollRangeMax ( GetControlHandle(cControlName,cParentForm), SB_HORZ )
SETSCROLLRANGE ( GetControlHandle(cControlName,cParentForm), SB_HORZ, 0, k + LISTVIEW_GETCOLUMNWIDTH (GetControlHandle (cControlName, cParentForm), nColIndex-1), .T. )
SHOWSCROLLBAR (GetControlHandle(cControlName,cParentForm), SB_HORZ, .T.)
You also need to check this events at forms:
ON SCROLLUP Your_Function()
ON SCROLLDOWN Your_Function()
ON SCROLLLEFT Your_Function()
ON SCROLLRIGHT Your_Function()
ON HSCROLLBOX Your_Function()
ON VSCROLLBOX Your_Function()
I hope you get a better idea how to start and please share with us any result about it !
Good lucky !
HMGing a better world
"Matter tells space how to curve, space tells matter how to move."
Albert Einstein
"Matter tells space how to curve, space tells matter how to move."
Albert Einstein
- Amarante
- Posts: 182
- Joined: Fri Apr 27, 2012 9:44 pm
- DBs Used: DBF, MySQL, MariaDB, SQLite, PostgreSQL
- Location: Araruama-RJ, Brazil
Re: GRID Scrollbar
Pablo was faster;)
Thanks for the tips.
I went far post less information than he.
I'm doing some tests to avoid using the CELLNavegation, but have not had success.
Example to change the position of the bar:
* _HMG_SYSDATA [ 345 ] -> ScrollStep
#define SB_HORZ 0
hwnd := GetControlHandle( cControlName, cParentForm )
NewHPos := GetScrollPos( hwnd , SB_HORZ ) + 100
SetScrollPos ( hwnd , SB_HORZ , NewHPos , .T. )
Thanks for the tips.
I went far post less information than he.
I'm doing some tests to avoid using the CELLNavegation, but have not had success.
Example to change the position of the bar:
* _HMG_SYSDATA [ 345 ] -> ScrollStep
#define SB_HORZ 0
hwnd := GetControlHandle( cControlName, cParentForm )
NewHPos := GetScrollPos( hwnd , SB_HORZ ) + 100
SetScrollPos ( hwnd , SB_HORZ , NewHPos , .T. )
- serge_girard
- Posts: 3166
- Joined: Sun Nov 25, 2012 2:44 pm
- DBs Used: 1 MySQL - MariaDB
2 DBF - Location: Belgium
- Contact:
Re: GRID Scrollbar
Thanks Pablo and Amarante !
I now have something like this working (almost perfect):
With this code only focuses on the rows is OK but not the scrollbar. Now I will find a way to synchronize scrollbars...
Serge
I now have something like this working (almost perfect):
Code: Select all
grid_1..
ON GOTFOCUS Grid_Left();
ON CHANGE Grid_Left()
grid_2..
ON GOTFOCUS Grid_Right();
ON CHANGE Grid_Right()
FUNCTION Grid_Left()
/*****************/
LOCAL c1 := Form_XFER.Tab_1(3).Grid_1.Value
Form_XFER.Tab_1(3).Grid_2.Value := c1
RETURN
FUNCTION Grid_Right()
/*******************/
LOCAL c1 := Form_XFER.Tab_1(3).Grid_2.Value
Form_XFER.Tab_1(3).Grid_1.Value := c1
RETURN
Serge
There's nothing you can do that can't be done...
- serge_girard
- Posts: 3166
- Joined: Sun Nov 25, 2012 2:44 pm
- DBs Used: 1 MySQL - MariaDB
2 DBF - Location: Belgium
- Contact:
Re: GRID Scrollbar
Pablo/Amarante,
Consider this little example. What lacks is the function for the mousewheel mouvements.
Clicking a row is OK
NB: Both GRIDs are allways filled up with equal number of rows/cols.
Meaning is comparing the data in the two grids.
Serge
Consider this little example. What lacks is the function for the mousewheel mouvements.
Code: Select all
#INCLUDE "hmg.ch"
DEFINE WINDOW Form_1;
AT 0,0 ;
WIDTH 1550 ;
HEIGHT 850 ;
MAIN ;
TITLE "Title "
ON KEY ESCAPE ACTION { Form_1.Release }
DEFINE TAB Tab_1 ;
AT 100,10 ;
WIDTH 1500 ;
HEIGHT 700 ;
VALUE 1 ;
TOOLTIP 'Database Controls'
DEFINE PAGE 'page 1'
@ 130,10 GRID Grid_1 ;
WIDTH 650 ;
HEIGHT 500 ;
HEADERS {'F1', 'f1 ' };
WIDTHS { 140, 40 } ;
FONT "Arial" SIZE 09 ;
MULTISELECT ;
ON GOTFOCUS Grid_Left();
ON CHANGE Grid_Left()
@ 130,710 GRID Grid_2 ;
WIDTH 650 ;
HEIGHT 500 ;
HEADERS {'F1', 'f1 ' };
WIDTHS { 140, 40 } ;
FONT "Arial" SIZE 09 ;
MULTISELECT ;
ON GOTFOCUS Grid_Right();
ON CHANGE Grid_Right()
END PAGE
END TAB
END WINDOW
FILL_GRIDS()
CENTER WINDOW Form_1
ACTIVATE WINDOW Form_1
RETURN
FUNCTION Grid_Left()
/*****************/
LOCAL c1 := Form_1.Tab_1(1).Grid_1.Value
Form_1.Tab_1(1).Grid_2.Value := c1
RETURN
FUNCTION Grid_Right()
/*******************/
LOCAL c1 := Form_1.Tab_1(1).Grid_2.Value
Form_1.Tab_1(1).Grid_1.Value := c1
RETURN
FUNCTION FILL_GRIDS()
/********************/
FOR A = 1 TO 100
ADD ITEM {STR(A), 'Grid_1' } TO Grid_1 OF Form_1
ADD ITEM {STR(A), 'Grid_2' } TO Grid_2 OF Form_1
NEXT A
NB: Both GRIDs are allways filled up with equal number of rows/cols.
Meaning is comparing the data in the two grids.
Serge
There's nothing you can do that can't be done...
- Pablo César
- Posts: 4059
- Joined: Wed Sep 08, 2010 1:18 pm
- Location: Curitiba - Brasil
GRID Scrollbar
Thanks Serge, but I needed before and now I done by this way:serge_girard wrote:Pablo/Amarante,
Consider this little example
Code: Select all
#include <hmg.ch>
#define SB_VERT 1
Function Main()
Local i, aItems:={}
For I=1 To 50
Aadd(aItems,{"Item "+AllTrim(Str(i))})
Next
DEFINE WINDOW Form_1 AT 132 , 235 WIDTH 719 HEIGHT 351 TITLE "ScrollBars at both Grids" MAIN
DEFINE GRID Grid_1
ROW 30
COL 20
WIDTH 320
HEIGHT 190
ITEMS aItems
VALUE Nil
WIDTHS { 100 }
HEADERS {'Items'}
FONTNAME "Arial"
FONTSIZE 9
TOOLTIP ""
ONCHANGE Nil // Grid_Left()
ONGOTFOCUS Grid_Left()
ONCHANGE Grid_Left()
FONTBOLD .F.
FONTITALIC .F.
FONTUNDERLINE .F.
FONTSTRIKEOUT .F.
ONDBLCLICK Nil
ONHEADCLICK Nil
ONQUERYDATA Nil
MULTISELECT .F.
ALLOWEDIT .F.
VIRTUAL .F.
DYNAMICBACKCOLOR Nil
DYNAMICFORECOLOR Nil
COLUMNWHEN Nil
COLUMNVALID Nil
COLUMNCONTROLS Nil
SHOWHEADERS .T.
CELLNAVIGATION .F.
NOLINES .F.
HELPID Nil
IMAGE Nil
JUSTIFY Nil
ITEMCOUNT Nil
BACKCOLOR Nil
FONTCOLOR Nil
HEADERIMAGES Nil
ROWSOURCE Nil
COLUMNFIELDS Nil
ALLOWAPPEND .F.
ALLOWDELETE .F.
BUFFERED .F.
DYNAMICDISPLAY Nil
ONSAVE Nil
LOCKCOLUMNS Nil
END GRID
DEFINE GRID Grid_2
ROW 30
COL 360
WIDTH 330
HEIGHT 190
ITEMS aItems
VALUE Nil
WIDTHS { 100 }
HEADERS {'Items'}
FONTNAME "Arial"
FONTSIZE 9
TOOLTIP ""
ONCHANGE Nil // Grid_Right()
ONGOTFOCUS Grid_Right()
ONLOSTFOCUS Grid_Right()
FONTBOLD .F.
FONTITALIC .F.
FONTUNDERLINE .F.
FONTSTRIKEOUT .F.
ONDBLCLICK Nil
ONHEADCLICK Nil
ONQUERYDATA Nil
MULTISELECT .F.
ALLOWEDIT .F.
VIRTUAL .F.
DYNAMICBACKCOLOR Nil
DYNAMICFORECOLOR Nil
COLUMNWHEN Nil
COLUMNVALID Nil
COLUMNCONTROLS Nil
SHOWHEADERS .T.
CELLNAVIGATION .F.
NOLINES .F.
HELPID Nil
IMAGE Nil
JUSTIFY Nil
ITEMCOUNT Nil
BACKCOLOR Nil
FONTCOLOR Nil
HEADERIMAGES Nil
ROWSOURCE Nil
COLUMNFIELDS Nil
ALLOWAPPEND .F.
ALLOWDELETE .F.
BUFFERED .F.
DYNAMICDISPLAY Nil
ONSAVE Nil
LOCKCOLUMNS Nil
END GRID
DEFINE BUTTON Button_1
ROW 260
COL 130
WIDTH 100
HEIGHT 28
ACTION GetScrollBarPos_Left()
CAPTION "Button_1"
FONTNAME "Arial"
FONTSIZE 9
TOOLTIP ""
FONTBOLD .F.
FONTITALIC .F.
FONTUNDERLINE .F.
FONTSTRIKEOUT .F.
ONGOTFOCUS Nil
ONLOSTFOCUS Nil
HELPID Nil
FLAT .F.
TABSTOP .T.
VISIBLE .T.
TRANSPARENT .F.
MULTILINE .F.
PICTURE Nil
PICTALIGNMENT TOP
END BUTTON
DEFINE BUTTON Button_2
ROW 260
COL 490
WIDTH 100
HEIGHT 28
ACTION GetScrollBarPos_Right()
CAPTION "Button_2"
FONTNAME "Arial"
FONTSIZE 9
TOOLTIP ""
FONTBOLD .F.
FONTITALIC .F.
FONTUNDERLINE .F.
FONTSTRIKEOUT .F.
ONGOTFOCUS Nil
ONLOSTFOCUS Nil
HELPID Nil
FLAT .F.
TABSTOP .T.
VISIBLE .T.
TRANSPARENT .F.
MULTILINE .F.
PICTURE Nil
PICTALIGNMENT TOP
END BUTTON
END WINDOW
CENTER WINDOW Form_1
ACTIVATE WINDOW Form_1
Return Nil
Function Grid_Left()
Local c1 := Form_1.Grid_1.Value
Form_1.Grid_2.Value := c1
Return Nil
Function Grid_Right()
Local c1 := Form_1.Grid_2.Value
Form_1.Grid_1.Value := c1
Return Nil
Function GetScrollBarPos_Left()
Local nHandle_Left:=GetControlHandle ( "Grid_1", "Form_1" )
Local nHandle_Right:=GetControlHandle ( "Grid_2", "Form_1" )
Local nPos:=GetScrollPos ( nHandle_Left, 1 )
SetScrollPos ( nHandle_Right, SB_VERT, nPos, .T. )
Return Nil
Function GetScrollBarPos_Right()
Local nHandle_Right:=GetControlHandle ( "Grid_2", "Form_1" )
Local nHandle_Left:=GetControlHandle ( "Grid_1", "Form_1" )
Local nPos:=GetScrollPos ( nHandle_Right, 1 )
SetScrollPos ( nHandle_Left, SB_VERT, nPos, .T. )
Return Nil
Another question is to set a new value and equalizing position of both grids, not only set scroll position. this is not enough.
HMGing a better world
"Matter tells space how to curve, space tells matter how to move."
Albert Einstein
"Matter tells space how to curve, space tells matter how to move."
Albert Einstein
- serge_girard
- Posts: 3166
- Joined: Sun Nov 25, 2012 2:44 pm
- DBs Used: 1 MySQL - MariaDB
2 DBF - Location: Belgium
- Contact:
Re: GRID Scrollbar
Thanks Pablo for helping!
It's not 100% OK but for the time being it is OK.
Serge
It's not 100% OK but for the time being it is OK.
Serge
There's nothing you can do that can't be done...
- Pablo César
- Posts: 4059
- Joined: Wed Sep 08, 2010 1:18 pm
- Location: Curitiba - Brasil
GRID Scrollbar
Hi Serge !
Look at this one:
It's almost near... but still can it be improved.
But I can not match the movement of the lines.
I hope you enjoy it !
Look at this one:
Code: Select all
#include <hmg.ch>
#define SB_VERT 1
Function Main()
Local i, aItems:={}
For I=1 To 50
Aadd(aItems,{"Item "+AllTrim(Str(i))})
Next
DEFINE WINDOW Form_1 AT 132 , 235 WIDTH 719 HEIGHT 351 TITLE "ScrollBars at both Grids" MAIN
DEFINE GRID Grid_1
ROW 30
COL 20
WIDTH 320
HEIGHT 190
ITEMS aItems
VALUE Nil
WIDTHS { 100 }
HEADERS {'Items'}
FONTNAME "Arial"
FONTSIZE 9
TOOLTIP ""
ONCHANGE Nil // Grid_Left()
ONGOTFOCUS Grid_Left()
ONCHANGE Grid_Left()
FONTBOLD .F.
FONTITALIC .F.
FONTUNDERLINE .F.
FONTSTRIKEOUT .F.
ONDBLCLICK Nil
ONHEADCLICK Nil
ONQUERYDATA Nil
MULTISELECT .F.
ALLOWEDIT .F.
VIRTUAL .F.
DYNAMICBACKCOLOR Nil
DYNAMICFORECOLOR Nil
COLUMNWHEN Nil
COLUMNVALID Nil
COLUMNCONTROLS Nil
SHOWHEADERS .T.
CELLNAVIGATION .F.
NOLINES .F.
HELPID Nil
IMAGE Nil
JUSTIFY Nil
ITEMCOUNT Nil
BACKCOLOR Nil
FONTCOLOR Nil
HEADERIMAGES Nil
ROWSOURCE Nil
COLUMNFIELDS Nil
ALLOWAPPEND .F.
ALLOWDELETE .F.
BUFFERED .F.
DYNAMICDISPLAY Nil
ONSAVE Nil
LOCKCOLUMNS Nil
END GRID
DEFINE GRID Grid_2
ROW 30
COL 360
WIDTH 330
HEIGHT 190
ITEMS aItems
VALUE Nil
WIDTHS { 100 }
HEADERS {'Items'}
FONTNAME "Arial"
FONTSIZE 9
TOOLTIP ""
ONCHANGE Nil // Grid_Right()
ONGOTFOCUS Grid_Right()
ONLOSTFOCUS Grid_Right()
FONTBOLD .F.
FONTITALIC .F.
FONTUNDERLINE .F.
FONTSTRIKEOUT .F.
ONDBLCLICK Nil
ONHEADCLICK Nil
ONQUERYDATA Nil
MULTISELECT .F.
ALLOWEDIT .F.
VIRTUAL .F.
DYNAMICBACKCOLOR Nil
DYNAMICFORECOLOR Nil
COLUMNWHEN Nil
COLUMNVALID Nil
COLUMNCONTROLS Nil
SHOWHEADERS .T.
CELLNAVIGATION .F.
NOLINES .F.
HELPID Nil
IMAGE Nil
JUSTIFY Nil
ITEMCOUNT Nil
BACKCOLOR Nil
FONTCOLOR Nil
HEADERIMAGES Nil
ROWSOURCE Nil
COLUMNFIELDS Nil
ALLOWAPPEND .F.
ALLOWDELETE .F.
BUFFERED .F.
DYNAMICDISPLAY Nil
ONSAVE Nil
LOCKCOLUMNS Nil
END GRID
DEFINE BUTTON Button_1
ROW 260
COL 130
WIDTH 100
HEIGHT 28
ACTION GetScrollBarPos_Left()
CAPTION "Button_1"
FONTNAME "Arial"
FONTSIZE 9
TOOLTIP ""
FONTBOLD .F.
FONTITALIC .F.
FONTUNDERLINE .F.
FONTSTRIKEOUT .F.
ONGOTFOCUS Nil
ONLOSTFOCUS Nil
HELPID Nil
FLAT .F.
TABSTOP .T.
VISIBLE .T.
TRANSPARENT .F.
MULTILINE .F.
PICTURE Nil
PICTALIGNMENT TOP
END BUTTON
DEFINE BUTTON Button_2
ROW 260
COL 490
WIDTH 100
HEIGHT 28
ACTION GetScrollBarPos_Right()
CAPTION "Button_2"
FONTNAME "Arial"
FONTSIZE 9
TOOLTIP ""
FONTBOLD .F.
FONTITALIC .F.
FONTUNDERLINE .F.
FONTSTRIKEOUT .F.
ONGOTFOCUS Nil
ONLOSTFOCUS Nil
HELPID Nil
FLAT .F.
TABSTOP .T.
VISIBLE .T.
TRANSPARENT .F.
MULTILINE .F.
PICTURE Nil
PICTALIGNMENT TOP
END BUTTON
DEFINE STATUSBAR FONT "Courier New" SIZE 9
STATUSITEM PadC("",75)
END STATUSBAR
END WINDOW
CREATE EVENT PROCNAME Check_Grid_Events()
CENTER WINDOW Form_1
ACTIVATE WINDOW Form_1
Return Nil
Function Grid_Left()
Local c1 := Form_1.Grid_1.Value
Form_1.Grid_2.Value := c1
Return Nil
Function Grid_Right()
Local c1 := Form_1.Grid_2.Value
Form_1.Grid_1.Value := c1
Return Nil
Function GetScrollBarPos_Left()
Local nHandle_Left:=GetControlHandle ( "Grid_1", "Form_1" )
Local nHandle_Right:=GetControlHandle ( "Grid_2", "Form_1" )
Local nPos:=GetScrollPos ( nHandle_Left, 1 )
SetScrollPos ( nHandle_Right, SB_VERT, nPos, .T. )
Return Nil
Function GetScrollBarPos_Right()
Local nHandle_Right:=GetControlHandle ( "Grid_2", "Form_1" )
Local nHandle_Left:=GetControlHandle ( "Grid_1", "Form_1" )
Local nPos:=GetScrollPos ( nHandle_Right, 1 )
SetScrollPos ( nHandle_Left, SB_VERT, nPos, .T. )
Return Nil
Function Check_Grid_Events()
Local nMsg := EventMsg()
Local wParam := EventWPARAM()
Local lScrollMove:=.F.
If wParam <> Form_1.HANDLE
DO CASE
CASE nMsg == WM_KEYUP
lScrollMove:=.T.
CASE nMsg == WM_KEYDOWN
lScrollMove:=.T.
CASE nMsg == 161
If LoWord(wParam) < 8
lScrollMove:=.T.
EndIf
CASE nMsg == WM_MOUSEWHEEL
lScrollMove:=.T.
OTHERWISE
Form_1.StatusBar.Item(1):=Str(nMsg)
ENDCASE
If lScrollMove
GetScrollBarPos_Left()
Endif
Endif
Return Nil
But I can not match the movement of the lines.
I hope you enjoy it !
HMGing a better world
"Matter tells space how to curve, space tells matter how to move."
Albert Einstein
"Matter tells space how to curve, space tells matter how to move."
Albert Einstein
- Amarante
- Posts: 182
- Joined: Fri Apr 27, 2012 9:44 pm
- DBs Used: DBF, MySQL, MariaDB, SQLite, PostgreSQL
- Location: Araruama-RJ, Brazil
Re: GRID Scrollbar
I think it will be necessary to work with percentage and not values.
Values with the number of rows and columns should be equal.
In percentage would work like this:
If the horizontal bar is 50% of the total, then the pipe should be adjusted to the same.
Of course we have to calculate the conversion of percentage to their values.
Just a thought, do not know if it's the best.
Values with the number of rows and columns should be equal.
In percentage would work like this:
If the horizontal bar is 50% of the total, then the pipe should be adjusted to the same.
Of course we have to calculate the conversion of percentage to their values.
Just a thought, do not know if it's the best.
- serge_girard
- Posts: 3166
- Joined: Sun Nov 25, 2012 2:44 pm
- DBs Used: 1 MySQL - MariaDB
2 DBF - Location: Belgium
- Contact:
Re: GRID Scrollbar
Thanks both!
I try tomorrow. Now off to guitar playing!
Serge
I try tomorrow. Now off to guitar playing!
Serge
There's nothing you can do that can't be done...