Hide Horizontal Scrollbar from TListView - delphi

I am facing a strange problem when removing the horizontal scrollbar from TListView.
procedure TForm1.listDataResize(Sender: TObject);
begin
ShowScrollBar(listData.Handle, SB_HORZ, False);
end;
When using down or up arrow keys, then Column header Second and beyond is erased, when i resize the column manually then it is displayed back. When i remove the code from listDataResize then this problem no more occurs.
I just want to remove the horizontal scroll-bar from appearing in the ListView. As above code is working fine, the only thing bothering me is why second and beyond column headers are erased.

I don't know why it was happening, I deleted the current form holding TListView and created a new Form not touched any property of the form except Caption of the form and dropped the TListView once again.
ListView.RePaint;
ListView.Refresh;
Now it is no-more erasing the column header. I have not touched any property like double buffering etc. Working good.

Related

How can I add a caption/text to my csExDropDownList Combobox in Delphi?

I'm currently trying to create a combobox that has a "caption". By caption I mean the text that you see when you haven't clicked on it yet or if you are choosing an option.
Before I added the csExDropDownList it worked fine, but I wanted it to be ReadOnly. Now when I edit the Text property, it instantly gets deleted. I thought about using a TLabel in front of the combobox and making it dissapear the moment I chose a dropdown, but the TLabel is always in the background. I also tried with the TStaticText component, but that leaves a different colored background in front of the combobox which looks bad.
If I was unable to explain with words what I'm trying to edit/wanted to add a text to, this is what I mean:
I've found a workaround to my problem. I added a third dropdown with the index of 0. Now in properties I put the ItemIndex to 0 which means that it will be displayed similar to the Text property. When I interact with either QuickSort or InsertSort I delete Index 0.
My code looks like this:
procedure TSorterForm.AlgorithmCbxChange(Sender: TObject);
begin
if (AlgorithmCbx.Text <> 'Choose Algorithm...') and not IsAlgorithmSelected then begin
AlgorithmCbx.Items.Delete(0);
IsAlgorithmSelected:= true;
end;
end;
Obviously not perfect so it'd be great if you could tell me how to improve this.

How do you right justify DBGrid titles when using a FDMemtable in Delphi?

I can't seem to get the fixed row Titles in a DBGrid to align right justified when using a FDMemtable. Whenever I set the Field alignment to taRightJustify it right justifies the data cells perfectly. However, the DBGrid titles are always left justified.
What's even more frustrating is I can set the corresponding DBGrid column title alignment to taRightJustify and it appears perfectly fine in the IDE. But when I run the program the column title shows as left justified.
Has anyone found a way to make DBGrid column titles stay right justified when using a FDMemtable?
BTW, this also happens with taCenter. The data cells align centered but the titles stay left justified.
PEBKAC
The issue was of my own making. I did not invoke the DBGrid Columns Editor and add all the fields. Instead, I was using the "Structure" pane and getting to the DBGrid columns that way. Although the Structure pane allowed me to modify the column titles this was only temporary and did not persist when the program was run.
I can't reproduce the issue using a TFDMemTable either.
I dropped a TFDMemTable, TDataSource, and TDBGrid on a new VCL application's main form, connected them as usual (the grid's datasource set to DataSource1, the datasource's DataSet set to FDMemTable1), and then added the below code to the form's OnCreate event:
procedure TForm3.FormCreate(Sender: TObject);
begin
FDMemTable1.FieldDefs.Add('ID', ftInteger, 0, True);
FDMemTable1.FieldDefs.Add('LastName', ftString, 20);
FDMemTable1.FieldDefs.Add('FirstName', ftString, 20);
FDMemTable1.FieldDefs.Add('Salary', ftCurrency);
FDMemTable1.CreateDataSet;
FDMemTable1.Active := True;
FDMemTable1.AppendRecord([1, 'Smith', 'John', 30000]);
FDMemTable1.AppendRecord([2, 'Jones', 'Jane', 40000]);
FDMemTable1.AppendRecord([3, 'Doe', 'David', 2500]);
DBGrid1.Columns[3].Alignment := TAlignment.taRightJustify;
DBGrid1.Columns[3].Title.Alignment := TAlignment.taRightJustify;
end;
It also works correctly if I set everything up at designtime. Repeat the same setup steps I used above, but instead of using the code, use the following steps:
Select FDMemTable1 in the Object Inspector. At the bottom of the OI, click the LoadFromFile link, and navigate to the BDS Samples data folder (by default, in C:\Users\Public\Public Documents\Embarcadero\Studio\17.0\Samples\Data) and select animals.fds. (No specific reason for choosing that one, except it has a numeric field we can use for testing.)
Right-click on the DBGrid, and choose Columns Editor, or click the ellipsis button on the DBGrid.Columns property in the Object Inspector. Right-click in the Columns Editor and choose Add all fields.
Select either the Size or Weight column, expand it's Title property, and set Alignment to taRightJustify.
Run the application. The column you modified in step #3 above has a right-aligned title. (Here I used the Size column.)
The code below works for me in Seattle. I'm using a TClientDataSet rather than a TFDMemTable, but I can't see that that would make any difference.
If you have persistent columns defined on your DBGrid, you can also set a column's title alignment via the Object Inspector - use it to select the column, then expand its Title node and you can set the title alignment there.
procedure TForm1.CDS1AfterOpen(DataSet: TDataSet);
var
i : Integer;
begin
for i := 0 to DBGrid1.Columns.Count - 1 do
DBGrid1.Columns[i].Title.Alignment := taRightJustify;
end;
Btw, if you think you're setting the alignment in the OI but it's getting ignored, see if you can find out why, as follows:
Make sure your form is saved, then right-click on it and select View as text. Then, in the IDE editor window, you can see whether the Alignment property is saved as you've specified in the OI. Use the editor context menu to return to viewing the form as a form.
Add an override of the form's Loaded method as I've described in a comment. With a breakpoint on the inherited in Loadeds body, you can inspect the Alignment value before and after inherited is called.
Why am I suggesting looking into Loaded? Well, it is called after a form is streamed in from the DFM and is the routine where the run-time system finishes setting up the form. Sometimes, admittedly very rarely, another component (usually a 3rd-party one) misbehaves and causes strange behaviour of the properties of other compononents.

