cxGrid selection - avoid selecting one particular column - delphi

When you select a row in the cxGrid, the entire row gets selected (changes color to blue).
How can I tell the grid not to select the records from a certain column i.e leave it colorless ? I tried afterscroll of the dataset to use :
cxGrid1dbTableView1.GetColumnByFieldName('MYFIELD').Focused := True;
But does not work.....

Use the OnCustomDrawCell event of the columns you want to change and put this code inside:
if AViewInfo.Selected then
begin
ACanvas.Brush.Color := clWindow;
ACanvas.Font.Color := clWindowText;
end;
In my case I am not using any theming so the colors match. If you are using something different you have to change them accordingly.

Related

Delphi: Bind a Chart with a DBGrid

I want to bind a Chart with a DBGrid.
Refer to the exhibit.
When I click in the DBGrid on number 3 (X-Axis), then the bar at position three should be highlighted(or a pointer to bar 3).
When I click on number 4 in the Grid then bar 4 is highlighted etc.
I'm using a TDBChart
Is there a way to do this?
Not knowing what the charting component is, cannot provide a working example, but the key which you are looking for is to use the AfterScroll event for the dataset in the grid. Since each row represents a different record, that event is fired when the grid selection moves to the row.
Edit: This doesn't highlight with a box, but does change the color of the value marks at the top of each bar. Hopefully this gets you on your way. MyQuery is what is feeding the datasource
var
savecolor : tcolor;
procedure MyForm.FormShow(Sender:TObject);
begin
...
SaveColor := dbchart1.series[0].marks.items[0].color;
...
end;
procedure MyForm.MyQueryBeforeScroll(DataSet : TDataSet);
begin
dbchart1.series[0].marks.items[MyQuery.recno-1].color := SaveColor;
end;
procedure MyForm.MyQueryAfterScroll(DataSet:TDataSet);
begin
dbchart1.series[0].marks.items[MyQuery.recno-1].color := clRed;
end;

How to show hint only in Header in TVirtualStringtree?

I want to show Hint only when user moves mouse over Header in TVirtualStringTree, not over Data nodes. Right now I can only show it Data nodes and not in Header, with this code:
procedure TForm1.FormCreate(Sender: TObject);
begin
VirtualStringTree1.Header.Columns.Add.Text := 'Brand';
VirtualStringTree1.Header.Columns[0].Width := 100;
VirtualStringTree1.Header.Columns.Add.Text := 'Model';
VirtualStringTree1.Header.Columns[1].Width := 100;
// Set the Hint text
VirtualStringTree1.Hint := 'Click to sort by Car brand';
// Show Header
VirtualStringTree1.Header.Options := VirtualStringTree1.Header.Options + [hoVisible];
// Enable Hint in Header
VirtualStringTree1.Header.Options := VirtualStringTree1.Header.Options + [hoShowHint];
// Disable the Hint in Data nodes
VirtualStringTree1.ShowHint := False;
end;
With this code there is no hint displayed anywhere, not in Data nodes and not in Header.
If I set:
// Enable Hint in Data nodes
VirtualStringTree1.ShowHint := True;
In this case the Hint is shown in Data nodes, but not in Header even if [hoShowHint] is added to Header.Options.
How can I show hint only in Header and not in Data nodes - so user can see 'Click to sort by Car brand' only when mouse is over Header and not over Data nodes?
To show hints in TVirtualStringTree (in the following VST) column headers:
With column editor open, select a column in the editor.
In Object Inspector locate the Hint property and enter text
With the VST selected look for property Header - Options - hoShowHint and set to true.
With the VST selected look for property ShowHint and set to true.
To show a hint in the "data" area, enter the hint text in the Hint property. To not show a hint in the "data" area, clear the Hint property.
In your code you are missing the lines where you enter the text for the column header hints:
VirtualStringTree1.Header.Columns[0].Hint := 'Hint for first column header';
and similar for the other columns.

Selecting a row in TStringGrid from click on any cell within that row.

