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

笑看風云淡

寵辱不驚,看庭前花開花落;去留無意,望天空云卷云舒
posts - 96, comments - 48, trackbacks - 0, articles - 0
  C++博客 :: 首頁 :: 新隨筆 ::  :: 聚合  :: 管理

ATL的GUI程序設計(二)

Posted on 2007-10-17 10:37 天之驕子 閱讀(568) 評論(0)  編輯 收藏 引用

第二章 一個最簡單窗口程序的轉型

我知道,可能會有很多朋友對上一章的“Hello, World!”ATL版不以為然,因為它并不能算是什么ATL程序——畢竟它只不過是有了個CComModule而已。不過不管怎樣我還是要說,它幾乎仍然擁有了一個ATL GUI程序的所有組成部分:入口、初始化、程序體、卸載……

“等等!”也許你會突然打斷我,“——還有注冊窗口類、消息循環呢?”

當然,對于一個完整的GUI程序來講,這也是必要的。

貌似廢話

不清楚你是否已經為本章的內容做好了準備,因為下面我們就要動真格的了。不過考慮到本書的讀者群中可能會存在著相當一部分了解MFC卻對Win32 GUI的基本原理和流程不甚熟悉的朋友,所以李馬特別為你們準備了這一節的內容。SDK的粉絲們可以跳過這一節,如果你們覺得李馬講的有些拖沓冗長的話。

那么,我還是先以一個標準的Win32 SDK程序開始:

//////////////////////////////////////////////////////////////////////////
// ATL的GUI程序設計配套源代碼
// 第二章 一個最簡單窗口程序的轉型
// 工程名稱:HelloSDK
// 作者:李馬
// http://www.titilima.cn
//////////////////////////////////////////////////////////////////////////

#include <windows.h>
#include <tchar.h>

LRESULT CALLBACK HelloWndProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam )
{
    switch ( uMsg )
    {
    case WM_DESTROY:
        
        break;
    case WM_PAINT:
        
        break;
    default:
        return DefWindowProc( hWnd, uMsg, wParam, lParam );
    }
    return 0;
}

BOOL InitApplication( HINSTANCE hInstance )
{
    WNDCLASS wc;
    wc.cbClsExtra    = 0;
    wc.cbWndExtra    = 0;
    wc.hbrBackground = (HBRUSH)GetStockObject( WHITE_BRUSH );
    wc.hCursor       = LoadCursor( NULL, IDC_ARROW );
    wc.hIcon         = LoadIcon( NULL, IDI_APPLICATION );
    wc.hInstance     = hInstance;
    wc.lpfnWndProc   = HelloWndProc;
    wc.lpszClassName = _T("HelloSDK");
    wc.lpszMenuName  = NULL;
    wc.style         = CS_HREDRAW | CS_VREDRAW;

    return RegisterClass( &wc );
}

int WINAPI _tWinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine, int nShowCmd )
{
    // 注冊窗口類
    InitApplication( hInstance );

    // 創建窗口
    HWND hWnd = CreateWindow( _T("HelloSDK"), _T("Hello SDK"), WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT,
        CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, hInstance, NULL );
    ShowWindow( hWnd, nShowCmd );
    UpdateWindow( hWnd );

    // 消息循環
    MSG msg;
    while ( GetMessage( &msg, NULL, 0, 0 ) )
    

    return msg.wParam;
}

不知道你是否會覺得這段代碼有些冗長?事實上,這個程序已經體現了Win32 GUI程序運行的所有流程(請注意,我并不會對這些代碼進行詳細的解釋,因為我已經假設你已經了解了這些代碼具體行為的必要細節。如果不是這樣的話,請參考相關的書籍或者MSDN):

  1. 注冊窗口類的部分。在這個程序中,InitApplication函數完成了這一工作。窗口類的概念類似于OO(面向對象)中的類,所有你在Windows中能看到的窗口都是某個特定窗口類的一份實例。但是,窗口類并非任何一種OOP語言中的類——它所包括的并不是通稱的屬性和方法(在C++中稱作成員變量和成員函數),而是屬性和響應。這個區別可能會使你感到費解,我會在下一章中為你詳細介紹——因為ATL中對窗口的封裝類將這一點體現得十分淋漓盡致。
  2. 創建窗口的部分。在通常的SDK代碼里,這些代碼被封裝在一個名為InitInstance的函數中。這段代碼所做的工作一般是創建窗口并將其顯示出來。
  3. 消息循環。Windows是一個基于消息機制的操作系統,各個窗口之間的通信也主要是靠Windows消息來完成的。而程序中的消息循環也就是將本程序UI線程中的消息隊列中提取各種消息,進行處理(如果有必要的話)之后分發給各個消息的屬主窗口(或者說是目標窗口)。

