OSDN Git Service

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