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

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完毕之后,窗口就起来了

duilib DirectUI库里面的一个简单的例子ListDemo_第1张图片



记得我们在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;
}

duilib DirectUI库里面的一个简单的例子ListDemo_第2张图片


在回头看看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==========



你可能感兴趣的:(duilib DirectUI库里面的一个简单的例子ListDemo)