在這里需要指出的是,HelloWndProc是我們自己定義的一個函數,我們需要用它來控制我們對特定窗口消息的特定響應。我們只需要在注冊窗口類之前,將這個函數的地址(也就是函數名)賦值給WNDCLASS::lpfnWndProc成員就可以了。這個函數我們自己不需要進行調用,它的調用是當我們的窗口收到窗口消息后,由Windows完成的。在這個回調函數中,我們的處理是這樣的:

  • WM_DESTROY。在窗口被銷毀的時候,窗口會收到此消息。在這里,我們會調用PostQuitMessage,用以向當前UI線程的消息隊列之中發送一條WM_QUIT消息,GetMessage在收到這條消息后,會返回FALSE,也就結束了消息循環,WinMain也就結束了。
  • WM_PAINT。在窗口需要繪制的時候,窗口會收到此消息。在這里我們只是簡單的在窗口的中間繪制了一行文字“Hello, SDK!”。
  • 其它消息。這些消息都是我們不關心的,所以我們將其交由系統默認的窗口過程DefWindowProc來處理。

這段代碼貌似冗長,但實際上還是很有條理的,你可以根據它以及我以上的解說來對照這個程序的ATL版本。


ATL等同品

在寫作這本書的時候,我總是希望我每次都能夠能使用讓你不太陌生的代碼來循序漸進地引導你。考慮再三,對于“Hello, ATL!”的這個程序,我決定先把它的WinMain展現給你:

int WINAPI _tWinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine, int nShowCmd )
{
    _Module.Init( NULL, hInstance );

    // 創建窗口
    CHelloATLWnd wnd;
    wnd.Create( NULL, CHelloATLWnd::rcDefault, _T("Hello ATL") );
    wnd.ShowWindow( nShowCmd );
    wnd.UpdateWindow();

    // 消息循環
    MSG msg;
    while ( GetMessage( &msg, NULL, 0, 0 ) )
    

    _Module.Term();
    return msg.wParam;
}

OK,上一章介紹過的_Module又出現在你的眼前了——不過還是沒有什么特別的變化,仍然是那熟悉的Init和Term。而且,正如“山喲還是那座山”一樣,消息循環喲也仍然是那個消息循環。當然,你肯定也發現了那寥寥的變化:CHelloATLWnd是什么?在我將它的代碼展現給你之前,你可能會做出這樣的猜想:

  • 這是一個C++類,它對Win32窗口類進行了封裝。
  • 這個類封裝了大多數窗口操作的API函數,諸如CreateWindow、ShowWindow、UpdateWindow。
  • 窗口類的注冊可能也是在這個C++類中完成的。

好,打住,這就夠了。讓我們來撩開CHelloATLWnd那貌似神秘的面紗吧,趕緊著。

class CHelloATLWnd : public CWindowImpl< CHelloATLWnd, CWindow, CWinTraits< WS_OVERLAPPEDWINDOW > >
{
public:
    CHelloATLWnd()
    
public:
    DECLARE_WND_CLASS( _T("HelloATL") )
public:
    BEGIN_MSG_MAP( CHelloATLWnd )
        MESSAGE_HANDLER( WM_DESTROY, OnDestroy )
        MESSAGE_HANDLER( WM_PAINT, OnPaint )
    END_MSG_MAP()
public:
    LRESULT OnDestroy( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& hHandled )
    {
        ::PostQuitMessage( 0 );
        return 0;
    }
    LRESULT OnPaint( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& hHandled )
    {
        HDC hdc;
        PAINTSTRUCT ps;

        hdc = BeginPaint( &ps );
        DrawText( hdc, _T("Hello, ATL!"), -1, &ps.rcPaint, DT_CENTER | DT_VCENTER | DT_SINGLELINE );
        EndPaint( &ps );
        return 0;
    }
};

猜想,還是猜想!

請允許我在本章中不為你解釋這個類的任何具體細節,取而代之的是繼續的猜想。因為,這個類中需要解釋的東西太多了,以至于我必須為它單獨開辟一章。

  • 窗口類的注冊是由這個C++類的構造函數與DECLARE_WND_CLASS宏一起完成的。
  • 對于BEGIN_MSG_MAP與END_MSG_MAP這一部分,想必使用過MFC的朋友們應該更容易理解。是的,這一對宏可以算作ATL的消息映射,在其中由MESSAGE_HANDLER作為消息分流器,將各種窗口消息分配給各個處理函數。
  • 創建窗口時指定的樣式貌似和模板參數CWinTraits有關。

