duilib DirectUI库里面的一个简单的例子ListDemo

来源:互联网 发布:adobe xd mac 编辑:程序博客网 时间:2024/06/04 01:28

1、从WinMain说起

int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE /*hPrevInstance*/, LPSTR /*lpCmdLine*/, int nCmdShow){    ListMainForm* pFrame = new ListMainForm();    pFrame->Create(NULL, _T("ListDemo"), UI_WNDSTYLE_FRAME, WS_EX_STATICEDGE | WS_EX_APPWINDOW , 0, 0, 600, 320);    pFrame->CenterWindow();    ::ShowWindow(*pFrame, SW_SHOW);    CPaintManagerUI::MessageLoop();return 0;}



这里面也没啥看的,因为是ui,所以消息很重要,来看看

INotifyUI:    void Notify(TNotifyUI& msg)    {        if( msg.sType == _T("windowinit") )             OnPrepare(msg);        else if( msg.sType == _T("click") )         {            else if( msg.pSender == m_pMinBtn )             {                 SendMessage(WM_SYSCOMMAND, SC_MINIMIZE, 0);                return;             }            else if(msg.pSender == m_pSearch)            {                OnSearch();            }        }        else if( msg.sType == _T("itemactivate") )         {            int iIndex = msg.pSender->GetTag();            CDuiString sMessage = _T("Click: ");;            sMessage += domain[iIndex].c_str();            ::MessageBox(NULL, sMessage.GetData(), _T("提示(by tojen)"), MB_OK);        }        else if(msg.sType == _T("menu"))         {            if( msg.pSender->GetName() != _T("domainlist") ) return;            CMenuWnd* pMenu = new CMenuWnd();            if( pMenu == NULL ) { return; }            POINT pt = {msg.ptMouse.x, msg.ptMouse.y};            ::ClientToScreen(*this, &pt);            pMenu->Init(msg.pSender, pt);        }        else if( msg.sType == _T("menu_Delete") ) {            CListUI* pList = static_cast<CListUI*>(msg.pSender);            int nSel = pList->GetCurSel();            if( nSel < 0 ) return;            pList->RemoveAt(nSel);            domain.erase(domain.begin() + nSel);            desc.erase(desc.begin() + nSel);           }    }


一步一步来看这里显示

一开始是

if( msg.sType == _T("windowinit") )             OnPrepare(msg);

OnPrepare函数没有做什么事情,所以忽略

其他的消息我们在后面继续看=============



在继承了CWindowWnd之后可以通过覆盖LRESULT HandleMessage(UINT uMsg, WPARAM wParam, LPARAM lParam)的实现,添加自己的消息响应

    LRESULT HandleMessage(UINT uMsg, WPARAM wParam, LPARAM lParam)    {        LRESULT lRes = 0;        BOOL bHandled = TRUE;        switch( uMsg ) {            case WM_ADDLISTITEM:   lRes = OnAddListItem(uMsg, wParam, lParam, bHandled); break;            case WM_CREATE:        lRes = OnCreate(uMsg, wParam, lParam, bHandled); break;            case WM_CLOSE:         lRes = OnClose(uMsg, wParam, lParam, bHandled); break;            case WM_DESTROY:       lRes = OnDestroy(uMsg, wParam, lParam, bHandled); break;            case WM_NCACTIVATE:    lRes = OnNcActivate(uMsg, wParam, lParam, bHandled); break;            case WM_NCCALCSIZE:    lRes = OnNcCalcSize(uMsg, wParam, lParam, bHandled); break;            case WM_NCPAINT:       lRes = OnNcPaint(uMsg, wParam, lParam, bHandled); break;            case WM_NCHITTEST:     lRes = OnNcHitTest(uMsg, wParam, lParam, bHandled); break;            case WM_SIZE:          lRes = OnSize(uMsg, wParam, lParam, bHandled); break;            case WM_GETMINMAXINFO: lRes = OnGetMinMaxInfo(uMsg, wParam, lParam, bHandled); break;            case WM_SYSCOMMAND:    lRes = OnSysCommand(uMsg, wParam, lParam, bHandled); break;            default:                bHandled = FALSE;        }        if( bHandled ) return lRes;        if( m_pm.MessageHandler(uMsg, wParam, lParam, lRes) ) return lRes;        return CWindowWnd::HandleMessage(uMsg, wParam, lParam);    }


2、下面的WM消息,一起来看看

a、首先发出的是WM_NCACTIVATE消息

======当客户区将要显示激活或者非激活时,WM_NCACTIVATE消息就会发送给窗口。一个窗口通过它的WindowProc函数来获取该消息。

    LRESULT OnNcActivate(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)    {        if( ::IsIconic(*this) ) bHandled = FALSE;        return (wParam == 0) ? TRUE : FALSE;    }

判断一下窗体是否是最小化,如果是则设置标志bHandled然后返回wParam



b、下来发出的是WM_CREATE消息:

======窗口创建CreateWindow,系统给消息处理程序发送的消息,每次窗口创建,有且只有1WM_CREATE消息

    LRESULT OnCreate(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)    {        LONG styleValue = ::GetWindowLong(*this, GWL_STYLE);        styleValue &= ~WS_CAPTION;        ::SetWindowLong(*this, GWL_STYLE, styleValue | WS_CLIPSIBLINGS | WS_CLIPCHILDREN);        Init();    }


这里是创建一个窗口并执行Init的操作:

    void Init()     {        m_pCloseBtn = static_cast<CButtonUI*>(m_pm.FindControl(_T("closebtn")));        m_pMaxBtn = static_cast<CButtonUI*>(m_pm.FindControl(_T("maxbtn")));        m_pRestoreBtn = static_cast<CButtonUI*>(m_pm.FindControl(_T("restorebtn")));        m_pMinBtn = static_cast<CButtonUI*>(m_pm.FindControl(_T("minbtn")));        m_pSearch = static_cast<CButtonUI*>(m_pm.FindControl(_T("btn")));    }

