文檔中心

控件開發_基礎

02.控件的共性

华东15选5 www.wjnoc.com 控件是人機界面上直接和開發人員交互的部分,不同控件的顯示外觀各有不同、控件和開發人員的交互方式也多種多樣,控件之間還有許多復雜的關系,而且控件系統的設計還要足夠的方 便和靈活,使得開發人員界面能夠適應各種需求(外觀定制、自動布局、多語言翻譯)。

控件系統設計的原則是:盡量抽象出各種控件都普遍具有的共性,總結出一套簡單的操 作接口,用少量的函數就能夠完成大部分的界面開發工作。

各種控件的共性體現在以下幾個方面:

1)控件的外觀

考察一個無論簡單還是復雜的控件或者界面,它在屏幕上的顯示都可以看成是若干個矩形顯示區域的組合,每個矩形里面可能顯示一個圖片或一段文字;矩形的位置和大小都可以按照各自所屬控件的規則動態改變,顯示的內容也可以動態修改??丶低吵橄蟪魷允鏡ピ幢硎疽桓鼉匭蝸允廄?,并且規定每個顯示單元上面可以同時顯示一個背景(圖片或顏色)、一個邊框(圖片或顏色)、一張圖片和多行文本。這樣最終一個控件在外觀上就是由一個或多個顯示單元組成的,如按鈕就是一個顯示單元;進度條就是由底框、進度和滑塊三個顯示單元組成;多行列表中的每一個行,每一個單元格都是一個顯示單元。

顯示單元中的背景、邊框、圖片的對齊方式、文本的字體,顏色和對齊方式被稱為顯示單元的風格或樣式,可以通過編輯文本文件來設定,開發人員不需要修改程序就可以改變控件中每個顯示單元的外觀。界面上的多個按鈕也可以分別指定不同的風格,如何寫風格配置文件以及如何指定風格見下文。

2)控件的狀態

每個控件都有四種狀態:

1、普通狀態:一般控件創建后的狀態,用 TW_STATUS_NORMAL表示;

2、活動狀態:當鼠標進入或有輸入焦點時的狀態,用 TW_STATUS_ACTIVE表示;

3、選中狀態:當鼠標點擊或被選中時的狀態,用 TW_STATUS_SELECT表示;

4、無效狀態:控件不能接受事件時的狀態,比如按鈕變灰,用 TW_STATUS_DISABLE表示;

控件在創建時都是普通狀態,然后根據設置和控件內部接收到的輸入事件自動切換,并 且控件狀態的變化通常也會導致顯示單元外觀的自動變化。

3)控件的創建

除了根窗口控件,其他所有的控件都用一個方法創建:

TWidget *TwCreate(T_ID type, TWidget *parent, Tint x, Tint y, Tint w, Tint h, char *style, Tuint flags);

用 TWidget來表示控件的結構,因為控件也是TD圖形軟件系統系統用 C語言封裝的對象(見《TD圖形軟件系統開發平臺_對象系統》),所以該函數內部其實也是調用了 TObjectCreate()函數來創建的控件對象,并返回控件對象的指針。參數 type是一個字符串 id,標識控件對象的類型,比如創建按鈕對象用 TStringID(“button”),創建窗口對象用 TStringID(“window”)。

參數 parent是父控件的指針,參數 x、y、w、h是創建的控件相對于父控件的坐標位置(左上角為(0,0))和大小。從這幾個參數可以看出所有的控件對象都組織在一棵控件樹上,除了樹根,其他所有控件都有父控件,控件可以有任意數目的子控件,父控件相同的控 件互為兄弟控件。根控件是一個窗口類型控件,是控件系統初始化時得到的。

