• <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>
            隨筆-250  評論-20  文章-55  trackbacks-0
            被包含的窗口:
            一個被包含的窗口是一個不響應(yīng)任何消息的窗口,它將收到的所有消息重新發(fā)送到另外一個窗口的消息映射,這個另外的窗口就是它的容器窗口。通常情況下,被包含的窗口是它的容器窗口的子窗口,但情況并不是總是這樣。容器窗口并不是必須等同于父窗口,包含與被包含的關(guān)系取決于C++類,被包含的窗口是容器窗口類的一個數(shù)據(jù)成員,而父窗口和子窗口的關(guān)系體現(xiàn)在屏幕上,它們的關(guān)系是創(chuàng)建窗口時確定的。

            一個被包含的窗口建立在已注冊的窗口類的基礎(chǔ)之上,比如編輯框控件。如果一個編輯框被包含,那么發(fā)送到它的消息實際上被它的容器窗口的消息映射處理。使用這種方法,可以改變編輯框控件的標(biāo)準(zhǔn)行為。這有點(diǎn)類似于子類化但是不需要定義新類來子類化控件。和前面那個定義CnoNumEdit類響應(yīng)WM_CHAR消息的例子相比,處理WM_CHAR消息的容器窗口類看起來如下:
            class CMyWindow: public CWindowImpl
            {
               CContainedWindow m_contained;
            public:
               CMyWindow(): m_contained( _T("edit"), this, 99 )
               {
               }
               ...
            
            CmyWindow是一個容器窗口類,它的構(gòu)造函數(shù)對CcontainedWindow類型的成員做這樣的初始化:被包含的窗口是編輯框,發(fā)送它的消息到“this”(它的父窗口),使用可選消息映射表99。
            BEGIN_MSG_MAP( CMyWindow )
               MESSAGE_HANDLER( WM_CREATE, OnCreate )
               MESSAGE_HANDLER( WM_DESTROY, OnDestroy )
            ALT_MSG_MAP( 99 ) // contained window''s messages come here...
               MESSAGE_HANDLER( WM_CHAR, OnChar )
            END_MSG_MAP()
            
            當(dāng)父窗口被創(chuàng)建的時候,被包含的窗口也被創(chuàng)建(在WM_CREATE消息的響應(yīng)函數(shù)中)。因為被包含的控件是以編輯框為基礎(chǔ)的,所以它在屏幕上看起來象一個編輯框:
            LRESULT OnCreate( UINT, WPARAM, LPARAM, BOOL& )
            {
               RECT rc = { 10, 10, 200, 35 };
               m_contained.Create( *this, rc, _T("non-numeric edit"),
                  WS_CHILD|WS_VISIBLE|WS_BORDER, 0, 666 );
               return 0;
            }
            
            在這個例子中,容器窗口同時也是被包含窗口的父窗口。

            當(dāng)被包含的窗口收到WM_CHAR消息時,容器窗口的OnChar成員函數(shù)被調(diào)用。這個函數(shù)和前面的CnoNumEdit例子中的相同,但是在這個例子中,它時容器類的成員函數(shù)。
            LRESULT OnChar( UINT, WPARAM wParam, LPARAM, BOOL& bHandled )
               {
               TCHAR ch = wParam;
               if( _T(''0'') <= ch && ch <= _T(''9'') )
                  MessageBeep( 0 );
               else
                  bHandled = FALSE;
               return 0;
               }
            
            LRESULT OnDestroy( UINT, WPARAM, LPARAM, BOOL& )
               {
               PostQuitMessage( 0 );
               return 0;
               }
            };
            
            我們同樣也可以用被包含的窗口來子類化對話框中已經(jīng)存在的控件,和正規(guī)的子類化不同,被子類化的窗口的消息時被容器窗口捕獲的。在下面的例子中,一個對話框子類化了一個編輯框控件,把它轉(zhuǎn)化成了被包含的窗口;那個對話框(容器)捕獲WM_CHAR消息并忽略掉數(shù)字字符,然后在發(fā)送到編輯框控件。(CdialogImpl在ATL中的對話框類一節(jié)講述。)
            class CMyDialog: public CDialogImpl<CMyDialog>
            {
            public:
               enum { IDD = IDD_DIALOG1 };
            // contained window is an edit control:
               CMyDialog(): m_contained( "edit", this, 123 )
               {
               }
            
               BEGIN_MSG_MAP( CMyDialog )
                  MESSAGE_HANDLER( WM_INITDIALOG, OnInitDialog )
               ALT_MSG_MAP( 123 ) // contained window''s messages come here...
                  MESSAGE_HANDLER( WM_CHAR, OnChar )
               END_MSG_MAP()
            
               LRESULT OnInitDialog( UINT, WPARAM, LPARAM, BOOL& bHandled )
               {
               // when the dialog box is created, subclass its edit control:
                  m_contained.SubclassWindow( GetDlgItem(IDC_EDIT1) );
                  bHandled = FALSE;
                  return 0;
               }
            
               LRESULT OnChar( UINT, WPARAM wParam, LPARAM, BOOL& bHandled )
               {
                  TCHAR ch = wParam;
                  if( _T(''0'') <= ch && ch <= _T(''9'') )
                     MessageBeep( 0 );
                  else
                     bHandled = FALSE;
                  return 0;
               }
            
               CContainedWindow m_contained;
            };
            
            消息反射:
            前面講述了一些擴(kuò)展窗口功能的方法,這些方法是通過使窗口響應(yīng)發(fā)往窗口的消息實現(xiàn)的。和前面的方法相反,消息反射是使窗口能夠響應(yīng)從它們自己發(fā)出的消息。

            當(dāng)用戶和控件交互的時候,控件通常使發(fā)送一個WM_COMMAND或者WM_NOTIFY消息給它的父窗口;然后父窗口做出響應(yīng),比如:
            class CParentWindow: CWindowImpl<CParentWindow>
            {
               // 假設(shè)這個窗口有一個按鈕型的子窗口,
               // 并且其 ID 為 ID_BUTTON
               BEGIN_MSG_MAP( CParentWindow )
                  COMMAND_ID_HANDLER( ID_BUTTON, OnButton )
                  MESSAGE_HANDLER( WM_CTLCOLORBUTTON, OnColorButton )
                  ...
            
            當(dāng)按鈕被按下的時候,它發(fā)送一個命令消息給父窗口,然后CParentWindow::OnButton被調(diào)用。同理,當(dāng)按鈕需要被繪制的時候,它發(fā)送WM_CTLCOLORBUTTON消息給父窗口,CParentWindow::OnColorButton響應(yīng)這個消息,它使用特定的畫刷繪制控件。

            某些情況下,讓控件自己響應(yīng)它發(fā)送出去的消息比讓父窗口響應(yīng)要好得多。ATL提供了消息反射的機(jī)制:當(dāng)控件向父窗口發(fā)送消息的時候,父窗口能夠?qū)⑾⒎瓷浣o控件。
            class CParentWindow: CWindowImpl
            {
               BEGIN_MSG_MAP( CParentWindow )
                  MESSAGE_HANDLER( WM_CREATE, OnCreate )
                  MESSAGE_HANDLER( WM_DESTROY, OnDestroy )
                  ...other messages that CParentWindow will handle...
                  REFLECT_NOTIFICATIONS()
               END_MSG_MAP()
               ...
            
            當(dāng)父窗口收到一個消息,先查找它的消息映射表,如果沒有和這個消息相匹配的入口,則REFLECT_NOTIFICATIONS宏使得該消息被反射給發(fā)送這個消息的控件。控件可以提供響應(yīng)反射消息的處理函數(shù),如下:
            class CHandlesItsOwnMessages: CWindowImpl<CHandlesItsOwnMessage>
            {
            public:
               DECLARE_WND_SUPERCLASS( _T("Superbutton"), _T("button") )
               BEGIN_MSG_MAP( CHandlesItsOwnMessage )
                  MESSAGE_HANDLER( OCM_COMMAND, OnCommand )
                  MESSAGE_HANDLER( OCM_CTLCOLORBUTTON, OnColorButton )
                  DEFAULT_REFLECTION_HANDLER()
               END_MSG_MAP()
               ...
            
            注意,反射消息的消息標(biāo)志以O(shè)CM_開頭,而不是WM_。這可以讓你區(qū)分這個消息究竟是否是被反射回來的。

            這個控件要么是這個類的實例,要么是一個被子類化的按鈕控件。例如:
            // in CParentWindow:
               CHandlesItsOwnMessages m_button;
               LRESULT OnCreate( UINT, WPARAM, LPARAM, BOOL& )
               {
                  RECT rc; // initialize appropriately
                  m_button.Create( *this, rc, _T("click me"), WS_CHILD|WS_VISIBLE );
                  ...
            
            或者,如果這個按鈕控件是已存在的(例如,父窗口是一個對話框):
            m_button.SubclassWindow( GetDlgItem(ID_BUTTON) );
            
            下面的例子定義了一個CstaticLink類,它是一個Static控件,當(dāng)點(diǎn)擊它的時候,將打開一個指定的網(wǎng)頁。所有從CstaticLink發(fā)送出去的消息都被它的父窗口反射回來(在這個例子中,用到對話框,請看ATL中的對話框類這一節(jié))。除了響應(yīng)反射回的命令消息,CstaticLink還處理反射回的WM_CTLCOLORSTATIC消息以便它能夠讓自己在點(diǎn)擊前和點(diǎn)擊后顯示不同的顏色。
            #include "stdafx.h"
            #include "resource.h"
            
            CComModule _Module;
            
            class CStaticLink : public CWindowImpl<CStaticLink> {
            /*
               Based on CStaticLink by Paul DiLascia, C++ Q&A, Microsoft Systems
               Journal 12/1997.
               Turns static controls into clickable "links" -- when the control is
               clicked, the file/program/webpage named in the control''s text (or
               set by SetLinkText()) is opened via ShellExecute().  Static control
               can be either text or graphic (bitmap, icon, etc.).
            */
            public:
               DECLARE_WND_SUPERCLASS( _T("StaticLink"), _T("Static") )
            
               CStaticLink() :
                  m_colorUnvisited( RGB(0,0,255) ),
                  m_colorVisited( RGB(128,0,128) ),
                  m_bVisited( FALSE ),
                  m_hFont( NULL )
               {
               }
            
               void SetLinkText( LPCTSTR szLink ) {
                  USES_CONVERSION;
                  m_bstrLink = T2OLE( szLink );
               }
            
               BEGIN_MSG_MAP(CStaticLink)
                  // uses message reflection: WM_* comes back as OCM_*
                  MESSAGE_HANDLER( OCM_COMMAND, OnCommand )
                  MESSAGE_HANDLER( OCM_CTLCOLORSTATIC, OnCtlColor )
                  MESSAGE_HANDLER( WM_DESTROY, OnDestroy ) // not a reflected message
                  DEFAULT_REFLECTION_HANDLER()
               END_MSG_MAP()
            
               LRESULT OnDestroy( UINT, WPARAM, LPARAM, BOOL& ) {
                  if( m_hFont ) DeleteObject( m_hFont );
                  return 0;
               }
            
               LRESULT OnCommand( UINT, WPARAM wParam, LPARAM, BOOL& ) {
                  USES_CONVERSION;
                  int code = HIWORD( wParam );
                  if( code == STN_CLICKED || code == STN_DBLCLK ){
                     if( m_bstrLink.Length() == 0 ){
                        GetWindowText( &m_bstrLink );
                     }
                     if( (int)ShellExecute( *this, _T("open"),
                        OLE2T(m_bstrLink), NULL, NULL, SW_SHOWNORMAL ) > 32 ){
                        m_bVisited = TRUE;   // return codes > 32 => success
                        Invalidate();
                     }else{
                        MessageBeep( 0 );
                        ATLTRACE( _T("Error: CStaticLink couldn''t open file") );
                     }
                  }
                  return 0;
               }
            
               LRESULT OnCtlColor( UINT, WPARAM wParam, LPARAM, BOOL& ) {
                  // notify bit must be set to get STN_* notifications
                  ModifyStyle( 0, SS_NOTIFY );
                  HBRUSH hBr = NULL;
                  if( (GetStyle() & 0xff) <= SS_RIGHT ){
                     // it''s a text control: set up font and colors
                     if( !m_hFont ){
                        LOGFONT lf;
                        GetObject( GetFont(), sizeof(lf), &lf );
                        lf.lfUnderline = TRUE;
                        m_hFont = CreateFontIndirect( &lf );
                     }
                     HDC hDC = (HDC)wParam;
                     SelectObject( hDC, m_hFont );
                     SetTextColor( hDC, m_bVisited ? m_colorVisited
                                                   : m_colorUnvisited );
                     SetBkMode( hDC, TRANSPARENT );
                     hBr = (HBRUSH)GetStockObject( HOLLOW_BRUSH );
                  }
                  return (LRESULT)hBr;
               }
            
            private:
               COLORREF m_colorUnvisited;
               COLORREF m_colorVisited;
               BOOL m_bVisited;
               HFONT m_hFont;
               CComBSTR m_bstrLink;
            }; // CStaticLink
            
            class CReflectDlg : public CDialogImpl<CReflectDlg> {
            public:
               enum { IDD = IDD_DIALOG1 };
               
               BEGIN_MSG_MAP(CReflectDlg)
                  COMMAND_RANGE_HANDLER( IDOK, IDCANCEL, OnClose )
                  MESSAGE_HANDLER(WM_INITDIALOG, OnInitDialog)
                  REFLECT_NOTIFICATIONS()      // reflect messages back to static links
               END_MSG_MAP()
                  
               LRESULT OnInitDialog(UINT, WPARAM, LPARAM, BOOL&)
               {
                  CenterWindow( GetParent() );
                  // a textual static control:
                  s1.SubclassWindow( GetDlgItem(IDS_TEST1) );
                  // a static control displaying an icon
                  s2.SubclassWindow( GetDlgItem(IDS_TEST2) );
                  // set the icon''s link
                  s2.SetLinkText( _T("http://www.microsoft.com") );
                  return 1;
               }
               
               LRESULT OnClose(UINT, WPARAM wID, HWND, BOOL& )
               {
                  ::EndDialog( m_hWnd, wID );
                  return 0;
               }
            private:
               CStaticLink s1, s2;
            }; // CReflectDlg
            
            int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE, LPSTR, int nCmdShow)
            {
               _Module.Init( NULL, hInstance );
            
               CReflectDlg dlg;
               dlg.DoModal();
            
               _Module.Term();
               return 0;
            }
            
            posted on 2007-03-13 10:07 jay 閱讀(892) 評論(0)  編輯 收藏 引用 所屬分類: ATL
            一本色道久久综合| 久久久久久无码国产精品中文字幕 | 久久精品国产精品亚洲精品| 看全色黄大色大片免费久久久| 精品久久久久久无码免费| 怡红院日本一道日本久久| 久久伊人影视| 国产精品久久波多野结衣| 青青国产成人久久91网 | 99蜜桃臀久久久欧美精品网站 | 久久精品成人免费国产片小草| 中文成人无码精品久久久不卡| 精品永久久福利一区二区| 久久精品免费大片国产大片| 久久精品国产亚洲AV大全| 一级做a爰片久久毛片看看| 久久精品免费一区二区三区| 波多野结衣久久一区二区| 国产精品欧美久久久久天天影视| 亚洲中文字幕久久精品无码喷水| 久久本道久久综合伊人| 久久er国产精品免费观看2| 亚洲va中文字幕无码久久| 欧美午夜精品久久久久久浪潮| 国产精品美女久久久久网| 香蕉久久夜色精品国产尤物| 久久午夜电影网| 久久91综合国产91久久精品| 久久午夜伦鲁片免费无码| 久久影院综合精品| 久久久久亚洲精品日久生情| 久久久久久无码国产精品中文字幕| 亚洲综合精品香蕉久久网97 | 99久久无色码中文字幕人妻| 综合久久精品色| 久久婷婷五月综合色奶水99啪 | 97久久久久人妻精品专区| 国产精品一区二区久久不卡 | 国产精品99久久精品爆乳| 国产99久久九九精品无码| 99久久精品国产一区二区蜜芽|