《匠人手记》推荐网上购书渠道:
互动出版网(china-pub)购书入口   >>>
当当网(dangdang)购书入口   >>>
卓越亚马逊网 购书入口   >>>
淘宝网(taobao)购书入口   >>>
更多购书渠道……   >>> 

设为首页加入收藏联系匠人管理入口21IC首页21IC博客21IC社区侃单片机回复的贴参与的贴

天气预报
百宝日历
载入中...

百宝专栏

载入中...
最新货色

载入中...

粉丝评论

载入中...

载入中...



百宝信息

载入中...

百宝流量

(2006-07-01开始)


匠人手记

 匠人观点: 好记性不如烂笔头  
 黑色幽默:三鹿门——后世畅想

事件驅動觀念
程序匠人 发表于 2006-5-27 0:38:00  阅读全文 | 回复(0) | 引用通告 | 编辑

事件驅動觀念

基本觀念

Palm與許多其它的應用程式一樣, 是採用事件驅動的方式來撰寫程式, 如果你曾經用過VB, VFP, VC, Delphi, 你應該對事件驅動的觀念並不陌生, 因為這些程式都是採用事件驅動的方式來開發程式.

什麼是事件驅動呢? 簡單來說, 當外界對Palm作了任何的動作後, 都會透過硬體的插斷傳入一個訊號給作業系統Palm OS, 而OS收到訊息後, 就會產生一個事件. 當然了, 事件並不一定是完全由硬體觸發產生, 也有可能由軟體產生一個事件. 舉例來說, 當觸筆點到螢幕上時, 會有硬體插斷產生一個PenDown的事件, 而PenDown的事件, 交給作業系統後, 可能會另外產生memuDown事件.

透過事件的產生, 我們在程式中, 只要透過解析事件, 即可依據事件的狀態, 決定下一步動作. 這也就形成了程式開發的基礎.

事件迴圈

在傳統的程式中, 通常在程式啟動完成後, 都會加一行 read events的指令, 一般在高階語言中, 有時候並不真正知道這行程式的用意, 只知道要寫下此行程式, 軟體才能順利執行. 其實 read events是事件驅動程式裡面一個很重要的觀念, 它就是讓程式進入一個無窮迴圈裡面, 不斷地去偵側事件的產生, 然後再依據產生的事件, 去回應事件的動作.

迴圈裡面究道是作什麼事呢? 其實它就是一組 Do while ( Loop ) 的語法, 如果迴圈裡面, 不作任何處理, 則程式一旦進入, 就永遠不會出來, 因為沒有一個適當的出口給它. 當然了, 沒有人會這樣寫程式, 讓程式跳不出來, 所以我們會在迴圈裡面寫一個判斷式, 只要遇到某一種狀況, 就要離開此迴圈, 然後讓程式順利結束. 通常這種狀況是發生在, 當使用者按了某個結束鈕後, 由此鈕的程式中, 去產生一個結束事件, 然後在迴圈中的判斷式中, 寫到當某個事件值等於結束事件時, 就跳出迴圈.

Palm程式的寫法, 也不脫離這樣的觀念, 它也是在程式啟動完成後, 即進入無窮迴圈中, 並等待結束事件產生後, 則離開程式. 但由於Palm沒有結束程式的觀念, 因此它並不像Windows程式一樣, 要有一個結束按鈕, 或在功能表中有一個結束的項目, 用來離開程式. Palm本身因為是單工的作業系統, 因此一次只能作一件事, 所以無法開發多執行緒的程式, 所以它所謂的程式結束, 其實是只要其它的程式一開始, 就是上個程式的結束. 因此在事件迴圈中, 系統會自動偵測到結束事件, 而我們的程式因收到一個結束事件, 而跳出迴圈.

事件迴圈程式

static void AppEventLoop (void)

 { Word error;

  EventType event;

  do {

    EvtGetEvent (&event, evtWaitForever);

    PreprocessEvent (&event);

     if (! SysHandleEvent (&event))

      if (! MenuHandleEvent (NULL, &event, &error))

       if (! ApplicationHandleEvent (&event))

        FrmDispatchEvent (&event);

   }

  while (event.eType != appStopEvent);

 }