參數 style指定控件顯示單元的風格名,同一種類型的控件也可以設定不同的顯示風格。(在風格配置文件中,每種風格都可以指定一個名字)。如果 style傳為 NULL或者不存 在這個名字的風格,那么就會采用該顯示單元的默認風格。最后是 TwCreate()的參數flags,這個參數是控件的標志,每一個標志都是二進制位的掩碼,所以可以用’|’運算同時 指定多個標志。標志分為每個控件都具有的公共標志和控件自己的私有標志。

下表列出了每個控件都具有的公共標志:

標志

說明

TW_NO_FOCUS

控件不能得到輸入焦點。

TW_CHILD_NO_FOCUS

控件的所有孩子(包括子子孫孫)都不能得到輸入焦點。

TW_DISABLE

控件創建時無效。

TW_HIDE

控件創建時隱藏。

TW_LAYOUT_FIX_W

排版控件可能會自動改變其子控件的大小,這兩個標

志告訴父控件不要修改我的寬或高

TW_LAYOUT_FIX_H

TW_LAYOUT_FIX_SIZE

TW_LAYOUT_FIX_W|TW_LAYOUT_FIX_H

TW_HIDE_H_SCROLL

當控件有滾動區域時隱藏水平滾動條。

TW_HIDE_V_SCROLL

當控件有滾動區域時隱藏垂直滾動條。

TW_HIDE_SCROLL

TW_HIDE_H_SCROLL|TW_HIDE_V_SCROLL

TW_AUTO_HIDE_H_SCROLL

當控件有滾動區域時,自動隱藏水平滾動條,即滾動

時才顯示滾動條,靜止時不顯示滾動條。

TW_AUTO_HIDE_V_SCROLL

當控件有滾動區域時,自動隱藏垂直滾動條,即滾動

時才顯示滾動條,靜止時不顯示滾動條。

TW_AUTO_HIDE_SCROLL

TW_AUTO_HIDE_H_SCROLL |      TW_AUTO_HIDE_V_SCROLL

TW_NO_H_SCROLL

禁止水平滾動,當然也沒有水平滾動條。

TW_NO_V_SCROLL

禁止垂直滾動,當然也沒有垂直滾動條。

TW_SCROLL_GRAB_MOUSE

可以手指在滾動區域滑動

TW_NO_EVENT

控件不處理輸入事件,只能通過函數接口操作控件

TW_NO_TRANSLATE

控件上的文字不自動翻譯

TW_LONG_PRESS_CLICK

控件的 CLICK事件支持長按事件

 

 

控件的公共標志和私有標志都規定了不同的掩碼范圍,不能沖突。不同控件的私有標志 之間是有可能沖突的。具體見每個控件的頭文件。

4)控件的事件

所有控件都具有的事件有:

事件

標識

說明

點擊事件

TStringID(“clicked”)

當點擊鼠標左鍵,左鍵,雙擊左鍵,長

按左鍵或鍵盤 Enter鍵時觸發

取消事件

TStringID(“escaped”)

當接收到鍵盤 Escape鍵時觸發

得到焦點事件

TStringID(“got_focus”)

當得到鍵盤輸入焦點時觸發

失去焦點事件

TStringID(“lost_focus”)

當失去鍵盤輸入焦點時觸發

鼠標進入事件

TStringID(“mouse_enter”)

當鼠標進入控件顯示區域時觸發

鼠標離開事件

TStringID(“mouse_leave”)

當鼠標離開控件顯示區域時觸發

修改事件

TStringID(“modified”)

當控件的內容發生變化時觸發

銷毀事件

TStringID(“destroy”)

當控件被銷毀時觸發

