【问题标题】:How can I create an ITaskbarList3 in C++ Builder?如何在 C++ Builder 中创建 ITaskbarList3?
【发布时间】:2013-01-30 22:12:26
【问题描述】:

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

这是我目前所拥有的:

我的 .cpp 文件中有一个全局变量来存储 TaskbarButtonCreated 的自定义消息 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 的返回值始终为真。我还确认我的 WndProcExt 函数接收到各种 Windows 消息,而不是我要查找的消息。 OnTaskbarBtnCreated 函数永远不会被调用。

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

【问题讨论】:

    标签: c++ winapi windows-7 taskbar c++builder-2010


    【解决方案1】:

    让 TForm 为它自己的 WindowProc 属性赋值并不是一个好主意。对于初学者,Handle 窗口可能在进入构造函数之前就已经分配,​​由于 DFM 流,因此在构造函数开始运行之前,您会错过窗口的所有初始消息(可能有多个消息)。您需要改写虚拟 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 窗口被(重新)分配(在Form 的生命周期内可能发生多次)时调用它,因此您需要覆盖虚拟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+ 相关的功能,例如 Flip 3D 和任务栏预览)。否则,您将不得不使用TApplication::HookMainWindow() 方法拦截任何可能发送到TApplication 窗口的“TaskbarButtonCreated”消息。

    【讨论】:

    • 我概述的内容在 BCB 6 中对我有用,但我必须做其他事情才能使 VCL 在 Vista+ 中运行。由于您使用的是 2010,因此我怀疑问题出在 TApplication::ShowMainFormOnTaskbar 属性上。它通常会影响TApplicationMainForm 与任务栏的交互方式。它需要设置为true,以便MainForm 窗口管理任务栏按钮。否则,请尝试使用TApplication::HookMainWindow() 方法拦截“TaskbarButtonCreated”消息,如果它在管理按钮时被发送到TApplication 窗口。
    • C++ Builder XE6(可能更早)已经自行处理TaskbarButtonCreated,但遗憾的是没有调用ChangeWindowMessageFilterEx
    • @MartinPrikrl:我假设您指的是 XE6 中添加的新 TTaskbar 组件?仅供参考,那个组件 has a bug 使它在 Vista 和更早版本上难以崩溃。
    • 很高兴知道。这使它双重无用。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-01-01
    • 1970-01-01
    • 2016-12-21
    • 2011-09-27
    相关资源
    最近更新 更多