c++ - 无法将缩略图按钮添加到窗口?

标签 c++ windows winapi

我正在尝试向窗口添加缩略图按钮,但没有出现错误,也没有显示缩略图按钮。我阅读了以下页面以供引用:

  1. Your First Windows Program ;

  2. ITaskbarList3::ThumbBarAddButtons method ;

  3. some code on github .

环境:win10 64位,vs2015

// function WindowProc and wWinMain are copied from msdn directly.

#include "stdafx.h"
#include <windows.h>
#include "shobjidl.h" 
#include <exception>


LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);

HRESULT addThumbnailButtons(HWND hwnd) {
    HRESULT hr = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED | COINIT_DISABLE_OLE1DDE);
    if (SUCCEEDED(hr)) {
        ITaskbarList4* ptbl = nullptr;
        HRESULT hr = CoCreateInstance(CLSID_TaskbarList, NULL, CLSCTX_INPROC_SERVER,
            IID_PPV_ARGS(&ptbl));

        if (SUCCEEDED(hr)) {
            // create 2 buttons
            THUMBBUTTON thmb[2] = {};

            thmb[0].dwMask = THB_TOOLTIP;
            thmb[0].iId = 0;
            wcscpy_s(thmb[0].szTip, L"Button 1");

            thmb[1].dwMask = THB_TOOLTIP;
            thmb[1].iId = 1;
            wcscpy_s(thmb[1].szTip, L"Button 2");

            //ptbl->HrInit();
            hr = ptbl->ThumbBarAddButtons(hwnd, ARRAYSIZE(thmb), thmb);

            ptbl->Release();

            return hr;
        }
        else {
            throw std::exception("createInstance failed");
        }
    }else{
        throw std::exception("coinitialize failed");
    }
}

int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE, PWSTR pCmdLine, int nCmdShow)
{
    // Register the window class.
    const wchar_t CLASS_NAME[] = L"Sample Window Class";

    WNDCLASS wc = {};

    wc.lpfnWndProc = WindowProc;
    wc.hInstance = hInstance;
    wc.lpszClassName = CLASS_NAME;

    RegisterClass(&wc);

    // Create the window.

    HWND hwnd = CreateWindowEx(
        0,                              // Optional window styles.
        CLASS_NAME,                     // Window class
        L"Learn to Program Windows",    // Window text
        WS_OVERLAPPEDWINDOW,            // Window style

                                        // Size and position
        CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,

        NULL,       // Parent window    
        NULL,       // Menu
        hInstance,  // Instance handle
        NULL        // Additional application data
    );

    if (hwnd == NULL)
    {
        return 0;
    }

    HRESULT hr = addThumbnailButtons(hwnd);
    if (FAILED(hr)) {
        throw std::exception("addbuttons failed");
    }

    ShowWindow(hwnd, nCmdShow);

    // Run the message loop.

    MSG msg = {};
    while (GetMessage(&msg, NULL, 0, 0))
    {
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }

    return 0;
}

LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
    switch (uMsg)
    {
    case WM_DESTROY:
        PostQuitMessage(0);
        return 0;

    case WM_PAINT:
    {
        PAINTSTRUCT ps;
        HDC hdc = BeginPaint(hwnd, &ps);

        FillRect(hdc, &ps.rcPaint, (HBRUSH)(COLOR_WINDOW + 1));

        EndPaint(hwnd, &ps);
    }
    return 0;

    }
    return DefWindowProc(hwnd, uMsg, wParam, lParam);
}

最佳答案

根据 ITaskBarList3文档:

When an application displays a window, its taskbar button is created by the system. When the button is in place, the taskbar sends a TaskbarButtonCreated message to the window. Your application should call RegisterWindowMessage(L"TaskbarButtonCreated") and handle that message in its wndproc. That message must be received by your application before it calls any ITaskbarList3 method.

在调用 addThumbnailButtons() 之前必须等待该消息,例如:

UINT uMsgTaskbarCreated;

int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE, PWSTR pCmdLine, int nCmdShow)
{
    uMsgTaskbarCreated = RegisterWindowMessage(L"TaskbarButtonCreated");

    // Register the window class.
    const wchar_t CLASS_NAME[] = L"Sample Window Class";

    WNDCLASS wc = {};

    wc.lpfnWndProc = WindowProc;
    wc.hInstance = hInstance;
    wc.lpszClassName = CLASS_NAME;

    RegisterClass(&wc);

    // Create the window.

    HWND hwnd = CreateWindowEx(
        0,                              // Optional window styles.
        CLASS_NAME,                     // Window class
        L"Learn to Program Windows",    // Window text
        WS_OVERLAPPEDWINDOW,            // Window style

                                        // Size and position
        CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,

        NULL,       // Parent window    
        NULL,       // Menu
        hInstance,  // Instance handle
        NULL        // Additional application data
    );

    if (hwnd == NULL)
    {
        return 0;
    }

    ShowWindow(hwnd, nCmdShow);

    // Run the message loop.

    MSG msg = {};
    while (GetMessage(&msg, NULL, 0, 0))
    {
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }

    return 0;
}

LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
    switch (uMsg)
    {
        case WM_DESTROY:
            PostQuitMessage(0);
            return 0;

        case WM_PAINT:
        {
            PAINTSTRUCT ps;
            HDC hdc = BeginPaint(hwnd, &ps);

            FillRect(hdc, &ps.rcPaint, (HBRUSH)(COLOR_WINDOW + 1));

            EndPaint(hwnd, &ps);
            return 0;
        }

        default:
            if ((uMsg == uMsgTaskbarCreated) && (uMsgTaskbarCreated != 0))
            {
                HRESULT hr = addThumbnailButtons(hwnd);
                if (FAILED(hr)) {
                    ...;
                }
            }
            break;
        }

    return DefWindowProc(hwnd, uMsg, wParam, lParam);
}

关于c++ - 无法将缩略图按钮添加到窗口?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38028623/

相关文章:

c++ - 将 DWORD 显式初始化为 1,但调试器显示超出范围的值

c++ - 如何在 C++ 中更改 freeglut 主窗口图标?

c++ - VCL 形成写入 stdout 的应用程序

c++ - Boost:仅安装 header

c++ - 如何检测 Windows 资源管理器是否显示给定文件夹?

c++ - 属性绑定(bind)导致错误,对象位置在插入时中断

windows - Microsoft 是否有关于在不同 Windows 平台上存储应用程序数据与用户数据的最佳实践文档?

c++ - 如何从内核模式 WFP 标注驱动程序调用 NtUserPostMessage?

c++ - C++ 标准中的什么措辞允许 static_cast<non-void-type*>(malloc(N));去工作?

c++ - 在这种情况下我是否需要清空 map 的内容以避免内存泄漏