#1 2011-03-05 08:31:54

ab
Administrator
From: France
Registered: 2010-06-21
Posts: 5,030
Website

Open Source SynTaskDialog unit for XP,Vista,Seven

Welcome to the SynTaskDialog unit!
  Implements TaskDialog window (native on Vista/Seven, emulated on XP).

  This unit is a part of the freeware Synopse framework,
   licensed under a MPL/GPL/LGPL tri-license.


Presentation

A task dialog is a dialog box that can be used to display information
and receive simple input from the user. Like a message box, it is
formatted by the operating system according to parameters you set.
However, a task dialog has many more features than a message box.

Windows provides a generic task dialog available since Vista/Seven.
But there is none available with previous versions of Windows, i.e.
Windows XP or 2K.


Our implementation

This unit will use the new TaskDialog API under Vista/Seven, and emulate
it with pure Delphi code and standard themed VCL components under XP or 2K.

Our task dialog is mainly implemented in the TTaskDialog record/object
type and methods.

It will compile from Delphi 6 up to XE, and is Unicode ready.

The emulation code is very simple, and only use standard VCL components.
With the theming enabled (don't forget to add XPMan as one of your units,
or set our {$R Vista.res} resource), it renders very nicely under XP.

Our task dialog has some additional features, which are not available by
default in the Vista/Seven TaskDialog: we have direct field edition or
selection (using a TEdit or a TComboBox), without any difficult callback
system to implement. Just fill the Selection property, or set the new
tdfQuery flag to enable those features (see sample code below).


Hello world

In order to use it, create a TTaskDialog object/record on the stack.
The Delphi compiler will initialize all its string parameters to ''
(it's a SHAME that since Delphi 2009, objects are not initialized any more:
we have to define this type as object before Delphi 2009, and as record
starting with Delphi 2009).

Then set the appropriate string parameters, and call Execute() with all
additional parameters.

After execution, RadioRes/SelectionRes/VerifyChecked can be used to
reflect the diverse results states.

See the comments in the unit souce code about all available properties
and parameters.

Here is a typical usage:

var Task: TTaskDialog;
begin
  Task.Inst := 'Saving application settings';
  Task.Content := 'This is the content';
  Task.Radios := 'Store settings in registry'#10'Store settings in XML file';
  Task.Verify := 'Do no ask for this setting next time';
  Task.VerifyChecked := true;
  Task.Footer := 'XML file is perhaps a better choice';
  Task.Execute([],0,[],tiQuestion,tfiInformation,200);
  ShowMessage(IntToStr(Task.RadioRes)); // 200=Registry, 201=XML
  if Task.VerifyChecked then
    ShowMessage(Task.Verify);
end;

Note that you don't need to put a Create/Free and a try..finally block to
protect the TTaskDialog instance. The Delphi compiler will do all the work
for us.


How to replace the VCL Dialogs unit functions

Here is some source code which may help you use the new task dialog
instead of the VCL Dialogs unit:

procedure ShowMessage(const Msg, Inst: string; Error: boolean=false);
const
  IconError: array[boolean] of TTaskDialogIcon = (tiInformation, tiError);
var Task: TTaskDialog;
begin
  Task.Inst := Inst;
  Task.Content := Msg;
  Task.Execute([cbOK],mrOk,[],IconError[Error]);
end;

function InputQuery(const ACaption, APrompt: string; var Value: string): Boolean;
var Task: TTaskDialog;
begin
  Task.Inst := ACaption;
  Task.Content := APrompt;
  Task.Query := Value;
  result := Task.Execute([cbOk,cbCancel],0,[tdfQuery],tiQuestion)=mrOk;
  if result then
    Value := Task.Query;
end;

