I want to implement a FillCell procedure for TStringGrid. I want to fill a certain cell with a color but only when the cell (row) is not selected.
procedure TMyStrGrid.FillCell(Rect: TRect; aColor: TColor);
begin
//if NOT (gdSelected in State) then <---- how do I obtain the 'State' here?
begin
Canvas.Brush.Color:= aColor;
Canvas.FillRect(Rect);
end;
end;
This is just an exercise :) I am trying to figure out VCL.Grids.pas which is quite complex.
According to the comments, you are calling this function from an OnDrawCell handler. That OnDrawCell handler is passed a TGridDrawState argument which specifies whether or not the cell is selected. The event handler is of this form:
TDrawCellEvent = procedure (Sender: TObject; ACol, ARow: Longint;
Rect: TRect; State: TGridDrawState) of object;
You are asking whether it is possible to ignore the TGridDrawState and somehow recover the information later. In principle it is possible:
You have available the row and column. That identifies the cell and you can check whether or not the cell is in the current selection.
If you want to ignore the row and column also, then you could inspect the TRect that is supplied. Map that back to the row and column and again check that against the current selection.
Frankly what you are trying to do is silly in my view. You have been supplied with the draw state for a good reason. It has the information you need. Use it.
Related
I have DBGrid. Sometimes, if i change some cell value, it give a wildcard. You can see that in the image.
My question : when this wildcard, it can be appear? How can disable that?
The * is an indicator that your dbgrid is in insert mode.
If you don't want this indicator to appear you can change (the drawing of) it in the OnDrawColumnCell event.
If you use this event you may need to set dbGrid.DefaultDrawing to false.
See also: http://docwiki.embarcadero.com/RADStudio/Seattle/en/Controlling_Grid_Drawing
Another option is to implement your own custom style.
type
TMyStyleWithNoIndicator = class(TCustomStyleServices)
function GetElementDetails(Detail: TThemedGrid): TThemedElementDetails; override;
end;
function TMyStyleWithNoIndicator.GetElementDetails(Detail: TThemedGrid): TThemedElementDetails;
begin
inherited;
//prevent drawing of the insert indicator.
if Detail in [tgIndicatorInsert] then Result.State = Ord(tgCellNormal);
end;
procedure TForm1.Form1Create(Sender: TObject);
begin
TStyleManager.SetStyle(TMyStyleWithNoIndicator.Create);
end;
I am selecting a certain cell in a TAdvStringGrid:
const
MyCol=4;
MyRow=1;
HiddenCol=2;
procedure TForm1.FormCreate(Sender: TObject);
begin
AdvStringGrid1.ColCount:=5;
AdvStringGrid1.RowCount:=10;
end;
procedure TForm1.BtnHideClick(Sender: TObject);
begin
AdvStringGrid1.HideColumn(2);
end;
procedure TForm1.BtnSelectCellClick(Sender: TObject);
begin
AdvStringGrid1.SelectCells(MyCol,MyRow,MyCol,MyRow);
end;
However, my problem is that after the column is hidden, the cell I need to be selected won't be selected, since the program is seeing that the ColCount is now 4 and the cell at col 5 no more exists. How can I still select the cell regardless the hidden column?
By selecting I mean to focus the cell, and show the user what cell is been selected, not just read its string value.
According to the TAdvStringGuide v6.1 Developers Guide on page 57, you can use grid.AllCells(ACol, ARow). The description says:
"Access the grid cell as string irrespective of hidden columns or rows. grid.AllCells returns the cell as displayed, ie. after possible processing of the real cell text by the event OnGetDisplText".
To show the selected cell, you could make use of some additional functions they give you. From page 131 in their guide:
TAdvStringGrid also provides a set of functions to allow performing the mapping of real cell indexes to visible cells indexes and vice versa. This is provided through:
function RealRowIndex(ARow: Integer): Integer;
function RealColIndex(ACol: Integer): Integer;
Returns the real column or row index for a given visible column or row index
function DisplRowIndex(ARow: Integer): Integer;
function DisplColIndex(ACol: Integer): Integer;
Returns the visible column or row index for a given real column or row index.
So I think you might find what you are looking for by changing your last method to:
procedure TForm1.BtnSelectCellClick(Sender: TObject);
begin
AdvStringGrid1.SelectCells(DisplColIndex(MyCol),DisplRowIndex(MyRow),DisplColIndex(MyCol),DisplRowIndex(MyRow));
end;
Parts of my stringgrid are eligible drop targets, and some are not (first row is column headings, first column is a sort of index and subsequent columns may be dropped to). I have that coded and working.
Now I am thinking that it might be nice to gve a visual indiation to the user as he drags the mouse over a cell which is a potential drop target. I woudl like to highlight the first cell in the row and column of the cell over which he is currently hovering (or possibly the entire row and column, forming a sort of crosshair; I am as yet undecided). I reckon I can code that in OnDrawCell.
I had thought to use OnMouseMove and cehck if Dragging then, but ...
My problem is that when I am dragging the OnMouseMove event never gets called.
Is there any other way to know when the cursor is hovering over a strigngrid during a drag operation?
The OnDragOver event is specifically designed for doing this; it's called automatically, and provides the X and Y coordinates where the mouse pointer is located. There's a code sample available at that link location that demonstrates using it as well - it's for a TListBox, but the principle is the same.
procedure TForm1.FormCreate(Sender: TObject);
begin
ListBox1.Items.Add('Not');
ListBox1.Items.Add('In');
ListBox1.Items.Add('Alphabetical');
ListBox1.Items.Add('Order');
end;
// This OnDragOver event handler allows the list box to
// accept a dropped label.
procedure TForm1.ListBox1DragOver(Sender, Source: TObject; X, Y: Integer;
State: TDragState; var Accept: Boolean);
begin
Accept := Source is TLabel;
end;
I am looking for a string grid that allows me select multiple cells anywhere in the grid without them adjoining each other, e.g pressing CTRL and clicking on various cells over the grid. Or if anyone knows how to do this with the standard Delphi TStringGrid.
Any pointer would be gratefully received.
Although there are a lot of better capable people here, since you haven't gotten any answers, I thought I'd give it a try.
I'm not aware of a way to have the component do this for you. However, when you Control-click a cell, the event OnSelectedCell is called. (I just tested that.) You could put code in an event handler that adds the cell's row and column to a list that you keep of the rows and columns that are selected. Then, in the OnDrawCell event, highlight the cell:
procedure TForm1.StringGrid1DrawCell( Sender: TObject;
ACol: Integer;
ARow: Integer;
Rect: TRect;
State: TGridDrawState);
begin
if CellSelected( ARow, ACol) then // you write CellSelected() to refer to the list you're keeping
begin
StringGrid1.Canvas.Brush.Color := clYellow;
StringGrid1.Canvas.FillRect(Rect);
StringGrid1.Canvas.TextOut(Rect.Left,Rect.Top,StringGrid1.Cells[ACol,ARow]);
end;
end;
I need to get the value of the selected cell of a DBGrid in Delphi.
I have no idea how to do it. I tried dbGrid's OnMouseMove
pt : TGridCoord;
...
pt:=dbGrid.MouseCoord(x, y);
[Edited]
I can use the OnCellClick to get the value of the cell with "Column.Field.AsString", but I want to get the value from the first column when I click on any column of that row.
Found it.
dbGrid.Fields[0].AsString gets the value of the first column of the selected row.
procedure TForm1.DBGrid_DrawColumnCell(Sender: TObject; const Rect: TRect; DataCol: Integer; Column: TColumnEh; State: TGridDrawState);
const defaultCheckBoxFieldNumber = 1;
begin
if DBGrid.SelectedField.FieldNo = defaultCheckBoxFieldNumber then
....;
else
...;
end;
DBGrid.SelectedField.FieldNo gets selected field on event DrawColumnCell in TDBGrid.
I know this is late and not sure if it is what the title means.
But if it means to get the selected cell value, then try this:
procedure Form1.dbGrid1CellClick(Column: TColumn);
begin
ShowMessage(table1.Fields[Column.Index].AsString);
end;
Make sure
dbGrid1.Options.dbRowSelect := False;
i think the easiest way is to connect a hidden DBText to your dataset then set the DBText to display which field you need, this way that DBText will always contain the needed value of the active record
A DBGrid has no focus, and therefore you cannot find out which row is seleted. Instead look at the linked DataSet. A DataSet has an active row.
try this to get the value of selected cell in dbgrid:
procedure Form1.dbGrid1CellClick(Column: TColumn);
begin
ShowMessage(table1.Fields[DBGrid1.SelectedIndex].AsString);
end;