-
Notifications
You must be signed in to change notification settings - Fork 29
/
dlgapp.cpp
143 lines (122 loc) · 3.29 KB
/
dlgapp.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <stdio.h>
#include <vector>
static HWND g_hDlg;
class DialogTemplate
{
private:
std::vector<BYTE> m_buf;
public:
DialogTemplate() = default;
inline operator LPCDLGTEMPLATEW()
{
return (LPCDLGTEMPLATEW)m_buf.data();
}
inline void Reset()
{
m_buf.clear();
}
inline void Align()
{
while (m_buf.size() % sizeof(WORD) != 0)
{
m_buf.push_back(0);
}
}
template<class T>
inline void Write(const T& value)
{
auto ptr = (const BYTE*)&value;
m_buf.insert(m_buf.end(), ptr, ptr + sizeof(T));
}
};
static INT_PTR DlgProc(HWND hDlg, UINT Msg, WPARAM wParam, LPARAM lParam)
{
switch (Msg)
{
case WM_INITDIALOG:
{
_InterlockedExchangePointer((PVOID*)&g_hDlg, hDlg);
// TODO
return TRUE;
}
case WM_DESTROY:
{
// TODO
_InterlockedExchangePointer((PVOID*)&g_hDlg, NULL);
return TRUE;
}
case WM_COMMAND:
{
switch (LOWORD(wParam))
{
case IDCANCEL:
EndDialog(hDlg, 0);
PostQuitMessage(0); // TODO: For testing only; remove in production
return TRUE;
default:
return FALSE;
}
}
case WM_PAINT:
{
// TODO
return TRUE;
}
default:
return FALSE;
}
}
int main()
{
DWORD dwUnits = GetDialogBaseUnits();
WORD wUnitX = LOWORD(dwUnits);
WORD wUnitY = HIWORD(dwUnits);
printf("%hu %hu\n", wUnitX, wUnitY);
// Pixel to dialog unit
// Reversed formula from https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-mapdialogrect#remarks
short cx = MulDiv(300, 4, wUnitX);
short cy = MulDiv(400, 8, wUnitY);
DialogTemplate dlg;
// DLGTEMPLATEEX
dlg.Write<WORD>(1); // dlgVer
dlg.Write<WORD>(0xFFFF); // signature
dlg.Write<DWORD>(0); // helpID
dlg.Write<DWORD>(0); // exStyle
dlg.Write<DWORD>(WS_VISIBLE | WS_CAPTION | WS_SYSMENU | DS_CENTER); // style
dlg.Write<WORD>(0); // cDlgItems
dlg.Write<short>(0); // x
dlg.Write<short>(0); // y
dlg.Write<short>(cx); // cx
dlg.Write<short>(cy); // cy
dlg.Write<WORD>(0); // menu (null)
dlg.Write<WORD>(0); // windowClass (null)
dlg.Write(L"Hello"); // title
#if 0 // DLGTEMPLATEEX, only when DS_SETFONT is set
dlg.Write<WORD>(0); // pointsize
dlg.Write<WORD>(0); // weight
dlg.Write<BYTE>(FALSE); // italic
dlg.Write<BYTE>(DEFAULT_CHARSET); // charset
dlg.Write(L""); // typeface
#endif
if (!_InterlockedCompareExchangePointer((PVOID*)&g_hDlg, (PVOID)(UINT_PTR)-1, NULL))
{
auto hwnd = CreateDialogIndirectW(NULL, dlg, GetConsoleWindow(), DlgProc);
printf("%p %u\n", hwnd, GetLastError());
if (hwnd)
{
MSG msg;
while (GetMessageW(&msg, NULL, WM_NULL, WM_NULL))
{
TranslateMessage(&msg);
DispatchMessageW(&msg);
}
}
else
{
_InterlockedExchangePointer((PVOID*)&g_hDlg, NULL);
}
}
return 0;
}