function InputSelect(const ACaption, APrompt, AItemsText, ASelectedText: string): integer;
var Task: TTaskDialog;
begin
  result := -1;
  if AItemsText='' then
    exit;
  Task.Inst := ACaption;
  Task.Content := APrompt;
  Task.Selection := AItemsText;
  Task.Query := ASelectedText;
  if Task.Execute([cbOk,cbCancel],0,[],tiQuestion)=mrOk then
    result := Task.SelectionRes;
end;

I think we have here the simpliest Task Dialog unit available for Delphi,
all for free!
smile


Reference material

For a general presentation about the TaskDialog, from the Microsoft POV,
see http://msdn.microsoft.com/en-us/library … S.85).aspx

For details about the Microsoft implementation API used in this unit, see
http://msdn.microsoft.com/en-us/library … S.85).aspx


One step further

This unit was developped for the User Interface, our SQlite3 Framework,
which is an Open Source ORM framework, based on a multi-tier architecture
and a RESTful approach.

E.g. in the SQLite3UILogin unit, you'll find additional functions and
usage of this unit. See also the sample application available in the
"Samples\08 - TaskDialog" folder.


If you find any bug, or need some enhancements, feel free to contribute
to this project. Enter the Open Source zone!

Offline

#2 2011-03-06 01:59:37

edwinsn
Member
Registered: 2010-07-02
Posts: 209

Re: Open Source SynTaskDialog unit for XP,Vista,Seven

great! Thanks!

Offline

#3 2011-03-08 09:36:38

uligerhardt
Member
Registered: 2011-03-08
Posts: 38

Re: Open Source SynTaskDialog unit for XP,Vista,Seven

Thanks for this unit. I have been considering writing a simple wrapper like yours for quite a while.

Some quick observations:

  • The command link emulation could perhaps achieve a more compatible look with the TBitBtn.Margin and Spacing properties.

  • Some ownerdrawing to draw the command link hints in emulation mode would be nice. But I guess that this would start to make this unit "heavy".

  • aButtonDef doesn't seem to workwith emulated command links.

Best regards,
Uli.

Offline

#4 2011-03-08 16:52:18

ab
Administrator
From: France
Registered: 2010-06-21
Posts: 5,030
Website

Re: Open Source SynTaskDialog unit for XP,Vista,Seven

There was an issue with aButtonDef and emulated command links.

About TBitBtn look, I've updated it using Margin and Spacing.
Thanks for the tip.

Ownerdrawing won't be feasible with Delphi 6 and raw TButton type...
If you find out a simple way to do it with other versions....

Here are the modifications:
http://synopse.info/fossil/info/12f5b0d9ee

Thanks for the feedback! smile

Offline

#5 2011-03-08 19:50:36

uligerhardt
Member
Registered: 2011-03-08
Posts: 38

Re: Open Source SynTaskDialog unit for XP,Vista,Seven

Thanks for the update!

Thanks to Borland ownerdrawing won't be easy because the TBitBtn code is totally un-reusable. One would have to copy half of the Buttons unit to do any ownerdrawing.

Last edited by uligerhardt (2011-03-08 20:08:14)

Offline

#6 2011-03-08 19:55:20

ab
Administrator
From: France
Registered: 2010-06-21
Posts: 5,030
Website

Re: Open Source SynTaskDialog unit for XP,Vista,Seven

That was my personal guess too.... un-reusable is the word!!!!

wink

IMHO the current implementation is just fine for most apps.
If you need a better looking button, you can use your own preferred button, since you've got the source code of the unit!
That's the beauty of Open Source.
But in its current state, this little unit is doing its purpose well enough.

Offline

#7 2011-03-25 09:09:42

christian
New member
Registered: 2011-03-25
Posts: 2

Re: Open Source SynTaskDialog unit for XP,Vista,Seven

Using your approach (at least with the examples given) gives some different results compared to the native Vista/7 TaskDialog:

- It doesn't produce a modal dialog !!
- The ShowMessage example cannot be closed by pressing the ESC key (only the return key is assigned to the btOK)

Is there some missed setting needed?

Regards,
Christian

Offline