Init是找到对应的控件

Create完毕之后,窗口就起来了




记得我们在void Notify(TNotifyUI& msg)中绑定了一个消息,消息类型为

if( msg.sType == _T("click") ) {    else if(msg.pSender == m_pSearch)    {        OnSearch();    }}


主要是这个OnSearch(),当点击了页面上面的Search按钮,那么相对应的消息便会发出来,m_pSearchInit的时候和UI上的Search按钮绑定(在这里再判断一下消息的发送者),如果对应 则执行了OnSearch()

void OnSearch(){    struct Prama *prama = new Prama;    CListUI* pList = static_cast<CListUI*>(m_pm.FindControl(_T("domainlist")));    CEditUI* pEdit = static_cast<CEditUI*>(m_pm.FindControl(_T("input")));    pEdit->SetEnabled(false);    CDuiString input = pEdit->GetText();    m_pSearch->SetEnabled(false);    pList->RemoveAll();    domain.empty();    domain.resize(0);    desc.empty();    desc.resize(0);    DWORD dwThreadID = 0;    pList->SetTextCallback(this);//[1]    prama->hWnd = GetHWND();    prama->pList = pList;    prama->pSearch = m_pSearch;    prama->tDomain = input;    HANDLE hThread = CreateThread(NULL,0,&ListMainForm::Search, (LPVOID)prama,  0,&dwThreadID);}


Prama是定义的一个结构体,因为在最底下需要开辟线程去执行Add的操作,所以通过这个结构体把所以需要到的东西都传过去。

pList为对应的List列表,pEdit为最上面的文本框

ListMainForm::Search(也就是线程的回调方法)

    static DWORD WINAPI Search(LPVOID lpParameter)    {        try        {            struct Prama* prama = (struct Prama *)lpParameter;            CListUI* pList = prama->pList;            CButtonUI* pSearch = prama->pSearch;            CDuiString tDomain = prama->tDomain;            //-------------------------------------            /*            * 添加数据循环            */            for(int i=0; i<100; i++)            {                std::stringstream ss;                ss << "www." << i << ".com";                domain.push_back(ss.str());                ss.clear();                ss << "it's " << i;                desc.push_back(ss.str());                CListTextElementUI* pListElement = new CListTextElementUI;                pListElement->SetTag(i);                if (pListElement != NULL)                {                    ::PostMessage(prama->hWnd, WM_ADDLISTITEM, 0L, (LPARAM)pListElement);                }                /*                *Sleep 为了展示添加的动态效果,故放慢了添加速度,同时可以看到添加过程中界面仍然可以响应                */                ::Sleep(100);            }            //------------------------------------------            delete prama;            pSearch->SetEnabled(true);            return 0;        }    }



取出上面的参数,发送WM_ADDLIST消息往里边加入Item

::PostMessage(prama->hWnd, WM_ADDLISTITEM, 0L, (LPARAM)pListElement);

LRESULT HandleMessage(UINT uMsg, WPARAM wParam, LPARAM lParam){    switch( uMsg ) {        case WM_ADDLISTITEM:   lRes = OnAddListItem(uMsg, wParam, lParam, bHandled); break;}


对应的OnAddListItem就是往List添加Item的

LRESULT OnAddListItem(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled){    CListTextElementUI* pListElement = (CListTextElementUI*)lParam;    CListUI* pList = static_cast<CListUI*>(m_pm.FindControl(_T("domainlist")));    if( pList ) pList->Add(pListElement);    return 0;}



在回头看看void Notify(TNotifyUI& msg)里面:

双击每一个Item则会发出消息itemactivate

else if( msg.sType == _T("itemactivate") ) {    int iIndex = msg.pSender->GetTag();    CDuiString sMessage = _T("Click: ");;sMessage += domain[iIndex].c_str();    ::MessageBox(NULL, sMessage.GetData(), _T("提示(by tojen)"), MB_OK);}

msg.pSender->GetTag()获取当前ListIndex




对着List右键,则会发出消息menu

else if(msg.sType == _T("menu")) {    if( msg.pSender->GetName() != _T("domainlist") ) return;    CMenuWnd* pMenu = new CMenuWnd();    if( pMenu == NULL ) { return; }    POINT pt = {msg.ptMouse.x, msg.ptMouse.y};    ::ClientToScreen(*this, &pt);    pMenu->Init(msg.pSender, pt);}


menu里边有个delete,对应的消息是menu_Delete

else if( msg.sType == _T("menu_Delete") ) {    CListUI* pList = static_cast<CListUI*>(msg.pSender);    int nSel = pList->GetCurSel();    if( nSel < 0 ) return;    pList->RemoveAt(nSel);    domain.erase(domain.begin() + nSel);    desc.erase(desc.begin() + nSel);   }}


好了 这个例子就看完了

这个例子中还有两外一个文件MenuWnd.h他其实是对的CMenuWnd描述,也是一个class CMenuWnd : public CWindowWnd, public INotifyUI窗口,他的分析和上面说的差不多。


最后,来看看这里:

else if(msg.sType == _T("menu")) {if( msg.pSender->GetName() != _T("domainlist") ) return;CMenuWnd* pMenu = new CMenuWnd();if( pMenu == NULL ) { return; }POINT pt = {msg.ptMouse.x, msg.ptMouse.y};::ClientToScreen(*this, &pt);pMenu->Init(msg.pSender, pt);}

==========最后delete this==========



原创粉丝点击