• <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>

              Creative Commons License
              本Blog采用 知識(shí)共享署名-非商業(yè)性使用-禁止演繹 3.0 Unported許可協(xié)議 進(jìn)行許可。 —— Fox <游戲人生>

              游戲人生

              游戲人生 != ( 人生 == 游戲 )
              站點(diǎn)遷移至:http://www.yulefox.com。請(qǐng)訂閱本博的朋友將RSS修改為http://feeds.feedburner.com/yulefox
              posts - 62, comments - 508, trackbacks - 0, articles - 7

              項(xiàng)目中使用了消息通信機(jī)制,因?yàn)橄㈩愋头浅6?,相?yīng)的,處理消息的地方代碼也非常多。

              自然而然想到MFC中的消息映射:

              創(chuàng)建一個(gè)缺省MFC框架程序的解決方案Test,在Test.h中看到以下內(nèi)容:

              class Ctest_mfcApp : public CWinApp
              {
              public:
                  Ctest_mfcApp();

              // 重寫
              public:
                  virtual BOOL InitInstance();

              // 實(shí)現(xiàn)
                  afx_msg void OnAppAbout();
                  DECLARE_MESSAGE_MAP()
              };

               

              其中,最緊要的就是DECLARE_MESSAGE_MAP()這個(gè)宏,相關(guān)內(nèi)容展開如下:

              struct AFX_MSGMAP_ENTRY
              {
                  UINT nMessage;   // windows message
                  UINT nCode;      // control code or WM_NOTIFY code
                  UINT nID;        // control ID (or 0 for windows messages)
                  UINT nLastID;    // used for entries specifying a range of control id's
                  UINT_PTR nSig;   // signature type (action) or pointer to message #
                  AFX_PMSG pfn;    // routine to call (or special value)
              };

              struct AFX_MSGMAP
              {
                  const AFX_MSGMAP* (PASCAL* pfnGetBaseMap)();
                  const AFX_MSGMAP_ENTRY* lpEntries;
              };

              #define DECLARE_MESSAGE_MAP() \
              protected: \
                  static const AFX_MSGMAP* PASCAL GetThisMessageMap(); \
                  virtual const AFX_MSGMAP* GetMessageMap() const; \

              其中AFX_PMSG不再解析下去,我們認(rèn)為這是一個(gè)指向特定消息對(duì)應(yīng)的實(shí)現(xiàn)函數(shù)的函數(shù)指針,這幾個(gè)宏的作用可簡(jiǎn)單理解成為Test這個(gè)項(xiàng)目定義了一個(gè)靜態(tài)的消息映射表。當(dāng)消息到來時(shí),從消息隊(duì)列中彈出消息并分發(fā)到具有入口實(shí)現(xiàn)的上層CWnd派生窗口。用戶只需要注冊(cè)消息,實(shí)現(xiàn)消息入口函數(shù)就夠了,這在MFC中一般放在.cpp文件頭部。Test.cpp中頭部有以下內(nèi)容:

              BEGIN_MESSAGE_MAP(CTest, CWinApp)
                  ON_COMMAND(ID_APP_ABOUT, &CTest::OnAppAbout)
                  // 基于文件的標(biāo)準(zhǔn)文檔命令
                  ON_COMMAND(ID_FILE_NEW, &CWinApp::OnFileNew)
                  ON_COMMAND(ID_FILE_OPEN, &CWinApp::OnFileOpen)
                  // 標(biāo)準(zhǔn)打印設(shè)置命令
                  ON_COMMAND(ID_FILE_PRINT_SETUP, &CWinApp::OnFilePrintSetup)
              END_MESSAGE_MAP()

              這里是為消息枚舉值與消息實(shí)現(xiàn)函數(shù)建立映射,其中涉及到的宏的展開如下:

              #define ON_COMMAND(id, memberFxn) \
                  { WM_COMMAND, CN_COMMAND, (WORD)id, (WORD)id, AfxSigCmd_v, \
                      static_cast<AFX_PMSG> (memberFxn) },

              #define BEGIN_MESSAGE_MAP(theClass, baseClass) \
                  PTM_WARNING_DISABLE \
                  const AFX_MSGMAP* theClass::GetMessageMap() const \
                      { return GetThisMessageMap(); } \
                  const AFX_MSGMAP* PASCAL theClass::GetThisMessageMap() \
                  { \
                      typedef theClass ThisClass;                           \
                      typedef baseClass TheBaseClass;                       \
                      static const AFX_MSGMAP_ENTRY _messageEntries[] =  \
                      {

              #define END_MESSAGE_MAP() \
                      {0, 0, 0, 0, AfxSig_end, (AFX_PMSG)0 } \
                  }; \
                      static const AFX_MSGMAP messageMap = \
                      { &TheBaseClass::GetThisMessageMap, &_messageEntries[0] }; \
                      return &messageMap; \
                  }                                  \
                  PTM_WARNING_RESTORE

              按照上述思路得到的相似代碼如下:

              // Test.h
              typedef void (* funCall)(void*);        // 消息執(zhí)行函數(shù)類型

              struct tagMsgEntry                      // 消息入口結(jié)構(gòu)
              {
                  int            nMsgType;            // 消息類型
                  funCall        MsgRun;              // 消息執(zhí)行函數(shù)
              };

              struct tagMsgMap                        // 消息映射表結(jié)構(gòu)
              {
                  const tagMsgMap* (__stdcall* funGetBaseMsgMap)();
                  const tagMsgEntry* pMsgEntries;     // 消息入口集
              };

              class CMessage
              {
                  // ...
              protected:
                  static const tagMsgMap* __stdcall GetThisMsgMap();
                  virtual const tagMsgMap* GetMsgMap() const;
              };

              // Test.cpp
              const tagMsgMap* CMessage::GetMsgMap() const
              {
                  return GetThisMsgMap();
              }

              const tagMsgMap* __stdcall CMessage::GetThisMsgMap()
              {
                  static const tagMsgEntry MsgEntries[] =
                  {
                      { MSG_SOME_ONE, SomeOneFunc },
                      { MSG_SOME_TWO, SomeTwoFunc },
                      { MSG_NULL, NULL }
                  };
                  static const tagMsgMap msgMap =
                  {
                      &CBaseMessage::GetThisMsgMap,    // 父類消息映射表
                      &MsgEntries[0]
                  };
                  return &msgMap;
              }

              int CMessage::MsgProc(int nMsgType)
              {
                  switch( nMsgType )
                  {
                  case MSG_SOME_ONE:
                      {

                      }
                      break;
                  }
                  return CBaseMessage::MsgProc(nMsgType);
              }

              這種處理的優(yōu)點(diǎn)在于,子類沒有定義的消息實(shí)現(xiàn)接口,可以使用父類接口實(shí)現(xiàn)。不過在現(xiàn)在的消息處理中,我們一般不需要由基類來完成,因此可以不依賴基類接口,使用宏可以使代碼看上去更加簡(jiǎn)潔。

              ___________________________________________________________

              簡(jiǎn)化版本的消息映射采用以下方式,簡(jiǎn)單清晰:

              // Test.h
              #define REG_MSG_FUNC(nMsgType, MsgFunc) \
                  CMessge::RegisterCallFunc(nMsgType, MsgFunc); \

              typedef void (* function)(void*);

              typedef std::map<int, function> MSG_MAP;
              typedef MSG_MAP::const_iterator MSG_CITR;

              class CMessage
              {
                  // ...
              public:
                  static const MSG_MAP& GetMsgMap();
                  static void RegisterCallFunc(int nMsgType, void(* Func)(void *))
                  {
                      s_MsgMap[nMsgType] = Func;
                  }

                  int CMessage::Run(int nMsgType)                // 消息公用執(zhí)行函數(shù)
                  {
                      MSG_ITR itr = s_MsgMap.find(nMsgType);
                      if( s_MsgMap.end() != itr )
                      {
                          itr->second(this);
                      }
                  }

              protected:
                  static MSG_MAP            s_MsgMap;            // 消息映射表
              };

              // UserTest.cpp -- 用戶在使用時(shí)對(duì)自己關(guān)心的消息予以注冊(cè), 入口函數(shù)予以實(shí)現(xiàn)即可
              REG_MSG_FUNC(MSG_SOME_ONE, SomeOneFunc)

              void SomeOneFunc(CBaseMessage *pMsg)
              {
                  return;
              }

              ___________________________________________________________

              最近忙的焦頭爛額,正好寫到消息,稍微整理一下,提供些許借鑒。

              Feedback

              # re: 消息映射機(jī)制的簡(jiǎn)單實(shí)現(xiàn)[未登錄]  回復(fù)  更多評(píng)論   

              2008-09-30 12:32 by cppexplore
              頂一下
              前幾天我也剛寫了一個(gè),用在線程消息的處理中,我的消息類型做數(shù)組下標(biāo)了,直接定位取處理函數(shù),這都是無關(guān)緊要的細(xì)節(jié)。關(guān)鍵在ON_COMMAND宏的展現(xiàn)方式,我的處理線程消息,名字起做ON_MESSAGE
              整體思路基本都是一樣的,呵呵。

              # re: 消息映射機(jī)制的簡(jiǎn)單實(shí)現(xiàn)  回復(fù)  更多評(píng)論   

              2008-10-10 08:50 by Condor
              對(duì)于成員函數(shù)這個(gè)寫法應(yīng)該沒用了。

              # re: 消息映射機(jī)制的簡(jiǎn)單實(shí)現(xiàn)  回復(fù)  更多評(píng)論   

              2008-10-10 10:23 by Fox
              @Condor
              你說的這個(gè)問題我也考慮了,既然被提到,可以查看新一篇:http://www.shnenglu.com/Fox/archive/2008/10/10/63625.html

              # re: 消息映射機(jī)制的簡(jiǎn)單實(shí)現(xiàn)  回復(fù)  更多評(píng)論   

              2009-02-18 02:30 by OwnWaterloo
              @cppexplore
              【消息類型做數(shù)組下標(biāo)了,直接定位取處理函數(shù),這都是無關(guān)緊要的細(xì)節(jié)。】
              這恰恰是最重要的細(xì)節(jié) …… 這樣做得不償失……



              # re: 消息映射機(jī)制的簡(jiǎn)單實(shí)現(xiàn)  回復(fù)  更多評(píng)論   

              2009-02-18 02:35 by OwnWaterloo
              @cppexplore
              我再說明白一點(diǎn):
              既然【用消息類型做數(shù)組下標(biāo),直接定位處理函數(shù)】,為什么不直接使用虛函數(shù)?

              你的方案是為了消息路由而消息路由,沒能理解采用消息路由的”苦衷“——如果采用更容易理解的虛函數(shù)來實(shí)現(xiàn),虛表將占用比較多的資源,不得已而采用消息路由。

              # re: 消息映射機(jī)制的簡(jiǎn)單實(shí)現(xiàn)[未登錄]  回復(fù)  更多評(píng)論   

              2009-02-18 12:00 by cppexplore
              @OwnWaterloo
              歡迎來我blog討論:http://www.shnenglu.com/CppExplore 這篇http://www.shnenglu.com/CppExplore/archive/2008/11/07/66216.html下。查表是本質(zhì),為什么要使用虛函數(shù)?更容易理解?MFC的消息映射展現(xiàn)方式很難理解嗎? 虛函數(shù)更容易擴(kuò)展嗎? 說到虛函數(shù)占用較多資源而導(dǎo)致不得已采用消息路由,我不能認(rèn)同,這個(gè)因素在整個(gè)系統(tǒng)中的開銷你有沒有量化過?比如 因?yàn)椴捎盟鼘?dǎo)致并發(fā)數(shù)下降了多少多少之類?歡迎來我blog討論。

              # re: 消息映射機(jī)制的簡(jiǎn)單實(shí)現(xiàn)  回復(fù)  更多評(píng)論   

              2009-02-18 16:29 by OwnWaterloo
              @cppexplore

              1. 時(shí)間消耗

              時(shí)間消耗自然不用說,是你的實(shí)現(xiàn)最得意的部分,o(1)。
              同樣,虛函數(shù)也是o(1)。

              2. 空間消耗

              假設(shè)你總共有N個(gè)消息,你仔細(xì)看看你的實(shí)現(xiàn):
              是不是每個(gè)(要處理消息的)類有一個(gè)長(zhǎng)度會(huì)N的函數(shù)表,
              空間大小至少是N×sizeof(void*);
              每個(gè)對(duì)象有一個(gè)指向(或間接指向)該表的指針,
              空間大小至少是sizeof(void*)。

              虛函數(shù)的經(jīng)典實(shí)現(xiàn)的空間消耗也是one class one vtbl, one object one vptr,和你的實(shí)現(xiàn)還是相同的。


              這就回答了你一個(gè)問題:
              【我不能認(rèn)同,這個(gè)因素在整個(gè)系統(tǒng)中的開銷你有沒有量化過?比如 因?yàn)椴捎盟鼘?dǎo)致并發(fā)數(shù)下降了多少多少之類?】
              兩者的時(shí)間空間效率是完全一致的,即使我沒有量化過,也可以肯定,不會(huì)導(dǎo)致并發(fā)數(shù)下降。



              # re: 消息映射機(jī)制的簡(jiǎn)單實(shí)現(xiàn)  回復(fù)  更多評(píng)論   

              2009-02-18 16:40 by OwnWaterloo
              @cppexplore

              【查表是本質(zhì)】
              這句你說到重點(diǎn)了,虛函數(shù)和你實(shí)現(xiàn)的那個(gè)還有哪些所謂的用C實(shí)現(xiàn)OO的,都是查表。

              【為什么要使用虛函數(shù)?更容易理解?MFC的消息映射展現(xiàn)方式很難理解嗎? 虛函數(shù)更容易擴(kuò)展嗎?】
              你這個(gè)實(shí)現(xiàn)就是在『模擬』虛函數(shù)。

              上面的時(shí)空分析,可以量化,我有把握你會(huì)同意我的觀點(diǎn)——兩者時(shí)空效率完全一樣——這個(gè)擴(kuò)展性嘛,不容易量化 ……

              你可以試著把你的實(shí)現(xiàn)用虛函數(shù)改寫一下(再次說明,時(shí)空效率完全一樣)??纯词欠裼X得虛函數(shù)更容易理解,更容易擴(kuò)展。



              btw:推薦你看看這個(gè),MFC會(huì)什么會(huì)采用消息映射而不是虛函數(shù)的理由,《C++多態(tài)技術(shù)的實(shí)現(xiàn)和反思》
              http://dev.yesky.com/189/2385189.shtml

              # re: 消息映射機(jī)制的簡(jiǎn)單實(shí)現(xiàn)  回復(fù)  更多評(píng)論   

              2009-02-18 18:03 by OwnWaterloo
              @cppexplore

              再看了下你的實(shí)現(xiàn),好像我們討論的著重點(diǎn)不一樣。

              1. 你的系統(tǒng)里,是不是首先有這樣一個(gè)需求:
              因?yàn)槟撤N原因(分布式,進(jìn)程間,無鎖線程),消息的發(fā)送者不能直接調(diào)用消息處理函數(shù),而是傳送一個(gè)消息代碼來表示需要處理的類型?

              消息代碼即是win32中的WM_XX或者你的系統(tǒng)中的 enum MsgType { MSG_TYPE_1=65, ...  };



              2. 消息的處理者,又需要按照約定(即消息代碼的含義),將其映射到某個(gè)處理函數(shù)中。

              如 win32 中
              switch (message) {
              case WM_XXX:
                 return OnXXX(hwnd,message,wparam,lparam);
              ...
              }

              或者你的系統(tǒng)中的
              switch(msg->type)
              {
                  
              case MSG_TYPE_1:
                       do_msg_type_1_();
                       
              break;
                  
              case MSG_TYPE_2:
                       do_msg_type_2_();
                       
              break;
                  ..
                  
              default:
                           do_default_msg_();
                           
              break;
              }



              在這一步,確實(shí)是你的實(shí)現(xiàn)方式時(shí)間效率比較高。
              但是在win32中, 這樣做不太現(xiàn)實(shí) ……  1000多個(gè)消息,表格就要包含1000多項(xiàng),而且大多都是DefWndProc。

              并且,在這一步中,虛函數(shù)根本就提供不了任何幫助。
              你的著重點(diǎn)在這一步?


              3. 你想實(shí)現(xiàn)一個(gè)消息處理者B,它對(duì)大多數(shù)消息的處理方式同A一樣,這時(shí)候如何盡可能的使用A的實(shí)現(xiàn)?
              (暫不說依賴于某實(shí)現(xiàn)是不太恰當(dāng)?shù)脑O(shè)計(jì),在MFC中多如牛毛……)

              我的著重點(diǎn)在這里,我對(duì)處理這步的觀點(diǎn)是: 『消息類型做數(shù)組下標(biāo)了,直接定位取處理函數(shù)』與『覆寫虛函數(shù)』相比,時(shí)空效率是相同的,我覺得后者更容易理解和擴(kuò)展。


              # re: 消息映射機(jī)制的簡(jiǎn)單實(shí)現(xiàn)[未登錄]  回復(fù)  更多評(píng)論   

              2009-02-18 18:21 by cppexplore
              @OwnWaterloo
              怎么不直接去我blog回復(fù)呢 呵呵
              其實(shí) 時(shí)間消耗 之類并不是我最得意的東西,這種實(shí)現(xiàn)的細(xì)節(jié) 我并不太關(guān)注,所以質(zhì)疑你以前說的 “虛函數(shù)占用較多資源而導(dǎo)致不得已采用消息路由”,如何實(shí)現(xiàn)并不重要,關(guān)鍵的是容易理解,容易擴(kuò)展,容易維護(hù),容易移植,容易簡(jiǎn)單化。
              win32 你是指win32 的界面設(shè)計(jì)? 業(yè)務(wù)系統(tǒng)里 基本不同的消息有不同的實(shí)現(xiàn),我的本意其實(shí)都不在實(shí)現(xiàn),而在于簡(jiǎn)單的思想,因此是查表實(shí)現(xiàn) 還是虛函數(shù)實(shí)現(xiàn) 也都無所謂,只要最后有統(tǒng)一的擴(kuò)展方式。

              # re: 消息映射機(jī)制的簡(jiǎn)單實(shí)現(xiàn)[未登錄]  回復(fù)  更多評(píng)論   

              2009-02-18 18:55 by cppexplore
              @OwnWaterloo
              呵呵,最后的問題歸結(jié)為:哪種更容易理解和擴(kuò)展。
              超大工程當(dāng)然是數(shù)組方式之上用宏展現(xiàn)最容易理解和擴(kuò)展了,簡(jiǎn)潔直接。幾十w行的代碼,用虛函數(shù),文件數(shù)量的迅速膨脹 找個(gè)東西都找不到在哪里,所有東西交織錯(cuò)亂在一起,最終維護(hù)程序的人都會(huì)想:要是有張表就好了,只看表就知道那個(gè)函數(shù)處理哪個(gè)消息,而宏的展現(xiàn)就是如此。 當(dāng)然如果用宏包裹下虛函數(shù)的實(shí)現(xiàn),結(jié)果就一樣了。
              并且數(shù)組表只是一個(gè)思路,不攜帶任何面向?qū)ο蟮恼Z義,在這個(gè)業(yè)務(wù)系統(tǒng)里可用,在那個(gè)業(yè)務(wù)系統(tǒng)里也可用,虛函數(shù)有這么好的移植性嗎?有這么簡(jiǎn)單化嗎?

              # re: 消息映射機(jī)制的簡(jiǎn)單實(shí)現(xiàn)  回復(fù)  更多評(píng)論   

              2009-02-19 01:57 by OwnWaterloo
              @cppexplore
              【怎么不直接去我blog回復(fù)呢 呵呵】
              好像是cppblog對(duì)url的分析有點(diǎn)問題,這個(gè)url: http://www.shnenglu.com/CppExplore/archive/2008/11/07/66216.html
              會(huì)被截取,只將前面一部分(也就是你的主頁(yè))制作成鏈接,點(diǎn)過去沒看見什么文章……
              后來才發(fā)現(xiàn)這個(gè)問題,找到那篇文章……
              【容易理解,容易擴(kuò)展,容易維護(hù),容易移植,容易簡(jiǎn)單化】
              嗯,這是重點(diǎn)。同時(shí)我也贊同你文章里最后一句話【一句話:重要的是思想,不是平臺(tái)和語言。】
               
              "你的實(shí)現(xiàn)就是模擬C++虛函數(shù)的經(jīng)典實(shí)現(xiàn)",這個(gè)觀點(diǎn)你贊同嗎?
              你的系統(tǒng)需要考慮向C(以及不支持虛函數(shù)的語言)移植嗎?
               
              如果贊同且不需要,那么繼續(xù)討論理解、擴(kuò)展、維護(hù)、簡(jiǎn)單
              你的系統(tǒng)具體要做什么不太了解,我用win32作例子可以嗎?比如,現(xiàn)在需要關(guān)心的消息只有2個(gè):
              enum MsgType {
                  WM__LBUTTONDOWN 
              /*= 0*/,
                  WM__SIZING,
                  
              // 
              };
              struct Msg {
                  MsgType type;
                  HWND    hwnd;
                  WPARAM  wparam;
                  LPARAM  lparam;
              };

              如果使用C++虛函數(shù)機(jī)制:
               
              class IHandler {
              public:
                  
              virtual ~IHandler() {};
              protected:
                  
              virtual void OnLButtonDown(POINTS pt,bool ctrl,bool shift,bool l,bool m,bool r) = 0 {};
                  
              virtual void OnSizing(RECT& rc,int side) = 0 {};
              public:
                  LRESULT Do(Msg
              * msg) {
                      
              switch (msg->type) {
                          
              case WM__LBUTTONDOWN:
                              OnLButtonDown(MAKEPOINTS(msg
              ->lparam)
                                           ,msg
              ->wparam & MK_CONTROL
                                           ,msg
              ->wparam & MK_SHIFT
                                           ,msg
              ->wparam & MK_LBUTTON
                                           ,msg
              ->wparam & MK_MBUTTON
                                           ,msg
              ->wparam & MK_RBUTTON);
                              
              return 0;
                          
              case WM__SIZING:
                              OnSizing(
              *reinterpret_cast<RECT*>(msg->lparam),msg->wparam);
                              
              return 0;
                      }

                      
              return DefWindowProc(msg->hwnd,msg->type,msg->wparam,msg->lparam);
                  }

              }
              ;
               
              具體的消息處理類可以這樣:
              class Handler1 : public IHandler {
                  
              void OnLButtonDown(POINTS pt,bool ctrl,bool shift,bool l,bool m,bool r) {
                      IHandler::OnLButtonDown(pt,ctrl,shift,l,m,r);
                  }

                  
              void OnSizing(RECT& rc,int side) {
                      IHandler::OnSizing(rc,side);
                  }

              }
              ;
               
              上面的基類的虛函數(shù)帶有默認(rèn)實(shí)現(xiàn),但設(shè)置為純虛函數(shù)。
              具體類必須實(shí)現(xiàn)每個(gè)消息處理過程,如果不關(guān)心,可以簡(jiǎn)單使用基類實(shí)現(xiàn)。
              另一種方式:基類提供默認(rèn)實(shí)現(xiàn),并且不是純虛函數(shù);具體類只需覆寫關(guān)心的消息。
               
              另一方面,上面的基類沒有使用表格,如果覺得switch case 不好維護(hù),也可以使用表格。
               
              兩方面都采用另一種方案的話,基類就如下:
              class IHandler {
              public:
                  
              virtual ~IHandler() {};
              private:
                  
              virtual void OnLButtonDown(POINTS pt,bool ctrl,bool shift,bool l,bool m,bool r)  {};
                  
              virtual void OnSizing(RECT& rc,int side)  {};
              public:
                  LRESULT Do(Msg
              * msg) {
                      assert(msg
              ->type>=0 && msg->type<WM__SIZING);
                      
              return MsgProcs[msg->type](msg->hwnd,msg->type,msg->wparam,msg->lparam,this);
                  }


              private:
                  typedef LRESULT (
              *MsgProc)(HWND,MsgType,WPARAM,LPARAM,IHandler* handler);
                  
              const static MsgProc MsgProcs[];
                  
              static LRESULT OnLButtonDown(HWND,MsgType,WPARAM wparam,LPARAM lparam,IHandler* handler) {
                      handler
              ->OnLButtonDown(MAKEPOINTS(lparam)
                                            ,wparam 
              & MK_CONTROL
                                            ,wparam 
              & MK_SHIFT
                                            ,wparam 
              & MK_LBUTTON
                                            ,wparam 
              & MK_MBUTTON
                                            ,wparam 
              & MK_RBUTTON);
                      
              return 0;
                  }

                  
              static LRESULT OnSizing(HWND,MsgType,WPARAM wparam,LPARAM lparam,IHandler* handler) {
                      handler
              ->OnSizing(*reinterpret_cast<RECT*>(lparam),wparam);
                      
              return 0;
                  }

              }
              ;

              const IHandler::MsgProc IHandler::MsgProcs[] = {
                  IHandler::OnLButtonDown,
                  IHandler::OnSizing,
              }
              ;

              具體類的編寫就更簡(jiǎn)單: 假設(shè)僅關(guān)心OnLButtonDown
              class Handler1 : public IHandler {
                  
              void OnLButtonDown(POINTS pt,bool ctrl,bool shift,bool l,bool m,bool r) {
                      printf(
              "(%d,%d) ctrl=%d,shitf=%d\n",pt.x,pt.y,ctrl,shift);
                  }

              }
              ;

               

              # re: 消息映射機(jī)制的簡(jiǎn)單實(shí)現(xiàn)  回復(fù)  更多評(píng)論   

              2009-02-19 02:16 by OwnWaterloo
                                            考慮擴(kuò)展
               
              添加一個(gè)新的消息處理類。
              如果基類不是純虛函數(shù),那最簡(jiǎn)單了,覆寫需要關(guān)心的消息就可以了。
              如果是純虛函數(shù),需要實(shí)現(xiàn)所有消息處理函數(shù),對(duì)不關(guān)心的消息,使用基類默認(rèn)處理。
               
              而你的方案,不得不將所有的消息都映射一遍——因?yàn)椤鞠㈩愋妥鰯?shù)組下標(biāo),直接定位取處理函數(shù)】——即使不關(guān)心而作一個(gè)空函數(shù)。 
              BEGIN_MESSAGE_MAP(SessionManager,SessionMsg)
                  ON_MESSAGE(MSG_TYPE_1, SessionManager::do_msg_type_1_)
                  ON_MESSAGE(MSG_TYPE_2, SessionManager::do_msg_type_2_)
                  
              // .. MORE
              END_MESSAGE_MAP()
              如果不是這樣,請(qǐng)務(wù)必告訴我你是怎么不使用虛函數(shù)實(shí)現(xiàn)的。
               
               
              添加一個(gè)新的消息種類(消息代碼)
              如果可以保證消息代碼連續(xù),可以使用上面的方案2,在表格中多加入一條。
              如果不能保證消息代碼連續(xù)(并且非常稀疏),就只能采用swtich case。
               
              已經(jīng)編寫好的具體的消息處理類,如果都可以安全忽略該消息,那么可以采用上面的方案2——基類有默認(rèn)實(shí)現(xiàn)且不純虛——那么除了基類,已經(jīng)編寫好的具體類都不需要修改
              如果不全都可以安全忽略該消息,那么可以采用上面的方案1——基類有空實(shí)現(xiàn),但是純虛——具類中可以忽略該消息的,使用基類實(shí)現(xiàn),不能忽略的,編寫處理函數(shù)。
               
              而你的方案,一旦添加一個(gè)新的消息處理代碼(同時(shí)要保證連續(xù)),所有的消息處理類都必須在其表格中增加一項(xiàng)。

              # re: 消息映射機(jī)制的簡(jiǎn)單實(shí)現(xiàn)  回復(fù)  更多評(píng)論   

              2009-02-19 02:16 by OwnWaterloo
              移植性確實(shí)會(huì)在不支持虛函數(shù)的語言中完敗。
              論理解、擴(kuò)展、維護(hù)、簡(jiǎn)單的話,你現(xiàn)在仍然覺得虛函數(shù)比不上表格嗎?

              # re: 消息映射機(jī)制的簡(jiǎn)單實(shí)現(xiàn)[未登錄]  回復(fù)  更多評(píng)論   

              2009-02-19 10:16 by cppexplore
              @OwnWaterloo
              呵呵 你覺得你的想法來源于面向?qū)ο蟮募埳险劚]有貶義)以及基于win32的mfc框架程序設(shè)計(jì)。
              我的實(shí)現(xiàn)不是為了模擬虛函數(shù)的實(shí)現(xiàn),只是為了實(shí)現(xiàn)一個(gè)易維護(hù)的消息映射而已。
              首先 對(duì)象A不能直接向?qū)ο驜直接發(fā)送消息,需要調(diào)用對(duì)象B的ON_send_msg,由B自己的方法向自己發(fā)送消息,由B的DO_Msg方法處理消息,當(dāng)然發(fā)送動(dòng)作和處理動(dòng)作在不同的線程內(nèi)。任何對(duì)象向B發(fā)送消息都要調(diào)用B自己的方法。也就是說對(duì)象B的具體消息類型對(duì)其它對(duì)象是不可見的。
              因此對(duì)象B中的消息類型是連續(xù)的,并且不存在自己不感興趣的消息,既然不感興趣,就不會(huì)存在這個(gè)消息類型,只要是存在的就是感興趣的,就是要處理的。也不存在對(duì)多個(gè)消息,處理方式相同的問題,既然處理方式相同,它們就是同一個(gè)消息。
              其次 你還是回避了大型程序開發(fā)中,使用虛函數(shù)方式,文件個(gè)數(shù)膨脹的問題。
              最后 我討論的是線程間的消息傳遞和映射,你的有偏向于 已經(jīng)發(fā)送到UI線程的消息,對(duì)責(zé)任鏈模式上的 各個(gè)對(duì)象的后續(xù)處理。

              # re: 消息映射機(jī)制的簡(jiǎn)單實(shí)現(xiàn)  回復(fù)  更多評(píng)論   

              2009-02-19 22:42 by OwnWaterloo
              @cppexplore

              第1個(gè)疑問:
              系統(tǒng)中所有類使用的消息代碼是否是同一套?都是
              enum MsgType
              {
              MSG_TYPE_1=65,//64一下預(yù)留,用于統(tǒng)一的管理控制
              MSG_TYPE_2,
              ..
              MSG_TYPE_MAX
              };
              ???

              第2個(gè)疑問:(同時(shí)也是回答)
              確實(shí)如你所說,我是【紙上談兵】。
              我沒有【大型程序】的開發(fā)經(jīng)驗(yàn),更是不能理解:
              【大型程序開發(fā)中,使用虛函數(shù)方式,文件個(gè)數(shù)膨脹的問題。】
              這是為什么? 請(qǐng)指教~~~ 昨天就想問你了,字打多了就忘了……

              # re: 消息映射機(jī)制的簡(jiǎn)單實(shí)現(xiàn)[未登錄]  回復(fù)  更多評(píng)論   

              2009-02-19 22:51 by cppexplore
              @OwnWaterloo
              不是同一套,只有64以下的是相同。64以上的各個(gè)線程之間可以重復(fù),因?yàn)閷?duì)其他對(duì)象是不可見得,所以不存在沖突問題??梢远xUSER_MSG_START=64.
              項(xiàng)目越大,越需要表格,容易維護(hù),容易擴(kuò)展,容易找對(duì)應(yīng)關(guān)系,也就是看一個(gè)文件就知道所有,而不是在幾十個(gè)上百個(gè)文件里查找。當(dāng)然要看你的虛函數(shù)實(shí)現(xiàn)成什么樣子了。
              我舉的例子,對(duì)象B是管理類,同時(shí)也是線程類。里面管理了很多的對(duì)象,B拿到消息也是找到對(duì)應(yīng)的對(duì)象去處理,貌似你一直談的是后續(xù)。
              而你在MFC里看到的是同一套,那是因?yàn)樗鼈兌荚赨I線程里,同屬于一個(gè)線程,一個(gè)管理類。

              # re: 消息映射機(jī)制的簡(jiǎn)單實(shí)現(xiàn)  回復(fù)  更多評(píng)論   

              2009-02-19 23:23 by OwnWaterloo
              @cppexplore
              我覺得加QQ聊會(huì)快一點(diǎn)…… “六久久思武柳留靈”

              不是同一套,那么A向B發(fā)一個(gè)65以上的消息,B如何知道代表什么含義呢?
              要么:A只向B發(fā)64以下的消息。
              要么:存在T1,T2, ... Tn個(gè)線程,每個(gè)線程下分別有
              A11,A12, ... An1...
              A21,A22, ... An2...
              ...
              A[i][j]只會(huì)和A[i][k]直接交互
              A[i][j]和A[k][l]通過某種機(jī)制間接交互



              -----------------------------
              【貌似你一直談的是后續(xù)。 】
              可能是這樣的,我在
              http://www.shnenglu.com/Fox/archive/2008/09/29/63056.aspx#74178
              也說了。

              # re: 消息映射機(jī)制的簡(jiǎn)單實(shí)現(xiàn)[未登錄]  回復(fù)  更多評(píng)論   

              2009-02-20 10:19 by cppexplore
              @OwnWaterloo
              上班不能qq 呵呵 下班加你
              A不能以指定消息值的方式向B發(fā)消息,通過調(diào)用B自身的ON_MSG方法發(fā)送。也就是除了B自己,誰也不知道它具體消息的枚舉值。
              64一下的也是調(diào)用B自身的方法發(fā)送,不過這些是B基類中的方法。

              # re: 消息映射機(jī)制的簡(jiǎn)單實(shí)現(xiàn)  回復(fù)  更多評(píng)論   

              2011-10-15 16:04 by
              人 需要一種簡(jiǎn)單的 東西來支撐屬于自身內(nèi)心的簡(jiǎn)單,這樣的簡(jiǎn)單一直以來是無形的,就如同所有存在的 對(duì)于支撐簡(jiǎn)單的東西已經(jīng) 進(jìn)行過的時(shí)候,那么內(nèi)心當(dāng)中還是缺少對(duì)于無法割舍的簡(jiǎn)單的 內(nèi)涵

              # re: 消息映射機(jī)制的簡(jiǎn)單實(shí)現(xiàn)  回復(fù)  更多評(píng)論   

              2011-10-15 16:06 by
              在某一種環(huán)境下面其實(shí)簡(jiǎn)單的來說在于一旦沒有了這樣的一種現(xiàn)實(shí),簡(jiǎn)單的環(huán)境是否在可能變化的環(huán)境當(dāng)中產(chǎn)生簡(jiǎn)單的過程那樣如此簡(jiǎn)單明了

              # re: 消息映射機(jī)制的簡(jiǎn)單實(shí)現(xiàn)  回復(fù)  更多評(píng)論   

              2011-10-15 16:07 by
              所以自己的內(nèi)心真誠(chéng)的東西不是對(duì)于某一種勢(shì)力的那種附和,而是對(duì)于在這個(gè)過程當(dāng)中自身能夠決定進(jìn)入某一種勢(shì)力需要的那種條件的 認(rèn)可

              # re: 消息映射機(jī)制的簡(jiǎn)單實(shí)現(xiàn)  回復(fù)  更多評(píng)論   

              2011-10-15 16:08 by
              在各種各樣的 范圍內(nèi)決定一個(gè)人能夠簡(jiǎn)單的進(jìn)行自身的活動(dòng)范圍內(nèi) 并且 能夠達(dá)到一些盡可能需要的行為內(nèi),需要的不僅僅是可靠性的 過程,更重要的是價(jià)值活動(dòng)的產(chǎn)生

              # re: 消息映射機(jī)制的簡(jiǎn)單實(shí)現(xiàn)  回復(fù)  更多評(píng)論   

              2011-10-15 16:09 by
              在過程行為當(dāng)中能夠明確的 在于是已經(jīng)形成出來的新的一種競(jìng)爭(zhēng)力自身需要的一種內(nèi)心活動(dòng) 當(dāng)中產(chǎn)生的角色轉(zhuǎn)換的 過程當(dāng)中需要的互動(dòng)意識(shí)與能力

              # re: 消息映射機(jī)制的簡(jiǎn)單實(shí)現(xiàn)  回復(fù)  更多評(píng)論   

              2011-10-15 16:10 by
              因此各種各樣的簡(jiǎn)單絕對(duì)不是取決于自身在竭盡全力自后需要的條件,而是自身竭盡全力的過程當(dāng)中自己需要的休息的素質(zhì)與能力的那種背景考量的能力

              # re: 消息映射機(jī)制的簡(jiǎn)單實(shí)現(xiàn)  回復(fù)  更多評(píng)論   

              2012-04-16 09:10 by
              基本上來說一個(gè)人成熟的機(jī)制恐怕是能夠讓自己能夠在不斷的磨合當(dāng)中逐漸消失成見的過程,就一個(gè)成熟的那種業(yè)績(jī)體系來說,實(shí)際上現(xiàn)在的復(fù)雜在于業(yè)績(jī)對(duì)象的那種針對(duì)的安全對(duì)象的成熟度沒有,如果僅僅針對(duì)的是一種瘋子般的業(yè)務(wù)來說的業(yè)績(jī)或者組織層面來說的業(yè)績(jī),這樣的機(jī)制成熟的業(yè)績(jī)體系是不存在的一個(gè)方式。

              # re: 消息映射機(jī)制的簡(jiǎn)單實(shí)現(xiàn)  回復(fù)  更多評(píng)論   

              2012-04-16 09:13 by
              實(shí)際上業(yè)績(jī)組合套拳的組合一定夾雜某一種對(duì)于私心認(rèn)可的范疇內(nèi)達(dá)到的應(yīng)急范疇內(nèi)實(shí)現(xiàn)對(duì)于業(yè)績(jī)整個(gè)機(jī)制的認(rèn)識(shí),從表面上來看,一旦業(yè)績(jī)沒有屬于自己范圍的業(yè)績(jī)過程,整個(gè)的業(yè)績(jī)鏈被居心叵測(cè)的人所掌握,那么業(yè)績(jī)機(jī)制上面的成熟機(jī)制在實(shí)現(xiàn)的過程永遠(yuǎn)被這樣或者那樣的理由所圈繞。一個(gè)成熟的業(yè)績(jī)機(jī)體本身上面是由于其中業(yè)績(jī)機(jī)體上面有按照其中規(guī)律方式運(yùn)轉(zhuǎn)的模式旋轉(zhuǎn),而與時(shí)代與行業(yè),和管理它的人就更加沒有關(guān)系的了

              # re: 消息映射機(jī)制的簡(jiǎn)單實(shí)現(xiàn)  回復(fù)  更多評(píng)論   

              2012-04-16 09:16 by
              業(yè)績(jī)機(jī)制上面的成熟度在于在不斷的磨合的組合的過程當(dāng)中永遠(yuǎn)不可能按照面上面的業(yè)績(jī)組合形成業(yè)績(jī)機(jī)制過程,業(yè)績(jī)機(jī)制表明的是在業(yè)績(jī)最初形成的時(shí)候,需要使用各種各樣關(guān)于技巧性的使用,一旦業(yè)績(jī)成熟,則不過是一種對(duì)于業(yè)績(jī)形成上面需要依照的規(guī)律模式行駛其中業(yè)績(jī)機(jī)制形成的規(guī)律線而已。

              # re: 消息映射機(jī)制的簡(jiǎn)單實(shí)現(xiàn)  回復(fù)  更多評(píng)論   

              2012-04-16 09:19 by
              業(yè)績(jī)機(jī)制形成的規(guī)律線絕對(duì)不是建立在回復(fù)其它層面的上面的不斷的 解釋層次上面表現(xiàn)出來的那種心安理得局面上面的業(yè)績(jī)機(jī)制,業(yè)績(jī)機(jī)制的形成在于自己認(rèn)為需要付出多少的代價(jià)愿意承受這樣的一種業(yè)績(jī)機(jī)制的形成,業(yè)績(jī)機(jī)制的形成一般是競(jìng)爭(zhēng)分析--競(jìng)爭(zhēng)對(duì)手分析---柜臺(tái)分析---賺錢分析---承載風(fēng)險(xiǎn)分析---合理的業(yè)績(jī)軌道,這個(gè)業(yè)績(jī)機(jī)制的形成在于一旦在那種對(duì)于業(yè)績(jī)本身模式不認(rèn)可,而且浮于人事層面上面是永遠(yuǎn)不可能體會(huì) 到這樣的一個(gè)業(yè)績(jī)機(jī)制形成的過程的。

              # re: 消息映射機(jī)制的簡(jiǎn)單實(shí)現(xiàn)  回復(fù)  更多評(píng)論   

              2012-04-16 09:22 by
              基于對(duì)于業(yè)績(jī)機(jī)制形成的事實(shí),然后規(guī)劃屬于自身現(xiàn)狀的業(yè)績(jī)狀況就能夠發(fā)現(xiàn),充分的運(yùn)用屬于自己的認(rèn)識(shí)與人事與實(shí)力來驗(yàn)證對(duì)于業(yè)績(jī)機(jī)制的本身帶來的效果,然后再這樣的一種效果當(dāng)中明確這樣的一種業(yè)績(jī)機(jī)制承載出來一個(gè)怎么樣的自己的體驗(yàn)當(dāng)中,從而對(duì)于自己有一個(gè)或者有一種全新的認(rèn)識(shí)的過程,至少在這個(gè)過程當(dāng)中,能夠承載屬于自己職業(yè)生命力的安全模式

              # re: 消息映射機(jī)制的簡(jiǎn)單實(shí)現(xiàn)  回復(fù)  更多評(píng)論   

              2012-04-16 09:25 by
              確切的說,業(yè)績(jī)機(jī)制承載的職業(yè)生命力具體表現(xiàn)在屬于一種胸襟,沒有一種胸襟,格局的誕生恐怕只能夠越來越小,胸襟不是以職業(yè)生命力的安全作為安全,而恰恰相反,胸襟是站在或者基于職業(yè)生命力維護(hù)的基礎(chǔ)上面去考慮胸襟本身的得失或者愿意承受的東西和不愿意承受的順應(yīng)心靈的一種呼喚。
              国产精品狼人久久久久影院| 国产日产久久高清欧美一区| 欧美一区二区久久精品| 天天做夜夜做久久做狠狠| 欧美熟妇另类久久久久久不卡| 2021精品国产综合久久| 亚洲国产成人乱码精品女人久久久不卡 | 天天爽天天狠久久久综合麻豆| 久久国产精品久久国产精品| 思思久久好好热精品国产| 久久久久国产精品| 日本WV一本一道久久香蕉| 91精品国产高清久久久久久91| 久久天天躁狠狠躁夜夜2020一| 久久中文娱乐网| 久久久精品国产sm调教网站| 久久笫一福利免费导航| 国产激情久久久久影院小草 | 久久线看观看精品香蕉国产| 国内精品久久久久久久久电影网| 丁香五月综合久久激情| 精品久久8x国产免费观看| 99蜜桃臀久久久欧美精品网站| 久久精品人妻一区二区三区| 69久久夜色精品国产69| 99久久综合狠狠综合久久止| 色偷偷88888欧美精品久久久| 久久综合色区| 四虎影视久久久免费观看| 久久影视综合亚洲| 性高朝久久久久久久久久| 亚洲国产精品综合久久网络| 色播久久人人爽人人爽人人片aV| 久久久精品视频免费观看| 精品欧美一区二区三区久久久| 天天久久狠狠色综合| 国产精品免费久久| 欧美性猛交xxxx免费看久久久| 青青草国产97免久久费观看| 亚洲欧美国产日韩综合久久| 国产精品久久久久久久app |