對於每個 Palm 程式而言,它一定有一個 PilotMain 函式作為開始,如下範例:

DWord PilotMain( Word cmd, Ptr cmdPBP, Word launchFlags)

{   

 return StarterPilotMain(cmd, cmdPBP, launchFlags);

}

我們會在 PilotMain 函式裡面,呼叫一個我們自訂的 StarterPilotMain 函式,然後從 StarterPilotMain 函式開始進入我們的程式.究竟上述的 AppEventLoop 函式要寫在那裡呢?其實就是寫在 StarterPilotMain 函式中,而且是當它處理完了所有程式的起始動作後,然後呼叫此 AppEventLoop 函式,開始進入事件迴圈中.在 5-1 開始一個範例程式中,會有一個標準的範例程式範本.

接著,我們就來看看這個事件迴圈是如何處理所有的事件.

一開始的 do { ... } while (event.eType != appStopEvent); 動作,是表示不斷地重覆執行迴圈,直到接收到一個appStopEvent事件,才結束,也就是迴圈的出口.什麼時候系統會產生此事件呢?一般是當你啟動另外一個程式的時候,appStopEvent事件會被觸發,然後你的程式也隨之結束.

一旦進入事件迴圈,第一件事就是透過 EvtGetEvent (&event, evtWaitForever); 抓取事件值,並放在 event 變數中,接下來進行 PreprocessEvent (&event); 這是作一些事件的準備動作,由你自己去完成,所以本函式可有可無,不一定需要.

接著連續執行下列動作,當其中一段不成立時,表示接收到的事件,在此函式中沒有或不需被處理,因此接著進行下一個函式來處理此事件.

if (! SysHandleEvent (&event))

 if (! MenuHandleEvent (NULL, &event, &error))

  if (! ApplicationHandleEvent (&event))

   FrmDispatchEvent (&event);

我們會透過參數傳遞,將我們接收到的事件,傳入給事件處理函式來處理它.什麼是事件處理函式呢?凡是xxxHandleEvent( ) 種類的函式,我們統稱事件處理函式,意思是指本函式是要用來處理事件規則的函式.

SysHandledEvent( ) ; 處理系統預設事件,像是硬體方面的事件,如 Turn on , Turn off 等.

MenuHandleEvent( ) ; 處理目前功能表的事件,當你點到功能表位置時,產生的事件,交由它處理.

ApplicationHandleEvent( ) ; 當傳入的事件不是系統事件,也不是功能表事件時,則呼叫應用程式事件函式,交由它來處理事件.

FrmDispatchEvent( );將事件導引到 Form 的事件處理函式來處理.意思就是說,經過上面三個函式都無法處理的事件,則需要透過目前的 Form 事件處理函式,來處理它.本函式的作用,就是會呼叫目前的 Form 事件處理函式.

前三個事件處理函式都比較容易理解,最後一個 FrmDispatchEvent 就比較難懂.其實,簡單地說,前二個事件處理函式,主要是處理系統本身的訊息,我們不太需要管它,而第三個程式事件處理函式,就是我們自己要寫的.

第三個事件處理函式,我們稱它為應用程式事件處理函式,一個 Palm 程式僅需要一個應用程式事件處理函式即可,一般命名為 ApplicationHandleEvent( ).它的功能僅是很簡單地偵側到目前是那個 Form 被啟動,然後,用 FrmSetEventHandler( ) 來設定目前 Form 的事件處理函式,設定好了後,當執行到 FrmDispatchEvent( ) 函式時,它就會呼叫目前 Form 的事件處理函式.

來看看 ApplicationHandleEvent( ) 它的寫法:

static Boolean ApplicationHandleEvent( EventPtr eventP)

