随笔 - 2146  文章 - 97 评论 - 11767 trackbacks - 253


窗体上放一个 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.

posted on 2010-01-16 13:22  万一  阅读(...)  评论(...编辑  收藏