summaryrefslogtreecommitdiff
path: root/shared/Taskbar_Seven/taskbar.cpp
blob: 4baf23925ae9dc168d74397b9d38b2fb59634d76 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
// **************************************************************************
// * This file is part of the FreeFileSync project. It is distributed under *
// * GNU General Public License: http://www.gnu.org/licenses/gpl.html       *
// * Copyright (C) 2008-2010 ZenJu (zhnmju123 AT gmx.de)                    *
// **************************************************************************
//
#include "taskbar.h"

#define WIN32_LEAN_AND_MEAN
#include "windows.h"
#include <ShObjIdl.h>

#include <map>
#include <string>
#include <comdef.h>


namespace
{
void writeString(const std::wstring& input, wchar_t* output, size_t outputBufferLen)
{
    const size_t newSize = min(input.length() + 1, outputBufferLen); //including null-termination
    memcpy(output, input.c_str(), newSize * sizeof(wchar_t));
    output[newSize-1] = 0; //if output buffer is too small...
}


std::wstring numberToHexString(const long number)
{
    wchar_t result[100];
    swprintf(result, 100, L"0x%08x", number);
    return std::wstring(result);
}


std::wstring writeErrorMsg(const wchar_t* input, HRESULT hr)
{
    std::wstring output(input);
    output += L" (";
    output += numberToHexString(hr);
    output += L": ";
    output += _com_error(hr).ErrorMessage();
    output += L")";
    return output;
}


using TaskbarSeven::TBHandle;
typedef std::map<TBHandle, ITaskbarList3*> TaskBarHandleMap;

TaskbarSeven::TBHandle generateHandle()
{
    static TBHandle handle = 0;
    return ++handle; //don't return 0! 0 is reserved for indicating failure
}

TaskBarHandleMap taskBarHandles;

std::wstring lastErrorMessage;
}
//##################################################################################################


TaskbarSeven::TBHandle TaskbarSeven::init() //call on app initializaiton; returns handle
{
    ITaskbarList3* pto = NULL;
    HRESULT hr = CoCreateInstance(CLSID_TaskbarList,
                                  NULL,
                                  CLSCTX_ALL,
                                  IID_PPV_ARGS(&pto));
    if (FAILED(hr))
    {
        lastErrorMessage = writeErrorMsg(L"Error calling \"CoCreateInstance\".", hr);
        return 0;
    }

    TBHandle newHandle = ::generateHandle();
    taskBarHandles[newHandle] = pto;
    return newHandle;
}


void TaskbarSeven::release(TBHandle handle) //release handle on app exit
{
    TaskBarHandleMap::const_iterator iter = taskBarHandles.find(handle);
    if (iter != taskBarHandles.end())
    {
        if (iter->second != NULL)
            iter->second->Release();
        taskBarHandles.erase(iter);
    }
}


bool TaskbarSeven::setStatus(TBHandle handle,
                             void* hwnd, //HWND: window assciated to the taskbar icon
                             TaskBarStatus status)
{
    TBPFLAG flag = TBPF_NORMAL;
    switch (status)
    {
    case STATUS_NOPROGRESS:
        flag = TBPF_NOPROGRESS;
        break;
    case STATUS_INDETERMINATE:
        flag = TBPF_INDETERMINATE;
        break;
    case STATUS_NORMAL:
        flag = TBPF_NORMAL;
        break;
    case STATUS_ERROR:
        flag = TBPF_ERROR;
        break;
    case STATUS_PAUSED:
        flag = TBPF_PAUSED;
        break;
    }

    ITaskbarList3* pto = taskBarHandles[handle];
    if (pto)
    {
        HRESULT hr = pto->SetProgressState(static_cast<HWND>(hwnd),  //[in]  HWND hwnd,
                                           flag); //[in]  TBPFLAG tbpFlags
        if (FAILED(hr))
        {
            lastErrorMessage = writeErrorMsg(L"Error calling \"SetProgressState\".", hr);
            return false;
        }
    }
    return true;
}


bool TaskbarSeven::setProgress(TBHandle handle,
                               void* hwnd, //HWND: window assciated to the taskbar icon
                               size_t current,
                               size_t total)
{
    ITaskbarList3* pto = taskBarHandles[handle];

    if (pto)
    {
        HRESULT hr = pto->SetProgressValue(
                         static_cast<HWND>(hwnd), //[in]  HWND hwnd,
                         current, //[in]  ULONGLONG ullCompleted,
                         total);  //[in]  ULONGLONG ullTotal
        if (FAILED(hr))
        {
            lastErrorMessage = writeErrorMsg(L"Error calling \"SetProgressValue\".", hr);
            return false;
        }
    }
    return true;
}


void TaskbarSeven::getLastError(wchar_t* errorMessage, size_t errorBufferLen)
{
    writeString(lastErrorMessage, errorMessage, errorBufferLen);
}
bgstack15