2025-11-28 00:35:46 +09:00

210 lines
7.2 KiB
C++

// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
// PARTICULAR PURPOSE.
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
#include <windows.h>
#include <strsafe.h>
#include <shobjidl.h> // For ITaskbarList3
#include "resource.h"
#pragma comment(linker, "\"/manifestdependency:type='Win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='*' publicKeyToken='6595b64144ccf1df' language='*'\"")
#define MAX_PROGRESS_IND 50
#define MAX_PROGRESS_NORMAL 50
HINSTANCE g_hInstance = NULL;
ITaskbarList3 *g_pTaskbarList = NULL; // careful, COM objects should only be accessed from apartment they are created in
UINT_PTR g_nTimerId = 0;
int g_nProgress = 0;
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
static UINT s_uTBBC = WM_NULL;
if (s_uTBBC == WM_NULL)
{
// Compute the value for the TaskbarButtonCreated message
s_uTBBC = RegisterWindowMessage(L"TaskbarButtonCreated");
// In case the application is run elevated, allow the
// TaskbarButtonCreated message through.
ChangeWindowMessageFilter(s_uTBBC, MSGFLT_ADD);
}
if (message == s_uTBBC)
{
// Once we get the TaskbarButtonCreated message, we can call methods
// specific to our window on a TaskbarList instance. Note that it's
// possible this message can be received multiple times over the lifetime
// of this window (if explorer terminates and restarts, for example).
if (!g_pTaskbarList)
{
HRESULT hr = CoCreateInstance(CLSID_TaskbarList, NULL, CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&g_pTaskbarList));
if (SUCCEEDED(hr))
{
hr = g_pTaskbarList->HrInit();
if (FAILED(hr))
{
g_pTaskbarList->Release();
g_pTaskbarList = NULL;
}
}
}
}
else switch (message)
{
case WM_COMMAND:
{
int const wmId = LOWORD(wParam);
switch (wmId)
{
case IDM_OVERLAY1:
case IDM_OVERLAY2:
case IDM_OVERLAY_CLEAR:
if (g_pTaskbarList)
{
// Choose which icon to set as the overlay
HICON hIcon = NULL; // for IDM_OVERLAY_CLEAR
if (wmId == IDM_OVERLAY1)
{
hIcon = LoadIcon(g_hInstance, MAKEINTRESOURCE(IDI_OVERLAY1));
}
else if (wmId == IDM_OVERLAY2)
{
hIcon = LoadIcon(g_hInstance, MAKEINTRESOURCE(IDI_OVERLAY2));
}
// Set the window's overlay icon, possibly NULL value
g_pTaskbarList->SetOverlayIcon(hWnd, hIcon, NULL);
if (hIcon)
{
// need to cleanup the icon as we no longer need it
DestroyIcon(hIcon);
}
}
break;
case IDM_SIMULATEPROGRESS:
// If simulated progress isn't underway, start it
if (g_pTaskbarList && g_nTimerId == 0)
{
g_nTimerId = SetTimer(hWnd, 1, 50, NULL);
g_nProgress = 0;
}
break;
case IDM_EXIT:
DestroyWindow(hWnd);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
break;
}
case WM_TIMER:
g_nProgress++;
if (g_nProgress == 1)
{
// First time through, so we'll set our progress state to
// be indeterminate - this simulates a background computation
// to figure out how much progress we'll need.
g_pTaskbarList->SetProgressState(hWnd, TBPF_INDETERMINATE);
}
else if (g_nProgress == MAX_PROGRESS_IND)
{
// Now set the progress state to indicate we have some normal
// progress to show.
g_pTaskbarList->SetProgressValue(hWnd, 0, MAX_PROGRESS_NORMAL);
g_pTaskbarList->SetProgressState(hWnd, TBPF_NORMAL);
}
else if (g_nProgress > MAX_PROGRESS_IND)
{
if (g_nProgress - MAX_PROGRESS_IND <= MAX_PROGRESS_NORMAL)
{
// Now show normal progress to simulate a background operation
g_pTaskbarList->SetProgressValue(hWnd, g_nProgress - MAX_PROGRESS_IND, MAX_PROGRESS_NORMAL);
}
else
{
// Progress is done, stop the timer and reset progress state
KillTimer(hWnd, g_nTimerId);
g_nTimerId = 0;
g_pTaskbarList->SetProgressState(hWnd, TBPF_NOPROGRESS);
MessageBox(hWnd, L"Done!", L"Progress Complete", MB_OK);
}
}
break;
case WM_DESTROY:
if (g_nTimerId)
{
KillTimer(hWnd, g_nTimerId);
g_nTimerId = 0;
}
if (g_pTaskbarList)
{
g_pTaskbarList->Release();
g_pTaskbarList = NULL;
}
PostQuitMessage(0);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
return 0;
}
int APIENTRY wWinMain(HINSTANCE hInstance, HINSTANCE, PWSTR, int nCmdShow)
{
g_hInstance = hInstance;
HRESULT hrInit = CoInitialize(NULL); // Initialize COM so we can call CoCreateInstance
if (SUCCEEDED(hrInit))
{
WCHAR const szWindowClass[] = L"PeripheralStatusWnd"; // The main window class name
WNDCLASSEX wc = { sizeof(wc) };
wc.lpfnWndProc = WndProc;
wc.hInstance = hInstance;
wc.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_APP));
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
wc.lpszMenuName = MAKEINTRESOURCE(IDC_PERIPHERALSTATUS);
wc.lpszClassName = szWindowClass;
RegisterClassEx(&wc);
WCHAR szTitle[100];
LoadString(hInstance, IDS_APP_TITLE, szTitle, ARRAYSIZE(szTitle));
HWND hWnd = CreateWindowEx(0, szWindowClass, szTitle, WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, CW_USEDEFAULT, 400, 400, NULL, NULL, hInstance, NULL);
if (hWnd)
{
ShowWindow(hWnd, nCmdShow);
UpdateWindow(hWnd);
// Main message loop:
MSG msg;
while (GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
CoUninitialize();
}
return 0;
}