4

I have a mixed CBuilder/Delphi dll that I load from a non-VCL host application. I'm using RAD Studio XE2. Upon loading the dll I set the Application handle to the host's main form, which has the effect of keeping my forms and dialogs off of the taskbar. However I would like to show the progress bar on the taskbar and have it stack with the host application. I've googled and searched extensively but can't find anything similar.

Dr. Bob wrote a nice tutorial here on the various features of the taskbar and from that I've gotten a progress bar showing up in the main application's taskbar button, but I really want to create a second 'stacked' icon for the progress bar, which a lot of applications do. Dr. Bob's example assumes you are part of the main application and uses this code to add a tab:

if not Application.MainFormOnTaskBar then
  FormHandle := Application.Handle
else FormHandle := Application.MainForm.Handle;
TaskbarList.AddTab(FormHandle);

which doesn't do anything in my case. I've tried

FormHandle := FindWindow('TfmProg', NIL);
TaskbarList.addTab(FormHandle);

but that doesn't change anything.

I've created the form with Application as the owner, and NIL. I've created it fsNormal or fsStayOnTop. Frankly, I've touched every parameter I can get at, but nothing seems to work.

2
  • 1
    If AddTab fails to add a tab, it should return an HResult telling you why. What does it tell you in this case? Commented Feb 27, 2013 at 22:28
  • Hello @RobKennedy, the value returned is 0, or s_ok I think. I suspect the tab was being created correctly but parented wrong, maybe to a hidden form? Commented Feb 28, 2013 at 3:36

1 Answer 1

2

You are correct to set Application.Handle to be the handle of the main form of the host app. This will make the host app's main window be the owner of your windows. However, as you have observed, that also keeps your top-level windows off the taskbar. That's because owned top-level window's do not appear in the taskbar.

To put an owned top-level window on the taskbar you should include the WS_EX_APPWINDOW extended window style. Add this in your form's CreateParams procedure.

procedure CreateParams(var Params: TCreateParams); override;
....
procedure TMyForm.CreateParams(var Params: TCreateParams);
begin
  inherited;
  Params.ExStyle := Params.ExStyle or WS_EX_APPWINDOW;
end;

Then you can use ITaskbarList3.SetProgressState and ITaskbarList3.SetProgressValue, passing your form's handle, to display taskbar progress for your form's taskbar button.


I must admit I find your code odd:

FormHandle := FindWindow('TfmProg', NIL);
TaskbarList.addTab(FormHandle);

Since the code is running in your DLL, which also created the form, you shouldn't be using FindWindow to obtain the handle. You can just use Form.Handle where Form is the reference to your form instance. That said, I'd still prefer the approach outlined above, using WS_EX_APPWINDOW, since it is resilient to window handle re-creation and feels rather simpler to me.

Sign up to request clarification or add additional context in comments.

1 Comment

Thanks @DavidHeffernan. That did the trick. I had tried something similar previously but must have gotten the syntax wrong. I probably forgot the override. An example is a wonderful thing. cheers.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.