9#include <codeanalysis\warnings.h>
11#pragma warning(disable: WXWIDGETS_CODE_ANALYSIS_WARNINGS)
13#include <wx/private/tlwgeom.h>
16#ifndef USER_DEFAULT_SCREEN_DPI
17#define USER_DEFAULT_SCREEN_DPI 96
22#define wxPERSIST_TLW_MONITOR_X "xmon"
23#define wxPERSIST_TLW_MONITOR_Y "ymon"
24#define wxPERSIST_TLW_MONITOR_W "wmon"
25#define wxPERSIST_TLW_MONITOR_H "hmon"
26#define wxPERSIST_TLW_DPI_HORZ "xdpi"
27#define wxPERSIST_TLW_DPI_VERT "ydpi"
29class wxTLWGeometryEx :
public wxTLWGeometryBase
34 wxZeroMemory(m_placement);
35 m_placement.length =
sizeof(m_placement);
37 wxZeroMemory(m_mntinfo);
38 m_mntinfo.cbSize =
sizeof(m_mntinfo);
40 m_dpiHorz = USER_DEFAULT_SCREEN_DPI;
41 m_dpiVert = USER_DEFAULT_SCREEN_DPI;
44 virtual bool Save(
const Serializer& ser)
const wxOVERRIDE
51 const RECT& rc = m_placement.rcNormalPosition;
52 if (!ser.SaveField(wxPERSIST_TLW_X, rc.left) ||
53 !ser.SaveField(wxPERSIST_TLW_Y, rc.top) ||
54 !ser.SaveField(wxPERSIST_TLW_W, rc.right - rc.left) ||
55 !ser.SaveField(wxPERSIST_TLW_H, rc.bottom - rc.top))
59 UINT show = m_placement.showCmd;
60 if (!ser.SaveField(wxPERSIST_TLW_MAXIMIZED, show == SW_SHOWMAXIMIZED))
63 if (!ser.SaveField(wxPERSIST_TLW_ICONIZED, show == SW_SHOWMINIMIZED))
67 const POINT pt = m_placement.ptMaxPosition;
68 if (!ser.SaveField(wxPERSIST_TLW_MAX_X, pt.x) ||
69 !ser.SaveField(wxPERSIST_TLW_MAX_Y, pt.y))
78 const RECT& rcMon = m_mntinfo.rcWork;
79 if (!ser.SaveField(wxPERSIST_TLW_MONITOR_X, rcMon.left) ||
80 !ser.SaveField(wxPERSIST_TLW_MONITOR_Y, rcMon.top) ||
81 !ser.SaveField(wxPERSIST_TLW_MONITOR_W, rcMon.right - rcMon.left) ||
82 !ser.SaveField(wxPERSIST_TLW_MONITOR_H, rcMon.bottom - rcMon.top))
86 if (!ser.SaveField(wxPERSIST_TLW_DPI_HORZ, m_dpiHorz) ||
87 !ser.SaveField(wxPERSIST_TLW_DPI_VERT, m_dpiVert))
93 virtual bool Restore(Serializer& ser) wxOVERRIDE
97 if (!ser.RestoreField(wxPERSIST_TLW_X, &r.x) ||
98 !ser.RestoreField(wxPERSIST_TLW_Y, &r.y) ||
99 !ser.RestoreField(wxPERSIST_TLW_W, &r.width) ||
100 !ser.RestoreField(wxPERSIST_TLW_H, &r.height))
102 wxCopyRectToRECT(r, m_placement.rcNormalPosition);
114 UINT& show = m_placement.showCmd;
115 if (ser.RestoreField(wxPERSIST_TLW_MAXIMIZED, &tmp) && tmp)
117 else if (ser.RestoreField(wxPERSIST_TLW_ICONIZED, &tmp) && tmp)
120 show = SW_SHOWNORMAL;
123 if (ser.RestoreField(wxPERSIST_TLW_MAX_X, &r.x) &&
124 ser.RestoreField(wxPERSIST_TLW_MAX_Y, &r.y))
126 m_placement.ptMaxPosition.x = r.x;
127 m_placement.ptMaxPosition.y = r.y;
129 m_placement.ptMaxPosition.x = -1;
130 m_placement.ptMaxPosition.y = -1;
133 m_placement.ptMinPosition.x = -1;
134 m_placement.ptMinPosition.y = -1;
138 if (!ser.RestoreField(wxPERSIST_TLW_MONITOR_X, &rmon.x) ||
139 !ser.RestoreField(wxPERSIST_TLW_MONITOR_Y, &rmon.y) ||
140 !ser.RestoreField(wxPERSIST_TLW_MONITOR_W, &rmon.width) ||
141 !ser.RestoreField(wxPERSIST_TLW_MONITOR_H, &rmon.height))
143 wxCopyRectToRECT(rmon, m_mntinfo.rcWork);
146 if (!ser.RestoreField(wxPERSIST_TLW_DPI_HORZ, &r.x) ||
147 !ser.RestoreField(wxPERSIST_TLW_DPI_VERT, &r.y))
155 virtual bool GetFrom(
const wxTopLevelWindow* tlw) wxOVERRIDE
157 WXHWND hWnd = GetHwndOf(tlw);
158 if (!::GetWindowPlacement(hWnd, &m_placement))
160 wxLogLastError(wxS(
"GetWindowPlacement"));
164 HMONITOR hMonitor = ::MonitorFromWindow(hWnd, MONITOR_DEFAULTTONEAREST);
165 wxASSERT_MSG(hMonitor, wxT(
"error locating monitor"));
166 _Analysis_assume_(hMonitor);
167 if (!::GetMonitorInfo(hMonitor, &m_mntinfo))
169 wxLogLastError(wxS(
"GetMonitorInfo"));
173 GetDPI(hWnd, &m_dpiHorz, &m_dpiVert) || GetDPI(hMonitor, &m_dpiHorz, &m_dpiVert);
178 virtual bool ApplyTo(wxTopLevelWindow* tlw) wxOVERRIDE
186 tlw->MSWSetShowCommand(m_placement.showCmd);
189 m_placement.showCmd = SW_HIDE;
193 HMONITOR hMonitor = ::MonitorFromRect(&m_mntinfo.rcWork, MONITOR_DEFAULTTONEAREST);
194 wxASSERT_MSG(hMonitor, wxT(
"error locating monitor"));
195 _Analysis_assume_(hMonitor);
197 mntinfo.cbSize =
sizeof(mntinfo);
198 if (!::GetMonitorInfo(hMonitor, &mntinfo))
200 wxLogLastError(wxS(
"GetMonitorInfo"));
204 UINT dpiHorz, dpiVert;
205 GetDPI(hMonitor, &dpiHorz, &dpiVert);
209 m_mntinfo.rcWork.right - m_mntinfo.rcWork.left,
210 m_mntinfo.rcWork.bottom - m_mntinfo.rcWork.top
213 mntinfo.rcWork.right - mntinfo.rcWork.left,
214 mntinfo.rcWork.bottom - mntinfo.rcWork.top
223 if (m_placement.ptMaxPosition.x != -1 && m_placement.ptMaxPosition.y != -1) {
224 m_placement.ptMaxPosition.x = wxMulDivInt32(m_placement.ptMaxPosition.x - m_mntinfo.rcWork.left, sizeWork.cx, sizeWorkPrev.cx) + mntinfo.rcWork.left;
225 m_placement.ptMaxPosition.y = wxMulDivInt32(m_placement.ptMaxPosition.y - m_mntinfo.rcWork.top, sizeWork.cy, sizeWorkPrev.cy) + mntinfo.rcWork.top;
228 SIZE sizeWndPrev, sizeWnd;
229 HWND hWnd = GetHwndOf(tlw);
231 if (tlw->GetWindowStyle() & wxRESIZE_BORDER) {
232 sizeWndPrev.cx = m_placement.rcNormalPosition.right - m_placement.rcNormalPosition.left;
233 sizeWndPrev.cy = m_placement.rcNormalPosition.bottom - m_placement.rcNormalPosition.top;
234 sizeWnd.cx = wxMulDivInt32(sizeWndPrev.cx, dpiHorz, m_dpiHorz);
235 sizeWnd.cy = wxMulDivInt32(sizeWndPrev.cy, dpiVert, m_dpiVert);
238 WINDOWPLACEMENT placement = {
sizeof(placement) };
239 if (!::GetWindowPlacement(hWnd, &placement))
241 wxLogLastError(wxS(
"GetWindowPlacement"));
245 placement.rcNormalPosition.right - placement.rcNormalPosition.left,
246 placement.rcNormalPosition.bottom - placement.rcNormalPosition.top
249 UINT dpiWndHorz, dpiWndVert;
250 GetDPI(hWnd, &dpiWndHorz, &dpiWndVert) || GetDPI(::MonitorFromWindow(hWnd, MONITOR_DEFAULTTONEAREST), &dpiWndHorz, &dpiWndVert);
252 sizeWndPrev.cx = wxMulDivInt32(size.cx, m_dpiHorz, dpiWndHorz);
253 sizeWndPrev.cy = wxMulDivInt32(size.cy, m_dpiVert, dpiWndVert);
254 sizeWnd.cx = wxMulDivInt32(size.cx, dpiHorz, dpiWndHorz);
255 sizeWnd.cy = wxMulDivInt32(size.cy, dpiVert, dpiWndVert);
258 m_placement.rcNormalPosition.left = wxMulDivInt32(m_placement.rcNormalPosition.left + sizeWndPrev.cx / 2 - m_mntinfo.rcWork.left, sizeWork.cx, sizeWorkPrev.cx) + mntinfo.rcWork.left - sizeWnd.cx / 2;
259 m_placement.rcNormalPosition.top = wxMulDivInt32(m_placement.rcNormalPosition.top + sizeWndPrev.cy / 2 - m_mntinfo.rcWork.top, sizeWork.cy, sizeWorkPrev.cy) + mntinfo.rcWork.top - sizeWnd.cy / 2;
260 m_placement.rcNormalPosition.right = m_placement.rcNormalPosition.left + sizeWnd.cx;
261 m_placement.rcNormalPosition.bottom = m_placement.rcNormalPosition.top + sizeWnd.cy;
263 if (!::SetWindowPlacement(hWnd, &m_placement))
265 wxLogLastError(wxS(
"SetWindowPlacement"));
273 static bool GetDPI(_In_ HWND hWnd, _Out_ UINT *dpiHorz, _Out_ UINT *dpiVert)
278#if wxUSE_DYNLIB_CLASS
279 typedef UINT(WINAPI *GetDpiForWindow_t)(HWND);
280 static bool s_checkedGetDpiForWindow =
false;
281 static GetDpiForWindow_t s_pfnGetDpiForWindow = NULL;
282 if (!s_checkedGetDpiForWindow && s_dllUser32.IsLoaded()) {
283 s_pfnGetDpiForWindow = (GetDpiForWindow_t)s_dllUser32.RawGetSymbol(wxT(
"GetDpiForWindow"));
284 s_checkedGetDpiForWindow =
true;
287 if (s_pfnGetDpiForWindow) {
288 *dpiHorz = *dpiVert = s_pfnGetDpiForWindow(hWnd);
293 *dpiHorz = *dpiVert = USER_DEFAULT_SCREEN_DPI;
297 static bool GetDPI(_In_ HMONITOR hMonitor, _Out_ UINT *dpiHorz, _Out_ UINT *dpiVert)
302#if wxUSE_DYNLIB_CLASS
303 enum MONITOR_DPI_TYPE {
304 MDT_EFFECTIVE_DPI = 0,
307 MDT_DEFAULT = MDT_EFFECTIVE_DPI
309 typedef HRESULT(WINAPI *GetDpiForMonitor_t)(HMONITOR, MONITOR_DPI_TYPE, UINT *, UINT *);
310 static GetDpiForMonitor_t s_pfnGetDpiForMonitor = NULL;
311 if (!s_pfnGetDpiForMonitor) {
312 if (s_dllShCore.IsLoaded())
313 s_pfnGetDpiForMonitor = (GetDpiForMonitor_t)s_dllShCore.GetSymbol(wxT(
"GetDpiForMonitor"));
316 if (s_pfnGetDpiForMonitor) {
317 s_pfnGetDpiForMonitor(hMonitor, MDT_DEFAULT, dpiHorz, dpiVert);
322 *dpiHorz = *dpiVert = USER_DEFAULT_SCREEN_DPI;
327 WINDOWPLACEMENT m_placement;
328 MONITORINFO m_mntinfo;
332#if wxUSE_DYNLIB_CLASS
333 static wxDynamicLibrary s_dllUser32;
334 static wxDynamicLibrary s_dllShCore;