小男孩‘自慰网亚洲一区二区,亚洲一级在线播放毛片,亚洲中文字幕av每天更新,黄aⅴ永久免费无码,91成人午夜在线精品,色网站免费在线观看,亚洲欧洲wwwww在线观看

分享

Fltk源碼學(xué)習(xí)筆記 | 喔滴剝殼

 duoyun 2012-09-15

2010年09月18日

Fltk源碼學(xué)習(xí)筆記

Filed under: UI框架&UI引擎 — 邱金武 @ 8:20 下午

      本文基于Windows操作系統(tǒng)下的Fltk 2.0版本,使用VS2008。該版本和之前的版本改動了不少地方,其招牌的FL_前綴去掉了,增加了貼圖支持和更好的非英文字符支持。不過代碼還是一如既往的“亂”。

      在深入源碼之前,先學(xué)習(xí)一下Fltk的基本用法。一個簡單的Sample如下:

int main(int argc, char **argv) {
  Window *window = new Window(300, 180);
  window->begin();
  Widget *box = new Widget(20, 40, 260, 100, "Hello, World!");
  box->box(UP_BOX);
  box->labelfont(HELVETICA_BOLD_ITALIC);
  box->labelsize(36);
  box->labeltype(SHADOW_LABEL);
  window->end();
  window->show(argc, argv);
  return run();
}

     

      這個Sample簡單的展現(xiàn)了Fltk程序的大致流程:

  1. 創(chuàng)建Window(窗口)
  2. 向該窗口塞控件
  3. 顯示窗口
  4. 進行Messsage Loop

 

窗口

      Fltk窗口使用Window類表示,該類派生自Widget。不過和普通的Widget不同的是,Window加入了窗口操作函數(shù),比如最大化窗口等。同時Window作為一個控件樹(本身也是一個控件)的根節(jié)點,它包含一個定位控件的邏輯,即在收到消息后定位具體的控件,并將消息派發(fā)給它。

 

控件樹

      Fltk不用顯式地往控件中插入子控件,這個操作通過 Group類Window類派生自它)的begin和end成員函數(shù)來完成。

      它的實現(xiàn)原來相當之簡單,在Group類中定義了一個靜態(tài)成員 static Group *current_,當調(diào)用begin函數(shù)時,就將該靜態(tài)變量賦值為自己的指針this),當調(diào)用end函數(shù)時,將它賦值為父控件的指針。當一個控件創(chuàng)建時,會查詢上述靜態(tài)變量是否為空,如否則將自己插入上述容器控件,具體見Widget類的構(gòu)造函數(shù)。

      在Fltk中,有普通控件Widget和容器控件Group 之分,區(qū)別是Group可以包含子控件。Widget包含一個Group指針來指向父控件,Group則還包含一個Widget**指針來包含子控件。Fltk就通過上述結(jié)構(gòu)來構(gòu)造一棵控件樹。

 

窗口創(chuàng)建

      Window類的構(gòu)造僅僅只是初始化一些數(shù)據(jù),而真正的窗口并未創(chuàng)建。這個過程在Window類的函數(shù)void show(int argc, char **argv)實現(xiàn)。除了窗口創(chuàng)建CreateWindow,窗口顯示ShowWindow也在這一并實現(xiàn)。

      為了實現(xiàn)跨平臺,F(xiàn)tlk不可能直接實現(xiàn)操作系統(tǒng)API來做上述事情,所以在Window類下面又整了一個CreatedWindow類fltk\win32.h,在這個類的(靜態(tài))成員函數(shù)封裝操作系統(tǒng)API。實際的窗口創(chuàng)建操作在靜態(tài)成員函數(shù)CreatedWindow::create(Window* window)中實現(xiàn),具體的Api函數(shù)在函數(shù)指針對象__CreateWindowExW中Windows使用API CreateWindowEx。

 

多窗口管理

      Fltk支持多窗口,為了做到這一點,CreatedWindow類包含一個靜態(tài)成員 first。這是一個CreatedWindow指針。每一次創(chuàng)建新窗口(會生成一個CreatedWindow實例)后,就將當前的CreatedWindow指針放在這個鏈表的最前(窗口Destroy時從鏈表中清除)。整個鏈表就存儲著所有已經(jīng)創(chuàng)建的窗口。

      當收到窗口消息時,F(xiàn)ltk就通過窗口ID查詢上述鏈表獲得具體的窗口類實例,然后將消息派發(fā)給它。在Windows操作系統(tǒng)下,這個ID是HWND。而在X11平臺下,這個ID是XWindowsrc\run.cxx

 

