DirectUI实现原理
2015-11-30 05:54
471 查看
一,概念
传统的Windows窗口程序对每一个控件都会创建一个句柄,而DUI技术奖所有控件都绘制在一个窗体上,这些控件的逻辑和绘图方式必须自己进行编写和封装,所以这些控件都是无句柄的。DUI技术的实现步骤和难点:
1,窗口的子类化,截获窗口的消息。
2,封装自己的控件,并将自己的控件绘制到该窗口上。
3,封装窗口的消息,并分发到自己的控件上,让自己的控件响应消息。
4,根据不同的行为发送自定义消息给窗口,比便程序进行调用。
5,一般窗口上控件的组织使用XML来描述。
二,消息分发过程
以一个窗口基类CWindowWnd为例,注册窗口时,调用这个类的成员函数[cpp] view plaincopy
bool RegisterWindowClass();
注册时指定窗口处理函数
[cpp] view plaincopy
static LRESULT CALLBACK __WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
然后再以一个成员函数创建窗口
[cpp] view plaincopy
HWND CWindowWnd::Create(HWND hwndParent, LPCTSTR pstrName, DWORD dwStyle,
DWORD dwExStyle, int x, int y, int cx, int cy, HMENU hMenu)
{
if( GetSuperClassName() != NULL && !RegisterSuperclass() ) return NULL;
if( GetSuperClassName() == NULL && !RegisterWindowClass() ) return NULL;
m_hWnd = ::CreateWindowEx(dwExStyle, GetWindowClassName(), pstrName,
dwStyle, x, y, cx, cy, hwndParent, hMenu,
CPaintManagerUI::GetInstance(), this);
ASSERT(m_hWnd!=NULL);
return m_hWnd;
}
创建时将this指针传入到CreateWindowEx的最后一个参数。响应WM_NCCREATE消息时就能取到this指针的值,进而调用虚函数,子类重写这个虚函数就能实现不同的消息处理。
[cpp] view plaincopy
LRESULT CALLBACK CWindowWnd::__WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
CWindowWnd* pThis = NULL;
if( uMsg == WM_NCCREATE ) {
LPCREATESTRUCT lpcs = reinterpret_cast<LPCREATESTRUCT>(lParam);
pThis = static_cast<CWindowWnd*>(lpcs->lpCreateParams);
pThis->m_hWnd = hWnd;
::SetWindowLongPtr(hWnd, GWLP_USERDATA, reinterpret_cast<LPARAM>(pThis));
}
else {
pThis = reinterpret_cast<CWindowWnd*>(::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 ) {
//HandleMessage为虚函数
return pThis->HandleMessage(uMsg, wParam, lParam);
}
else {
return ::DefWindowProc(hWnd, uMsg, wParam, lParam);
}
}
消息转发过程和传统的Windows程序也不一样。比如在一个传统的窗口上左键点击一个按钮时,将会发送一个WM_COMMAND的消息给窗口,wParam的低字节为按钮ID,高字节为BN_CLICKED,而lParam为按钮句柄。而在DUI里面是怎样的呢?首先系统发送一个WM_LBUTTONDOWN消息给窗口,lParam为点击的坐标信息,根据这个坐标找到相应的按钮。然后将一些必要的信息(比如控件指针,名称,消息类型)组成一个Notify发送给窗口,窗口再根据Notify里面的信息作出相应处理。
三、界面绘制过程
窗口接收到WM_PAINT消息时,先绘制自身,然后根据控件树的组织由Parent节点到Child节点依次绘制。绘制每一个元素时一般是按以下步骤:[cpp] view plaincopy
void CControlUI::DoPaint(HDC hDC, const RECT& rcPaint)
{
if( !::IntersectRect(&m_rcPaint, &rcPaint, &m_rcItem) ) return;
// 绘制循序:背景颜色->背景图->状态图->文本->边框
if( m_cxyBorderRound.cx > 0 || m_cxyBorderRound.cy > 0 ) {
CRenderClip roundClip;
CRenderClip::GenerateRoundClip(hDC, m_rcPaint, m_rcItem, m_cxyBorderRound.cx, m_cxyBorderRound.cy, roundClip);
PaintBkColor(hDC);
PaintBkImage(hDC);
PaintStatusImage(hDC);
PaintText(hDC);
PaintBorder(hDC);
}
else {
PaintBkColor(hDC);
PaintBkImage(hDC);
PaintStatusImage(hDC);
PaintText(hDC);
PaintBorder(hDC);
}
}
/article/2725427.html
相关文章推荐
- Codeforces Round #333 D. Lipshitz Sequence (单调栈)
- ZOJ 3911 Prime Query(线段树)
- juery.jqgrid新建demo
- 开始学习requirejs+easyui的使用.
- UIImage 图片处理:截图,缩放,设定大小,存储
- 黑马程序员_javaGUI初学体会
- Eigen+suitesparse for windows 安装
- Continue
- iOS UIImage扩展方法(category):放大、旋转、合并UIImage、增加渐变层、添加阴影、调节透明度、保存到相...
- 仿新浪微博IOS客户端(v5.2.8)——自定义UITabBar替换系统默认的(添加“+”号按钮),
- 出现Error:java: javacTask: source release 1.7 requires target release 1.7
- android源码分析之类Build
- Value与innerHTML区别
- 代码手写UI,xib和StoryBoard间的博弈,以及Interface Builder的一些小技巧
- BTO (Built to option) Bidadari Alkaff Vista
- Jenkins xcodebuild There are no schemes in workspace
- HDU-3177 Crixalis's Equipment
- UIImage_Category
- hdoj--5567--sequence1(水题)
- hdoj--5567--sequence1(水题)