青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品

cexer

cexer
posts - 12, comments - 334, trackbacks - 0, articles - 0
  C++博客 :: 首頁 :: 新隨筆 :: 聯系 :: 聚合  :: 管理
轉帖請注明出處 http://m.shnenglu.com/cexer/archive/2008/08/07/58262.html


  有時候在界面上的一系列相關控件,它們作為一組相互協作提供一個功能,則在事件處理的時候,給這一組的控件僅提供一個事件處理程序,要比給每一個單獨的控件都提供一個事件處理程序要簡單得多,邏輯也更清楚。一個簡單的例子就是 windows 自帶的計算器程序界面上的按鈕 1,2,……,9。

  未命名

  一般來說,這樣的控件的 ID 都定義是連續的,如果是這樣,那么 GUI 框架就有可能提供這樣一個接口,客戶端只需要對這個接口提供控件組的開始 ID 和 結束 ID (以及通知消息的 ID),GUI 框架就能自動地把這一組控件的消息映射到某一個消息處理函數。

MFC:

  MFC 提供了這樣一個接口,就是 COMMAND_RANGE_HANDLER 宏。使用方法很簡單,用計算器的按鈕作為例子,假設計算器的數字按鈕從 0 到 9 的 ID 分別定義為從 IDB_0 到 IDB_9的十個常數,并且它們連續,遞增的。先定義一個消息處理函數:

   1: void numberClicked( UINT id,UINT code )
   2: {
   3:     int number = id - IDB_0;
   4:  
   5:     // do something else
   6:     // ....
   7: }


  然后就以用宏來將數據按鈕的消息映射到這個函數了:

   1: COMMAND_RANGE_HANDLER( IDB_0,IDB_9,numberClicked )

 

Win32GUI:

  Win32Gui 也提供了一這樣的接口,使用方法如下(不過這個消息處理函數好像無法知道到底是誰被點擊了):

   1: handle_event on_number_clicked() 
   2: {
   3:     // don't know who's been clicked
   4:     // do something 
   5:     // ...
   6:  
   7:     return command_range<IDB_0,IDB_9,BN_CLICKED>().HANDLED_BY(&me::on_number_clicked);
   8: }


SmartWin++:

  SmartWin++ 沒有提供這樣的接口,所以如果要處理那些數字按鈕的點擊事件就比較麻煩,必須得這樣:

   1: void nubmerClicked( WidgetButtonPtr button )
   2: {
   3:     int number = button->getID() - IDB_0;
   4:  
   5:     // do something else
   6:     // ....
   7: }
   8:  
   9: void initAndCreate()
  10: {
  11:     button0->onClicked( &This::numberClicked );
  12:     button1->onClicked( &This::numberClicked );
  13:     //.....
  14:     button9->onClicked( &This::numberClicked );
  15: }


  如果按鈕數目比較多,比如說程序同時需要能輸入字母和數字,那么按鈕就至少有三十多個,這個情況下,除非是CTRL+C,CTRL+V 的愛好者,否則都不會愿意這樣一個個地手動映射。不過因為 ID 是連續的,當數目太多的時候,可以利用循環來映射:

   1: void initAndCreate()
   2: {
   3:     for ( UINT i=IDB_0; i<=IDB_9; ++i )
   4:     {
   5:         WidgetButtonPtr button = this->subclassButton( i );
   6:         button->onClicked( &This::numberClicked );
   7:     }
   8: }

 

QT:
  QT 類似 SmartWin,我沒有找到這樣的接口,用 QT 來實現將這些數字按鈕的點擊消息映射到消息處理函數的代碼類似這樣(似乎對于按鈕的 clicked() 信號,這樣多個按鈕的點擊事件用一個函數處理,在函數當中也無法得知究竟是誰被點擊了,不過其它帶參數的信號大概有些是可以的):

   1: void numberClicked()
   2: {
   3:     // don't known who's been clicked
   4:     // do something
   5:     // ....
   6: }
   7:  
   8:  
   9: QPushButton* button0;
  10: QPushButton* button1;
  11: //....
  12: QPushButton* button9;
  13:  
  14:  
  15: connect( button0,SIGNAL(clicked()),this,SLOT(numberClicked()) );
  16: connect( button1,SIGNAL(clicked()),this,SLOT(numberClicked()) );
  17: //....
  18: connect( button9,SIGNAL(clicked()),this,SLOT(numberClicked()) );


