YSTest: Win32GUI.cpp 源文件

YSTest PreAlpha_b500_20140530 The YSLib Test Project

- 首页
- 相关页面
- 模块
- 命名空间
- 类
- 文件

- 文件列表
- 文件成员

全部 类 命名空间 文件 函数 变量 类型定义 枚举 枚举值 友元 宏定义 组 页
Win32GUI.cpp
浏览该文件的文档.
1 /*
2 © 2013-2014 FrankHB.
3
4 This file is part of the YSLib project, and may only be used,
5 modified, and distributed under the terms of the YSLib project
6 license, LICENSE.TXT. By continuing to use, modify, or distribute
7 this file you indicate that you have read the license and
8 understand and accept it fully.
9 */
10
29 #include "YCLib/YModules.h"
30 #include YFM_MinGW32_YCLib_Win32GUI
31
32 using namespace YSLib;
33 using namespace Drawing;
34
35 namespace platform_ex
36 {
37
38 namespace Windows
39 {
40
41 namespace
42 {
43
45 void
46 ResizeWindow(::HWND h_wnd, SDst w, SDst h)
47 {
48 if(YB_UNLIKELY(!::SetWindowPos(h_wnd, {}, 0, 0, w, h,
49 SWP_ASYNCWINDOWPOS | SWP_NOACTIVATE
50 | SWP_NOMOVE | SWP_NOOWNERZORDER | SWP_NOSENDCHANGING | SWP_NOZORDER)))
51 YF_Raise_Win32Exception("SetWindowPos @ ResizeWindow");
52 }
53
55 ::RECT
56 FetchWindowRect(::HWND h_wnd)
57 {
58 ::RECT rect;
59
60 if(YB_UNLIKELY(!::GetWindowRect(h_wnd, &rect)))
61 YF_Raise_Win32Exception("GetWindowRect");
62 return rect;
63 }
64
66
67 Size
68 FetchSizeFromBounds(const ::RECT& rect)
69 {
70 YAssert(rect.right - rect.left >= 0 && rect.bottom - rect.top >= 0,
71 "Invalid boundary found.");
72 return {rect.right - rect.left, rect.bottom - rect.top};
73 }
74
75 inline Rect
76 FetchRectFromBounds(const ::RECT& rect)
77 {
78 return Rect(rect.left, rect.top, FetchSizeFromBounds(rect));
79 }
80
81 inline ::DWORD
82 FetchWindowStyle(::HWND h_wnd)
83 {
84 return ::GetWindowLongW(h_wnd, GWL_STYLE);
85 }
86
87 void
88 AdjustWindowBounds(::RECT& rect, ::HWND h_wnd, bool b_menu = false)
89 {
90 if(YB_UNLIKELY(!::AdjustWindowRect(&rect, FetchWindowStyle(h_wnd), b_menu)))
91 YF_Raise_Win32Exception("AdjustWindowRect");
92 YAssert(rect.right - rect.left >= 0 && rect.bottom - rect.top >= 0,
93 "Invalid boundary found.");
94 }
95
96 void
97 SetWindowBounds(::HWND h_wnd, int x, int y, int cx, int cy)
98 {
99 if(YB_UNLIKELY(!::SetWindowPos(h_wnd, {}, x, y, cx, cy,
100 SWP_ASYNCWINDOWPOS | SWP_NOACTIVATE
101 | SWP_NOOWNERZORDER | SWP_NOSENDCHANGING | SWP_NOZORDER)))
102 YF_Raise_Win32Exception("SetWindowPos @ SetWindowBounds");
103 }
105
106 } // unnamed namespace;
107
108
109 Rect
110 WindowReference::GetClientBounds() const
111 {
112 return {GetClientLocation(), GetClientSize()};
113 }
114 Point
115 WindowReference::GetClientLocation() const
116 {
117 ::POINT point{0, 0};
118
119 if(YB_UNLIKELY(!::ClientToScreen(hWindow, &point)))
120 YF_Raise_Win32Exception("ClientToScreen");
121 return {point.x, point.y};
122 }
123 Size
124 WindowReference::GetClientSize() const
125 {
126 ::RECT rect;
127
128 if(YB_UNLIKELY(!::GetClientRect(hWindow, &rect)))
129 YF_Raise_Win32Exception("GetClientRect");
130 return {rect.right, rect.bottom};
131 }
132 Point
133 WindowReference::GetLocation() const
134 {
135 const auto& rect(FetchWindowRect(hWindow));
136
137 return {rect.left, rect.top};
138 }
139 YSLib::Drawing::AlphaType
140 WindowReference::GetOpacity() const
141 {
142 ystdex::byte a;
143
144 if(YB_UNLIKELY(!GetLayeredWindowAttributes(hWindow, {}, &a, {})))
145 YF_Raise_Win32Exception("GetLayeredWindowAttributes");
146 return a;
147 }
148 Size
149 WindowReference::GetSize() const
150 {
151 return FetchSizeFromBounds(FetchWindowRect(hWindow));
152 }
153
154 void
155 WindowReference::SetClientBounds(const Rect& r)
156 {
157 ::RECT rect{r.X, r.Y, r.X + r.Width, r.Y + r.Height};
158
159 AdjustWindowBounds(rect, hWindow);
160 SetWindowBounds(hWindow, rect.left, rect.top, rect.right - rect.left,
161 rect.bottom - rect.top);
162 }
163 void
164 WindowReference::SetOpacity(YSLib::Drawing::AlphaType a)
165 {
166 if(YB_UNLIKELY(!SetLayeredWindowAttributes(hWindow, 0, a, LWA_ALPHA)))
167 YF_Raise_Win32Exception("SetLayeredWindowAttributes");
168 }
169 void
170 WindowReference::SetText(const wchar_t* str)
171 {
172 if(YB_UNLIKELY(!::SetWindowTextW(hWindow, str)))
173 YF_Raise_Win32Exception("SetWindowTextW");
174 }
175
176 void
177 WindowReference::Close()
178 {
179 if(YB_UNLIKELY(!::SendNotifyMessageW(hWindow, WM_CLOSE, 0, 0)))
180 YF_Raise_Win32Exception("SendNotifyMessageW");
181 }
182
183 void
184 WindowReference::Invalidate()
185 {
186 if(YB_UNLIKELY(!::InvalidateRect(hWindow, {}, false)))
187 YF_Raise_Win32Exception("InvalidateRect");
188 }
189
190 void
191 WindowReference::Move(const Point& pt)
192 {
193 if(YB_UNLIKELY(!::SetWindowPos(hWindow, {}, pt.X, pt.Y, 0, 0,
194 SWP_ASYNCWINDOWPOS | SWP_NOACTIVATE | SWP_NOOWNERZORDER | SWP_NOREDRAW
195 | SWP_NOSENDCHANGING | SWP_NOSIZE | SWP_NOZORDER)))
196 YF_Raise_Win32Exception("SetWindowPos @ WindowReference::Move");
197 }
198
199 void
200 WindowReference::Resize(const Size& s)
201 {
202 ResizeWindow(hWindow, s.Width, s.Height);
203 }
204
205 void
206 WindowReference::ResizeClient(const Size& s)
207 {
208 ::RECT rect{0, 0, s.Width, s.Height};
209
210 AdjustWindowBounds(rect, hWindow);
211 ResizeWindow(hWindow, rect.right - rect.left, rect.bottom - rect.top);
212 }
213
214 bool
215 WindowReference::Show() ynothrow
216 {
217 return ::ShowWindowAsync(hWindow, SW_SHOWNORMAL) != 0;
218 }
219
220
221 NativeWindowHandle
222 CreateNativeWindow(const wchar_t* class_name, const Drawing::Size& s,
223 const wchar_t* title, ::DWORD wstyle, ::DWORD wstyle_ex)
224 {
225 ::RECT rect{0, 0, s.Width, s.Height};
226
227 ::AdjustWindowRect(&rect, wstyle, false);
228 return ::CreateWindowExW(wstyle_ex, class_name, title, wstyle,
229 CW_USEDEFAULT, CW_USEDEFAULT, rect.right - rect.left,
230 rect.bottom - rect.top, HWND_DESKTOP, {}, ::GetModuleHandleW({}), {});
231 }
232
233
234 ScreenBuffer::ScreenBuffer(const Size& s)
235 : size(s), hBitmap([this]{
236 // NOTE: Bitmap format is hard coded here for explicit buffer
237 // compatibility. %::CreateCompatibleBitmap is not fit for unknown
238 // windows.
239 ::BITMAPINFO bmi{{sizeof(::BITMAPINFOHEADER), size.Width,
240 -size.Height - 1, 1, 32, BI_RGB,
241 sizeof(PixelType) * size.Width * size.Height, 0, 0, 0, 0}, {}};
242
243 return ::CreateDIBSection({}, &bmi, DIB_RGB_COLORS,
244 &reinterpret_cast<void*&>(pBuffer), {}, 0);
245 }())
246 {}
247 ScreenBuffer::ScreenBuffer(ScreenBuffer&& sbuf) ynothrow
248 : size(sbuf.size), hBitmap(sbuf.hBitmap)
249 {
250 sbuf.hBitmap = {};
251 }
252 ScreenBuffer::~ScreenBuffer()
253 {
254 ::DeleteObject(hBitmap);
255 }
256
257 ScreenBuffer&
258 ScreenBuffer::operator=(ScreenBuffer&& sbuf)
259 {
260 sbuf.swap(*this);
261 return *this;
262 }
263
264 void
265 ScreenBuffer::Resize(const Size& s)
266 {
267 if(s != size)
268 *this = ScreenBuffer(s);
269 }
270
271 void
272 ScreenBuffer::Premultiply(BitmapPtr buf) ynothrow
273 {
274 // NOTE: Since the stride is guaranteed equal to the width, the storage for
275 // pixels can be supposed to be contiguous.
276 std::transform(buf, buf + size.Width * size.Height, pBuffer,
277 [](const PixelType& pixel){
278 const auto a(pixel.GetA());
279
280 return PixelType{MonoType(pixel.GetB() * a / 0xFF),
281 MonoType(pixel.GetG() * a / 0xFF),
282 MonoType(pixel.GetR() * a / 0xFF), a};
283 });
284 }
285
286 void
287 ScreenBuffer::UpdateFrom(BitmapPtr p_buf) ynothrow
288 {
289 // NOTE: Since the pitch is guaranteed equal to the width, the storage for
290 // pixels can be supposed to be contiguous.
291 YAssertNonnull(p_buf);
292 std::copy_n(p_buf, size.Width * size.Height, GetBufferPtr());
293 }
294
295 void
296 ScreenBuffer::swap(ScreenBuffer& sbuf) ynothrow
297 {
298 std::swap(size, sbuf.size),
299 std::swap(pBuffer, sbuf.pBuffer),
300 std::swap(hBitmap, sbuf.hBitmap);
301 }
302
303
304 void
305 ScreenRegionBuffer::UpdateFrom(BitmapPtr buf) ynothrow
306 {
307 std::lock_guard<std::mutex> lck(mtx);
308
309 ScreenBuffer::UpdateFrom(buf);
310 }
311
312 void
313 ScreenRegionBuffer::UpdatePremultipliedTo(NativeWindowHandle h_wnd, AlphaType a,
314 const Point& pt) ynothrow
315 {
316 std::lock_guard<std::mutex> lck(mtx);
317 GSurface<> sf(h_wnd);
318
319 sf.UpdatePremultiplied(*this, h_wnd, a, pt);
320 }
321
322 void
323 ScreenRegionBuffer::UpdateTo(NativeWindowHandle h_wnd, const Point& pt) ynothrow
324 {
325 std::lock_guard<std::mutex> lck(mtx);
326 GSurface<> sf(h_wnd);
327
328 sf.Update(*this, pt);
329 }
330
331
332 void
333 WindowMemorySurface::Update(ScreenBuffer& sbuf, const Point& pt) ynothrow
334 {
335 const auto h_old(::SelectObject(h_mem_dc, sbuf.GetNativeHandle()));
336 const auto& s(sbuf.GetSize());
337
338 // NOTE: Unlocked intentionally for performance.
339 ::BitBlt(h_owner_dc, pt.X, pt.Y, s.Width, s.Height, h_mem_dc, 0, 0,
340 SRCCOPY);
341 ::SelectObject(h_mem_dc, h_old);
342 }
343 void
344 WindowMemorySurface::UpdatePremultiplied(ScreenBuffer& sbuf,
345 NativeWindowHandle h_wnd, YSLib::Drawing::AlphaType a, const Point& pt)
346 ynothrow
347 {
348 const auto h_old(::SelectObject(h_mem_dc, sbuf.GetNativeHandle()));
349 auto rect(FetchWindowRect(h_wnd));
350 ::SIZE size{rect.right - rect.left, rect.bottom - rect.top};
351 ::POINT ptx{pt.X, pt.Y};
352 ::BLENDFUNCTION bfunc{AC_SRC_OVER, 0, a, AC_SRC_ALPHA};
353
354 // NOTE: Unlocked intentionally for performance.
355 if(YB_UNLIKELY(!::UpdateLayeredWindow(h_wnd, h_owner_dc,
356 reinterpret_cast<::POINT*>(&rect), &size, h_mem_dc, &ptx, 0, &bfunc,
357 ULW_ALPHA)))
358 {
359 // TODO: Use RAII.
360 ::SelectObject(h_mem_dc, h_old);
361 YF_Raise_Win32Exception("UpdateLayeredWindow");
362 }
363 ::SelectObject(h_mem_dc, h_old);
364 }
365
366
367 WindowClass::WindowClass(const wchar_t* class_name, ::WNDPROC wnd_proc,
368 ::UINT style, ::HBRUSH h_bg)
369 : h_instance(::GetModuleHandleW({}))
370 {
371 // NOTE: Intentionally no %CS_OWNDC or %CS_CLASSDC, so %::ReleaseDC
372 // is always needed.
373 const ::WNDCLASSW wnd_class{style, wnd_proc, 0, 0, h_instance,
374 ::LoadIconW({}, IDI_APPLICATION), ::LoadCursorW({}, IDC_ARROW),
375 h_bg, nullptr, class_name};
376
377 if(YB_UNLIKELY(::RegisterClassW(&wnd_class) == 0))
378 YF_Raise_Win32Exception("RegisterClassW");
379 // TODO: Trace class name.
380 YTraceDe(Notice, "Window class registered.");
381 }
382 WindowClass::~WindowClass()
383 {
384 ::UnregisterClassW(WindowClassName, h_instance);
385 // TODO: Trace class name.
386 YTraceDe(Notice, "Window class unregistered.");
387 }
388
389
390 HostWindow::HostWindow(NativeWindowHandle h)
391 : WindowReference(h),
392 MessageMap()
393 {
394 YAssert(::IsWindow(h), "Invalid window handle found.");
395 YAssert(::GetWindowThreadProcessId(h, {}) == ::GetCurrentThreadId(),
396 "Window not created on current thread found.");
397 YAssert(::GetWindowLongPtrW(h, GWLP_USERDATA) == 0,
398 "Invalid user data of window found.");
399
400 wchar_t buf[ystdex::arrlen(WindowClassName)];
401
402 if(YB_UNLIKELY(!::GetClassNameW(hWindow, buf,
403 ystdex::arrlen(WindowClassName))))
404 YF_Raise_Win32Exception("GetClassNameW");
405 if(std::wcscmp(buf, WindowClassName) != 0)
406 throw LoggedEvent("Wrong windows class name found.");
407 ::SetLastError(0);
408 if(YB_UNLIKELY(::SetWindowLongPtrW(hWindow, GWLP_USERDATA,
409 ::LONG_PTR(this)) == 0 && GetLastError() != 0))
410 YF_Raise_Win32Exception("SetWindowLongPtrW");
411 if(YB_UNLIKELY(!::SetWindowPos(hWindow, {}, 0, 0, 0, 0, SWP_NOACTIVATE
412 | SWP_NOMOVE | SWP_NOOWNERZORDER | SWP_NOREDRAW | SWP_NOSENDCHANGING
413 | SWP_NOSIZE | SWP_NOZORDER)))
414 YF_Raise_Win32Exception("SetWindowPos @ HostWindow::HostWindow");
415
416 ::RAWINPUTDEVICE rid{0x01, 0x02, 0, nullptr};
417
418 if(YB_UNLIKELY(!::RegisterRawInputDevices(&rid, 1, sizeof(rid))))
419 YF_Raise_Win32Exception("RegisterRawInputDevices");
420 MessageMap[WM_DESTROY] += []{
421 ::PostQuitMessage(0);
422 };
423 }
424 HostWindow::~HostWindow()
425 {
426 ::SetWindowLongPtrW(hWindow, GWLP_USERDATA, ::LONG_PTR());
427 // NOTE: The window could be already destroyed in window procedure.
428 if(::IsWindow(hWindow))
429 ::DestroyWindow(hWindow);
430 }
431
432 } // namespace Windows;
433
434 } // namespace platform_ex;
435
platform_ex::Windows::ScreenBuffer::swap
void swap(ScreenBuffer &) ynothrow
Definition: Win32GUI.cpp:296
platform_ex::Windows::WindowClass::h_instance
::HINSTANCE h_instance
Definition: include/YCLib/Win32GUI.h:402
platform_ex::Windows::ScreenBuffer::~ScreenBuffer
~ScreenBuffer()
Definition: Win32GUI.cpp:252
platform_ex::Windows::WindowClassName
yconstexpr wchar_t WindowClassName[]
Definition: include/YCLib/Win32GUI.h:412
YSLib::PostQuitMessage
YF_API void PostQuitMessage(int nExitCode, Messaging::Priority p=0xF0)
以优先级 p 发起 Shell 终止请求，返回 nExitCode。
Definition: yapp.cpp:83
platform_ex::Windows::GSurface
显式区域表面：储存显式区域上的二维图形绘制状态。
Definition: include/YCLib/Win32GUI.h:385
ystdex::arrlen
size_t arrlen(_type(&)[_vN])
计算指定数组类型对象的长度。
Definition: utility.hpp:196
platform_ex::Windows::ScreenBuffer::operator=
ScreenBuffer & operator=(ScreenBuffer &&)
Definition: Win32GUI.cpp:258
platform_ex::Windows::WindowMemorySurface::UpdatePremultiplied
pt void UpdatePremultiplied(ScreenBuffer &, NativeWindowHandle, YSLib::Drawing::AlphaType=0xFF, const YSLib::Drawing::Point &={}) ynothrow
Definition: Win32GUI.cpp:344
YSLib::UI::Invalidate
YF_API void Invalidate(IWidget &, const Rect &)
无效化：使相对于部件的指定区域在直接和间接的窗口缓冲区中无效。
Definition: ywidget.cpp:111
YModules.h
platform_ex::Windows::HostWindow::MessageMap
std::map<::UINT, YSLib::GEvent< void(::WPARAM,::LPARAM)> > MessageMap
窗口消息转发事件映射。
Definition: include/YCLib/Win32GUI.h:432
ystdex::byte
unsigned char byte
字节类型。
Definition: ydef.h:555
YSLib::Drawing::Size::Height
SDst Height
宽和高。
Definition: ygdibase.h:258
platform_ex::Windows::WindowClass::~WindowClass
~WindowClass()
Definition: Win32GUI.cpp:382
platform_ex::Windows::ScreenBuffer::pBuffer
YSLib::Drawing::BitmapPtr pBuffer
Definition: include/YCLib/Win32GUI.h:176
platform::SDst
std::uint16_t SDst
屏幕坐标距离。
Definition: Video.h:39
YSLib::UI::Show
YF_API void Show(IWidget &)
显示部件。
Definition: ywidget.cpp:206
platform_ex::Windows::HostWindow::HostWindow
HostWindow(NativeWindowHandle)
Definition: Win32GUI.cpp:390
platform_ex::Windows::WindowReference::hWindow
NativeWindowHandle hWindow
Definition: include/YCLib/Win32GUI.h:57
platform_ex::Windows::hBitmap
hBitmap(sbuf.hBitmap)
Definition: Win32GUI.cpp:248
platform_ex::Windows::CreateNativeWindow
YF_API NativeWindowHandle CreateNativeWindow(const wchar_t *, const YSLib::Drawing::Size &, const wchar_t *=L"",::DWORD=WS_POPUP,::DWORD=WS_EX_LTRREADING)
按指定窗口类名、客户区大小、标题文本、样式和附加样式创建本机顶层窗口。
Definition: Win32GUI.cpp:222
ystdex::swap
void swap(any &x, any &y)
交换对象。
Definition: any.h:729
YB_UNLIKELY
#define YB_UNLIKELY(expr)
分支预测提示。
Definition: ydef.h:298
platform_ex::Windows::ScreenBuffer::ScreenBuffer
ScreenBuffer(const YSLib::Drawing::Size &)
Definition: Win32GUI.cpp:234
platform_ex::Windows::WindowReference
本机窗口引用。
Definition: include/YCLib/Win32GUI.h:54
platform_ex::Android::UpdateFrom
DefGetter(ynothrow, ScreenBuffer &, ScreenBufferRef,*this) using ScreenBuffer voi UpdateFrom)(YSLib::Drawing::BitmapPtr) ynothrow
Definition: Android.h:234
platform::Descriptions::Notice
Definition: ycommon.h:76
ynothrow
#define ynothrow
YSLib 无异常抛出保证：若支持 noexcept 关键字， 指定特定的 noexcept 异常规范。
Definition: ydef.h:514
YSLib::Drawing::GBinaryGroup::Y
_type Y
分量。
Definition: ygdibase.h:59
YSLib::Drawing::Rect
屏幕标准矩形：表示屏幕矩形区域。
Definition: ygdibase.h:416
YSLib::Drawing::GBinaryGroup< SPos >
YF_Raise_Win32Exception
#define YF_Raise_Win32Exception(...)
按 ::GetLastError 的结果和指定参数抛出 Windows::Win32Exception 对象。
Definition: include/YCLib/MinGW32.h:97
platform_ex::Windows::UpdatePremultipliedTo
void UpdatePremultipliedTo(NativeWindowHandle, YSLib::Drawing::AlphaType=0xFF, const YSLib::Drawing::Point &={}) ynothrow
Definition: Win32GUI.cpp:313
YAssertNonnull
#define YAssertNonnull(_expr)
Definition: cassert.h:81
YSLib::Drawing::GBinaryGroup::X
_type X
Definition: ygdibase.h:59
platform_ex::NativeWindowHandle
::ANativeWindow * NativeWindowHandle
Definition: Android.h:50
platform_ex::Android::UpdateTo
void UpdateTo(NativeWindowHandle, const YSLib::Drawing::Point &={}) ynothrow
platform_ex::Windows::ScreenBuffer
虚拟屏幕缓存。
Definition: include/YCLib/Win32GUI.h:169
platform_ex::Windows::s
return s
Definition: MinGW32.cpp:49
platform_ex::Windows::ScreenBuffer::hBitmap
::HBITMAP hBitmap
Definition: include/YCLib/Win32GUI.h:177
YTraceDe
#define YTraceDe(...)
YCLib 默认调试跟踪。
Definition: Debug.h:269
YSLib::LoggedEvent
记录日志的异常事件类。
Definition: yexcept.h:58
platform::BitmapPtr
PixelType * BitmapPtr
Definition: Video.h:295
YSLib::Drawing::r
bounds & r
Definition: ydraw.h:220
YSLib::Drawing::Size
屏幕区域大小。
Definition: ygdibase.h:249
YSLib::Drawing::Size::Width
SDst Width
Definition: ygdibase.h:258
platform::AlphaType
ystdex::octet AlphaType
Definition: Video.h:186
YSLib::UI::Close
void Close(IWidget &wgt)
Definition: ywidget.cpp:95
YAssert
#define YAssert(_expr, _msg)
Definition: cassert.h:73
platform_ex::Windows::ScreenBuffer::Resize
hBitmap DefGetter(const ynothrow, const YSLib::Drawing::Size &, Size, size) void Premultiply(YSLib void Resize(const YSLib::Drawing::Size &)
从缓冲区更新并按 Alpha 预乘。
Definition: include/YCLib/Win32GUI.h:210
platform_ex::Windows::ScreenBuffer::size
YSLib::Drawing::Size size
Definition: include/YCLib/Win32GUI.h:173