2010. december 21., kedd
Create a Combobox winthin in a Stringgrid
Problem/Question/Abstract:
How to dynamically create a Combobox within a Cell of a StringGrid
Answer:
You need a descendent of TStringgrid that properly reflects WM_COMMAND to embedded controls. The standard grid does not do it since it is not intended to play parent to other controls.
Additionaly simply declare a Set- and GetMethod to access the items of die combobox
unit BWControlStringGrid;
interface
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
Grids, stdctrls;
type
TBWControlStringGrid = class(TStringGrid)
private
fComboBox: TCombobox;
procedure WMCommand(var msg: TWMCommand); message WM_COMMAND;
procedure DblClick; override;
procedure Click; override;
procedure RelocateComboBox;
procedure HideCombobox;
protected
procedure KeyPress(var Key: Char); override;
public
constructor Create(AOWner: TComponent); override;
destructor Destroy; override;
published
end;
procedure Register;
implementation
procedure Register;
begin
RegisterComponents('hEaDRoOm', [TBWControlStringGrid]);
end;
procedure TBWControlStringGrid.WMCommand(var msg: TWMCommand);
begin
if EditorMode and (msg.Ctl = fComboBox.Handle) then
inherited
else if msg.Ctl <> 0 then
msg.result :=
SendMessage(msg.ctl, CN_COMMAND,
TMessage(msg).wparam,
TMessage(msg).lparam);
end;
procedure TBWControlStringGrid.KeyPress(var Key: Char);
begin
if Key = #13 then
RelocateComboBox
else
HideCombobox;
end;
procedure TBWControlStringGrid.DblClick;
begin
inherited;
RelocateComboBox;
end;
procedure TBWControlStringGrid.Click;
begin
inherited;
HideCombobox;
end;
procedure TBWControlStringGrid.RelocateComboBox;
begin
fcombobox.boundsrect := CellRect(Selection.Left, Selection.Top);
fcomboBox.Visible := TRUE;
fcombobox.setfocus;
end;
procedure TBWControlStringGrid.HideCombobox;
begin
fcomboBox.Visible := false;
end;
constructor TBWControlStringGrid.Create(AOWner: TComponent);
begin
inherited Create(Aowner);
fComboBox := TComboBox.Create(self);
fComboBox.Parent := self;
fComboBox.Visible := FALSE;
Options := Options - [goRangeSelect];
end;
destructor TBWControlStringGrid.Destroy;
begin
fComboBox.Destroy;
inherited destroy;
end;
end.
This is great, but is just the skeleton, of course..
There needs to be some mechansim for getting the combo's text/selection into the cell, also for relaying the cells contents into the combo in the first place.
This can be done in the Hide and Relocate methods.
The whole thing can get unwieldy if you add a lot of get/set methods for updating the combos dropdownlist, etc, so making the Combo a Public property, rather than just a private field might help with that - the onus is then on the programmer to deal with the combo directly - it is unlikely, for instance, that the dropdownlist would be the same for each column.
Or two new events could be triggered - OnHide and OnRelocate
eg:
TComboVisibleChangeEvent = procedure(Sender: TObject; Row, Col: Longint; Combo:
TComboBox; AllowVisibleChange: boolean) of object
fOnHide: TComboVisibleChangeEvent;
fOnRelocate: TComboVisibleChangeEvent;
etc.
This way the Combo would be make public when needed. When the Relocate fires, the dropdownlist could be repopulated, etc
Just ideas for whoever wants them!
Feliratkozás:
Megjegyzések küldése (Atom)
Nincsenek megjegyzések:
Megjegyzés küldése