自己寫的 GUI 框架:

  今天下午我在用自己的 GUI 框架寫一個類似計算器測試程序的時候,發現了這種 Range 消息映射功能的重要性,于是看了看各框架對于這個功能的支持。

  自己的 GUI 框架不支持,不過研究了一下,寫了一個模板:

   1: template<typename TCommand,WORD t_firstId,WORD t_lastId,WORD t_code>
   2: class RangeCommandBase
   3: {
   4:  
   5: protected:
   6:  
   7:     typedef RangeCommandBase<TCommand,t_firstId,t_lastId,t_code> _BaseRangeCommand;
   8:  
   9: public:
  10:  
  11:     UINT    mess;
  12:     WPARAM    wpar;
  13:     LPARAM    lpar;
  14:     WORD    id;
  15:     WORD    code;
  16:     DWORD    data;
  17:  
  18:   // .....   
  19: }


  如果需要將一組控件(ID 從 t_firstId 到 t_lastId )的某個通知消息作統一處理(即使用一個特定的消息處理函數),只需要將消息類從這個模板派生即可,然后我寫了一個模板作為一般的“范圍 ID 的命令消息”類的實現:

   1: template<WORD t_firstId,WORD t_lastId,WORD t_code>
   2: class RangeCommand:public RangeCommandBase<RangeCommand<t_firstId,t_lastId,t_code>,t_firstId,t_lastId,t_code>
   3: {
   4: public:
   5:     template<typename TWidget>
   6:     RangeCommand( TWidget*,UINT mess,WPARAM wpar,LPARAM lpar )
   7:         :_BaseRangeCommand( mess,wpar,lpar )
   8:     {
   9:  
  10:     }
  11:  
  12: };


  利用這個模板來實現用計算器程序當中 IDB_0 到 IDB_9 的按鈕的點擊事件處理的代碼像這樣:

   1: LRESULT onCommand( RangeCommand<IDB_0,IDB_9,BN_CLICKED>& numberClicked )
   2: {
   3:     int number = numberClicked.id - IDB_0;
   4:  
   5:     // do something else
   6:     // ......
   7:  
   8:     return numberClicked.handled(this);
   9: }


  如果不想每次都寫 BN_CLICKED,那么可以從 RangeCommandBase 的基礎上派生,派生的時候提供給該模板 BN_CLICKED 作為 t_code 參數即可,比如:

   1: template<WORD t_firstId,WORD t_lastId>
   2: class RangeButtonClicked:public RangeCommandBase<RangeButtonClicked<t_firstId,t_lastId>,t_firstId,t_lastId,BN_CLICKED>
   3: {
   4: public:
   5:     template<typename TWidget>
   6:     RangeButtonClicked( TWidget*,UINT mess,WPARAM wpar,LPARAM lpar )
   7:         :_BaseRangeCommand( mess,wpar,lpar )
   8:     {
   9:  
  10:     }
  11:  
  12: };


  利用這個模板來實現用計算器程序當中 IDB_0 到 IDB_9 的按鈕的點擊事件處理的代碼像這樣:

   1: LRESULT onCommand( RangeButtonClicked<IDB_0,IDB_9>& numberClicked )
   2: {
   3:     int number = numberClicked.id - IDB_0;
   4:  
   5:     // do something else
   6:     // ...
   7:  
   8:     return numberClicked.handled(this);
   9: }

Feedback

# re: 各 GUI 框架的 COMMAND_RANGE_HANDLER(范圍 ID 的命令消息統一處理)[未登錄]  回復  更多評論   

2008-08-08 11:50 by eXile
Qt中可以采用 QSignalMapper.

void numberClicked(int id) {}

QPushButton* button0;
QPushButton* button1;

QSignalMapper* map = new QSignalMapper(this);
connect(button0, SIGNAL(clicked()), signalMapper, SLOT(map()));
connect(button1, SIGNAL(clicked()), signalMapper, SLOT(map()));
map->setMapping(button0, 0);
map->setMapping(button1, 1);

connect(map, SIGNAL(mapped(int)), this, SIGNAL(numberClicked(id)));

