我有一个动态代码,它在StringGrid单元格中创建一个comboBox,这个组合是在运行时创建的,我应该为它设置onChange事件。 我正在使用这个代码,但是这段代码引发异常,有人可以帮我 - 在TNotifyEvent中成为我的comboBoxOnChange方法吗?
procedure TForm1.gridSelectCell(Sender: TObject; ACol, ARow: Integer;
var CanSelect: Boolean);
var
R: TRect;
combo : TComboBox;
procedure comboBoxOnChange(Sender: TObject);
begin
combo.Visible := false;
combo.Free;
end;
begin
combo := TComboBox.Create(self);
combo.Parent := self;
//[DCC Error] Unit1.pas(57): E2010 Incompatible types: 'TNotifyEvent' and 'procedure, untyped pointer or untyped parameter'
combo.OnChange := comboBoxOnChange;
combo.Items.Add('Item1');
combo.Items.Add('Item2');
combo.Items.Add('Item3');
combo.Items.Add('Item4');
combo.Items.Add('Item5');
combo.Items.Add('Item6');
combo.Items.Add('Item7');
combo.Items.Add('Item8');
combo.Items.Add('Item9');
combo.Items.Add('Item10');
R := Grid.CellRect(ACol, ARow);
R.Left := R.Left + grid.Left;
R.Right := R.Right + grid.Left;
R.Top := R.Top + grid.Top;
R.Bottom := R.Bottom + grid.Top;
combo.Left := R.Left + 1;
combo.Top := R.Top + 1;
combo.Width := (R.Right + 1) - R.Left;
combo.Height := (R.Bottom + 1) - R.Top;
combo.Visible := True;
combo.SetFocus;
CanSelect := True;
end;
答案 0 :(得分:3)
如果手动声明并填写TMethod
记录,然后在将其分配给目标事件时键入 - 将其用作事件处理程序,则可以使用任何非类方法过程。此外,不是类的成员意味着缺少隐藏的Self
参数,因此您必须明确声明它。
在嵌套过程的情况下,只要过程不尝试从其包含过程访问任何内容,此方法就可以正常工作,因为当事件实际被触发时,这些变量将不再在范围内。
话虽如此,更大的问题是控件不能Free()
本身来自其自身事件之一,否则会出现AccessViolation错误。这是因为在事件处理程序退出后,RTL仍然需要访问该对象。因此,您必须延迟调用Free()
,直到事件处理程序退出为止,例如通过发布带有PostMessage()
的自定义窗口消息,以便它通过消息队列。
试试这个:
type
TForm1 = class(TForm)
//...
protected
procedure WndProc(var Message: TMessage); override;
//...
end;
const
APPWM_FREE_OBJECT = WM_APP + 100;
procedure TForm1.WndProc(var Message: TMessage);
begin
if Message.Msg = APPWM_FREE_OBJECT then
TObject(Message.LParam).Free
else
inherited;
end;
procedure TForm1.gridSelectCell(Sender: TObject; ACol, ARow: Integer; var CanSelect: Boolean);
var
combo : TComboBox;
M: TMethod;
//...
procedure comboBoxOnChange(Self: Pointer; Sender: TObject);
begin
TComboBox(Sender).Visible := false;
//combo.Free;
PostMessage(Form1.Handle, APPWM_FREE_OBJECT, 0, LPARAM(Sender));
end;
begin
combo := TComboBox.Create(Self);
combo.Parent := Self;
//...
M.Code := Addr(comboBoxOnChange);
M.Data := combo;
combo.OnChange := TNotifyEvent(M);
CanSelect := True;
end;
答案 1 :(得分:1)
无法使用嵌套过程作为事件处理程序,您必须将其设置为表单的方法:
type
TForm1 = class(...)
private
procedure comboBoxOnChange(Sender: TObject);
...
end
procedure TForm1.comboBoxOnChange(Sender: TObject);
var combo : TComboBox;
begin
combo := Sender as TComboBox;
combo.Visible := false;
combo.Free;
end;