15
New Windows 7 API support for Taskbar – Part 1
0 Comments | Posted by Alexander in Snippets
The latest OS release from Microsoft introduces to us a lot of new features that (can) make life of developers easier and improve usability of own applications. This post is about small part of new Windows API that allows to customize taskbar button of your application.
Pictures and source code are telling more than 1000 words, hence we start immediately with practical examples:
Here is picture of what we will get after compiling sample project – we will create project that has buttons on it’s taskbar thumbnail, that allow to control progressbar and another part is reflect progressbar state on application taskbar button:
NB #2 All manipulatations with taskbar buttons must be done after button will be created, to catch this moment we should subscribe to WM_TASKBARBUTTONCREATED event, that must firstly registered by RegisterWindowMessage(‘TaskbarButtonCreated’); – I reccomend you to add this registration to initialization section of unit with your form:
//.....//
initialization
WM_TASKBARBUTTONCREATED := RegisterWindowMessage('TaskbarButtonCreated');
end.
NB #3 You must be sure that Application.MainFormOnTaskbar is True; or drop on form TLMDFormVista for delphi 6-2005 versions
Now, when we registered message we can handle it in WndProc method to setup taskbar button:
type
TForm8 = class(TForm)
Timer1: TTimer;
ImageList1: TImageList;
ProgressBar1: TProgressBar;
procedure FormCreate(Sender: TObject);
procedure Timer1Timer(Sender: TObject);
procedure Button2Click(Sender: TObject);
procedure Button1Click(Sender: TObject);
private
FTick: Int64;
FButtons: array[0..2] of TThumbButton;
FNormalIcon: Cardinal;
FPauseIcon: Cardinal;
FTaskBar: ITaskbarList3;
protected
procedure WndProc(var Message: TMessage); override;
{ Private declarations }
public
{ Public declarations }
end;
//...//
procedure TForm8.WndProc(var Message: TMessage);
begin
inherited;
// Is tasbar button created?
if Message.Msg = WM_TASKBARBUTTONCREATED then
begin
// Create instance of ITaskbarList3
CoCreateInstance(CLSID_TaskbarList, nil, CLSCTX_INPROC_SERVER, IID_ITaskbarList3, FTaskBar);
// Init
FTaskBar.HrInit;
// This method set progress state of tasbar button.
// Button has next states: error, paused, normal and indetermintate
FTaskBar.SetProgressState(Handle, TBPF_NORMAL);
FNormalIcon := LoadIcon(0, IDI_ASTERISK);
FPauseIcon := LoadIcon(0, IDI_WARNING);
// Set overlay icon for taskbar button - "!" - asterix
FTaskBar.SetOverlayIcon(Handle, FNormalIcon, 'In progress');
// Buttons setup
// Set imagelist handle that contains glyphs for our buttons
FTaskBar.ThumbBarSetImageList(Handle, ImageList1.Handle);
// This identificator will be used to determinate what button pressed
FButtons[0].iId := 40001;
FButtons[0].dwFlags := THBF_ENABLED;
FButtons[0].iBitmap := 0;
StringToWideChar('Reset', FButtons[0].szTip, 260);
FButtons[0].dwMask := THB_BITMAP or THB_FLAGS or THB_TOOLTIP;
FButtons[1].iId := 40002;
FButtons[1].dwFlags := THBF_DISABLED;
FButtons[1].iBitmap := 1;
StringToWideChar('Play', FButtons[1].szTip, 260);
FButtons[1].dwMask := THB_BITMAP or THB_FLAGS or THB_TOOLTIP;
FButtons[2].iId := 40003;
FButtons[2].dwFlags := THBF_ENABLED;
FButtons[2].iBitmap := 2;
StringToWideChar('Pause', FButtons[2].szTip, 260);
FButtons[2].dwMask := THB_BITMAP or THB_FLAGS or THB_TOOLTIP;
// Add buttons to thumbnail
FTaskBar.ThumbBarAddButtons(Handle, 3, @FButtons[0]);
FTaskBar.SetThumbnailTooltip(Handle, 'Test');
Timer1.Enabled := True;
end;
end;
To handle buttons click we need to catch WM_COMMAND message, WParamLo field will contains id of clicked button:
procedure TForm8.WndProc(var Message: TMessage);
begin
//...//
if Message.Msg = WM_COMMAND then
begin
// Handle 'Reset' button
if Message.WParamLo = 40001 then
begin
Timer1.Enabled := True;
FTaskBar.SetProgressState(Handle, TBPF_NORMAL);
FTick := 0;
end;
// Handle 'Play' button
if Message.WParamLo = 40002 then
begin
// Run timer again
Timer1.Enabled := True;
FTaskBar.SetProgressState(Handle, TBPF_NORMAL);
// Set overlay icon to asterix icon
FTaskBar.SetOverlayIcon(Handle, FNormalIcon, 'In progress');
ProgressBar1.State := pbsNormal;
// Disable 'Play' button
FButtons[1].dwFlags := THBF_DISABLED;
// Enable 'Pause' button
FButtons[2].dwFlags := THBF_ENABLED;
// Update buttons
FTaskBar.ThumbBarUpdateButtons(Handle, 3, @FButtons[0])
end;
// Handle 'Pause' button. Almost the same as for 'Play'
if Message.WParamLo = 40003 then
begin
Timer1.Enabled := False;
FTaskBar.SetProgressState(Handle, TBPF_PAUSED);
FTaskBar.SetOverlayIcon(Handle, FPauseIcon, 'Paused');
ProgressBar1.State := pbsPaused;
FButtons[1].dwFlags := THBF_ENABLED;
FButtons[2].dwFlags := THBF_DISABLED;
FTaskBar.ThumbBarUpdateButtons(Handle, 3, @FButtons[0])
end;
end;
end;
And finally OnTimer handler code:
procedure TForm8.Timer1Timer(Sender: TObject);
begin
FTaskBar.SetProgressValue(Handle, FTick, 200);
ProgressBar1.Position := FTick;
Inc(FTick);
// It's all?
if FTick >= 200 then
begin
// Set indeterminate progress mode for tasbar button
FTaskBar.SetProgressState(Handle, TBPF_INDETERMINATE);
Timer1.Enabled := False;
end;
end;
That’s all for “Part 1″ – I hope that it will be useful for someone.

DelphiFeeds.com

