/// ****************************************************************************
/// @file   
/// @author Dr.Neeton
/// @date   200X/X/X - 2015/11/13
/// 
/// @brief  Win32 基本コンポーネント。
/// 
/// ****************************************************************************

#pragma once

#include "../../Base/CPL_WIN_Base.h"
#include "../../GObj/CPL_WIN_Graphics.h"
#include "../../Base/CPL_WIN_FileList.h"
#include "CPL_WIN_ToolTip.h"


namespace CPL {
namespace WIN {

// _____________________________________________________________________________
/// @brief ウィンドウスタイル
///
// *****************************************************************************
union STYLE {
  LONG_PTR datasize[2]; // 全サイズ確保用
  LONG_PTR style;
  STYLE(){ datasize[0] = datasize[1] = 0; }
  STYLE( LONG_PTR in_style )
  {
    style = in_style;
    datasize[1] = 0;
  }
  STYLE( LONG_PTR in_style, LONG_PTR in_ex_style )
  {
    style = in_style;
    datasize[1] = in_ex_style;
  }

  struct WinStyle {
    unsigned dummy0         :16; ///< ダミー
    unsigned maxbox_tabstop : 1; ///< WS_TABSTOP      : タブキーを使用して移動できる多数のコントロールのうち１つを指定します。\n
                                 ///< WS_MAXIMIZEBOX  : 最大化ボタンのあるウィンドウを作成。
    unsigned minbox_group   : 1; ///< WS_GROUP        : 方向キーを使用してあるコントロールから次のコントロールに移動できるコントロールグループの最初のコントロールを指定。\n
                                 ///< WS_MINIMIZEBOX  : 最小化ボタンのあるウィンドウを作成。
    unsigned sizebox        : 1; ///< WS_THICKFRAME   : サイズ変更可の境界線。
    unsigned sysmenu        : 1; ///< WS_SYSMENU      : タイトルバーにコントロールメニューボックスのあるウィンドウを作成する（タイトルバーのあるウィンドウで使用します）。
    unsigned hscroll        : 1; ///< WS_HSCROLL      : 水平スクロールバー。
    unsigned vscroll        : 1; ///< WS_VSCROLL      : 垂直スクロールバー。
    unsigned dlgframe       : 1; ///< WS_DLGFRAME     : サイズ変更不可の境界線。
    unsigned border         : 1; ///< WS_BORDER       : 境界線を表示。
    unsigned dummy1         : 1; ///< ダミー
    unsigned clipchildren   : 1; ///< WS_CLIPCHILDREN : 親ウィンドウ内に描画するときに、子ウィンドウにより占有されている領域を除外する（親ウィンドウを作成するときに使用する）。
    unsigned clipsiblings   : 1; ///< WS_CLIPSIBLINGS : 子ウィンドウを互いに重ならないようにクリップする。
    unsigned disabled       : 1; ///< WS_DISABLED     : 初期状態で使用不可
    unsigned visible        : 1; ///< WS_VISIBLE      : 初期状態で表示
    unsigned minimize       : 1; ///< WS_MINIMIZE     : 初期状態で最小化
    unsigned child          : 1; ///< WS_CHILD        : 子ウィンドウ          　×popup
    unsigned popup          : 1; ///< WS_POPUP        : ポップアップウィンドウ　×child
    void MaxBox()      { maxbox_tabstop    = true; } ///< @copydoc maxbox_tabstop
    void TabStop()     { MaxBox();                 } ///< @copydoc maxbox_tabstop
    void MinBox()      { minbox_group      = true; } ///< @copydoc minbox_group
    void Group()       { MinBox();                 } ///< @copydoc minbox_group
    void SizeBox()     { sizebox           = true; } ///< @copydoc sizebox
    void SysMenu()     { sysmenu           = true; } ///< @copydoc sysmenu
    void ScrollH()     { hscroll           = true; } ///< @copydoc hscroll
    void ScrollV()     { vscroll           = true; } ///< @copydoc vscroll
    void DlgFrame()    { dlgframe          = true; } ///< @copydoc dlgframe
    void Border()      { border            = true; } ///< @copydoc border
    void ClipChildren(){ clipchildren      = true; } ///< @copydoc clipchildren
    void ClipSiblings(){ clipsiblings      = true; } ///< @copydoc clipsiblings
    void Disabled()    { disabled          = true; } ///< @copydoc disabled
    void Visible()     { visible           = true; } ///< @copydoc visible
    void Minimize()    { minimize          = true; } ///< @copydoc minimize
    void Child()       { child             = true; } ///< @copydoc child
    void Popup()       { popup             = true; } ///< @copydoc popup
    void Caption()     { border = dlgframe = true; } ///< タイトル バーを持つウィンドウを作成。
  } Win;
  struct BtnStyle {
    WORD btn_style;
    void PushButton()     { btn_style |= BS_PUSHBUTTON;      } ///< プッシュボタン
    void DefPushButton()  { btn_style |= BS_DEFPUSHBUTTON;   } ///< 太い境界をもつデフォルトのプッシュボタン
    void CheckBox()       { btn_style |= BS_CHECKBOX;        } ///< チェックボックス
    void AutoCheckBox()   { btn_style |= BS_AUTOCHECKBOX;    } ///< チェックボックス（ユーザーの操作で状態が自動的に変わる）
    void RadioButton()    { btn_style |= BS_RADIOBUTTON;     } ///< ラジオボタン
    void State3()         { btn_style |= BS_3STATE;          } ///< ３つの状態を持つチェックボックス（選択・非選択・灰色）
    void Auto3State()     { btn_style |= BS_AUTO3STATE;      } ///< ３つの状態を持つチェックボックス（選択・日選択・灰色：自動で変わる）
    void GroupBox()       { btn_style |= BS_GROUPBOX;        } ///< グループボックス
    void AutoRadioButton(){ btn_style |= BS_AUTORADIOBUTTON; } ///< ラジオボタン（グループ内では自動で１つのみ選択される）
    void OwnerDraw()      { btn_style |= BS_OWNERDRAW;       } ///< オーナードローボタン
    void LeftText()       { btn_style |= BS_LEFTTEXT;        } ///< 左側にテキストを配置
    void RightButton()    { btn_style |= BS_RIGHTBUTTON;     } ///< 右側にテキストを配置
    void Icon()           { btn_style |= BS_ICON;            } ///< アイコンを表示するボタン
    void Bitmap()         { btn_style |= BS_BITMAP;          } ///< ビットマップを表示するボタン
    void Left()           { btn_style |= BS_LEFT;            } ///< 左寄せテキスト
    void Right()          { btn_style |= BS_RIGHT;           } ///< 右寄せテキスト
    void Center()         { btn_style |= BS_CENTER;          } ///< 水平方向中央にテキストを配置
    void Top()            { btn_style |= BS_TOP;             } ///< ボタンの最上部にテキストを配置
    void Bottom()         { btn_style |= BS_BOTTOM;          } ///< ボタンの下部にテキストを配置
    void VCenter()        { btn_style |= BS_VCENTER;         } ///< 垂直方向中央にテキストを配置
    void PushLike()       { btn_style |= BS_PUSHLIKE;        } ///< プッシュボタンの外観を持つチェックボックスORラジオボタン
    void MultiLine()      { btn_style |= BS_MULTILINE;       } ///< 複数行テキスト
    void Notify()         { btn_style |= BS_NOTIFY;          } ///< 親ウィンドウに、BN_DBLCLK,BNKILLFOCUS,BNSETFOCUS のメッセージを送るようにする
    void Flat()           { btn_style |= BS_FLAT;            } ///< フラットボタン
  } Btn;
  struct ComboStyle {
    WORD combo_style;
    void Simple()           { combo_style |= CBS_SIMPLE;            } ///< 常時リストボックスが表示されるコンボボックス
    void DropDown()         { combo_style |= CBS_DROPDOWN;          } ///< ドロップダウンコンボボックス
    void DropDownList()     { combo_style |= CBS_DROPDOWNLIST;      } ///< ドロップダウンリストボックス
    void OwnerDrawFixed()   { combo_style |= CBS_OWNERDRAWFIXED;    } ///< 各項目の高さがすべて同じのオーナードローコンボボックス
    void OwnerDrawVariable(){ combo_style |= CBS_OWNERDRAWVARIABLE; } ///< 各項目の高さが可変のオーナードローコンボボックス
    void AutoHScroll()      { combo_style |= CBS_AUTOHSCROLL;       } ///< エディットコントロール内のテキストが自動的に右スクロール
    void OemConvert()       { combo_style |= CBS_OEMCONVERT;        } ///< Windows文字セットからOEM文字セットへ変換（CBS_SIMPLE,CBS_DROPDOWNスタイルのみ有効）
    void Sort()             { combo_style |= CBS_SORT;              } ///< 自動的にソートする
    void Hasstrings()       { combo_style |= CBS_HASSTRINGS;        } ///< オーナードローコンボボックスのアイテムがテキストであることを指定
    void NoIntegralHeight() { combo_style |= CBS_NOINTEGRALHEIGHT;  } ///< コンボボックスのサイズを指定
    void DisableNoScroll()  { combo_style |= CBS_DISABLENOSCROLL;   } ///< 垂直スクロールバーが常に表示、項目数が少ない場合無効表示
    void UpperCase()        { combo_style |= CBS_UPPERCASE;         } ///< 入力された小文字を大文字に変換
    void LowerCase()        { combo_style |= CBS_LOWERCASE;         } ///< 入力された大文字を小文字に変換
  }Combo;
  struct EditStyle{
    WORD edit_style;
    void Left()       { edit_style |= ES_LEFT;        } ///< テキストを左揃えで表示
    void Center()     { edit_style |= ES_CENTER;      } ///< 複数行エディットコントロールにおいて、中央揃えで表示
    void Right()      { edit_style |= ES_RIGHT;       } ///< 複数エディットコントロールにおいて、右揃えで表示
    void MultiLine()  { edit_style |= ES_MULTILINE;   } ///< 複数行エディットコントロールを作成
    void UpperCase()  { edit_style |= ES_UPPERCASE;   } ///< 入力された文字を大文字に変換
    void LowerCase()  { edit_style |= ES_LOWERCASE;   } ///< 入力された文字を小文字に変換
    void PassWord()   { edit_style |= ES_PASSWORD;    } ///< 入力された文字をアスタリスクに置き換えて表示
    void AutoVScroll(){ edit_style |= ES_AUTOHSCROLL; } ///< 最下行でEnterを押すと、自動で上にスクロール
    void NoHideSel()  { edit_style |= ES_NOHIDESEL;   } ///< 選択テキストが、フォーカスを持っていないときでも反転表示
    void OemConvert() { edit_style |= ES_OEMCONVERT;  } ///< 入力されたテキストをWindows文字セットからOEM文字セットに変換
    void ReadOnly()   { edit_style |= ES_READONLY;    } ///< ユーザーによるテキストの入力や編集をできないようにする
    void WantReturn() { edit_style |= ES_WANTRETURN;  } ///< 複数行エディットコントロールにおいて、Enterキーによる改行を挿入する
    void Number()     { edit_style |= ES_NUMBER;      } ///< 数字のみ入力可
  } Edit;
  struct ListStyle {
    WORD list_style;
    void Notify()           { list_style |= LBS_NOTIFY;            } ///< クリック（ダブルクリック）を親ウィンドウに入力メッセージを通知
    void Sort()             { list_style |= LBS_SORT;              } ///< 自動的にソート
    void NoRedraw()         { list_style |= LBS_NOREDRAW;          } ///< アイテムが変更されてもリストボックスの概観を更新しないようにする
    void MultipleSel()      { list_style |= LBS_MULTIPLESEL;       } ///< 複数の項目選択可
    void OwnerDrawFixed()   { list_style |= LBS_OWNERDRAWFIXED;    } ///< 各アイテムの高さがすべて同じのリストボックス
    void OwnerDrawVariable(){ list_style |= LBS_OWNERDRAWVARIABLE; } ///< 各アイテムの高さがすべて可変のリストボックス
    void HasStrings()       { list_style |= LBS_HASSTRINGS;        } ///< オーナードローリストボックスのアイテムが文字列であることを指定
    void UseTabStops()      { list_style |= LBS_USETABSTOPS;       } ///< タブ文字を認識し表示できるようにする
    void NoIntegralHeight() { list_style |= LBS_NOINTEGRALHEIGHT;  } ///< リストボックスのサイズを指定
    void MultiColumn()      { list_style |= LBS_MULTICOLUMN;       } ///< 水平にスクロールする複数行のリストボックス
    void WantKeyboardInput(){ list_style |= LBS_WANTKEYBOARDINPUT; } ///< 入力フォーカスを持っているときに、ユーザーがキーを押すと、リストボックスのオーナーが WM_VKEYTOITEM or WM_CHARTOITEM メッセージを受け取る
    void ExtendedSel()      { list_style |= LBS_EXTENDEDSEL;       } ///< Shiftキーとマウス、または特殊なキーの組み合わせで、複数のアイテムを選択可
    void DisableNoScroll()  { list_style |= LBS_DISABLENOSCROLL;   } ///< 垂直スクロールバーを常に表示、項目数が満たない場合無効表示
    void NoData()           { list_style &= ~(LBS_SORT | LBS_HASSTRINGS);
                  list_style |= LBS_NODATA;
                              list_style |= LBS_OWNERDRAWFIXED;    } ///< データを持たないリストボックスを指定。項目数が1000を超えるときにこのスタイルを指定する。
    void NoSel()            { list_style |= LBS_NOSEL;             } ///< 選択できないアイテムを持つリストボックス
//  void Standard()         { list_style |= LBS_STANDARD;          } ///< Notify,sort,vscroll,border
  } List;
  struct ScrollStyle {
    WORD scroll_style;
    void Horz()    { scroll_style |= SBS_HORZ; } ///< 水平スクロールバー
    void Vert()    { scroll_style |= SBS_VERT; } ///< 垂直スクロールバー
    void TopLeftAlign(){ scroll_style |= SBS_TOPALIGN; } ///< 水平スクロールバーならば指定された矩形の上端に、  \n
                                                         ///< 垂直スクロールバーならば指定された矩形の左端に、  \n
                                                         ///< サイズボックスならば指定された矩形の左上はしに表示。
    void BottomRightAligin(){ scroll_style |= SBS_BOTTOMALIGN; } ///< 水平スクロールバーならば指定された矩形の下端に、        \n
                                                                 ///< 垂直スクロールバーならば指定された矩形の右端に、        \n
                                                                 ///< サイズボックスがならば指定された矩形の右下端に表示される。
    void SizeBox() { scroll_style |= SBS_SIZEBOX;  } ///< サイズボックス
    void SizeGrip(){ scroll_style |= SBS_SIZEGRIP; } ///< 縁が盛り上がったサイズボックス
  } Scroll;
  struct StaticStyle {
    LONG_PTR static_style;
    void Left()          { static_style |= SS_LEFT;           } ///< 左揃え
    void Center()        { static_style |= SS_CENTER;         } ///< 中央揃え
    void Right()         { static_style |= SS_RIGHT;          } ///< 右揃え
    void Icon()          { static_style |= SS_ICON;           } ///< アイコンを表示、サイズ自動調整
    void BlackRect()     { static_style |= SS_BLACKRECT;      } ///< ウィンドウ枠と同じ色で塗りつぶされた長方形を作成
    void GrayRect()      { static_style |= SS_GRAYRECT;       } ///< 画面の背景と同じ色で塗りつぶされた長方形を作成
    void WhiteRect()     { static_style |= SS_WHITERECT;      } ///< ウィンドウの背景と同じ色で塗りつぶされた長方形を作成
    void BlackFrame()    { static_style |= SS_BLACKFRAME;     } ///< ウィンドウの沸くと同じ色の枠をもつボックスを作成
    void GrayFrame()     { static_style |= SS_GRAYFRAME;      } ///< 画面の背景と同じ色の枠をもつボックスを作成
    void WhiteFrame()    { static_style |= SS_WHITEFRAME;     } ///< ウィンドウの背景と同じ色をもつボックスを作成
    void UserItem()      { static_style |= SS_USERITEM;       } ///< ユーザー定義のアイテムを指定
    void Simple()        { static_style |= SS_SIMPLE;         } ///< 単一行のテキスト左揃え（このコントロールの親はWM_CTLCOLORメッセージをしょりしてはいけいない）
    void LeftNoWordWrap(){ static_style |= SS_LEFTNOWORDWRAP; } ///< 左揃えでタブを展開。テキストは折り返されない
    void OwnerDraw()     { static_style |= SS_OWNERDRAW;      } ///< オーナードローコントロールを作成
    void Bitmap()        { static_style |= SS_BITMAP;         } ///< ビットマップを表示するスタティックコントロール
    void EnhMetaFile()   { static_style |= SS_ENHMETAFILE;    } ///< メタファイル…
    void EtchedHorz()    { static_style |= SS_ETCHEDHORZ;     } ///< 上下端の縁をEDDEC_ETCHEDエッジスタイルを使用して描画
    void EtchedVert()    { static_style |= SS_ETCHEDVERT;     } ///< 左右端の縁をEDDEC_ETCHEDエッジスタイルを使用して描画
    void EtchedFrame()   { static_style |= SS_ETCHEDFRAME;    } ///< 縁をEDDEC_ETCHEDエッジスタイルを使用して描画
    void NoPrefix()      { static_style |= SS_NOPREFIX;       } ///< アンパサンド(&)をアクセラレータのプレフィックス文字として解釈しないように指定
    void Notify()        { static_style |= SS_NOTIFY;         } ///< クリック（ダブルクリック）するたびに、親ウィンドウに STN_CLICKED(STR_DBLCLK)通知メッセージを送る
    void CenterImage()   { static_style |= SS_CENTERIMAGE;    } ///< サイズが変更されてもビットマップやアイコンスタイルを持つコントロールの中心点を変えないようにする
    void RightJust()     { static_style |= SS_RIGHTJUST;      } ///< イメージを右下隅に固定
    void RealSizeImage() { static_style |= SS_REALSIZEIMAGE;  } ///< コントロールサイズがイメージに合わされる
    void Sunken()        { static_style |= SS_SUNKEN;         } ///< コントロールの周囲にくぼんだ縁を描画
    void EndEllipsis()   { static_style |= SS_ENDELLIPSIS;    } ///< 表示しきれない場合、文字列の一部を省略記号に置き換える
    void WordEllipsis()  { static_style |= SS_WORDELLIPSIS;   } ///< 表示しきれない場合、文字列を切り縮めて、省略記号をつけます
  } Static;
//  struct Mdi{
//  };
  struct TreeStyle {
    LONG_PTR tree_style;
  };
  struct ExWinStyle {
    LONG_PTR dummy;
    LONG_PTR style;
    void Acceptfiles(){ style |= WS_EX_ACCEPTFILES; } ///< ドラッグ＆ドロップ受け入れ
    void ToolWindow() { style |= WS_EX_TOOLWINDOW;  } ///< ツールウィンドウ
//    void TreeView(){ style |= WC_TREEVIEW; }
  } ExStyle;
};


// _____________________________________________________________________________
// タグタイプ指定フラグ
// 
CPL_SCOPED_ENUM
( eTagTypes, U64
, UserID     = BIT0
, Rect       = BIT1
, FrameWidth = BIT2
, IsVisible  = BIT3
, IsEnable   = BIT4
, SizeMode   = BIT5
, ColorBG    = BIT6
, ColorFrame = BIT7
, ColorText  = BIT8
, Title      = BIT9
, Text       = BIT10
, Message    = BIT11
, Parent     = BIT12

, All = (U32)(BIT32-1)
, _users_ = BIT32
);


namespace doxycomment {
/// @param[in] in_hdl_win_parent : 親のウィンドウハンドルを指定します。
inline void arg_in_hdl_win_parent( _in<HWND> in_hdl_win_parent ){}
/// @param[in] in_pos  : 左上の座標を指定します。
inline void arg_in_pos( _in<td_Coord2> in_pos ){}
/// @param[in] in_size : ウィンドウのサイズを指定します。
inline void arg_in_size( _in<td_Coord2> in_size ){}
/// @param[out] in_rect : ４点座標をRect形式で指定します。
inline void arg_in_rect( _in<Rect> in_rect ){}
/// @param[out] out_rect : 座標取得用のRectオブジェクトを指定します。
inline void arg_out_rect( rout<Rect> out_rect ){}
/// @param[in] in_flag_redraw
///   : サイズ変更後、再描画するかどうか指定します。\n
///   : true  - 再描画する。\n
///   : false - 再描画しない。
inline void arg_in_flag_redraw( _in<bool> in_flag_redraw ){}
/// @param[in] in_flag_client_size
///   : 指定されたサイズがウィンドウサイズかクライアントサイズか指定します。\n
///   : true  - クライアントサイズ\n
///   : false - ウィンドウサイズ
inline void arg_in_flag_client_size( _in<bool> in_flag_client_size ){}
/// @param[in] in_win_style
///   : ウィンドウスタイルを指定します。\n
///   : 詳しくはCPL::WIN::STYLEを参照してください。
inline void arg_in_win_style( _in<CPL::WIN::STYLE> in_win_style ){}
/// @param[in] in_hdc : デバイスコンテキストのハンドルを指定します。
inline void arg_in_hdc( _in<HDC> in_hdc ){}
}


// _____________________________________________________________________________
/// @brief コンポーネント基底クラス
///
// *****************************************************************************
class BaseComponent
  : public Core::BaseObject
{
private:
  CPL_SINGLETON_INIT( HINSTANCE, zzf_sm_hInstance_, (HINSTANCE)::GetModuleHandle(nullptr) )
  CPL_SINGLETON_INIT( Core::SwitchTable, sm_id_table, 0x2ffff )

  SDEF  m_comp_id;

protected:
  static SDEF zzf_NewComponentID_();
  static void zzf_DelComponentID_( SDEF id );

  struct MSG_PARAM {
    UINT   msg;
    WPARAM wp;
    LPARAM lp;

    MSG_PARAM( UINT msg_, WPARAM wp_, LPARAM lp_ )
      : msg( msg_), wp( wp_), lp( lp_)
    {}
    MSG_PARAM(){} // これ必須
  };

  Core::Stack<MSG_PARAM> m_message_stack;

  friend class BaseComponent;
  struct CallStackMsg {
    Core::Stack<MSG_PARAM>& m_message_stack;

    CallStackMsg( BaseComponent* in_ptr_comp, UINT in_message, WPARAM in_wparam, LPARAM in_lparam )
      : m_message_stack(in_ptr_comp->m_message_stack)
    {
      m_message_stack.Push( MSG_PARAM(in_message, in_wparam, in_lparam) );
    }
    ~CallStackMsg()
    {
      m_message_stack.Pop();
    }
  };

  // デフォルトフォント
  CPL_SINGLETON_INIT
    ( sdptr<DrawFont>
    , sm_sp_DefFont_MS_Gothic
    , CPL_MAKE_SHARED( DrawFont, nullptr, 12, SwS("ＭＳ ゴシック") )
    )
  CPL_SINGLETON_INIT
    ( sdptr<DrawFont>
    , sm_sp_DefFont_MS_PGothic
    , CPL_MAKE_SHARED( DrawFont, nullptr, 12, SwS("ＭＳ Ｐゴシック") )
    )

public:
  static HINSTANCE GetInstance_(){ return zzf_sm_hInstance_(); }

  SDEF  GetComponentID() const { return m_comp_id; }

  BaseComponent()
  {
    m_comp_id = zzf_NewComponentID_();
  }
  virtual ~BaseComponent()
  {
    zzf_DelComponentID_( m_comp_id );
  }

  
  // _____________________________________________________________________________
  /// @brief BaseComponent Pimpl実装用
  ///
  // *****************************************************************************
  class Binder {
  protected:
    friend class Binder;

    sdptr<BaseComponent> impl;

    // 継承用コンストラクタ　※ BaseComponentは単体で使用してはいけない
    Binder( BaseComponent* in_ptr_base_comp )
      : impl( in_ptr_base_comp )
    {}
    Binder( _in<sdptr<BaseComponent>> in_sp_base_comp )
      : impl( in_sp_base_comp )
    {}

  public:
    SDEF  GetComponentID(){ return impl->GetComponentID(); }
  };

};




// 前方宣言
class DrawFont;

//
#define CPL_WIN_COMPONENT_GET_CLASS_NAME( classname )\
  virtual char_cptr    zzf_GetClassNameA() const override { return classname; }\
  virtual wchar_t_cptr zzf_GetClassNameW() const override { return L##classname; }\
  virtual str_cptr     zzf_GetClassName () const override { return SwS(classname); }

#define CPL_WIN_COMPONENT_GET_CLASS_NAME_Base( baseclass )\
  virtual char_cptr    zzf_GetClassNameA() const override { return baseclass::zzf_GetClassNameA(); }\
  virtual wchar_t_cptr zzf_GetClassNameW() const override { return baseclass::zzf_GetClassNameW(); }\
  virtual str_cptr     zzf_GetClassName () const override { return baseclass::zzf_GetClassName(); }

// _____________________________________________________________________________
/// @brief コンポーネントクラス
///
// *****************************************************************************
class Component
  : public BaseComponent
{
public:
  friend class Component;
  friend class Container;
  friend class Window;
  friend class MdiWindow;
  friend class DialogWindow;

  CPL_SCOPED_ENUM
    ( eSizeMode, int
    , Restore  = SIZE_RESTORED  // 通常のサイズ変更
    , Minimize = SIZE_MINIMIZED // 最小化
    , Maximize = SIZE_MAXIMIZED // 最大化
    , MaxShow  = SIZE_MAXSHOW   // 他のウィンドウが元のサイズに戻された
    , MaxHide  = SIZE_MAXHIDE   // 他のウィンドウが最大化された
    );
  CPL_SCOPED_ENUM
    ( eMouseButton, int
    , Left
    , Middle
    , Right
    );
  CPL_SCOPED_ENUM
    ( eEventMode, int
    , Throw    // 全てのイベントを処理する（デフォルト）
    , AllCut   // 全てのイベントを遮断
    , ChildCut // 子供からのメッセージをカット
    );
  CPL_SCOPED_ENUM
    ( eRectFlag, int
    , Left   = BIT0
    , Top    = BIT1
    , Right  = BIT2
    , Bottom = BIT3
    , L_R    = Left | Right
    , L_T    = Left | Top
    , L_B    = Left | Bottom
    , R_T    = Right | Top
    , R_B    = Right | Bottom
    , T_B    = Top | Bottom
    , L_R_T  = L_R | Top
    , L_R_B  = L_R | Bottom
    , L_T_B  = Left | T_B
    , R_T_B  = Right | T_B
    , All    = BIT0 | BIT1 | BIT2 | BIT3
    );

  // イベントモードのローカル設定用クラス
  class StackEventMode {
    Component* m_ptr_comp;
    eEventMode m_old_event;
  public:
    StackEventMode( Component* in_ptr_comp, int in_event_mode )
      : m_ptr_comp( in_ptr_comp )
      , m_old_event( (eEventMode)in_ptr_comp->GetEventMode() )
    {
      m_ptr_comp->SetEventMode( (eEventMode)in_event_mode );
    }
    ~StackEventMode()
    {
      m_ptr_comp->SetEventMode( m_old_event );
    }
  };


private:

  HCURSOR   m_def_cursor;
  HBRUSH    m_back_brush;
  COLORREF  m_back_color;
  U8        m_flag_win_instance;
  U8        m_event_mode; // EVENt_MODEを参照
  U8        m_event_mask; // 今の所、これをtrueにすることでマウスキャプチャーを無効にする
  U8        m_flag_child_size; // 自身の変更メッセージを親へ通知するかどうか

  static LRESULT CALLBACK
    zzf_staticProc_
      ( HWND   in_hdl_window
      , UINT   in_message
      , WPARAM in_wparam
      , LPARAM in_lparam );

protected:
  CPL_SINGLETON_INIT(Component*, sm_ptr_modal_window, nullptr)

  HWND           m_hdl_window;        // ウィンドウハンドル
  HWND           m_hdl_win_parent;    // 親のウィンドウハンドル
  sdptr<ToolTip> m_sp_tool_tip;       // ツールチップ
  std::string    m_user_ID;

  bool zzf_SetHandle( HWND in_hdl_window );
  bool zzf_Create
        ( _in<HWND     > in_hdl_win_parent
        , pin<char     > in_title
        , _in<td_Coord2> in_pos
        , _in<td_Coord2> in_size
        , _in<SDEF     > in_ID
        , _in<LONG_PTR > in_win_style
        , _in<LONG_PTR > in_win_ex_style
        , pio<void     > in_ptr_this
        );
  bool zzf_Create
        ( _in<HWND     > in_hdl_win_parent
        , pin<wchar_t  > in_title
        , _in<td_Coord2> in_pos
        , _in<td_Coord2> in_size
        , _in<SDEF     > in_ID
        , _in<LONG_PTR > in_win_style
        , _in<LONG_PTR > in_win_ex_style
        , pio<void     > in_ptr_this
        );
  void    zzf_SetProc( WNDPROC in_win_proc )
  {
    ::SetWindowLongPtr
        ( m_hdl_window
        , GWLP_WNDPROC
        , reinterpret_cast<LONG_PTR>(in_win_proc)
        );
  }
  static WNDPROC zzf_GetProc( HWND in_hdl_window )
  {
    return (WNDPROC)::GetWindowLongPtr( in_hdl_window, GWLP_WNDPROC );
  }

  // マウス処理関係
  virtual SDEF  On_MouseDown ( _in<eMouseButton> in_mouse_btn ){ return false; }
  virtual SDEF  On_MouseUp   ( _in<eMouseButton> in_mouse_btn ){ return false; }
  virtual SDEF  On_MouseMove ()                                { return false; }
  virtual SDEF  On_MouseWheel( _in<WORD> in_fw_keys, _in<short> in_z_delta ){ return false; }
  //virtual SDEF  On_DblClick  ( MOUSe_BTN in_type_mouse_btn )            { return false; }
  // キー処理
  virtual SDEF  On_KeyDown( _in<int> in_virtual_key_code )               { return false; }
  virtual SDEF  On_KeyUp  ( _in<int> in_virtual_key_code )               { return false; }
  virtual SDEF  On_Char   ( _in<int> in_char_code, _in<int> in_key_data ){ return false; }
  virtual SDEF  On_Focus  ( _in<int> in_set_flag )                       { return false; }
  // ウィンドウ処理
  virtual SDEF  On_Create()                             { return false; }
  virtual SDEF  On_Size  ( _in<eSizeMode> in_size_mode ){ return false; }
  virtual SDEF  On_Sizing( Rect* in_rect )              { return false; }
  virtual SDEF  On_Move  ()                             { return false; }
  virtual SDEF  On_Moving( Rect* in_rect )              { return false; }
  // その他
  virtual SDEF  On_Destroy(){ return false; }
  virtual SDEF  On_Active ( _in<int> in_flag_active, _in<int> in_flag_min, _in<HWND> in_hdl_win_prev ){ return false; }   // in_flag_active   0:非アクティブ  1:マウス以外  2:マウスでアクティブ
  virtual SDEF  On_Show   ( _in<BOOL> in_show_flag ){ return false; }
  virtual SDEF  On_Timer  ( _in<int> in_timer_ID )  { return false; }
//  virtual long  On_MenuSelect();
  
//  virtual long  On_Draw( HDC hDC, PAINTSTRUCT* ps ){ return false; }
  virtual SDEF  On_Paint(){ return false; }
  virtual SDEF  On_EraseBkGnd( _in<HDC> in_hdc )
  {
    Rect rt;
    ::GetClientRect( m_hdl_window, &rt );
    ::FillRect( in_hdc, &rt, m_back_brush );
    return false;
  }

  virtual SDEF  On_OtherProc( _in<HWND> in_hdl_window, _in<UINT> in_message, _in<WPARAM> in_wparam, _in<LPARAM> in_lparam ){ return false; } // その他のシステムイベント
  virtual SDEF  On_UserProc ( _in<HWND> in_hdl_window, _in<UINT> in_message, _in<WPARAM> in_wparam, _in<LPARAM> in_lparam ){ return false; } // ユーザー定義用

  virtual SDEF  DefaultProc_( _in<UINT> in_message, _in<WPARAM> in_wparam, _in<LPARAM> in_lparam );
  
  //CPL_WIN_COMPONENT_GET_CLASS_NAME( "CPL_WIN_Component" );
  virtual char_cptr    zzf_GetClassNameA() const { return "CPL_WIN_Component"; }
  virtual wchar_t_cptr zzf_GetClassNameW() const { return L"CPL_WIN_Component"; }
  virtual str_cptr     zzf_GetClassName () const { return SwS("CPL_WIN_Component"); }
  int2 zzf_GetTextSize( char_cptr    in_ptr_text, HFONT in_hdl_font = nullptr ) const;
  int2 zzf_GetTextSize( wchar_t_cptr in_ptr_text, HFONT in_hdl_font = nullptr ) const;

public:
  static auto* GetPropertyName_(){ return SwS("CPL_WIN_Component"); }
  BOOL   GetFlag_hWndInstance_() const { return m_flag_win_instance; }

  static Component* GetHandleToPointer( HWND in_hdl_win_this )
  {
    return (Component*)::GetProp( in_hdl_win_this, GetPropertyName_() );
  }
  Component*        GetLinkParent()
  {
    return (Component*)::GetProp( GetParentWindowHandle(), GetPropertyName_() );
  }
  Component const*  GetLinkParent() const
  {
    return (Component*)::GetProp( GetParentWindowHandle(), GetPropertyName_() );
  }

  LRESULT SendParentMessage( UINT in_message, WPARAM in_wparam, LPARAM in_lparam )
  {
    Component* ptr_comp_parent = GetLinkParent();
    if( ptr_comp_parent  &&  ptr_comp_parent->GetEventMode() != eEventMode::Throw )
    {
      return 0;
    }
    return ::SendMessage( GetParentWindowHandle(), in_message, in_wparam, in_lparam );
  } // 親へメッセージを送る
  
  LRESULT PostParentMessage( UINT in_message, WPARAM in_wparam, LPARAM in_lparam )
  {
    Component* ptr_comp_parent = GetLinkParent();
    if( ptr_comp_parent  &&  ptr_comp_parent->GetEventMode() != eEventMode::Throw )
    {
      return 0;
    }
    return ::PostMessage( GetParentWindowHandle(), in_message, in_wparam, in_lparam );
  } // 親へメッセージを送る（Postバージョン）


  virtual td_Coord2  GetWindowPos() const;
  virtual td_Coord2  GetWindowSize() const;
  virtual void       GetWindowRect
                      ( rout<Rect> out_rect
                      , _in <bool> in_flag_parent_mapping = true ) const;
  virtual td_Coord2  GetClientSize() const;
  virtual void       GetClientRect( rout<Rect> out_rect ) const
  {
    ::GetClientRect( m_hdl_window, &out_rect );
  }

  /// @brief ウィンドウハンドルの取得
  /// @return ウィンドウハンドルを返します。
  virtual HWND       GetWindowHandle      () const { return m_hdl_window; }
  /// @brief 親ウィンドウハンドルの取得
  /// @return 親のウィンドウハンドルを返します。
  virtual HWND       GetParentWindowHandle() const { return m_hdl_win_parent; }
  /// @brief ウィンドウスタイルの取得
  /// @return ウィンドウスタイルを返します。
  virtual LONG_PTR   GetStyle    () const { return GetWindowLongPtr( m_hdl_window, GWL_STYLE );   }
  /// @brief ウィンドウ拡張スタイルの取得
  /// @return ウィンドウの拡張スタイルを返します。
  virtual LONG_PTR   GetExStyle  () const { return GetWindowLongPtr( m_hdl_window, GWL_EXSTYLE ); }
  /// @brief IDの取得
  /// @return 関連付けられているIDを返します。
  virtual int        GetID       () const { return (int)GetWindowLongPtr( m_hdl_window, GWL_ID ); }
  /// @brief イベントモードの取得
  /// @return イベントモードを返します。\n詳しくはeEventModeを参照してください。
  virtual int        GetEventMode() const { return m_event_mode; }
  /// @brief タイトル取得
  /// @param[in] out_ptr_str : 取得用の文字列バッファアドレスを指定します。
  /// @param[in] in_length   : バッファ長(サイズ/sizeof(１文字))を指定します。
  /// @return なし。
  virtual void       GetTitle( pout<char> out_ptr_str, _in<int> in_length ) const
  {
    ::GetWindowTextA( m_hdl_window, out_ptr_str, in_length );
  }
  /// @copydoc GetTitle(pout<char>,_in<int>)const
  virtual void       GetTitle( pout<wchar_t> out_ptr_str, _in<int> in_length ) const
  {
    ::GetWindowTextW( m_hdl_window, out_ptr_str, in_length );
  }
  /// @brief タイトル取得
  /// @param[in] out_title : 取得用の文字列オブジェクトを指定します。
  /// @return なし。
  template<class T_String>
  void GetTitle( rout<T_String> out_title ) const
  {
    typename std::remove_reference<decltype(out_title[0])>::type tmp_str[1024] = {};
    GetTitle( tmp_str, CPL_ARRAY_NUM(tmp_str) );
    out_title = tmp_str;
  }
  virtual COLORREF   GetBgColor() const;
  /// @brief フォントオブジェクトの取得
  /// @return フォントオブジェクトのハンドルを返します。
  virtual HFONT      GetFont() const
  {
    return reinterpret_cast<HFONT>(SendMessage( m_hdl_window, WM_GETFONT, 0, 0 ));
  }
  /// @brief ユーザーIDの取得
  /// @return ユーザーIDを返します。
  virtual cref<std::string>
                     GetUserID() const { return m_user_ID; }
  /// @brief 表示フラグの取得
  /// @retval true  : 表示
  /// @retval false : 非表示
  virtual BOOL       IsVisible() const { return ::IsWindowVisible( m_hdl_window ); }
  /// @brief 有効・無効状態フラグの取得
  /// @retval true  : 有効
  /// @retval false : 無効
  virtual BOOL       IsEnable() const { return ::IsWindowEnabled( m_hdl_window ); }
  virtual BOOL       IsChild( _in<HWND> in_hdl_child ) const;
  virtual BOOL       IsChild( pin<Component> in_ptr_comp_child ) const;
  virtual BOOL       IsParent( _in<HWND> in_hdl_parent ) const;
  virtual BOOL       IsParent( pin<Component> in_ptr_comp_parent ) const;

  virtual void       SetWindowSize   ( _in<td_Coord2> in_size, _in<bool> in_flag_redraw = true, _in<bool> in_flag_client_size = false );
  virtual void       SetWindowPos    ( _in<td_Coord2> in_pos, _in<bool> in_flag_redraw = true );
  virtual void       SetWindowRect   ( _in<td_Coord2> in_pos, _in<td_Coord2> in_size, _in<bool> in_flag_client_size = false );
  virtual void       SetWindowRect   ( _in<Rect> in_rect, _in<bool> in_flag_client_size = false, _in<int> in_flag_rect_factor = eRectFlag::All );
  virtual void       SetDefaultCursor( _in<HCURSOR> in_hdl_cursor );//{ wcex.hCursor = _cursor; }
  virtual void       SetBgColor      ( _in<COLORREF> rgb = -1, _in<HBRUSH> hbrBackground = (HBRUSH)(COLOR_BTNFACE+1) );
  virtual void       SetWindowStyle  ( _in<LONG_PTR> in_win_style ){ ::SetWindowLongPtr( m_hdl_window, GWL_STYLE, in_win_style ); }
  virtual void       SetFont         ( _in<HFONT> in_hdl_font );
  virtual void       SetFont         ( _in<DrawFont> in_font );
  virtual void       SetToolTip      ( _in<str_ptr> in_ptr_str );

  /// @brief 状態設定
  /// @param[in] in_flag_enable : 表示状態を指定します。\n
  ///   : true : 表示します。\n
  ///   : false : 非表示にします。
  /// @return なし。
  virtual void       SetEnable( _in<bool> in_flag_enable )
  {
    ::EnableWindow( m_hdl_window, in_flag_enable );
  }
  /// @brief タイトルの設定
  /// @param[in] in_title : タイトルに設定する文字列を指定します。
  /// @return なし。
  virtual void       SetTitle( pin<char> in_title )
  {
    ::SetWindowTextA( m_hdl_window, in_title );
  }
  /// @copydoc SetTitle(pin<char>)
  virtual void       SetTitle( pin<wchar_t> in_title )
  {
    ::SetWindowTextW( m_hdl_window, in_title );
  }
  /// @copydoc SetTitle(pin<char>)
  template<class T_String>
  void SetTitle( cref<T_String> in_title )
  {
    SetTitle( &in_title[0] );
  }
  /// @brief 自身の変更メッセージの親への通知設定
  /// @param[in] in_flag_child_resize
  ///   : true  - 親へ通知します。\n
  ///   : false - 親へ通知しません。
  virtual void       SetSendChildResize( _in<bool> in_flag_child_resize )
  {
    m_flag_child_size = (in_flag_child_resize != false);
  }
  virtual void       SetParent( _in<HWND> in_hdl_win_parent );
  virtual void       SetParent( pin<Component> in_ptr_win_parent );
  /// @brief イベントモードの設定
  /// @param[in] in_flag_event_mode
  ///   : イベントモードを指定します。\n
  ///   : 詳しくはeEventModeを参照してください。
  /// @return なし。
  virtual void       SetEventMode( _in<eEventMode> in_flag_event_mode )
  {
    m_event_mode = in_flag_event_mode;
  }
  /// @brief ユーザーIDの設定
  /// @param[in] in_user_ID : ユーザーIDを文字列で指定します。
  /// @return なし。
  virtual void       SetUserID( _in<std::string> in_user_ID )
  {
    m_user_ID = in_user_ID;
  }

  virtual void       Destroy();
  virtual void       ReleaseTooltip();
  virtual void       Show( _in<bool> in_flag_view ) const;
  virtual void       Update( _in<bool> in_flag_redraw = true ) const;
  virtual void       SetReferenceWndHandle( _in<HWND> in_hdl_window );

  virtual bool
    Create
      ( _in<HWND     > in_hdl_win_parent
      , _in<td_Coord2> in_pos  = kPOS_DEFAULT
      , _in<td_Coord2> in_size = kSIZE_DEFAULT
      );
  virtual Component*
    CreateClone
      ( _in<HWND> in_hdl_win_parent
      , _in<int > in_offs_x
      , _in<int > in_offs_y
      ) const;
  
           Component( U8 in_event_mask = false );
  virtual ~Component();

  
  virtual void MakeTag( rout<TBTag> out_tag, _in<U64> in_types );
  virtual void LoadTag( _in<TBTag> in_tag, _in<U64> in_types );
  virtual void On_LoadTagItem( _in<TBTag> in_tag ){};

  // _____________________________________________________________________________
  /// @brief コンポーネントクラス　Pimpl実装用
  ///
  // *****************************************************************************
  class Binder
    : public BaseComponent::Binder
  {
  private:
    Component*       getEntity()       { return dynamic_cast<Component*>(&*this->impl); }
    Component const* getEntity() const { return dynamic_cast<Component const*>(&*this->impl); }

  public:
    static auto* GetPropertyName_(){ return Component::GetPropertyName_(); }
    BOOL GetFlag_hWndInstance_(){ return getEntity()->GetFlag_hWndInstance_(); }

    Component* GetLinkParent()
    {
      return getEntity()->GetLinkParent();
    }

    LRESULT SendParentMessage( UINT in_message, WPARAM in_wparam, LPARAM in_lparam )
    {
      return getEntity()->SendParentMessage( in_message, in_wparam, in_lparam );
    } // 親へメッセージを送る

    td_Coord2  GetWindowPos         () const { return getEntity()->GetWindowPos();  }
    td_Coord2  GetWindowSize        () const { return getEntity()->GetWindowSize(); }
    void       GetWindowRect        ( rout<Rect> out_rect, bool in_flag_parent_mapping = true ) const { getEntity()->GetWindowRect( out_rect, in_flag_parent_mapping ); }
    td_Coord2  GetClientSize        ()                                      const { return getEntity()->GetClientSize();           }
    void       GetClientRect        ( rout<Rect> out_rect )                 const {        getEntity()->GetClientRect( out_rect ); }
    HWND       GetWindowHandle      ()                                      const { return getEntity()->GetWindowHandle();         }
    HWND       GetParentWindowHandle()                                      const { return getEntity()->GetParentWindowHandle();   }
    LONG_PTR   GetStyle             ()                                      const { return getEntity()->GetStyle();                }
    LONG_PTR   GetExStyle           ()                                      const { return getEntity()->GetExStyle();              }
    int        GetID                ()                                      const { return getEntity()->GetID();                   }
    int        GetEventMode         ()                                      const { return getEntity()->GetEventMode();            }
    void       GetTitle             ( pout<char   > out_ptr_str, _in<int> in_size ) const { getEntity()->GetTitle( out_ptr_str, in_size ); }
    void       GetTitle             ( pout<wchar_t> out_ptr_str, _in<int> in_size ) const { getEntity()->GetTitle( out_ptr_str, in_size ); }
    template<class T_String>
    void       GetTitle( rout<T_String> out_title ) const
    {
      getEntity()->GetTitle( out_title );
    }
    COLORREF   GetBgColor() const { return getEntity()->GetBgColor(); }
    HFONT      GetFont   () const { return getEntity()->GetFont();    }
    BOOL       IsVisible () const { return getEntity()->IsVisible();  }
    BOOL       IsEnable  () const { return getEntity()->IsEnable();   }
    BOOL       IsChild   ( _in<HWND>      in_hdl_child      ) const { return getEntity()->IsChild( in_hdl_child ); }
    BOOL       IsChild   ( pin<Component> in_ptr_comp_child ) const { return getEntity()->IsChild( in_ptr_comp_child ); }
    BOOL       IsParent  ( _in<HWND>      in_hdl_parent      ) const { return getEntity()->IsParent( in_hdl_parent ); }
    BOOL       IsParent  ( pin<Component> in_ptr_comp_parent ) const { return getEntity()->IsParent( in_ptr_comp_parent ); }
    
    void
      SetWindowSize
        ( _in<td_Coord2> in_size
        , _in<bool     > in_flag_redraw = true
        , _in<bool     > in_flag_client_size = false
        )
    {
      getEntity()->SetWindowSize( in_size, in_flag_redraw, in_flag_client_size );
    }
    void
      SetWindowPos
        ( _in<td_Coord2> in_pos
        , _in<bool     > in_flag_redraw = true
        )
    {
      getEntity()->SetWindowPos( in_pos, in_flag_redraw );
    }
    void
      SetWindowRect
        ( _in<td_Coord2> in_pos
        , _in<td_Coord2> in_size
        , _in<bool     > in_flag_client_size = false
        )
    {
      getEntity()->SetWindowRect( in_pos, in_size, in_flag_client_size );
    }
    void
      SetWindowRect
        ( _in<Rect> in_rect
        , _in<bool> in_flag_client_size = false
        , _in<int> in_fRectFactor = Component::eRectFlag::All
        )
    {
      getEntity()->SetWindowRect( in_rect, in_flag_client_size, in_fRectFactor );
    }
    void       SetDefaultCursor( _in<HCURSOR> in_hdl_cursor ){ getEntity()->SetDefaultCursor( in_hdl_cursor ); }
    void       SetBgColor      ( _in<COLORREF> rgb = -1, _in<HBRUSH> hbrBackground = (HBRUSH)(COLOR_BTNFACE+1) )
    {
      getEntity()->SetBgColor( rgb, hbrBackground );
    }
    void       SetWindowStyle    ( _in<LONG_PTR> in_win_style ){ getEntity()->SetWindowStyle( in_win_style );             }
    void       SetFont           ( _in<HFONT>    in_hdl_font  ){ getEntity()->SetFont( in_hdl_font );                     }
    void       SetFont           ( _in<DrawFont> in_ptr_font  ){ getEntity()->SetFont( in_ptr_font );                     }
    void       SetToolTip        ( _in<str_ptr>  in_ptr_str   ){ getEntity()->SetToolTip( in_ptr_str );                   }
    void       SetEnable         ( _in<bool> in_flag_enable ){ getEntity()->SetEnable( in_flag_enable );                }
    void       SetTitle          ( pin<char   > in_title ){ getEntity()->SetTitle( in_title );                       }
    void       SetTitle          ( pin<wchar_t> in_title ){ getEntity()->SetTitle( in_title );                       }
    template<class T_String>
    void       SetTitle          ( cref<T_String> in_title ){ getEntity()->SetTitle( in_title );                       }
    void       SetSendChildResize( _in<bool> in_flag_child_resize ){ getEntity()->SetSendChildResize( in_flag_child_resize ); }
    void       SetEventMode      ( _in<Component::eEventMode> in_flag_event_mode )  { getEntity()->SetEventMode( in_flag_event_mode );         }
    
    void       Destroy       (){ getEntity()->Destroy();        }
    void       ReleaseTooltip(){ getEntity()->ReleaseTooltip(); }
    void       Show          ( _in<bool> in_flag_view )         { getEntity()->Show( in_flag_view );     }
    void       Update        ( _in<bool> in_flag_redraw = true ){ getEntity()->Update( in_flag_redraw ); }

    void       SetReferenceWndHandle( _in<HWND> in_hdl_window ){ getEntity()->SetReferenceWndHandle( in_hdl_window ); }

    bool       Create( _in<HWND     > in_hdl_win_parent
                     , _in<td_Coord2> in_pos
                     , _in<td_Coord2> in_size )
    {
      return getEntity()->Create( in_hdl_win_parent, in_pos, in_size );
    }
    virtual Component*
      CreateClone
        ( _in<HWND> in_hdl_win_parent
        , _in<int > in_offs_x
        , _in<int > in_offs_y
        ) const
    {
      return getEntity()->CreateClone( in_hdl_win_parent, in_offs_x, in_offs_y );
    }
    
    //
    Binder( U8 in_event_mask = false )
      : BaseComponent::Binder( CPL_NEW(Component)( in_event_mask ) )
    {}
  protected:
    // 継承用
    Binder( pio<Component> in_ptr_comp )
      : BaseComponent::Binder( in_ptr_comp )
    {}
    Binder( _in<sdptr<Component>> in_sp_component )
      : BaseComponent::Binder( in_sp_component )
    {}
  };

};


} // namespace WIN
} // namespace CPL