{  

 Word formId;  

 FormPtr frmP;  

 if (eventP->eType == frmLoadEvent)   

 {  

  // 載入 Form 的資源號碼

  formId = eventP->data.frmLoad.formID;

  frmP = FrmInitForm(formId);

  FrmSetActiveForm(frmP);

  // 依據偵測到的 Form ID ,來決定設定目前 Form 的事件處理函式

  switch (formId)    

  {

   case MainForm:

     // 將目前的 Form 事件處理函式,指向設為 MainFormHandleEvent( )

     FrmSetEventHandler(frmP, MainFormHandleEvent);     

     break;     

   default:

   break;    

  }   

  return true;   

 }   

 return false;

}

當 MainForm 被啟動時,會被 ApplicationHandleEvent( ) 抓到它的 FormID值,然後將本 Form 的事件處理函式設為 MainFormHandleEvent( ),也就是當 FrmDispatchEvent( ) 被執行時,會呼叫 MainFormHandleEvent( ) 函式,然後我們再將要處理的程式寫在 MainFormHandleEvent( ) 函式中.

再重覆一次,一個應用程式只需一個 ApplicationHandleEvent( ),然後看它需要幾個 Form,就有幾個 FormHandleEvent( ),也就是每個 Form 有它自己的事件處理函式,這是你應該注意的.

看《匠人手记》,与匠人同行!北航出版,正在热卖!

发表评论:
载入中...

芯片专题

器件专题

软件专题

硬件专题

综合专题

项目专题

原创专题

器件检测
LCD LED
按键 触摸键
E2PROM
电池 电机
电阻 电容 电感

指令系统
软件算法
编程规范
滤波算法
串行通讯

PCB设计
I2C PWM
红外遥控
充电技术
中断 ADC 

匠人手记
匠人夜话
网络心路
一周热点串烧
从零开始玩PIC
DIY旋转时钟

广告5号位 [投放]


学习板、开发板、编程器、下载器、仿真器(查看详情……)

广告3号位 [投放]

站内搜索


站外搜索


百度  google
mp3  歌词 
图片  FLASH 
知道  文档
新闻  词典 
地图  mp3 
软件  天网 
雅虎  爱问 
搜狗  讯雷 
网讯  华军 
天空 

21IC器件搜索
百宝箱分站
  • 《匠人的百宝箱》21IC站
  • 《匠人的百宝箱》21IC笔记团队
  • 《匠人手记》21IC书友会
  • 《匠人的百宝箱》MCUBLOG站
  • 《匠人的百宝箱》MCUBLOG笔记团队
  • 《匠人的百宝箱》EDN站
  • 《匠人手记》EDN书友会
  • 《匠人的百宝箱》与非网站
  • 《匠人的百宝箱》新浪站
  • 《匠人的百宝箱》百度站
  • 《匠人的百宝箱》网易126站
  • 《匠人的百宝箱》网易163站
  • 《匠人的百宝箱》互动出版网站
  • 广告4号位 [投放]

     
     

    匠人原创

    往日酷贴

     
     
     

    大千八卦

    友情连接

    新浪新闻:
    新浪财经:
    AK58新闻:
    新浪股票:
    新浪股票:
    证券之星:

     [更多酷站连接]

     

     

    [欢迎交换连接]

    [百宝箱之与非门分舵]

    [电脑圈圈的家当]

    [IC921的博客]

    [柔月阁]

    [八楼的呼吸]

    [hotpower 的水潭]

    [xwj的文君阁]

    [所长的BLOG]

    [阿摆手记]

    [电子伙伴]

    [unaided的笔记]

    [小飞的笔记]

    [单片机开发联盟]

    [网址之家]

    [好东西网址大全]

    [美萍中文精选]

    [数字电视之家]

    [SMARTCODE电子书斋]

    [软件开发之窗]

    [Armoric]

    [我爱研发网]

    [infernal的笔记]

    [雄鹰的空中加油站]

    [SunK]

    [逍遥电子]

    [ningpanda的博客]

    [C-Design]

    [一网见天下]

    [海边淘沙]

    [嵌入式365]

    [水牛的仓库]

    [股剩是怎样炼成的]

    [PIC论坛]

    [ICC AVR开发网]

    [中国高校自动化网]

     

     

     

    MCU博客-中国电子工程师博客网 

    大学生电子网 

     

     

     

     

     

    !!! 《匠人的百宝箱》 !!!