Discussion:
A DBGrid with a clickable button
(too old to reply)
Stark
2012-02-12 15:54:10 UTC
Permalink
I found a number of examples on the web on how to add a CheckBox in a DBGrid
column, but I need a Button. Inspired by those examples, I tried by myself
with little success. In my test project I get a button in a boolen field (it
could be any field), but the button remains pushed when clicked, and only
the click on a button in another row will reset it raised. I cant find a
remedy ? This is the OnDrawColumnCell I wrote:

procedure TForm1.DBGrid1DrawColumnCell(Sender: TObject; const Rect: TRect;
DataCol: Integer; Column: TColumn; State: TGridDrawState);
begin
with Sender as TDBGrid do
begin
if Column.Field.DataType = ftBoolean then
begin
Canvas.FillRect(Rect);
DrawFrameControl(Canvas.Handle, Rect, DFC_BUTTON, DFCS_BUTTONPUSH);
end;
end;
end;
Jamie
2012-02-12 17:07:32 UTC
Permalink
Post by Stark
I found a number of examples on the web on how to add a CheckBox in a
DBGrid column, but I need a Button. Inspired by those examples, I tried
by myself with little success. In my test project I get a button in a
boolen field (it could be any field), but the button remains pushed when
clicked, and only the click on a button in another row will reset it
procedure TForm1.DBGrid1DrawColumnCell(Sender: TObject; const Rect: TRect;
DataCol: Integer; Column: TColumn; State: TGridDrawState);
begin
with Sender as TDBGrid do
begin
if Column.Field.DataType = ftBoolean then
begin
Canvas.FillRect(Rect);
DrawFrameControl(Canvas.Handle, Rect, DFC_BUTTON, DFCS_BUTTONPUSH);
end;
end;
end;
I see a potential problem here, this above code does not say when at
what point does the event get called? After reviewing the events that
are available to you (TDBGrid), it is my best guess that this event
above only gets called after the mouse is released and not when it is
pushed down.

How ever, a simple test can determine this, if you press and hold the
mouse key down and see your little button drawn, then you are in luck :)

You can stash the RECT value away and process the WM_KEYUP message in
the form that contains this DBgrid.. When you process this message,
check to see if the stashed RECT is valid? IN other words, its not set
to a 0 value, if so then process the graphics code needed to undo the
button box and then clear the RECT value. You could also test for the
currently active control while there to save time.

You cold also simply assign a Button over that area and then process
the DB code yourself in the button event. Set your own image on the
button. They're a few ways :)


