OSDN Git Service

Windows APIを実装部に隠蔽してみた。まだ不完全だが。
[wintimer/wintimer.git] / wintimer / sf_windows.h
1 #pragma once
2 /*
3 */
4 // Windows Header Files:
5 #include "exception.h"
6 #include "base_window.h"
7 #define XBYAK64
8 #include "xbyak.h"
9 // DLLのリンク
10 #pragma comment(lib,"d2d1.lib")
11 #pragma comment(lib,"winmm.lib")
12 #pragma comment(lib,"dwrite.lib")
13 #pragma comment(lib,"dwmapi.lib")
14
15 //#include "input.h"
16
17 _COM_SMARTPTR_TYPEDEF(ID2D1Factory,__uuidof(ID2D1Factory));
18 _COM_SMARTPTR_TYPEDEF(IWICImagingFactory, __uuidof(IWICImagingFactory));
19 _COM_SMARTPTR_TYPEDEF(IDWriteFactory , __uuidof(IDWriteFactory));
20 _COM_SMARTPTR_TYPEDEF(IDWriteGdiInterop , __uuidof(IDWriteGdiInterop));
21 _COM_SMARTPTR_TYPEDEF(IDWriteFontFace , __uuidof(IDWriteFontFace));
22 _COM_SMARTPTR_TYPEDEF(IDWriteFont , __uuidof(IDWriteFont));
23 _COM_SMARTPTR_TYPEDEF(IDWriteFontFamily , __uuidof(IDWriteFontFamily));
24 _COM_SMARTPTR_TYPEDEF(IDWriteFontCollection , __uuidof(IDWriteFontCollection));
25 _COM_SMARTPTR_TYPEDEF(IDWriteLocalizedStrings , __uuidof(IDWriteLocalizedStrings));
26 _COM_SMARTPTR_TYPEDEF(ID2D1HwndRenderTarget , __uuidof(ID2D1HwndRenderTarget));
27 _COM_SMARTPTR_TYPEDEF(ID2D1BitmapRenderTarget , __uuidof(ID2D1BitmapRenderTarget));
28 _COM_SMARTPTR_TYPEDEF(ID2D1GdiInteropRenderTarget , __uuidof(ID2D1GdiInteropRenderTarget));
29 _COM_SMARTPTR_TYPEDEF(IDWriteTextFormat, __uuidof(IDWriteTextFormat));
30 _COM_SMARTPTR_TYPEDEF(IDWriteTextLayout, __uuidof(IDWriteTextLayout));
31 _COM_SMARTPTR_TYPEDEF(ID2D1PathGeometry , __uuidof(ID2D1PathGeometry));
32 _COM_SMARTPTR_TYPEDEF(ID2D1LinearGradientBrush , __uuidof(ID2D1LinearGradientBrush));
33 _COM_SMARTPTR_TYPEDEF(ID2D1GradientStopCollection , __uuidof(ID2D1GradientStopCollection));
34 _COM_SMARTPTR_TYPEDEF(ID2D1SolidColorBrush , __uuidof(ID2D1SolidColorBrush));
35 _COM_SMARTPTR_TYPEDEF(ID2D1BitmapBrush , __uuidof(ID2D1BitmapBrush));
36 _COM_SMARTPTR_TYPEDEF(ID2D1Bitmap , __uuidof(ID2D1Bitmap));
37 _COM_SMARTPTR_TYPEDEF(IWICBitmapDecoder,__uuidof(IWICBitmapDecoder));
38 _COM_SMARTPTR_TYPEDEF(IWICBitmapFrameDecode,__uuidof(IWICBitmapFrameDecode));
39 _COM_SMARTPTR_TYPEDEF(IWICStream,__uuidof(IWICStream));
40 _COM_SMARTPTR_TYPEDEF(IWICFormatConverter,__uuidof(IWICFormatConverter));
41 _COM_SMARTPTR_TYPEDEF(IWICBitmapScaler,__uuidof(IWICBitmapScaler));
42 _COM_SMARTPTR_TYPEDEF(ITaskbarList3,__uuidof(ITaskbarList3));
43
44 template <class COM_SMART_PTR > inline void safe_release(COM_SMART_PTR& ptr)
45 {
46   if(ptr)
47   {
48     ptr.Release();
49   }
50 };
51
52 namespace sf{
53
54   template <class Exc> struct throw_if_err
55   {
56     void operator()(HRESULT hr) {if(hr != S_OK){throw Exc(hr);}}
57   };
58
59
60   ID2D1BitmapPtr load_bitmap_from_file(
61     ID2D1HwndRenderTargetPtr render_target,
62     IWICImagingFactoryPtr wic_factory,
63     std::wstring uri,
64     boost::uint32_t destination_width = 0,
65     boost::uint32_t destination_height = 0
66     );
67
68   /** WNDCLASSEXラッパクラス */
69   struct window_class_ex
70   {
71     window_class_ex(
72       const wchar_t*  menu_name ,
73       const std::wstring&  class_name ,
74       HINSTANCE   hInstance = NULL,
75       WNDPROC     lpfnWndProc = ::DefWindowProcW,
76       boost::uint32_t        style = CS_HREDRAW | CS_VREDRAW,
77       boost::int32_t     cbClsExtra  = 0,
78       HICON       hIcon = ::LoadIcon(NULL,IDI_APPLICATION),
79       HCURSOR     hCursor = ::LoadCursor(NULL, IDC_ARROW),
80       HBRUSH      hbrBackground = ::CreateSolidBrush(0xff000000),
81       HICON       hIconSm = NULL
82       ) : is_register_(false)
83     {
84
85       if(::GetClassInfoExW(hInstance,class_name.c_str(),&wndclass_) == 0)
86       {
87         if(::GetLastError() == ERROR_CLASS_DOES_NOT_EXIST)
88         { 
89           ::ZeroMemory(&wndclass_,sizeof(wndclass_));
90           wndclass_.lpszMenuName = (LPCWSTR)menu_name;
91           wndclass_.lpszClassName = class_name.c_str();
92           wndclass_.cbSize = sizeof(::WNDCLASSEXW);
93           wndclass_.cbWndExtra = sizeof(LONG_PTR);
94           wndclass_.hInstance = hInstance;
95           wndclass_.lpfnWndProc = lpfnWndProc;
96           wndclass_.style = style;
97           wndclass_.cbClsExtra = cbClsExtra;
98           wndclass_.hIcon = hIcon;
99           wndclass_.hCursor = hCursor;
100           wndclass_.hbrBackground = hbrBackground;
101           wndclass_.hIconSm = hIconSm;
102           atom_ = ::RegisterClassExW(&wndclass_) ;
103           BOOST_ASSERT(atom_ != 0);
104           is_register_ = true;
105         } else {
106           throw win32_error_exception();
107         }
108       } else {
109         is_register_ = false;
110       }
111     };
112
113     ~window_class_ex()
114     {
115       if(is_register_){
116         ::UnregisterClassW(wndclass_.lpszClassName,wndclass_.hInstance);
117       }
118     }
119
120   private:
121     bool is_register_;
122     ATOM atom_;
123     ::WNDCLASSEXW wndclass_;
124   };
125
126
127
128   struct get_dc {
129     get_dc(HWND hwnd) : hwnd_(hwnd),hdc_(GetDC(hwnd)) {}
130     HDC get(){return hdc_;}
131     ~get_dc(){::ReleaseDC(hwnd_,hdc_);}
132   private:
133     HDC hdc_;
134     HWND hwnd_;
135   };
136
137   struct compatible_dc {
138     compatible_dc(HDC hdc) : hdc_(::CreateCompatibleDC(hdc)){}; 
139     ~compatible_dc(){::DeleteDC(hdc_);};
140     HDC get() { return hdc_;};
141   private:
142     HDC hdc_;
143   };
144
145   struct ref_dc {
146     ref_dc(HDC& hdc) : hdc_(hdc) {};
147     ~ref_dc(){};
148     HDC get() { return hdc_;};
149   private:
150     HDC& hdc_;
151   };
152
153   struct d2_dc {
154     d2_dc(ID2D1GdiInteropRenderTargetPtr& ptr,D2D1_DC_INITIALIZE_MODE mode) :hdc_(0),ptr_(ptr)
155     {
156       hr_ = ptr->GetDC(mode,&hdc_);
157     };
158     ~d2_dc(){ptr_->ReleaseDC(NULL);};
159     HDC get() { return hdc_;};
160   private:
161     HRESULT hr_;
162     HDC hdc_;
163     ID2D1GdiInteropRenderTargetPtr& ptr_;
164   };
165
166   template <typename Holder>
167   struct device_context
168   {
169     explicit device_context(Holder* holder) : holder_(holder){};
170     ~device_context() {}
171     operator HDC(){return holder_->get();}
172   private:
173     boost::scoped_ptr<Holder> holder_;
174   };
175
176   struct handle_holder : boost::noncopyable
177   {
178     explicit handle_holder(HANDLE handle) : handle_(handle) {};
179     ~handle_holder(){if(handle_) ::CloseHandle(handle_);}
180     operator HANDLE(){return handle_;}
181   private:
182     HANDLE handle_;
183   };
184
185   typedef device_context<d2_dc> d2_dc_type;
186
187   struct paint_struct 
188   {
189     paint_struct(HWND hwnd) : hwnd_(hwnd)
190     {
191       ::BeginPaint(hwnd,&paintstruct_);
192     }
193     ~paint_struct() {::EndPaint(hwnd_,&paintstruct_);}
194     PAINTSTRUCT* operator->(){return &paintstruct_;}
195   private:
196     HWND hwnd_;
197     PAINTSTRUCT paintstruct_;
198   };
199
200   // GDI オブジェクト管理テンプレート
201   template <class GdiObject> 
202     struct gdi_object: boost::noncopyable
203   {
204     explicit gdi_object(GdiObject obj) : gdiobj_(obj) {}
205     ~gdi_object(){::DeleteObject(gdiobj_);}
206     operator GdiObject(){return gdiobj_;}
207   private:
208     GdiObject gdiobj_;
209   };
210
211   
212   // Direct2D BeginDrawヘルパ関数
213   template <typename T >
214   struct begin_draw
215   {
216     typedef std::function<void(HRESULT hr)> err_handler_type;
217
218     begin_draw(T& render_target,err_handler_type& handler)
219       : render_target_(render_target) ,
220         is_end_(false),handler_(handler)
221     {render_target->BeginDraw();}
222
223     ~begin_draw(){ 
224       HRESULT hr = S_OK;
225       hr = render_target_->EndDraw();
226       if( hr != S_OK)
227       {
228         handler_(hr);
229       }
230     }
231   private:
232     T& render_target_;
233     err_handler_type handler_;
234   };
235
236   struct mouse
237   {
238     mouse() : x_(0.0f),y_(0.0f),left_button_(false),middle_button_(false),right_button_(false){}
239   private:
240     float x_,y_;
241     bool left_button_,middle_button_,right_button_;
242   };
243
244
245   /** window ベースクラス */
246   struct base_win32_window : public base_window 
247   {
248     typedef boost::signals2::signal<LRESULT (HWND,boost::uint32_t,WPARAM, LPARAM) > on_message_type;
249     on_message_type on_message;
250     
251     operator HWND() {return hwnd_;};
252     
253     virtual void * raw_handle(){return hwnd_;};
254     virtual void show(boost::uint32_t show_flag);
255     virtual void text(std::wstring& text)
256     {
257       ::SetWindowTextW(*this,text.c_str());
258     };
259
260     virtual void update();
261
262   protected:
263     
264     base_win32_window(
265       const std::wstring& title,
266       const std::wstring& name,bool fit_to_display,
267       float width,float height);
268     
269     ~base_win32_window();
270
271     void register_class (
272       wchar_t* menu_name,
273       boost::uint32_t style, 
274       boost::int32_t     cbClsExtra  = 0,
275       HICON       hIcon = ::LoadIcon(NULL,IDI_APPLICATION),
276       HCURSOR     hCursor = ::LoadCursor(NULL, IDC_ARROW),
277       HBRUSH      hbrBackground = ::CreateSolidBrush(0xff000000),
278       HICON       hIconSm = NULL
279       );                
280
281     /** デフォルト設定 */
282     void register_class();
283     void create_window();
284
285     // SetWindowLong API
286     void set_long(int index,long data)
287     {
288       SetLastError(0);
289       if(::SetWindowLongW(hwnd_,index,data) == 0)
290       {
291         long err = 0;
292         if( (err = GetLastError()) != 0){
293           SetLastError(err);
294           throw sf::win32_error_exception();
295         }
296       };
297     }
298
299     bool invalidate_rect(bool erase = false,const RECT * rect_ptr = 0)
300     {
301       return ::InvalidateRect(*this,rect_ptr,erase) == TRUE;
302     }
303
304   public:
305     virtual LRESULT window_proc(HWND hwnd,boost::uint32_t message, WPARAM wParam, LPARAM lParam);
306   protected:
307     static LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
308     {
309       base_win32_window* ptr = reinterpret_cast<base_win32_window*>(hwnd);
310       hwnd = ptr->hwnd_;
311       return ptr->window_proc(hwnd,message,wParam,lParam);
312     };
313
314     // thisとhwndをつなぐthunkクラス
315     struct hwnd_this_thunk : public Xbyak::CodeGenerator {
316       hwnd_this_thunk(base_win32_window* impl,WNDPROC proc)
317       {
318         // rcxにhwndが格納されているので、それをimpl->hwndに保存
319         mov(qword[&(impl->hwnd_)],rcx);
320         // 代わりにthisのアドレスをrcxに格納
321         mov(rcx,(LONG_PTR)impl);
322         // r10にproc(Window プロシージャ)へのアドレスを格納
323         mov(r10,(LONG_PTR)proc);
324         // Window プロシージャへへジャンプ
325         jmp(r10);
326       }
327     };
328
329     HWND hwnd_;
330     hwnd_this_thunk thunk_;
331     std::wstring title_;
332     std::wstring name_;
333     float width_,height_;
334     bool fit_to_display_;
335     boost::shared_ptr<sf::window_class_ex> wnd_class_;
336     WNDPROC thunk_proc_;
337   };
338   
339   struct av_mm_thread_characteristics
340   {
341     av_mm_thread_characteristics(std::wstring& str) : task_name_(str)
342     {
343       handle_ = ::AvSetMmThreadCharacteristicsW(str.c_str(),(LPDWORD)&task_index_);
344     }
345
346     bool set_priority(AVRT_PRIORITY p){return (::AvSetMmThreadPriority(handle_,p) == TRUE);}
347
348     ~av_mm_thread_characteristics()
349     {
350       ::AvRevertMmThreadCharacteristics(handle_);
351     }
352
353   private:
354     std::wstring task_name_;
355     boost::uint32_t task_index_;
356     HANDLE handle_;
357     std::wstring title_;
358     std::wstring name_;
359     float width_,height_;
360     bool fit_to_display_;
361
362   };
363
364   struct widget
365   {
366     void draw();
367     float x_,y_;
368   };
369
370   typedef sf::begin_draw<ID2D1BitmapRenderTargetPtr> begin_draw_bitmap;
371   typedef sf::begin_draw<ID2D1HwndRenderTargetPtr> begin_draw_hwnd;
372
373 }