#8 2011-03-25 10:49:12

ab
Administrator
From: France
Registered: 2010-06-21
Posts: 5,030
Website

Re: Open Source SynTaskDialog unit for XP,Vista,Seven

With the emulated code:

christian wrote:

- It doesn't produce a modal dialog !!

It's modal to the current application only.
Is this a problem?

christian wrote:

- The ShowMessage example cannot be closed by pressing the ESC key (only the return key is assigned to the btOK)

On my computer, ESC does close the window.

Offline

#9 2011-03-26 06:49:03

christian
New member
Registered: 2011-03-25
Posts: 2

Re: Open Source SynTaskDialog unit for XP,Vista,Seven

Well yes and no wink

It gives a different behaviour with the native (Win7) and the emulated (WinXP) version.

With Win7 the ShowMessage Example produces no modal dialog windows and they cannot be closed with ESC!
With WinXP the behaviour is as expected (modal and can be closed with ESC).



Example with a Form with one Button:

procedure MyShowMessage(const Msg, Inst: string; Error: boolean=false);
const
  IconError: array[boolean] of TTaskDialogIcon = (tiInformation, tiError);
var Task: TTaskDialog;
begin
  Task.Inst := Inst;
  Task.Content := Msg;
  Task.Execute([cbOK],mrOk,[],IconError[Error]);
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
  MyShowMessage('MyMsg', 'MyInst');
end;

Offline

#10 2011-03-26 08:46:36

ab
Administrator
From: France
Registered: 2010-06-21
Posts: 5,030
Website

Re: Open Source SynTaskDialog unit for XP,Vista,Seven

So under Win7, the standard task dialog API is called directly.
That is, the code from Microsoft is executed.
I'm not able to change it.

Perhaps some hidden flag?

Offline

#11 2011-03-26 11:47:19

ab
Administrator
From: France
Registered: 2010-06-21
Posts: 5,030
Website

Re: Open Source SynTaskDialog unit for XP,Vista,Seven

OK. I found the possible issue.

Fixed issue: "no modal dialog windows and they cannot be closed with ESC"
See http://synopse.info/fossil/info/478dbb2449

Thanks for the report!

Offline

#12 2011-10-12 12:18:02

uligerhardt
Member
Registered: 2011-03-08
Posts: 38

Re: Open Source SynTaskDialog unit for XP,Vista,Seven

Hello ab!

Some more nitpicking about the look of your emulation. :-)
I'd like to look the emulated dialogs more like the real Windows 7 task dialog under Windows Classic (i.e. unthemed), that is similar to this:
taskdialog1.png.

  • no white panel

  • different fonts

  • narrower borders

  • etc.

I have played a bit with SynTaskDialog.pas and got a look that I like better (even if I'm not done yet). Would you be interested in integrating this in the official unit as an compile time or runtime option?

Another thing: I'd suggest you remove the shadow from the arrow bitmap because it looks ugly when you have configured your system to a non-gray clBtnFace. (PNG probably isn't an option.)

Best regards,
Uli.

Last edited by uligerhardt (2011-10-12 12:41:13)

Offline

#13 2011-10-12 13:14:03

uligerhardt
Member
Registered: 2011-03-08
Posts: 38

Re: Open Source SynTaskDialog unit for XP,Vista,Seven

One other question: Is there a reason that there are so many arguments to TTaskDialog.Execute? I think SynTaskDialog would be easier to use if most of these parameters were fields of the TTaskDialog record instead.

And it might be good to replace TTaskDialogForm.FormShow with an override of DoShow.

Last edited by uligerhardt (2011-10-12 13:17:04)

Offline

#14 2011-10-12 14:41:10

uligerhardt
Member
Registered: 2011-03-08
Posts: 38

Re: Open Source SynTaskDialog unit for XP,Vista,Seven

If I have more suggestions, would http://synopse.info/fossil/rptview?rn=1 / http://synopse.info/fossil/tktnew be the place to report them?

