zoukankan      html  css  js  c++  java
  • DirectUI实现原理

    一,概念 

    传统的Windows窗口程序对每一个控件都会创建一个句柄,而DUI技术奖所有控件都绘制在一个窗体上,这些控件的逻辑和绘图方式必须自己进行编写和封装,所以这些控件都是无句柄的。

    DUI技术的实现步骤和难点:

    1,窗口的子类化,截获窗口的消息。

    2,封装自己的控件,并将自己的控件绘制到该窗口上。

    3,封装窗口的消息,并分发到自己的控件上,让自己的控件响应消息。

    4,根据不同的行为发送自定义消息给窗口,比便程序进行调用。

    5,一般窗口上控件的组织使用XML来描述。

    二,消息分发过程

    以一个窗口基类CWindowWnd为例,注册窗口时,调用这个类的成员函数
    [cpp] view plaincopy
     
    1. bool RegisterWindowClass();  

    注册时指定窗口处理函数

    [cpp] view plaincopy
     
    1. static LRESULT CALLBACK __WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);  

    然后再以一个成员函数创建窗口

    [cpp] view plaincopy
     
    1. HWND CWindowWnd::Create(HWND hwndParent, LPCTSTR pstrName, DWORD dwStyle,   
    2.     DWORD dwExStyle, int x, int y, int cx, int cy, HMENU hMenu)  
    3. {  
    4.     if( GetSuperClassName() != NULL && !RegisterSuperclass() ) return NULL;  
    5.     if( GetSuperClassName() == NULL && !RegisterWindowClass() ) return NULL;  
    6.   
    7.     m_hWnd = ::CreateWindowEx(dwExStyle, GetWindowClassName(), pstrName,   
    8.         dwStyle, x, y, cx, cy, hwndParent, hMenu,   
    9.         CPaintManagerUI::GetInstance(), this);  
    10.   
    11.     ASSERT(m_hWnd!=NULL);  
    12.     return m_hWnd;  
    13. }  

    创建时将this指针传入到CreateWindowEx的最后一个参数。响应WM_NCCREATE消息时就能取到this指针的值,进而调用虚函数,子类重写这个虚函数就能实现不同的消息处理。

    [cpp] view plaincopy
     
    1. LRESULT CALLBACK CWindowWnd::__WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)  
    2. {  
    3.     CWindowWnd* pThis = NULL;  
    4.     if( uMsg == WM_NCCREATE ) {  
    5.         LPCREATESTRUCT lpcs = reinterpret_cast<LPCREATESTRUCT>(lParam);  
    6.         pThis = static_cast<CWindowWnd*>(lpcs->lpCreateParams);  
    7.         pThis->m_hWnd = hWnd;  
    8.         ::SetWindowLongPtr(hWnd, GWLP_USERDATA, reinterpret_cast<LPARAM>(pThis));  
    9.     }   
    10.     else {  
    11.         pThis = reinterpret_cast<CWindowWnd*>(::GetWindowLongPtr(hWnd, GWLP_USERDATA));  
    12.         if( uMsg == WM_NCDESTROY && pThis != NULL ) {  
    13.             LRESULT lRes = ::CallWindowProc(pThis->m_OldWndProc, hWnd, uMsg, wParam, lParam);  
    14.             ::SetWindowLongPtr(pThis->m_hWnd, GWLP_USERDATA, 0L);  
    15.             if( pThis->m_bSubclassed ) pThis->Unsubclass();  
    16.             pThis->m_hWnd = NULL;  
    17.             pThis->OnFinalMessage(hWnd);  
    18.             return lRes;  
    19.         }  
    20.     }  
    21.     if( pThis != NULL ) {  
    22.         //HandleMessage为虚函数  
    23.         return pThis->HandleMessage(uMsg, wParam, lParam);  
    24.     }   
    25.     else {  
    26.         return ::DefWindowProc(hWnd, uMsg, wParam, lParam);  
    27.     }  
    28. }  

    消息转发过程和传统的Windows程序也不一样。比如在一个传统的窗口上左键点击一个按钮时,将会发送一个WM_COMMAND的消息给窗口,wParam的低字节为按钮ID,高字节为BN_CLICKED,而lParam为按钮句柄。而在DUI里面是怎样的呢?首先系统发送一个WM_LBUTTONDOWN消息给窗口,lParam为点击的坐标信息,根据这个坐标找到相应的按钮。然后将一些必要的信息(比如控件指针,名称,消息类型)组成一个Notify发送给窗口,窗口再根据Notify里面的信息作出相应处理。

    三、界面绘制过程

    窗口接收到WM_PAINT消息时,先绘制自身,然后根据控件树的组织由Parent节点到Child节点依次绘制。绘制每一个元素时一般是按以下步骤:

    [cpp] view plaincopy
     
      1. void CControlUI::DoPaint(HDC hDC, const RECT& rcPaint)  
      2. {  
      3.     if( !::IntersectRect(&m_rcPaint, &rcPaint, &m_rcItem) ) return;  
      4.   
      5.     // 绘制循序:背景颜色->背景图->状态图->文本->边框  
      6.     if( m_cxyBorderRound.cx > 0 || m_cxyBorderRound.cy > 0 ) {  
      7.         CRenderClip roundClip;  
      8.         CRenderClip::GenerateRoundClip(hDC, m_rcPaint,  m_rcItem, m_cxyBorderRound.cx, m_cxyBorderRound.cy, roundClip);  
      9.         PaintBkColor(hDC);  
      10.         PaintBkImage(hDC);  
      11.         PaintStatusImage(hDC);  
      12.         PaintText(hDC);  
      13.         PaintBorder(hDC);  
      14.     }  
      15.     else {  
      16.         PaintBkColor(hDC);  
      17.         PaintBkImage(hDC);  
      18.         PaintStatusImage(hDC);  
      19.         PaintText(hDC);  
      20.         PaintBorder(hDC);  
      21.     }  
      22. }  

    http://blog.csdn.net/passion_wu128/article/details/38400535

  • 相关阅读:
    junit源码解析--测试驱动运行阶段
    junit源码解析--初始化阶段
    junit源码解析--核心类
    junit测试套件
    junit参数化测试
    junit忽略测试方法
    Junit4常用注解
    泛型技术
    在使用Java8并行流时的问题分析
    Linux 常用性能分析命令
  • 原文地址:https://www.cnblogs.com/findumars/p/5006173.html
Copyright © 2011-2022 走看看