BorlandTalk.com Forum Index BorlandTalk.com
Borland discussion newsgroups
 
Archives   FAQFAQ   SearchSearch   MemberlistMemberlist   UsergroupsUsergroups   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

Keyboard behaviour of TStringGrid

 
Post new topic   Reply to topic    BorlandTalk.com Forum Index -> C++ Builder (VCL Components Development)
View previous topic :: View next topic  
Author Message
Martin Nijhoff
Guest





PostPosted: Thu Mar 30, 2006 2:03 pm    Post subject: Keyboard behaviour of TStringGrid Reply with quote



Hi,

I use a component derived from TStringGrid, to display data in tabular form.
The grid consists of value cells (displaying integers, floats and strings)
and label cells, which describe the contents of the value cells. Each row in
the grid can contain more than one set of label + value cells, for example:

First name: Martin Last name: Nijhoff Age: 33

where 'First name:', 'Last name:' and 'Age:' are label cells and 'Martin',
'Nijhoff' and '33' are value cells.

The user should only be able to select a value cell in the grid. For this
purpose, I use an OnSelectCell handler, which sets CanSelect=false for label
cells. This works fine when the user selects cells using the mouse. However,
if the keyboard is used, the label cells 'block' the value cells next to it,
because the unselectable cells are not skipped-over.

I had a look at the VCL source and found that the keyboard behaviour is
implemented in TCustomGrid. The 'navigational' keypresses are handled by
KeyDown(), which calls FocusCell() to select the cell. FocusCell() calls
MoveCurrent to change the current selection, which in turn calls
SelectCell() to trigger the OnSelectCell event. If SelectCell() returns
false, indicating the cell can't be selected, then MoveCurrent() does
nothing.

To change the keyboard behaviour of my string grid component, I would have
to override MoveCurrent() and include some logic to skip over unselectable
cells if SelectCell() returns false. Unfortunately, MoveCurrent() is a
private method, so I can't override it.

Is there any way to change the keyboard behaviour, without having to write a
string grid component from scratch?

Any help would be greatly appreciated.


Martin
Back to top
JD
Guest





PostPosted: Fri Mar 31, 2006 8:03 am    Post subject: Re: Keyboard behaviour of TStringGrid Reply with quote



"Martin Nijhoff" <dont (AT) mail (DOT) me> wrote:
Quote:

[...]
First name: Martin Last name: Nijhoff Age: 33

where 'First name:', 'Last name:' and 'Age:' are label cells
and 'Martin', 'Nijhoff' and '33' are value cells.

[...] Is there any way to change the keyboard behaviour,

Override it's KeyDown method so you can determine if the next
cell would be a label cell. From there you can decide if you
want to swallow the key and manually set the Col property or
do nothing and allow the grid to process the key (you could
also optionally increment the Row property so that the user
doesn't have to change fingers on the arrow keys). For example
assumes the above record is the entire row layout):

protected:
DYNAMIC void __fastcall KeyDown(Word &Key, TShiftState Shift);

//-------------------------------------------------------------
void __fastcall TMyGrid::KeyDown(Word &Key, TShiftState Shift)
{
if( Key == VK_LEFT )
{
if( Col == 1 )
{
if( Row > FixedRows ) --Row;
Col = 5;
}
else Col -= 2;
Key = 0;
}
else if( Key == VK_RIGHT )
{
if( Col == 5 )
{
if( Row < (RowCount - 1) ) ++Row;
Col = 1;
}
else Col += 2;
Key = 0;
}
TStringGrid::KeyDown(Key, Shift);
}
//-------------------------------------------------------------

~ JD
Back to top
Martin Nijhoff
Guest





PostPosted: Fri Mar 31, 2006 9:03 am    Post subject: Re: Keyboard behaviour of TStringGrid Reply with quote



Thanks for your reply, JD.

Quote:
assumes the above record is the entire row layout):

Unfortunately, this is not the case. A row can also consist of a single
label cell or a single value cell. If a value cell contains a string value
that consists of two or more lines of text, than the value cell uses an
entire row and the label cell is located in the row above it. For example:

First name: Martin Last name: Nijhoff Age: 33
Street: Blablablablablabla Number: 123
Remarks:
Blabla blablabla blablablabla blabla blablabla blablablabla blabla
blablablabla blabla blabla blablabla bla blablabla blabla blabla
blabla blabla blablabla blablablabla blabla blablabla blablablabla.

The grid can also contain a number of 'informative' cells, which are not
linked to any value cells at all.

There is no way of knowing what the layout of the grid is, except what the
application reports back in the OnSelectCell event. The grid component is
used for a number of tables, all with varying layouts. The solution you
proposed would mean that I would have to write custom grid components for
each table.

Any other suggestions?

Martin
Back to top
JD
Guest





PostPosted: Fri Mar 31, 2006 1:03 pm    Post subject: Re: Keyboard behaviour of TStringGrid Reply with quote

"Martin Nijhoff" <dont (AT) mail (DOT) me> wrote:
Quote:
Thanks for your reply, JD.

assumes the above record is the entire row layout):

Unfortunately, this is not the case. [...]

You can intercept WM_KEYDOWN and and add your own event so
that each instance can have it's own method of handling the
key press. For example:

typedef int __fastcall (__closure *TOnGridKeyDown)(TObject* Sender, int Key );
//-------------------------------------------------------------
class TMyGrid : public TStringGrid
{
__published:
protected:
virtual void __fastcall WndProc( TMessage &Message );
private:
typedef TStringGrid inherited;
TOnGridKeyDown FOnGridKeyDown;
public:
__fastcall TMyGrid( TComponent* Owner );
__property TOnGridKeyDown OnGridKeyDown = { read = FOnGridKeyDown, write = FOnGridKeyDown };
};
//-------------------------------------------------------------
#endif


//-------------------------------------------------------------
void __fastcall TMyGrid::WndProc( TMessage &Message )
{
if( FOnGridKeyDown ) Message.WParam = FOnGridKeyDown( this, Message.WParam );
inherited::WndProc( Message );
}
//-------------------------------------------------------------

~ JD
Back to top
Display posts from previous:   
Post new topic   Reply to topic    BorlandTalk.com Forum Index -> C++ Builder (VCL Components Development) All times are GMT
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2006 phpBB Group
SEO toolkit © 2004-2006 webmedic.