Jamie
Stark
2012-02-12 23:09:32 UTC
Permalink
Post by Stark
I found a number of examples on the web on how to add a CheckBox in a
DBGrid column, but I need a Button. Inspired by those examples, I tried
by myself with little success. In my test project I get a button in a
boolen field (it could be any field), but the button remains pushed when
clicked, and only the click on a button in another row will reset it
procedure TForm1.DBGrid1DrawColumnCell(Sender: TObject; const Rect: TRect;
DataCol: Integer; Column: TColumn; State: TGridDrawState);
begin
with Sender as TDBGrid do
begin
if Column.Field.DataType = ftBoolean then
begin
Canvas.FillRect(Rect);
DrawFrameControl(Canvas.Handle, Rect, DFC_BUTTON, DFCS_BUTTONPUSH);
end;
end;
end;
I see a potential problem here, this above code does not say when at what
point does the event get called? After reviewing the events that
are available to you (TDBGrid), it is my best guess that this event above
only gets called after the mouse is released and not when it is
pushed down.
How ever, a simple test can determine this, if you press and hold the
mouse key down and see your little button drawn, then you are in luck :)
You can stash the RECT value away and process the WM_KEYUP message in
the form that contains this DBgrid.. When you process this message, check
to see if the stashed RECT is valid? IN other words, its not set to a 0
value, if so then process the graphics code needed to undo the button box
and then clear the RECT value. You could also test for the
currently active control while there to save time.
You cold also simply assign a Button over that area and then process the
DB code yourself in the button event. Set your own image on the button.
They're a few ways :)
Jamie
I am not sure I understand your comments. I'll try to explain what I did: In
a form I have a DBGrid and a Table as Datasource. I want one of the columns
to display a button, rather then its content. So I set DefaultDrawing to
true and paint the button with DrawFrameControl. The DBGrid1
OnDrawColumnCell event is called initially when the DBGrid associated table
is opened and whenever any cell is entered or the grid scrolled. The button
shows correctly. But clicking on it, the button is repainted pushed and does
not raise if clicked again. If I click on the button in another row, this
will show pushed and the previous will raise. If you have an idea on how to
correct this behaviour, can you show an example ? Thanks
Jamie
2012-02-13 02:01:49 UTC
Permalink
Post by Stark
Post by Jamie
Post by Stark
I found a number of examples on the web on how to add a CheckBox in a
DBGrid column, but I need a Button. Inspired by those examples, I
tried by myself with little success. In my test project I get a
button in a boolen field (it could be any field), but the button
remains pushed when clicked, and only the click on a button in
another row will reset it raised. I cant find a remedy ? This is the
procedure TForm1.DBGrid1DrawColumnCell(Sender: TObject; const Rect: TRect;
DataCol: Integer; Column: TColumn; State: TGridDrawState);
begin
with Sender as TDBGrid do
begin
if Column.Field.DataType = ftBoolean then
begin
Canvas.FillRect(Rect);
DrawFrameControl(Canvas.Handle, Rect, DFC_BUTTON,
DFCS_BUTTONPUSH);
end;
end;
end;
I see a potential problem here, this above code does not say when at
what point does the event get called? After reviewing the events that
are available to you (TDBGrid), it is my best guess that this event
above only gets called after the mouse is released and not when it is
pushed down.
How ever, a simple test can determine this, if you press and hold
the mouse key down and see your little button drawn, then you are in
luck :)
You can stash the RECT value away and process the WM_KEYUP message
in the form that contains this DBgrid.. When you process this
message, check to see if the stashed RECT is valid? IN other words,
its not set to a 0 value, if so then process the graphics code needed
to undo the button box and then clear the RECT value. You could also
test for the
currently active control while there to save time.
You cold also simply assign a Button over that area and then process
the DB code yourself in the button event. Set your own image on the
button. They're a few ways :)
Jamie
I am not sure I understand your comments. I'll try to explain what I
did: In a form I have a DBGrid and a Table as Datasource. I want one of
the columns to display a button, rather then its content. So I set
DefaultDrawing to true and paint the button with DrawFrameControl. The
DBGrid1 OnDrawColumnCell event is called initially when the DBGrid
associated table is opened and whenever any cell is entered or the grid
scrolled. The button shows correctly. But clicking on it, the button is
repainted pushed and does not raise if clicked again. If I click on the
button in another row, this will show pushed and the previous will
raise. If you have an idea on how to correct this behaviour, can you
show an example ? Thanks
I only assumed you wanted the button to raise as you lifted your
mouse button? Now it seems you want a toggle action?

If the DataType boolean isn't changing state then how would you
expect it to redraw anything but the same thing, over and over again?

If infact the DataType value is changing when you click there, then
you need another DrawFrameCOntrol in a raise state when the DataType is
false. I see that you are only drawing one state there and most likely
the form isn't getting a Invalidate to repaint that area otherwise.

Put a Beep in the event code to see if your clicks are even reaching
it all the time.. It is possible the canvas thinks you don't need to
update there and there for, it does not always get called.

Jamie
Stark
2012-02-13 13:48:40 UTC
Permalink
I only assumed you wanted the button to raise as you lifted your mouse
button? Now it seems you want a toggle action?
If the DataType boolean isn't changing state then how would you
expect it to redraw anything but the same thing, over and over again?
If infact the DataType value is changing when you click there, then you
need another DrawFrameCOntrol in a raise state when the DataType is
false. I see that you are only drawing one state there and most likely
the form isn't getting a Invalidate to repaint that area otherwise.
Put a Beep in the event code to see if your clicks are even reaching it
all the time.. It is possible the canvas thinks you don't need to
update there and there for, it does not always get called.
Jamie
Sorry for my english, but I don't want a toggle action. I just want a
clickable button, that is a button that when clicked just blinks and stays
as it is. What happens is that when I click the button becomes pushed and
stays pushed. If I click a button in another row, this will become pushed,
and the previous is raised. It is not what I want. In fact I wanted to give
the user a way to choose one of the rows of the DBGrid and push its button
to act on that row. I may find another way, for example a single external
button; the user can highlight a row and then push this single button.
I just wanted what I thought was a more intuitive interface for the user..
GS
2012-02-13 15:40:33 UTC
Permalink
Post by Stark
I only assumed you wanted the button to raise as you lifted your mouse
button? Now it seems you want a toggle action?
If the DataType boolean isn't changing state then how would you
expect it to redraw anything but the same thing, over and over again?
If infact the DataType value is changing when you click there, then you
need another DrawFrameCOntrol in a raise state when the DataType is
false. I see that you are only drawing one state there and most likely the
form isn't getting a Invalidate to repaint that area otherwise.
Put a Beep in the event code to see if your clicks are even reaching it
all the time.. It is possible the canvas thinks you don't need to
update there and there for, it does not always get called.
Jamie
Sorry for my english, but I don't want a toggle action. I just want a
clickable button, that is a button that when clicked just blinks and stays as
it is. What happens is that when I click the button becomes pushed and stays
pushed. If I click a button in another row, this will become pushed, and the
previous is raised. It is not what I want. In fact I wanted to give the user
a way to choose one of the rows of the DBGrid and push its button to act on
that row. I may find another way, for example a single external button; the
user can highlight a row and then push this single button.
I just wanted what I thought was a more intuitive interface for the user..
Just a thought...

