我正在尝试使用Windows 7引入的ITaskbarList3接口(interface),以便可以在任务栏图标中显示冗长任务的任务进度。该文档指出,在尝试初始化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函数永远不会被调用。

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

最佳答案

让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窗口每次被(重新)分配时调用(在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 +相关的功能,例如Flip 3D和任务栏预览)。否则,您将必须使用TApplication::HookMainWindow()方法来拦截可能发送到TApplication窗口的任何“TaskbarButtonCreated”消息。

10-06 10:38