消息循環(huán)

      Fltk通過運行全局函數(shù)run來進入消息循環(huán)。首先檢測是否還有窗口實例,如有則繼續(xù)wait,然后處理一些idle和timer等雜七雜八的消息,最后在操作系統(tǒng)層面的消息循環(huán)中等待。

 

消息

      Fltk在分發(fā)消息時,僅僅傳遞了一個消息ID,而沒有一些附加的消息,例如鼠標消息的坐標,按鍵消息的KeyValue等等。Fltk定義了一堆全局變量src\run.cxx,將這些附加信息放在那,每次收到新的窗口消息后,首先會更新需要更新的變量。在后面的控件處理中,可以去這些變量去查詢和獲取需要的值(這種方式可能比較“省”,可是做法鄙人不敢茍同)。

      對于鼠標消息,F(xiàn)ltk通過鼠標位置和控件的位置比較來定位。后添加的控件Z軸在上,所以如果兩控件重疊,后添加的控件將獲得鼠標消息。

      Fltk消息種類如下圖2.0版本沒有前綴FL_

      來源(http://www.ibm.com/developerworks/cn/linux/l-fltk/index.html

fasdf

      具體的定義在(fltk\events.h)

      Fltk所有的消息通過函數(shù)bool fltk::handle(int event, Window* window)來分發(fā)。Fltk和控件通過int Widget::send(int event)函數(shù)來傳遞消息,在該函數(shù)中會調(diào)用虛函數(shù) Widget::handle。

 

回調(diào)

      為了處理業(yè)務(wù)邏輯,需要向控件注冊回調(diào)。和MFC/WTL或者WxWidget等UI框架相比,F(xiàn)LTK的回調(diào)綁定機制相當簡單。這個綁定通過Widget類的成員函數(shù)callback實現(xiàn)。Fltk定義了幾個回調(diào)函數(shù)類型:

typedef void (Callback )(Widget*, void*);
typedef Callback* Callback_p; // needed for BORLAND
typedef void (Callback0)(Widget*);
typedef void (Callback1)(Widget*, long);

 

      在widget類中包含一個成員Callback*callback_,callback函數(shù)所做的就是給它賦值。不過這種實現(xiàn)也是有些不足,一是無法同時綁定多個回調(diào),而是對類成員函數(shù)(非靜態(tài))和仿函數(shù)支持不足。當然既然人家都叫Fltk,那也就無可厚非了。

      Fltk針對回調(diào)定義了一些Flag:

enum { // Widget::when() values
  WHEN_NEVER		= 0,
  WHEN_CHANGED		= 1,
  WHEN_RELEASE		= 4,
  WHEN_RELEASE_ALWAYS	= 6,
  WHEN_ENTER_KEY	= 8,
  WHEN_ENTER_KEY_ALWAYS	=10,
  WHEN_ENTER_KEY_CHANGED=11,
  WHEN_NOT_CHANGED	= 2 // modifier bit to disable changed() test
};

 

      這些標志通過widget類的成員函數(shù)when來設(shè)置,這些標志可以影響回調(diào)的調(diào)用機制。例如Button默認在鍵盤Release時觸發(fā)回調(diào),而設(shè)置WHEN_CHANGED標志后Press和Release都會觸發(fā)回調(diào)。

      Fltk這套回調(diào)機制雖然使用簡單,不過個人認為大可不必在widget這一層支持回調(diào)。試想Static控件一般情況下是不需要回調(diào)的,所以完全沒必要 給每一個控件強制分配一個回調(diào)指針。第二個,控件的回調(diào)需要什么格式很難用幾個簡單的定義覆蓋,而且這些標志位也很難覆蓋所有的需求,試想我需要在鼠標移 入按鈕時觸發(fā)回調(diào)用標志位怎么處理(雖然這個需求比較猥瑣)?所以最好是將回調(diào)綁定交給控件自己去實現(xiàn),底層僅僅將具體的消息分發(fā)給它。

(待續(xù))

    本站是提供個人知識管理的網(wǎng)絡(luò)存儲空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點。請注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購買等信息,謹防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點擊一鍵舉報。
    轉(zhuǎn)藏 分享 獻花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多