IM 开源项目 客户端UI框架 Direct UI
2012-01-06 12:01
405 查看
客户端
目前客户端的实现,不少大公司采用了较为新潮的Direct UI技术,本项目中也考虑使用Direct UI,但可惜微软并没有提供可使用的Direct UI 封装,因此我们自己设计实现Direct UI,并在此基础上实现客户端UI部分的功能。
Direct UI 框架的实现并不复杂,就是繁琐,如抽象窗口,控件自绘制,设计完成消息循环与映射,资源管理...
CWinWnd: 注册创建主窗口,也是唯一具备Win 窗口句柄的窗口,其他一切控件子窗口,均绘制在此窗口上,维持逻辑存在。
具体实现如下:
头文件:
实现文件:
窗体控件构建:CUIBuilder 解析配置文件,构建出窗口上的个个控件窗口(类似于MFC的 Dialog)
头文件:
实现文件:
附窗体构建后的图:
后续继续补充 消息循环映射处理, 控件构建,渲染等内容。
目前客户端的实现,不少大公司采用了较为新潮的Direct UI技术,本项目中也考虑使用Direct UI,但可惜微软并没有提供可使用的Direct UI 封装,因此我们自己设计实现Direct UI,并在此基础上实现客户端UI部分的功能。
Direct UI 框架的实现并不复杂,就是繁琐,如抽象窗口,控件自绘制,设计完成消息循环与映射,资源管理...
CWinWnd: 注册创建主窗口,也是唯一具备Win 窗口句柄的窗口,其他一切控件子窗口,均绘制在此窗口上,维持逻辑存在。
具体实现如下:
头文件:
#ifndef H_WINWND_H #define H_WINWND_H #include "CTypeDef.h" #include "UIStructDef.h" #include "UIMSGMgr.h" #include <map> class CWinWnd : public IWinWnd { public: CWinWnd(void); virtual ~CWinWnd(void); BOOL RegWinClass( HINSTANCE hInstance = NULL); // 注册窗口类 HWND Create(HWND ahwndParent, LPCTSTR apstrName, DWORD adwStyle, DWORD adwExStyle, // 创建窗口 const RECT arc, HMENU ahMenu = NULL, HINSTANCE hInstance = NULL); HWND Create(HWND ahwndParent, LPCTSTR apstrName, DWORD adwStyle, DWORD adwExStyle, // 创建窗口 int ax = CW_USEDEFAULT, int ay = CW_USEDEFAULT, int acx = CW_USEDEFAULT, int acy = CW_USEDEFAULT, HMENU ahMenu = NULL, HINSTANCE hInstance = NULL); void SetWndInfo(HINSTANCE ahInstance, ULong aulStyle,ULong aulStyleEx, int aiXVertex, int aiYVertex, int aiWeigth, int aiHeigth, HMENU ahMenu = NULL); // 设置大小信息 void ShowWindow(BOOL bShow /*= true*/, BOOL bTakeFocus /*= false*/); // 显示窗口 static LRESULT CALLBACK __WndProc(HWND ahWnd, UINT auMsg, WPARAM awParam, LPARAM alParam); // 消息回调 HWND Subclass(HWND hWnd); // 子类化 void Unsubclass(void); // 反子类化 void SetIcon(UINT nRes); // 设置图标 void CenterWindow(void); // 居中 void Close(UINT nRet); // 关闭 UINT ShowModal(void); // ??? //protected: protected: virtual LRESULT HandleMessage(UINT auMsg, WPARAM awParam, LPARAM alParam); // 消息处理 virtual void OnFinalMessage(HWND ahWnd); // 退出 virtual void SetWinClassName(TCHAR* apClassName); // 设置注册类名称 virtual LPCTSTR GetWinClassName(void) const; // 获得注册类名称 virtual void SetWinName(TCHAR* apClassName); // 设置窗口名称 virtual LPCTSTR GetWinName(void) const; // 获得窗口名称 virtual void SetXmlFile(TCHAR* apXmlFile); // 设置Xml文件名称 virtual LPCTSTR GetXmlFile(void) const; // 获得Xml文件名称 protected: HWND m_hWnd; // 窗口句柄 WNDPROC m_OldWndProc; // 旧的消息回调 bool m_bSubclassed; // 子窗口 TCHAR m_lszRegClassName[MAX_PATH+1]; // 窗口注册类名称 TCHAR m_lszWndName[MAX_PATH+1]; // 窗口名称 TCHAR m_szXmlFile[MAX_PATH+1]; // 界面配置文件名称 TCHAR m_lszInstancePath[MAX_PATH+1]; TCHAR m_lszCurPath[MAX_PATH+1]; CMSGMgr m_oMsgMgr; // 对象消息处理 CUIBaseCtrl* m_pRootCtrl; // 根控件 CUICache* m_pUICache; // 界面资源缓存 int m_iXVertex; int m_iYVertex; int m_iWeigth; int m_iHeigth; HMENU m_hMenu; ULong m_ulStyle; ULong m_ulStyleEx; HINSTANCE m_hInstance; }; #endif//H_WINWND_H
实现文件:
#include "StdAfx.h" #include "UIWinWnd.h" #include <afxwin.h> CWinWnd::CWinWnd(void) : m_hWnd(NULL) , m_OldWndProc(::DefWindowProc) , m_iXVertex(CW_USEDEFAULT) , m_iYVertex(CW_USEDEFAULT) , m_iWeigth(CW_USEDEFAULT) , m_iHeigth(CW_USEDEFAULT) , m_hMenu(NULL) , m_hInstance(NULL) , m_pUICache(NULL) { memset(m_lszRegClassName, 0, sizeof(TCHAR)*(MAX_PATH+1)); memset(m_lszInstancePath, 0, sizeof(TCHAR)*(MAX_PATH+1)); memset(m_lszCurPath, 0, sizeof(TCHAR)*(MAX_PATH+1)); memset(m_lszWndName, 0, sizeof(TCHAR)*(MAX_PATH+1)); memset(m_szXmlFile, 0, sizeof(TCHAR)*(MAX_PATH+1)); m_pUICache = CUICache::GetSigoObj(); } CWinWnd::~CWinWnd(void) { } LRESULT CALLBACK CWinWnd::__WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { CWinWnd* pThis = NULL; if( uMsg == WM_NCCREATE ) { LPCREATESTRUCT lpcs = reinterpret_cast<LPCREATESTRUCT>(lParam); pThis = static_cast<CWinWnd*>(lpcs->lpCreateParams); if (pThis) { pThis->m_hWnd = hWnd; ::SetWindowLongPtr(hWnd, GWLP_USERDATA, reinterpret_cast<LPARAM>(pThis)); } } else { pThis = reinterpret_cast<CWinWnd*>(::GetWindowLongPtr(hWnd, GWLP_USERDATA)); if( uMsg == WM_NCDESTROY && pThis != NULL ) { LRESULT lRes = ::CallWindowProc(pThis->m_OldWndProc, hWnd, uMsg, wParam, lParam); ::SetWindowLongPtr(pThis->m_hWnd, GWLP_USERDATA, 0L); if( pThis->m_bSubclassed ) { // pThis->Unsubclass(); } pThis->m_hWnd = NULL; pThis->OnFinalMessage(hWnd); return lRes; } } if( pThis != NULL ) return pThis->HandleMessage(uMsg, wParam, lParam); else return ::DefWindowProc(hWnd, uMsg, wParam, lParam); } LRESULT CWinWnd::HandleMessage(UINT uMsg, WPARAM wParam, LPARAM lParam) { return ::CallWindowProc(m_OldWndProc, m_hWnd, uMsg, wParam, lParam); } void CWinWnd::OnFinalMessage(HWND /*hWnd*/) { } // 注册窗口类 BOOL CWinWnd::RegWinClass(HINSTANCE hInstance) { m_hInstance = hInstance; if (!m_pUICache) return FALSE; m_pUICache->SetInstance(hInstance); // 初始化应用程序路径 m_pUICache->GetInstancePath(m_lszInstancePath); m_pUICache->SetResPackPath(m_lszInstancePath); m_pUICache->GetCurrentPath(m_lszCurPath); WNDCLASS wc = {0}; wc.style = CS_DBLCLKS; wc.cbClsExtra = 0; wc.cbWndExtra = 0; wc.hIcon = NULL; wc.lpfnWndProc = CWinWnd::__WndProc; wc.hInstance = hInstance; wc.hInstance = NULL; wc.hCursor = ::LoadCursor(NULL, IDC_ARROW); wc.hbrBackground = NULL; wc.lpszMenuName = NULL; wc.lpszClassName = GetWinClassName(); ATOM ret = ::RegisterClass(&wc); ASSERT((NULL != ret) || (::GetLastError()==ERROR_CLASS_ALREADY_EXISTS)); return (ret != NULL) || ::GetLastError() == ERROR_CLASS_ALREADY_EXISTS; } HWND CWinWnd::Create(HWND ahwndParent, LPCTSTR apstrName, DWORD adwStyle, DWORD adwExStyle, const RECT arc, HMENU ahMenu, HINSTANCE hInstance) { return Create(ahwndParent, apstrName, adwStyle, adwExStyle, arc.left, arc.top, arc.right - arc.left, arc.bottom - arc.top, ahMenu, hInstance); } HWND CWinWnd::Create(HWND ahwndParent, LPCTSTR apstrName, DWORD adwStyle, DWORD adwExStyle, int ax, int ay, int acx, int acy, HMENU ahMenu, HINSTANCE ahInstance) { if (GetWinClassName() && RegWinClass(ahInstance)) { m_hWnd = ::CreateWindowEx(adwExStyle, GetWinClassName(), apstrName, adwStyle, ax, ay, acx, acy, ahwndParent, ahMenu, ahInstance, this); ASSERT(m_hWnd!=NULL); return m_hWnd; } return NULL; } void CWinWnd::ShowWindow(BOOL bShow /*= true*/, BOOL bTakeFocus /*= false*/) { ASSERT(::IsWindow(m_hWnd)); if( !::IsWindow(m_hWnd) ) return; ::ShowWindow(m_hWnd, bShow ? (bTakeFocus ? SW_SHOWNORMAL : SW_SHOWNOACTIVATE) : SW_HIDE); } // 加载初始控件 void CWinWnd::SetWndInfo(HINSTANCE ahInstance, ULong aulStyle,ULong aulStyleEx, int aiXVertex, int aiYVertex, int aiWeigth, int aiHeigth, HMENU ahMenu) { m_ulStyle = aulStyle; m_ulStyleEx = aulStyleEx; m_iXVertex = aiXVertex; m_iYVertex = aiYVertex; m_iWeigth = aiWeigth; m_iHeigth = aiHeigth; m_hMenu = ahMenu; m_hInstance = ahInstance; } // 设置注册类名称 void CWinWnd::SetWinClassName(TCHAR* apClassName) { if (!apClassName) return; #ifdef UNICODE memcpy(m_lszRegClassName, apClassName, sizeof(TCHAR)*wcslen(apClassName)); #else memcpy(m_lszRegClassName, apClassName, strlen(apClassName)); #endif } // 获得注册类名称 LPCTSTR CWinWnd::GetWinClassName(void) const { return m_lszRegClassName; } // 设置窗口名称 void CWinWnd::SetWinName(TCHAR* apWndName) { if (!apWndName) return; #ifdef UNICODE memcpy(m_lszWndName, apWndName, sizeof(TCHAR)*wcslen(apWndName)); #else memcpy(m_lszWndName, apWndName, strlen(apWndName)); #endif } // 获得Xml文件名称 LPCTSTR CWinWnd::GetWinName(void) const { return m_lszWndName; } // 设置Xml文件名称 void CWinWnd::SetXmlFile(TCHAR* apXmlFile) { if (!apXmlFile) return; #ifdef UNICODE memcpy(m_szXmlFile, apXmlFile, sizeof(TCHAR)*wcslen(apXmlFile)); #else memcpy(m_szXmlFile, apXmlFile, strlen(apXmlFile)); #endif } // 获得窗口名称 LPCTSTR CWinWnd::GetXmlFile(void) const { return m_szXmlFile; } HWND CWinWnd::Subclass(HWND hWnd) { ASSERT(::IsWindow(hWnd)); ASSERT(m_hWnd==NULL); m_OldWndProc = SubclassWindow(hWnd, __WndProc); if( m_OldWndProc == NULL ) return NULL; m_bSubclassed = true; m_hWnd = hWnd; return m_hWnd; } void CWinWnd::Unsubclass() { ASSERT(::IsWindow(m_hWnd)); if( !::IsWindow(m_hWnd) ) return; if( !m_bSubclassed ) return; SubclassWindow(m_hWnd, m_OldWndProc); m_OldWndProc = ::DefWindowProc; m_bSubclassed = false; } UINT CWinWnd::ShowModal() { ASSERT(::IsWindow(m_hWnd)); UINT nRet = 0; HWND hWndParent = GetWindowOwner(m_hWnd); ::ShowWindow(m_hWnd, SW_SHOWNORMAL); ::EnableWindow(hWndParent, FALSE); MSG msg = { 0 }; while( ::IsWindow(m_hWnd) && ::GetMessage(&msg, NULL, 0, 0) ) { if( msg.message == WM_CLOSE && msg.hwnd == m_hWnd ) { nRet = msg.wParam; ::EnableWindow(hWndParent, TRUE); ::SetFocus(hWndParent); } //if( !CPaintManagerUI::TranslateMessage(&msg) ) { ::TranslateMessage(&msg); ::DispatchMessage(&msg); } if( msg.message == WM_QUIT ) break; } ::EnableWindow(hWndParent, TRUE); ::SetFocus(hWndParent); if( msg.message == WM_QUIT ) ::PostQuitMessage(msg.wParam); return nRet; } void CWinWnd::Close(UINT nRet) { ASSERT(::IsWindow(m_hWnd)); if( !::IsWindow(m_hWnd) ) return; ::PostMessage(m_hWnd, WM_CLOSE, (WPARAM)nRet, 0L); } void CWinWnd::CenterWindow() { ASSERT(::IsWindow(m_hWnd)); ASSERT((GetWindowStyle(m_hWnd)&WS_CHILD)==0); RECT rcDlg = { 0 }; ::GetClientRect(m_hWnd, &rcDlg); RECT rcArea = { 0 }; RECT rcCenter = { 0 }; HWND hWndParent = ::GetParent(m_hWnd); HWND hWndCenter = ::GetWindowOwner(m_hWnd); ::SystemParametersInfo(SPI_GETWORKAREA, NULL, &rcArea, NULL); if( hWndCenter == NULL ) rcCenter = rcArea; else ::GetClientRect(hWndCenter, &rcCenter); int DlgWidth = rcDlg.right - rcDlg.left; int DlgHeight = rcDlg.bottom - rcDlg.top; // Find dialog's upper left based on rcCenter int xLeft = (rcCenter.left + rcCenter.right) / 2 - DlgWidth / 2; int yTop = (rcCenter.top + rcCenter.bottom) / 2 - DlgHeight / 2; // The dialog is outside the screen, move it inside if( xLeft < rcArea.left ) xLeft = rcArea.left; else if( xLeft + DlgWidth > rcArea.right ) xLeft = rcArea.right - DlgWidth; if( yTop < rcArea.top ) yTop = rcArea.top; else if( yTop + DlgHeight > rcArea.bottom ) yTop = rcArea.bottom - DlgHeight; ::SetWindowPos(m_hWnd, NULL, xLeft, yTop, -1, -1, SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE); } void CWinWnd::SetIcon(UINT nRes) { HICON hIcon = (HICON)::LoadImage(m_hInstance, MAKEINTRESOURCE(nRes), IMAGE_ICON, ::GetSystemMetrics(SM_CXICON), ::GetSystemMetrics(SM_CYICON), LR_DEFAULTCOLOR); ASSERT(hIcon); ::SendMessage(m_hWnd, WM_SETICON, (WPARAM) TRUE, (LPARAM) hIcon); hIcon = (HICON)::LoadImage(m_hInstance, MAKEINTRESOURCE(nRes), IMAGE_ICON, ::GetSystemMetrics(SM_CXSMICON), ::GetSystemMetrics(SM_CYSMICON), LR_DEFAULTCOLOR); ASSERT(hIcon); ::SendMessage(m_hWnd, WM_SETICON, (WPARAM) FALSE, (LPARAM) hIcon); }
窗体控件构建:CUIBuilder 解析配置文件,构建出窗口上的个个控件窗口(类似于MFC的 Dialog)
头文件:
class CUIBuilder : public CWinWnd { public: CUIBuilder(void); virtual ~CUIBuilder(void); public: BOOL InitUIBuilder( TCHAR* apClass, TCHAR* apZipPack, TCHAR* apXmlFile, TCHAR* apWndName, HWND ahwndParent, DWORD adwStyle, DWORD adwExStyle, int ax, int ay, int acx, int acy, HMENU ahMenu, HINSTANCE ahInstance); BOOL DoModule(void); private: CUIBaseCtrl* LoadCtrls(TCHAR* apXmlFileName); LRESULT HandleMessage(UINT uMsg, WPARAM wParam, LPARAM lParam); };
实现文件:
#include "StdAfx.h" #include "UIBuilder.h" CUIBuilder::CUIBuilder(void) { } CUIBuilder::~CUIBuilder(void) { } CUIBaseCtrl* CUIBuilder::LoadCtrls(TCHAR* apXmlFileName) { // 范例代码 这里在窗体上创建了三个逻辑子窗口 //【区域控件】 CUIBaseCtrl* lAreaCtrl = new CUIAreaCtrl(m_pUICache, m_hWnd); RECT loRect; ::GetClientRect(m_hWnd, &loRect); lAreaCtrl->SetRect(loRect); lAreaCtrl->SetBkColor(0x01FFFFFF); lAreaCtrl->SetCtrlID(1); //【子按钮控件】 CUIBaseCtrl* lpCtrl = new CUIButton(m_pUICache, m_hWnd); lpCtrl->SetRect(0,0, 500, 500); lpCtrl->SetBkColor(0x02FFFFFF); lpCtrl->SetBkImage(_T("file=\"SysBk.png\" source=\"0,0,0,0\" corner=\"10,10,10,10\"")); lpCtrl->SetCtrlID(2); lAreaCtrl->AddChildCtrl(lpCtrl); //【嵌套子按钮控件】 CUIBaseCtrl* lpCtrlBt = new CUIButton(m_pUICache, m_hWnd); lpCtrlBt->SetRect(10,10, 200, 200); lpCtrlBt->SetBkColor(0x02FFFFFF); lpCtrlBt->SetCtrlID(3); lpCtrl->AddChildCtrl(lpCtrlBt); return lAreaCtrl; } LRESULT CUIBuilder::HandleMessage(UINT uMsg, WPARAM wParam, LPARAM lParam) { LRESULT lRes = 0; BOOL bHandled = FALSE; if( bHandled ) return lRes; if(!m_oMsgMgr.MessageHandler(uMsg, wParam, lParam, lRes) ) return lRes; return CWinWnd::HandleMessage(uMsg, wParam, lParam); } BOOL CUIBuilder::InitUIBuilder( TCHAR* apClass, TCHAR* apZipPack,TCHAR* apXmlFile, TCHAR* apWndName, HWND ahwndParent, DWORD adwStyle, DWORD adwExStyle, int ax, int ay, int acx, int acy, HMENU ahMenu, HINSTANCE ahInstance) { // 设置资产类名称 SetWinClassName(apClass); // 设置窗口名称 SetWinName(apWndName); // 设置界面配置文件名称 SetXmlFile(apXmlFile); // 设置窗口信息大小 SetWndInfo(ahInstance, adwStyle, adwExStyle, ax, ay, acx, acy,ahMenu); // 设置资源文件压缩包路径 if (m_pUICache) m_pUICache->SetResPackName(apZipPack); return TRUE; } BOOL CUIBuilder::DoModule(void) { // 创建窗口 if (!Create(NULL, m_lszWndName, m_ulStyle, m_ulStyleEx , m_iXVertex, m_iYVertex, m_iWeigth, m_iHeigth, m_hMenu, m_hInstance)) return FALSE; // 加载控件配置文件创建控件 m_pRootCtrl = LoadCtrls(m_szXmlFile); if (!m_pRootCtrl) return FALSE; m_oMsgMgr.InitMsgMgr(m_hWnd, m_pRootCtrl); ShowWindow(TRUE, FALSE); CMSGMgr::MSGLoop(); return TRUE; }
附窗体构建后的图:
后续继续补充 消息循环映射处理, 控件构建,渲染等内容。
相关文章推荐
- IM 开源项目 客户端UI框架 Direct UI(01)
- Android开源项目以及开源框架,各种UI实现效果
- Android开源项目以及开源框架,各种UI实现效果。
- [开源项目]Adium——MAC下IM聚合客户端
- Android酷炫实用的开源框架(UI框架) – Android开发中文站 http://www.androidchina.net/1992.html
- jeecms2012 框架分析 Spring mvc+hibernate+freemarker(开源项目)
- 【开源项目2】Android推送框架 androidpn
- 开源项目之C++远程方法调用框架 RMI for C++
- 几个FTP客户端开源项目
- 【Erlang开源项目】HTTP客户端ibrowse
- Android酷炫实用的开源框架(UI框架)
- iOS开源项目之日志框架CocoaLumberjack
- 开源框架ViewPageIndicator 和 ViewPager 仿网易新闻客户端Tab标签
- 个人开源项目cuteRecorder---录音框架的使用
- React Native开源项目-嘎嘎商城客户端(持续更新中)
- 开源的IM框架--担心
- 开源物联网框架ServerSuperIO(SSIO),项目中实践应用介绍
- Android 开源框架ViewPageIndicator 和 ViewPager 仿网易新闻客户端Tab标签
- Android 开源框架ViewPageIndicator 和 ViewPager 仿网易新闻客户端Tab标签
- 谷歌竟然开源这么神奇的UI框架,不学你就落后了