-
Notifications
You must be signed in to change notification settings - Fork 6
/
Copy pathContainerWindow.cpp
163 lines (150 loc) · 5.16 KB
/
ContainerWindow.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
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
#include "ContainerWindow.h"
#include "Engine.h"
#include "EngineThread.h"
#include "EngineWindow.h"
#include "config.h"
#include "utils.h"
constexpr int minimizeCheckTimeout = 10'000; // milliseconds
constexpr int minimizeCheckTimerId = 665;
ContainerWindow::ContainerWindow(HWND parent, StyleManager& styleManager,
ui_element_instance_callback_ptr duiCallback) {
TRACK_CALL_TEXT("ContainerWindow::startup");
createWindow(parent);
try {
sessionCompiledCPInfo.ensureIsSet();
engineWindow = make_unique<EngineWindow>(*this, styleManager, duiCallback);
} catch (std::exception& e) {
engineError = e.what();
FB2K_console_formatter() << "foo_chronflow failed to initialize:\n" << e.what();
}
}
HWND ContainerWindow::createWindow(HWND parent) {
constexpr wchar_t* mainwindowClassname = L"foo_chronflow ContainerWindow";
static bool classRegistered = [&] {
WNDCLASS wc = {0};
wc.lpszClassName = mainwindowClassname;
wc.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC | CS_DBLCLKS | CS_NOCLOSE;
wc.lpfnWndProc = ContainerWindow::WndProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = sizeof(ContainerWindow*);
wc.hInstance = core_api::get_my_instance();
wc.hIcon = LoadIcon(nullptr, IDI_HAND); // NOLINT
wc.hCursor = LoadCursor(nullptr, IDC_ARROW); // NOLINT
wc.hbrBackground = nullptr;
wc.lpszMenuName = nullptr;
check(RegisterClass(&wc));
return true;
}();
return check(CreateWindowEx(0, // Extended Style For The Window
mainwindowClassname, // Class Name
L"foo_chronflow container", // Title
WS_CHILD | WS_CLIPSIBLINGS | WS_CLIPCHILDREN, // Style
CW_USEDEFAULT, CW_USEDEFAULT, // Window Position
CW_USEDEFAULT, CW_USEDEFAULT, // Window Dimensions
parent, nullptr, core_api::get_my_instance(),
static_cast<void*>(this)));
};
ContainerWindow::~ContainerWindow() {
if (hwnd)
DestroyWindow(hwnd);
}
LRESULT CALLBACK ContainerWindow::WndProc(HWND wnd, UINT msg, WPARAM wp, LPARAM lp) {
ContainerWindow* self = nullptr;
if (msg == WM_NCCREATE) {
self = static_cast<ContainerWindow*>(
(reinterpret_cast<CREATESTRUCT*>(lp))->lpCreateParams);
SetWindowLongPtr(wnd, GWLP_USERDATA, reinterpret_cast<LONG_PTR>(self));
if (self != nullptr)
self->hwnd = wnd;
} else {
self = reinterpret_cast<ContainerWindow*>(GetWindowLongPtr(wnd, GWLP_USERDATA));
}
if (self == nullptr)
return DefWindowProc(wnd, msg, wp, lp);
PFC_ASSERT(wnd == self->hwnd);
if (msg == WM_NCDESTROY) {
self->hwnd = nullptr;
SetWindowLongPtr(wnd, GWLP_USERDATA, NULL);
return DefWindowProc(wnd, msg, wp, lp);
} else {
return self->MessageHandler(msg, wp, lp);
}
}
LRESULT ContainerWindow::MessageHandler(UINT msg, WPARAM wp, LPARAM lp) {
switch (msg) {
case WM_DESTROY:
engineWindow.reset();
break;
case WM_SIZE: {
if (engineWindow)
engineWindow->setWindowSize(LOWORD(lp), HIWORD(lp));
return 0;
}
case WM_DISPLAYCHANGE:
case WM_DEVMODECHANGE: {
if (engineWindow)
engineWindow->engineThread->send<EM::DeviceModeMessage>();
return 0;
}
case WM_TIMER:
switch (wp) {
case minimizeCheckTimerId:
if (!mainWinMinimized && !ui_control::get()->is_visible()) {
mainWinMinimized = true;
if (engineWindow)
engineWindow->engineThread->send<EM::WindowHideMessage>();
KillTimer(hwnd, minimizeCheckTimerId);
}
return 0;
}
break;
case WM_ERASEBKGND:
return TRUE;
case WM_PAINT: {
if (GetUpdateRect(hwnd, nullptr, FALSE)) {
SetTimer(hwnd, minimizeCheckTimerId, minimizeCheckTimeout, nullptr);
if (mainWinMinimized) {
mainWinMinimized = false;
if (engineWindow)
engineWindow->engineThread->send<EM::WindowShowMessage>();
}
if (engineWindow) {
engineWindow->onDamage();
} else {
drawErrorMessage();
return 0;
}
}
break;
}
}
return DefWindowProc(hwnd, msg, wp, lp);
}
void ContainerWindow::drawErrorMessage() {
PAINTSTRUCT ps;
HDC hdc = BeginPaint(hwnd, &ps);
RECT rc;
GetClientRect(hwnd, &rc);
FillRect(hdc, &rc, static_cast<HBRUSH>(GetStockObject(WHITE_BRUSH)));
if (rc.bottom > 50)
rc.top += 10;
if (rc.right - rc.left > 200) {
rc.left += 10;
rc.right -= 10;
}
SelectObject(hdc, GetStockObject(DEFAULT_GUI_FONT));
SetTextColor(hdc, RGB(40, 0, 0));
DrawText(hdc,
uT(PFC_string_formatter() << "foo_chronflow error:\n"
<< engineError.c_str()),
-1, &rc, DT_WORDBREAK | DT_CENTER | DT_NOCLIP | DT_NOPREFIX);
EndPaint(hwnd, &ps);
}
void ContainerWindow::destroyEngineWindow(std::string errorMessage) {
if (!engineWindow)
return;
engineWindow.reset();
engineError = errorMessage;
FB2K_console_formatter() << "foo_chronflow encountered an error:\n"
<< errorMessage.c_str();
}