需要說明以下幾點:
a)所有對象在被銷毀時都會觸發銷毀事件,不僅僅是控件對象;
b)點擊事件(clicked)有多種發生場景:單擊鼠標左鍵、雙擊鼠標左鍵、長按鼠標左鍵(控件創建時有 TW_LONG_PRESS_CLICK標記)、單擊鼠標右鍵、鍵盤 Enter建??梢醞ü?TwClickTypeEnum TwGetLastClickType(void) 得到 clicked事件產生的具體原因。注意是在按鍵松開時產生 clicked事件。
c)修改事件(modified)對不同的控件來說,觸發時機不一樣,比如按鈕控件在狀態發生變化時觸發,滾動條控件在滑塊滑動時觸發,窗口控件沒有這個事件。注意:用戶主動調用某函數導致控件發生改變時,不觸發改變事件,比如用戶主動設置滾動條的滑塊位置不 觸發該事件。
d)注冊事件及其事件處理和一般的對象相同,見《TD圖形軟件系統開發平臺_對象系統》。
上述這些事件觸發時都沒有參數。

5)控件的屬性和方法

每個控件都具有的屬性和相關方法如下表:

屬性

相關方法

說明

位置

void TwMove(TWidget *widget, Tint x, Tint y)

設置和獲取相對父

控件左上角的坐標

void TwGetPos(TWidget *widget, Tint *x, Tint*y)

void TwGetAbsolutePos(TWidget * widget, int*px, int *py)

得到相對屏幕左上

角的絕對坐標

大小

void TwResize(TWidget *widget, Tint w, Tint h)

設置和獲取控件的

大小

void TwGetSize(TWidget *widget, Tint *w, Tint *h)

是否顯示

void TwShow(TWidget *widget)

顯示控件

void TwHide(TWidget *widget)

隱藏控件

Tbool TwCheckShow(TWidget *widget)

檢測是否顯示

是否有效

void TwEnable(TWidget *widget)

使控件有效

void TwDisable(TWidget *widget)

使控件無效

Tbool TwCheckEnable(TWidget *widget)

檢測是否有效

value (一

個整數值)

Tbool TwSetValue(TWidget *widget, Tint value)

設置一個整數值

Tint TwGetValue(TWidget *widget)

得到一個整數值

caption(一個字符串)

void TwSetCaption(TWidget *widget, const char*string)

設置標題

const char * TwGetCaption(TWidget *widget,Tint *rlen);

得到標題

用 戶 附 加數據

void * TwAttachData(TWidget * widget, void *data)

設置和獲取控件上附加的用戶數據

void * TwGetAttachedData(TWidget *widget)

和 其 他 控件的關系

 

 

TWidget *TwGetParent(TWidget *widget)

得到父控件

TWidget *TwGetChild(TWidget *widget, Tboolif_first)

得到子控件

TWidget *TwGetSibling(TWidget *widget, Tbool if_next)

得到兄弟控件

鍵 盤 輸 入

焦點

void TwSetFocus(TWidget *widget)

設置焦點

TWidget * TwGetFocus(void)

得到當前焦點控件

Tbool TwCheckFocus(TWidget *widget)

檢測是否有焦點

需要說明以下幾點:

a)整個系統只能有一個控件得到鍵盤輸入焦點,當一個控件得到焦點,那么前一個焦 點控件就會自動失去焦點。

b)控件的用戶附加數據完全交給用戶負責,控件系統內部不會使用它,初始為 NULL。

c)控件的值(value,一個整數)和標題(caption,一個字符串)是控件的兩個特殊屬性,不同控件的這兩個屬性的含義可能不同,也可能有的控件有值沒有標題,有的控件有標題沒有值。比如:按鈕的值就是按鈕的狀態(普通、活動、選中、無效),按鈕的標題就是按鈕上顯示的文字;進度條的值就是進度,進度條的標題就是上面的文字;窗口控件有標題沒有值;

d)當獲取父控件、子控件、兄弟控件時,有可能得到一些不是你創建的控件,請不要吃驚,因為有的控件是組合控件,它內部創建了其他控件。比如窗口控件內部可能創建滾動條控件。

e)創建控件時的位置(x,y)和大?。╳,h)一般是以像素為單位,父控件的左上角位置為(0,0)。

6)控件的外觀設置