Offline

#15 2011-10-12 15:36:44

ab
Administrator
From: France
Registered: 2010-06-21
Posts: 5,030
Website

Re: Open Source SynTaskDialog unit for XP,Vista,Seven

Welcome uligerhardt!

Any suggestion is always welcome.

The look depends on the Windows theming - using plain Windows controls has its pros and cons.
I wanted the unit to stay "plain" VCL ready, and the resulting layout is expected to use Windows theming.

The fact that there are some many arguments in Execute() is, as far as I remember, that... there is no obvious reason unless that they will provide default parameters.
We may pass all arguments as TTaskDialog fields, but since it is an object/record, there is no default values to them (when allocated on the stack, it is not filled with zero).

You can use the fossil tickets, but for issues.
For suggestions and enhancements, you can better use this forum, and we will discuss here.

Thanks for your interest.

Offline

#16 2011-10-12 16:44:07

uligerhardt
Member
Registered: 2011-03-08
Posts: 38

Re: Open Source SynTaskDialog unit for XP,Vista,Seven

ab wrote:

The look depends on the Windows theming - using plain Windows controls has its pros and cons.
I wanted the unit to stay "plain" VCL ready, and the resulting layout is expected to use Windows theming.

The fact that your unit uses standard VCL controls and respects theming is one of the things I like about it.

What I mean is that the emulated task dialogs look like the MS dialogs from a standard Windows Vista/7 Aero. Because of this they look a bit out of place on on XP with Luna and on every classic/unthemed Windows (even on unthemed Vista/7). If the emulation looked more like a Windows Classic task dialog it would blend in better on those platforms.

ab wrote:

The fact that there are some many arguments in Execute() is, as far as I remember, that... there is no obvious reason unless that they will provide default parameters.
We may pass all arguments as TTaskDialog fields, but since it is an object/record, there is no default values to them (when allocated on the stack, it is not filled with zero).

OK, I see.

ab wrote:

You can use the fossil tickets, but for issues.
For suggestions and enhancements, you can better use this forum, and we will discuss here.

OK.

ab wrote:

Thanks for your interest.

Thanks for your component. :-)

Offline

#17 2011-10-12 20:40:21

uligerhardt
Member
Registered: 2011-03-08
Posts: 38

Re: Open Source SynTaskDialog unit for XP,Vista,Seven

Regarding the border width of the emulation: Just compare the border around the icon of an emulated dialog
TaskDialog04.png
with a Windows task dialog, either themed
TaskDialog03.png
or unthemed
taskdialog1.png

(Replacing the 24's after WIN_ICONS[aDialogIcon] with 10's (and 48 with 20) should work. wink)

Offline

#18 2011-10-13 12:00:12

ab
Administrator
From: France
Registered: 2010-06-21
Posts: 5,030
Website

Re: Open Source SynTaskDialog unit for XP,Vista,Seven

As a matter of fact, for personal taste, I made the button layout a bit larger.

I'll stick to your values.
See http://synopse.info/fossil/info/0da563d560

Offline

#19 2011-10-13 13:43:12

uligerhardt
Member
Registered: 2011-03-08
Posts: 38

Re: Open Source SynTaskDialog unit for XP,Vista,Seven

Thank you, Arnaud,

this almost looks like the original!
Maybe you could insert

Panel.BevelOuter := bvNone;
Panel.BevelEdges := [beBottom];
Panel.BevelKind := bkFlat;

after the

Panel.BorderStyle := bsNone;

line to make the border around the white panel more authentic.

Two more things: If I show a task dialog like this:

var
  Task: TTaskDialog;
  Res: Integer;
begin
  Task.Inst := 'Saving application settings';
  Task.Content := 'This is the content';
  Task.Buttons := 'Registry\nStore settings in registry' + sLineBreak + 'XML\nStore settings in XML file';
  Res := Task.Execute([cbOK, cbCancel], 101, [tdfUseCommandLinks], tiQuestion, tfiInformation, 0, 0, Handle, CheckBoxUseEmulation.Checked);
