Today I was considering how to improve the general look of one class of my programs. These have a dbgrid and several buttons, and whilst they are functional, they are somewhat old fashioned. As a picture is worth a thousand words, here is a screen shot of the main form of one of the programs (I should point out that these programs display personal data, which in the interests of privacy I am not going to show here, so I'm showing the form as it appears at design time. Imagine that the grid is populated).
The first improvement was to take all the buttons and place them on a gray panel
This is certainly better, but the real problem is the grid, which is "so Win 3.1". What can be done? Dispose of the grid! I decided to display the data in a listview control, which is where the fun begins. I need the listview to be displayed from right to left, which requires a magic code. Once I had done that, I discovered that the header of the listview considers itself to be autonomous; this resolutely stayed as left to right as the lines displayed right to left, making an ugly sight. More searching of the internet revealed how to get a pointer to the header of the listview, which was then fed the magic code. Success!
Of course, I couldn't leave things as they were; I had to figure out how to change the sort order data in the listview whenever a header was clicked. This turned out to be slightly easier than I thought. I also added code to allow editing (via a subform) of a row, and to display any change that might be made in the data. This required an extra query component to get the new data for the chosen record.
Here is the new screen (note that the header is still left to right):
And here is (some of) the code:
type
TForm1 = class(TForm)
lv: TListView;
Panel1: TPanel;
EditBtn: TBitBtn;
BitBtn2: TBitBtn;
SQLConnection1: TSQLConnection;
SQLQuery1: TSQLQuery;
qPerson: TSQLQuery;
procedure FormCreate(Sender: TObject);
procedure BitBtn2Click(Sender: TObject);
procedure EditBtnClick(Sender: TObject);
procedure FormActivate(Sender: TObject);
procedure lvColumnClick(Sender: TObject; Column: TListColumn);
private
LastSortedColumn: integer;
public
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
uses unit2;
Function SortByColumn (Item1, Item2: TListItem; Data: integer): integer; stdcall;
begin
case data of
0: Result:= AnsiCompareText (Item1.Caption, Item2.Caption);
1, 2: Result:= AnsiCompareText(Item1.SubItems[0], Item2.SubItems[0]);
3: if strtodate (Item1.SubItems[2]) < strtodate (Item2.SubItems[2])
then result:= 1
else result:= -1
end;
end;
procedure TForm1.FormCreate(Sender: TObject);
const
LVM_FIRST = $1000; // ListView messages
LVM_GETHEADER = LVM_FIRST + 31;
var
ListItem: TListItem;
header: thandle;
i: integer;
begin
header:= SendMessage (lv.Handle, LVM_GETHEADER, 0, 0);
SetWindowLong (header, GWL_EXSTYLE, GetWindowLong (header, GWL_EXSTYLE) or
WS_EX_LAYOUTRTL or WS_EX_NOINHERITLAYOUT);
SetWindowLong (lv.Handle, GWL_EXSTYLE, GetWindowLong (lv.Handle, GWL_EXSTYLE) or
WS_EX_LAYOUTRTL or WS_EX_NOINHERITLAYOUT);
lv.invalidate; // get the list view to display right to left
lv.items.beginupdate; // reduce flicker
with sqlquery1 do
begin
open;
while not eof do
begin
ListItem:= lv.Items.Add;
ListItem.Caption:= fieldbyname ('zehut').asstring;
for i:= 1 to 4 do ListItem.SubItems.Add (fields[i].asstring);
next
end;
close
end;
lv.Items.endupdate;
qPerson.Prepared:= true;
LastSortedColumn:= -1;
end;
procedure TForm1.lvColumnClick(Sender: TObject; Column: TListColumn);
begin
LastSortedColumn:= Column.Index;
TListView(Sender).CustomSort(@SortByColumn, Column.Index);
end;
procedure TForm1.FormActivate(Sender: TObject);
begin
lv.setfocus
end;
procedure TForm1.BitBtn2Click(Sender: TObject);
begin
close
end;
procedure TForm1.EditBtnClick(Sender: TObject);
var
flag: boolean;
id: longint;
i: integer;
begin
if lv.selected = nil then exit;
id:= strtoint (lv.selected.SubItems[3]);
with TGetDetails.Create (nil) do
try
flag:= execute (id);
finally
free
end;
if flag then
begin
with qPerson do
begin
params[0].asinteger:= id;
open;
lv.selected.Caption:= fieldbyname ('zehut').AsString;
for i:= 1 to 3 do lv.selected.subitems[i - 1]:= fields[i].asstring;
close
end
end;
lv.setfocus
end;
end.
TForm1 = class(TForm)
lv: TListView;
Panel1: TPanel;
EditBtn: TBitBtn;
BitBtn2: TBitBtn;
SQLConnection1: TSQLConnection;
SQLQuery1: TSQLQuery;
qPerson: TSQLQuery;
procedure FormCreate(Sender: TObject);
procedure BitBtn2Click(Sender: TObject);
procedure EditBtnClick(Sender: TObject);
procedure FormActivate(Sender: TObject);
procedure lvColumnClick(Sender: TObject; Column: TListColumn);
private
LastSortedColumn: integer;
public
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
uses unit2;
Function SortByColumn (Item1, Item2: TListItem; Data: integer): integer; stdcall;
begin
case data of
0: Result:= AnsiCompareText (Item1.Caption, Item2.Caption);
1, 2: Result:= AnsiCompareText(Item1.SubItems[0], Item2.SubItems[0]);
3: if strtodate (Item1.SubItems[2]) < strtodate (Item2.SubItems[2])
then result:= 1
else result:= -1
end;
end;
procedure TForm1.FormCreate(Sender: TObject);
const
LVM_FIRST = $1000; // ListView messages
LVM_GETHEADER = LVM_FIRST + 31;
var
ListItem: TListItem;
header: thandle;
i: integer;
begin
header:= SendMessage (lv.Handle, LVM_GETHEADER, 0, 0);
SetWindowLong (header, GWL_EXSTYLE, GetWindowLong (header, GWL_EXSTYLE) or
WS_EX_LAYOUTRTL or WS_EX_NOINHERITLAYOUT);
SetWindowLong (lv.Handle, GWL_EXSTYLE, GetWindowLong (lv.Handle, GWL_EXSTYLE) or
WS_EX_LAYOUTRTL or WS_EX_NOINHERITLAYOUT);
lv.invalidate; // get the list view to display right to left
lv.items.beginupdate; // reduce flicker
with sqlquery1 do
begin
open;
while not eof do
begin
ListItem:= lv.Items.Add;
ListItem.Caption:= fieldbyname ('zehut').asstring;
for i:= 1 to 4 do ListItem.SubItems.Add (fields[i].asstring);
next
end;
close
end;
lv.Items.endupdate;
qPerson.Prepared:= true;
LastSortedColumn:= -1;
end;
procedure TForm1.lvColumnClick(Sender: TObject; Column: TListColumn);
begin
LastSortedColumn:= Column.Index;
TListView(Sender).CustomSort(@SortByColumn, Column.Index);
end;
procedure TForm1.FormActivate(Sender: TObject);
begin
lv.setfocus
end;
procedure TForm1.BitBtn2Click(Sender: TObject);
begin
close
end;
procedure TForm1.EditBtnClick(Sender: TObject);
var
flag: boolean;
id: longint;
i: integer;
begin
if lv.selected = nil then exit;
id:= strtoint (lv.selected.SubItems[3]);
with TGetDetails.Create (nil) do
try
flag:= execute (id);
finally
free
end;
if flag then
begin
with qPerson do
begin
params[0].asinteger:= id;
open;
lv.selected.Caption:= fieldbyname ('zehut').AsString;
for i:= 1 to 3 do lv.selected.subitems[i - 1]:= fields[i].asstring;
close
end
end;
lv.setfocus
end;
end.
No comments:
Post a Comment