duilib duilib Concise Guide to Getting Started tutorial 15 owner-drawn

In [ 2013 duilib Concise Guide to Getting Started - Introduction complex controls (13) ], although describes all the controls on the interface designer, but there are some controls have not been placed on the interface designer, there are some common controls and duilib It does not provide (such as menu control). Although duilib not provide these controls, but himself drawn up is also very convenient, but duilib painting from the comparable MFC easily get more than a little, in fact, self-painted duilib mostly do not have to draw is that some controls and pictures of combinations only, rather simple ~ ~ ~
    First, the menu control
    in fact, the appearance of the menu control and ListBox very much like, so we can use the tutorial ListBox control simulation 13, you can also use other combinations of their own, due to the duilib comes Demo, there are two menu, and the style is still very good, so Alberl make use of them, but those few Demo is also terribly complicated, remember tutorials 13 ListCtrl how easy to use it? If you do not feel it simple, so then compare duilib comes ListDemo, you can feel it's a simple matter ~ O (∩_∩) O ~
    who saw duilib comes MenuDemo and ListDemo inside the menu, will not I think the menu is very simple, so take a look at to achieve the following menu bar O ~ (∩ _ ∩) O ~
    1, a new menu.xml, as follows:

  1. <?xml version="1.0" encoding="utf-8"?>
  2. <Window size="120,82">
  3. <VerticalLayout bkimage="file='Menu/menu_bk.png' corner='40,8,8,8'" hole="false">
  4.     <List header="hidden" inset="8,8,8,8" itemhotimage="file='Menu/menu_hot_bk.png' corner='2,2,2,2'">
  5.         <ListContainerElement name="menu_Open" height="22" inset="40,0,0,0">
  6.             <Label text="打开" mouse="false"/>
  7.         </ListContainerElement>
  8.         <ListContainerElement name="menu_Mark" height="22" inset="40,0,0,0">
  9.             <Label text="标注" mouse="false"/>
  10.         </ListContainerElement>
  11.         <ListContainerElement name="menu_Delete" height="22" inset="40,0,0,0">
  12.             <Label text="删除" mouse="false"/>
  13.         </ListContainerElement>
  14.     </List>
  15. </VerticalLayout>
  16. </Window>
