annotate foosdk/sdk/libPPUI/win32_utility.cpp @ 1:20d02a178406 default tip

*: check in everything else yay
author Paper <paper@tflc.us>
date Mon, 05 Jan 2026 02:15:46 -0500
parents
children
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
1
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
1 #include "stdafx.h"
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
2 #include "win32_utility.h"
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
3 #include "win32_op.h"
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
4 #include <list>
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
5
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
6 SIZE QueryContextDPI(HDC dc) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
7 return {GetDeviceCaps(dc,LOGPIXELSX), GetDeviceCaps(dc,LOGPIXELSY)};
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
8 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
9 unsigned QueryScreenDPI(HWND wnd) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
10 HDC dc = GetDC(wnd);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
11 unsigned ret = GetDeviceCaps(dc, LOGPIXELSY);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
12 ReleaseDC(wnd, dc);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
13 return ret;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
14 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
15 unsigned QueryScreenDPI_X(HWND wnd) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
16 HDC dc = GetDC(wnd);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
17 unsigned ret = GetDeviceCaps(dc, LOGPIXELSX);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
18 ReleaseDC(wnd, dc);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
19 return ret;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
20 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
21 unsigned QueryScreenDPI_Y(HWND wnd) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
22 HDC dc = GetDC(wnd);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
23 unsigned ret = GetDeviceCaps(dc, LOGPIXELSY);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
24 ReleaseDC(wnd, dc);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
25 return ret;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
26 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
27
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
28 SIZE QueryScreenDPIEx(HWND wnd) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
29 HDC dc = GetDC(wnd);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
30 SIZE ret = { GetDeviceCaps(dc,LOGPIXELSX), GetDeviceCaps(dc,LOGPIXELSY) };
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
31 ReleaseDC(wnd, dc);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
32 return ret;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
33 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
34
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
35 void HeaderControl_SetSortIndicator(HWND header_, int column, bool isUp) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
36 CHeaderCtrl header(header_);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
37 const int total = header.GetItemCount();
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
38 for (int walk = 0; walk < total; ++walk) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
39 HDITEM item = {}; item.mask = HDI_FORMAT;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
40 if (header.GetItem(walk, &item)) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
41 auto newFormat = item.fmt;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
42 newFormat &= ~(HDF_SORTUP | HDF_SORTDOWN);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
43 if (walk == column) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
44 newFormat |= isUp ? HDF_SORTUP : HDF_SORTDOWN;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
45 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
46 if (newFormat != item.fmt) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
47 item.fmt = newFormat;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
48 header.SetItem(walk, &item);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
49 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
50 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
51 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
52 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
53
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
54 HINSTANCE GetThisModuleHandle() {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
55 return (HINSTANCE)_AtlBaseModule.m_hInst;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
56 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
57
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
58 WinResourceRef_t WinLoadResource(HMODULE hMod, const TCHAR * name, const TCHAR * type, WORD wLang) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
59 SetLastError(0);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
60 HRSRC res = wLang ? FindResourceEx(hMod, type, name, wLang) : FindResource(hMod, name, type);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
61 if ( res == NULL ) WIN32_OP_FAIL();
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
62 SetLastError(0);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
63 HGLOBAL hglob = LoadResource(hMod, res);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
64 if ( hglob == NULL ) WIN32_OP_FAIL();
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
65 SetLastError(0);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
66 void * ptr = LockResource(hglob);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
67 if ( ptr == nullptr ) WIN32_OP_FAIL();
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
68 WinResourceRef_t ref;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
69 ref.ptr = ptr;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
70 ref.bytes = SizeofResource(hMod, res);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
71 return ref;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
72 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
73
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
74 CComPtr<IStream> WinLoadResourceAsStream(HMODULE hMod, const TCHAR * name, const TCHAR * type, WORD wLang) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
75 auto res = WinLoadResource(hMod, name, type, wLang );
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
76 auto str = SHCreateMemStream( (const BYTE*) res.ptr, (UINT) res.bytes );
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
77 if ( str == nullptr ) throw std::bad_alloc();
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
78 CComPtr<IStream> ret;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
79 ret.Attach( str );
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
80 return ret;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
81 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
82
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
83 UINT GetFontHeight(HFONT font)
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
84 {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
85 UINT ret;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
86 HDC dc = CreateCompatibleDC(0);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
87 SelectObject(dc, font);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
88 ret = GetTextHeight(dc);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
89 DeleteDC(dc);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
90 return ret;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
91 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
92
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
93 UINT GetTextHeight(HDC dc)
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
94 {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
95 TEXTMETRIC tm;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
96 POINT pt[2];
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
97 GetTextMetrics(dc, &tm);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
98 pt[0].x = 0;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
99 pt[0].y = tm.tmHeight;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
100 pt[1].x = 0;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
101 pt[1].y = 0;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
102 LPtoDP(dc, pt, 2);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
103
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
104 int ret = pt[0].y - pt[1].y;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
105 return ret > 1 ? (unsigned)ret : 1;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
106 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
107
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
108
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
109 LRESULT RelayEraseBkgnd(HWND p_from, HWND p_to, HDC p_dc) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
110
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
111 CDCHandle dc(p_dc);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
112 DCStateScope scope(dc);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
113 CRect client;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
114 if (GetClientRect(p_from, client)) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
115 dc.IntersectClipRect(client);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
116 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
117
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
118 LRESULT status;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
119 POINT pt = { 0, 0 }, pt_old = { 0,0 };
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
120 MapWindowPoints(p_from, p_to, &pt, 1);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
121 OffsetWindowOrgEx(p_dc, pt.x, pt.y, &pt_old);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
122 status = SendMessage(p_to, WM_ERASEBKGND, (WPARAM)p_dc, 0);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
123 SetWindowOrgEx(p_dc, pt_old.x, pt_old.y, 0);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
124 return status;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
125 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
126
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
127 static LRESULT CALLBACK EraseHandlerProc(
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
128 HWND hWnd,
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
129 UINT uMsg,
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
130 WPARAM wParam,
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
131 LPARAM lParam,
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
132 UINT_PTR uIdSubclass,
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
133 DWORD_PTR dwRefData
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
134 ) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
135 if (uMsg == WM_ERASEBKGND) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
136 HWND wndTarget = reinterpret_cast<HWND>(dwRefData);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
137 PFC_ASSERT(wndTarget != NULL);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
138 return RelayEraseBkgnd(hWnd, wndTarget, (HDC)wParam);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
139 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
140 return DefSubclassProc(hWnd, uMsg, wParam, lParam);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
141 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
142
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
143 static LRESULT CALLBACK CtlColorProc(
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
144 HWND hWnd,
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
145 UINT uMsg,
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
146 WPARAM wParam,
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
147 LPARAM lParam,
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
148 UINT_PTR uIdSubclass,
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
149 DWORD_PTR dwRefData
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
150 ) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
151 switch (uMsg) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
152 case WM_CTLCOLORMSGBOX:
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
153 case WM_CTLCOLOREDIT:
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
154 case WM_CTLCOLORLISTBOX:
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
155 case WM_CTLCOLORBTN:
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
156 case WM_CTLCOLORDLG:
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
157 case WM_CTLCOLORSCROLLBAR:
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
158 case WM_CTLCOLORSTATIC:
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
159 return SendMessage(GetParent(hWnd), uMsg, wParam, lParam);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
160 default:
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
161 return DefSubclassProc(hWnd, uMsg, wParam, lParam);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
162 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
163 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
164
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
165
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
166 void InjectEraseHandler(HWND wnd, HWND sendTo) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
167 PFC_ASSERT(sendTo != NULL);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
168 WIN32_OP_D(SetWindowSubclass(wnd, EraseHandlerProc, 0, reinterpret_cast<DWORD_PTR>(sendTo)));
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
169 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
170 void InjectParentEraseHandler(HWND wnd) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
171 InjectEraseHandler(wnd, GetParent(wnd));
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
172 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
173 void InjectParentCtlColorHandler(HWND wnd) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
174 WIN32_OP_D(SetWindowSubclass(wnd, CtlColorProc, 0, 0));
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
175 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
176 static LRESULT CALLBACK BounceNextDlgCtlProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, UINT_PTR uIdSubclass, DWORD_PTR dwRefData) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
177 if (uMsg == WM_NEXTDLGCTL) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
178 return ::SendMessage((HWND)dwRefData, uMsg, wParam, lParam);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
179 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
180 return DefSubclassProc(hWnd, uMsg, wParam, lParam);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
181 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
182
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
183 void BounceNextDlgCtl(HWND wnd, HWND wndTo) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
184 ::SetWindowSubclass(wnd, BounceNextDlgCtlProc, 0, (DWORD_PTR)wndTo);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
185 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
186
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
187
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
188 pfc::string8 EscapeTooltipText(const char * src)
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
189 {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
190 pfc::string8 out;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
191 while (*src)
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
192 {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
193 if (*src == '&')
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
194 {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
195 out.add_string("&&&");
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
196 src++;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
197 while (*src == '&')
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
198 {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
199 out.add_string("&&");
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
200 src++;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
201 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
202 } else out.add_byte(*(src++));
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
203 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
204 return out;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
205 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
206
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
207 bool IsMenuNonEmpty(HMENU menu) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
208 unsigned n, m = GetMenuItemCount(menu);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
209 for (n = 0; n < m; n++) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
210 if (GetSubMenu(menu, n)) return true;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
211 if (!(GetMenuState(menu, n, MF_BYPOSITION)&MF_SEPARATOR)) return true;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
212 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
213 return false;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
214 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
215
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
216 void SetDefaultMenuItem(HMENU p_menu, unsigned p_id) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
217 MENUITEMINFO info = { sizeof(info) };
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
218 info.fMask = MIIM_STATE;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
219 GetMenuItemInfo(p_menu, p_id, FALSE, &info);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
220 info.fState |= MFS_DEFAULT;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
221 SetMenuItemInfo(p_menu, p_id, FALSE, &info);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
222 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
223
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
224 static bool FetchWineInfoAppend(pfc::string_base & out) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
225 typedef const char *(__cdecl *t_wine_get_build_id)(void);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
226 typedef void(__cdecl *t_wine_get_host_version)(const char **sysname, const char **release);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
227 const HMODULE ntdll = GetModuleHandle(_T("ntdll.dll"));
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
228 if (ntdll == NULL) return false;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
229 t_wine_get_build_id wine_get_build_id;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
230 t_wine_get_host_version wine_get_host_version;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
231 wine_get_build_id = (t_wine_get_build_id)GetProcAddress(ntdll, "wine_get_build_id");
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
232 wine_get_host_version = (t_wine_get_host_version)GetProcAddress(ntdll, "wine_get_host_version");
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
233 if (wine_get_build_id == NULL || wine_get_host_version == NULL) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
234 if (GetProcAddress(ntdll, "wine_server_call") != NULL) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
235 out << "wine (unknown version)";
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
236 return true;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
237 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
238 return false;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
239 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
240 const char * sysname = NULL; const char * release = NULL;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
241 wine_get_host_version(&sysname, &release);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
242 out << wine_get_build_id() << ", on: " << sysname << " / " << release;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
243 return true;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
244 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
245
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
246 static void GetOSVersionStringAppend(pfc::string_base & out) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
247
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
248 if (FetchWineInfoAppend(out)) return;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
249
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
250 OSVERSIONINFO ver = {}; ver.dwOSVersionInfoSize = sizeof(ver);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
251 WIN32_OP_D(GetVersionEx(&ver));
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
252 SYSTEM_INFO info = {};
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
253 GetNativeSystemInfo(&info);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
254
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
255 out << "Windows " << (int)ver.dwMajorVersion << "." << (int)ver.dwMinorVersion << "." << (int)ver.dwBuildNumber;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
256 if (ver.szCSDVersion[0] != 0) out << " " << pfc::stringcvt::string_utf8_from_os(ver.szCSDVersion, PFC_TABSIZE(ver.szCSDVersion));
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
257
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
258 switch (info.wProcessorArchitecture) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
259 case PROCESSOR_ARCHITECTURE_AMD64:
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
260 out << " x64"; break;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
261 case PROCESSOR_ARCHITECTURE_IA64:
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
262 out << " IA64"; break;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
263 case PROCESSOR_ARCHITECTURE_INTEL:
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
264 out << " x86"; break;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
265 case PROCESSOR_ARCHITECTURE_ARM64:
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
266 out << " ARM64"; break;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
267 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
268 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
269
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
270 void GetOSVersionString(pfc::string_base & out) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
271 out.reset(); GetOSVersionStringAppend(out);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
272 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
273 WORD GetOSVersionCode() {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
274 OSVERSIONINFO ver = {sizeof(ver)};
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
275 WIN32_OP_D(GetVersionEx(&ver));
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
276
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
277 DWORD ret = ver.dwMinorVersion;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
278 ret += ver.dwMajorVersion << 8;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
279
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
280 return (WORD)ret;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
281 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
282
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
283 bool IsWine() {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
284 static bool ret = [] {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
285 HMODULE module = GetModuleHandle(_T("ntdll.dll"));
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
286 if (!module) return false;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
287 return GetProcAddress(module, "wine_server_call") != NULL;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
288 } ();
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
289 return ret;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
290 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
291
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
292 static BOOL CALLBACK EnumChildWindowsProc(HWND w, LPARAM p) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
293 auto f = reinterpret_cast<std::function<void(HWND)>*>(p);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
294 (*f)(w);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
295 return TRUE;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
296 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
297 void EnumChildWindows(HWND w, std::function<void(HWND)> f) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
298 ::EnumChildWindows(w, EnumChildWindowsProc, reinterpret_cast<LPARAM>(&f));
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
299 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
300 void EnumChildWindowsHere(HWND parent, std::function<void(HWND)> f) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
301 for (HWND walk = GetWindow(parent, GW_CHILD); walk != NULL; walk = GetWindow(walk, GW_HWNDNEXT)) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
302 f(walk);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
303 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
304 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
305 static DWORD Win10BuildNumber_() {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
306 OSVERSIONINFO ver = { sizeof(ver) };
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
307 WIN32_OP_D(GetVersionEx(&ver));
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
308 return ver.dwMajorVersion == 10 ? ver.dwBuildNumber : 0;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
309 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
310 DWORD Win10BuildNumber() {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
311 static DWORD b = Win10BuildNumber_();
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
312 return b;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
313 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
314
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
315 #include "hookWindowMessages.h"
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
316 #include <algorithm>
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
317
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
318 namespace {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
319
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
320 class CWindowHook_Map : public CWindowImpl<CWindowHook_Map, CWindow> {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
321 public:
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
322 CMessageMap* m_target = nullptr;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
323 DWORD m_targetID = 0;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
324
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
325 std::vector< DWORD > m_messages;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
326
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
327 void setup(std::initializer_list<DWORD>&& arg) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
328 m_messages = std::move(arg);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
329 std::sort(m_messages.begin(), m_messages.end());
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
330 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
331
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
332 bool isMsgWanted(DWORD msg) const {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
333 return std::binary_search(m_messages.begin(), m_messages.end(), msg);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
334 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
335 BEGIN_MSG_MAP(CWindowHook)
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
336 if (isMsgWanted(uMsg)) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
337 CHAIN_MSG_MAP_ALT_MEMBER((*m_target), m_targetID);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
338 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
339 END_MSG_MAP()
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
340 };
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
341
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
342 class CWindowHook_Proc : public CWindowImpl<CWindowHook_Proc, CWindow> {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
343 public:
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
344 CWindowHook_Proc(PP::messageHook_t proc) : m_proc(proc) {}
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
345 const PP::messageHook_t m_proc;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
346
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
347 BEGIN_MSG_MAP(CWindowHook)
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
348 if (m_proc(hWnd, uMsg, wParam, lParam, lResult)) return TRUE;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
349 END_MSG_MAP()
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
350 };
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
351
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
352 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
353
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
354 void PP::hookWindowMessages(HWND wnd, CMessageMap* target, DWORD targetID, std::initializer_list<DWORD>&& msgs) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
355 auto obj = PP::subclassThisWindow< CWindowHook_Map >(wnd);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
356 obj->m_target = target; obj->m_targetID = targetID;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
357 obj->setup(std::move(msgs));
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
358 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
359 void PP::hookWindowMessages(HWND wnd, messageHook_t h) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
360 PP::subclassThisWindow< CWindowHook_Proc >(wnd, h);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
361 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
362
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
363 namespace PP {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
364 static LONG regReadHelper(HKEY root, const wchar_t* path, const wchar_t* value, LONG def) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
365 wchar_t buf[64] = {};
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
366 DWORD cb = (DWORD)((std::size(buf) - 1) * sizeof(buf[0]));
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
367 if (RegGetValue(root, path, value, RRF_RT_REG_SZ, NULL, buf, &cb) == 0) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
368 return _wtol(buf);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
369 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
370 return def;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
371 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
372
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
373 static SIZE querySystemDragThreshold() {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
374 constexpr DWORD def = 1;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
375 static constexpr wchar_t path[] = L"Control Panel\\Desktop";
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
376 return {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
377 (LONG)regReadHelper(HKEY_CURRENT_USER, path, L"DragWidth", def),
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
378 (LONG)regReadHelper(HKEY_CURRENT_USER, path, L"DragHeight", def)
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
379 };
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
380 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
381 SIZE queryDragThresholdForDPI(SIZE dpi) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
382 PFC_ASSERT(dpi.cx > 0 && dpi.cy > 0);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
383 static SIZE sys = {};
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
384 if ( sys.cx == 0 || sys.cy == 0 ) sys = querySystemDragThreshold();
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
385 return { MulDiv(sys.cx, dpi.cx, 96), MulDiv(sys.cy, dpi.cy, 96) };
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
386 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
387 SIZE queryDragThreshold(HWND wndFor) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
388 return queryDragThresholdForDPI(QueryScreenDPIEx(wndFor));
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
389 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
390 }