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

cexer

cexer
posts - 12, comments - 334, trackbacks - 0, articles - 0
  C++博客 :: 首頁(yè) :: 新隨筆 :: 聯(lián)系 :: 聚合  :: 管理
轉(zhuǎn)帖請(qǐng)注明出處 http://m.shnenglu.com/cexer/archive/2008/08/07/58262.html


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

  未命名

  一般來(lái)說(shuō),這樣的控件的 ID 都定義是連續(xù)的,如果是這樣,那么 GUI 框架就有可能提供這樣一個(gè)接口,客戶端只需要對(duì)這個(gè)接口提供控件組的開(kāi)始 ID 和 結(jié)束 ID (以及通知消息的 ID),GUI 框架就能自動(dòng)地把這一組控件的消息映射到某一個(gè)消息處理函數(shù)。

MFC:

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

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


  然后就以用宏來(lái)將數(shù)據(jù)按鈕的消息映射到這個(gè)函數(shù)了:

   1: COMMAND_RANGE_HANDLER( IDB_0,IDB_9,numberClicked )

 

Win32GUI:

  Win32Gui 也提供了一這樣的接口,使用方法如下(不過(guò)這個(gè)消息處理函數(shù)好像無(wú)法知道到底是誰(shuí)被點(diǎn)擊了):

   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++ 沒(méi)有提供這樣的接口,所以如果要處理那些數(shù)字按鈕的點(diǎn)擊事件就比較麻煩,必須得這樣:

   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: }


  如果按鈕數(shù)目比較多,比如說(shuō)程序同時(shí)需要能輸入字母和數(shù)字,那么按鈕就至少有三十多個(gè),這個(gè)情況下,除非是CTRL+C,CTRL+V 的愛(ài)好者,否則都不會(huì)愿意這樣一個(gè)個(gè)地手動(dòng)映射。不過(guò)因?yàn)?ID 是連續(xù)的,當(dāng)數(shù)目太多的時(shí)候,可以利用循環(huán)來(lái)映射:

   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,我沒(méi)有找到這樣的接口,用 QT 來(lái)實(shí)現(xiàn)將這些數(shù)字按鈕的點(diǎn)擊消息映射到消息處理函數(shù)的代碼類似這樣(似乎對(duì)于按鈕的 clicked() 信號(hào),這樣多個(gè)按鈕的點(diǎn)擊事件用一個(gè)函數(shù)處理,在函數(shù)當(dāng)中也無(wú)法得知究竟是誰(shuí)被點(diǎn)擊了,不過(guò)其它帶參數(shù)的信號(hào)大概有些是可以的):

   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()) );


自己寫(xiě)的 GUI 框架:

  今天下午我在用自己的 GUI 框架寫(xiě)一個(gè)類似計(jì)算器測(cè)試程序的時(shí)候,發(fā)現(xiàn)了這種 Range 消息映射功能的重要性,于是看了看各框架對(duì)于這個(gè)功能的支持。

  自己的 GUI 框架不支持,不過(guò)研究了一下,寫(xiě)了一個(gè)模板:

   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 )的某個(gè)通知消息作統(tǒng)一處理(即使用一個(gè)特定的消息處理函數(shù)),只需要將消息類從這個(gè)模板派生即可,然后我寫(xiě)了一個(gè)模板作為一般的“范圍 ID 的命令消息”類的實(shí)現(xiàn):

   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: };


  利用這個(gè)模板來(lái)實(shí)現(xiàn)用計(jì)算器程序當(dāng)中 IDB_0 到 IDB_9 的按鈕的點(diǎn)擊事件處理的代碼像這樣:

   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: }


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

   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: };


  利用這個(gè)模板來(lái)實(shí)現(xiàn)用計(jì)算器程序當(dāng)中 IDB_0 到 IDB_9 的按鈕的點(diǎn)擊事件處理的代碼像這樣:

   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 的命令消息統(tǒng)一處理)[未登錄](méi)  回復(fù)  更多評(píng)論   

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 的命令消息統(tǒng)一處理)[未登錄](méi)  回復(fù)  更多評(píng)論   

2008-08-08 11:55 by eXile
上面有些錯(cuò)誤:

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 的命令消息統(tǒng)一處理)  回復(fù)  更多評(píng)論   

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

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

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

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

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

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

