4 // Windows Header Files:
7 #include "base_window.h"
13 #include <type_traits>
15 //#include <boost/type_traits/is_same.hpp>
17 #pragma comment(lib,"d2d1.lib")
18 #pragma comment(lib,"winmm.lib")
19 #pragma comment(lib,"dwrite.lib")
20 #pragma comment(lib,"dwmapi.lib")
27 _WRL_PTR_TYPEDEF(IDWriteFactory);
28 _WRL_PTR_TYPEDEF(IDWriteGdiInterop);
29 _WRL_PTR_TYPEDEF(IDWriteFontFace);
30 _WRL_PTR_TYPEDEF(IDWriteFont);
31 _WRL_PTR_TYPEDEF(IDWriteFontFamily);
32 _WRL_PTR_TYPEDEF(IDWriteFontCollection);
33 _WRL_PTR_TYPEDEF(IDWriteLocalizedStrings);
34 _WRL_PTR_TYPEDEF(IDWriteTextFormat);
35 _WRL_PTR_TYPEDEF(IDWriteTextLayout);
36 _WRL_PTR_TYPEDEF(IDWriteFontFile);
37 //_WRL_PTR_TYPEDEF(IDWriteFontFile);
41 _WRL_PTR_TYPEDEF(ID2D1Factory);
42 _WRL_PTR_TYPEDEF(ID2D1HwndRenderTarget);
43 _WRL_PTR_TYPEDEF(ID2D1BitmapRenderTarget);
44 _WRL_PTR_TYPEDEF(ID2D1GdiInteropRenderTarget);
45 _WRL_PTR_TYPEDEF(ID2D1DCRenderTarget);
46 _WRL_PTR_TYPEDEF(ID2D1PathGeometry);
47 _WRL_PTR_TYPEDEF(ID2D1LinearGradientBrush);
48 _WRL_PTR_TYPEDEF(ID2D1GradientStopCollection);
49 _WRL_PTR_TYPEDEF(ID2D1SolidColorBrush);
50 _WRL_PTR_TYPEDEF(ID2D1BitmapBrush);
51 _WRL_PTR_TYPEDEF(ID2D1Bitmap);
55 _WRL_PTR_TYPEDEF(IWICImagingFactory);
56 _WRL_PTR_TYPEDEF(IWICBitmapDecoder);
57 _WRL_PTR_TYPEDEF(IWICBitmapFrameDecode);
58 _WRL_PTR_TYPEDEF(IWICStream);
59 _WRL_PTR_TYPEDEF(IWICFormatConverter);
60 _WRL_PTR_TYPEDEF(IWICBitmapScaler);
61 _WRL_PTR_TYPEDEF(ITaskbarList3);
65 _WRL_PTR_TYPEDEF(IDXGISwapChain);
66 _WRL_PTR_TYPEDEF(IDXGIFactory1);
67 _WRL_PTR_TYPEDEF(IDXGIAdapter1);
68 _WRL_PTR_TYPEDEF(IDXGIDevice1);
69 _WRL_PTR_TYPEDEF(IDXGIKeyedMutex);
70 _WRL_PTR_TYPEDEF(IDXGIObject);
71 _WRL_PTR_TYPEDEF(IDXGIDeviceSubObject);
72 _WRL_PTR_TYPEDEF(IDXGISurface1);
73 _WRL_PTR_TYPEDEF(IDXGIOutput);
74 //_WRL_PTR_TYPEDEF(IDXGI);
75 //_WRL_PTR_TYPEDEF(IDXGI);
79 _WRL_PTR_TYPEDEF(ID3D11Device);
80 _WRL_PTR_TYPEDEF(ID3D11DeviceContext);
81 _WRL_PTR_TYPEDEF(ID3D11RenderTargetView);
82 _WRL_PTR_TYPEDEF(ID3D11DepthStencilView);
83 _WRL_PTR_TYPEDEF(ID3D11VertexShader);
84 _WRL_PTR_TYPEDEF(ID3D11PixelShader);
85 _WRL_PTR_TYPEDEF(ID3D11InputLayout);
86 _WRL_PTR_TYPEDEF(ID3D11Buffer);
87 _WRL_PTR_TYPEDEF(ID3D11Texture2D);
88 _WRL_PTR_TYPEDEF(ID3DBlob);
89 _WRL_PTR_TYPEDEF(ID3D11ShaderResourceView);
90 _WRL_PTR_TYPEDEF(ID3D11SamplerState);
91 _WRL_PTR_TYPEDEF(ID3D11Resource);
95 /* inline template <class Exc = win32_error_exception> void throw_if_err<>()(HRESULT hr)
97 if(hr != S_OK){throw Exc(hr);}
101 ID2D1BitmapPtr load_bitmap_from_file(
102 ID2D1HwndRenderTargetPtr render_target,
103 IWICImagingFactoryPtr wic_factory,
105 uint32_t destination_width = 0,
106 uint32_t destination_height = 0
109 /** WNDCLASSEXラッパクラス */
110 struct window_class_ex
113 const wchar_t* menu_name ,
114 const std::wstring& class_name ,
115 HINSTANCE hInstance = NULL,
116 WNDPROC lpfnWndProc = ::DefWindowProcW,
117 uint32_t style = CS_HREDRAW | CS_VREDRAW,
118 int32_t cbClsExtra = 0,
119 int32_t cbWndExtra = sizeof(LONG_PTR),
120 HICON hIcon = ::LoadIcon(NULL,IDI_APPLICATION),
121 HCURSOR hCursor = ::LoadCursor(NULL, IDC_ARROW),
122 HBRUSH hbrBackground = ::CreateSolidBrush(0xff000000),
124 ) : is_register_(false)
127 if(::GetClassInfoExW(hInstance,class_name.c_str(),&wndclass_) == 0)
129 if(::GetLastError() == ERROR_CLASS_DOES_NOT_EXIST)
131 ::ZeroMemory(&wndclass_,sizeof(wndclass_));
132 wndclass_.lpszMenuName = (LPCWSTR)menu_name;
133 wndclass_.lpszClassName = class_name.c_str();
134 wndclass_.cbSize = sizeof(::WNDCLASSEXW);
135 wndclass_.cbWndExtra = cbWndExtra;
136 wndclass_.hInstance = hInstance;
137 wndclass_.lpfnWndProc = lpfnWndProc;
138 wndclass_.style = style;
139 wndclass_.cbClsExtra = cbClsExtra;
140 wndclass_.hIcon = hIcon;
141 wndclass_.hCursor = hCursor;
142 wndclass_.hbrBackground = hbrBackground;
143 wndclass_.hIconSm = hIconSm;
144 atom_ = ::RegisterClassExW(&wndclass_) ;
145 BOOST_ASSERT(atom_ != 0);
148 throw win32_error_exception();
151 is_register_ = false;
158 ::UnregisterClassW(wndclass_.lpszClassName,wndclass_.hInstance);
165 ::WNDCLASSEXW wndclass_;
169 get_dc(HWND hwnd) : hwnd_(hwnd),hdc_(GetDC(hwnd)) {}
170 HDC get(){return hdc_;}
171 ~get_dc(){::ReleaseDC(hwnd_,hdc_);}
177 struct get_window_dc {
178 get_window_dc(HWND hwnd) : hwnd_(hwnd),hdc_(GetWindowDC(hwnd)) {}
179 HDC get(){return hdc_;}
180 ~get_window_dc(){::ReleaseDC(hwnd_,hdc_);}
186 struct compatible_dc {
187 compatible_dc(HDC hdc) : hdc_(::CreateCompatibleDC(hdc)){};
188 ~compatible_dc(){::DeleteDC(hdc_);};
189 HDC get() { return hdc_;};
195 ref_dc(HDC& hdc) : hdc_(hdc) {};
197 HDC get() { return hdc_;};
203 d2_dc(ID2D1GdiInteropRenderTargetPtr& ptr,D2D1_DC_INITIALIZE_MODE mode) :hdc_(0),ptr_(ptr)
205 hr_ = ptr->GetDC(mode,&hdc_);
207 ~d2_dc(){ptr_->ReleaseDC(NULL);};
208 HDC get() { return hdc_;};
212 ID2D1GdiInteropRenderTargetPtr& ptr_;
215 template <typename Holder>
216 struct device_context
218 explicit device_context(Holder* holder) : holder_(holder){};
220 operator HDC(){return holder_->get();}
222 std::unique_ptr<Holder> holder_;
225 //struct handle_holder : boost::noncopyable
227 // explicit handle_holder(HANDLE handle) : handle_(handle) {};
228 // ~handle_holder(){if(handle_) ::CloseHandle(handle_);}
229 // operator HANDLE(){return handle_;}
235 struct HBITMAP_deleter {
236 typedef HBITMAP pointer;
237 void operator ()(HBITMAP handle) {
239 ::DeleteObject(handle);
244 //template <typename Handle,typename Handle_Deleter>
245 //struct handle_holder {
246 // typedef boost::unique_ptr<Handle,Handle_Deleter> holder_type;
247 // handle_holder(Handle handle) : holder_(handle) {}
248 // operator Handle(){return holder_->get();}
250 // holder_type holder_;
253 typedef std::unique_ptr<HBITMAP,HBITMAP_deleter> bitmap_holder;
255 typedef device_context<d2_dc> d2_dc_type;
259 paint_struct(HWND hwnd) : hwnd_(hwnd)
261 ::BeginPaint(hwnd,&paintstruct_);
263 ~paint_struct() {::EndPaint(hwnd_,&paintstruct_);}
264 PAINTSTRUCT* operator->(){return &paintstruct_;}
267 PAINTSTRUCT paintstruct_;
270 // GDI オブジェクト管理テンプレート
271 template <class GdiObject>
272 struct gdi_object: boost::noncopyable
274 explicit gdi_object(GdiObject obj) : gdiobj_(obj) {}
275 ~gdi_object(){::DeleteObject(gdiobj_);}
276 operator GdiObject(){return gdiobj_;}
284 select_object(HDC dc,HGDIOBJ o) : dc_(dc),o_(::SelectObject(dc,o)) {}
285 ~select_object(){::SelectObject(dc_,o_);}
291 // Direct2D BeginDrawヘルパ関数
292 template <typename T >
295 typedef std::function<void(HRESULT hr)> err_handler_type;
297 begin_draw(T& render_target,err_handler_type& handler = err_handler_type([](HRESULT hr)->void{throw sf::win32_error_exception(hr);}))
298 : render_target_(render_target) ,
300 {render_target->BeginDraw();}
304 hr = render_target_->EndDraw();
312 err_handler_type handler_;
317 mouse() : x_(0.0f),y_(0.0f),left_button_(false),middle_button_(false),right_button_(false){}
320 bool left_button_,middle_button_,right_button_;
324 // ウィンドウプロシージャの識別用クラス
327 typedef WNDPROC proc_type;
328 typedef LRESULT return_type;
329 static inline return_type def_wnd_proc(HWND hwnd,uint32_t message, WPARAM wParam, LPARAM lParam)
331 return ::DefWindowProcW(hwnd,message,wParam,lParam);
335 // ダイアログプロシージャの識別用クラス
338 typedef DLGPROC proc_type;
339 typedef INT_PTR return_type;
340 static inline return_type def_wnd_proc(HWND hwnd,uint32_t message, WPARAM wParam, LPARAM lParam)
347 template <typename ProcType = wndproc>
348 struct base_win32_window : public base_window
350 typedef ProcType proc_t;
351 typedef typename proc_t::return_type result_t;
352 // typedef proc_t::return_type result_t;
354 operator HWND() const {return hwnd_;};
356 virtual void * raw_handle() const {return hwnd_;};
357 // virtual void show(uint32_t show_flag);
359 virtual void show() {
360 ::ShowWindow(hwnd_,SW_SHOW);
361 ::GetWindowPlacement(hwnd_,&wp_);
365 virtual bool is_show() {
366 return ( wp_.showCmd == SW_SHOWMAXIMIZED
367 || wp_.showCmd == SW_SHOWMINIMIZED
368 || wp_.showCmd == SW_SHOWNORMAL );
374 ::ShowWindow(hwnd_,SW_HIDE);
375 ::GetWindowPlacement(hwnd_,&wp_);
378 virtual void text(std::wstring& text)
380 ::SetWindowTextW(*this,text.c_str());
383 virtual void send_message(uint32_t message,uint32_t wparam,uint32_t lparam )
385 ::SendNotifyMessage(hwnd_,message,wparam,lparam);
388 virtual void post_message(uint32_t message,uint32_t wparam,uint32_t lparam )
390 ::PostMessage(hwnd_,message,wparam,lparam);
393 virtual void message_box(const std::wstring& text,const std::wstring& caption,uint32_t type = MB_OK)
395 ::MessageBox(hwnd_,text.c_str(),caption.c_str(),type);
398 virtual void update();
400 virtual void create_device_independent_resources();
401 virtual void create_device();
402 virtual void create_swapchain_dependent_resources();
404 virtual void discard_swapchain_dependent_resources();
405 virtual void discard_device();
406 virtual void discard_device_independant_resources();
411 const std::wstring& title,
412 const std::wstring& name,bool fit_to_display,
413 float width,float height);
416 ~base_win32_window();
418 void register_class (
419 const wchar_t* menu_name,
421 int32_t cbClsExtra = 0,
422 int32_t cbWndExtra = sizeof(LONG_PTR),
423 HICON hIcon = ::LoadIcon(NULL,IDI_APPLICATION),
424 HCURSOR hCursor = ::LoadCursor(NULL, IDC_ARROW),
425 HBRUSH hbrBackground = ::CreateSolidBrush(0xff000000),
430 void register_class();
431 void create_window(HWND parent = NULL);
433 void calc_client_size()
435 //クライアント領域の現在の幅、高さを求める
437 GetClientRect( hwnd_, &rc );
438 client_width_ = rc.right - rc.left;
439 client_height_ = rc.bottom - rc.top;
443 void set_long(int index,long data)
446 if(::SetWindowLongW(hwnd_,index,data) == 0)
449 if( (err = GetLastError()) != 0){
451 throw sf::win32_error_exception();
457 HWND hwnd_insert_after, // 配置順序のハンドル
462 UINT flags // ウィンドウ位置のオプション
465 BOOL res = SetWindowPos(hwnd_,hwnd_insert_after,x,y,cx,cy,flags);
468 throw win32_error_exception();
472 bool invalidate_rect(bool erase = false,const RECT * rect_ptr = 0)
474 return ::InvalidateRect(*this,rect_ptr,erase) == TRUE;
477 void enable_control(uint32_t id,bool enable)
479 ::EnableWindow(GetDlgItem(hwnd_,id),enable?TRUE:FALSE);
482 void enable_control(HWND hwnd,uint32_t id,bool enable)
484 ::EnableWindow(GetDlgItem(hwnd,id),enable?TRUE:FALSE);
487 virtual result_t window_proc(HWND hwnd,uint32_t message, WPARAM wParam, LPARAM lParam);
488 virtual result_t other_window_proc(HWND hwnd,uint32_t message, WPARAM wParam, LPARAM lParam)
490 return proc_t::def_wnd_proc(hwnd,message,wParam,lParam);
493 // デフォルトウィンドウメッセージハンドラ
494 virtual result_t on_nccreate(CREATESTRUCT *p) ;//{ return std::is_same<proc_t,wndproc>::value?1:FALSE;}
495 virtual result_t on_create(CREATESTRUCT *p); //{ return std::is_same<proc_t,wndproc>::value?0:FALSE;}
496 virtual result_t on_init_dialog(HWND default_focus_ctrl,LPARAM data) {return TRUE;}
497 virtual result_t on_size(uint32_t flag,uint32_t width,uint32_t height);//{return std::is_same<proc_t,wndproc>::value?0:FALSE; }
499 virtual result_t on_paint();
500 virtual result_t on_display_change(uint32_t bpp,uint32_t h_resolution,uint32_t v_resolution) { invalidate_rect();return std::is_same<proc_t,wndproc>::value?0:FALSE;}
501 virtual result_t on_erase_backgroud(HDC dc) {return std::is_same<proc_t,wndproc>::value?1:TRUE;}
502 virtual result_t on_hscroll(uint32_t state,uint32_t position,HWND ctrl_hwnd) {return std::is_same<proc_t,wndproc>::value?0:FALSE;}
503 virtual result_t on_vscroll(uint32_t state,uint32_t position,HWND ctrl_hwnd) {return std::is_same<proc_t,wndproc>::value?0:FALSE;}
504 virtual result_t on_left_mouse_button_down(uint32_t mouse_key,int x,int y ) { return std::is_same<proc_t,wndproc>::value?0:FALSE; }
505 virtual result_t on_left_mouse_button_up(uint32_t mouse_key,int x,int y) { return std::is_same<proc_t,wndproc>::value?0:FALSE; }
506 virtual result_t on_left_mouse_button_double_click(uint32_t mouse_key,int x,int y) { return std::is_same<proc_t,wndproc>::value?0:FALSE; }
507 virtual result_t on_mouse_move(uint32_t mouse_key,int x,int y) {return std::is_same<proc_t,wndproc>::value?0:FALSE; }
508 virtual result_t on_mouse_wheel(uint32_t mouse_key,int delta,int x,int y) { return std::is_same<proc_t,wndproc>::value?0:FALSE; }
509 //virtual bool on_mouse_enter(uint32_t mouse_key,int x,int y) { return false; }
510 virtual result_t on_mouse_leave() { return std::is_same<proc_t,wndproc>::value?0:FALSE; }
511 virtual result_t on_destroy(){
512 //::PostQuitMessage(0);
513 return std::is_same<proc_t,wndproc>::value?0:FALSE;
516 virtual result_t on_close()
520 BOOL ret(::DestroyWindow(hwnd_));
521 BOOST_ASSERT(ret != 0);
523 return std::is_same<proc_t,wndproc>::value?1:TRUE;
526 virtual result_t on_set_cursor() { return std::is_same<proc_t,wndproc>::value?0:FALSE; }
527 virtual result_t on_key_down(uint32_t vkey,uint32_t ext_key,uint32_t repeat) { return std::is_same<proc_t,wndproc>::value?0:FALSE; }
528 virtual result_t on_key_up(uint32_t vkey,uint32_t ext_key,uint32_t repeat) { return std::is_same<proc_t,wndproc>::value?0:FALSE; }
529 virtual result_t on_app_command(uint32_t command,uint32_t device,uint32_t keystate) {return std::is_same<proc_t,wndproc>::value?0:FALSE;}
530 virtual result_t on_command(uint32_t wparam, uint32_t lparam) { return std::is_same<proc_t,wndproc>::value?0:FALSE; }
531 virtual result_t on_timer(uint32_t timer_id) {
532 //::InvalidateRect(hwnd_,NULL,FALSE);
534 return std::is_same<proc_t,wndproc>::value?0:FALSE;
536 virtual result_t on_notify(NMHDR* nmhdr) { return std::is_same<proc_t,wndproc>::value?0:FALSE; }
537 virtual result_t on_dwm_composition_changed();
538 virtual void render();
540 void get_dxgi_information();
543 // WM_NCCREATEメッセージの時にthunkに切り替える
544 static result_t CALLBACK start_wnd_proc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
546 if(message == WM_NCCREATE)
548 LPCREATESTRUCT param = reinterpret_cast<LPCREATESTRUCT>(lParam);
549 base_win32_window* ptr = reinterpret_cast<base_win32_window*>(param->lpCreateParams);
551 // ウィンドウプロシージャをインスタンスと結び付けるthunkプロシージャに入れ替える
552 LONG_PTR r = SetWindowLongPtr(hwnd,GWLP_WNDPROC,reinterpret_cast<LONG_PTR>(ptr->thunk_proc_));
553 assert(r == reinterpret_cast<LONG_PTR>(&start_wnd_proc));
554 return ptr->window_proc(hwnd,message,wParam,lParam);
556 return ::DefWindowProcW(hwnd,message,wParam,lParam);
559 static result_t CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
561 base_win32_window* ptr = reinterpret_cast<base_win32_window*>(hwnd);
562 return ptr->window_proc(ptr->hwnd_,message,wParam,lParam);
565 // thisとhwndをつなぐthunkクラス
566 struct hwnd_this_thunk : public Xbyak::CodeGenerator {
567 hwnd_this_thunk(base_win32_window* impl,typename proc_t::proc_type proc)
569 // rcxにhwndが格納されているので、それをimpl->hwndに保存
570 // mov(ptr[&(impl->hwnd_)],rcx); // <-- エラー発生部分
571 mov(rax,(size_t)&impl->hwnd_); // <-- 訂正
572 mov(ptr[rax],rcx); // <-- 訂正
573 // 代わりにthisのアドレスをrcxに格納
574 mov(rcx,(LONG_PTR)impl);
575 // r10にproc(Window プロシージャ)へのアドレスを格納
576 mov(r10,(LONG_PTR)proc);
577 // Window プロシージャへへジャンプ
582 void update_window_size()
585 GetWindowRect(hwnd_,&r);
586 width_ = r.right - r.left;
587 height_ = r.bottom - r.top;
590 void init_view_matrix();
593 hwnd_this_thunk thunk_;
596 float width_,height_;
597 bool fit_to_display_;
598 std::shared_ptr<sf::window_class_ex> wnd_class_;
599 typename proc_t::proc_type thunk_proc_;
604 ID2D1FactoryPtr factory_;
605 ID2D1HwndRenderTargetPtr render_target_;
606 IDWriteFactoryPtr write_factory_;
607 IWICImagingFactoryPtr wic_imaging_factory_;
608 IDWriteTextFormatPtr write_text_format_;
610 IDXGIFactory1Ptr dxgi_factory_;
611 IDXGIAdapter1Ptr adapter_;
612 IDXGIOutputPtr output_;
613 ID3D11DevicePtr d3d_device_;
614 ID3D11DeviceContextPtr d3d_context_;
615 ID3D11Texture2DPtr texture_;
616 ID3D11RenderTargetViewPtr view_;
617 ID3D11Texture2DPtr depth_texture_;
618 ID3D11DepthStencilViewPtr depth_view_;
619 ID3D11VertexShaderPtr v_shader_;
620 ID3D11InputLayoutPtr input_layout_;
621 ID3D11PixelShaderPtr p_shader_;
622 ID3D11BufferPtr v_buffer_;
623 ID3D11BufferPtr i_buffer_;
624 ID3D11BufferPtr cb_never_changes_;
625 ID3D11BufferPtr cb_change_on_resize_;
626 ID3D11BufferPtr cb_changes_every_frame_;
627 ID3D11ShaderResourceViewPtr shader_res_view_;
628 ID3D11SamplerStatePtr sampler_state_;
629 ID3D11Texture2DPtr back_buffer_;
631 ID3D11SamplerStatePtr cube_sampler_state_;
632 ID3D11Texture2DPtr cube_texture_;
633 ID3D11Texture2DPtr cube_depth_texture_;
634 ID3D11ShaderResourceViewPtr cube_shader_res_view_;
635 ID3D11RenderTargetViewPtr cube_view_;
636 ID3D11DepthStencilViewPtr cube_depth_view_;
638 DXGI_MODE_DESC actual_desc_;
639 IDXGISwapChainPtr swap_chain_;
640 std::wstring dxgi_info_;
644 DirectX::XMMATRIX mat_world_;
645 DirectX::XMMATRIX mat_view_;
646 DirectX::XMMATRIX mat_projection_;
647 DirectX::XMMATRIX cube_mat_projection_;
649 DirectX::XMFLOAT4 mesh_color_;
650 float client_width_,client_height_;
654 // __declspec ( thread ) static std::queue<proc_t::proc_type> ptrs_ ;// thread local storage
658 typedef base_win32_window<> base_win32_window_t;
659 typedef base_win32_window<dlgproc> base_win32_dialog_t;
662 struct subclass_window : public base_win32_window_t
664 subclass_window(HWND hwnd);
666 void attach(HWND hwnd);
669 virtual result_t window_proc(HWND hwnd,uint32_t message, WPARAM wParam, LPARAM lParam)
671 return CallWindowProc(proc_backup_,hwnd,message,wParam,lParam);
675 WNDPROC proc_backup_;
678 struct av_mm_thread_characteristics
680 av_mm_thread_characteristics(std::wstring& str) : task_name_(str)
682 handle_ = ::AvSetMmThreadCharacteristicsW(str.c_str(),(LPDWORD)&task_index_);
685 bool set_priority(AVRT_PRIORITY p){return (::AvSetMmThreadPriority(handle_,p) == TRUE);}
687 ~av_mm_thread_characteristics()
689 ::AvRevertMmThreadCharacteristics(handle_);
693 std::wstring task_name_;
694 uint32_t task_index_;
704 typedef sf::begin_draw<ID2D1BitmapRenderTargetPtr> begin_draw_bitmap;
705 typedef sf::begin_draw<ID2D1HwndRenderTargetPtr> begin_draw_hwnd;