锚点布局
size
size="width, height"
width height
- full
- 代表高度或者宽度和父窗口的客户区大小相等
- -1
- 根据窗口内容自动计算窗口大小
- int
pos
- 代表参考父窗口的中心
%
- 代表在父窗口的百分比
[
- 用于X时,参考前一兄弟窗口的right,用于Y时参考前一兄弟窗口的bottom
]
- 用于X时,参考后一兄弟的left,用于Y时参考后一兄弟的top
{
- 用于X时,参考前一兄弟窗口的left,用于Y时参考前一兄弟窗口的top
}
- 用于X时,参考后一兄弟的right,用于Y时参考后一兄弟的bottom
@
- 指定窗口的大小,只能出现在pos属性的第3,4个值中,用来标识窗口的宽度
- 当后面的值为负时,代表自动计算窗口的宽度或者高度
offset
- offset属性包含两个值,用来代表窗口在通过其它布局属性完成后的偏移量
事件的响应
事件映射表
- 事件映射表是一种编译期形成的静态的映射表,对于在运行期动态创建的控件的事件响应无能为力。
- 从SHostWnd的派生类重载
1 |
virtual BOOL SHostWnd::_HandleEvent(SOUI::EventArgs *pEvt){return FALSE;} |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
//UI控件的事件及响应函数映射表 EVENT_MAP_BEGIN() EVENT_ID_COMMAND(1, OnClose) EVENT_ID_COMMAND(2, OnMaximize) EVENT_ID_COMMAND(3, OnRestore) EVENT_ID_COMMAND(5, OnMinimize) EVENT_NAME_CONTEXTMENU(L"edit_1140",OnEditMenu) EVENT_NAME_COMMAND(L"btn_msgbox",OnBtnMsgBox) EVENT_NAME_COMMAND(L"btnSelectGif",OnBtnSelectGIF) EVENT_NAME_COMMAND(L"btn_menu",OnBtnMenu) EVENT_NAME_COMMAND(L"btn_webkit_go",OnBtnWebkitGo) EVENT_NAME_COMMAND(L"btn_webkit_back",OnBtnWebkitBackward) EVENT_NAME_COMMAND(L"btn_webkit_fore",OnBtnWebkitForeward) EVENT_NAME_COMMAND(L"btn_webkit_refresh",OnBtnWebkitRefresh) EVENT_NAME_COMMAND(L"btn_hidetst",OnBtnHideTest) EVENT_NAME_COMMAND(L"btn_insert_gif",OnBtnInsertGif2RE) EVENT_MAP_END() |
事件订阅
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 |
void CMainDlg::InitListCtrl() { //找到列表控件 SListCtrl *pList=FindChildByName2<SListCtrl>(L"lc_test"); if(pList) { //列表控件的唯一子控件即为表头控件 SWindow *pHeader=pList->GetWindow(GSW_FIRSTCHILD); //向表头控件订阅表明点击事件,并把它和OnListHeaderClick函数相连。 pHeader->GetEventSet()->subscribeEvent(EVT_HEADER_CLICK,Subscriber(&CMainDlg::OnListHeaderClick,this)); //省略列表初始化代码 } } //表头点击事件处理函数 bool CMainDlg::OnListHeaderClick(EventArgs *pEvtBase) { //事件对象强制转换 EventHeaderClick *pEvt =(EventHeaderClick*)pEvtBase; SHeaderCtrl *pHeader=(SHeaderCtrl*)pEvt->sender; //从表头控件获得列表控件对象 SListCtrl *pList= (SListCtrl*)pHeader->GetParent(); //列表数据排序 SHDITEM hditem; hditem.mask=SHDI_ORDER; pHeader->GetItem(pEvt->iItem,&hditem); pList->SortItems(funCmpare,&hditem.iOrder); return true; } |
自定义绘图对象
实现
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 |
/** * @struct ISkinObj * @brief Skin 对象 * * Describe */ class SOUI_EXP ISkinObj : public SObject,public TObjRefImpl2<IObjRef,ISkinObj> { public: ISkinObj() { } virtual ~ISkinObj() { } /** * Draw * @brief 将this绘制到RenderTarget上去 * @param IRenderTarget * pRT -- 绘制用的RenderTarget * @param LPCRECT rcDraw -- 绘制位置 * @param DWORD dwState -- 绘制状态 * @param BYTE byAlpha -- 透明度 * @return void * Describe */ virtual void Draw(IRenderTarget *pRT, LPCRECT rcDraw, DWORD dwState,BYTE byAlpha=0xFF)=0; /** * GetSkinSize * @brief 获得Skin的默认大小 * @return SIZE -- Skin的默认大小 * Describe 派生类应该根据skin的特点实现该接口 */ virtual SIZE GetSkinSize() { SIZE ret = {0, 0}; return ret; } /** * IgnoreState * @brief 查询skin是否有状态信息 * @return BOOL -- true有状态信息 * Describe */ virtual BOOL IgnoreState() { return TRUE; } /** * GetStates * @brief 获得skin对象包含的状态数量 * @return int -- 状态数量 * Describe 默认为1 */ virtual int GetStates() { return 1; } }; |
SOjbect
使得ISkinObj
可以方便的从XML配置文件中初始化TObjRefImpl2<IObjRef,ISkinObj>
则提供引用计数的实现
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 |
namespace SOUI { class SGifFrame { public: CAutoRefPtr<IBitmap> pBmp; int nDelay; }; /** * @class SSkinGif * @brief GIF图片加载及显示对象 * * Describe */ class SSkinGif : public ISkinObj { SOUI_CLASS_NAME(SSkinGif, L"gif") public: SSkinGif():m_nFrames(0),m_iFrame(0),m_pFrames(NULL) { } //初始化GDI+环境,由于这里需要使用GDI+来解码GIF文件格式 static BOOL Gdiplus_Startup(); //退出GDI+环境 static void Gdiplus_Shutdown(); virtual ~SSkinGif() { if(m_pFrames) delete [] m_pFrames; } /** * Draw * @brief 绘制指定帧的GIF图 * @param IRenderTarget * pRT -- 绘制目标 * @param LPCRECT rcDraw -- 绘制范围 * @param DWORD dwState -- 绘制状态,这里被解释为帧号 * @param BYTE byAlpha -- 透明度 * @return void * Describe */ virtual void Draw(IRenderTarget *pRT, LPCRECT rcDraw, DWORD dwState,BYTE byAlpha=0xFF); /** * GetStates * @brief 获得GIF帧数 * @return int -- 帧数 * Describe */ virtual int GetStates(){return m_nFrames;} /** * GetSkinSize * @brief 获得图片大小 * @return SIZE -- 图片大小 * Describe */ virtual SIZE GetSkinSize() { SIZE sz={0}; if(m_nFrames>0 && m_pFrames) { sz=m_pFrames[0].pBmp->Size(); } return sz; } /** * GetFrameDelay * @brief 获得指定帧的显示时间 * @param int iFrame -- 帧号,为-1时代表获得当前帧的延时 * @return long -- 延时时间(*10ms) * Describe */ long GetFrameDelay(int iFrame=-1); /** * ActiveNextFrame * @brief 激活下一帧 * @return void * Describe */ void ActiveNextFrame(); /** * SelectActiveFrame * @brief 激活指定帧 * @param int iFrame -- 帧号 * @return void * Describe */ void SelectActiveFrame(int iFrame); /** * LoadFromFile * @brief 从文件加载GIF * @param LPCTSTR pszFileName -- 文件名 * @return int -- GIF帧数,0-失败 * Describe */ int LoadFromFile(LPCTSTR pszFileName); /** * LoadFromMemory * @brief 从内存加载GIF * @param LPVOID pBits -- 内存地址 * @param size_t szData -- 内存数据长度 * @return int -- GIF帧数,0-失败 * Describe */ int LoadFromMemory(LPVOID pBits,size_t szData); SOUI_ATTRS_BEGIN() ATTR_CUSTOM(L"src",OnAttrSrc) //XML文件中指定的图片资源名,(type:name) SOUI_ATTRS_END() protected: LRESULT OnAttrSrc(const SStringW &strValue,BOOL bLoading); int LoadFromGdipImage(Gdiplus::Bitmap * pImg); int m_nFrames; int m_iFrame; SGifFrame * m_pFrames; }; }//end of name space SOUI |
注册
1 |
theApp->RegisterSkinFactory(TplSkinFactory<SSkinGif>());//注册SkinGif |
使用
1 2 3 4 5 |
<skin> <!--局部skin对象--> <gif name="gif_horse" src="gif:gif_horse"/> <gif name="gif_penguin" src="gif:gif_penguin"/> </skin> |
自定义控件
实现
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 |
namespace SOUI { /** * @class SGifPlayer * @brief GIF图片显示控件 * * Describe */ class SGifPlayer : public SWindow { SOUI_CLASS_NAME(SGifPlayer, L"gifplayer") //定义GIF控件在XM加的标签 public: SGifPlayer(); ~SGifPlayer(); /** * PlayGifFile * @brief 在控件中播放一个GIF图片文件 * @param LPCTSTR pszFileName -- 文件名 * @return BOOL -- true:成功 * Describe */ BOOL PlayGifFile(LPCTSTR pszFileName); protected://SWindow的虚函数 virtual CSize GetDesiredSize(LPRECT pRcContainer); public://属性处理 SOUI_ATTRS_BEGIN() ATTR_CUSTOM(L"skin", OnAttrGif) //为控件提供一个skin属性,用来接收SSkinObj对象的name SOUI_ATTRS_END() protected: HRESULT OnAttrGif(const SStringW & strValue, BOOL bLoading); protected://消息处理,SOUI控件的消息处理和WTL,MFC很相似,采用相似的映射表,相同或者相似的消息映射宏 /** * OnPaint * @brief 窗口绘制消息响应函数 * @param IRenderTarget * pRT -- 绘制目标 * @return void * Describe 注意这里的参数是IRenderTarget *,而不是WTL中使用的HDC,同时消息映射宏也变为MSG_WM_PAINT_EX */ void OnPaint(IRenderTarget *pRT); /** * OnTimer * @brief SOUI窗口的定时器处理函数 * @param char cTimerID -- 定时器ID,范围从0-127。 * @return void * Describe SOUI控件的定时器是Host窗口定时器ID的分解,以方便所有的控件都通过Host获得定时器的分发。 * 注意使用MSG_WM_TIMER_EX来映射该消息。定时器使用SWindow::SetTimer及SWindow::KillTimer来创建及释放。 * 如果该定时器ID范围不能满足要求,可以使用SWindow::SetTimer2来创建。 */ void OnTimer(char cTimerID); /** * OnShowWindow * @brief 处理窗口显示消息 * @param BOOL bShow -- true:显示 * @param UINT nStatus -- 显示原因 * @return void * Describe 参考MSDN的WM_SHOWWINDOW消息 */ void OnShowWindow(BOOL bShow, UINT nStatus); //SOUI控件消息映射表 SOUI_MSG_MAP_BEGIN() MSG_WM_TIMER_EX(OnTimer) //定时器消息 MSG_WM_PAINT_EX(OnPaint) //窗口绘制消息 MSG_WM_SHOWWINDOW(OnShowWindow)//窗口显示状态消息 SOUI_MSG_MAP_END() private: SSkinGif *m_pgif; int m_iCurFrame; }; } |
注册
1 |
theApp->RegisterWndFactory(TplSWindowFactory<SGifPlayer>());//注册GIFPlayer |
使用
1 2 3 |
<gifplayer pos="10,10" skin="gif_horse" name="giftest" cursor="ANI_ARROW"/> <button width="250" height="30" name="btnSelectGif">load gif file</button> <gifplayer pos="10,150" skin="gif_penguin"/> |
本文为原创文章,版权归Aet所有,欢迎分享本文,转载请保留出处!
你可能也喜欢
- ♥ Soui一03/17
- ♥ C++_关于对象的具体初始化顺序11/30
- ♥ Windows 窗口以及渲染相关06/15
- ♥ Windbg关于死锁的简单调试分析总结09/13
- ♥ Spdlog记述:一07/07
- ♥ Windows 核心编程 _ 内核对象:线程同步三07/31