I have a TStringGrid object on a form which has 1 FixedCol and 1 FixedRow. I want to be able to select an entire row on the object when the user clicks on any cell within that row. This selection must also be visible to the user (I want the row to change colour).
EDIT: Have put goRowSelect in options on the object. Is there now a way to select the row on the click of one of the cells in the fixed column?
In order highlight entire row when ever the user clicks on any cell in that row, set the following StringGrid properties.
In design time: Go to options property and check the following sub-properties.
goEditing := TRUE;
goRowSelect := TRUE;
To achieve this at run time,
StringGrid1.Options := StringGrid1.Options + [goEditing];
StringGrid1.Options := StringGrid1.Options + [goRowSelect];
If you enable the option goFixedColClick of the string grid you can then use the OnFixedCellClick event to determine which row to select. You can then set StringGrid1.Selection := TGridRect(Rect(0, Row, n, Row)); where Row is the row clicked and n is the width of your StringGrid.

hyperlink field in DBGRID

I'm doing a small internal software to search branch lines in my company. In addition to the branch lines I also put an e-mail field in the database as shown below:
My intention is to click on the registered e-mail and the software via the ShellExecute open a window to send the e-mail. I'm using the option dgRowSelect as TRUE and because of that the OnCellClick event does not correctly identify which cell was clicked.
In my searches have not found any way to do this. Then I thought of using a TLabel within the field. I can use the onclick event in the TLabel and also change the cursor icon.
If TLabel is a good solution, how can I add a TLabel in DBGrid?
Or what would be another good solution?
I'm guessing that purpose of dgRowSelect=true is for highlighting whole selected row.
TLabel is not the way I would go - I would set dgRowSelect=false and paint selected row in OnDrawColumnCell or create my own fixed dbgrid.
There was a similar question:
how can i colour whole row in DBGrid with rowselect turned off?
Anyway if you want to use dgRowSelect=true and get valid info about clicked cell, here it is:
type THackDBGrid=class(TDBGrid);
procedure TForm1.dbgrd1CellClick(Column: TColumn);
var p:TPoint;
col:TGridCoord;
i: Integer;
grid:THackDBGrid;
begin
p := Mouse.CursorPos;
grid := THackDBGrid(Column.Grid);
p := grid.ScreenToClient(p);
col := grid.MouseCoord(p.X,p.Y);
i := grid.RawToDataColumn(col.X);
Label1.Caption := 'Column index: ' + IntToStr(i);
end;

DGRid showing Selected but no Bookmark