# re: 各 GUI 框架的 COMMAND_RANGE_HANDLER(范圍 ID 的命令消息統一處理)[未登錄]  回復  更多評論   

2008-08-08 11:55 by eXile
上面有些錯誤:

QSignalMapper* map = new QSignalMapper(this);
connect(button0, SIGNAL(clicked()), map, SLOT(map()));
connect(button1, SIGNAL(clicked()), map, SLOT(map()));
map->setMapping(button0, 0);
map->setMapping(button1, 1);

connect(map, SIGNAL(mapped(int)), this, SIGNAL(numberClicked(int)));

# re: 各 GUI 框架的 COMMAND_RANGE_HANDLER(范圍 ID 的命令消息統一處理)  回復  更多評論   

2008-08-08 12:56 by cexer
@eXile
多謝,我對QT用得不多,我會把你這個方法更新到日志上去.

# re: 各 GUI 框架的 COMMAND_RANGE_HANDLER(范圍 ID 的命令消息統一處理)  回復  更多評論   

2008-08-09 02:52 by 陳梓瀚(vczh)
凡是做GUI最終都還是要做GUI Editor的。讓他去生成代碼,所有問題都不是問題。

# re: 各 GUI 框架的 COMMAND_RANGE_HANDLER(范圍 ID 的命令消息統一處理)  回復  更多評論   

2008-08-09 11:56 by cexer
@陳梓瀚(vczh)
GUI 太復雜了,GUI Editor 不可能完成所有的工作.而且有了這些接口,GUI Editor 的相關部分要容易實現得多.

# re: 各 GUI 框架的 COMMAND_RANGE_HANDLER(范圍 ID 的命令消息統一處理)  回復  更多評論   

