Subject Bug in TIB_Grid
Author Calin Pirtea
TIB_Grid treats mouse up event as a click.

Steps to reproduce:
1) create a form that has an edit condtrol and a TIB_Grid.
2) assign everything needed for the grid to be browse able. (Add query,
source and so on)
3) assign oncellclick event for the TIB_Grid.
4) press the left mouse button down on the edit control and move the mouse
on top of a grid row then release the mouse.
The grid will perform an oncellclick.

The reason why this is a problem is because in the
event of opening a form from another form using a
button that's under the grid, when the grid is displayed
it will pick up the mouse up event and treat is as a click
performing an oncellclick.



Wether this is considered by everyone as a bug or not is a matter to be
discussed.
If you consider this a bug read further to see how we fixed it. (long
message)





Looking through the code there is a variable that was used sometime to
establish if the mouse was pressed over the grid.

The variable is called FMouseIsDown.

When the mouse button is pressed this variable is assigned to true.

When the mouse is released this variable is cleared and not taken into
account.

This procedure in ib_grid.pas:

procedure TIB_CustomGrid.MouseUp( Button: TMouseButton; Shift: TShiftState;
X, Y: Integer );
var
Cell: TGridCoord;
SaveState: TGridState;
SaveShift: TShiftState;

begin
if AllowLockSession then
DataLink.UnlockSessionCursor;
FMouseDownPoint.X := 0;
FMouseDownPoint.Y := 0;
SaveState := FGridState;
SaveShift := Shift;
try
inherited MouseUp( Button, Shift, X, Y );
finally
FMouseIsDown := false; // Keep below inherited.
**************************************************
This line resets the FMouseIsDown before checking to see if a click is
appropriate.

end;
if Dragging or (SaveState = gsRowSizing) or
(SaveState = gsColSizing) or
((InplaceEditor <> nil) and
(InplaceEditor.Visible) and
(PtInRect(InplaceEditor.BoundsRect, Point(X,Y)))) then Exit;
if not DataLink.Disabled then
begin
Cell := MouseCoord( X, Y );
if ( Cell.X >= FixedCols - FixedDataCols ) and
( Cell.Y >= FixedRows ) and FWasDblClick then
CellDblClick( Cell.X, Cell.Y, Button, Shift )
else
if ( Cell.X >= FixedCols - FixedDataCols ) and
( Cell.Y >= FixedRows ) and not FWasDblClick then
CellClick( Cell.X, Cell.Y, Button, Shift )
else
if IndicateTitles and
( Cell.X >= FixedCols - FixedDataCols ) and
( Cell.Y = FixedRows - 1 ) then
begin
if not FMouseWasMoved and IndicateOrdering and
( Cell.Y = FixedRows - 1 ) and
( Button = mbLeft ) then
UpdateOrdering( Cell.X, Cell.Y );
TitleClick( Cell.X, Cell.Y, Button, Shift );
end
else
BorderClick( Cell.X, Cell.Y, Button, Shift );
end;
end;

We fixed this problem in this way:

procedure TIB_CustomGrid.MouseUp( Button: TMouseButton; Shift: TShiftState;
X, Y: Integer );
var
Cell: TGridCoord;
SaveState: TGridState;
SaveShift: TShiftState;

******************************
Message needed to remove the mouse up windows message from the queue if
there is more than one.
Msg: TMsg;
begin
if AllowLockSession then
DataLink.UnlockSessionCursor;
FMouseDownPoint.X := 0;
FMouseDownPoint.Y := 0;
SaveState := FGridState;
SaveShift := Shift;
try
inherited MouseUp( Button, Shift, X, Y );

**************************************
We delete all WM_LBUTTONUP since it is possible that there is more than one
out there.
PeekMessage( Msg, Handle, WM_LBUTTONUP, WM_LBUTTONUP, PM_REMOVE );

The reason there can be more that one is:
procedure TIB_CustomGrid.WMLButtonUp( var Msg: TWMLButtonUp );
begin
if FScrollInProgress <> 0 then
MessageRequeueTimer.QueueMessage( Handle, TMessage(Msg) )//This is the
reason.
else
inherited;
end;
**************************************


finally
**************************************
we no longer reset FMouseIsDown
**************************************

end;
if Dragging or (SaveState = gsRowSizing) or
(SaveState = gsColSizing) or
((InplaceEditor <> nil) and
(InplaceEditor.Visible) and
(PtInRect(InplaceEditor.BoundsRect, Point(X,Y)))) then Exit;

**************************************
If the row is different we reset FMouseIsDown because we don't want the
click to happen on a different row.
Cell := MouseCoord( X, Y );
if (Cell.Y <> Row) then FMouseIsDown := False;
**************************************


**************************************
And we make sure we call the click methods only if the mouse was down.

if not DataLink.Disabled and FMouseIsDown then
begin

if ( Cell.X >= FixedCols - FixedDataCols ) and
( Cell.Y >= FixedRows ) and FWasDblClick then
CellDblClick( Cell.X, Cell.Y, Button, Shift )
else
if ( Cell.X >= FixedCols - FixedDataCols ) and
( Cell.Y >= FixedRows ) and not FWasDblClick then
CellClick( Cell.X, Cell.Y, Button, Shift )
else
if IndicateTitles and
( Cell.X >= FixedCols - FixedDataCols ) and
( Cell.Y = FixedRows - 1 ) then
begin
if not FMouseWasMoved and IndicateOrdering and
( Cell.Y = FixedRows - 1 ) and
( Button = mbLeft ) then
UpdateOrdering( Cell.X, Cell.Y );
TitleClick( Cell.X, Cell.Y, Button, Shift );
end
else
BorderClick( Cell.X, Cell.Y, Button, Shift );
end;
FMouseIsDown := false;
and we reset the FMouseIsDown.
************************************
end;


************************************
This change is required to make the fix work for cell double click.
************************************
procedure TIB_CustomGrid.MouseDown( Button: TMouseButton; Shift:
TShiftState;
X, Y: Integer );
var
Cell: TGridCoord;
OldCol, OldRow: Integer;
begin
if DataLink.Disabled then Exit;
if not AcquireFocus then Exit;
FWasDblClick := ( ssDouble in Shift ) and ( Button = mbLeft );
Cell := MouseCoord( X, Y );
if FWasDblClick then
begin
if ( Cell.X > 0 ) or ( Cell.Y > 0 ) then begin
DblClick;
*********************************************
Set the mouse down so the celldblclick will be triggered.
*********************************************
FMouseIsDown := true;
end;
Exit;
end;

if ( Cell.X < 0 ) and ( Cell.Y < 0 ) then
begin
inherited MouseDown( Button, Shift, X, Y );
*********************************************
If the mouse down is outside the cells then reset FMouseIsDown
FMouseIsDown := false;
*********************************************
Exit;
end;
...



Calin.
Medisys Australia Pty Ltd
08 9332 2433
www.medisys.com.au
calin.pirtea@...