Just found a weirdness with D5 and/or Zeos. I have a TDBgrid and DataSet.
I have a "Delete" function to delete selected Rows of the DBGrid.
If I Ctlr-Left-click to select Row (or Rows) it all works fine, but...
if I use the Vertical Scrollbar slider to move to the top of the DataSet then it shows the first Row in the select color.
If do not click the top line, (it already looks selected) then click "Delete" it crashes. Stepping through the code, at the first line SelectedRows.Count displays "1" but then at the Bookmark line I get a "Bookmark not found error" If I first click on the already selected Row after using the slider, then this does not crash.
for i:=0 to dbgridAddr.SelectedRows.Count-1 do
begin
dbgridAddr.DataSource.DataSet.GotoBookmark(pointer(dbgridAddr.SelectedRows.Items[i]));
How can I fix this ?
Thanks
A bit late to answer I guess, but maybe someone else can find it useful. The problem is that as you click within the boundaries of a DbGrid, a row shows up as selected even though it is not .
Add this to the OnDrawColumnCell event handler of your DBGrid:
procedure TForm1.DBGrid1DrawColumnCell(Sender: TObject; const Rect: TRect;
DataCol: Integer; Column: TColumn; State: TGridDrawState);
begin
// Only highlight the row if it is actually selected
if TDBGrid(Sender).SelectedRows.CurrentRowSelected then
begin
TDBGrid(Sender).Canvas.Brush.Color := clHighlight;
TDBGrid(Sender).Canvas.Font.Style := Font.Style + [fsBold];
TDBGrid(Sender).Canvas.Font.Color := clHighlightText;
end
else
begin
TDBGrid(Sender).Canvas.Brush.Color := clBtnFace;
TDBGrid(Sender).Canvas.Font.Style := Font.Style - [fsBold];
TDBGrid(Sender).Canvas.Font.Color := clWindowText;
end;
// Commit drawing
TDBGrid(Sender).DefaultDrawColumnCell(Rect, DataCol, Column, State);
end;
Add a block like this if you want to be able to see the cursor position in the grid when using the arrow keys
else if (gdSelected in State) then
begin
TDBGrid(Sender).Canvas.Brush.Color := clBtnFace;
TDBGrid(Sender).Canvas.Font.Style := Font.Style + [fsBold];
TDBGrid(Sender).Canvas.Font.Color := clWindowText;
end
Delphi 5:
You wrote:
if I use the Vertical Scrollbar slider to move to the top of the DataSet then it shows the first Row in the select color.
Even if it looks that way. This does not mean that it is also evaluated as marked.
You can test it with:
if dbgridAddr.SelectedRows.CurrentRowSelected then
ShowMessage('selected') else
ShowMessage('NOT selected');
Description
Position markers are not automatically removed from the list when records are deleted from the dataset.
It follows that some position markers may be invalid.
dbgridAddr.SelectedRows.Refresh;
Refresh to make sure that the list contains only valid entries.
Refresh trying to locate all records in the dataset that appear as a position marker in the Items property array.
All position marker for which there is no equivalent in the amount of data will be deleted.
If the position marker is invalid , Refresh returns a value of True and makes the DBGrid-object invalid so that a redraw is triggered, in which case all invalid records are deleted.
If all the position marker in the list should be valid, Refresh returns a value of False.
Never delete items ​​from lists with this construction.
for i:=0 to whatEver.Count-1 do
whatEver.delete(i);
e.g. Consider a list with 10 items on.
whatEver = 0 .. 9
If we now in the "for loop" with i = 1 do whatEver.delete(i);,
With this we delete the second item.
Now whatEver is only 0 .. 8 .
The loop is initialized to run through 0 to 9. Now you can understand if i = 9 then with whatEver.delete(i); attempts to access whatEver outside of 0 .. 8
This leads to errors.
Another example.
You delete incorrect records.
We will assume.
Before the lopp you've identified the following items (data record) - number to delete.
#3 , #6 , #8
for i:=0 to whatEver.Count-1 do
if (i=3) OR (i=6) OR (i=8) then whatEver.delete(i);
if i=3 then following is executed whatEver.delete(3);
afterwards
row 4 is now row 3
row 5 is now row 4
row 6 is now row 5
and so on
now with
if... OR (i=6) then whatEver.delete(6);
you delete the wrong item, the previous row 7 !
Also the bookmark pointer refers to #6, without refresh.
Please don't post now it is better to compare the content.
for i:=0 to whatEver.Count-1 do
if (whatEver[i] = 'blue') OR (whatEver[i] = 'green') OR (whatEver[i] = 'red')
then whatEver.delete(i);
I know that, it's just an example to show what happens when you delete items from the sequence out.
Do it better this way:
for i:= whatEver.Count-1 downto 0 do
whatEver.delete(i);
So that it is started from the end with the delete. Lower items keep their validity.
Edit:
I don't know what event of DBGrid you are using?
To test that there is no selection, only with a scroll.
Close your App und restart, do nothing only scroll the DBGrid.
Do not click into the DBGrid !!
Then press your testbutton.
procedure TForm1.Button2Click(Sender: TObject);
begin
if DBGrid1.SelectedRows.CurrentRowSelected then
begin
ShowMessage('selected');
end else begin
if DBGrid1.SelectedRows.Count>0 then
ShowMessage(' CurrentRow NOT selected'+#13#10+
'A part in your code must have select another row.')
else
ShowMessage('NOT selected');
end;
end;

Resources