前面已經提到所有的控件外觀都是由一個或多個顯示單元組成的,顯示單元就是窗口里面的一個矩形區域,在這個區域中可以顯示一個背景(圖片或顏色)、一個邊框(圖片或顏色)、一張圖片和多行文本。其中背景、邊框、圖片的對齊方式、文本的字體、顏色和對齊 方式屬于這個顯示單元的風格或樣式,可以通過一個文本文件來設定。這個文本文件就是風格設置文件,一個簡單的例子如下:

#注釋(直到換行)
@include “another_style_file” #包含其他的風格設置文件,
window { #設定窗口控件的默認風格
bg="win_bg.png", stretch_tile #設定窗口背景圖片,平鋪顯示
}
button { #設定按鈕控件的默認風格
bg=”file1.png”, stretch_hv3 #設定背景圖片,采用九宮格拉伸顯示方式 text_color=rgb(255,0,0) #設定顯示文本的顏色是紅色font=”default-12:bold” #設定顯示文本的字體名,大小 12像素,加黑text_aline=text_left, text_bottom #設定文字的水平左對齊,垂直下對齊
image_aline=image_top #設定圖片為垂直上對齊(水平默認居中對齊)
}
button.ok { #設定風格名為”ok”的按鈕控件的風格
[nd] #設定當控件狀態是普通和無效時的外觀
bg=”normal.png”, stretch_hv3
[as] #設定當控件狀態是活動和選中時的外觀
bg=”active_png”, stretch_hv3
在一個風格設置文件里可以設置多個風格,也可以包含另一個風格設置文件,另一個文 件名可以是絕對路徑,也可以是相對路徑(相對于包含它的風格文件所在的路徑)
每個風格的格式為:
type 或者 type.name {
[status]
item=value
item=value, value
}

1)type表示該風格對應的控件類型,常用的類型有:

type

說明

button

普通按鈕

bool_button

布爾按鈕

window

窗口

text

單行文本框

textarea

多行文本框

processbar_h_thumb

水平進度條的滑塊

processbar_h_process

水平進度條的進度指示

processbar_h_carrier

水平進度條的背景

processbar_v_thumb

垂直進度條的滑塊

processbar_v_process

垂直進度條的進度指示

processbar_v_carrier

垂直進度條的背景

在以后開發新的控件時,也可以動態聲明新的風格類型。

2)name表示該風格的名字,如果沒有 name,表示該風格是該控件類型的默認外觀。

在前面“ 控件的創建” 這一節介紹了 TwCreate()函數的參數 style指明新控件的風格名字,如果不存在該類型的指定名字的風格或者 style為 NULL時,就采用該類型的默認風格。

type和 name一起唯一標識一個風格,當之前已經設定過有相同 type和 name的風 格時,前一個風格的內容將被替換,除非前一個風格的 type前面有一個感嘆號!。

4)status表示控件的狀態,用四個字母 n,a,s,d或者 N,A,S,D分別表示控件的正常(normal)、激活(active)、選中(select)、無效(disable)四個狀態??梢醞鄙瓚ǘ喔鱟刺姆綹衲諶?。當沒有[status]時,表示設定的是所有狀態的風格內容(即等價于[nasd])。

如果一個風格設定中有多個[status]時,注意多個 status不要有重疊,因為重疊的狀態只取起前面的。

控件被創建時,狀態都是正常(normal),然后才轉為其他三個狀態,外觀也會相應的改為風格中的設定內容,風格中沒有設定的內容不會改變。

5)item就是風格中可以設定的項目,value就是項目的值,可以是顏色、圖片、整數或字符串。不同的 item會要求不同類型的 value,也可能要求多個 value。item

value

例子

說明

bg

(背景)

顏色

bg=rgb(255,200,200)

 

圖片

bg=”bg.png”, stretch_hv3

bg=”None” #特殊圖片, 表示沒有背景

stretch_hv3 是圖 片的 一 種拉 伸 方式

父親相關

bg=”ParentRelative”

父親相關模式

img

圖片