當然,除了這些猜想之外,你可能還會同時存在以下疑問:

  • CWindowImpl、CWindow、CWinTraits究竟是什么?
  • 窗口類是在何時注冊的?
  • 消息分流器是如何實現的?

也許你還會有更多的疑問,那么就讓我一并將它們留到下一章再解決吧。如果你實在等不及的話,atlwin.h的代碼也會告訴你一切的。

補敘CComModule

由于這本書主要針對的是ATL 3.0/Visual C++ 6.0,所以我疏忽了對CComModule的研究。在此感謝老李老刀兄提出的一點,就是CComModule在ATL 7.0中已經不建議使用了。于是我將MSDN中的相關章節摘抄下來,權作借花獻佛之用。

CComModule 替換類

ATL 的早期版本使用 CComModule。在 ATL 7.0 中,CComModule 功能被若干個類所取代:

  • CAtlBaseModule 包含大多數使用 ATL 的應用程序所需的信息。包含模塊和資源實例的 HINSTANCE。
  • CAtlComModule 包含 ATL 中的 COM 類所需的信息。
  • CAtlWinModule 包含 ATL 中的窗口化類所需的信息。
  • CAtlDebugInterfacesModule 包含接口調試支持。
  • CAtlModule 下列 CAtlModule 派生的類被自定義為包含特定應用程序類型中所需的信息。這些類中的大部分成員都可以被重寫:
    CAtlDllModuleT 在 DLL 應用程序中使用。為標準導出提供代碼。
    CAtlExeModuleT 在 EXE 應用程序中使用。提供 EXE 中所需的代碼。
    CAtlServiceModuleT 為創建 Windows NT 和 Windows 2000 服務提供支持。
    CComModule 仍然可用以便向后兼容。

分布 CComModule 功能的原因

由于以下原因,CComModule 的功能分布到了幾個新類中:

  • 使 CComModule 中的功能呈粒狀分割。
    對 COM、窗口化、接口調試和應用程序特定的(DLL 或 EXE)功能的支持現在在不同的類中。
  • 自動為這些模塊的每一個聲明全局實例。
    所需模塊類的全局實例鏈接到項目中。
  • 消除了調用 Init 和 Term 方法的必要性。
    Init 和 Term 方法已移動到模塊類的構造函數和析構函數中;不再需要調用 Init 和 Term。

不過,出于代碼的兼容性以及WTL的內容考慮,本系列后續文章仍然將使用ATL 3.0中的CComModule。


只有注冊用戶登錄后才能發表評論。
網站導航: 博客園   IT新聞   BlogJava   博問   Chat2DB   管理