复制代码




    可以看到Menu其实就是一个List和图片组合的,当然,亲们也可以用教程13中的ListBox来替换上述内容,只不过需要自己调整一下。这里非常感谢提供MenuDemo的大神,菜单样式非常漂亮~O(∩_∩)O~



    2、新建一个DuiMenu.h,如下(为了方便演示,将cpp的代码都放到了.h里,并且减少了空行,在最后的教程里,会有一个完整的工程下载):

  1. #pragma once
  2. // 此处需要包含duilib的头文件#include <UIlib.h>那一段,详细代码请见前面教程
  3. class CDuiMenu : public WindowImplBase
  4. {
  5. protected:
  6.     virtual ~CDuiMenu(){};        // 私有化析构函数,这样此对象只能通过new来生成,而不能直接定义变量。就保证了delete this不会出错
  7.     CDuiString  m_strXMLPath;
  8. public:
  9.     explicit CDuiMenu(LPCTSTR pszXMLPath): m_strXMLPath(pszXMLPath){}
  10.     virtual LPCTSTR    GetWindowClassName()const{ return _T("CDuiMenu "); }
  11.     virtual CDuiString GetSkinFolder()          { return _T("");            }
  12.     virtual CDuiString GetSkinFile()            { return m_strXMLPath;      }
  13.     virtual void       OnFinalMessage(HWND hWnd){ delete this;              }
  14.     virtual LRESULT OnKillFocus(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
  15.     {
  16.         Close();
  17.         bHandled = FALSE;
  18.         return 0;
  19.     }
  20.     void Init(HWND hWndParent, POINT ptPos)
  21.     {
  22.         Create(hWndParent, _T("MenuWnd"), UI_WNDSTYLE_FRAME, WS_EX_WINDOWEDGE);
  23.         ::ClientToScreen(hWndParent, &ptPos);
  24.         ::SetWindowPos(*this, NULL, ptPos.x, ptPos.y, 0, 0, SWP_NOZORDER | SWP_NOSIZE | SWP_NOACTIVATE);
  25.     }
  26.     virtual LRESULT HandleMessage(UINT uMsg, WPARAM wParam, LPARAM lParam)
  27.     {
  28.         LRESULT lRes = 0;
  29.         BOOL    bHandled = TRUE;
  30.         switch( uMsg )
  31.         {
  32.         case WM_KILLFOCUS:    
  33.             lRes = OnKillFocus(uMsg, wParam, lParam, bHandled); 
  34.             break; 
  35.         default:
  36.             bHandled = FALSE;
  37.         }
  38.         if(bHandled || m_PaintManager.MessageHandler(uMsg, wParam, lParam, lRes)) 
  39.         {
  40.             return lRes;
  41.         }
  42.         return __super::HandleMessage(uMsg, wParam, lParam);
  43.     }
  44. };
复制代码



    3、此时一个菜单控件的所有代码就完成啦,下面接下来要显示菜单控件,我们模仿MFC的方式,即点击一个菜单按钮后,弹出菜单项~


    显然第一步需要添加一个菜单按钮,XML如下:

  1.             <Button name="btnMenu" text="选项" float="true" pos="475,28,0,0" width="37" height="19" align="center" normalimage="" hotimage="Menu/btn_menu_hot.png" pushedimage="Menu/btn_menu_hot.png" focusedimage="Menu/btn_menu_hot.png" textcolor="#FF000000" hottextcolor="#FFFFFFFF" pushedtextcolor="#FFFFFFFF" focusedtextcolor="#FFFFFFFF" bkcolor="#FFECE9D8" />
  2.   
复制代码


            
  第二步就是响应菜单按钮的点击,在主窗口的Notify函数里添加以下代码:

  1. if( msg.sType == _T("click") ) 
  2.         {
  3.             if( msg.pSender->GetName() == _T("btnMenu") ) 
  4.             {
  5.                 POINT pt = {msg.ptMouse.x, msg.ptMouse.y};
  6.                 CDuiMenu *pMenu = new CDuiMenu(_T("Menu/menu.xml"));
  7.                 pMenu->Init(*this, pt);
  8.                 pMenu->ShowWindow(TRUE);
  9.             }
  10.         }
Copy the code



    And most important step is to extract image resources to exe directory you, download resources Mengchuo here ~  2013 Concise Guide to Getting duilib entire project (including resource code) .7z  (216.45 KB, downloads: 97) ( Note: This Department has given all the resources and code, will not be repeated later in the tutorial provide resources to download )

    well, the menu button and MFC is not much like it, there are shadows oh O ~ (∩ _ ∩) O ~
    (more extensive menu style see duilib comes MenuDemo)


     

    [Tips] menu class
     if that is not the way pointer, and the direct use of the variable displayed menu CDuiMenu menu (_T ( "menu / menu.xml")), it can not be used ShowWindow, otherwise it will collapse, because after scoping out the window is destroyed, so in this case can be defined as a member CDuiMenu variables, global variables, or static variable, but as a class for topical use, these methods are clearly not very good ;
     then you can use ShowModal instead of ShowWindow, so it will be able to see the window, but it creates a problem, that is the menu window does not lose focus, or other area click on the main window The menu will not disappear, of course, little friends can capture their own mouse, clicks to determine whether other areas of the main window, it is clear that this approach is not very good;
     这个时候delete this就派上用场啦(用智能指针也会崩溃,因为出了作用域同样会销毁内存,所以只能用delete this啦~ 用delete this就是将作用域交给duilib了),据说COM里面就是用delete this来销毁内存的。Alberl在duilib的Demo里面见到了大量的delete this,觉得这种自杀的方法很不靠谱,这不,前面教程就提到了ActiveX的一个bug,也是和delete this脱不了干系的~  不过既然COM里面都用了delete this,那就说明如果用好这把双刃剑,还是可以带来很多好处的。
     因为duilib提供了一个机制,就是窗口的最后一个函数一定是OnFinalMessage,之后不再调用窗口类的其他函数,这就为自杀提供了两个必要条件;delete this而还有一个必要条件就是这个类必须是通过new来申请内存的(而非 "new[]",亦非placement的"new" ,一定要是最原始的 "new",当然malloc也行(需要用free,而不是delete)),所以就将析构函数设置成私有函数,就保证了只有通过new申请内存的方式才能编译通过。 而duilib的Demo中大量使用delete this却没有保证这些必要条件,只要直接用变量的方式来声明类,则关闭窗口时就会崩溃,作为Demo,如此不严谨,有待好好规范。 当然,没有XX党,就没有新中国,没有那些大神的Demo,也就轮不到Alberl唧唧歪歪啦,这里Alberl只是觉得Demo应该严谨和权威,毕竟是官方的,并没有其他意思,请多多谅解~O(∩_∩)O~

    二、组合框控件
    由于duilib也没有自带GroupBox,所以我们一般采用的是Label + Control的组合,迅雷、百度、金山快盘、华为网盘这些都是这种组合,如图:
 
    这个就不用代码了吧,左边的Label 设置文字颜色,右边的Control设置背景色,高度设置为1就好了。

    三、复选框、单选框
    duilib的TestApp1中有几个CheckBox,不过也是需要图片资源的,因为图中的方框就是图片模拟的,代码也很简单,后面的教程会有详细的代码~
      

    四、时间选择控件
    这个也很简单,代码如下:

  1. <DateTime name="DateTimeDemo1" float="true" pos="30,118,0,0" width="120" height="30" bkcolor="#FFE2E5EA" padding="0,5,0,0" />
复制代码




 


    五、RichList、树形控件
    经过前面教程详细的介绍,相信现在已经基本入门了,由于Alberl暂时也没看这些控件,所以请自行参阅duilib自带的Demo。
    RichList请参阅duilib自带的RichListDemo,效果如图:
 

    Tree控件请参阅 (QQDemo、GameDemo,TestApp1),效果如图:
     
    duilib的控件就基本介绍完啦,其他控件也请自行参阅~O(∩_∩)O~

Guess you like

Origin www.cnblogs.com/blogpro/p/11427095.html