OSDN Git Service

Windows APIを実装部に隠蔽してみた。まだ不完全だが。
[wintimer/wintimer.git] / wintimer / toplevel_window.cpp
index c1939a5..51adbe0 100644 (file)
@@ -5,6 +5,7 @@
 #include <boost/assign/ptr_list_inserter.hpp>
 #include <boost/foreach.hpp>
 #include "toplevel_window.h"
+#include "sf_windows.h"
 #include "exception.h"
 
 #define THROW_IFERR(hres) \
@@ -17,157 +18,42 @@ EXTERN_C IMAGE_DOS_HEADER __ImageBase;
 
 namespace sf 
 {
-  //ID2D1FactoryPtr base_window::factory() { return impl_->factory();};
-  //ID2D1HwndRenderTargetPtr base_window::render_target() { return impl_->render_target();};
-  //IDWriteFactoryPtr base_window::write_factory() {return impl_->write_factory();};
 
+HRESULT EnableBlurBehind(HWND hwnd)
+{
+  HRESULT hr = S_OK;
+
+  //Create and populate the BlurBehind structre
+  DWM_BLURBEHIND bb = {0};
+  //Enable Blur Behind and Blur Region;
+  bb.dwFlags = DWM_BB_ENABLE;
+  bb.fEnable = true;
+  bb.hRgnBlur = NULL;
+
+  //Enable Blur Behind
+  hr = DwmEnableBlurBehindWindow(hwnd, &bb);
+  if (SUCCEEDED(hr))
+  {
+    //do more things
+  }
+  return hr;
+}
  
-  toplevel_window::toplevel_window(const std::wstring& menu_name,const std::wstring& name,
-    bool fit_to_display,float width,float height) 
-    : base_window(menu_name,name,fit_to_display,width,height) , wm_task_bar_create_(0),timer_id_(0),result_time_(INTERVAL_SEC1),status_(active)
+struct toplevel_window::impl : public base_win32_window
+{
+
+  impl(const std::wstring& menu_name,const std::wstring& name,bool fit_to_display,float width = 160,float height = 100) 
+    : base_win32_window(menu_name,name,fit_to_display,width,height) , wm_task_bar_create_(0),timer_id_(0),result_time_(INTERVAL_SEC1),status_(active)
   {
-    on_render.connect(boost::bind(&toplevel_window::render,this));
+    on_render.connect(boost::bind(&impl::render,this));
   };
 
-  toplevel_window::~toplevel_window()
-  {
+  ~impl(){
     safe_release(factory_);
     safe_release(write_factory_);
   };
 
-  void toplevel_window::create_window()
-  {
-
-    // Windowを作成する
-    CreateWindowEx(
-      WS_EX_APPWINDOW,
-      name_.c_str(),
-      title_.c_str(),
-      0 ,
-      CW_USEDEFAULT,
-      CW_USEDEFAULT,
-      static_cast<boost::uint32_t>(ceil(width_ /** dpiX / 96.f*/)),
-      static_cast<boost::uint32_t>(ceil(height_ /** dpiY / 96.f*/)),
-      NULL,
-      NULL,
-      HINST_THISCOMPONENT,
-      this
-      );
-  }
-
-  void toplevel_window::create_device()
-  {
-
-    //         入力_.reset(new input(HINST_THISCOMPONENT,hwnd_));
-    HRESULT hr = S_OK;
-
-
-    //ウィンドウの現在の幅、高さを求める
-    RECT rc;
-    GetClientRect( hwnd_, &rc );
-    boost::uint32_t width = rc.right - rc.left;
-    boost::uint32_t height = rc.bottom - rc.top;
-
-    {
-      //wic_imaging_factory_.CreateInstance(CLSID_WICImagingFactory);
-      //                       bitmap_ = load_bitmap_from_file(render_target_,wic_imaging_factory_,L"myship.png");
-    }
-
-    if(!render_target_)
-    {
-      RECT rc;
-      GetClientRect(hwnd_, &rc);
-
-      D2D1_SIZE_U size = D2D1::SizeU(
-        rc.right - rc.left,
-        rc.bottom - rc.top
-        );
-      
-      const D2D1_PIXEL_FORMAT format =
-          D2D1::PixelFormat(DXGI_FORMAT_B8G8R8A8_UNORM,
-                            D2D1_ALPHA_MODE_PREMULTIPLIED);
-      
-      const D2D1_RENDER_TARGET_PROPERTIES target_prop = 
-          D2D1::RenderTargetProperties(D2D1_RENDER_TARGET_TYPE_DEFAULT,format);
-
-      THROW_IFERR(factory_->CreateHwndRenderTarget(
-        target_prop,
-        D2D1::HwndRenderTargetProperties(hwnd_, size,D2D1_PRESENT_OPTIONS_IMMEDIATELY),
-        &render_target_
-        ));
-      // Create a DC render target 
-      //D2D1_RENDER_TARGET_PROPERTIES props = D2D1::RenderTargetProperties(
-      //       D2D1_RENDER_TARGET_TYPE_DEFAULT,
-      //       D2D1::PixelFormat(
-      //               DXGI_FORMAT_B8G8R8A8_UNORM,
-      //               D2D1_ALPHA_MODE_IGNORE
-      //               ) , 0.0, 0.0,
-      //       D2D1_RENDER_TARGET_USAGE_GDI_COMPATIBLE
-      //       );
-
-      //THROW_IFERR(factory_->CreateDCRenderTarget(
-      //       &props,
-      //       &render_target_
-      //       ));
-    }
-  }
-
-  void toplevel_window::discard_device()
-  {
-    safe_release(render_target_);
-  }
-
-  void toplevel_window::create_device_independent_resources()
-  {
-    // Direct2DFactory の生成
-
-    if(!factory_){
-#if defined(DEBUG) || defined(_DEBUG)
-      D2D1_FACTORY_OPTIONS options;
-      options.debugLevel = D2D1_DEBUG_LEVEL_INFORMATION ;
-      THROW_IFERR(D2D1CreateFactory(
-        D2D1_FACTORY_TYPE_SINGLE_THREADED,
-        options,
-        &factory_
-        ));
-#else
-      THROW_IFERR(D2D1CreateFactory(D2D1_FACTORY_TYPE_SINGLE_THREADED, &factory_));
-#endif
-
-    }
-
-    if(!write_factory_){
-      THROW_IFERR(::DWriteCreateFactory(
-        DWRITE_FACTORY_TYPE_SHARED,
-        __uuidof(IDWriteFactory),
-        reinterpret_cast<IUnknown**>(&write_factory_)
-        ));
-    }
-
-
-    //wic_imaging_factory_.CreateInstance(CLSID_WICImagingFactory);
-
-    //thunk_proc_ = (WNDPROC)thunk_.getCode();
-    layout_rect_ = D2D1::RectF(0.0f,0.0f,width_,height_);
-    // Text Formatの作成
-    THROW_IFERR(write_factory_->CreateTextFormat(
-    L"メイリオ",                // Font family name.
-    NULL,                       // Font collection (NULL sets it to use the system font collection).
-    DWRITE_FONT_WEIGHT_REGULAR,
-    DWRITE_FONT_STYLE_NORMAL,
-    DWRITE_FONT_STRETCH_NORMAL,
-    24.0f,
-    L"ja-jp",
-    &write_text_format_
-    ));
-
-  }
-
-  LRESULT toplevel_window::window_proc(HWND hwnd,boost::uint32_t message, WPARAM wParam, LPARAM lParam) 
-  {
-
-
+  LRESULT window_proc(HWND hwnd,boost::uint32_t message, WPARAM wParam, LPARAM lParam){
     switch (message)
     {
     case WM_CREATE:
@@ -175,7 +61,7 @@ namespace sf
         // TODO:
         create_device();
         wm_task_bar_create_ = RegisterWindowMessage(L"TaskbarButtonCreated");
-        ::SetWindowTextW(hwnd_,L"ミニタイマー(活動中)");
+        text(std::wstring(L"ミニタイマー(活動中)"));
         //MARGINS mgn = {-1,0,0,0};//let,right,top,bottom
         //HRESULT hr = DwmExtendFrameIntoClientArea(hwnd_, &mgn);
         break;
@@ -236,33 +122,33 @@ namespace sf
         {
         case active:
           --result_time_;
-          taskbar_list_->SetProgressValue(hwnd_,result_time_,INTERVAL_SEC1);
+          taskbar_.progress_value(*this,result_time_,INTERVAL_SEC1);
 
           if(result_time_ == 0)
           {
             ::MessageBeep(MB_ICONEXCLAMATION);
             status_ = sleep;
             result_time_ = INTERVAL_SEC2;
-            taskbar_list_->SetProgressState(hwnd_,TBPF_PAUSED);
-            taskbar_list_->SetProgressValue(hwnd_,result_time_,INTERVAL_SEC2);
-            ::SetWindowTextW(hwnd_,L"ミニタイマー(休憩中)");
+            taskbar_.progress_state(*this,taskbar::paused);
+            taskbar_.progress_value(*this,result_time_,INTERVAL_SEC2);
+            text(std::wstring(L"ミニタイマー(休憩中)"));
           }
             ::InvalidateRect(hwnd_,NULL,FALSE);
           break;
         case sleep:
           {
             --result_time_;
-            taskbar_list_->SetProgressValue(hwnd_,result_time_,INTERVAL_SEC2);
+            taskbar_.progress_value(*this,result_time_,INTERVAL_SEC2);
             if(result_time_ == 0)
             {
               ::MessageBeep(MB_OK);
               status_ = active;
               result_time_ = INTERVAL_SEC1;
-              taskbar_list_->SetProgressState(hwnd_,TBPF_INDETERMINATE);
-              taskbar_list_->SetProgressValue(hwnd_,result_time_,INTERVAL_SEC1);
-              ::SetWindowTextW(hwnd_,L"ミニタイマー(活動中)");
+              taskbar_.progress_state(*this,taskbar::indeterminate);
+              taskbar_.progress_value(*this,result_time_,INTERVAL_SEC1);
+              text(std::wstring(L"ミニタイマー(活動中)"));
             }
-            ::InvalidateRect(hwnd_,NULL,FALSE);
+            invalidate_rect();
           }
           break;
         }
@@ -278,10 +164,10 @@ namespace sf
 
     if(message == wm_task_bar_create_)
     {
-      THROW_IFERR(taskbar_list_.CreateInstance(CLSID_TaskbarList,0,CLSCTX_INPROC));
-      taskbar_list_->SetOverlayIcon(hwnd_,NULL,L"ミニタイマー");
-      taskbar_list_->SetProgressState(hwnd_,TBPF_INDETERMINATE);
-      taskbar_list_->SetProgressValue(hwnd_,100,100);
+      taskbar_.create();
+      taskbar_.overlay_icon(*this,NULL,std::wstring(L"ミニタイマー"));
+      taskbar_.progress_state(*this,taskbar::indeterminate);
+      taskbar_.progress_value(*this,100,100);
       // タイマーの設定
       ::SetTimer(hwnd_,(UINT_PTR)&timer_id_,1000,NULL);
     }
@@ -290,7 +176,7 @@ namespace sf
     {
       ::KillTimer(hwnd_,(UINT_PTR)&timer_id_);
       //
-      safe_release(taskbar_list_);
+      taskbar_.discard();
       // 後始末
       discard_device();
       // レンダーターゲットのリリース
@@ -309,16 +195,124 @@ namespace sf
     return ::DefWindowProcW(hwnd,message,wParam,lParam);
   }
 
-  void toplevel_window::main_loop()
+  virtual void create(){
+    create_device_independent_resources();
+    register_class();
+    create_window();
+
+    // 半透明ウィンドウを有効にする。
+    BOOL dwmEnable;
+    DwmIsCompositionEnabled (&dwmEnable); 
+    if (dwmEnable) EnableBlurBehind(*this);
+
+  };
+
+  virtual void discard_device()
   {
-    render();
+    safe_release(render_target_);
   }
 
-  void toplevel_window::render()
-  {
+  virtual void create_device(){
+    //         入力_.reset(new input(HINST_THISCOMPONENT,hwnd_));
+    HRESULT hr = S_OK;
+
+    //ウィンドウの現在の幅、高さを求める
+    RECT rc;
+    GetClientRect( hwnd_, &rc );
+    boost::uint32_t width = rc.right - rc.left;
+    boost::uint32_t height = rc.bottom - rc.top;
+
+    {
+      //wic_imaging_factory_.CreateInstance(CLSID_WICImagingFactory);
+      //                       bitmap_ = load_bitmap_from_file(render_target_,wic_imaging_factory_,L"myship.png");
+    }
+
+    if(!render_target_)
+    {
+      RECT rc;
+      GetClientRect(hwnd_, &rc);
+
+      D2D1_SIZE_U size = D2D1::SizeU(
+        rc.right - rc.left,
+        rc.bottom - rc.top
+        );
+      
+      const D2D1_PIXEL_FORMAT format =
+          D2D1::PixelFormat(DXGI_FORMAT_B8G8R8A8_UNORM,
+                            D2D1_ALPHA_MODE_PREMULTIPLIED);
+      
+      const D2D1_RENDER_TARGET_PROPERTIES target_prop = 
+          D2D1::RenderTargetProperties(D2D1_RENDER_TARGET_TYPE_DEFAULT,format);
+
+      THROW_IFERR(factory_->CreateHwndRenderTarget(
+        target_prop,
+        D2D1::HwndRenderTargetProperties(hwnd_, size,D2D1_PRESENT_OPTIONS_IMMEDIATELY),
+        &render_target_
+        ));
+      // Create a DC render target 
+      //D2D1_RENDER_TARGET_PROPERTIES props = D2D1::RenderTargetProperties(
+      //       D2D1_RENDER_TARGET_TYPE_DEFAULT,
+      //       D2D1::PixelFormat(
+      //               DXGI_FORMAT_B8G8R8A8_UNORM,
+      //               D2D1_ALPHA_MODE_IGNORE
+      //               ) , 0.0, 0.0,
+      //       D2D1_RENDER_TARGET_USAGE_GDI_COMPATIBLE
+      //       );
+
+      //THROW_IFERR(factory_->CreateDCRenderTarget(
+      //       &props,
+      //       &render_target_
+      //       ));
+    }
+  }
+
+  virtual void create_device_independent_resources(){
+    // Direct2DFactory の生成
+
+    if(!factory_){
+#if defined(DEBUG) || defined(_DEBUG)
+      D2D1_FACTORY_OPTIONS options;
+      options.debugLevel = D2D1_DEBUG_LEVEL_INFORMATION ;
+      THROW_IFERR(D2D1CreateFactory(
+        D2D1_FACTORY_TYPE_SINGLE_THREADED,
+        options,
+        &factory_
+        ));
+#else
+      THROW_IFERR(D2D1CreateFactory(D2D1_FACTORY_TYPE_SINGLE_THREADED, &factory_));
+#endif
+
+    }
+
+    if(!write_factory_){
+      THROW_IFERR(::DWriteCreateFactory(
+        DWRITE_FACTORY_TYPE_SHARED,
+        __uuidof(IDWriteFactory),
+        reinterpret_cast<IUnknown**>(&write_factory_)
+        ));
+    }
+
+
+    //wic_imaging_factory_.CreateInstance(CLSID_WICImagingFactory);
+
+    //thunk_proc_ = (WNDPROC)thunk_.getCode();
+    layout_rect_ = D2D1::RectF(0.0f,0.0f,width_,height_);
+    // Text Formatの作成
+    THROW_IFERR(write_factory_->CreateTextFormat(
+    L"メイリオ",                // Font family name.
+    NULL,                       // Font collection (NULL sets it to use the system font collection).
+    DWRITE_FONT_WEIGHT_REGULAR,
+    DWRITE_FONT_STYLE_NORMAL,
+    DWRITE_FONT_STRETCH_NORMAL,
+    24.0f,
+    L"ja-jp",
+    &write_text_format_
+    ));
+
+  }
 
+  void render(){
     static float t = 0.0f;
-    
 
     if (render_target_)
     {
@@ -355,8 +349,51 @@ namespace sf
         throw;
       }
     }
+  }
+  void create_window()
+  {
+
+    // Windowを作成する
+    CreateWindowEx(
+      WS_EX_APPWINDOW | WS_EX_TOPMOST,
+      name_.c_str(),
+      title_.c_str(),
+      0 ,
+      CW_USEDEFAULT,
+      CW_USEDEFAULT,
+      static_cast<boost::uint32_t>(ceil(width_ /** dpiX / 96.f*/)),
+      static_cast<boost::uint32_t>(ceil(height_ /** dpiY / 96.f*/)),
+      NULL,
+      NULL,
+      HINST_THISCOMPONENT,
+      this
+      );
+  };
+
+private:
+
+  long wm_task_bar_create_;
+  sf::taskbar taskbar_;
+  UINT timer_id_;
+  static const int INTERVAL_SEC1 = 60 * 15;// 15分
+  static const int INTERVAL_SEC2 = 30;// 30秒
+
+  int result_time_;
+  enum timer_status {
+    active,
+    sleep
   };
 
+  ID2D1FactoryPtr factory_;
+  ID2D1HwndRenderTargetPtr render_target_;
+  IDWriteFactoryPtr write_factory_;
+  IWICImagingFactoryPtr wic_imaging_factory_;
+
+  timer_status status_;
+  IDWriteTextFormatPtr write_text_format_;
+  D2D1_RECT_F layout_rect_;
+};
+
   //
   // Creates a Direct2D bitmap from the specified
   // file name.
@@ -448,25 +485,17 @@ namespace sf
     return bitmap;
   }
 
-  HRESULT EnableBlurBehind(HWND hwnd)
-{
-   HRESULT hr = S_OK;
-
-   //Create and populate the BlurBehind structre
-   DWM_BLURBEHIND bb = {0};
-   //Enable Blur Behind and Blur Region;
-   bb.dwFlags = DWM_BB_ENABLE;
-   bb.fEnable = true;
-   bb.hRgnBlur = NULL;
-
-   //Enable Blur Behind
-   hr = DwmEnableBlurBehindWindow(hwnd, &bb);
-   if (SUCCEEDED(hr))
-   {
-      //do more things
-   }
-   return hr;
-}
+  toplevel_window::toplevel_window(const std::wstring& menu_name,const std::wstring& name,bool fit_to_display,float width ,float height)
+    : impl_(new impl(menu_name,name,fit_to_display,width,height))
+  {
+
+  };
+
+  void * toplevel_window::raw_handle(){return impl_->raw_handle();};
+  void toplevel_window::create(){impl_->create();};
+  void toplevel_window::show(boost::uint32_t show_flag){impl_->show(show_flag);};
+  void toplevel_window::text(std::wstring& text){impl_->text(text);};
+  void toplevel_window::update(){impl_->update();};
 
  toplevel_window_ptr create_toplevel_window
     (
@@ -479,14 +508,7 @@ namespace sf
     )
   {
     toplevel_window* p = new toplevel_window(menu_name,name,fit_to_display,width,height);
-    p->create_device_independent_resources();
-    p->register_class();
-    p->create_window();
-
-    BOOL dwmEnable;
-    DwmIsCompositionEnabled (&dwmEnable); 
-    if (dwmEnable) EnableBlurBehind(p->hwnd_);
-
+    p->create();
     p->show(show_flag);
     p->update();
     return toplevel_window_ptr(p);