img=”img.png”

img=”None” #特殊圖片, 表示沒有

 

border

(邊框,大小 可以為 0)

顏色、類型、

大小

border=rgb(255,200,200),border_rect,2

border_rect是一

種邊框類型

圖片、大小

border=”border.png”,2

邊框為 2個像素

border_mar

gin

( 邊 框 和 中間 文 本 或 圖的 間 距 (上 , 下,左,右四個方向)

1 個整數

border_margin=5

左,上,右,下邊都

為 5個像素

2 個整數

border_margin=5,6

左,右為 5;上,下

為 6

3 個整數

border_margin=5,6,7

左為 5;上,下為 6;

右為 7

4 個整數

border_margin=5,6,7,8

左為 5;上為 6;

右為 7;下為 6

text_aline

(文本的對齊方式)

text_left

text_aline=text_left

左對齊,垂直居中

text_right

text_aline=text_top

水平居中,上對齊

text_xfollow

text_aline=text_xfollow,text_top

水 平方 向 在圖 片

后面,上對齊

text_top

text_aline=text_top,text_left

上對齊,左對齊

text_bottom

text_aline=text_bottom,text_left

下對齊,左對齊

text_yfollow

text_aline=text_yfollow

垂 直方 向 在圖 片

下面,水平居中

image_aline( 圖 片 的 對齊方式)

image_left

image_aline=image_left

左對齊,垂直居中

image_right

image_aline=image_right,image_top

右對齊,上對齊

image_top

image_aline=image_top

上對齊,水平居中

image_bott om

image_aline=image_bottom,ima ge_left

下對齊,左對齊

text_margin

一個整數

text_margin=2

兩 行文 本 的間 距

為 2個像素

image_margin

一個整數

image_margin=4

當 文本 的 對齊 方式在圖片后面時,圖 片和 文 本的 間 距為 4個像素

text_color( 文 本 顯 示的顏色)

文本顏色

text_color=rgb(0,0,0)

黑色文本

文本顏色,文本背景顏色

text_color=rgb(0,0,0),rgb(0,255,0)

黑色文本,并且文本的背景為綠色

font

(文本顯示的字體)

一個表示字體

名的字符串

font=”default-16”

默認字體,大小為16像素

font=”yahei-16:bold”

字體名”yahei”,16像素,加黑

風格中出現的圖片文件的路徑都是相對于該風格文件所在的目錄。

當背景是圖片時,因為圖片的大小和顯示單元的大小可能不一致,所以需要拉伸顯示, 拉伸的方式有:

圖片對齊方式

說明

stretch_normal

普通拉伸(水平和垂直方向都放大或縮?。?/p>

stretch_hv3

把圖片切為 3x3的 9塊,4個角的不拉伸,四個邊塊水平或垂直拉

伸,中間塊普通拉伸。

stretch_hv2

把圖片切為 2x2的 4塊,4個角的不拉伸,對兩條分隔線及其交叉

點進行拉伸。

stretch_tile

平鋪,不拉伸。

注意:窗口的背景圖片只能是平鋪,窗口沒有前景圖片。前景圖片只能是普通拉伸。

背景可以設置成一種特殊的模式:“ ParentRelative”(父親相關模式),這種模式下的背景和父窗口的背景相同,常用于滾動顯示區域時保持背景不滾動。

風格中設定的邊框類型目前有:

邊框類型

說明

border_rect

簡單矩形邊框

border_circle

圓角邊框

border_down

凹邊框

border_up

凸邊框

border_right_br

下邊和右邊有線條的邊框

border_right_b

下劃線邊框

border_right_b_d

下劃線虛邊框

border_blank

空白框,不顯示任何線條,只用來占位

必須要先加載風格設置文件,才能創建使用其中的風格:

void TwStyleParseFile(const char *file) //加載風格文件
例子:
TwStyleParseFile(“/some/path/style.rc”);
文件名可以是絕對路徑,也可以是相對路徑,但是當程序的路徑不固定,并且程序運行
時的當前路徑也不固定時,那么絕對路徑和相對路徑都無法確定。這時就可以使用在《TD圖形軟件系統開發平臺_基礎》講到的獲取程序絕對路徑的函數,來確定風格文件的路徑:
/* 假定程序為/some/path/bin/file1,風格文件為/some/path/style/file2 */
TwStyleParseFile(TGetExecutePath(“../style/file2”));
7)多語言支持

多語言支持是指在用戶界面上顯示的靜態文本能夠根據當前的語言環境,自動顯示為翻
譯后的文本內容,用戶程序不需要改動。TD圖形軟件系統控件系統的多語言支持類似于 Linux下的GetText機制。首先需要用戶先編輯一個翻譯文件,文件的內容如下:
“string1”=”字符串 1”
“string2”=”字符串 2”
“ok”=”確定”
即每一行是一項翻譯,等號前面是程序中出現的字符串,等號后面是翻譯后的文本串。 注意:該翻譯文件的編碼必須是 UTF-8。
然后加載翻譯文件:

void TwTransParseFile(const char * file);
/* 假定程序為/some/path/bin/file1,翻譯文件為/some/path/trans/file3 */
TwTransParseFile(TGetExecutePath(“../trans/file3”));
該函數可以調用多次加載多個翻譯文件,但是如果等號左邊的字符串重復了,將忽略這一行。當用戶需要得到某個字符串 string的翻譯結果時,調用下面的函數:
const char * TwTrans(const char * string);
例如:TwTrans("ok"); //把”ok”翻譯成等號右邊的內容(”確定”)
注意:當翻譯文件中不存在要翻譯的字符串時,twTrans()就返回參數 string。
注意:設置到控件上顯示的文字,控件內部都會調用 twTrans()函數來自動翻譯,即 TwSetCaption(button_ok, "ok")按鈕上顯示的文字是”ok”被翻譯的內容。
8)示例

