📄 jvqdsadialogs.pas
字号:
function DSAQueueStore: TDSAQueueStorage;
//----------------------------------------------------------------------------
// VCL component
//----------------------------------------------------------------------------
type
EJvDSADialog = class(EJVCLException);
TJvDSADataEvent = procedure(Sender: TObject; const DSAInfo: TDSARegItem; const Storage: TDSAStorage) of object;
TJvDSAAutoCloseEvent = procedure(Sender: TObject; var Handled: Boolean) of object;
TJvDSADialog = class(TJvComponent)
private
FCheckControl: TWinControl;
FDialogID: Integer;
FIgnoreDSAChkMrkTxt: Boolean;
FOnUpdateKeys: TJvDSADataEvent;
FOnApplyKeys: TJvDSADataEvent;
FOrgOwner: TComponent;
FOrgShowModalPtr: Pointer;
FTimeout: Integer;
FTimer: TTimer;
FTimerCount: Integer;
FOnCountdown: TNotifyEvent;
FOnAutoClose: TJvDSAAutoCloseEvent;
protected
procedure AutoClose;
procedure AfterShow; virtual;
procedure ApplySavedState; virtual;
procedure BeforeShow; virtual;
procedure DoApplyKeys(const Storage: TDSAStorage; const DSAInfo: TDSARegItem); virtual;
function DoAutoClose: Boolean;
procedure DoCountDown;
procedure DoUpdateKeys(const Storage: TDSAStorage; const DSAInfo: TDSARegItem); virtual;
function GetDSAStateInternal(out ModalResult: Integer): Boolean;
function GetOrgOwner: TComponent;
function GetOrgShowModalPtr: Pointer;
function GetStorage: TDSAStorage;
procedure FormPatch;
procedure FormUnPatch;
procedure Notification(AComponent: TComponent; Operation: TOperation); override;
procedure SetCheckControl(Value: TWinControl); virtual;
procedure SetDialogID(Value: Integer); virtual;
procedure SetOrgOwner(Value: TComponent);
procedure SetOrgShowModalPtr(Value: Pointer);
procedure TimerEvent(Sender: TObject);
procedure UpdateDSAState; virtual;
property OrgOwner: TComponent read GetOrgOwner write SetOrgOwner;
property OrgShowModalPtr: Pointer read GetOrgShowModalPtr write SetOrgShowModalPtr;
property Storage: TDSAStorage read GetStorage;
public
constructor Create(AOwner: TComponent); override;
destructor Destroy; override;
function GetModalResult: Integer; virtual;
function IsDSAChecked: Boolean; virtual;
procedure Loaded; override;
procedure CancelCountdown; virtual;
function SecondsLeft: Integer;
published
property Timeout: Integer read FTimeout write FTimeout;
property CheckControl: TWinControl read FCheckControl write SetCheckControl;
property DialogID: Integer read FDialogID write SetDialogID;
property IgnoreDSAChkMrkTxt: Boolean read FIgnoreDSAChkMrkTxt write FIgnoreDSAChkMrkTxt;
property OnApplyKeys: TJvDSADataEvent read FOnApplyKeys write FOnApplyKeys;
property OnUpdateKeys: TJvDSADataEvent read FOnUpdateKeys write FOnUpdateKeys;
property OnCountdown: TNotifyEvent read FOnCountdown write FOnCountdown;
property OnAutoClose: TJvDSAAutoCloseEvent read FOnAutoClose write FOnAutoClose;
end;
implementation
uses
{$IFDEF UNITVERSIONING}
JclUnitVersioning,
{$ENDIF UNITVERSIONING}
QConsts, Math, TypInfo,
{$IFDEF MSWINDOWS}
JclRegistry,
{$ENDIF MSWINDOWS}
JclBase, JclSysUtils,
JvQDynControlEngineIntf, JvQConsts, JvQResources;
const
cDSAStateValueName = 'DSA_State'; // do not localize
cDSAStateLastResultName = 'LastResult'; // do not localize
type
PBoolean = ^Boolean;
//=== CheckMarkTexts =========================================================
var
GlobalCheckMarkTexts: TStringList = nil;
function CheckMarkTexts: TStrings;
begin
if GlobalCheckMarkTexts = nil then
GlobalCheckMarkTexts := TStringList.Create;
Result := GlobalCheckMarkTexts;
end;
function GetCheckMarkText(const ID: TDSACheckTextKind): string;
var
Idx: Integer;
begin
Idx := CheckMarkTexts.IndexOfObject(TObject(ID));
if Idx > -1 then
Result := CheckMarkTexts[Idx]
else
Result := '';
end;
//=== { TDSAMessageForm } ====================================================
constructor TDSAMessageForm.CreateNew(AOwner: TComponent; Dummy: Integer);
begin
inherited CreateNew(AOwner, Dummy);
FTimer := TTimer.Create(Self);
FTimer.Enabled := False;
FTimer.Interval := 1000;
FTimer.OnTimer := TimerEvent;
end;
procedure TDSAMessageForm.CustomKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState);
begin
CancelAutoClose;
if (Shift = [ssCtrl]) and (Key = Word('C')) then
begin
// (rom) deactivated annoying
// SysUtils.Beep;
WriteToClipboard(GetFormText);
end;
end;
procedure TDSAMessageForm.CustomMouseDown(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
begin
CancelAutoClose;
end;
procedure TDSAMessageForm.CustomShow(Sender: TObject);
var
I: Integer;
begin
if Timeout <> 0 then
FTimer.Enabled := True;
for I := 0 to ComponentCount - 1 do
begin
if (Components[I] is TButton) and (Components[I] as TButton).Default then
begin
(Components[I] as TButton).SetFocus;
Break;
end;
end;
FCountdown := TLabel(FindComponent('Countdown'));
end;
procedure TDSAMessageForm.HelpButtonClick(Sender: TObject);
begin
CancelAutoClose;
Application.ContextHelp(HelpContext);
end;
procedure TDSAMessageForm.TimerEvent(Sender: TObject);
var
I: Integer;
begin
if FTimer.Enabled then
begin
Dec(FTimeout);
if FTimeout = 0 then
begin
FTimer.Enabled := False;
for I := 0 to ComponentCount - 1 do
begin
if (Components[I] is TButton) and (Components[I] as TButton).Default then
begin
(Components[I] as TButton).Click;
Exit;
end;
end;
// No default button found; just close the form
Close;
end
else
if FCountdown <> nil then
FCountdown.Caption := Format(RsCntdownText, [Timeout, TimeoutUnit(Timeout)]);
end;
end;
procedure TDSAMessageForm.WriteToClipboard(const Text: string);
begin
Clipboard.AsText := Text;
end;
function TDSAMessageForm.GetFormText: string;
var
DividerLine, ButtonCaptions: string;
I: Integer;
begin
DividerLine := StringOfChar('-', 27) + CrLf;
for I := 0 to ComponentCount - 1 do
if Components[I] is TButton then
ButtonCaptions := ButtonCaptions + TButton(Components[I]).Caption + StringOfChar(' ', 3);
ButtonCaptions := StringReplace(ButtonCaptions, '&', '', [rfReplaceAll]);
I := ComponentCount - 1;
while (I > -1) and not (Components[I] is TLabel) do
Dec(I);
Result := Format('%s%s%s%s%s%s%s%s%s%s', [DividerLine, Caption, CrLf, DividerLine,
TLabel(Components[I]).Caption, CrLf, DividerLine, ButtonCaptions, CrLf, DividerLine]);
end;
function TDSAMessageForm.TimeoutUnit(Secs: Integer): string;
begin
if Secs <> 1 then
Result := RsCntdownSecsText
else
Result := RsCntdownSecText;
end;
procedure TDSAMessageForm.CancelAutoClose;
begin
FTimer.Enabled := False;
FreeAndNil(FCountdown);
end;
function TDSAMessageForm.IsDSAChecked: Boolean;
var
I: Integer;
begin
I := ComponentCount - 1;
while (I > -1) and not (Components[I] is TCustomCheckBox) do
Dec(I);
if (I > -1) then
Result := TCheckBox(Components[I]).Checked
else
Result := False;
end;
function GetAveCharSize(Canvas: TCanvas): TPoint;
var
I: Integer;
Buffer: array [0..51] of Char;
begin
for I := 0 to 25 do
Buffer[I] := Chr(I + Ord('A'));
for I := 0 to 25 do
Buffer[I + 26] := Chr(I + Ord('a'));
GetTextExtentPoint32(Canvas.Handle, Buffer, 52, TSize(Result));
Result.X := Result.X div 52;
end;
function CreateDSAMessageForm(const ACaption, Msg: string; const APicture: TGraphic;
const Buttons: array of string; const Results: array of Integer; const HelpCtx: Integer;
const CheckCaption: string; const Center: TDlgCenterKind = dckScreen;
const ATimeout: Integer = 0; const DefaultButton: Integer = 0;
const CancelButton: Integer = 1; HelpButton: Integer = -1;
const ADynControlEngine: TJvDynControlEngine = nil): TDSAMessageForm;
const
mcHorzMargin = 8;
mcVertMargin = 8;
mcHorzSpacing = 10;
mcVertSpacing = 10;
mcButtonWidth = 50;
mcButtonHeight = 14;
mcButtonSpacing = 4;
var
DialogUnits: TPoint;
HorzMargin, VertMargin, HorzSpacing, VertSpacing, ButtonWidth: Integer;
ButtonHeight, ButtonSpacing, ButtonCount, ButtonGroupWidth: Integer;
IconTextWidth, IconTextHeight, X, ALeft: Integer;
ChkTextWidth: Integer;
TimeoutTextWidth: Integer;
IconID: PChar;
TempRect, TextRect: TRect;
I: Integer;
CenterParent: TComponent;
CenterParLeft, CenterParTop, CenterParWidth, CenterParHeight: Integer;
DynControlEngine: TJvDynControlEngine;
CountDownlabel, MessageLabel: TControl;
Image: TWinControl;
DynControlImage: IJvDynControlImage;
DynControlLabel: IJvDynControlLabel;
Panel: TWinControl;
begin
if Assigned(ADynControlEngine) then
DynControlEngine := ADynControlEngine
else
DynControlEngine := DefaultDynControlEngine;
case Center of
dckScreen:
CenterParent := Screen;
dckMainForm:
CenterParent := Application.MainForm;
dckActiveForm:
CenterParent := Screen.ActiveCustomForm;
else
CenterParent := nil;
end;
if CenterParent = nil then
CenterParent := Screen;
if CenterParent is TScreen then
begin
CenterParLeft := 0;
CenterParTop := 0;
CenterParWidth := TScreen(CenterParent).Width;
CenterParHeight := TScreen(CenterParent).Height;
end
else
begin
with TWinControl(CenterParent) do
begin
CenterParLeft := Left;
CenterParTop := Top;
CenterParWidth := Width;
CenterParHeight := Height;
end;
end;
if HelpButton = High(Integer) then
HelpButton := High(Buttons);
Result := TDSAMessageForm.CreateNew(Screen.ActiveCustomForm);
try
with Result do
begin
Position := poDesigned; // Delphi 2005 has a new default
BorderStyle := fbsDialog;
Canvas.Font := Font;
KeyPreview := True;
OnKeyDown := CustomKeyDown;
OnShow := CustomShow;
OnMouseDown := CustomMouseDown;
DialogUnits := GetAveCharSize(Canvas);
HorzMargin := MulDiv(mcHorzMargin, DialogUnits.X, 4);
VertMargin := MulDiv(mcVertMargin, DialogUnits.Y, 8);
HorzSpacing := MulDiv(mcHorzSpacing, DialogUnits.X, 4);
VertSpacing := MulDiv(mcVertSpacing, DialogUnits.Y, 8);
ButtonWidth := MulDiv(mcButtonWidth, DialogUnits.X, 4);
Timeout := Abs(ATimeout);
for I := Low(Buttons) to High(Buttons) do
begin
TextRect := Rect(0, 0, 0, 0);
{Windows.}DrawText(Canvas.Handle, PChar(Buttons[I]), -1, TextRect,
DT_CALCRECT or DT_LEFT or DT_SINGLELINE or DrawTextBiDiModeFlagsReadingOnly);
with TextRect do
if (Right - Left + 8) > ButtonWidth then
ButtonWidth := (Right - Left + 8);
end;
ButtonHeight := MulDiv(mcButtonHeight, DialogUnits.Y, 8);
ButtonSpacing := MulDiv(mcButtonSpacing, DialogUnits.X, 4);
if (Screen.Width div 2) > (CenterParWidth + (2 * CenterParLeft)) then
SetRect(TextRect, 0, 0, CenterParWidth + (2 * CenterParLeft), 0)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -