Windows 7最小代码实现任务栏状态

13
什么是设置已知窗口句柄的 Windows 7 任务栏按钮状态的最短代码?
目标是编写一个控制台实用程序,从批处理脚本更改控制台窗口任务栏项的进度和状态(颜色)。虽然脚本执行不同的任务,但其控制台窗口的任务栏项应表示当前状态。
我使用 GetConsoleWindow() 函数获取窗口句柄,但似乎需要大量的 COM 和 Shell API,我不理解。我找到了一个示例,使用整个具有 MFC 的 GUI 应用程序来演示该 API,但其中大部分对于我的小工具来说都太复杂了,我不理解它们足够好以删除我不需要的东西。
该工具应在 Windows 7 上使用 VS2010(C++)进行编译,但也应在早期的 Windows 版本上运行(如果未提供某个功能,则不执行任何操作)。

“任务栏状态”是什么意思?您是指仅显示进度还是其他内容? - sashoalm
是的,只需要进度和状态(不确定、暂停、错误,即绿色、黄色和红色)。没有跳转列表、缩略图或操作按钮。 - ygoe
2个回答

15
我曾经为一个项目创建了一个类来设置Win7任务栏中的进度。它是对可从Windows Shell获取的ITaskBarList3接口的封装。具体来说,它使用ITaskBarList3.SetProgressStateITaskBarList3.SetProgressValue函数实现。
这是我找到的代码:
#include <shobjidl.h>
#include <windows.h>
#pragma comment(lib, "Shell32.lib")
#pragma comment(lib, "Ole32.lib")

class Win7TaskbarProgress  
{
public:
    Win7TaskbarProgress();
    virtual ~Win7TaskbarProgress();

    void SetProgressState(HWND hwnd, TBPFLAG flag);
    void SetProgressValue(HWND hwnd, ULONGLONG ullCompleted, ULONGLONG ullTotal);

private:
    bool Init();
    ITaskbarList3* m_pITaskBarList3;
    bool m_bFailed;
};

Win7TaskbarProgress::Win7TaskbarProgress()
{
    m_pITaskBarList3 = NULL;
    m_bFailed = false;
}

Win7TaskbarProgress::~Win7TaskbarProgress()
{
    if (m_pITaskBarList3)   
    {
        m_pITaskBarList3->Release();
        CoUninitialize();
    }
}

void Win7TaskbarProgress::SetProgressState( HWND hwnd, TBPFLAG flag )
{
    if (Init())
        m_pITaskBarList3->SetProgressState(hwnd, flag);
}

void Win7TaskbarProgress::SetProgressValue( HWND hwnd, ULONGLONG ullCompleted, ULONGLONG ullTotal )
{
    if (Init())
        m_pITaskBarList3->SetProgressValue(hwnd, ullCompleted, ullTotal);
}

bool Win7TaskbarProgress::Init()
{
    if (m_pITaskBarList3)
        return true;

    if (m_bFailed)
        return false;
    
    // Initialize COM for this thread...
    CoInitialize(NULL);
    
    CoCreateInstance(CLSID_TaskbarList, NULL, CLSCTX_INPROC_SERVER, IID_ITaskbarList3, (void **)&m_pITaskBarList3);

    if (m_pITaskBarList3)
        return true;

    m_bFailed = true;
    CoUninitialize();
    return false;
}

1
我认为我需要这个:#include <ShObjIdl.h> 但是 VERIFY() 是做什么的? - ygoe
1
没什么重要的,我编辑了我的回答并将其删除了。它类似于ASSERT(),但语句在发布版本中仍会被执行。请参见http://msdn.microsoft.com/en-us/library/fcatwy09(v=vs.80).aspx。 - sashoalm
4
我已经将这个方便的小工具制作出来了,扩展了我之前仅限于Flash的功能。你可以在这里找到它:http://dev.unclassified.de/apps/flashconsolewindow - ygoe
它在多线程应用程序中无法运行。如果SetProgressState方法从工作线程中调用,则会在Release()中崩溃。 - palota

0

请注意,在SetProgressValue()生效之前,您仍然需要调用RegisterWindowMessage("TaskbarButtonCreated")ChangeWindowMessageFilterEx()来设置消息过滤器。

根据MSDN文档,每次接收到创建的消息时,您应该重新创建对象,但我发现只需执行ChangeWindowMessageFilterEx()即可在正常情况下正常工作。


1
我已经编写了一个应用程序,使用SetProgressValue函数,并且在没有使用RegisterWindowMessageChangeWindowMessageFilterEx的情况下运行得非常完美。就像往常一样,在文档中缺少很多信息。 - v77

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接