示例:字体对话框 说明: 例如,考虑一个图形用户界面中对话框的实现。对话框使用一个窗口来展现一系列的窗口组件,如按钮、菜单和输入域等。 FontDialogDirector可作为一个对话框中的窗口组件间的中介者。FontDialogDirector对象知道对话框中的各窗口组件,并协调它们之间的交互。它充当窗口组件间通信的中转中心。 代码: unit uFontDialog; interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, ExtCtrls, StdCtrls, Spin; type TDialogDirector = class; {组件} TWidget = class private FDirector: TDialogDirector; FControl: TControl; function GetHeight: Integer; function GetLeft: Integer; function GetTop: Integer; function GetWidth: Integer; procedure SetHeight(const Value: Integer); procedure SetLeft(const Value: Integer); procedure SetParent(const Value: TWidget); procedure SetTop(const Value: Integer); procedure SetWidth(const Value: Integer); protected procedure DoMouseDown(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer); public constructor Create(ADirector: TDialogDirector); destructor Destroy; override; //--- procedure Changed(); virtual; procedure HandleMouse(event: TMouseButton); virtual; //--- property Left: Integer read GetLeft write SetLeft; property Top: Integer read GetTop write SetTop; property Height: Integer read GetHeight write SetHeight; property Width: Integer read GetWidth write SetWidth; property Parent: TWidget write SetParent; end; TFontDialog = class(TWidget) private FForm: TForm; function GetText: string; procedure SetText(const Value: string); public constructor Create(ADirector: TDialogDirector); //--- function ShowModal: Integer; procedure Close; //--- property Text: string read GetText write SetText; end; TLabel1 = class(TWidget) private FLabel: TLabel; function GetFont: TFont; function GetText: string; procedure SetText(const Value: string); public constructor Create(ADirector: TDialogDirector); //--- property Text: string read GetText write SetText; property Font: TFont read GetFont; end; {输入域} TEntryField1 = class(TWidget) private FEdit: TEdit; function GetText: string; procedure SetText(const Value: string); public constructor Create(ADirector: TDialogDirector); //--- procedure HandleMouse(event: TMouseButton); override; //--- property Text: string read GetText write SetText; end; {列表框} TListBox1 = class(TWidget) private FListBox: TListBox; function GetSelection(): string; procedure SetList(const Value: TStrings); public constructor Create(ADirector: TDialogDirector); //--- procedure HandleMouse(event: TMouseButton); override; //--- property Selection: string read GetSelection; property List: TStrings write SetList; end; TPanel1 = class(TWidget) private FPanel: TPanel; public constructor Create(ADirector: TDialogDirector); end; TRadioButton1 = class(TWidget) private FRadioButton: TRadioButton; function GetChecked: Boolean; procedure SetChecked(const Value: Boolean); procedure SetText(const Value: string); public constructor Create(ADirector: TDialogDirector); //--- procedure HandleMouse(event: TMouseButton); override; //--- property Text: string write SetText; property Checked: Boolean read GetChecked write SetChecked; end; TSpinEdit1 = class(TWidget) private FSpinEdit: TSpinEdit; procedure DoChange(Sender: TObject); function GetValue: LongInt; procedure SetValue(const Value: LongInt); public constructor Create(ADirector: TDialogDirector); //--- property Value: LongInt read GetValue write SetValue; end; TCheckBox1 = class(TWidget) private FCheckBox: TCheckBox; procedure SetText(const Value: string); public constructor Create(ADirector: TDialogDirector); //--- property Text: string write SetText; end; TButton1 = class(TWidget) private FButton: TButton; procedure SetText(const Value: string); public constructor Create(ADirector: TDialogDirector); //--- procedure HandleMouse(event: TMouseButton); override; //--- property Text: string write SetText; end; {导控者} TDialogDirector = class protected procedure CreateWidgets(); virtual; abstract; public procedure ShowDialog(); virtual; procedure WidgetChanged(theChangedWidget: TWidget); virtual; abstract; end; TFontDialogDirector = class(TDialogDirector) private FFontDialog: TFontDialog; FFontLabel, FFamilyLabel, FWeightLabel, FSlantLabel, FSizeLabel: TLabel1; FFontName: TEntryField1; FFontList: TListBox1; FWeightPanel, FSlantPanel: TPanel1; FFontWeight1, FFontWeight2, FFontWeight3: TRadioButton1; FFontSlant1, FFontSlant2, FFontSlant3: TRadioButton1; FFontSize: TSpinEdit1; FCondensed: TCheckBox1; FOk: TButton1; FCancel: TButton1; protected procedure CreateWidgets; override; public destructor Destroy; override; //--- procedure WidgetChanged(theChangedWidget: TWidget); override; end; procedure Test; implementation procedure Test; var ADirector: TFontDialogDirector; begin ADirector := TFontDialogDirector.Create; ADirector.ShowDialog; ADirector.Free; end; procedure TDialogDirector.ShowDialog(); begin Self.CreateWidgets; end; constructor TWidget.Create(ADirector: TDialogDirector); begin FDirector := ADirector; end; destructor TWidget.Destroy; begin FControl.Free; //--- inherited; end; procedure TWidget.Changed(); begin FDirector.WidgetChanged(self); end; procedure TWidget.DoMouseDown(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer); begin self.HandleMouse(Button); end; function TWidget.GetHeight: Integer; begin Result := FControl.Height; end; function TWidget.GetLeft: Integer; begin Result := FControl.Left; end; function TWidget.GetTop: Integer; begin Result := FControl.Top; end; function TWidget.GetWidth: Integer; begin Result := FControl.Width; end; procedure TWidget.HandleMouse(event: TMouseButton); begin //.... end; procedure TWidget.SetHeight(const Value: Integer); begin FControl.Height := Value; end; procedure TWidget.SetLeft(const Value: Integer); begin FControl.Left := Value; end; procedure TWidget.SetParent(const Value: TWidget); begin FControl.Parent := TWinControl(Value.FControl); end; procedure TWidget.SetTop(const Value: Integer); begin FControl.Top := Value; end; procedure TWidget.SetWidth(const Value: Integer); begin FControl.Width := Value; end; constructor TListBox1.Create(ADirector: TDialogDirector); begin inherited; //--- FListBox := TListBox.Create(nil); FListBox.OnMouseDown := self.DoMouseDown; //--- FControl := FListBox; end; function TListBox1.GetSelection(): string; var i: Integer; begin with FListBox do begin Result := ''; for i := 0 to (Items.Count - 1) do begin if Selected[i] then Result := Items.Strings[i]; end; end; end; procedure TListBox1.HandleMouse(event: TMouseButton); begin if event = mbLeft then Self.Changed(); end; procedure TListBox1.SetList(const Value: TStrings); begin FListBox.Items := Value; end; constructor TEntryField1.Create(ADirector: TDialogDirector); begin inherited; //--- FEdit := TEdit.Create(nil); FControl := FEdit; end; function TEntryField1.GetText: string; begin Result := FEdit.Text; end; procedure TEntryField1.HandleMouse(event: TMouseButton); begin //.... end; procedure TEntryField1.SetText(const Value: string); begin FEdit.Text := Value; end; constructor TButton1.Create(ADirector: TDialogDirector); begin inherited; //--- FButton := TButton.Create(nil); FButton.OnMouseDown := self.DoMouseDown; //--- FControl := FButton; end; procedure TButton1.HandleMouse(event: TMouseButton); begin if event = mbLeft then Self.Changed(); end; procedure TButton1.SetText(const Value: string); begin FButton.Caption := Value; end; procedure TFontDialogDirector.CreateWidgets; const CNT_Left = 40; CNT_Height = 20; CNT_RowSize = 10; var ATop, ALeft: Integer; begin FFontDialog := TFontDialog.Create(self); with FFontDialog do begin Text := 'Font Chooser'; Width := 350; Height := 500; end; //--- FFontLabel := TLabel1.Create(self); with FFontLabel do begin Parent := FFontDialog; Top := 15; Left := 10; Text := 'The quick brown fox…'; //--- ATop := Top + Height + 20 + CNT_RowSize; ALeft := Left; end; //--- FFamilyLabel := TLabel1.Create(self); with FFamilyLabel do begin Parent := FFontDialog; Top := ATop; Left := ALeft; Text := 'Family'; end; //--- FFontName := TEntryField1.Create(self); with FFontName do begin Parent := FFontDialog; Top := ATop; Left := ALeft + CNT_Left; Width := 250; //--- ATop := Top + Height + CNT_RowSize; end; //--- FFontList := TListBox1.Create(self); with FFontList do begin Parent := FFontDialog; Top := ATop; Left := ALeft + CNT_Left; Width := 250; Height := 100; //--- ATop := Top + Height + CNT_RowSize; end; //--- FWeightLabel := TLabel1.Create(self); with FWeightLabel do begin Parent := FFontDialog; Top := ATop; Left := ALeft; Text := 'Weight'; end; //--- FWeightPanel := TPanel1.Create(self); with FWeightPanel do begin Parent := FFontDialog; Top := ATop; Left := ALeft + CNT_Left; Width := 200; Height := 20; //--- ATop := Top + Height + CNT_RowSize; end; //--- FFontWeight1 := TRadioButton1.Create(self); with FFontWeight1 do begin Parent := FWeightPanel; Top := 0; Left := 0; Text := 'medium'; end; //--- FFontWeight2 := TRadioButton1.Create(self); with FFontWeight2 do begin Parent := FWeightPanel; Top := 0; Left := FFontWeight1.Left + 60; Text := 'bold'; end; //--- FFontWeight3 := TRadioButton1.Create(self); with FFontWeight3 do begin Parent := FWeightPanel; Top := 0; Left := FFontWeight2.Left + 60; Text := 'demibold'; end; //--- FSlantLabel := TLabel1.Create(self); with FSlantLabel do begin Parent := FFontDialog; Top := ATop; Left := ALeft; Text := 'Slant'; end; //--- FSlantPanel := TPanel1.Create(self); with FSlantPanel do begin Parent := FFontDialog; Top := ATop; Left := ALeft + CNT_Left; Width := 200; Height := 20; //--- ATop := Top + Height + CNT_RowSize; end; //--- FFontSlant1 := TRadioButton1.Create(self); with FFontSlant1 do begin Parent := FSlantPanel; Top := 0; Left := 0; Text := 'roman'; end; //--- FFontSlant2 := TRadioButton1.Create(self); with FFontSlant2 do begin Parent := FSlantPanel; Top := 0; Left := FFontSlant1.Left + 60; Text := 'italic'; end; //--- FFontSlant3 := TRadioButton1.Create(self); with FFontSlant3 do begin Parent := FSlantPanel; Top := 0; Left := FFontSlant2.Left + 60; Text := 'oblique'; end; //--- FSizeLabel := TLabel1.Create(self); with FSizeLabel do begin Parent := FFontDialog; Top := ATop; Left := ALeft; Text := 'Size'; end; //--- FFontSize := TSpinEdit1.Create(self); with FFontSize do begin Parent := FFontDialog; Top := ATop; Left := ALeft + CNT_Left; Width := 50; end; //--- FCondensed := TCheckBox1.Create(self); with FCondensed do begin Parent := FFontDialog; Top := ATop; Left := FFontSize.Left + 60; Text := 'condensed'; //--- ATop := Top + Height + CNT_RowSize; end; //--- FCancel := TButton1.Create(self); with FCancel do begin Parent := FFontDialog; Top := ATop; Left := ALeft + 150; Text := 'Cancel'; end; //--- FOk := TButton1.Create(self); with FOk do begin Parent := FFontDialog; Top := ATop; Left := ALeft + 250; Text := 'Ok'; end; //--- FFontName.Text := '宋体'; FFontList.List := Screen.Fonts; FFontWeight2.Checked := True; FFontWeight2.Changed; FFontSlant2.Checked := True; FFontSlant2.Changed; FFontSize.Value := 21; //--- FFontDialog.ShowModal; end; destructor TFontDialogDirector.Destroy; //--- procedure _FreeWidget(AWidget: TWidget); begin if AWidget <> nil then AWidget.Free; end; begin _FreeWidget(FFontLabel); _FreeWidget(FFamilyLabel); _FreeWidget(FFontName); _FreeWidget(FFontList); _FreeWidget(FWeightLabel); _FreeWidget(FFontWeight1); _FreeWidget(FFontWeight2); _FreeWidget(FFontWeight3); _FreeWidget(FWeightPanel); _FreeWidget(FFontSlant1); _FreeWidget(FFontSlant2); _FreeWidget(FFontSlant3); _FreeWidget(FSlantPanel); _FreeWidget(FFontSize); _FreeWidget(FCondensed); _FreeWidget(FOk); _FreeWidget(FCancel); _FreeWidget(FFontDialog); //--- inherited; end; procedure TFontDialogDirector.WidgetChanged(theChangedWidget: TWidget); //--- procedure _SetFontName; var ASelection: string; begin ASelection := FFontList.Selection; //--- FFontName.Text := ASelection; FFontLabel.Font.Name := ASelection; end; begin if (theChangedWidget = FFontList) then _SetFontName else if (theChangedWidget = FFontWeight1) then FFontLabel.Font.Style := FFontLabel.Font.Style - [fsBold] else if (theChangedWidget = FFontWeight2) then FFontLabel.Font.Style := FFontLabel.Font.Style + [fsBold] else if (theChangedWidget = FFontWeight3) then FFontLabel.Font.Style := FFontLabel.Font.Style - [fsBold] else if (theChangedWidget = FFontSlant1) then FFontLabel.Font.Style := FFontLabel.Font.Style - [fsItalic] else if (theChangedWidget = FFontSlant2) then FFontLabel.Font.Style := FFontLabel.Font.Style + [fsItalic] else if (theChangedWidget = FFontSlant3) then FFontLabel.Font.Style := FFontLabel.Font.Style - [fsItalic] else if (theChangedWidget = FFontSize) then FFontLabel.Font.Size := FFontSize.Value else if (theChangedWidget = FOk) then begin ShowMessage('变更字体'); FFontDialog.Close; end else if (theChangedWidget = FCancel) then FFontDialog.Close; end; procedure TFontDialog.Close; begin FForm.Close; end; constructor TFontDialog.Create(ADirector: TDialogDirector); begin inherited; //--- FForm := TForm.Create(nil); with FForm do begin Font.Charset := GB2312_CHARSET; Font.Name := '宋体'; end; //--- FControl := FForm; end; function TFontDialog.GetText: string; begin Result := FForm.Caption; end; procedure TFontDialog.SetText(const Value: string); begin FForm.Caption := Value; end; constructor TLabel1.Create(ADirector: TDialogDirector); begin inherited; //--- FLabel := TLabel.Create(nil); FControl := FLabel; end; function TLabel1.GetFont: TFont; begin Result := FLabel.Font; end; function TLabel1.GetText: string; begin Result := FLabel.Caption; end; procedure TLabel1.SetText(const Value: string); begin FLabel.Caption := Value; end; function TFontDialog.ShowModal: Integer; begin Result := FForm.ShowModal; end; constructor TPanel1.Create(ADirector: TDialogDirector); begin inherited; //--- FPanel := TPanel.Create(nil); with FPanel do begin BevelOuter := bvNone; Caption := ''; end; //--- FControl := FPanel; end; constructor TRadioButton1.Create(ADirector: TDialogDirector); begin inherited; //--- FRadioButton := TRadioButton.Create(nil); FRadioButton.OnMouseDown := self.DoMouseDown; //--- FControl := FRadioButton; end; function TRadioButton1.GetChecked: Boolean; begin Result := FRadioButton.Checked; end; procedure TRadioButton1.HandleMouse(event: TMouseButton); begin if event = mbLeft then Self.Changed(); end; procedure TRadioButton1.SetChecked(const Value: Boolean); begin FRadioButton.Checked := Value; end; procedure TRadioButton1.SetText(const Value: string); begin FRadioButton.Caption := Value; end; constructor TSpinEdit1.Create(ADirector: TDialogDirector); begin inherited; //--- FSpinEdit := TSpinEdit.Create(nil); FSpinEdit.OnChange := self.DoChange; //--- FControl := FSpinEdit; end; procedure TSpinEdit1.DoChange(Sender: TObject); begin Self.Changed(); end; function TSpinEdit1.GetValue: LongInt; begin Result := FSpinEdit.Value; end; procedure TSpinEdit1.SetValue(const Value: LongInt); begin FSpinEdit.Value := Value; end; constructor TCheckBox1.Create(ADirector: TDialogDirector); begin inherited; //--- FCheckBox := TCheckBox.Create(nil); FControl := FCheckBox; end; procedure TCheckBox1.SetText(const Value: string); begin FCheckBox.Caption := Value; end; end.