視窗之父cxwnd的封裝
在一般的程式中的對話方塊、按鈕、編輯框等都屬於視窗。在
mfc中,類
cwnd
作為視窗類的基類,抽象出了它們的共同特徵,並由此派生出若干的子類。在普通的
windows
程式中,我們可以方便的使用
mfc為我們封裝好的這些類(
cdialog, cbutton ,cedit
等),而在遊戲程式中,由於需要與
dx/opengl
結合以及效率等原因,因此不直接使用它們,這就需要我們自己來封裝。如此之多的控制項如何封裝能?我們不妨也為所有的視窗、控制項抽象乙個基類,就叫她
cxwnd
。那就讓我們從
cxwnd
開始,一步一步來實現我們真正的
ui吧。
我們先撇開
dx具體繪製視窗的過程,看看視窗、控制項有什麼共同的特徵,以及如何在
cxwnd
中來實現。
1、
視窗的大小與位置
視窗是乙個矩形的區域,因此用兩個變數就可以表示其大小(寬:
m_wdith,
高:m_height)。
視窗的位置也可以用兩個變數表示(
x座標:
m_xpos , y
座標:m_ypos
)。但這兩個變數表示視窗的絕對座標(相對於螢幕左上角)還是相對座標(相對于父視窗的坐上角)呢?
從使用者的角度(即建立視窗)看,使用相對座標方便一點;
從程式的角度(即繪製視窗)看,使用絕對座標方便一點。
我們封裝
cxwnd
的目的在於使用,因此要從使用者的角度出發,即
m_xpos
和m_ypos
表示的是視窗的相對座標。當繪製視窗的時候,我們需要獲得視窗的絕對座標,因此需要提供乙個成員函式來轉化——
getabsolutepos(float& x, float& y)。
(圖就不用畫了吧,:))
2、
視窗之間的聯絡
為了更具代表性,想一下(就不畫了哦)乙個帶屬性頁的對話方塊的視窗層次,與它相關的視窗有乙個父視窗(不包括祖父哦),若干的子視窗(各種控制項),以及若干個同級視窗,因此就需要有乙個指向其父視窗的指標(
cxwnd* m_wndparent
),乙個指向其子視窗鍊錶的指標(
cxwnd* m_wndchild
,m_wndchild
指向視窗鍊錶的第乙個視窗,該視窗
z序在子視窗中最小,既顯示在最前面),再加上同級視窗間的指標(
cxwnd* m_wndnextsibling
指向下乙個同級視窗;
cxwnd* m_wndprevioussibling
指向前乙個同級視窗)。這麼多視窗之間用這四種指標聯絡起來,畫出來就是一棵視窗關係樹。為什麼同級視窗需要兩個指標呢?在訊息迴圈中就可以找到答案了。
對這些指標,需要哪些操作呢?
除了基本的
get***wnd()
和set***wnd()
外,還需要:
新增乙個子視窗
addchildwnd(wndchild : cxwnd*)
刪除乙個子視窗
deletechildwnd(wndchild : cxwnd*)
刪除所有的子視窗
deleteallchildwnd()
,用來釋放記憶體。
獲取子視窗個數
getchildcount()
以上幾個都是對單向鍊錶的基本操作。
3、
訊息迴圈
從經典的訊息函式
wndproc(hwnd hwnd, uint message, wparam wparam, lparam lparam)
那,得到訊息後,主視窗需要傳遞下去,於是
cxwnd
有了乙個相似的函式——
postmessage(uint msg, wparam wparam, lparam lparam, void* data);
,其中對訊息進行分類處理。
1)
滑鼠訊息
滑鼠訊息處理,當然是如下三個(不過在
cxwnd
中不需要實現它們,只是宣告為純虛函式,因為各個控制項的滑鼠處理函式都不盡相同)
virtual void onmousedown(int button, int x, int y) = null;
virtual void onmousemove(int x, int y) = null;
virtual void onmouseup(int button, int x, int y) = null;
如何得知是哪個視窗得到了滑鼠訊息呢?那就需要挨個搜尋各個視窗,看滑鼠當前的座標(注意是絕對座標)在哪個視窗上。因此加入函式
cursorintersect(float x, float y)
來完成此功能。
滑鼠訊息是如何在視窗樹中傳遞的呢?範圍肯定是從大到小掃瞄,即先看是否在某視窗上,若在則看是否在該視窗的子視窗上……,終於找到最上的最底層的視窗,於是子視窗先處理滑鼠訊息,即最上的子視窗具有處理滑鼠訊息的優先權
。因此訊息的傳遞是從上而下,就稱之為正序訊息傳遞吧——
postmsgtochildren
(……)負責把訊息正序傳給每乙個子視窗。
2)
鍵盤訊息
同滑鼠訊息一樣,鍵盤訊息的處理有如下兩個純虛成員函式:
virtual void onkeydown(wparam key, lparam extended) = null;
virtual void onkeyup(wparam key, lparam extended) = null;
鍵盤訊息的處理的特殊之處在於處理它的視窗(控制項)需要獲得焦點(原因很簡單),因此每個窗體需要乙個存放其獲取焦點的子窗體的指標成員變數(
cxwnd* m_wndfocus
)和乙個判斷其是否獲得焦點的
bool
成員變數(
bool m_bfocus
),從而就有了
setfocuswnd
(……)和
getfocus()
成員函式。
鍵盤訊息的傳遞與滑鼠訊息的傳遞一樣。
3)
視窗繪製訊息
視窗的繪製是與具體的視窗物件相關的,因此在
cxwnd
中不予實現,但視窗繪製的訊息是要傳遞的,那該訊息是如何傳遞的呢?
每個視窗都有自己的
z序,最後面的要先繪製,最前面的要後繪製(要不就被當住了),對應與視窗樹就是,父視窗要先繪製,然後最下子視窗後繪製,最後是最上的子視窗。因此最下的視窗具有處理視窗繪製訊息的優先權
。而最上的子視窗排在子視窗鍊錶的最前面,因此該訊息需要逆序從後往前傳遞。因此需要乙個專門的傳遞該訊息的成員函式——
postmsgtochildrenreverse
(……)。
視窗的z序不是固定的,因此需要乙個函式來改變它們的z序
——movetofront
(……)。
至此,cxwnd
的主體功能已經完成了,看看它有那些成員吧:
遊戲ui設計,遊戲ui設計需要學什麼
一.什麼是遊戲ui?ui設計大體可以分為應用ui和遊戲ui兩個方向。應用ui多指的是網頁 安卓 ios圖示介面設計等內容,也是現在普遍培訓機構的課程。而遊戲ui設計則是在應用ui的基礎上,主要針對遊戲介面 遊戲道具 圖示設計 登陸介面等方面,很少有培訓機構去統一培訓。其中遊戲介面又包含頁遊 客戶端介...
移動遊戲ui設計(一)
遊戲世界 遊戲介面就是根據遊戲特性,把必要的資訊展現在遊戲主介面,操控介面和彈出界面上,通過合理的設計引導使用者進行人機互動操作 1,遊戲介面設計原則 互動設計盡量不要繁瑣,用最簡單的方式引導使用者即可 把控好遊戲的介面風格,注意色彩對介面的影響 引導介面的設計應言簡意賅 遊戲設計師要懂得很多客觀知...
如何設計21點遊戲
21點遊戲的設計能夠充分體現c語言結構化程式設計的思想,如果你是c語言的初學者,本文對你一定有幫助.21點遊戲的規則如下 撲克牌a 2 3 4 10 j q k 大小鬼分別代表數字1 2 3 4 10 11 12 13 21 人和電腦輪流坐莊,莊家先發牌。勝利條件 將所取牌點數相加湊成 和 是21,...