2008-08-09 18:50 by 陳梓瀚(vczh)
事實上非編譯時期綁定的事件處理函數更加易于給GUI Editor提供便利。
青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            久久久免费观看视频| 欧美成人在线免费视频| 亚洲第一页在线| 亚洲国产午夜| 亚洲精品一区二区三区99| 黑人巨大精品欧美一区二区小视频| 欧美日韩理论| 欧美视频专区一二在线观看| 欧美体内she精视频在线观看| 欧美全黄视频| 国产精品乱码一区二三区小蝌蚪| 国产精品久久久久久av福利软件| 国产精品日日摸夜夜添夜夜av | 久久精品国产99国产精品澳门| 99视频一区二区三区| 日韩午夜免费| 欧美一级黄色录像| 久久久免费精品| 欧美日韩国产高清| 国产午夜精品麻豆| 久久国内精品视频| 欧美日韩免费高清一区色橹橹| 欧美日韩一区二区在线| 精品成人一区| 亚洲欧美日韩在线| 91久久极品少妇xxxxⅹ软件| 亚洲欧美国产视频| 欧美国产日本| 亚洲风情在线资源站| 欧美亚洲日本一区| 91久久黄色| 欧美精品一区二区三区久久久竹菊| 国产日韩精品久久| 亚洲尤物视频网| 一区二区三区四区五区精品视频| 久久国产主播精品| 国产视频观看一区| 亚洲欧美日韩精品一区二区| 亚洲乱码精品一二三四区日韩在线 | 欧美日韩免费网站| 久久精品成人| 欧美一区二区大片| 亚洲国产一区二区三区在线播| 欧美va亚洲va日韩∨a综合色| 亚洲人成人一区二区在线观看 | 亚洲一区在线视频| 亚洲激情网站免费观看| 免费久久99精品国产自| 亚洲美女一区| 一区二区三区视频观看| 国产亚洲精品一区二555| 欧美一区深夜视频| 欧美aⅴ99久久黑人专区| 在线观看日韩av先锋影音电影院| 久久综合一区二区三区| 欧美国产日产韩国视频| 99精品久久久| 亚洲综合精品| 亚洲国产天堂久久综合网| 亚洲国产成人在线视频| 欧美午夜视频一区二区| 久久精品免费电影| 免费成人在线视频网站| 亚洲制服av| 国产尤物精品| 国产欧美一区二区精品忘忧草 | 欧美国产亚洲视频| 午夜精品久久久久| 久久久天天操| 亚洲在线黄色| 欧美极品一区| 亚洲国产精品久久久久| 国内精品久久久| 先锋a资源在线看亚洲| 亚洲一区二区视频在线| 久久久综合视频| 国产精品永久免费| 一区二区三区视频在线观看| 亚洲午夜激情网站| 欧美日本高清视频| 一区二区不卡在线视频 午夜欧美不卡'| 国产亚洲成精品久久| 亚洲欧美日韩精品久久奇米色影视 | 久久蜜桃资源一区二区老牛| 性色av一区二区三区在线观看| 国产精品v欧美精品v日本精品动漫| 亚洲欧洲综合另类| 久久精品论坛| 欧美日韩在线视频首页| 亚洲综合精品| 欧美韩国一区| 欧美亚洲一级片| 激情综合色丁香一区二区| 麻豆成人av| 一区二区电影免费在线观看| 欧美亚洲视频一区二区| 一区免费视频| 欧美三区在线观看| 久久久夜夜夜| 日韩亚洲精品在线| 久久se精品一区精品二区| 亚洲精品久久久久久久久久久久久| 欧美色道久久88综合亚洲精品| 一区二区国产精品| 欧美激情精品久久久久久| 欧美在线日韩在线| 夜夜精品视频| 亚洲美女在线国产| 亚洲级视频在线观看免费1级| 亚洲日本va午夜在线电影 | 羞羞视频在线观看欧美| 91久久精品国产91久久性色tv | 亚洲美女一区| 国产精品a久久久久久| 美女国内精品自产拍在线播放| 亚洲欧美日韩精品久久亚洲区| 亚洲美女av电影| 亚洲精品久久视频| 欧美va天堂va视频va在线| 欧美在线观看www| 亚洲欧美日本国产有色| 中文日韩电影网站| 一区二区三区精品视频| 一区二区精品在线| 亚洲一区成人| 午夜亚洲性色福利视频| 久久狠狠久久综合桃花| 美女任你摸久久| 欧美福利视频一区| 亚洲免费大片| 久久av红桃一区二区小说| 久久久精品动漫| 欧美不卡福利| 欧美日韩在线视频首页| 国产欧美精品日韩区二区麻豆天美 | 一区二区欧美在线| 欧美一区二区三区免费看| 久久精品国产亚洲一区二区三区| 欧美成人高清视频| 亚洲专区一区| 欧美精品色综合| 尤物网精品视频| 亚洲激情网站| 欧美视频在线免费| 国内精品久久久久伊人av| 亚洲人成人99网站| 久久大逼视频| 夜夜爽夜夜爽精品视频| 欧美国产日韩二区| 亚洲国产一区二区a毛片| 亚洲专区免费| 中文精品视频| 欧美日韩国产专区| 亚洲黄色免费网站| 欧美高潮视频| 欧美成人精品在线| 亚洲欧洲一区二区三区久久| 老妇喷水一区二区三区| 欧美在线欧美在线| 国产欧美日韩免费| 久久午夜av| 羞羞视频在线观看欧美| 狠狠色丁香婷婷综合| 玖玖国产精品视频| 欧美一区免费视频| 在线观看欧美亚洲| 亚洲电影网站| 欧美日韩亚洲一区二区三区四区| 亚洲一区二区视频| 久久久99精品免费观看不卡| 亚洲国产精品欧美一二99| 亚洲美女在线国产| 国产在线播精品第三| 91久久精品一区| 国产精品日韩欧美大师| 性伦欧美刺激片在线观看| 91久久线看在观草草青青| 亚洲视频1区2区| 欧美激情免费在线| 性欧美暴力猛交另类hd| 男人的天堂亚洲| 在线精品一区二区| 亚洲欧美在线免费观看| 亚洲欧洲在线看| 欧美高清在线视频| 国产精品综合视频| 国内偷自视频区视频综合| 亚洲欧美日韩另类精品一区二区三区| 久久久久九九九九| 国产精品99免费看 | aa成人免费视频| 国产亚洲欧美在线| 中国av一区| 亚洲一区二区三区欧美| 欧美精品在线观看91| 久久久久成人精品免费播放动漫| 99re6热在线精品视频播放速度| 国产精品欧美一区喷水| 日韩一区二区福利| 亚洲一区美女视频在线观看免费|