如何在C++生成器中创建 ITaskbarList3

How can I create an ITaskbarList3 in C++ Builder?

本文关键字:创建 ITaskbarList3 C++      更新时间:2023-10-16

我正在尝试使用Windows 7引入的ITaskbarList3界面,以便我可以在任务栏图标中显示冗长任务的任务进度。 文档指出,在尝试初始化我的 ITaskbarList3 组件之前,我应该等待 TaskbarButtonCreated 消息,但我似乎没有收到任何 TaskbarButtonCreated 消息。

这是我到目前为止所拥有的:

我的.cpp文件中有一个全局变量来存储任务栏按钮创建的自定义消息ID。

static const UINT m_uTaskbarBtnCreatedMsg = 
    RegisterWindowMessage( _T("TaskbarButtonCreated") );

我创建了一个单独的 WndProc 函数来处理新消息。

void __fastcall TForm1::WndProcExt(TMessage &Message)
{
    if(Message.Msg == uTaskbarBtnCreatedMsg && uTaskbarBtnCreatedMsg != 0) {
        OnTaskbarBtnCreated();
    }
    else {
        WndProc(Message);
    }
}

在我的窗体构造函数中,第一行将 WindowProc 属性设置为 WndProcExt 以路由消息。 我还尝试在ChangeWindowMessageFilter中折腾,以查看TaskbarButtonCreated消息是否由于某种原因而被过滤。

__fastcall TForm1::TForm1(TComponent* Owner) : TForm(Owner)
{
    WindowProc = WndProcExt;
    ChangeWindowMessageFilterEx(Handle, uTaskbarBtnCreatedMsg, MSGFLT_ALLOW, NULL);
    ...
}

在调试器中,来自 ChangeWindowMessageFilterEx 的返回值始终为 true。 我还确认我的WndProcExt函数接收各种Windows消息,只是不是我要找的那个。 OnTaskbarBtnCreated 函数永远不会被调用。

我错过了一步吗? 消息是否在我的消息处理程序准备就绪之前被筛选掉或发送?

让 TForm 为其自己的 WindowProc 属性分配值不是一个好主意。 对于初学者来说,由于 DFM 流,Handle窗口可能在进入构造函数之前就已经分配了,因此在构造函数开始运行之前,您将错过窗口的所有初始消息(可能有几个)。 您需要重写虚拟WndProc()方法,并将 TaskbarButtonCreated 消息传递给默认处理程序,不要阻止它:

static const UINT m_uTaskbarBtnCreatedMsg = RegisterWindowMessage( _T("TaskbarButtonCreated") );
void __fastcall TForm1::WndProc(TMessage &Message)
{
    TForm::WndProc(Message);
    if ((Message.Msg == uTaskbarBtnCreatedMsg) && (uTaskbarBtnCreatedMsg != 0))
        OnTaskbarBtnCreated();
}

至于ChangeWindowMessageFilterEx(),您需要在每次 TForm 的Handle窗口被(重新)分配时调用它(在表单的生命周期中可能会发生多次),因此您需要重写虚拟CreateWnd()方法:

void __fastcall TForm1::CreateWnd()
{
    TForm::CreateWnd();
    if (CheckWin32Version(6, 1) && (uTaskbarBtnCreatedMsg != 0))
        ChangeWindowMessageFilterEx(Handle, uTaskbarBtnCreatedMsg, MSGFLT_ALLOW, NULL);
    // any other Handle-specific registrations, etc...
}
void __fastcall TForm1::DestroyWindowHandle()
{
    // any Handle-specific de-registrations, etc...
    TForm::DestroyWindowHandle();
}

最后,在创建MainForm之前,将项目的WinMain()函数中的 TApplication::ShowMainFormOnTaskbar 属性设置为true,以便其窗口(而不是TApplication窗口)管理任务栏按钮(并启用其他与 Vista+ 相关的功能,如翻转 3D 和任务栏预览)。 否则,您将不得不使用 TApplication::HookMainWindow() 方法来拦截可能发送到TApplication窗口的任何"任务栏按钮创建"消息。