最后還有幾個常用的全局函數:

TWidget *TwAppInit(void); //控件系統初始化,返回根窗口控件
void TwMainLoop(void); //控件系統的事件循環,內部其實就是調用:
//while(1) TTaskLoopOnce(0);
void TwUpdateShow(void); //立即更新界面的顯示
當調用某些函數導致控件外觀發生變化時,界面并沒有立即更新,而是等到一輪事件都
處理完畢后才一起自動刷新,這樣可以提高系統的性能。用戶也可以調用 TwUpdateShow()立即更新界面顯示。
通過上述統一的方法調用和事件就可以完成界面編程開發的大部分工作,比如一個完整 的 hello例子:
#include <TWidget/TWidget.h> //包含控件系統的頭文件
TWidget *root, *mainwindow, *button_ok, *button_cancel; //定義用到的控件 指針
void cancel_click_callback(void *obj, T_ID event, TTable *in, void *arg, TExist *exist) {
exit(0); //退出程序
}
void ok_click_callback(void *obj, T_ID event, TTable *in, void *arg, TExist *exist) {
TLogD("you have click button %s\n", TwGetCaption(obj, NULL));
}
int main(int argc, char **argv)
{
root = TwAppInit(); //初始化控件系統,得到根窗口指針
TwStyleParseFile(TGetExecutePath(“../style/style.rc”); //加載風格文件,可 以沒有
TwTransParseFile(TGetExecutePath(“../trans/trans.rc”); //加載翻譯文件, 可以沒有
//創建主窗口,設置標題
mainwindow = TwCreate(TW_WINDOW, root, 20, 20, 200, 100, NULL, 0);
TwSetCaption(mainwindow, "hello");
//創建按鈕,設置標題,注冊事件
button_ok = TwCreate(TW_BUTTON, mainwindow, 20, 20, 50, 30, NULL, 0);
編譯及運行見《TD開發環境》。

{ganrao}