2

我正在尝试使用 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 的返回值始终为 true。我还确认我的 WndProcExt 函数接收到各种 Windows 消息,但不是我要查找的消息。OnTaskbarBtnCreated 函数永远不会被调用。

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

4

1 回答 1

4

让 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();
}

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

于 2013-01-31T04:38:26.003 回答