First use of TListView and TTreeView does not show data

I have only one form in my application, where I insert a frame accordingly the user action.
This form is inserted in a TScrollBox, since it sometimes has a width bigger than the screen/window.
I have one or more TListViews on the frame, and many TEdits.
When running the application and opening any frame, one or more TListView are not filled in. By debug I see the data is pulled from the SQL. TEdits are filled in. Moving the SQL cursors gets all TEdits updated accordingly.
The closing this frame and opening again (or any other) then it start showing the data on the TListView.
I have not found any correlation that make sense. Apparently there is some kind of initialization missing. Not all TListView are empty, in some frames I have 4 or 5 of them and it show 2 with data, the others are empty.
EDIT: I have changed the title of this question, since I have noted that the problem seems not be related to the LiveBindings primarly, but seems to be related to some kind of initialization of the TListView on other lists.
I made a new test and see that TTreeView is also having the same problem, showing totally out of order the data, only at first time. If I previouslly opens something else it works fine, if I close and open the frame with the TTreeview the second time is ok.
In this image I show the TreeView messed:
It should not have all that spaces and some of the nodes are overlapped.
My application has only one form, and everything are frames that are created as parent of a TScrollBox.
With Delphi XE5 the issues of TScrollBox were many, I had to upgrade to XE6.
Many things start working with XE6, however there is still a little problem with TScrollBox:
There is a need to call ApplyStyleLookup, after the frame is inserted and parented to the scroll, to make the initialization. That makes the TListView and TTreeView works fine since the very first time.
constructor TFrameBase.Create(AOwner: TComponent);
begin
inherited;
Align := TAlignLayout.Left;
Parent := AOwner as TFmxObject;
if (AOwner is TScrollBox) then
(AOwner as TScrollBox).ApplyStyleLookup;
end;
This is my frame constructor. This fixed all the problems.

VirtualTreeview enabling and disabling columns

I have a VirtualTreeView which has some columns initially hidden (coVisible is not present).
After enabling them (adding coVisible to the column Options) a strange thing happens - column appears but overlaps with previous column. I can fix the problem by changing width to 1 pixel smaller, then back to original width of the column which forces some repaint which then displays column correctly.
Is there something I need to do additionally except adding coVisible to make the columns repaint properly?
Use:
VTV.Header.Columns.BeginUpdate;
try
// Enable or Disable columns...
finally
VTV.Header.Columns.EndUpdate;
end;
This should keep the Header.Columns in sync.

How to avoid TDbgrid scrolling when returning to a previous location

In the code below, we do some operations (not deletions) on some selected rows.
However, sometimes, when finished, the top selected row has scrolled so that it is displayed 1/2 way down the grid. Is there a way to avoid this scrolling? (If my code to traverse the selected row below is improper for some unrelated reason, I welcome corrections.)
Function TForm.DoSomethingToSelectedRows;
var
KeyAtStart: Integer;
begin
Result := TRUE;
KeyAtStart := DataSet.FieldByName('Key').AsInteger;
DataSet.DisableControls;
DataSet.First;
try
while Result AND (NOT DataSet.EOF) do DataSet
begin
if DBGrid1.SelectedRows.CurrentRowSelected then
Result := ... do something ...
fMPODataTls.GetDS.Next;
end;
finally
DataSet.Locate('Key', KeyAtStart, []); // re-position where we started
DataSet.EnableControls;
end;
end;
Before looping through the dataset, you can keep note of the top row that the grid is displaying and the number of total records that is displayed. With this information, after you relocate the record, you can position the record to the exact row by moving either to the top or to the bottom and then moving back again.
You can carry out the moving by MoveBys. Unfortunately the Row and RowCount properties of TDBGrid is protected, for that you have to use what is widely known as 'protected hack'.
There's code example in this answer, together with checking bookmarks, so that you don't end up on a wrong record.
There is no guarantee that the current record in your grid is exactly positioned at the center of the visible rows, but doing a Locate when it has scrolled out of sight will make it (the new current record) the middle row of the grid, hence the apparent scrolling.
If you want to re-position the grid as it was, you have to memorize which record is at the top row.
If you are using a TClientDataset, you don't have to mess with the user's cursor, you can clone it and do your edits there.
If I have DBGrid1 linked to ClientDataSet1, and I have the cursor on row 5 of the DBGrid (and the ClientDataSet) and within view of the the first row, and delete the first row using a cloned cursor like below, I'd see the first row disappear and my selected row would go up by one row height.
Function TForm.DeleteFirstRow;
var
myCDS: TClientDataSet;
begin
myCDS := myCDS.Create(nil);
try
myCDS.CloneCursor(ClientDataSet1, False);
myCDS.First;
myCDS.Delete;
finally
myCDS.Free;
end;
If I was scrolled all the way down to row 500 or so, out of view of the first row, and executed it again, the selected row would not move at all in the grid.

Resources