OSDN Git Service

fcbd1ed3ff7f58b82dabfd247059c946bc6117ff
[winaudioj/stedx.git] / sf_windows.cpp
1 // Direct2DBurn.cpp : アプリケーションのエントリ ポイントを定義します。\r
2 \r
3 #include "stdafx.h"\r
4 #define BOOST_ASSIGN_MAX_PARAMS 7\r
5 #include <boost/assign.hpp>\r
6 #include <boost/assign/ptr_list_of.hpp>\r
7 #include <boost/assign/ptr_list_inserter.hpp>\r
8 #include <boost/foreach.hpp>\r
9 #include "sf_windows.h"\r
10 #include "exception.h"\r
11 \r
12 #define EXCEPTION_ON_ERROR(hres) \\r
13         if (FAILED(hres)) { throw sf::win32_error_exception(hres); }\r
14 \r
15 #ifndef HINST_THISCOMPONENT\r
16 EXTERN_C IMAGE_DOS_HEADER __ImageBase;\r
17 #define HINST_THISCOMPONENT ((HINSTANCE)&__ImageBase)\r
18 #endif\r
19 \r
20 #define SAFE_RELEASE(x) if(x) x.Release(); \r
21 \r
22 namespace sf \r
23 {\r
24         LRESULT base_window::window_proc(HWND hwnd,boost::uint32_t message, WPARAM wParam, LPARAM lParam)\r
25         {\r
26                 \r
27                 LRESULT result = 0;\r
28                 switch (message)\r
29                 {\r
30                 case WM_CREATE:\r
31                         {\r
32                                 // TODO:\r
33                                 create_device();\r
34                                 break;\r
35                         }\r
36                 case WM_SIZE:\r
37                         {\r
38                                 //if (render_target_)\r
39                                 //{\r
40                                 //      D2D1_SIZE_U size;\r
41                                 //      size.width = lParam & 0xFFFF;\r
42                                 //      size.height = (lParam >> 16) & 0xFFFF; ;\r
43 \r
44                                 //      // Note: This method can fail, but it's okay to ignore the\r
45                                 //      // error here -- it will be repeated on the next call to\r
46                                 //      // EndDraw.\r
47                                 //      //render_target_->Resize(size);\r
48                                 //}\r
49                         }\r
50                 case WM_PAINT:\r
51                         {\r
52                                 //create_device();\r
53                                 \r
54                                 paint_struct begin_paint(hwnd);\r
55 \r
56                                 //if (!(render_target_->CheckWindowState() & D2D1_WINDOW_STATE_OCCLUDED))\r
57                                 //{\r
58                                 //      // Retrieve the size of the render target.\r
59                                 //      D2D1_SIZE_F renderTargetSize = render_target_->GetSize();\r
60                                 //      try {\r
61                                 //              //render_target_->BeginDraw();\r
62                                 //              base_->on_render();\r
63                                 //              //EXCEPTION_ON_ERROR(render_target_->EndDraw());\r
64                                 //      } catch (sf::win32_error_exception& e )\r
65                                 //      {\r
66                                 //              if(e.hresult() == D2DERR_RECREATE_TARGET)\r
67                                 //              {\r
68                                 //                      discard_device();\r
69                                 //              } else {\r
70                                 //                      throw;\r
71                                 //              }\r
72                                 //      }\r
73                                 //}\r
74                                 return FALSE;\r
75                         }\r
76                 case WM_DISPLAYCHANGE:\r
77                         {\r
78                                 ::InvalidateRect(hwnd, NULL, FALSE);\r
79                         }\r
80                 case WM_ERASEBKGND:\r
81                         {\r
82                                 return FALSE;\r
83                         }\r
84                 case WM_MOUSEMOVE:\r
85                         {\r
86 //                                      on_mouse_move(GET_X_LPARAM(lParam),GET_Y_LPARAM(lParam),wParam); \r
87                         }\r
88                 case WM_LBUTTONDOWN:\r
89                         {\r
90                         }\r
91                 }\r
92                 return ::DefWindowProcW(hwnd,message,wParam,lParam);\r
93         };\r
94 \r
95 \r
96         void base_window::create_device_independent_resources()\r
97         {\r
98 \r
99                 // Direct2DFactory の生成\r
100 \r
101     if(!factory_){\r
102 #if defined(DEBUG) || defined(_DEBUG)\r
103         D2D1_FACTORY_OPTIONS options;\r
104         options.debugLevel = D2D1_DEBUG_LEVEL_INFORMATION ;\r
105         EXCEPTION_ON_ERROR(D2D1CreateFactory(\r
106             D2D1_FACTORY_TYPE_SINGLE_THREADED,\r
107             options,\r
108             &factory_\r
109             ));\r
110 #else\r
111                   EXCEPTION_ON_ERROR(D2D1CreateFactory(D2D1_FACTORY_TYPE_SINGLE_THREADED, &factory_));\r
112 #endif\r
113 \r
114     }\r
115 \r
116     if(!write_factory_){\r
117                   EXCEPTION_ON_ERROR(::DWriteCreateFactory(\r
118                           DWRITE_FACTORY_TYPE_SHARED,\r
119                           __uuidof(IDWriteFactory),\r
120                           reinterpret_cast<IUnknown**>(&write_factory_)\r
121                   ));\r
122     }\r
123 \r
124 \r
125                 //wic_imaging_factory_.CreateInstance(CLSID_WICImagingFactory);\r
126 \r
127                 //thunk_proc_ = (WNDPROC)thunk_.getCode();\r
128 \r
129         };\r
130 \r
131         void base_window::register_class (\r
132                 wchar_t * menu_name,\r
133                 boost::uint32_t        style ,\r
134                 boost::int32_t     cbClsExtra,\r
135                 HICON       hIcon ,\r
136                 HCURSOR     hCursor,\r
137                 HBRUSH      hbrBackground ,\r
138                 HICON       hIconSm\r
139         )               \r
140         {\r
141                 wnd_class_.reset(new sf::window_class_ex(menu_name,name_,HINST_THISCOMPONENT,thunk_proc_,style,cbClsExtra,hIcon,hCursor,hbrBackground,hIconSm));\r
142         }\r
143 \r
144         /** デフォルト設定 */\r
145         void base_window::register_class()\r
146         {\r
147                 wnd_class_.reset(new sf::window_class_ex(0,name_,HINST_THISCOMPONENT,thunk_proc_));\r
148         }\r
149 \r
150         void base_window::create_window()\r
151         {\r
152                 // Create the application window.\r
153                 //\r
154                 // Because the CreateWindow function takes its size in pixels, we\r
155                 // obtain the system DPI and use it to scale the window size.\r
156                 FLOAT dpiX, dpiY;\r
157                 //factory_->GetDesktopDpi(&dpiX, &dpiY);\r
158 \r
159 \r
160                 // Windowを作成する\r
161                 CreateWindow(\r
162                         name_.c_str(),\r
163                         title_.c_str(),\r
164                         WS_OVERLAPPEDWINDOW,\r
165                         CW_USEDEFAULT,\r
166                         CW_USEDEFAULT,\r
167                         static_cast<boost::uint32_t>(ceil(width_ /** dpiX / 96.f*/)),\r
168                         static_cast<boost::uint32_t>(ceil(height_ /** dpiY / 96.f*/)),\r
169                         NULL,\r
170                         NULL,\r
171                         HINST_THISCOMPONENT,\r
172                         this\r
173                         );\r
174         }\r
175 \r
176         void base_window::create_device()\r
177         {\r
178 \r
179 //              input_.reset(new input(HINST_THISCOMPONENT,hwnd_));\r
180                 HRESULT hr = S_OK;\r
181 \r
182 \r
183                 //ウィンドウの現在の幅、高さを求める\r
184                 RECT rc;\r
185                 GetClientRect( hwnd_, &rc );\r
186                 boost::uint32_t width = rc.right - rc.left;\r
187                 boost::uint32_t height = rc.bottom - rc.top;\r
188 \r
189                 {\r
190                         //wic_imaging_factory_.CreateInstance(CLSID_WICImagingFactory);\r
191 //                      bitmap_ = load_bitmap_from_file(render_target_,wic_imaging_factory_,L"myship.png");\r
192                 }\r
193 \r
194                 if(!render_target_)\r
195                 {\r
196                         RECT rc;\r
197                         GetClientRect(hwnd_, &rc);\r
198 \r
199                         D2D1_SIZE_U size = D2D1::SizeU(\r
200                                 rc.right - rc.left,\r
201                                 rc.bottom - rc.top\r
202                                 );\r
203 \r
204                         EXCEPTION_ON_ERROR(factory_->CreateHwndRenderTarget(\r
205                                 D2D1::RenderTargetProperties(),\r
206                                 D2D1::HwndRenderTargetProperties(hwnd_, size,D2D1_PRESENT_OPTIONS_IMMEDIATELY),\r
207                                 &render_target_\r
208                                 ));\r
209                         // Create a DC render target \r
210                         //D2D1_RENDER_TARGET_PROPERTIES props = D2D1::RenderTargetProperties(\r
211                         //      D2D1_RENDER_TARGET_TYPE_DEFAULT,\r
212                         //      D2D1::PixelFormat(\r
213                         //              DXGI_FORMAT_B8G8R8A8_UNORM,\r
214                         //              D2D1_ALPHA_MODE_IGNORE\r
215                         //              ) , 0.0, 0.0,\r
216                         //      D2D1_RENDER_TARGET_USAGE_GDI_COMPATIBLE\r
217                         //      );\r
218 \r
219                         //EXCEPTION_ON_ERROR(factory_->CreateDCRenderTarget(\r
220                         //      &props,\r
221                         //      &render_target_\r
222                         //      ));\r
223                 }\r
224         }\r
225 \r
226 \r
227         void base_window::discard_device()\r
228         {\r
229 /*              if(render_target_)\r
230                 {\r
231                         render_target_.Release();\r
232                 }*/\r
233         }\r
234 \r
235         void base_window::show(boost::uint32_t show_flag) \r
236         {\r
237                 //HRESULT hr = S_OK;\r
238                 //BOOL enable;\r
239                 //DwmIsCompositionEnabled (&enable);\r
240                 //if(enable){\r
241                 //   //Create and populate the BlurBehind structre\r
242                 //   DWM_BLURBEHIND bb = {0};\r
243                 //   //Enable Blur Behind and Blur Region;\r
244                 //   bb.dwFlags = DWM_BB_ENABLE;\r
245                 //   bb.fEnable = true;\r
246                 //   bb.hRgnBlur = NULL;\r
247 \r
248                 //   //Enable Blur Behind\r
249                 //   hr = DwmEnableBlurBehindWindow(hwnd_, &bb);\r
250                 //}\r
251                 ::ShowWindow(hwnd_,show_flag);\r
252         }\r
253         void base_window::update() {::UpdateWindow(hwnd_);}\r
254 \r
255         base_window::~base_window()\r
256         {\r
257     safe_release(factory_);\r
258     safe_release(write_factory_);\r
259 \r
260   }\r
261 \r
262 \r
263         base_window::base_window(const std::wstring& title,const std::wstring& name,bool fit_to_display,float width,float height)\r
264                 : title_(title),name_(name),fit_to_display_(fit_to_display),\r
265                 width_(width),height_(height),thunk_(this,base_window::WndProc),hwnd_(0)\r
266         {\r
267                 thunk_proc_ = (WNDPROC)thunk_.getCode();\r
268                 //create_device_independent_resources();\r
269         }\r
270 \r
271 \r
272 \r
273         base_window::operator HWND()\r
274         {\r
275                 return hwnd_;\r
276         };\r
277 \r
278         //ID2D1FactoryPtr base_window::factory() { return impl_->factory();};\r
279         //ID2D1HwndRenderTargetPtr base_window::render_target() { return impl_->render_target();};\r
280         //IDWriteFactoryPtr base_window::write_factory() {return impl_->write_factory();};\r
281 \r
282 //  toplevel_window_ptr create_toplevel_window\r
283 //  (\r
284 //        const std::wstring& menu_name,\r
285 //        const std::wstring& name,\r
286 //        const boost::uint32_t show_flag,\r
287 //        bool fit_to_display,\r
288 //        float width,\r
289 //        float height\r
290 //        )\r
291 //  {\r
292 //        toplevel_window* p = new toplevel_window(menu_name,name,fit_to_display,width,height);\r
293 //        p->register_class();\r
294 //        p->create_window();\r
295 //        p->show(show_flag);\r
296 //        p->update();\r
297 //        return toplevel_window_ptr(p);\r
298 //  }\r
299 //\r
300 //      LRESULT toplevel_window::window_proc(HWND hwnd,boost::uint32_t message, WPARAM wParam, LPARAM lParam) \r
301 //      {\r
302 //              \r
303 //\r
304 //              switch (message)\r
305 //              {\r
306 //              case WM_CREATE:\r
307 //                      {\r
308 //                              // TODO:\r
309 //                              create_device();\r
310 //                              break;\r
311 //                      }\r
312 //              case WM_SIZE:\r
313 //                      {\r
314 //                              //if (render_target_)\r
315 //                              //{\r
316 //                              //      D2D1_SIZE_U size;\r
317 //                              //      size.width = lParam & 0xFFFF;\r
318 //                              //      size.height = (lParam >> 16) & 0xFFFF; ;\r
319 //\r
320 //                              //      // Note: This method can fail, but it's okay to ignore the\r
321 //                              //      // error here -- it will be repeated on the next call to\r
322 //                              //      // EndDraw.\r
323 //                              //      render_target_->Resize(size);\r
324 //                              //}\r
325 //                      }\r
326 //              case WM_PAINT:\r
327 //                      {\r
328 //                              //create_device();\r
329 //                              \r
330 //                              paint_struct begin_paint(hwnd);\r
331 //                              render();\r
332 //\r
333 //\r
334 //                              return FALSE;\r
335 //                      }\r
336 //              case WM_DISPLAYCHANGE:\r
337 //                      {\r
338 //                              ::InvalidateRect(hwnd, NULL, FALSE);\r
339 //                      }\r
340 //              case WM_ERASEBKGND:\r
341 //                      {\r
342 //                              return FALSE;\r
343 //                      }\r
344 //              case WM_MOUSEMOVE:\r
345 //                      {\r
346 ////                                    on_mouse_move(GET_X_LPARAM(lParam),GET_Y_LPARAM(lParam),wParam); \r
347 //                      }\r
348 //              case WM_LBUTTONDOWN:\r
349 //                      {\r
350 //                      }\r
351 //              }\r
352 //\r
353 //              if(message == WM_CLOSE)\r
354 //              {\r
355 //                      BOOL ret(::DestroyWindow(hwnd));\r
356 //                      BOOST_ASSERT(ret != 0);\r
357 //              }\r
358 //\r
359 //              if(message == WM_DESTROY)\r
360 //              {\r
361 //                      ::PostQuitMessage(0);\r
362 //                      return 0;\r
363 //              }\r
364 //\r
365 //              return ::DefWindowProcW(hwnd,message,wParam,lParam);\r
366 //      }\r
367 //\r
368 //      void toplevel_window::main_loop()\r
369 //      {\r
370 //              render();\r
371 //      }\r
372 //\r
373 //      void toplevel_window::render()\r
374 //      {\r
375 //\r
376 //              static float t = 0.0f;\r
377 //\r
378 //              if (render_target_)\r
379 //              {\r
380 //                      // Retrieve the size of the render target.\r
381 //                      D2D1_SIZE_F renderTargetSize = render_target_->GetSize();\r
382 //                      try {\r
383 //                              render_target_->BeginDraw();\r
384 //                              render_target_->Clear(D2D1::ColorF(D2D1::ColorF::White));\r
385 //                              render_target_->SetTransform(D2D1::Matrix3x2F::Identity());\r
386 //                              //render_target_->Clear(D2D1::ColorF(D2D1::ColorF::White));\r
387 //                              ID2D1SolidColorBrushPtr brush;\r
388 //                              render_target_->CreateSolidColorBrush(D2D1::ColorF(D2D1::ColorF::Black), &brush);\r
389 //                              ID2D1SolidColorBrushPtr brushr;\r
390 //                              render_target_->CreateSolidColorBrush(D2D1::ColorF(D2D1::ColorF::Red), &brushr);\r
391 //\r
392 //                              D2D1_RECT_F layoutRect = D2D1::RectF(50.f, 50.f, 600.f, 200.f);\r
393 //                              IDWriteTextFormatPtr write_text_format;\r
394 //                              // Text Formatの作成\r
395 //                              EXCEPTION_ON_ERROR(write_factory_->CreateTextFormat(\r
396 //                                      L"メイリオ",                // Font family name.\r
397 //                                      NULL,                       // Font collection (NULL sets it to use the system font collection).\r
398 //                                      DWRITE_FONT_WEIGHT_REGULAR,\r
399 //                                      DWRITE_FONT_STYLE_NORMAL,\r
400 //                                      DWRITE_FONT_STRETCH_NORMAL,\r
401 //                                      48.0f,\r
402 //                                      L"ja-jp",\r
403 //                                      &write_text_format\r
404 //                              ));\r
405 //                              // Actually draw the text at the origin.\r
406 //                              render_target_->DrawTextW(\r
407 //                                      L"こんにちは、世界!By S.F.",\r
408 //                                              wcslen(L"こんにちは、世界!By S.F."),\r
409 //                                      write_text_format,\r
410 //                                      layoutRect, \r
411 //                                      brush);\r
412 ////                            render_target_->DrawBitmap(bitmap_,D2D1::Rect<float>(40.0f,200.0f,64.0f + 40.0f,64.0f + 200.0f),1.0f,D2D1_BITMAP_INTERPOLATION_MODE_LINEAR,D2D1::Rect<float>(0.0f,0.0f,64.0f,64.0f));\r
413 //\r
414 //                              IDWriteTextFormatPtr write_text_format2;\r
415 //                              // Text Formatの作成\r
416 //                              EXCEPTION_ON_ERROR(write_factory_->CreateTextFormat(\r
417 //                                      L"メイリオ",                // Font family name.\r
418 //                                      NULL,                       // Font collection (NULL sets it to use the system font collection).\r
419 //                                      DWRITE_FONT_WEIGHT_REGULAR,\r
420 //                                      DWRITE_FONT_STYLE_NORMAL,\r
421 //                                      DWRITE_FONT_STRETCH_NORMAL,\r
422 //                                      12.0f,\r
423 //                                      L"ja-jp",\r
424 //                                      &write_text_format2\r
425 //                              ));\r
426 //                              std::wstring lbl1(L"Direct2D");\r
427 //                              render_target_->DrawTextW(lbl1.c_str(),lbl1.size(),write_text_format2,D2D1::RectF(40.0f,270.0f,64.0f+40.0f,64.0f + 270.0f),brushr);\r
428 //                              std::wstring lbl2(L"D3DX10Sprite");\r
429 //                              render_target_->DrawTextW(lbl2.c_str(),lbl2.size(),write_text_format2,D2D1::RectF(140.0f,270.0f,96.0f+140.0f,128.0f + 270.0f),brushr);\r
430 //\r
431 ////                            std::wstring lbl3(L"DirectWrite+Direct2D");\r
432 //                              render_target_->DrawTextW(lbl3.c_str(),lbl3.size(),write_text_format2,D2D1::RectF(60.0f,40.0f,280.0f,128.0f),brushr);\r
433 //\r
434 //                              std::wstring lbl4(L"Direct3D");\r
435 //                              render_target_->DrawTextW(lbl4.c_str(),lbl4.size(),write_text_format2,D2D1::RectF(280.0f,160.0f,380.0f,190.0f),brushr);\r
436 //\r
437 //                              EXCEPTION_ON_ERROR(render_target_->EndDraw());\r
438 //\r
439 //                      }  catch(...) {\r
440 //                              throw;\r
441 //                      }\r
442 //              }\r
443 //      };\r
444 \r
445 //\r
446 // Creates a Direct2D bitmap from the specified\r
447 // file name.\r
448 //\r
449 ID2D1BitmapPtr load_bitmap_from_file(\r
450     ID2D1HwndRenderTargetPtr render_target,\r
451     IWICImagingFactoryPtr wic_factory,\r
452         std::wstring uri,\r
453         boost::uint32_t destination_width,\r
454         boost::uint32_t destination_height\r
455 )\r
456 {\r
457     HRESULT hr = S_OK;\r
458 \r
459     IWICBitmapDecoderPtr decoder;\r
460     IWICBitmapFrameDecodePtr decoder_source;\r
461     IWICStreamPtr stream;\r
462     IWICFormatConverterPtr converter;\r
463     IWICBitmapScalerPtr scaler;\r
464         ID2D1BitmapPtr bitmap;\r
465 \r
466     EXCEPTION_ON_ERROR(wic_factory->CreateDecoderFromFilename(\r
467         uri.c_str(),\r
468         NULL,\r
469         GENERIC_READ,\r
470         WICDecodeMetadataCacheOnLoad,\r
471         &decoder\r
472         ));\r
473 \r
474     // Create the initial frame.\r
475     EXCEPTION_ON_ERROR(decoder->GetFrame(0, &decoder_source));\r
476   \r
477     // Convert the image format to 32bppPBGRA\r
478     // (DXGI_FORMAT_B8G8R8A8_UNORM + D2D1_ALPHA_MODE_PREMULTIPLIED).\r
479     EXCEPTION_ON_ERROR(hr = wic_factory->CreateFormatConverter(&converter));\r
480 \r
481     // If a new width or height was specified, create an\r
482     // IWICBitmapScaler and use it to resize the image.\r
483     if (destination_width != 0 || destination_height != 0)\r
484     {\r
485         boost::uint32_t originalWidth, originalHeight;\r
486         EXCEPTION_ON_ERROR(decoder_source->GetSize((UINT*)&originalWidth, (UINT*)&originalHeight));\r
487         if (destination_width == 0)\r
488         {\r
489             FLOAT scalar = static_cast<FLOAT>(destination_height) / static_cast<FLOAT>(originalHeight);\r
490             destination_width = static_cast<boost::uint32_t>(scalar * static_cast<FLOAT>(originalWidth));\r
491         }\r
492         else if (destination_height == 0)\r
493         {\r
494             FLOAT scalar = static_cast<FLOAT>(destination_width) / static_cast<FLOAT>(originalWidth);\r
495             destination_height = static_cast<boost::uint32_t>(scalar * static_cast<FLOAT>(originalHeight));\r
496         }\r
497 \r
498         EXCEPTION_ON_ERROR(wic_factory->CreateBitmapScaler(&scaler));\r
499         EXCEPTION_ON_ERROR(scaler->Initialize(\r
500                 decoder_source,\r
501                 destination_width,\r
502                 destination_height,\r
503                 WICBitmapInterpolationModeCubic\r
504                 ));\r
505         EXCEPTION_ON_ERROR(converter->Initialize(\r
506             scaler.GetInterfacePtr(),\r
507             GUID_WICPixelFormat32bppPBGRA,\r
508             WICBitmapDitherTypeNone,\r
509             NULL,\r
510             0.f,\r
511             WICBitmapPaletteTypeMedianCut\r
512             ));\r
513     }\r
514     else // Don't scale the image.\r
515     {\r
516         EXCEPTION_ON_ERROR(converter->Initialize(\r
517             decoder_source.GetInterfacePtr(),\r
518             GUID_WICPixelFormat32bppPBGRA,\r
519             WICBitmapDitherTypeNone,\r
520             NULL,\r
521             0.f,\r
522             WICBitmapPaletteTypeMedianCut\r
523             ));\r
524     }\r
525 \r
526     // Create a Direct2D bitmap from the WIC bitmap.\r
527     EXCEPTION_ON_ERROR(render_target->CreateBitmapFromWicBitmap(\r
528         converter.GetInterfacePtr(),\r
529         NULL,\r
530         &bitmap\r
531         ));\r
532 \r
533         return bitmap;\r
534 }\r
535 \r
536 \r
537 }\r
538 \r