YSTest: HostedGUI.cpp 源文件

YSTest PreAlpha_b800_20170810 The YSLib Test Project

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

- 文件列表
- 文件成员

HostedGUI.cpp
浏览该文件的文档.
1 /*
2 © 2013-2017 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_YCLib_HostedGUI // for default_delete;
31 #include YFM_YSLib_Core_YCoreUtilities // for YSLib::CheckPositive,
32 // ystdex::aligned_store_cast;
33 #if YCL_Win32
34 # include YFM_Win32_YCLib_MinGW32
35 # include <ystdex/exception.h> // for ystdex::unimplemented;
36 # if SW_SHOWNORMAL != 1 || WS_POPUP != 0x80000000L || WS_EX_LTRREADING != 0L
37 # error "Wrong macro defined."
38 # endif
39 # include YFM_YCLib_Input // for platform::ClearKeyStates;
40 # include "YSLib/Service/YModules.h"
41 # include YFM_YSLib_Service_YBlit // for ystdex::pvoid, YSLib::BlitLines;
42 # include YFM_Win32_YCLib_NLS // for platform_ex::WCSToUTF8;
43 # include <Shellapi.h> // for ::ShellExecuteW;
44 # include <ystdex/mixin.hpp> // for ystdex::wrap_mixin_t;
45 #elif YCL_Android
46 # include YFM_Android_YCLib_Android
47 # include <android/native_window.h>
48 # include "YSLib/Service/YModules.h"
49 # include YFM_YSLib_Service_YBlit // for YSLib::BlitLines;
50 #endif
51 #if YCL_HostedUI_XCB || YCL_Android
52 # include "YSLib/Service/YModules.h"
53 # include YFM_YSLib_Service_YGDI
54 #endif
55
56 using namespace YSLib;
57 using namespace Drawing;
59 using YSLib::string;
61 using platform::string_view;
62
63 #if YF_Hosted
64
65 namespace platform_ex
66 {
67
68 void
69 HostWindowDelete::operator()(pointer p) const ynothrow
70 {
71 # if YCL_HostedUI_XCB
72 default_delete<XCB::WindowData>()(p.get());
73 # elif YCL_Win32
74 // NOTE: The window could be already destroyed in window procedure.
75 if(::IsWindow(p))
76 // XXX: Error ignored.
77 ::DestroyWindow(p);
78 # elif YCL_Android
79 // XXX: Error ignored.
80 ::ANativeWindow_release(p);
81 # endif
82 }
83
84
85 # if YCL_Win32
86 void
87 GDIObjectDelete::operator()(pointer h) const ynothrow
88 {
89 static_assert(std::is_same<pointer, ::HGDIOBJ>::value,
90 "Mismatched type found.");
91
92 YCL_TraceCallF_Win32(DeleteObject, h);
93 }
94 # endif
95
96 namespace
97 {
98
99 # if YCL_HostedUI_XCB || YCL_Android
100 SDst
102 CheckStride(SDst buf_stride, SDst w)
103 {
104 if(buf_stride < w)
105 // XXX: Use more specified exception type.
106 throw std::runtime_error("Stride is small than width.");
107 return buf_stride;
108 }
109 # elif YCL_Win32
110 void
112 MoveWindow(::HWND h_wnd, SPos x, SPos y)
113 {
114 YCL_CallF_Win32(SetWindowPos, h_wnd, {}, x, y, 0, 0, SWP_ASYNCWINDOWPOS
115 | SWP_NOACTIVATE | SWP_NOOWNERZORDER | SWP_NOREDRAW | SWP_NOSENDCHANGING
116 | SWP_NOSIZE | SWP_NOZORDER);
117 }
118
120 void
121 ResizeWindow(::HWND h_wnd, SDst w, SDst h)
122 {
123 YCL_CallF_Win32(SetWindowPos, h_wnd, {}, 0, 0, int(w), int(h),
124 SWP_ASYNCWINDOWPOS | SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOOWNERZORDER
125 | SWP_NOREDRAW | SWP_NOSENDCHANGING | SWP_NOZORDER);
126 }
127
129 ::RECT
130 FetchWindowRect(::HWND h_wnd)
131 {
132 ::RECT rect;
133
134 YCL_CallF_Win32(GetWindowRect, h_wnd, &rect);
135 return rect;
136 }
137
139
140 Size
141 FetchSizeFromBounds(const ::RECT& rect)
142 {
143 return {CheckArithmetic<SDst>(rect.right - rect.left, "width"),
144 CheckArithmetic<SDst>(rect.bottom - rect.top, "height")};
145 }
146
148 Rect
149 FetchRectFromBounds(const ::RECT& rect)
150 {
151 return {rect.left, rect.top, FetchSizeFromBounds(rect)};
152 }
153
155 inline WindowStyle
156 FetchWindowStyle(::HWND h_wnd)
157 {
158 return WindowStyle(::GetWindowLongW(h_wnd, GWL_STYLE));
159 }
160
161 void
162 AdjustWindowBounds(::RECT& rect, ::HWND h_wnd, bool b_menu = {})
163 {
164 YCL_CallF_Win32(AdjustWindowRect, &rect, FetchWindowStyle(h_wnd), b_menu);
165 FetchSizeFromBounds(rect);
166 }
167
169 void
170 SetWindowBounds(::HWND h_wnd, int x, int y, SDst w, SDst h)
171 {
172 YCL_CallF_Win32(SetWindowPos, h_wnd, {}, x, y, int(w), int(h),
173 SWP_ASYNCWINDOWPOS | SWP_NOACTIVATE | SWP_NOOWNERZORDER
174 | SWP_NOREDRAW | SWP_NOSENDCHANGING | SWP_NOZORDER);
175 }
177
178
180 inline unique_ptr_from<GlobalDelete>
181 MakeMoveableGlobalMemory(size_t size)
182 {
183 auto p(unique_raw(::GlobalAlloc(GMEM_MOVEABLE, size), GlobalDelete()));
184
185 if(YB_UNLIKELY(!p))
186 // TODO: Use inherited class of exception.
187 throw std::bad_alloc();
188 return p;
189 }
190
192 template<typename _tChar, class _tString>
193 YB_ALLOCATOR YB_ATTR_returns_nonnull void*
194 CopyGlobalString(const _tString& str)
195 {
196 const auto len(str.length());
197 auto p(MakeMoveableGlobalMemory((len + 1) * sizeof(_tChar)));
198 {
199 const GlobalLocked gl(Nonnull(p));
200 const auto p_buf(gl.GetPtr<_tChar>().get());
201
202 ystdex::ntctscpy(p_buf, str.data(), len);
203 }
204 return p.release();
205 }
206 # endif
207
208 } // unnamed namespace;
209
210
211 # if YCL_Win32
212 void
213 BindDefaultWindowProc(NativeWindowHandle h_wnd, MessageMap& m, unsigned msg,
214 EventPriority prior)
215 {
216 m[msg].Add(
217 [=](::WPARAM w_param, ::LPARAM l_param, ::LRESULT& res) ynothrow{
218 res = ::DefWindowProcW(h_wnd, msg, w_param, l_param);
219 }, prior);
220 }
221 # endif
222
223
224 # if YCL_HostedUI_XCB
225 XCB::WindowData&
226 WindowReference::Deref() const
227 {
228 if(const auto h = GetNativeHandle().get())
229 return *h;
230 throw std::runtime_error("Null window reference found.");
231 }
232 # elif YCL_Win32
233 bool
234 WindowReference::IsMaximized() const ynothrow
235 {
236 return ::IsZoomed(GetNativeHandle());
237 }
238 bool
239 WindowReference::IsMinimized() const ynothrow
240 {
241 return ::IsIconic(GetNativeHandle());
242 }
243 bool
244 WindowReference::IsVisible() const ynothrow
245 {
246 return ::IsWindowVisible(GetNativeHandle());
247 }
248
249 Rect
250 WindowReference::GetBounds() const
251 {
252 return FetchRectFromBounds(FetchWindowRect(GetNativeHandle()));
253 }
254 Rect
255 WindowReference::GetClientBounds() const
256 {
257 return {GetClientLocation(), GetClientSize()};
258 }
259 Point
260 WindowReference::GetClientLocation() const
261 {
262 ::POINT point{0, 0};
263
264 YCL_CallF_Win32(ClientToScreen, GetNativeHandle(), &point);
265 return {point.x, point.y};
266 }
267 Size
268 WindowReference::GetClientSize() const
269 {
270 ::RECT rect;
271
272 YCL_CallF_Win32(GetClientRect, GetNativeHandle(), &rect);
273 return {rect.right, rect.bottom};
274 }
275 Point
276 WindowReference::GetCursorLocation() const
277 {
278 ::POINT cursor;
279
280 YCL_CallF_Win32(GetCursorPos, &cursor);
281 YCL_CallF_Win32(ScreenToClient, GetNativeHandle(), &cursor);
282 return {cursor.x, cursor.y};
283 }
284 Point
285 WindowReference::GetLocation() const
286 {
287 const auto& rect(FetchWindowRect(GetNativeHandle()));
288
289 return {rect.left, rect.top};
290 }
291 YSLib::Drawing::AlphaType
292 WindowReference::GetOpacity() const
293 {
294 byte a;
295
296 YCL_CallF_Win32(GetLayeredWindowAttributes, GetNativeHandle(), {}, &a, {});
297 return a;
298 }
299 Size
300 WindowReference::GetSize() const
301 {
302 return FetchSizeFromBounds(FetchWindowRect(GetNativeHandle()));
303 }
304
305 void
306 WindowReference::SetBounds(const Rect& r)
307 {
308 SetWindowBounds(GetNativeHandle(), r.X, r.Y, r.Width, r.Height);
309 }
310 void
311 WindowReference::SetClientBounds(const Rect& r)
312 {
313 ::RECT rect{r.X, r.Y, CheckArithmetic<SPos>(r.GetRight(), "width"),
314 CheckArithmetic<SPos>(r.GetBottom(), "height")};
315 const auto h_wnd(GetNativeHandle());
316
317 AdjustWindowBounds(rect, h_wnd);
318 SetWindowBounds(h_wnd, rect.left, rect.top, SDst(rect.right - rect.left),
319 SDst(rect.bottom - rect.top));
320 }
321 void
322 WindowReference::SetOpacity(YSLib::Drawing::AlphaType a)
323 {
324 YCL_CallF_Win32(SetLayeredWindowAttributes, GetNativeHandle(), 0, a,
325 LWA_ALPHA);
326 }
327 WindowReference
328 WindowReference::GetParent() const
329 {
330 // TODO: Implementation.
331 throw ystdex::unimplemented();
332 }
333
334 void
335 WindowReference::SetText(const wchar_t* str)
336 {
337 YTraceDe(Debug, "Setting text '%p' to window reference '%p'...",
338 ystdex::pvoid(str), ystdex::pvoid(this));
339 YCL_CallF_Win32(SetWindowTextW, GetNativeHandle(), str);
340 }
341
342 void
343 WindowReference::Close()
344 {
345 YTraceDe(Debug, "Closing window reference '%p'...", ystdex::pvoid(this));
346 YCL_CallF_Win32(SendNotifyMessageW, GetNativeHandle(), WM_CLOSE, 0, 0);
347 }
348
349 void
350 WindowReference::Invalidate()
351 {
352 YTraceDe(Debug, "Invalidating window reference '%p'...",
353 ystdex::pvoid(this));
354 YCL_CallF_Win32(InvalidateRect, GetNativeHandle(), {}, {});
355 }
356
357 void
358 WindowReference::Move(const Point& pt)
359 {
360 MoveWindow(GetNativeHandle(), pt.X, pt.Y);
361 }
362
363 void
364 WindowReference::MoveClient(const Point& pt)
365 {
366 ::RECT rect{pt.X, pt.Y, pt.X, pt.Y};
367 const auto h_wnd(GetNativeHandle());
368
369 AdjustWindowBounds(rect, h_wnd);
370 MoveWindow(h_wnd, rect.left, rect. top);
371 }
372
373 void
374 WindowReference::Resize(const Size& s)
375 {
376 ResizeWindow(GetNativeHandle(), s.Width, s.Height);
377 }
378
379 void
380 WindowReference::ResizeClient(const Size& s)
381 {
382 ::RECT rect{0, 0, CheckArithmetic<SPos>(s.Width, "width"),
383 CheckArithmetic<SPos>(s.Height, "height")};
384 const auto h_wnd(GetNativeHandle());
385
386 AdjustWindowBounds(rect, h_wnd);
387 ResizeWindow(h_wnd, SDst(rect.right - rect.left),
388 SDst(rect.bottom - rect.top));
389 }
390
391 bool
392 WindowReference::Show(int n_cmd_show) ynothrow
393 {
394 return ::ShowWindowAsync(GetNativeHandle(), n_cmd_show) != 0;
395 }
396 # elif YCL_Android
397 SDst
398 WindowReference::GetWidth() const
399 {
400 return CheckPositive<SDst>(
401 ::ANativeWindow_getWidth(GetNativeHandle()), "width");
402 }
403 SDst
404 WindowReference::GetHeight() const
405 {
406 return CheckPositive<SDst>(::ANativeWindow_getHeight(
407 GetNativeHandle()), "height");
408 }
409 # endif
410
411
412 # if YCL_HostedUI_XCB
413 void
414 UpdateContentTo(NativeWindowHandle h_wnd, const Rect& r, const ConstGraphics& g)
415 {
416 XCB::UpdatePixmapBuffer(Deref(h_wnd.get()), r, g);
417 }
418 # elif YCL_Win32
419 YF_API ::HBITMAP
420 CreateCompatibleDIBSection(const YSLib::Drawing::Size& s, BitmapPtr& p_buffer)
421 {
422 // NOTE: There is no resolution information created. See https://msdn.microsoft.com/en-us/library/dd183494.aspx.
423 // NOTE: It would return %ERROR_INVALID_PARAMETER for many calls if
424 // allocated memory is not on 32-bit boundary. Anyway it is not a matter
425 // here because the pixel is at least 32-bit. See
426 // http://msdn2.microsoft.com/en-us/library/ms532292.aspx and https://msdn.microsoft.com/en-us/library/dd183494.aspx.
427 // NOTE: Bitmap format is hard coded here for explicit buffer
428 // compatibility. %::CreateCompatibleBitmap is not fit for unknown
429 // windows.
430 ::BITMAPINFO bmi{{sizeof(::BITMAPINFOHEADER), CheckPositive<long>(
431 s.Width, "width"), -CheckPositive<long>(s.Height,
432 "height") - 1, 1, 32, BI_RGB, static_cast<unsigned long>(
433 sizeof(Pixel) * s.Width * s.Height), 0, 0, 0, 0}, {}};
434 void* p_buf{};
435 const auto h(YCL_CallF_Win32(CreateDIBSection, {}, &bmi, DIB_RGB_COLORS,
436 &p_buf, {}, 0));
437
438 if(YB_LIKELY(p_buf))
439 p_buffer = static_cast< BitmapPtr>(p_buf);
440 else
441 // XXX: This should not occur unless there are bugs in implementation of
442 // %::CreateCompatibleDIBSection.
443 throw std::runtime_error("Failed writing pointer"
444 " @ CreateCompatibleDIBSection.");
445 return h;
446 }
447
448 NativeWindowHandle
449 CreateNativeWindow(const wchar_t* class_name, const Drawing::Size& s,
450 const wchar_t* title, WindowStyle wstyle, WindowStyle wstyle_ex)
451 {
452 ::RECT rect{0, 0, CheckArithmetic<SPos>(s.Width, "width"),
453 CheckArithmetic<SPos>(s.Height, "height")};
454
455 ::AdjustWindowRect(&rect, wstyle, false);
456 return ::CreateWindowExW(wstyle_ex, class_name, title, wstyle,
457 CW_USEDEFAULT, CW_USEDEFAULT, rect.right - rect.left, rect.bottom
458 - rect.top, {}/*HWND_DESKTOP*/, {}, ::GetModuleHandleW({}), {});
459 }
460 # elif YCL_Android
461 void
462 UpdateContentTo(NativeWindowHandle h_wnd, const Rect& r, const ConstGraphics& g)
463 {
464 ::ANativeWindow_Buffer abuf;
465 ::ARect arect{r.X, r.Y, r.X + r.Width, r.Y + r.Height};
466 const auto res(::ANativeWindow_lock(Nonnull(h_wnd), &abuf, &arect));
467
468 if(YB_LIKELY(res == 0))
469 {
470 BlitLines<false, false>(CopyLine<true>(), BitmapPtr(abuf.bits),
471 g.GetBufferPtr(), WindowReference(h_wnd).GetSize(), g.GetSize(),
472 r.GetPoint(), {}, r.GetSize());
473 ::ANativeWindow_unlockAndPost(h_wnd);
474 }
475 else
476 YTraceDe(Warning, "::ANativeWindow_lock failed, error = %d.", int(res));
477 }
478 # endif
479
480
481 # if YCL_HostedUI_XCB || YCL_Android
482 class ScreenBufferData : public CompactPixmap
483 {
484 public:
485 ScreenBufferData(const Size&, SDst);
486
487 DefDeMoveCtor(ScreenBufferData)
488 };
489
490 ScreenBufferData::ScreenBufferData(const Size& s, SDst buf_stride)
491 : CompactPixmap({}, CheckStride(buf_stride, s.Width), s.Height)
492 {}
493 # endif
494
495
496 # if YCL_HostedUI_XCB || YCL_Android
497 ScreenBuffer::ScreenBuffer(const Size& s)
498 : ScreenBuffer(s, s.Width)
499 {}
500 ScreenBuffer::ScreenBuffer(const Size& s, SDst buf_stride)
501 : p_impl(new ScreenBufferData(s, buf_stride)), width(s.Width)
502 {}
503 ScreenBuffer::ScreenBuffer(ScreenBuffer&& sbuf) ynothrow
504 : p_impl(new ScreenBufferData(std::move(*sbuf.p_impl))), width(sbuf.width)
505 {
506 sbuf.width = 0;
507 }
508 # elif YCL_Win32
509 ScreenBuffer::ScreenBuffer(const Size& s)
510 : size(s), p_bitmap(CreateCompatibleDIBSection(s, p_buffer))
511 {}
512 ScreenBuffer::ScreenBuffer(ScreenBuffer&&) ynothrow = default;
513 # endif
514 ImplDeDtor(ScreenBuffer)
515
516 # if YCL_HostedUI_XCB || YCL_Android
517 BitmapPtr
518 ScreenBuffer::GetBufferPtr() const ynothrow
519 {
520 return Deref(p_impl).GetBufferPtr();
521 }
522 YSLib::Drawing::Graphics
523 ScreenBuffer::GetContext() const ynothrow
524 {
525 return Deref(p_impl).GetContext();
526 }
527 Size
528 ScreenBuffer::GetSize() const ynothrow
529 {
530 return {width, Deref(p_impl).GetHeight()};
531 }
532 YSLib::SDst
533 ScreenBuffer::GetStride() const ynothrow
534 {
535 return Deref(p_impl).GetWidth();
536 }
537
538 void
539 ScreenBuffer::Resize(const Size& s)
540 {
541 // TODO: Expand stride for given width using a proper strategy.
542 Deref(p_impl).SetSize(s);
543 width = s.Width;
544 }
545 # elif YCL_Win32
546 void
547 ScreenBuffer::Resize(const Size& s)
548 {
549 if(s != size)
550 *this = ScreenBuffer(s);
551 }
552
553 void
554 ScreenBuffer::Premultiply(ConstBitmapPtr p_buf) ynothrow
555 {
556 YAssertNonnull(p_buf);
557 // NOTE: Since the stride is guaranteed equal to the width, the storage for
558 // pixels can be supposed to be contiguous.
559 std::transform(p_buf, p_buf + size.Width * size.Height, p_buffer,
560 [](const Pixel& pixel) ynothrow{
561 const auto a(pixel.GetA());
562
563 return Pixel{MonoType(pixel.GetB() * a / 0xFF),
564 MonoType(pixel.GetG() * a / 0xFF),
565 MonoType(pixel.GetR() * a / 0xFF), a};
566 });
567 }
568 # endif
569
570 void
571 ScreenBuffer::UpdateFrom(ConstBitmapPtr p_buf) ynothrow
572 {
573 # if YCL_HostedUI_XCB || YCL_Android
574 // TODO: Expand stride for given width using a proper strategy.
575 CopyBitmapBuffer(Deref(p_impl).GetBufferPtr(), p_buf, GetSize());
576 # elif YCL_Win32
577 // NOTE: Since the pitch is guaranteed equal to the width, the storage for
578 // pixels can be supposed to be contiguous.
579 CopyBitmapBuffer(GetBufferPtr(), p_buf, size);
580 # endif
581 }
582
583 # if YCL_Win32
584 void
585 ScreenBuffer::UpdateFromBounds(ConstBitmapPtr p_buf, const Rect& r) ynothrow
586 {
587 BlitLines<false, false>(CopyLine<true>(), GetBufferPtr(), Nonnull(p_buf),
588 size, size, r.GetPoint(), r.GetPoint(), r.GetSize());
589 }
590
591 void
592 ScreenBuffer::UpdatePremultipliedTo(NativeWindowHandle h_wnd, AlphaType a,
593 const Point& pt)
594 {
595 GSurface<> sf(h_wnd);
596
597 sf.UpdatePremultiplied(*this, h_wnd, a, pt);
598 }
599 # endif
600
601 void
602 ScreenBuffer::UpdateTo(NativeWindowHandle h_wnd, const Point& pt) ynothrow
603 {
604 # if YCL_HostedUI_XCB || YCL_Android
605 UpdateContentTo(h_wnd, {pt, GetSize()}, GetContext());
606 # elif YCL_Win32
607 GSurface<>(h_wnd).UpdateBounds(*this, {pt, GetSize()});
608 # endif
609 }
610 # if YCL_Win32
611 void
612 ScreenBuffer::UpdateToBounds(NativeWindowHandle h_wnd, const Rect& r,
613 const Point& sp) ynothrow
614 {
615 GSurface<>(h_wnd).UpdateBounds(*this, r, sp);
616 }
617 # endif
618
619 void
620 swap(ScreenBuffer& x, ScreenBuffer& y) ynothrow
621 {
622 # if YCL_HostedUI_XCB || YCL_Android
623 swap(Deref(x.p_impl), Deref(y.p_impl)),
624 std::swap(x.width, y.width);
625 # elif YCL_Win32
626 std::swap(x.size, y.size),
627 std::swap(x.p_buffer, y.p_buffer),
628 std::swap(x.p_bitmap, y.p_bitmap);
629 # endif
630 }
631
632
633 # if YCL_Win32
634 WindowMemorySurface::WindowMemorySurface(::HDC h_dc)
635 : h_owner_dc(h_dc), h_mem_dc(::CreateCompatibleDC(h_dc))
636 {}
637 WindowMemorySurface::~WindowMemorySurface()
638 {
639 ::DeleteDC(h_mem_dc);
640 }
641
642 void
643 WindowMemorySurface::UpdateBounds(ScreenBuffer& sbuf, const Rect& r,
644 const Point& sp) ynothrow
645 {
646 // NOTE: %Nonnull is for invariant check.
647 const auto h_old(::SelectObject(h_mem_dc, Nonnull(sbuf.GetNativeHandle())));
648
649 if(h_old)
650 {
651 YCL_TraceCallF_Win32(BitBlt, h_owner_dc, int(r.X), int(r.Y),
652 int(r.Width), int(r.Height), h_mem_dc, int(sp.X), int(sp.Y),
653 SRCCOPY);
654 if(YB_UNLIKELY(!::SelectObject(h_mem_dc, h_old)))
655 YTraceDe(Err, "Restoring GDI object failed"
656 " @ WindowMemorySurface::UpdateBounds.");
657 }
658 else
659 YTraceDe(Err, "Setting GDI object failed"
660 " @ WindowMemorySurface::UpdateBounds.");
661 }
662
663 void
664 WindowMemorySurface::UpdatePremultiplied(ScreenBuffer& sbuf,
665 NativeWindowHandle h_wnd, YSLib::Drawing::AlphaType a, const Point& sp)
666 ynothrow
667 {
668 const auto h_old(::SelectObject(h_mem_dc, sbuf.GetNativeHandle()));
669 auto rect(FetchWindowRect(h_wnd));
670 ::SIZE size{rect.right - rect.left, rect.bottom - rect.top};
671 ::POINT pt{sp.X, sp.Y};
672 ::BLENDFUNCTION bfunc{AC_SRC_OVER, 0, a, AC_SRC_ALPHA};
673
674 YCL_TraceCallF_Win32(UpdateLayeredWindow, h_wnd, h_owner_dc,
675 ystdex::aligned_store_cast<::POINT*>(&rect), &size, h_mem_dc, &pt, 0,
676 &bfunc, ULW_ALPHA);
677 ::SelectObject(h_mem_dc, h_old);
678 }
679
680
681 WindowDeviceContext::WindowDeviceContext(NativeWindowHandle h_wnd)
682 // NOTE: Painting using %::GetDC and manually managing clipping areas
683 // instead of %::GetDCEx, for performance and convenience calculation
684 // of input boundary.
685 : WindowDeviceContextBase(h_wnd, ::GetDC(Nonnull(h_wnd)))
686 {
687 if(YB_UNLIKELY(!hDC))
688 throw LoggedEvent("Retrieving device context failure.");
689 }
690 WindowDeviceContext::~WindowDeviceContext()
691 {
692 ::ReleaseDC(hWindow, hDC);
693 }
694
695
696 struct PaintStructData::Data final : ::PAINTSTRUCT
697 {};
698
699
700 PaintStructData::PaintStructData()
701 : pun(ystdex::default_init, &ps)
702 {
703 static_assert(ystdex::is_aligned_storable<decltype(ps), Data>(),
704 "Invalid buffer found.");
705 }
706 ImplDeDtor(PaintStructData)
707
708
709 WindowRegionDeviceContext::WindowRegionDeviceContext(NativeWindowHandle h_wnd)
710 : PaintStructData(),
711 WindowDeviceContextBase(h_wnd, ::BeginPaint(Nonnull(h_wnd), &Get()))
712 {
713 if(YB_UNLIKELY(!hDC))
714 throw LoggedEvent("Device context initialization failure.");
715 }
716 WindowRegionDeviceContext::~WindowRegionDeviceContext()
717 {
718 // NOTE: Return value is ignored since it is always %TRUE.
719 ::EndPaint(hWindow, &Get());
720 }
721
722 bool
723 WindowRegionDeviceContext::IsBackgroundValid() const ynothrow
724 {
725 return !bool(Get().fErase);
726 }
727
728 Rect
729 WindowRegionDeviceContext::GetInvalidatedArea() const
730 {
731 return FetchRectFromBounds(Get().rcPaint);
732 }
733
734
735 WindowClass::WindowClass(const wchar_t* class_name, ::WNDPROC wnd_proc,
736 unsigned style, ::HBRUSH h_bg, ::HINSTANCE h_inst)
737 // NOTE: Intentionally no %CS_OWNDC or %CS_CLASSDC, so %::ReleaseDC
738 // is always needed.
739 : WindowClass(::WNDCLASSW{style, wnd_proc ? wnd_proc
740 : HostWindow::WindowProcedure, 0, 0, h_inst
741 ? h_inst : ::GetModuleHandleW({}), ::LoadIconW({}, IDI_APPLICATION),
742 ::LoadCursorW({}, IDC_ARROW), h_bg, nullptr, Nonnull(class_name)})
743 {}
744 WindowClass::WindowClass(const ::WNDCLASSW& wc)
745 : WindowClass(wc.lpszClassName, YCL_CallF_Win32(RegisterClassW, &wc),
746 wc.hInstance)
747 {}
748 WindowClass::WindowClass(const ::WNDCLASSEXW& wc)
749 : WindowClass(wc.lpszClassName, YCL_CallF_Win32(RegisterClassExW, &wc),
750 wc.hInstance)
751 {}
752 WindowClass::WindowClass(wstring_view class_name,
753 unsigned short class_atom, ::HINSTANCE h_inst)
754 : name((Nonnull(class_name.data()), class_name)), atom(class_atom),
755 h_instance(h_inst)
756 {
757 if(YB_UNLIKELY(atom == 0))
758 throw std::invalid_argument("Invalid atom value found.");
759 YTraceDe(Notice, "Window class '%s' of atom '%hu' registered.",
760 name.empty() ? "<unknown>" : WCSToUTF8(name).c_str(), atom);
761 }
762 WindowClass::~WindowClass()
763 {
764 ::UnregisterClassW(reinterpret_cast<const wchar_t*>(atom), h_instance);
765 FilterExceptions([this]{
766 YTraceDe(Notice, "Window class '%s' of atom '%hu' unregistered.",
767 name.empty() ? "<unknown>" : WCSToUTF8(name).c_str(), atom);
768 }, yfsig);
769 }
770 # endif
771
772
773 HostWindow::HostWindow(NativeWindowHandle h)
774 : WindowReference(Nonnull(h))
775 # if YCL_HostedUI_XCB
776 , WM_PROTOCOLS(platform::Deref(h.get()).LookupAtom("WM_PROTOCOLS"))
777 , WM_DELETE_WINDOW(h.get()->LookupAtom("WM_DELETE_WINDOW"))
778 # endif
779 # if YCL_HostedUI_XCB || YCL_Win32
780 , MessageMap()
781 # endif
782 {
783 # if YCL_HostedUI_XCB
784 h.get()->GetConnectionRef().Check();
785 # elif YCL_Win32
786 YAssert(::IsWindow(h), "Invalid window handle found.");
787 YAssert(::GetWindowThreadProcessId(h, {}) == ::GetCurrentThreadId(),
788 "Window not created on current thread found.");
789 YAssert(::GetWindowLongPtrW(h, GWLP_USERDATA) == 0,
790 "Invalid user data of window found.");
791
792 wchar_t buf[size(WindowClassName)];
793
794 YCL_CallF_Win32(GetClassNameW, GetNativeHandle(), buf,
795 int(size(WindowClassName)));
796 if(std::wcscmp(buf, WindowClassName) != 0)
797 throw GeneralEvent("Wrong windows class name found.");
798 ::SetLastError(0);
799 if(YB_UNLIKELY(::SetWindowLongPtrW(GetNativeHandle(), GWLP_USERDATA,
800 ::LONG_PTR(this)) == 0 && GetLastError() != 0))
801 YCL_Raise_Win32E("SetWindowLongPtrW", yfsig);
802 YCL_CallF_Win32(SetWindowPos, GetNativeHandle(), {}, 0, 0, 0, 0,
803 SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOOWNERZORDER | SWP_NOREDRAW
804 | SWP_NOSENDCHANGING | SWP_NOSIZE | SWP_NOZORDER);
805
806 ::RAWINPUTDEVICE rid{0x01, 0x02, 0, nullptr};
807
808 YCL_CallF_Win32(RegisterRawInputDevices, &rid, 1, sizeof(rid));
809 MessageMap[WM_DESTROY] += []() ynothrow{
810 ::PostQuitMessage(0);
811 YTraceDe(Debug, "Host quit message posted.");
812 };
813 # elif YCL_Android
814 ::ANativeWindow_acquire(GetNativeHandle());
815 # endif
816 }
817
818 HostWindow::~HostWindow()
819 {
820 const unique_ptr_from<HostWindowDelete> p_wnd(GetNativeHandle());
821
822 # if YCL_Win32
823 // XXX: Error ignored.
824 ::SetWindowLongPtrW(p_wnd.get(), GWLP_USERDATA, ::LONG_PTR());
825 # endif
826 }
827
828 # if YCL_Win32
829 Point
830 HostWindow::MapPoint(const Point& pt) const
831 {
832 return pt;
833 }
834
835 ::LRESULT __stdcall
836 HostWindow::WindowProcedure(::HWND h_wnd, unsigned msg, ::WPARAM w_param,
837 ::LPARAM l_param) ynothrowv
838 {
839 if(const auto p = reinterpret_cast<HostWindow*>(
840 ::GetWindowLongPtrW(h_wnd, GWLP_USERDATA)))
841 {
842 auto& m(p->MessageMap);
843
844 try
845 {
846 const auto i(m.find(msg));
847
848 if(i != m.cend())
849 {
850 ::LRESULT res(0);
851
852 i->second(w_param, l_param, res);
853 return res;
854 }
855 }
856 CatchExpr(..., YTraceDe(Warning, "HostWindow::WindowPrecedure failed."))
857 }
858 return ::DefWindowProcW(h_wnd, msg, w_param, l_param);
859 }
860 # endif
861
862
863 WindowInputHost::WindowInputHost(HostWindow& wnd)
864 : Window(wnd)
865 # if YCL_Win32
866 , has_hosted_caret(::CreateCaret(wnd.GetNativeHandle(), {}, 1, 1))
867 # endif
868 {
869 # if YCL_Win32
870 auto& m(wnd.MessageMap);
871
872 yunseq(
873 m[WM_MOVE] += [this]{
874 UpdateCandidateWindowLocation();
875 },
876 m[WM_KILLFOCUS] += []{
877 ClearKeyStates();
878 },
879 m[WM_INPUT] += [this](::WPARAM, ::LPARAM l_param) ynothrow{
880 ::RAWINPUT ri;
881 unsigned size(sizeof(ri));
882
883 // TODO: Use '{}' to simplify initialization after CWG 1368 resolved by
884 // C++14. See $2015-09 @ %Documentation::Workflow::Annual2015.
885 ystdex::trivially_fill_n(&ri);
886 if(YB_LIKELY(::GetRawInputData(::HRAWINPUT(l_param), RID_INPUT, &ri,
887 &size, sizeof(::RAWINPUTHEADER)) != unsigned(-1) && ri.header.dwType
888 == RIM_TYPEMOUSE) && ri.data.mouse.usButtonFlags == RI_MOUSE_WHEEL)
889 // NOTE: This value is safe to cast because it is
890 // specified as a signed value, see https://msdn.microsoft.com/en-us/library/windows/desktop/ms645578(v=vs.85).aspx.
891 RawMouseButton = short(ri.data.mouse.usButtonData);
892 },
893 m[WM_CHAR] += [this](::WPARAM w_param, ::LPARAM l_param){
894 lock_guard<recursive_mutex> lck(input_mutex);
895 size_t n(l_param & 0x7FFF);
896
897 while(n-- != 0)
898 comp_str += char16_t(w_param);
899 },
900 m[WM_IME_COMPOSITION] += [this]{
901 UpdateCandidateWindowLocation();
902 }
903 );
904 ystdex::unseq_apply([&](int msg){
905 BindDefaultWindowProc(wnd.GetNativeHandle(), m, unsigned(msg));
906 }, WM_MOVE, WM_IME_COMPOSITION);
907 # endif
908 }
909 WindowInputHost::~WindowInputHost()
910 {
911 # if YCL_Win32
912 if(has_hosted_caret)
913 ::DestroyCaret();
914 # endif
915 }
916
917 # if YCL_Win32
918 void
919 WindowInputHost::UpdateCandidateWindowLocation()
920 {
921 lock_guard<recursive_mutex> lck(input_mutex);
922
923 UpdateCandidateWindowLocationUnlocked();
924 }
925 void
926 WindowInputHost::UpdateCandidateWindowLocation(const Point& pt)
927 {
928 if(pt != Point::Invalid)
929 {
930 lock_guard<recursive_mutex> lck(input_mutex);
931
932 caret_location = pt;
933 UpdateCandidateWindowLocationUnlocked();
934 }
935 }
936 void
937 WindowInputHost::UpdateCandidateWindowLocationUnlocked()
938 {
939 if(YB_LIKELY(caret_location != Point::Invalid))
940 {
941 YTraceDe(Informative, "Update composition form position: %s.",
942 to_string(caret_location).c_str());
943
944 const auto h_wnd(Nonnull(Window.GetNativeHandle()));
945
946 if(const auto h_imc = ::ImmGetContext(h_wnd))
947 {
948 // FIXME: Correct location?
949 const auto client_pt(caret_location + Window.GetClientLocation()
950 - Window.GetClientLocation());
951
952 ::CANDIDATEFORM cand_form{0, CFS_CANDIDATEPOS,
953 {client_pt.X, client_pt.Y}, {0, 0, 0, 0}};
954
955 // TODO: Error handling.
956 ::ImmSetCandidateWindow(h_imc, &cand_form);
957 ::ImmReleaseContext(h_wnd, h_imc);
958 }
959 // FIXME: Correct implementation for non-Chinese IME.
960 // NOTE: See comment on %IMM32Manager::MoveImeWindow in
961 // https://src.chromium.org/viewvc/chrome/trunk/src/ui/base/ime/win/imm32_manager.cc.
962 ::SetCaretPos(caret_location.X, caret_location.Y);
963 }
964 }
965 # endif
966
967
968 # if YCL_Win32
969 class Clipboard::Data : public GlobalLocked
970 {
971 using GlobalLocked::GlobalLocked;
972 };
973
974
975 Clipboard::Clipboard(NativeWindowHandle h_wnd)
976 {
977 // FIXME: Spin for remote desktops?
978 YCL_CallF_Win32(OpenClipboard, h_wnd);
979 }
980 Clipboard::~Clipboard()
981 {
982 YCL_TraceCallF_Win32(CloseClipboard, );
983 }
984
985 bool
986 Clipboard::IsAvailable(FormatType fmt) ynothrow
987 {
988 return bool(::IsClipboardFormatAvailable(fmt));
989 }
990
991 void
992 Clipboard::CheckAvailable(FormatType fmt)
993 {
994 YCL_CallF_Win32(IsClipboardFormatAvailable, fmt);
995 }
996
997 void
998 Clipboard::Clear() ynothrow
999 {
1000 YCL_TraceCallF_Win32(EmptyClipboard, );
1001 }
1002
1003 NativeWindowHandle
1004 Clipboard::GetOpenWindow() ynothrow
1005 {
1006 return ::GetOpenClipboardWindow();
1007 }
1008
1009 bool
1010 Clipboard::Receive(YSLib::string& str)
1011 {
1012 return ReceiveRaw(CF_TEXT, [&](const Data& d) ynothrowv{
1013 str = d.GetPtr<char>().get();
1014 });
1015 }
1016 bool
1017 Clipboard::Receive(YSLib::String& str)
1018 {
1019 return ReceiveRaw(CF_UNICODETEXT, [&](const Data& d) ynothrowv{
1020 str = d.GetPtr<char16_t>().get();
1021 });
1022 }
1023
1024 bool
1025 Clipboard::ReceiveRaw(FormatType fmt, std::function<void(const Data&)> f)
1026 {
1027 if(IsAvailable(fmt))
1028 if(const auto h = ::GetClipboardData(fmt))
1029 {
1030 const Data d(h);
1031
1032 Nonnull(f)(d);
1033 return true;
1034 }
1035 return {};
1036 }
1037
1038 void
1039 Clipboard::Send(string_view sv)
1040 {
1041 YAssertNonnull(sv.data());
1042 SendRaw(CF_TEXT, CopyGlobalString<char>(sv));
1043 }
1044 void
1045 Clipboard::Send(u16string_view sv)
1046 {
1047 YAssertNonnull(sv.data());
1048 SendRaw(CF_UNICODETEXT, CopyGlobalString<char16_t>(sv));
1049 }
1050 void
1051 Clipboard::Send(ConstBitmapPtr p_bmp, const Size& s)
1052 {
1053 YAssertNonnull(p_bmp),
1054 YAssert(s != Size::Invalid, "Invalid size found.");
1055
1056 auto p(MakeMoveableGlobalMemory(sizeof(::BITMAPV5HEADER)
1057 + GetAreaOf(s) * sizeof(Pixel)));
1058 {
1059 const GlobalLocked gl(Nonnull(p));
1060 const auto p_buf(gl.GetPtr<::BITMAPV5HEADER>().get());
1061
1062 *p_buf = {sizeof(::BITMAPV5HEADER), CheckPositive<long>(s.Width,
1063 "width"), -CheckPositive<long>(s.Height, "height"), 1, 32,
1064 BI_BITFIELDS, static_cast<unsigned long>(sizeof(Pixel)
1065 * GetAreaOf(s)), 0, 0, 0, 0, 0x00FF0000, 0x0000FF00, 0x000000FF,
1066 0xFF000000, 0x73524742/*LCS_sRGB*/, {{0, 0, 0}, {0, 0, 0}, {0, 0, 0}
1067 }, 0, 0, 0, LCS_GM_IMAGES, 0, 0, 0},
1068 CopyBitmapBuffer(ystdex::aligned_store_cast<Pixel*>(p_buf + 1), p_bmp,
1069 s);
1070 }
1071 SendRaw(CF_DIBV5, p.release());
1072 }
1073
1074 void
1075 Clipboard::SendRaw(FormatType fmt, void* h)
1076 {
1077 Clear();
1078 YCL_CallF_Win32(SetClipboardData, fmt, h);
1079 }
1080
1081
1082 void
1083 ExecuteShellCommand(const wchar_t* cmd, const wchar_t* args, bool use_admin,
1084 const wchar_t* dir, int n_cmd_show, NativeWindowHandle h_parent)
1085 {
1086 // TODO: Set current working directory as %USERPROFILE%?
1087 auto res(int(std::intptr_t(::ShellExecuteW(h_parent,
1088 use_admin ? L"runas" : nullptr, Nonnull(cmd), args, dir, n_cmd_show))));
1089
1090 switch(res)
1091 {
1092 case 0:
1093 case SE_ERR_OOM:
1094 // TODO: Use inherited class of exception.
1095 throw std::bad_alloc();
1096 case SE_ERR_SHARE:
1097 case SE_ERR_DLLNOTFOUND:
1098 res = SE_ERR_SHARE ? ERROR_SHARING_VIOLATION : ERROR_DLL_NOT_FOUND;
1099 YB_ATTR_fallthrough;
1100 case ERROR_FILE_NOT_FOUND: // NOTE: Same as %SE_ERR_FNF.
1101 case ERROR_PATH_NOT_FOUND: // NOTE: Same as %SE_ERR_PNF.
1102 case ERROR_ACCESS_DENIED: // NOTE: Same as %SE_ERR_ACCESSDENIED.
1103 case ERROR_BAD_FORMAT:
1104 throw Win32Exception(ErrorCode(res), "ShellExecuteW", Err);
1105 case SE_ERR_ASSOCINCOMPLETE:
1106 case SE_ERR_NOASSOC:
1107 case SE_ERR_DDETIMEOUT:
1108 case SE_ERR_DDEFAIL:
1109 case SE_ERR_DDEBUSY:
1110 {
1111 using boxed_exception
1112 = ystdex::wrap_mixin_t<std::runtime_error, int>;
1113
1114 TryExpr(throw
1115 boxed_exception{std::runtime_error("ShellExecuteW"), res})
1116 catch(boxed_exception& e)
1117 {
1118 const auto throw_ex([=](int ec) YB_ATTR(noreturn){
1119 std::throw_with_nested(Win32Exception(ErrorCode(ec),
1120 ystdex::sfmt("ShellExecuteW: %d", res), Err));
1121 });
1122
1123 switch(e.value)
1124 {
1125 case SE_ERR_ASSOCINCOMPLETE:
1126 case SE_ERR_NOASSOC:
1127 throw_ex(ERROR_NO_ASSOCIATION);
1128 case SE_ERR_DDETIMEOUT:
1129 case SE_ERR_DDEFAIL:
1130 case SE_ERR_DDEBUSY:
1131 throw_ex(ERROR_DDE_FAIL);
1132 default:
1133 break;
1134 }
1135 }
1136 YAssert(false, "Invalid state found.");
1137 }
1138 YB_ATTR_fallthrough;
1139 default:
1140 if(res > 32)
1141 YTraceDe(Informative, "ExecuteShellCommand: ::ShellExecute call"
1142 " succeed with return value %d.", res);
1143 else
1144 throw LoggedEvent(ystdex::sfmt("ExecuteShellCommand:"
1145 " ::ShellExecuteW call failed" " with unknown error '%d'.",
1146 res), Err);
1147 }
1148 }
1149 # endif
1150
1151 } // namespace platform_ex;
1152
1153 #endif
1154
YTraceDe
#define YTraceDe(...)
YCLib 默认调试跟踪。
Definition: Debug.h:313
YSLib::Drawing::GetHeight
tr GetHeight())) inline PDefH(void
按字体高度和行距调整文本区域的底边距。
ystdex::ntctscpy
enable_if_irreplaceable_char_t< _tChar, _tChar * > ntctscpy(_tChar *s1, const _tChar *s2)
复制 NTCTS 。
Definition: cstring.h:250
YSLib::UI::Move
移动：位置调整。
Definition: YWidgetEvent.h:382
platform::Descriptions::Debug
Definition: YCommon.h:170
YSLib::UI::ynothrow
AView &y ynothrow
Definition: YWidgetView.cpp:47
platform::msg
const string & msg
Definition: Debug.h:464
YSLib::UI::args
yconstfn const string _tParams && args
Definition: Loader.h:131
YModules.h
YSLib::EventPriority
std::uint8_t EventPriority
事件优先级。
Definition: YEvent.hpp:211
YSLib::Drawing::GBinaryGroup::Y
_type Y
分量。
Definition: YGDIBase.h:63
YSLib
YSLib 命名空间。
Definition: AndroidHost.h:45
ystdex::to_string
std::string to_string(const std::thread::id &)
转换 thread::id 为字符串表示。
YSLib::Drawing::GGraphics
二维图形接口上下文模板。
Definition: YGraphics.h:62
platform
默认平台命名空间。
Definition: Container.h:47
platform::Deref
yconstfn auto Deref(_type &&p) -> decltype(*p)
断言并解引用非空指针。
Definition: Debug.h:451
YSLib::UI::y
SPos SPos y
Definition: YWidget.cpp:44
YSLib::Drawing::BitmapPtr
Pixel * BitmapPtr
Definition: YGraphics.h:42
yfsig
#define yfsig
展开为表示函数签名的预定义变量的宏。
Definition: ydef.h:728
YSLib::Drawing::r
The boundary is out of the const Graphics const Rect const Point const Point Color c const Rect const Rect & r
Definition: YDraw.h:174
ystdex::u16string_view
basic_string_view< char16_t > u16string_view
Definition: string_view.hpp:416
ystdex::trivially_fill_n
_type * trivially_fill_n(_type *first, size_t n=1, byte value={})
填充字节序列。
Definition: algorithm.hpp:369
YCL_HostedUI_XCB
#define YCL_HostedUI_XCB
在宿主用户界面使用 X C 绑定。
Definition: Platform.h:384
CHRLib::f
f(d, s)
YSLib::Drawing::CompactPixmap
标准矩形像素图缓冲区。
Definition: YGDI.h:243
YSLib::Drawing::CopyBitmapBuffer
void CopyBitmapBuffer(_tOut p_dst, _tIn p_src, const Size &s)
Definition: YGraphics.h:50
DefDeMoveCtor
#define DefDeMoveCtor(_t)
Definition: YBaseMacro.h:167
YAssertNonnull
#define YAssertNonnull(_expr)
Definition: cassert.h:120
ystdex::is_aligned_storable
判断是否可对齐存储。
Definition: type_pun.hpp:72
YB_UNLIKELY
#define YB_UNLIKELY(_expr)
分支预测提示。
Definition: ydef.h:464
NPL::c_str
YF_API const char src c_str())) YF_API void InstallDirectory(const string &
安装目录：复制目录树。
Definition: Dependency.h:131
YSLib::UI::Close
void Close(IWidget &wgt)
Definition: YWidget.cpp:92
YSLib::LoggedEvent
记录日志的异常事件类。
Definition: YException.h:50
YCL_Raise_Win32E
#define YCL_Raise_Win32E(...)
取转换为 errno 的 Win32 错误。
Definition: MinGW32.h:138
platform::containers::string
basic_string< char > string
Definition: Container.h:101
YSLib::Text::buf
const char * buf
Definition: TextFile.h:81
YCL_CallF_Win32
#define YCL_CallF_Win32(_fn,...)
Definition: MinGW32.h:190
ystdex::unique_raw
std::unique_ptr< _type > unique_raw(_pSrc *p)
Definition: memory.hpp:740
ystdex::data
auto data(_tRange &c) -> decltype(c.data())
Definition: range.hpp:280
platform::KeyCodes::DS::L
Definition: Keys.h:227
YSLib::YAssert
YAssert(!(v< Deref(a)),"Value less than lower bound found.")
yunseq
#define yunseq
无序列依赖表达式组求值。
Definition: ydef.h:1022
YSLib::UI::IsVisible
IsVisible
Definition: YWidget.h:101
platform_ex::Windows::unsigned
YF_API unsigned
Definition: NLS.h:52
YSLib::UI::Invalidate
YF_API void Invalidate(IWidget &, const Rect &)
无效化：使相对部件的指定区域在直接和间接的窗口缓冲区中无效。
Definition: YWidget.cpp:108
platform_ex::Windows::WCSToUTF8
const char *str string_view sv WCSToUTF8
Definition: NLS.h:79
YSLib::PostQuitMessage
YF_API void PostQuitMessage(int=0, Messaging::Priority p=DefaultQuitPriority)
以指定错误码和优先级发起 Shell 终止请求。
Definition: YApplication.cpp:86
YB_ATTR
#define YB_ATTR(...)
GNU 风格属性。
Definition: ydef.h:353
platform::AlphaType
octet AlphaType
Definition: Video.h:253
TryExpr
#define TryExpr(...)
指定表达式在 try 块中求值。
Definition: YBaseMacro.h:120
YB_ATTR_returns_nonnull
#define YB_ATTR_returns_nonnull
指示返回非空属性。
Definition: ydef.h:413
ystdex::wstring_view
basic_string_view< wchar_t > wstring_view
Definition: string_view.hpp:418
YSLib::a
YB_PURE const _type * a
Definition: YCoreUtilities.h:167
YSLib::UI::Resize
大小调整。
Definition: YWidgetEvent.h:383
YSLib::Drawing::Size::Width
SDst Width
Definition: YGDIBase.h:302
platform::SDst
std::uint16_t SDst
屏幕坐标距离。
Definition: Video.h:44
CatchExpr
#define CatchExpr(_ex,...)
指定表达式作为异常处理器。
Definition: YBaseMacro.h:129
YSLib::Drawing::x
The boundary is out of the const Rect SDst SPos x
Definition: YDraw.h:127
YSLib::Drawing::w
The boundary is out of the const Rect SDst w
Definition: YDraw.h:127
YSLib::Drawing::g
The boundary is out of the const Graphics & g
Definition: YDraw.h:161
YSLib::FilterExceptions
bool FilterExceptions(_func f, const char *desc={}, RecordLevel lv=Alert, ExceptionTracer trace=ExtractAndTrace) ynothrow
调用函数并过滤宿主异常。
Definition: YException.h:203
YSLib::Drawing::Size::Invalid
static const Size Invalid
无效对象。
Definition: YGDIBase.h:300
CHRLib::s
_tDst const _tSrc * s
Definition: CharacterProcessing.h:140
NPL::LexemeCategory::Data
数据字面量。
YSLib::UI::Window
窗口。
Definition: YWindow.h:44
platform::if
if(!p) p
ystdex::sfmt
auto sfmt(const _tChar *fmt,...) -> decltype(vsfmt(fmt, std::declval< std::va_list >()))
以 C 标准输出格式的输出 std::basic_string 实例的对象。
Definition: string.hpp:1200
ystdex
特性测试宏。
Definition: ydef.h:822
YSLib::Drawing::GBinaryGroup< SPos >::Invalid
static const GBinaryGroup Invalid
无效（不在屏幕坐标系中）对象。
Definition: YGDIBase.h:58
YSLib::i
return i
Definition: YCoreUtilities.h:176
Drawing
YModules.h
platform::SPos
std::int16_t SPos
屏幕坐标度量。
Definition: Video.h:43
YSLib::ynothrow
YB_PURE const _type size_t n ynothrow
Definition: YCoreUtilities.h:168
platform::Descriptions::Notice
Definition: YCommon.h:168
YSLib::UI::e
void e
Definition: YWidget.h:352
exception.h
YSLib::Drawing::GBinaryGroup< SPos >
ynothrowv
#define ynothrowv
YSLib 无异常抛出保证验证：有条件地使用无异常抛出规范。
Definition: ydef.h:786
YSLib::UI::Show
YF_API void Show(IWidget &)
显示部件。
Definition: YWidget.cpp:202
YSLib::Drawing::Rect
屏幕标准矩形：表示屏幕矩形区域。
Definition: YGDIBase.h:540
YSLib::Drawing::Size::Height
SDst Height
宽和高。
Definition: YGDIBase.h:302
ystdex::swap
void swap(container_adaptor< _tSeqCon > &x, container_adaptor< _tSeqCon > &y)
Definition: container.hpp:179
std
Definition: memory.hpp:1183
ystdex::byte
unsigned char byte
字节类型。
Definition: ydef.h:834
platform::Nonnull
_type && Nonnull(_type &&p) ynothrowv
断言并返回非空参数。
Definition: Debug.h:422
mixin.hpp
基于类继承的混入接口。
YB_ALLOCATOR
#define YB_ALLOCATOR
指示修饰的是分配器，或返回分配器调用的函数或函数模板。
Definition: ydef.h:432
YSLib::GeneralEvent
std::runtime_error GeneralEvent
一般运行时异常事件类。
Definition: YException.h:46
ystdex::unimplemented
异常：未实现的操作。
Definition: ystdex/exception.h:135
platform::Descriptions::Warning
Definition: YCommon.h:167
platform::Descriptions::Err
Definition: YCommon.h:166
platform_ex::ClearKeyStates
YF_API void ClearKeyStates()
清除按键缓冲。
Definition: Input.cpp:159
ystdex::mixin
混入对象。
Definition: mixin.hpp:45
platform_ex
平台扩展命名空间。
Definition: Android.h:45
YSLib::UI::name
yconstfn const string & name
Definition: Loader.h:130
platform::Descriptions::Informative
Definition: YCommon.h:169
YSLib::Drawing::Size
屏幕区域大小。
Definition: YGDIBase.h:293
YSLib::Text::str
const char const char * str
Definition: TextFile.h:81
ystdex::pvoid
enable_if_t< or_< is_object< _type >, is_void< _type > >::value, void * > pvoid(_type *p)
取 void* 类型的指针。
Definition: addressof.hpp:101
YSLib::Drawing::GBinaryGroup::X
_type X
Definition: YGDIBase.h:63
YCL_TraceCallF_Win32
#define YCL_TraceCallF_Win32(_fn,...)
Definition: MinGW32.h:211
platform_ex::Windows::ErrorCode
unsigned long ErrorCode
Definition: MinGW32.h:57
CHRLib::char16_t
char16_t((*c_ptr<< CHAR_BIT)|c_ptr[1])) inline PDefH(char16_t
取 c_ptr 指向的小端序双字节字符。
ystdex::unseq_apply
void unseq_apply(_func &&f, _tParams &&...args)
无序调用。
Definition: functional.hpp:240
CHRLib::d
_tDst * d
Definition: CharacterProcessing.h:139
YSLib::UI::bool
IWidget bool b bool
Definition: YControl.h:121
ystdex::size
auto size(const _tRange &c) -> decltype(c.size())
类容器访问。
Definition: range.hpp:233
ystdex::default_init
const struct ystdex::default_init_t default_init
YB_LIKELY
#define YB_LIKELY(_expr)
Definition: ydef.h:463
YSLib::IO::int
YF_API int
Definition: File.h:51
YB_ATTR_fallthrough
#define YB_ATTR_fallthrough
用于 switch 语句的 fallthrough 属性。
Definition: ydef.h:383
ystdex::string_view
basic_string_view< char > string_view
Definition: string_view.hpp:415
YSLib::Drawing::CopyLine
扫描线：按指定扫描顺序复制一行像素。
Definition: YBlit.h:443
YSLib::Drawing::ConstBitmapPtr
const Pixel * ConstBitmapPtr
Definition: YGraphics.h:44
CHRLib::p
const auto p(d)
YSLib::swap
void swap(ValueNode &x, ValueNode &y) ynothrow
Definition: ValueNode.cpp:73
YSLib::Text::String
YSLib 标准字符串（使用 UCS-2 作为内部编码）。
Definition: YString.h:46
ystdex::details::get
get())
Definition: cast.hpp:102
YSLib::UI::ImplDeDtor
ImplDeDtor(Thumb) void DecorateAsCloseButton(Thumb &tmb)
Definition: Button.cpp:125