end;

the "real" dialog has a close button in the upper right corner, while the emulated one hasn't. Is there a way to have the button in the emulation, too?

With the same code, the tab order of the OK and Cancel buttons is reversed. This could fixed like this:

  • Declare

    CurrTabOrder: TTabOrder;

    next to Par and Panel.

  • Put the line

    CurrTabOrder := Panel.TabOrder;

    at the beginning of the

    if (byte(aCommonButtons) <> 0)...

    branch.

  • Set

        result.TabOrder := CurrTabOrder;

    in AddButton.

BTW: I hate to be a PITA, but I like my GUI to be "right". :-)

Offline

#20 2011-10-14 11:51:00

uligerhardt
Member
Registered: 2011-03-08
Posts: 38

Re: Open Source SynTaskDialog unit for XP,Vista,Seven

Once more a PITA. :-)

uligerhardt wrote:

Another thing: I'd suggest you remove the shadow from the arrow bitmap because it looks ugly when you have configured your system to a non-gray clBtnFace. (PNG probably isn't an option.)

Do see what I mean compare these pictures:
Original Windows dialog:
2wgc4dy.png
Emulation, arrow with shadow:
120pgno.png
Emulation, arrow without shadow:
mlo6ti.png

The last screenshot was produced with this BTNARROW (can't append the real bmp, unfortunately):
2ef8he9.png
Looks better, doesn't it?

Best regards,
Uli.

Last edited by uligerhardt (2011-10-14 11:51:15)

Offline

#21 2011-10-20 08:36:05

uligerhardt
Member
Registered: 2011-03-08
Posts: 38

Re: Open Source SynTaskDialog unit for XP,Vista,Seven

Hello Arnaud,

if you have an app that uses SynTaskDialog and has runtime packages enabled you get compiler errors

E2201: Need imported data reference ($G) to access 'SMsgDlgOK' from unit 'SynTaskDialog'

for TD_BTNS and TD_ICONS_IDENT. I don't know where this comes from - probably vcl.dpk is compiled with the "wrong {$IMPORTEDDATA ...} directive. There is a (German) post that seems to deal with this problem: http://www.delphipraxis.net/72509-resou … ckage.html and this post: https://forums.embarcadero.com/message. … ageID=6844.

I've found two workarounds: Either

  1. replace the pointer arrays with string arrays like

    TD_ICONS_IDENT: array[TTaskDialogIcon] of string =(
        '', SMsgDlgWarning, SMsgDlgConfirm, SMsgDlgError, SMsgDlgInformation,
        '', SMsgDlgInformation);

    and remove some LoadResString calls or

  2. replace the pointer arrays with functions like

    GetIconIdent(TTaskDialogIcon): Pointer

    .

Best regards,
Uli.

Last edited by uligerhardt (2011-10-20 08:40:14)

Offline

#22 2011-10-21 19:02:53

uligerhardt
Member
Registered: 2011-03-08
Posts: 38

Re: Open Source SynTaskDialog unit for XP,Vista,Seven

Hello Arnaud,

I have made some modifications to SynTaskDialog.pas and will send them to you per mail as I can't attach it here. You probably won't like all of the changes but feel free to take what you like.

I wrote a little wrapper TTaskDialogEx to make the usage of TTaskDialog.Execute a bit easier if you want to change just one or two of the default arguments. There is a global variable DefaultTaskDialogEx: TTaskDialogEx  which is initialized to the default values from TTaskDialog.Execute.
You could use it like this:

  • Customize DefaultTaskDialogEx in some initialization section, FormCreate or similar, maybe

    DefaultTaskDialogEx.EmulateClassicStyle := True;

    or

    DefaultTaskDialogEx.AlwaysEmulate := True;
  • Use it like

    procedure TForm1.Button3Click(Sender: TObject);
    const
      Icons: array[TMsgDlgType] of SynTaskDialog.TTaskDialogIcon = (
        tiWarning, tiError, tiInformation, tiQuestion, tiNotUsed);
    var
      Task: SynTaskDialog.TTaskDialogEx;
      Res: Integer;
    begin
      Task := DefaultTaskDialogEx;
      
      // Base is a TTaskDialog
      Task.Base.Title := 'My Test App';
      Task.Base.Inst := 'Saving application settings';
      // more Base settings...
    
      Task.CommonButtons := [cbOK, cbCancel];
      Task.ButtonDef := 101;
      Task.Flags := [tdfUseCommandLinks];
      // Notice: no mentioning of DialogIcon, FooterIcon, RadioDef, Width, ...
    
      Res := Task.Execute(Handle);
    end;

All other changes only apply if emulation is active.

  1. New parameter EmulateClassicStyle in TTaskDialog.Execute. If True then the emulation is drawn more like the original Microsoft dialog under Windows Classic. (This is not finished yet - the verification checkbox and footer text aren't handled correctly yet.)

  2. If EmulateClassicStyle = False I've reverted the icon border to your taste (24 instead of 10, see post http://synopse.info/forum/viewtopic.php?pid=2777#p2777).

  3. BitmapOK (and its accompanying res entry) weren't used, so I removed them.

  4. Removed the shadow in the arrow bitmap (see http://synopse.info/forum/viewtopic.php?pid=2785#p2785).

  5. I split TSynButton in two: TSynCommandLink for the command links and TSynButton for the other buttons. The latter ones are now never TBitBtns because this looks ugly for OK buttons etc (wrong text base line) and the Glyph isn't used anyway.

  6. The DropDown stuff in TSynButton wasn't used, so I commented it out.

  7. Fixed the E2201 error by using an array of strings (see http://synopse.info/forum/viewtopic.php?pid=2850#p2850).

  8. By overloading TTaskDialogForm.Create (calling CreateNew) some ugly casting could be removed.

  9. Used ActiveControl instead of the Tag/FormShow trick.

  10. Fixed the TabOrder issue (see http://synopse.info/forum/viewtopic.php?pid=2778#p2778).

Uli

Offline

#23 2011-10-24 19:08:26

uligerhardt
Member
Registered: 2011-03-08
Posts: 38

Re: Open Source SynTaskDialog unit for XP,Vista,Seven

uligerhardt wrote:

3. BitmapOK (and its accompanying res entry) weren't used, so I removed them.
5. I split TSynButton in two: TSynCommandLink for the command links and TSynButton for the other buttons. ...
6. The DropDown stuff in TSynButton wasn't used, so I commented it out.

That move wasn't too smart, as all of these are used elsewhere in your framework. I've reinstated them and will send you an update later.

Last edited by uligerhardt (2011-10-24 19:12:14)

Offline

#24 2011-10-25 12:29:22

ab
Administrator
From: France
Registered: 2010-06-21
Posts: 5,030
Website

Re: Open Source SynTaskDialog unit for XP,Vista,Seven

uligerhardt wrote:

That move wasn't too smart, as all of these are used elsewhere in your framework. I've reinstated them and will send you an update later.

I would not have deleted those lines either.
wink

I'm waiting for your update.

Offline

#25 2011-10-25 13:48:17

uligerhardt
Member
Registered: 2011-03-08
Posts: 38

Re: Open Source SynTaskDialog unit for XP,Vista,Seven

ab wrote:
uligerhardt wrote:

That move wasn't too smart, as all of these are used elsewhere in your framework. I've reinstated them and will send you an update later.

I would not have deleted those lines either.
wink

I guessed so. :-)

ab wrote:

I'm waiting for your update.

I sent it this morning to your bouchez-info address. Slow electrons today...

Offline

Board footer

Powered by FluxBB