窗体上放一个 BitBtn1, 设置其属性 Kind 的值为 bkClose; 然后运行看看...
结果是: 不仅自动更改了标题、图标, 并且还真的有了关闭窗口的功能.
实话说, 这之前我不知道这个小功能.
TBitBtn 的 Kind 属性对应的是一个枚举:
TBitBtnKind = (bkCustom, bkOK, bkCancel, bkHelp, bkYes, bkNo, bkClose, bkAbort, bkRetry, bkIgnore, bkAll);
再试其他值, 除了图标的变化外, 貌似没有其他功能了, 为什么 bkClose 可以关闭窗口?
代码追踪到 TBitBtn 重写的 Click 方法, 就明白了:
procedure TBitBtn.Click; var Form: TCustomForm; Control: TWinControl; begin case FKind of bkClose: begin Form := GetParentForm(Self); if Form <> nil then Form.Close else inherited Click; end; bkHelp: begin Control := Self; while (Control <> nil) and (Control.HelpContext = 0) do Control := Control.Parent; if Control <> nil then Application.HelpContext(Control.HelpContext) else inherited Click; end; else inherited Click; end; end;
看来不只是 bkClose, 还有 bkHelp 也赋予了功能, 当然这得先给窗体关联了帮助文件才行.
那其他呢? 譬如 bkOK、bkCancel 等等, 难道只是更换个图标那么简单?
当代码追踪到:
procedure TBitBtn.SetKind(Value: TBitBtnKind); begin ... ModalResult := BitBtnModalResults[Value]; ... end;
原来 TBitBtn 不同的 Kind 属性决定着其 ModalResult 的值, 并且根据 BitBtnModalResults 的定义, 知道了 Kind 与 ModalResult 的对应关系:
bkCustom { ModalResult = 0 } bkOK { ModalResult = 1 } bkCancel { ModalResult = 2 } bkHelp { ModalResult = 0 } bkYes { ModalResult = 6 } bkNo { ModalResult = 7 } bkClose { ModalResult = 0 } bkAbort { ModalResult = 3 } bkRetry { ModalResult = 4 } bkIgnore { ModalResult = 5 } bkAll { ModalResult = 8 }
什么是 ModalResult, 这是模式窗口(用 ShowModal 方法打开的窗口)的返回值.
这个 ModalResult 不是 TBitBtn 的吗? 和窗口有什么关系? 继续追踪代码:
procedure TCustomButton.Click; var Form: TCustomForm; begin Form := GetParentForm(Self); if Form <> nil then Form.ModalResult := ModalResult; inherited Click; end;
原来在按钮点击时, 按钮的 ModalResult 值就付给了窗体的同名属性.
对模式窗口来讲, 如果给 ModalResult 赋的值大于 0, 模式窗口将即刻关闭, 测试下:
//代码功能: //点击按钮弹出一个模式窗口; //在模式窗口中画有 11 个 TBitBtn 按钮, 分别设置了不同的 Kind 属性; //鼠标指向按钮, Hint 提示出按钮的 ModalResult 值. unit Unit1; interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls, Buttons; { TBitBtn 在 Buttons 单元 } type TForm1 = class(TForm) Button1: TButton; procedure Button1Click(Sender: TObject); end; var Form1: TForm1; implementation {$R *.dfm} procedure TForm1.Button1Click(Sender: TObject); const w = 75; h = 25; a = 8; b = 8; var ModalForm: TForm; i,x,y: Integer; begin Application.HintColor := clRed; ModalForm := TForm.Create(Application); ModalForm.ClientWidth := (w + a) * 6 + a; ModalForm.ClientHeight := (h + b) * 2 + b; ModalForm.Caption := 'ModalFormTest'; x := a; y := b; for i := 0 to 10 do begin with TBitBtn.Create(ModalForm) do begin Parent := ModalForm; Kind := TBitBtnKind(i); Hint := Format(' %d ', [ModalResult]); ShowHint := True; SetBounds(x, y, w, h); Inc(x, w + a); if i = 5 then begin x := a; Inc(y, h + b); end; end; end; ModalForm.ShowModal; end; end.
点击按钮后, 弹出窗口的效果图如下:
其中有 3 个按钮的值是 0, 也就是说点击它们窗口不应该关闭, 但点击 Kind 属性是 bkClose 的按钮窗口也还是关闭了, 尽管它的 ModalResult 值也是 0.
这不矛盾, 又回到刚开始的问题了, 这是 TBitBtn 重写的 Click 方法赋予的功能.
其他按钮行吗? 譬如: TButton.
看了一下, TButton 根本没有 Kind 属性, 但它有 ModalResult 属性; 这样我们也可以:
procedure TForm1.Button1Click(Sender: TObject); var frm: TForm; begin frm := TForm.Create(Application); with TButton.Create(frm) do begin Caption := '确认'; ModalResult := mrOk; {1} Parent := frm; Left := 100; top := 40; end; with TButton.Create(frm) do begin Caption := '取消'; ModalResult := mrCancel; {2} Parent := frm; Left := 100; top := 80; end; frm.ShowModal; frm.Free; end;
其他控件行吗? 譬如 TEdit.
查了一下, 它没有 ModalResult 属性, 但它所在的窗口有啊.
譬如下面的例子, 在模式窗口的 Edit 中输入 "Exit" 即可关闭该模式窗口:
unit Unit1; interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls; type TForm1 = class(TForm) Button1: TButton; procedure Button1Click(Sender: TObject); procedure EditChange(Sender: TObject); end; var Form1: TForm1; implementation {$R *.dfm} procedure TForm1.Button1Click(Sender: TObject); var frm: TForm; begin frm := TForm.Create(Application); with TEdit.Create(frm) do begin Parent := frm; Left := 100; top := 40; CharCase := ecLowerCase; OnChange := EditChange; // end; frm.ShowModal; frm.Free; end; { 这是供动态建立的 TEdit 的 OnChange 事件调用的方法 } procedure TForm1.EditChange(Sender: TObject); begin if TEdit(Sender).Text = 'exit' then GetParentForm(TEdit(Sender)).ModalResult := 1; end; end.