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

158 lines
6.7 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
#define NTDDI_VERSION NTDDI_WIN7 // Specifies that the minimum required platform is Windows 7.
#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers
#include <windows.h>
#include <shobjidl.h>
#include <propkey.h>
#include <propvarutil.h>
#include <shellapi.h>
#include "resource.h"
#pragma comment(linker,"/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='*' publicKeyToken='6595b64144ccf1df' language='*'\"")
WCHAR const c_szTitle[] = L"AppUserModelID Window Property Sample";
WCHAR const c_szWindowClass[] = L"APPUSERMODELIDWINDOWPROPERTY";
WCHAR const c_szAppUserModelID1[] = L"Microsoft.Samples.App1";
WCHAR const c_szAppUserModelID2[] = L"Microsoft.Samples.App2";
WCHAR const c_szAppUserModelID3[] = L"Microsoft.Samples.App3";
// Sets the specified AppUserModelID on the window, or removes the value if a negative index is provided
void SetAppID(HWND hWnd, PCWSTR pszAppID)
{
// Obtain the window's property store. This IPropertyStore implementation does not require
// IPropertyStore::Commit to be called - values are updated on the window immediately. Setting a
// property on a window via this IPropertyStore allocates global storage space for the property value
// that is not automatically cleaned up upon window destruction or process termination, thus all
// properties set on a window should be removed in response to WM_DESTROY.
IPropertyStore *pps;
HRESULT hr = SHGetPropertyStoreForWindow(hWnd, IID_PPV_ARGS(&pps));
if (SUCCEEDED(hr))
{
PROPVARIANT pv;
if (pszAppID)
{
hr = InitPropVariantFromString(pszAppID, &pv);
}
else
{
// Sets the variant type as VT_EMPTY, which removes the property from the window, if present
PropVariantInit(&pv);
}
if (SUCCEEDED(hr))
{
// Sets the PKEY_AppUserModel_ID property, which controls how windows are grouped into buttons
// on the taskbar. If the window needed other PKEY_AppUserModel_* properties to be set, they
// should be set BEFORE setting PKEY_AppUserModel_ID, as the taskbar will only respond to
// updates of PKEY_AppUserModel_ID.
hr = pps->SetValue(PKEY_AppUserModel_ID, pv);
PropVariantClear(&pv);
}
pps->Release();
}
}
// All windows with the same AppUserModelID will group together. Changing a window's AppUserModelID will cause
// the taskbar to reassign it to a different group.
//
// NOTE: All AppUserModelID values used here are for sample purposes only. Applications should define their
// own values in the form of CompanyName.ProductName.SubProduct.VersionInformation. See the "Application User
// Model IDs (AppIDs)" MSDN topic for more information.
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message)
{
case WM_CREATE:
// Set an initial AppUserModelID on the window, before the window is presented in the taskbar. If
// the value is set after this time, the window may visibly change groups in the taskbar. This may
// be desireable if, as this sample illustrates, the window can change identities throughout its
// lifetime. However, if the window's identity will not change, then the value should be set here,
// or the window should be created hidden and shown only once the value has been set to prevent the
// window's taskbar representation from jumping around quickly as the window is created and then
// assigned an explicit AppUserModelID.
//
// All windows with the same AppUserModelID will group together. Changing a window's AppUserModelID
// will cause the taskbar to reassign it to a different group. Windows without an explicitly set
// AppUserModelID will group together, but separate from any windows with an explicit value.
SetAppID(hWnd, c_szAppUserModelID1);
break;
case WM_COMMAND:
{
int const wmId = LOWORD(wParam);
// Parse the menu selections
switch (wmId)
{
case IDM_EXIT:
DestroyWindow(hWnd);
break;
case IDM_FILE_APPID1:
// Set the first AppUserModelID on the window, replacing the previous value
SetAppID(hWnd, c_szAppUserModelID1);
break;
case IDM_FILE_APPID2:
// Set the second AppUserModelID on the window, replacing the previous value
SetAppID(hWnd, c_szAppUserModelID2);
break;
case IDM_FILE_APPID3:
// Set the third AppUserModelID on the window, replacing the previous value
SetAppID(hWnd, c_szAppUserModelID3);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
break;
}
case WM_DESTROY:
// Remove any AppUserModelID value set on this window. This must be done before the window
// is completely destroyed, or the value will be leaked.
SetAppID(hWnd, NULL);
PostQuitMessage(0);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
return 0;
}
int APIENTRY wWinMain(HINSTANCE hInstance, HINSTANCE, PWSTR, int nCmdShow)
{
HRESULT hr = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED | COINIT_DISABLE_OLE1DDE);
if (SUCCEEDED(hr))
{
WNDCLASSEX wcex = {sizeof(wcex)};
wcex.style = CS_HREDRAW | CS_VREDRAW;
wcex.lpfnWndProc = WndProc;
wcex.hInstance = hInstance;
wcex.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_CUSTOMJUMPLISTSAMPLE));
wcex.hCursor = LoadCursor(NULL, IDC_ARROW);
wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
wcex.lpszMenuName = MAKEINTRESOURCE(IDC_CUSTOMJUMPLISTSAMPLE);
wcex.lpszClassName = c_szWindowClass;
RegisterClassEx(&wcex);
HWND hWnd = CreateWindow(c_szWindowClass, c_szTitle, WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, 0, 300, 200, NULL, NULL, hInstance, NULL);
if (hWnd)
{
ShowWindow(hWnd, nCmdShow);
MSG msg;
while (GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
CoUninitialize();
}
return 0;
}