Intuitively, most users would expect a menu/toolbar/button to act on a
selection of the grid, whether it be a single cell or a range. What
they would not expect is to find a button in the grid as might be done
with a spreadsheet, for example, using Form or ActiveX controls.

I use Farpoint's Spread.ocx in place of any control where I want a grid
or multi-columns. I know there's a similar control available for Delphi
but I don't know if it hosts buttons as does the Spread.ocx!
Regardless, I don't like putting buttons on a spreadsheet because they
don't stay put after hiding rows/cols without tonnes of positioning
code. Might seem trivial for a few buttons but not how I want to work
with dozens of them! It's easier to make cells 'look/behave' like
buttons and use a 'SelectionChange' event to fire their respective
procedures.
--
Garry

Free usenet access at http://www.eternal-september.org
ClassicVB Users Regroup! comp.lang.basic.visual.misc
Jamie
2012-02-13 22:48:41 UTC
Permalink
Post by Stark
Post by Jamie
I only assumed you wanted the button to raise as you lifted your
mouse button? Now it seems you want a toggle action?
If the DataType boolean isn't changing state then how would you
expect it to redraw anything but the same thing, over and over again?
If infact the DataType value is changing when you click there, then
you need another DrawFrameCOntrol in a raise state when the DataType is
false. I see that you are only drawing one state there and most
likely the form isn't getting a Invalidate to repaint that area
otherwise.
Put a Beep in the event code to see if your clicks are even reaching
it all the time.. It is possible the canvas thinks you don't need to
update there and there for, it does not always get called.
Jamie
Sorry for my english, but I don't want a toggle action. I just want a
clickable button, that is a button that when clicked just blinks and
stays as it is. What happens is that when I click the button becomes
pushed and stays pushed. If I click a button in another row, this will
become pushed, and the previous is raised. It is not what I want. In
fact I wanted to give the user a way to choose one of the rows of the
DBGrid and push its button to act on that row. I may find another way,
for example a single external button; the user can highlight a row and
then push this single button.
I just wanted what I thought was a more intuitive interface for the user..
Right, and your code isn't going to allow for that.

THe boolean value you are testing remains the same between the click
down and click up. You need to test for the mouse state when you're
there to properly indicate if you should be drawing the button down or up.

Basically, you need to check the mouse state. I suppose you could also
test for the boolean value to not draw the button at all, that is your
choice.


Jamie
Stark
2012-02-14 11:11:04 UTC
Permalink
Post by Jamie
Post by Stark
I just wanted what I thought was a more intuitive interface for the user..
Right, and your code isn't going to allow for that.
I think this comment will put an end to the discussion. At the end, I was
rather after a technical problem and forgot the main question which is the
ease of use for the user. I guess my wasn't a good idea and I will abandon
it. Thanks all of you for your help

Hans-Peter Diettrich
2012-02-13 08:50:00 UTC
Permalink
Post by Stark
I am not sure I understand your comments. I'll try to explain what I
did: In a form I have a DBGrid and a Table as Datasource. I want one of
the columns to display a button, rather then its content. So I set
DefaultDrawing to true and paint the button with DrawFrameControl.
This IMO is the wrong approach. Such drawings tend to disappear almost
immediately. Try to find the properties that make the control behave as
you want.
Post by Stark
The
DBGrid1 OnDrawColumnCell event is called initially when the DBGrid
associated table is opened and whenever any cell is entered or the grid
scrolled. The button shows correctly. But clicking on it, the button is
repainted pushed and does not raise if clicked again.
AFAIR there exists some propery AllowAllUp (or the like). When such
buttons are grouped, they can behave like radio buttons (exactly one
down), or as independent up/down buttons. That's different behaviour
from ordinary push buttons (OK, Cancel...).

DoDi
Loading...