青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <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人久久精品视频最新地址| 亚洲人成人99网站| 亚洲电影一级黄| 亚洲精品人人| 在线观看一区二区视频| 亚洲精品视频在线观看免费| 欧美一区二区三区免费视| 久久漫画官网| 亚洲精品久久久久久久久久久久久 | 久久综合99re88久久爱| 国产一在线精品一区在线观看| 欧美日韩一区二区三区在线视频| 小嫩嫩精品导航| 亚洲精品一区在线| 欧美日韩少妇| 久久美女性网| 欧美与欧洲交xxxx免费观看| 欧美成人午夜77777| 欧美99在线视频观看| 卡通动漫国产精品| 午夜日韩福利| 欧美 日韩 国产在线 | 日韩视频免费大全中文字幕| 国产精品久久久久99| 一本到高清视频免费精品| 亚洲国产国产亚洲一二三| 性欧美大战久久久久久久免费观看| 国产欧美va欧美不卡在线| 欧美在线观看一区| 中文av字幕一区| 久久噜噜噜精品国产亚洲综合| 免费在线看一区| 亚洲专区一二三| 欧美激情影音先锋| 国产色综合网| 亚洲一区在线免费| 亚洲国产欧美一区二区三区同亚洲| 亚洲手机在线| 国产精品久久二区| 99精品国产热久久91蜜凸| 亚洲综合第一| 免费观看成人网| 亚洲黄网站在线观看| 能在线观看的日韩av| 欧美久久视频| 亚洲视频欧美在线| 欧美成人精品不卡视频在线观看| 亚洲精品一区在线观看| 久久乐国产精品| 亚洲欧洲精品成人久久奇米网| 亚洲日韩欧美视频| 欧美精品亚洲精品| 亚洲激情影视| 亚洲国产小视频在线观看| 久久久久久色| 亚洲电影免费| 欧美激情一区二区三区在线视频观看 | 猫咪成人在线观看| 欧美日韩在线不卡| 国产日韩三区| 亚洲黄色片网站| 午夜激情一区| 欧美日韩蜜桃| 欧美高清一区| 久久久久国色av免费看影院| 国产目拍亚洲精品99久久精品| 亚洲一二三四区| 亚洲精品乱码久久久久久日本蜜臀| 狠狠噜噜久久| 99在线|亚洲一区二区| 欧美日韩成人综合| 在线一区欧美| 亚洲欧美中日韩| 黄色国产精品| 美腿丝袜亚洲色图| 久久综合精品一区| 日韩午夜在线观看视频| 9l国产精品久久久久麻豆| 欧美日韩亚洲天堂| 午夜精品久久久久| 久久久国产一区二区三区| 一区在线播放| 亚洲区欧美区| 国产精品久久久一区二区三区| 欧美在线中文字幕| 久久人人97超碰精品888| 亚洲精选久久| 亚洲一区二区三区四区中文 | 欧美性猛片xxxx免费看久爱| 亚洲欧美精品| 久久一二三四| 亚洲欧美一级二级三级| 久久国产精品色婷婷| 欧美国产一区二区三区激情无套| 欧美成人免费全部观看天天性色| 在线日本成人| 亚洲精品中文字幕有码专区| 国产欧美一区在线| 欧美国产成人在线| 国产精品视频大全| 亚洲成色最大综合在线| 国产精品一二一区| 亚洲黄色av一区| 国内一区二区三区在线视频| 亚洲国产专区| 国模叶桐国产精品一区| 99精品久久久| 亚洲精选视频免费看| 久久久免费精品视频| 亚洲午夜性刺激影院| 欧美一级电影久久| 亚洲一区二区三区中文字幕| 噜噜噜躁狠狠躁狠狠精品视频 | 欧美激情91| 日韩亚洲欧美一区二区三区| 亚洲九九精品| 亚洲国产精品专区久久| 亚洲自拍偷拍网址| 亚洲嫩草精品久久| 欧美日韩国产123| 欧美jizzhd精品欧美喷水| 国产欧美三级| 亚洲欧美日韩另类| 亚洲无玛一区| 欧美视频日韩| 亚洲免费电影在线| 99在线视频精品| 欧美女同视频| 亚洲第一精品电影| 在线免费一区三区| 开心色5月久久精品| 奶水喷射视频一区| 亚洲国产一区二区三区a毛片| 欧美在线3区| 欧美中文字幕| 性欧美在线看片a免费观看| 欧美一级二级三级蜜桃| 国产精品美女www爽爽爽视频| 99视频一区二区三区| 亚洲一区二区欧美| 国产精品毛片va一区二区三区| 亚洲午夜电影网| 久久精品导航| 激情偷拍久久| 久久综合一区二区| 欧美国产先锋| 99视频热这里只有精品免费| 欧美日韩日本视频| 亚洲午夜精品一区二区| 午夜精品久久久久久| 国产综合一区二区| 欧美91大片| 一区二区三区精品在线| 欧美在线视频二区| 亚洲国产成人精品久久久国产成人一区| 老司机精品视频一区二区三区| 欧美激情一区在线观看| 一区二区久久久久| 欧美亚男人的天堂| 国产精品a级| 亚洲欧洲av一区二区| 麻豆精品精品国产自在97香蕉| 亚洲国产91精品在线观看| 欧美绝品在线观看成人午夜影视| 亚洲视频免费| 久久亚洲综合网| 亚洲午夜高清视频| 国内外成人免费激情在线视频 | 欧美三级资源在线| 欧美日韩国产天堂| 一区二区三区国产在线观看| 国产精品稀缺呦系列在线| 久久高清免费观看| aaa亚洲精品一二三区| 久久精品国产v日韩v亚洲| 亚洲电影在线观看| 欧美日韩国产综合视频在线观看中文| 亚洲精品国产欧美| 久久不射中文字幕| 亚洲日本成人| 国产伦精品一区二区三区四区免费| 久久蜜桃香蕉精品一区二区三区| 亚洲激情在线激情| 亚洲天堂成人在线观看| 伊人久久婷婷色综合98网| 国产精品白丝黑袜喷水久久久| 久久琪琪电影院| 午夜在线精品偷拍| 日韩午夜在线电影| 蜜桃av久久久亚洲精品| 性久久久久久久久| 日韩小视频在线观看| 亚洲第一福利在线观看|