日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

Duilib教程-自动布局2

發(fā)布時(shí)間:2024/4/11 编程问答 47 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Duilib教程-自动布局2 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

在上一節(jié)中,我簡單介紹了控件隨父LAYOUT自由移動(dòng)的設(shè)置。在這一節(jié),我將介紹一種常見的情況:嵌入窗口。

?

在項(xiàng)目中,我們很少會100%的編寫一個(gè)軟件,特別是界面相關(guān)的,我們會使用以前已經(jīng)編寫好的窗口,或網(wǎng)上的開源模塊。舉一個(gè)簡單的例子來說,如果你要編寫一個(gè)視頻播放器,關(guān)于視頻的播放窗口,就用不著用DUI來實(shí)現(xiàn),我們完全可以使用網(wǎng)上的開源庫,嵌入一個(gè)播放的WND即可(當(dāng)然有的庫也支持回調(diào)的方式,用戶可以在自己的窗口中將回調(diào)出來的圖片進(jìn)行自由繪制)。

?

我們需要在窗口大小改變時(shí),即時(shí)地改變播放窗口的大小。也許你會說這非常簡單,直接重載OnSize,然后獲取占位控件(使用占位控件才是最正確的選擇,如果在程序中判斷左邊距、右邊距,就做不到UI、CODE分離了)的大小,然后設(shè)置即可。但是當(dāng)你真正使用的時(shí)候,發(fā)現(xiàn)并沒有那么簡單。來看代碼:

?

UIManager.cpp 第750行:

case WM_SIZE:{if( m_pFocus != NULL ) {TEventUI event = { 0 };event.Type = UIEVENT_WINDOWSIZE;event.pSender = m_pFocus;event.dwTimestamp = ::GetTickCount();m_pFocus->Event(event);}if( m_pRoot != NULL ) m_pRoot->NeedUpdate();}return true;

?

我們看到,窗口大小改變,ROOT只是簡單的 NeedUpdate,重繪而已,它的大小并沒有設(shè)置為與窗口一樣的大小。

?

在WinImplBase.cpp 第214 行:

LRESULT WindowImplBase::OnSize(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled){SIZE szRoundCorner = m_PaintManager.GetRoundCorner();#if defined(WIN32) && !defined(UNDER_CE)if( !::IsIconic(*this) && (szRoundCorner.cx != 0 || szRoundCorner.cy != 0) ) {CDuiRect rcWnd;::GetWindowRect(*this, &rcWnd);rcWnd.Offset(-rcWnd.left, -rcWnd.top);rcWnd.right++; rcWnd.bottom++;HRGN hRgn = ::CreateRoundRectRgn(rcWnd.left, rcWnd.top, rcWnd.right, rcWnd.bottom, szRoundCorner.cx, szRoundCorner.cy);::SetWindowRgn(*this, hRgn, TRUE);::DeleteObject(hRgn);}#endifbHandled = FALSE;return 0;}

?

也是啥也沒做。

所以在OnSize里面設(shè)置窗口位置,并不會達(dá)到效果。

?

那么DUILIB是在哪里設(shè)置ROOT的大小呢?UIManager.cpp 第 615行,即在WM_PAINT中進(jìn)行設(shè)置。

m_pRoot->SetPos(rcClient);

?

1.SetPos

當(dāng)你看到這里時(shí),我想你已經(jīng)知道第一種方法了。即在 OnSize中,

RECT rc;GetClientRect (m_hWnd, &rc);m_PaintManager.GetRoot()->SetPos (rc);const RECT& rc_pos = targer_ui_->GetPos ();::MoveWindow (move_wnd, rc_pos.left, rc_pos.top, rc_pos.right – rc_pos.left, rc_pos.bottom – rc_pos.top, TRUE);

?

?

即我們主動(dòng)設(shè)置大小,ROOT設(shè)置了POS后,會將它的子控件也設(shè)置POS,詳情請看源碼。所以,我們就能夠得到正確的位置信息了。

?

但是這并不是最好的方式,原因很簡單,OnSize會被頻繁的調(diào)用,特別是在程序初始化的時(shí)候,OnSize被調(diào)用N次,而且在最小化的時(shí)候也會被調(diào)用。而且當(dāng)你看1.SetPos時(shí),你也猜到了會有第二種方式了。

?

2.委托?OnSize

假設(shè)我們的占位控件為 target_ui_,它有一個(gè)委托成員變量:OnSize。直接看代碼吧:

target_ui_->OnSize += MakeDelegate (this, &CYourWnd::OnTargetSizeChanged);bool CYourWnd:: OnTargetSizeChanged (void* param){const RECT& rc_pos = targer_ui_->GetPos ();::MoveWindow (move_wnd, rc_pos.left, rc_pos.top, rc_pos.right – rc_pos.left, rc_pos.bottom – rc_pos.top, TRUE);}

?

如此簡單,又如此優(yōu)美的代碼。

注意使用的是?+=

在這里,我們也看到了作者自己實(shí)現(xiàn)了委托的編寫(我不清楚是不是使用了開源庫),可見作者的C++功底是相當(dāng)深厚的。

?

?

看CControlUI的源碼,你會發(fā)現(xiàn)如下委托對象:

public:CEventSource OnInit;CEventSource OnDestroy;CEventSource OnSize;CEventSource OnEvent;CEventSource OnNotify;

?

顧名思義,無需贅述。

?

這里說一下Event和Notify的區(qū)別。

Event是控件自己收到的消息,比如鼠標(biāo)左鍵按下、彈起、雙擊等,DUILIB先向控件自己發(fā)一個(gè)事件。

Notify通知,是向WND發(fā)送的通知消息,類似MFC中對話框收到控件的NOTIFY(包括按鈕的單擊),它默認(rèn)情況下是由窗口接收的,在窗口的Notify函數(shù)中進(jìn)行響應(yīng)。

?

DUILIB的處理流程是,先向CONTROL發(fā)送事件,然后向WND發(fā)送通知。

?

OnNotify相當(dāng)有用,因?yàn)槟憧梢远ㄖ泼總€(gè)控件的響應(yīng),而不需要在WND的Notify中進(jìn)行一大堆的if..else..了。

?

OnEvent用處也很大,看情況使用了。

總結(jié)

以上是生活随笔為你收集整理的Duilib教程-自动布局2的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。