Thursday, October 14, 2010

Message dialogs: you're doing it wrong...

No matter what you say or think, end-users are beasts, they will always find a way to make their life more complicated instead of reading messages or instructions...
I'm pretty sure AT least once in your life you pressed the wrong button on a message dialog, because you „thought¯ you know what it will ask you OR because you was in a hurry...
The main problem with the end-user is that (s)he will do this most of the times, let's suppose that you're asking the user if (s)he is sure to wipe a file or discard changes that are very important to him/her, even if the user should be blamed because (s)he didn't read the message, you're still the one that will be sweared.
So what can we do to overcome such a situation?! well not much without stressing the user BUT we can use a timed message dialog with which the user cannot interact for a amount of time — this will probably force the user to read the freaking message!
So here's my implementation of a timed message dialog:
unit uTimedMessageDlg;

interface

uses
  SysUtils,
  Windows,
  Classes,
  Forms,
  Dialogs,
  Controls,
  ExtCtrls;

const
  CDEFAULT_WAIT_SEC = 10;
  CSECOND = 1000;
  CTIMED_MESSAGE = '%s (%d seconds)';

type
  TTimedMessageDlg = class(TObject)
  private
    FTimer: TTimer;
    FSeconds: Cardinal;
    FMessageForm: TForm;
    FCountDown: Integer;
    FCaption: string;
    procedure OnTimer(Sender: TObject);
    procedure OnDialogShow(Sender: TObject);
  public
    constructor Create;
    destructor Destroy; override;
  public
    function DisplayDialog(const Msg: string; const Args: array of const;
      DlgType: TMsgDlgType; Buttons: TMsgDlgButtons;
      const SecondsToWait: Cardinal = 10): Integer;
  public
    property Seconds: Cardinal
      read FSeconds write FSeconds;
  end;
  
function TimedMessageDlg(const Msg: string; const Args: array of const ;
  DlgType: TMsgDlgType; Buttons: TMsgDlgButtons;
  const SecondsToWait: Cardinal): Integer;

implementation

{ TTimedMessageDlg }

constructor TTimedMessageDlg.Create;
begin
  FTimer := TTimer.Create(NIL);
  FTimer.Enabled := False;
  FTimer.Interval := 1000;
  FTimer.OnTimer := OnTimer;
  FSeconds := 10;
end;

function TTimedMessageDlg.DisplayDialog(const Msg: string;
  const Args: array of const;
  DlgType: TMsgDlgType; Buttons: TMsgDlgButtons;
  const SecondsToWait: Cardinal = 10): Integer;
begin
  FMessageForm := CreateMessageDialog(Format(Msg, Args), DlgType, Buttons);
  FMessageForm.OnShow := OnDialogShow;
  FCountDown := SecondsToWait -1;
  FCaption := FMessageForm.Caption;
  FMessageForm.Caption := Format(CTIMED_MESSAGE, [FCaption, FCountDown]);
  FTimer.Interval := 1000;
  FTimer.Enabled := True;
  Result := FMessageForm.ShowModal;
  FreeAndNil(FMessageForm);
end;

destructor TTimedMessageDlg.Destroy;
begin
  FreeAndNil(FTimer);
  inherited;
end;

procedure TTimedMessageDlg.OnTimer(Sender: TObject);
begin
  Dec(FCountDown);
  FMessageForm.Caption := Format(CTIMED_MESSAGE, [FCaption, FCountDown]);
  if FCountDown <= 0 then begin
    FMessageForm.Caption := FCaption;
    FTimer.Enabled := False;
    FMessageForm.Enabled := True;
  end; // if FCountDown <= 0 then begin
end;

procedure TTimedMessageDlg.OnDialogShow(Sender: TObject);
begin
  FMessageForm.Enabled := False;
end;

function TimedMessageDlg(const Msg: string; const Args: array of const ;
  DlgType: TMsgDlgType; Buttons: TMsgDlgButtons;
  const SecondsToWait: Cardinal): Integer;
var
  TimedMessage: TTimedMessageDlg;
begin
  TimedMessage := TTimedMessageDlg.Create;
  Result := TimedMessage.DisplayDialog(Msg, Args, DlgType, Buttons,
    SecondsToWait);
  FreeAndNil(TimedMessage);
end;

end.
Sooo... what's the difference between normal and this custom message dialog?! nothing much, just that it can also format your message if you wish to AND the user cannot close or press any button on the message for the specified amount of time — I suggest to keep the time-out value somewhere between 3 to 7 seconds max.

No comments:

Post a Comment

Blogroll(General programming and Delphi feeds)