2008-08-09 18:50 by 陳梓瀚(vczh)
事實(shí)上非編譯時(shí)期綁定的事件處理函數(shù)更加易于給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>
            黄色成人在线免费| 欧美激情小视频| 久久这里只精品最新地址| 亚洲一区在线观看视频 | 国产最新精品精品你懂的| 国产精品美女视频网站| 国产手机视频精品| 在线日本成人| 日韩亚洲精品电影| 亚洲伊人网站| 欧美人与性动交a欧美精品| 欧美日韩成人在线视频| 欧美日韩国产在线看| 国产精品久久波多野结衣| 国产农村妇女精品一区二区| 伊人蜜桃色噜噜激情综合| 亚洲欧洲精品一区二区精品久久久| 亚洲精品一区久久久久久| 亚洲男人第一av网站| 久久中文字幕导航| 亚洲精品社区| 欧美一区二区三区的| 猫咪成人在线观看| 国产精品久久久一区麻豆最新章节| 国产精品一级久久久| 在线成人免费观看| 亚洲线精品一区二区三区八戒| 欧美亚洲三级| 亚洲在线中文字幕| 久久久一二三| 99av国产精品欲麻豆| 篠田优中文在线播放第一区| 欧美精品v日韩精品v国产精品| 国产欧美日韩麻豆91| 在线视频精品| 亚洲国产精品v| 亚洲欧美综合国产精品一区| 欧美激情精品久久久| 极品av少妇一区二区| 性做久久久久久免费观看欧美| 亚洲黄色有码视频| 久久国产福利| 国产精品羞羞答答| 亚洲你懂的在线视频| 亚洲精品一区二区三区福利| 欧美电影打屁股sp| 在线免费观看一区二区三区| 欧美在线啊v| 亚洲午夜女主播在线直播| 欧美日韩激情网| 亚洲第一天堂av| 免费在线观看一区二区| 欧美一区高清| 国产日韩欧美精品| 亚洲欧美综合另类中字| 一本久久a久久免费精品不卡| 欧美电影免费观看网站| 亚洲黄色av| 亚洲黄网站在线观看| 欧美电影打屁股sp| 99热在这里有精品免费| 欧美激情中文不卡| 你懂的视频欧美| 亚洲国产精品久久久| 亚洲高清资源综合久久精品| 欧美电影在线观看完整版| 亚洲欧洲日夜超级视频| 亚洲欧洲视频| 在线视频你懂得一区| 欧美日韩在线播放一区二区| av成人天堂| 亚洲专区欧美专区| 国产欧亚日韩视频| 久久久午夜精品| 久久一区二区视频| 一本一本久久| 亚洲女人天堂av| 国产一区二区黄色| 男人的天堂亚洲| 欧美日韩视频在线第一区| 亚洲一区二区精品视频| 欧美亚洲一区二区三区| 极品尤物久久久av免费看| 亚洲国产精品久久久久| 欧美体内谢she精2性欧美| 久久精品视频在线看| 免费欧美高清视频| 亚洲欧美激情一区二区| 久久久久久综合网天天| 亚洲日本电影| 亚洲一区二区在线| 激情综合亚洲| 一区二区三区欧美激情| 狠狠色伊人亚洲综合网站色| 亚洲国产精品悠悠久久琪琪| 国产精品视频自拍| 免费在线国产精品| 国产精品激情av在线播放| 久久久久国产精品厨房| 欧美精品一区二区三区一线天视频 | 久久噜噜噜精品国产亚洲综合| 亚洲国产精品久久久久婷婷老年| av不卡在线观看| 尤物在线观看一区| 一本色道久久综合亚洲91| 国内久久视频| 亚洲图片在线观看| 亚洲国产高清aⅴ视频| 亚洲欧美一区二区激情| 一道本一区二区| 免费观看日韩av| 久久精品动漫| 国产精品日韩一区二区三区| 日韩视频不卡| 亚洲黄色在线观看| 欧美一区二区三区免费视| 亚洲一区二区在线观看视频| 免费在线观看精品| 久久久综合网站| 国产麻豆9l精品三级站| 亚洲精品国久久99热| 亚洲大胆美女视频| 久久国产加勒比精品无码| 亚洲综合色自拍一区| 欧美a级片网| 欧美成人亚洲成人| 国产三区精品| 亚洲女人天堂av| 欧美一区二区三区视频在线| 国产精品麻豆va在线播放| 亚洲尤物影院| 欧美片第一页| 亚洲精品亚洲人成人网| 91久久久精品| 欧美激情小视频| 亚洲精品在线电影| 日韩亚洲精品在线| 欧美日韩一区在线| 亚洲一区久久久| 欧美一区二区三区在线观看视频 | 亚洲日产国产精品| 欧美福利电影网| 亚洲精品一区久久久久久| 一区二区三区欧美亚洲| 欧美视频精品一区| 亚洲免费在线视频| 久久久精品免费视频| 国内精品久久久久久久97牛牛| 午夜精品久久久久影视| 久久露脸国产精品| 亚洲国产欧美日韩精品| 欧美日产在线观看| 亚洲制服av| 久热精品视频在线免费观看| 亚洲第一区在线观看| 欧美日韩精品在线视频| 亚洲尤物精选| 免费视频最近日韩| 一区二区精品| 国产精品久久久一区二区| 欧美影院在线| 亚洲激情图片小说视频| 亚洲伊人一本大道中文字幕| 狠狠网亚洲精品| 欧美日本一区| 久久成人国产| 亚洲精品国产日韩| 久久女同精品一区二区| 99精品视频免费| 今天的高清视频免费播放成人| 欧美日韩国产一级| 久久精品国产免费观看| 日韩一区二区电影网| 久久久久久亚洲综合影院红桃 | 最新国产成人av网站网址麻豆| 欧美色网一区二区| 久久久国产视频91| 99精品黄色片免费大全| 久久这里只有| 欧美一区二区视频免费观看| 99精品视频免费| 一区二区三区在线视频观看| 国产精品二区在线观看| 欧美第一黄色网| 久久福利毛片| 亚洲自拍偷拍麻豆| 亚洲精品久久久久久下一站| 蜜桃av综合| 久久免费国产| 亚洲欧美日韩在线不卡| 亚洲久色影视| 1024成人网色www| 国产一区二区三区高清| 国产精品久久久久久久久借妻 | 欧美日韩国产va另类| 免费一级欧美片在线播放| 久久精品人人做人人爽| 性欧美暴力猛交另类hd| 亚洲欧美激情一区二区| 一本大道久久a久久精品综合 |