mirror of
https://github.com/Blinue/Magpie.git
synced 2026-06-24 02:04:10 +00:00
feat: WindowCase 支持模拟不同类型的光标
This commit is contained in:
parent
17497bbfe9
commit
fb4c3b183d
23 changed files with 334 additions and 51 deletions
|
|
@ -11,7 +11,7 @@ static winrt::com_ptr<IPresentationFactory> CreatePresentationFactory(ID3D11Devi
|
|||
winrt::com_ptr<IPresentationFactory> result;
|
||||
|
||||
static const auto createPresentationFactory =
|
||||
Win32Helper::LoadSystemFunction<decltype(::CreatePresentationFactory)>(
|
||||
Win32Helper::LoadFunction<decltype(::CreatePresentationFactory)>(
|
||||
L"dcomp.dll", "CreatePresentationFactory");
|
||||
if (!createPresentationFactory) {
|
||||
return result;
|
||||
|
|
|
|||
|
|
@ -225,7 +225,7 @@ void CursorManager::_ShowSystemCursor(bool show, bool onDestory) {
|
|||
}
|
||||
|
||||
static const auto showSystemCursor =
|
||||
Win32Helper::LoadSystemFunction<void WINAPI(BOOL)>(L"user32.dll", "ShowSystemCursor");
|
||||
Win32Helper::LoadFunction<void WINAPI(BOOL)>(L"user32.dll", "ShowSystemCursor");
|
||||
|
||||
if (showSystemCursor) {
|
||||
showSystemCursor((BOOL)show);
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@
|
|||
|
||||
namespace Magpie {
|
||||
|
||||
using DwmGetDxSharedSurfaceFunc = BOOL(
|
||||
using FnDwmGetDxSharedSurface = BOOL WINAPI(
|
||||
HWND hWnd,
|
||||
HANDLE* phSurface,
|
||||
LUID* pAdapterLuid,
|
||||
|
|
@ -17,11 +17,11 @@ using DwmGetDxSharedSurfaceFunc = BOOL(
|
|||
ULONGLONG* pWin32KUpdateId
|
||||
);
|
||||
|
||||
static DwmGetDxSharedSurfaceFunc* DwmGetDxSharedSurface = nullptr;
|
||||
static FnDwmGetDxSharedSurface* DwmGetDxSharedSurface = nullptr;
|
||||
|
||||
bool DwmSharedSurfaceFrameSource::_Initialize() noexcept {
|
||||
[[maybe_unused]] static Ignore _ = [] {
|
||||
DwmGetDxSharedSurface = Win32Helper::LoadSystemFunction<DwmGetDxSharedSurfaceFunc>(
|
||||
DwmGetDxSharedSurface = Win32Helper::LoadFunction<FnDwmGetDxSharedSurface>(
|
||||
L"user32.dll", "DwmGetDxSharedSurface");
|
||||
return Ignore();
|
||||
}();
|
||||
|
|
|
|||
|
|
@ -98,7 +98,7 @@ ScalingError Renderer2::Initialize(
|
|||
|
||||
_presenter = std::make_unique<SwapChainPresenter>();
|
||||
if (!_presenter->Initialize(_graphicsContext, hwndAttach, size, _colorInfo)) {
|
||||
Logger::Get().Error("初始化 SwapChainPresenter 失败");
|
||||
Logger::Get().Error("SwapChainPresenter::Initialize 失败");
|
||||
return ScalingError::ScalingFailedGeneral;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -187,7 +187,7 @@ bool SrcTracker::UpdateState(
|
|||
// 不要使用 IsHungAppWindow,它有误报的情况,见 GH#1244。这里用了未记录函数
|
||||
// GhostWindowFromHungWindow,它可以准确检查源窗口是否已被替换为幽灵窗口。
|
||||
static const auto ghostWindowFromHungWindow =
|
||||
Win32Helper::LoadSystemFunction<HWND WINAPI(HWND)>(
|
||||
Win32Helper::LoadFunction<HWND WINAPI(HWND)>(
|
||||
L"user32.dll", "GhostWindowFromHungWindow");
|
||||
if (ghostWindowFromHungWindow && ghostWindowFromHungWindow(_hWnd)) {
|
||||
// 检查源窗口是否真的处于无响应状态
|
||||
|
|
|
|||
|
|
@ -135,7 +135,7 @@ static void WaitForDwmComposition() noexcept {
|
|||
// Win11 可以使用准确的 DCompositionWaitForCompositorClock
|
||||
if (Win32Helper::GetOSVersion().IsWin11()) {
|
||||
static const auto dCompositionWaitForCompositorClock =
|
||||
Win32Helper::LoadSystemFunction<decltype(DCompositionWaitForCompositorClock)>(
|
||||
Win32Helper::LoadFunction<decltype(DCompositionWaitForCompositorClock)>(
|
||||
L"dcomp.dll", "DCompositionWaitForCompositorClock");
|
||||
if (dCompositionWaitForCompositorClock) {
|
||||
dCompositionWaitForCompositorClock(0, nullptr, INFINITE);
|
||||
|
|
|
|||
|
|
@ -54,7 +54,7 @@ wil::unique_process_handle Win32Helper::GetWindowProcessHandle(HWND hWnd) noexce
|
|||
|
||||
// 在某些窗口上 OpenProcess 会失败(如暗黑 2),尝试使用 GetProcessHandleFromHwnd
|
||||
static const auto getProcessHandleFromHwnd =
|
||||
Win32Helper::LoadSystemFunction<HANDLE WINAPI(HWND)>(L"Oleacc.dll", "GetProcessHandleFromHwnd");
|
||||
Win32Helper::LoadFunction<HANDLE WINAPI(HWND)>(L"Oleacc.dll", "GetProcessHandleFromHwnd");
|
||||
if (!getProcessHandleFromHwnd) {
|
||||
return result;
|
||||
}
|
||||
|
|
@ -426,7 +426,7 @@ bool Win32Helper::CreateDir(const std::wstring& path, bool recursive) noexcept {
|
|||
const Win32Helper::OSVersion& Win32Helper::GetOSVersion() noexcept {
|
||||
static OSVersion version = [] {
|
||||
const auto rtlGetVersion =
|
||||
LoadSystemFunction<LONG WINAPI(PRTL_OSVERSIONINFOW)>(L"ntdll.dll", "RtlGetVersion");
|
||||
LoadFunction<LONG WINAPI(PRTL_OSVERSIONINFOW)>(L"ntdll.dll", "RtlGetVersion");
|
||||
if (!rtlGetVersion) {
|
||||
return OSVersion();
|
||||
}
|
||||
|
|
@ -885,7 +885,7 @@ void Win32Helper::WaitForDwmComposition() noexcept {
|
|||
// Win11 可以使用准确的 DCompositionWaitForCompositorClock
|
||||
if (Win32Helper::GetOSVersion().IsWin11()) {
|
||||
static const auto dCompositionWaitForCompositorClock =
|
||||
Win32Helper::LoadSystemFunction<decltype(DCompositionWaitForCompositorClock)>(
|
||||
Win32Helper::LoadFunction<decltype(DCompositionWaitForCompositorClock)>(
|
||||
L"dcomp.dll", "DCompositionWaitForCompositorClock");
|
||||
if (dCompositionWaitForCompositorClock) {
|
||||
dCompositionWaitForCompositorClock(0, nullptr, INFINITE);
|
||||
|
|
|
|||
|
|
@ -187,7 +187,7 @@ struct Win32Helper {
|
|||
static const std::filesystem::path& GetExePath() noexcept;
|
||||
|
||||
template<typename T, std::enable_if_t<std::is_function_v<T>, int> = 0>
|
||||
static T* LoadSystemFunction(const wchar_t* dllName, const char* funcName) noexcept {
|
||||
static T* LoadFunction(const wchar_t* dllName, const char* funcName) noexcept {
|
||||
assert(dllName && funcName);
|
||||
|
||||
HMODULE hMod = GetModuleHandle(dllName);
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@ bool SmoothResizeHelper::EnableResizeSync(HWND hWnd, const winrt::Application& a
|
|||
// UWP 使用这个未记录的接口实现平滑调整尺寸
|
||||
// https://gist.github.com/apkipa/20cae438aef2a8633f99e10e0b90b11e
|
||||
static auto enableResizeLayoutSynchronization =
|
||||
Win32Helper::LoadSystemFunction<void WINAPI(HWND hwnd, BOOL enable)>(
|
||||
Win32Helper::LoadFunction<void WINAPI(HWND hwnd, BOOL enable)>(
|
||||
L"user32.dll", MAKEINTRESOURCEA(2615));
|
||||
|
||||
// 检查是否支持 IFrameworkApplicationPrivate 接口
|
||||
|
|
|
|||
244
tools/WindowCase/CursorWindow.cpp
Normal file
244
tools/WindowCase/CursorWindow.cpp
Normal file
|
|
@ -0,0 +1,244 @@
|
|||
#include "pch.h"
|
||||
#include "CursorWindow.h"
|
||||
|
||||
static HCURSOR CreateCursorFromBitmaps(HBITMAP hColorBitmap, HBITMAP hMaskBitmap) noexcept {
|
||||
ICONINFO iconInfo = {
|
||||
.fIcon = FALSE,
|
||||
.xHotspot = 0,
|
||||
.yHotspot = 0,
|
||||
.hbmMask = hMaskBitmap,
|
||||
.hbmColor = hColorBitmap
|
||||
};
|
||||
return CreateIconIndirect(&iconInfo);
|
||||
}
|
||||
|
||||
static HCURSOR CreateColorCursor() noexcept {
|
||||
const uint32_t width = (uint32_t)GetSystemMetrics(SM_CXCURSOR);
|
||||
const uint32_t height = (uint32_t)GetSystemMetrics(SM_CYCURSOR);
|
||||
|
||||
// 颜色位图初始化为半透明红色
|
||||
std::vector<uint32_t> colorBits(width * height, 0x80FF0000);
|
||||
|
||||
wil::unique_hbitmap hColorBitmap(CreateBitmap(width, height, 1, 32, colorBits.data()));
|
||||
// 仍需要遮罩位图,不过既然颜色位图有透明通道,遮罩位图不会被使用,因此无需初始化
|
||||
wil::unique_hbitmap hMaskBitmap(CreateBitmap(width, height, 1, 1, nullptr));
|
||||
return CreateCursorFromBitmaps(hColorBitmap.get(), hMaskBitmap.get());
|
||||
}
|
||||
|
||||
static HCURSOR CreateMonochromeCursor() noexcept {
|
||||
const uint32_t width = (uint32_t)GetSystemMetrics(SM_CXCURSOR);
|
||||
const uint32_t height = (uint32_t)GetSystemMetrics(SM_CYCURSOR);
|
||||
|
||||
// width 必定是 16 的倍数,因此遮罩位图每行都已按 WORD 对齐
|
||||
assert(width % 16 == 0);
|
||||
const uint32_t widthByteCount = width / 8;
|
||||
// 单色光标无颜色位图,遮罩位图高度是光标高度的两倍
|
||||
const uint32_t bitmapHeight = height * 2;
|
||||
|
||||
// 分为四个部分:
|
||||
// 左上:白色 (AND=0, XOR=1)
|
||||
// 右上:黑色 (AND=0, XOR=0)
|
||||
// 左下:反色 (AND=1, XOR=1)
|
||||
// 右下:透明 (AND=1, XOR=0)
|
||||
assert(width % 16 == 0);
|
||||
std::vector<uint8_t> maskBits(widthByteCount * bitmapHeight);
|
||||
|
||||
// AND 遮罩下半置 1
|
||||
for (uint32_t y = height / 2; y < height; ++y) {
|
||||
for (uint32_t x = 0; x < width; ++x) {
|
||||
uint32_t byteIdx = y * widthByteCount + x / 8;
|
||||
uint32_t bitIdx = 7 - (x % 8);
|
||||
maskBits[byteIdx] |= 1 << bitIdx;
|
||||
}
|
||||
}
|
||||
|
||||
// XOR 遮罩左半置 1
|
||||
for (uint32_t y = height; y < bitmapHeight; ++y) {
|
||||
for (uint32_t x = 0; x < width / 2; ++x) {
|
||||
uint32_t byteIdx = y * widthByteCount + x / 8;
|
||||
uint32_t bitIdx = 7 - (x % 8);
|
||||
maskBits[byteIdx] |= 1 << bitIdx;
|
||||
}
|
||||
}
|
||||
|
||||
wil::unique_hbitmap hMaskBitmap(CreateBitmap(width, bitmapHeight, 1, 1, maskBits.data()));
|
||||
return CreateCursorFromBitmaps(NULL, hMaskBitmap.get());
|
||||
}
|
||||
|
||||
static HCURSOR CreateMaskedColorCursor() noexcept {
|
||||
const uint32_t width = (uint32_t)GetSystemMetrics(SM_CXCURSOR);
|
||||
const uint32_t height = (uint32_t)GetSystemMetrics(SM_CYCURSOR);
|
||||
|
||||
// width 必定是 16 的倍数,因此遮罩位图每行都已按 WORD 对齐
|
||||
assert(width % 16 == 0);
|
||||
const uint32_t widthByteCount = width / 8;
|
||||
|
||||
// 分为两个部分:
|
||||
// 左半:红色 (COLOR=0x00FF0000, MASK=0)
|
||||
// 右半:和红色 XOR (COLOR=0x00FF0000, MASK=1)
|
||||
|
||||
// 颜色位图初始化为红色。注意透明通道为 0,否则会被识别为彩色光标,遮罩位图被忽略
|
||||
std::vector<uint32_t> colorBits(width * height, 0x00FF0000);
|
||||
std::vector<uint8_t> maskBits(widthByteCount * height, 0);
|
||||
|
||||
// XOR 遮罩右半置 1
|
||||
for (uint32_t y = 0; y < height; ++y) {
|
||||
for (uint32_t x = width / 2; x < width; ++x) {
|
||||
uint32_t byteIdx = y * widthByteCount + x / 8;
|
||||
uint32_t bitIdx = 7 - (x % 8);
|
||||
maskBits[byteIdx] |= 1 << bitIdx;
|
||||
}
|
||||
}
|
||||
|
||||
wil::unique_hbitmap hColorBitmap(CreateBitmap(width, height, 1, 32, colorBits.data()));
|
||||
wil::unique_hbitmap hMaskBitmap(CreateBitmap(width, height, 1, 1, maskBits.data()));
|
||||
return CreateCursorFromBitmaps(hColorBitmap.get(), hMaskBitmap.get());
|
||||
}
|
||||
|
||||
bool CursorWindow::Create() noexcept {
|
||||
static const wchar_t* WINDOW_NAME = L"CursorWindow";
|
||||
|
||||
_hCursor = CreateColorCursor();
|
||||
|
||||
WNDCLASSEXW wcex = {
|
||||
.cbSize = sizeof(WNDCLASSEX),
|
||||
.style = CS_HREDRAW | CS_VREDRAW,
|
||||
.lpfnWndProc = _WndProc,
|
||||
.hInstance = wil::GetModuleInstanceHandle(),
|
||||
.lpszClassName = WINDOW_NAME
|
||||
};
|
||||
if (!RegisterClassEx(&wcex)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
CreateWindow(
|
||||
WINDOW_NAME,
|
||||
WINDOW_NAME,
|
||||
WS_OVERLAPPEDWINDOW,
|
||||
CW_USEDEFAULT,
|
||||
CW_USEDEFAULT,
|
||||
CW_USEDEFAULT,
|
||||
CW_USEDEFAULT,
|
||||
NULL,
|
||||
NULL,
|
||||
wil::GetModuleInstanceHandle(),
|
||||
this
|
||||
);
|
||||
if (!Handle()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const double dpiScale = _DpiScale();
|
||||
SetWindowPos(Handle(), NULL, 0, 0,
|
||||
std::lround(500 * dpiScale), std::lround(400 * dpiScale),
|
||||
SWP_NOMOVE | SWP_SHOWWINDOW);
|
||||
return true;
|
||||
}
|
||||
|
||||
LRESULT CursorWindow::_MessageHandler(UINT msg, WPARAM wParam, LPARAM lParam) noexcept {
|
||||
switch (msg) {
|
||||
case WM_CREATE:
|
||||
{
|
||||
const LRESULT ret = base_type::_MessageHandler(msg, wParam, lParam);
|
||||
|
||||
const HMODULE hInst = wil::GetModuleInstanceHandle();
|
||||
_hwndBtn1 = CreateWindow(L"BUTTON", L"彩色光标",
|
||||
WS_CHILD | WS_VISIBLE, 0, 0, 0, 0, Handle(), (HMENU)1, hInst, 0);
|
||||
_hwndBtn2 = CreateWindow(L"BUTTON", L"单色光标",
|
||||
WS_CHILD | WS_VISIBLE, 0, 0, 0, 0, Handle(), (HMENU)2, hInst, 0);
|
||||
_hwndBtn3 = CreateWindow(L"BUTTON", L"彩色掩码光标",
|
||||
WS_CHILD | WS_VISIBLE, 0, 0, 0, 0, Handle(), (HMENU)3, hInst, 0);
|
||||
_UpdateButtonPos();
|
||||
|
||||
SendMessage(_hwndBtn1, WM_SETFONT, (WPARAM)_UIFont(), TRUE);
|
||||
SendMessage(_hwndBtn2, WM_SETFONT, (WPARAM)_UIFont(), TRUE);
|
||||
SendMessage(_hwndBtn3, WM_SETFONT, (WPARAM)_UIFont(), TRUE);
|
||||
|
||||
return ret;
|
||||
}
|
||||
case WM_COMMAND:
|
||||
{
|
||||
if (HIWORD(wParam) == BN_CLICKED) {
|
||||
const WORD btnId = LOWORD(wParam);
|
||||
if (btnId == 1) {
|
||||
_hCursor = CreateColorCursor();
|
||||
} else if (btnId == 2) {
|
||||
_hCursor = CreateMonochromeCursor();
|
||||
} else {
|
||||
_hCursor = CreateMaskedColorCursor();
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case WM_SIZE:
|
||||
{
|
||||
_UpdateButtonPos();
|
||||
break;
|
||||
}
|
||||
case WM_SETCURSOR:
|
||||
{
|
||||
if (LOWORD(lParam) == HTCLIENT) {
|
||||
SetCursor(_hCursor);
|
||||
return TRUE;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case WM_ERASEBKGND:
|
||||
{
|
||||
// 绘制渐变背景
|
||||
PAINTSTRUCT ps;
|
||||
HDC hdc = BeginPaint(Handle(), &ps);
|
||||
|
||||
RECT rc;
|
||||
GetClientRect(Handle(), &rc);
|
||||
|
||||
TRIVERTEX vertices[] = {
|
||||
{
|
||||
.x = rc.left,
|
||||
.y = rc.top,
|
||||
.Red = 0xE000,
|
||||
.Green = 0x6000,
|
||||
.Blue = 0xE000
|
||||
},
|
||||
{
|
||||
.x = rc.right,
|
||||
.y = rc.bottom,
|
||||
.Red = 0x6000,
|
||||
.Green = 0xE000,
|
||||
.Blue = 0x6000
|
||||
}
|
||||
};
|
||||
GRADIENT_RECT rect = { 0, 1 };
|
||||
GradientFill(hdc, vertices, 2, &rect, 1, GRADIENT_FILL_RECT_V);
|
||||
|
||||
EndPaint(Handle(), &ps);
|
||||
return TRUE;
|
||||
}
|
||||
case WM_DESTROY:
|
||||
PostQuitMessage(0);
|
||||
break;
|
||||
}
|
||||
|
||||
return base_type::_MessageHandler(msg, wParam, lParam);
|
||||
}
|
||||
|
||||
void CursorWindow::_UpdateButtonPos() noexcept {
|
||||
RECT clientRect;
|
||||
GetClientRect(Handle(), &clientRect);
|
||||
|
||||
const double dpiScale = _DpiScale();
|
||||
const SIZE btnSize = { std::lround(160 * dpiScale),std::lround(40 * dpiScale) };
|
||||
const LONG spacing = std::lround(8 * dpiScale);
|
||||
|
||||
const LONG btnLeft = ((clientRect.right - clientRect.left) - btnSize.cx) / 2;
|
||||
const LONG windowCenterY = (clientRect.bottom - clientRect.top) / 2;
|
||||
|
||||
SetWindowPos(_hwndBtn1, NULL, btnLeft, windowCenterY - 3 * btnSize.cy / 2 - spacing,
|
||||
btnSize.cx, btnSize.cy, SWP_NOACTIVATE);
|
||||
SetWindowPos(_hwndBtn2, NULL, btnLeft, windowCenterY - btnSize.cy / 2,
|
||||
btnSize.cx, btnSize.cy, SWP_NOACTIVATE);
|
||||
SetWindowPos(_hwndBtn3, NULL, btnLeft, windowCenterY + btnSize.cy / 2 + spacing,
|
||||
btnSize.cx, btnSize.cy, SWP_NOACTIVATE);
|
||||
}
|
||||
21
tools/WindowCase/CursorWindow.h
Normal file
21
tools/WindowCase/CursorWindow.h
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
#pragma once
|
||||
#include "WindowBase.h"
|
||||
|
||||
class CursorWindow : public WindowBaseT<CursorWindow> {
|
||||
using base_type = WindowBaseT<CursorWindow>;
|
||||
friend base_type;
|
||||
|
||||
public:
|
||||
bool Create() noexcept;
|
||||
|
||||
private:
|
||||
LRESULT _MessageHandler(UINT msg, WPARAM wParam, LPARAM lParam) noexcept;
|
||||
|
||||
void _UpdateButtonPos() noexcept;
|
||||
|
||||
HCURSOR _hCursor = NULL;
|
||||
|
||||
HWND _hwndBtn1 = NULL;
|
||||
HWND _hwndBtn2 = NULL;
|
||||
HWND _hwndBtn3 = NULL;
|
||||
};
|
||||
|
|
@ -1,6 +1,5 @@
|
|||
#include "pch.h"
|
||||
#include "HideCursorWindow.h"
|
||||
#include "Utils.h"
|
||||
|
||||
bool HideCursorWindow::Create() noexcept {
|
||||
static const wchar_t* WINDOW_NAME = L"HideCursorWindow";
|
||||
|
|
@ -9,7 +8,7 @@ bool HideCursorWindow::Create() noexcept {
|
|||
.cbSize = sizeof(WNDCLASSEX),
|
||||
.style = CS_HREDRAW | CS_VREDRAW,
|
||||
.lpfnWndProc = _WndProc,
|
||||
.hInstance = Utils::GetModuleInstanceHandle(),
|
||||
.hInstance = wil::GetModuleInstanceHandle(),
|
||||
.hCursor = LoadCursor(nullptr, IDC_ARROW),
|
||||
.hbrBackground = HBRUSH(COLOR_WINDOW + 1),
|
||||
.lpszClassName = WINDOW_NAME
|
||||
|
|
@ -28,7 +27,7 @@ bool HideCursorWindow::Create() noexcept {
|
|||
CW_USEDEFAULT,
|
||||
NULL,
|
||||
NULL,
|
||||
Utils::GetModuleInstanceHandle(),
|
||||
wil::GetModuleInstanceHandle(),
|
||||
this
|
||||
);
|
||||
if (!Handle()) {
|
||||
|
|
@ -49,7 +48,7 @@ LRESULT HideCursorWindow::_MessageHandler(UINT msg, WPARAM wParam, LPARAM lParam
|
|||
const LRESULT ret = base_type::_MessageHandler(msg, wParam, lParam);
|
||||
|
||||
_hwndBtn = CreateWindow(L"BUTTON", L"未隐藏光标", WS_CHILD | WS_VISIBLE,
|
||||
0, 0, 0, 0, Handle(), (HMENU)1, Utils::GetModuleInstanceHandle(), 0);
|
||||
0, 0, 0, 0, Handle(), (HMENU)1, wil::GetModuleInstanceHandle(), 0);
|
||||
_UpdateButtonPos();
|
||||
|
||||
SendMessage(_hwndBtn, WM_SETFONT, (WPARAM)_UIFont(), TRUE);
|
||||
|
|
|
|||
|
|
@ -1,6 +1,5 @@
|
|||
#include "pch.h"
|
||||
#include "HungWindow.h"
|
||||
#include "Utils.h"
|
||||
|
||||
bool HungWindow::Create() noexcept {
|
||||
static const wchar_t* WINDOW_NAME = L"HungWindow";
|
||||
|
|
@ -9,7 +8,7 @@ bool HungWindow::Create() noexcept {
|
|||
.cbSize = sizeof(WNDCLASSEX),
|
||||
.style = CS_HREDRAW | CS_VREDRAW,
|
||||
.lpfnWndProc = _WndProc,
|
||||
.hInstance = Utils::GetModuleInstanceHandle(),
|
||||
.hInstance = wil::GetModuleInstanceHandle(),
|
||||
.hCursor = LoadCursor(nullptr, IDC_ARROW),
|
||||
.hbrBackground = HBRUSH(COLOR_WINDOW + 1),
|
||||
.lpszClassName = WINDOW_NAME
|
||||
|
|
@ -28,7 +27,7 @@ bool HungWindow::Create() noexcept {
|
|||
CW_USEDEFAULT,
|
||||
NULL,
|
||||
NULL,
|
||||
Utils::GetModuleInstanceHandle(),
|
||||
wil::GetModuleInstanceHandle(),
|
||||
this
|
||||
);
|
||||
if (!Handle()) {
|
||||
|
|
@ -49,7 +48,7 @@ LRESULT HungWindow::_MessageHandler(UINT msg, WPARAM wParam, LPARAM lParam) noex
|
|||
const LRESULT ret = base_type::_MessageHandler(msg, wParam, lParam);
|
||||
|
||||
_hwndBtn = CreateWindow(L"BUTTON", L"无响应 10 秒", WS_CHILD | WS_VISIBLE,
|
||||
0, 0, 0, 0, Handle(), (HMENU)1, Utils::GetModuleInstanceHandle(), 0);
|
||||
0, 0, 0, 0, Handle(), (HMENU)1, wil::GetModuleInstanceHandle(), 0);
|
||||
_UpdateButtonPos();
|
||||
|
||||
SendMessage(_hwndBtn, WM_SETFONT, (WPARAM)_UIFont(), TRUE);
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ bool KirikiriWindow::Create() noexcept {
|
|||
.cbSize = sizeof(WNDCLASSEX),
|
||||
.style = CS_HREDRAW | CS_VREDRAW,
|
||||
.lpfnWndProc = _OwnerWndProc,
|
||||
.hInstance = Utils::GetModuleInstanceHandle(),
|
||||
.hInstance = wil::GetModuleInstanceHandle(),
|
||||
.hCursor = LoadCursor(nullptr, IDC_ARROW),
|
||||
.hbrBackground = HBRUSH(COLOR_WINDOW + 1),
|
||||
.lpszClassName = OWNER_NAME
|
||||
|
|
@ -34,7 +34,7 @@ bool KirikiriWindow::Create() noexcept {
|
|||
0,
|
||||
NULL,
|
||||
NULL,
|
||||
Utils::GetModuleInstanceHandle(),
|
||||
wil::GetModuleInstanceHandle(),
|
||||
this
|
||||
);
|
||||
|
||||
|
|
@ -54,7 +54,7 @@ bool KirikiriWindow::Create() noexcept {
|
|||
CW_USEDEFAULT,
|
||||
_hwndOwner,
|
||||
NULL,
|
||||
Utils::GetModuleInstanceHandle(),
|
||||
wil::GetModuleInstanceHandle(),
|
||||
this
|
||||
);
|
||||
if (!Handle()) {
|
||||
|
|
@ -81,7 +81,7 @@ LRESULT KirikiriWindow::_MessageHandler(UINT msg, WPARAM wParam, LPARAM lParam)
|
|||
{
|
||||
const LRESULT ret = base_type::_MessageHandler(msg, wParam, lParam);
|
||||
|
||||
const HMODULE hInst = Utils::GetModuleInstanceHandle();
|
||||
const HMODULE hInst = wil::GetModuleInstanceHandle();
|
||||
_hwndBtn1 = CreateWindow(L"BUTTON", L"同类名所有者关系弹窗",
|
||||
WS_CHILD | WS_VISIBLE, 0, 0, 0, 0, Handle(), (HMENU)1, hInst, 0);
|
||||
_hwndBtn2 = CreateWindow(L"BUTTON", L"同类名模拟模态弹窗",
|
||||
|
|
@ -129,7 +129,7 @@ LRESULT KirikiriWindow::_MessageHandler(UINT msg, WPARAM wParam, LPARAM lParam)
|
|||
popupSize.cy,
|
||||
isOwnedPopup ? Handle() : NULL,
|
||||
NULL,
|
||||
Utils::GetModuleInstanceHandle(),
|
||||
wil::GetModuleInstanceHandle(),
|
||||
curPopup.get()
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ bool PopupHostWindow::Create() noexcept {
|
|||
.cbSize = sizeof(WNDCLASSEX),
|
||||
.style = CS_HREDRAW | CS_VREDRAW,
|
||||
.lpfnWndProc = _WndProc,
|
||||
.hInstance = Utils::GetModuleInstanceHandle(),
|
||||
.hInstance = wil::GetModuleInstanceHandle(),
|
||||
.hCursor = LoadCursor(nullptr, IDC_ARROW),
|
||||
.hbrBackground = HBRUSH(COLOR_WINDOW + 1),
|
||||
.lpszClassName = WINDOW_NAME
|
||||
|
|
@ -28,7 +28,7 @@ bool PopupHostWindow::Create() noexcept {
|
|||
CW_USEDEFAULT,
|
||||
NULL,
|
||||
NULL,
|
||||
Utils::GetModuleInstanceHandle(),
|
||||
wil::GetModuleInstanceHandle(),
|
||||
this
|
||||
);
|
||||
if (!Handle()) {
|
||||
|
|
@ -70,7 +70,7 @@ LRESULT PopupHostWindow::_MessageHandler(UINT msg, WPARAM wParam, LPARAM lParam)
|
|||
{
|
||||
const LRESULT ret = base_type::_MessageHandler(msg, wParam, lParam);
|
||||
|
||||
const HMODULE hInst = Utils::GetModuleInstanceHandle();
|
||||
const HMODULE hInst = wil::GetModuleInstanceHandle();
|
||||
_hwndBtn1 = CreateWindow(L"BUTTON", L"模态弹窗",
|
||||
WS_CHILD | WS_VISIBLE, 0, 0, 0, 0, Handle(), (HMENU)1, hInst, 0);
|
||||
_hwndBtn2 = CreateWindow(L"BUTTON", L"模拟模态弹窗",
|
||||
|
|
@ -112,7 +112,7 @@ LRESULT PopupHostWindow::_MessageHandler(UINT msg, WPARAM wParam, LPARAM lParam)
|
|||
.cbSize = sizeof(WNDCLASSEX),
|
||||
.style = CS_HREDRAW | CS_VREDRAW,
|
||||
.lpfnWndProc = _Popup2WndProc,
|
||||
.hInstance = Utils::GetModuleInstanceHandle(),
|
||||
.hInstance = wil::GetModuleInstanceHandle(),
|
||||
.hCursor = LoadCursor(nullptr, IDC_ARROW),
|
||||
.hbrBackground = HBRUSH(COLOR_WINDOW + 1),
|
||||
.lpszClassName = POPUP2_WINDOW_NAME
|
||||
|
|
@ -134,7 +134,7 @@ LRESULT PopupHostWindow::_MessageHandler(UINT msg, WPARAM wParam, LPARAM lParam)
|
|||
popupSize.cy,
|
||||
Handle(),
|
||||
NULL,
|
||||
Utils::GetModuleInstanceHandle(),
|
||||
wil::GetModuleInstanceHandle(),
|
||||
this
|
||||
);
|
||||
} else {
|
||||
|
|
@ -144,7 +144,7 @@ LRESULT PopupHostWindow::_MessageHandler(UINT msg, WPARAM wParam, LPARAM lParam)
|
|||
.cbSize = sizeof(WNDCLASSEX),
|
||||
.style = CS_HREDRAW | CS_VREDRAW,
|
||||
.lpfnWndProc = DefWindowProc,
|
||||
.hInstance = Utils::GetModuleInstanceHandle(),
|
||||
.hInstance = wil::GetModuleInstanceHandle(),
|
||||
.hCursor = LoadCursor(nullptr, IDC_ARROW),
|
||||
.hbrBackground = HBRUSH(COLOR_WINDOW + 1),
|
||||
.lpszClassName = POPUP_WINDOW_NAME
|
||||
|
|
@ -166,7 +166,7 @@ LRESULT PopupHostWindow::_MessageHandler(UINT msg, WPARAM wParam, LPARAM lParam)
|
|||
popupSize.cy,
|
||||
btnId == 3 ? Handle() : NULL,
|
||||
NULL,
|
||||
Utils::GetModuleInstanceHandle(),
|
||||
wil::GetModuleInstanceHandle(),
|
||||
nullptr
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,5 @@
|
|||
#include "pch.h"
|
||||
#include "TopmostWindow.h"
|
||||
#include "Utils.h"
|
||||
|
||||
bool TopmostWindow::Create() noexcept {
|
||||
static const wchar_t* WINDOW_NAME = L"TopmostWindow";
|
||||
|
|
@ -9,7 +8,7 @@ bool TopmostWindow::Create() noexcept {
|
|||
.cbSize = sizeof(WNDCLASSEX),
|
||||
.style = CS_HREDRAW | CS_VREDRAW,
|
||||
.lpfnWndProc = _WndProc,
|
||||
.hInstance = Utils::GetModuleInstanceHandle(),
|
||||
.hInstance = wil::GetModuleInstanceHandle(),
|
||||
.hCursor = LoadCursor(nullptr, IDC_ARROW),
|
||||
.hbrBackground = HBRUSH(COLOR_WINDOW + 1),
|
||||
.lpszClassName = WINDOW_NAME
|
||||
|
|
@ -28,7 +27,7 @@ bool TopmostWindow::Create() noexcept {
|
|||
CW_USEDEFAULT,
|
||||
NULL,
|
||||
NULL,
|
||||
Utils::GetModuleInstanceHandle(),
|
||||
wil::GetModuleInstanceHandle(),
|
||||
this
|
||||
);
|
||||
if (!Handle()) {
|
||||
|
|
@ -49,7 +48,7 @@ LRESULT TopmostWindow::_MessageHandler(UINT msg, WPARAM wParam, LPARAM lParam) n
|
|||
const LRESULT ret = base_type::_MessageHandler(msg, wParam, lParam);
|
||||
|
||||
_hwndBtn = CreateWindow(L"BUTTON", L"未置顶", WS_CHILD | WS_VISIBLE,
|
||||
0, 0, 0, 0, Handle(), (HMENU)1, Utils::GetModuleInstanceHandle(), 0);
|
||||
0, 0, 0, 0, Handle(), (HMENU)1, wil::GetModuleInstanceHandle(), 0);
|
||||
_UpdateButtonPos();
|
||||
|
||||
SendMessage(_hwndBtn, WM_SETFONT, (WPARAM)_UIFont(), TRUE);
|
||||
|
|
|
|||
|
|
@ -1,16 +1,9 @@
|
|||
#include "pch.h"
|
||||
#include "Utils.h"
|
||||
|
||||
EXTERN_C IMAGE_DOS_HEADER __ImageBase;
|
||||
|
||||
RECT Utils::MonitorRectFromWindow(HWND hWnd) noexcept {
|
||||
HMONITOR hMon = MonitorFromWindow(hWnd, MONITOR_DEFAULTTONEAREST);
|
||||
MONITORINFO mi{ sizeof(mi) };
|
||||
GetMonitorInfo(hMon, &mi);
|
||||
return mi.rcMonitor;
|
||||
}
|
||||
|
||||
// https://github.com/microsoft/wil/blob/1fae8ac13f393d727d6c3dba50b1dfe3f63e835b/include/wil/win32_helpers.h#L788
|
||||
HINSTANCE Utils::GetModuleInstanceHandle() noexcept {
|
||||
return reinterpret_cast<HINSTANCE>(&__ImageBase);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,6 +2,4 @@
|
|||
|
||||
struct Utils {
|
||||
static RECT MonitorRectFromWindow(HWND hWnd) noexcept;
|
||||
|
||||
static HINSTANCE GetModuleInstanceHandle() noexcept;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -33,6 +33,7 @@
|
|||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
<Import Project="packages\Microsoft.Windows.ImplementationLibrary.1.0.250325.1\build\native\Microsoft.Windows.ImplementationLibrary.targets" Condition="Exists('packages\Microsoft.Windows.ImplementationLibrary.1.0.250325.1\build\native\Microsoft.Windows.ImplementationLibrary.targets')" />
|
||||
</ImportGroup>
|
||||
<PropertyGroup Label="UserMacros" />
|
||||
<ItemDefinitionGroup>
|
||||
|
|
@ -40,10 +41,11 @@
|
|||
<PrecompiledHeader>Use</PrecompiledHeader>
|
||||
<PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
|
||||
<PrecompiledHeaderOutputFile>$(IntDir)pch.pch</PrecompiledHeaderOutputFile>
|
||||
<PreprocessorDefinitions>_WINDOWS;WIN32_LEAN_AND_MEAN;NOMINMAX;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<PreprocessorDefinitions>_WINDOWS;WIN32_LEAN_AND_MEAN;NOMINMAX;WIL_SUPPRESS_EXCEPTIONS;WIL_USE_STL=1;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
<AdditionalDependencies>Msimg32.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
|
|
@ -70,6 +72,7 @@
|
|||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="CursorWindow.cpp" />
|
||||
<ClCompile Include="HideCursorWindow.cpp" />
|
||||
<ClCompile Include="HungWindow.cpp" />
|
||||
<ClCompile Include="PopupHostWindow.cpp" />
|
||||
|
|
@ -82,6 +85,7 @@
|
|||
<ClCompile Include="Utils.cpp" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="CursorWindow.h" />
|
||||
<ClInclude Include="HideCursorWindow.h" />
|
||||
<ClInclude Include="HungWindow.h" />
|
||||
<ClInclude Include="PopupHostWindow.h" />
|
||||
|
|
@ -94,5 +98,14 @@
|
|||
<ItemGroup>
|
||||
<Manifest Include="app.manifest" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="packages.config" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
|
||||
<PropertyGroup>
|
||||
<ErrorText>这台计算机上缺少此项目引用的 NuGet 程序包。使用“NuGet 程序包还原”可下载这些程序包。有关更多信息,请参见 http://go.microsoft.com/fwlink/?LinkID=322105。缺少的文件是 {0}。</ErrorText>
|
||||
</PropertyGroup>
|
||||
<Error Condition="!Exists('packages\Microsoft.Windows.ImplementationLibrary.1.0.250325.1\build\native\Microsoft.Windows.ImplementationLibrary.targets')" Text="$([System.String]::Format('$(ErrorText)', 'packages\Microsoft.Windows.ImplementationLibrary.1.0.250325.1\build\native\Microsoft.Windows.ImplementationLibrary.targets'))" />
|
||||
</Target>
|
||||
</Project>
|
||||
|
|
@ -9,9 +9,7 @@
|
|||
<ClCompile Include="PopupHostWindow.cpp" />
|
||||
<ClCompile Include="HideCursorWindow.cpp" />
|
||||
<ClCompile Include="Utils.cpp" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Manifest Include="app.manifest" />
|
||||
<ClCompile Include="CursorWindow.cpp" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="pch.h" />
|
||||
|
|
@ -22,5 +20,12 @@
|
|||
<ClInclude Include="PopupHostWindow.h" />
|
||||
<ClInclude Include="HideCursorWindow.h" />
|
||||
<ClInclude Include="Utils.h" />
|
||||
<ClInclude Include="CursorWindow.h" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Manifest Include="app.manifest" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="packages.config" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
|
|
@ -1,4 +1,5 @@
|
|||
#include "pch.h"
|
||||
#include "CursorWindow.h"
|
||||
#include "KirikiriWindow.h"
|
||||
#include "HungWindow.h"
|
||||
#include "TopmostWindow.h"
|
||||
|
|
@ -12,7 +13,7 @@ int APIENTRY wWinMain(
|
|||
_In_ int /*nCmdShow*/
|
||||
) {
|
||||
// 模拟 TVP(KIRIKIRI) 2 引擎窗口
|
||||
KirikiriWindow window;
|
||||
// KirikiriWindow window;
|
||||
|
||||
// 模拟挂起的窗口
|
||||
// HungWindow window;
|
||||
|
|
@ -26,6 +27,9 @@ int APIENTRY wWinMain(
|
|||
// 模拟隐藏光标的窗口
|
||||
// HideCursorWindow window;
|
||||
|
||||
// 模拟各种光标的窗口
|
||||
CursorWindow window;
|
||||
|
||||
if (!window.Create()) {
|
||||
return false;
|
||||
}
|
||||
|
|
|
|||
4
tools/WindowCase/packages.config
Normal file
4
tools/WindowCase/packages.config
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<packages>
|
||||
<package id="Microsoft.Windows.ImplementationLibrary" version="1.0.250325.1" targetFramework="native" />
|
||||
</packages>
|
||||
|
|
@ -21,5 +21,9 @@
|
|||
#include <string_view>
|
||||
#include <vector>
|
||||
|
||||
// WIL
|
||||
#include <wil/resource.h>
|
||||
#include <wil/win32_helpers.h>
|
||||
|
||||
using namespace std::string_literals;
|
||||
using namespace std::string_view_literals;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue