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

笑看風云淡

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

ATL的GUI程序設計(四)

Posted on 2007-10-17 10:42 天之驕子 閱讀(609) 評論(0)  編輯 收藏 引用
四章 對話框和控件

對于Win32 GUI的程序設計來說,其實大部分的情況下我們都不需要自己進行窗口類的設計,而是可以使用Win32中與用戶交互的標準方式——對話框(Dialog Box)。我們可以在VC IDE的資源設計器中設計對話框資源,并在其上放置各種控件資源——的確是非常方便。在本章里,李馬將要向諸位介紹如何利用ATL來操作對話框,以及如何操作對話框上的各種控件。

題外話先

ATL,是的,正是由于我所講的是“ATL的GUI程序設計”,所以我才可能將內容直接經由CWindowImpl過渡到CDialogImpl——而不是過渡到你先前所熟悉的CFrameWnd和Doc/View體系。況且,即使這之后我深入到了CDialogImpl之中,我也不會講到你所熟悉的DDX/DDV機制。再三考慮之下,我還是決定把這些東西在CDialogImpl前一并當作題外話說出來,先。

再來回顧一下ATL的性質。它是一個被設計用來開發COM組件的Framework,所以對GUI部分的支持——套用一句2006年的流行語來說:那是相~~當~~(加重且延長聲音地)少。于是,它沒有“框架窗口”這個概念,更不會有Doc/View體系。其實我對MFC的這一設計特點感覺不錯,畢竟它可以通過一個簡單的CFrameWnd類來實現一個標準的SDI/MDI框架,而且其中帶有工具欄、狀態欄和一個用來容納視圖的標準的工作區域。我們可以通過控制框架窗口中的View及其相關的Doc類型來完成特定文檔類型的讀寫與顯示。——但是,很不幸,這一切都只屬于偉大的MFC;在ATL中,我們什么都沒有。

另外,在對話框的技術領域中,使用ATL的我們也不會享有數據交換與驗證(DDX/DDV)的支持。這一所謂的缺憾我并不想多加評價,一是因為我并不了解MFC中DDX/DDV的內部機制,二是因為我直覺上認為這是影響MFC效率的罪魁之一。在MFC中,我們可以通過向導的支持輕易地為表單的輸入域加入輸入校驗與限制,而且表現在源代碼上的僅僅是幾個宏而已——我自認天下沒有免費的午餐,這幾個簡單的宏既然能為我們包辦一切,那我們勢必會相應地失去些東西,要不然忒便宜了也就。

題外話的最后不免落入俗套,我將會向諸位介紹解決以上缺憾的方法。——也許你猜到了,就是從WTL中尋找解決方案。WTL是對ATL的擴展,所以它的很多代碼可以直接拿過來用(當然可能需要一些小小的修改)。而且,不知道WTL的設計者是不是為了拉攏MFC的開發人員,總之它里面添加了很多與MFC相似的元素,例如以上所說的框架窗口和DDX/DDV。

CDialogImpl

與ATL窗口類CWindowImpl相對應,ATL的對話框類名為CDialogImpl。它的定義如下:

template <class T, class TBase = CWindow>
class ATL_NO_VTABLE CDialogImpl : public CDialogImplBaseT< TBase >
{
// ...
};

你可以從上面的代碼看到,CDialogImpl與CWindowImpl類似,也經歷了一系列的繼承鏈。不過,它較之CWindowImpl的模板參數要簡單得多——畢竟是標準對話框,有些東西是不用操心的。

CDialogImpl的使用方法大致如下:

class CYourDlg : public CDialogImpl< CYourDlg >
{
public:
enum { IDD = IDD_YOUR_DLG };
public:
BEGIN_MSG_MAP( CYourDlg )
// 消息映射
END_MSG_MAP()
public:
// 消息響應函數
///////////////////
// 其余的部分...
};

和CWindowImpl不一樣,CDialogImpl不需要使用DECLARE_WND_CLASS來定義窗口類。在原來DECLARE_WND_CLASS的位置,一個枚舉代替了原來窗口類定義的部分。這里的枚舉列表必須有一個被命名為IDD,并且它的值要被設置為相應的對話框資源ID。呃……寫到這里,我仿佛已經感覺到了你的不快,但CDialogImpl的實現即是如此(以CDialogImpl::DoModal為例):

// from CDialogImpl::DoModal
return ::DialogBoxParam(_Module.GetResourceInstance(), MAKEINTRESOURCE(T::IDD),
hWndParent, (DLGPROC)T::StartDialogProc, dwInitParam);

當然,如果你不喜歡這么做的話,也可以自己從CDialogImplBaseT派生出屬于你的對話框類。

再回到CDialogImpl的話題上來。這個類主要有以下幾個常用的成員函數:

成員函數 說明
DoModal 顯示一個模態對話框
EndDialog 銷毀一個模態對話框
Create 創建一個非模態對話框
DestroyWindow 銷毀一個非模態對話框

這樣看來是不是和MFC十分相似?事實上,如果你已經定義好了一個對話框類,那么它的使用和MFC的對話框類的確沒什么兩樣:

CYourDlg dlg;
dlg.DoModal();

控件的使用

從與用戶交互的角度來看,控件是對話框上必不可少的元素。在Win32 GUI程序設計中,對控件的操作大可歸為兩個方面:一是對控件進行操作,二是響應控件的事件。排除子類化的事件響應(后面我會專門介紹如何在ATL中進行控件的子類化),那么這兩方面的具體實現就是:

  • 使用窗口操作的API函數或發送消息來操作控件。
  • 處理WM_COMMAND或WM_NOTIFY來響應控件的事件。

根據順序,李馬來為大家介紹一下如何對控件進行操作先。這通常可以經由CWindow及其派生類實現,以下代碼示范了如何禁用一個控件:

CWindow ctrl = GetDlgItem( IDC_CONTROL );
ctrl.EnableWindow( FALSE );

如果你要操作的控件需要用到特定的特性(也就是通過發送消息來實現的特有行為),當然你可以通過使用CWindow::SendMessage來實現,不過我并不推薦你使用這種方法,因為SendMessage是不會對消息參數進行類型檢查的。而且,考慮到代碼的可復用性,你可以對CWindow進行派生以達到目的。例如,對于列表控件的封裝可以是類似下面這個樣子:

class CListBox : public CWindow
{
public:
int AddString( LPCTSTR lpszString )
{
return ::SendMessage( m_hWnd, LB_ADDSTRING, 0, (LPARAM)lpszString );
}
};

然后,這樣進行調用:

CListBox list;
list.Attach( GetDlgItem( IDC_LIST ) );
list.AddString( _T("This is a test line") );

可能你會有所疑問:為什么CWindow的例子直接使用了“=”來進行賦值,而CListBox則要使用Attach來初始化。當然,其實這兩者并沒有實質上的區別,只不過是CWindow重載了operator=操作符,而CListBox沒有這樣做罷了(嚴格說來,派生自CWindow的CListBox當然繼承了CWindow的operator=,但是它并不能用于CListBox對象,如果強行使用則會得到一個“error C2679: binary '=' : no operator defined which takes a right-hand operand of type 'struct HWND__ *' (or there is no acceptable conversion)”的錯誤)。如果你也希望CListBox支持operator=的初始化方式,可以這樣來對CListBox進行封裝:

class CListBox : public CWindow
{
public:
CListBox& operator=( HWND hWnd )
{
m_hWnd = hWnd;
return *this;
}
public:
int AddString( LPCTSTR lpszString )
{
return ::SendMessage( m_hWnd, LB_ADDSTRING, 0, (LPARAM)lpszString );
}
};

下面來介紹對控件事件的處理。通常控件在某些事件發生時會以發送WM_COMMAND(普通控件)或WM_NOTIFY(公共控件)消息的方式通知其父窗口,然后我們在其父窗口的窗口過程中處理這些消息即可。WM_COMMAND和WM_NOTIFY的參數意義如下:

  WM_COMMAND WM_NOTIFY
wParam HIWORD(wParam)為通知消息代碼,LOWORD(wParam)為控件ID 發生通知消息的控件ID,不過仍建議使用lParam參數中的ID
lParam 發生通知消息的控件句柄 一個指向NMHDR結構的指針,這個結構中包含了通知消息的各種信息

在ATL中,可以使用如下的宏來進行各種消息的分流(在此將Windows消息分流的宏也一并加上):

消息分流宏 說明
MESSAGE_HANDLER 用于將某個特定消息分流至一個消息處理函數。
MESSAGE_RANGE_HANDLER 用于將某個范圍內的消息一并分流至同一個消息處理函數。
COMMAND_HANDLER 用于將來自特定ID、特定通知碼的WM_COMMAND消息分流至一個消息處理函數。
COMMAND_ID_HANDLER 用于將來自特定ID的WM_COMMAND消息分流至一個消息處理函數。
COMMAND_CODE_HANDLER 用于將來自特定通知碼的WM_COMMAND消息分流至一個消息處理函數。
COMMAND_RANGE_HANDLER 用于將來自某個ID范圍內的WM_COMMAND消息分流至一個消息處理函數。
NOTIFY_HANDLER 用于將來自特定ID、特定通知碼的WM_NOTIFY消息分流至一個消息處理函數。
NOTIFY_ID_HANDLER 用于將來自特定ID的WM_NOTIFY消息分流至一個消息處理函數。
NOTIFY_CODE_HANDLER 用于將來自特定通知碼的WM_NOTIFY消息分流至一個消息處理函數。
NOTIFY_RANGE_HANDLER 用于將來自某個ID范圍內的WM_NOTIFY消息分流至一個消息處理函數。

另外,處理Windows消息、WM_COMMAND消息、WM_NOTIFY消息的消息處理函數應該分別滿足如下規格要求:

// atlwin.h
// Handler prototypes:
// LRESULT MessageHandler(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
// LRESULT CommandHandler(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled);
// LRESULT NotifyHandler(int idCtrl, LPNMHDR pnmh, BOOL& bHandled);

李馬牌通訊錄管理系統

別誤會,這并不是什么正兒八經的所謂“信息管理系統”,而只是我為本章寫下的一個簡單示例而已。這里面并不涉及數據的存儲,而只是為演示本章的內容而實現了必要的流程而已。在此李馬并不打算對這個程序的代碼進行過多解說,僅僅點出幾點需要特殊說明的。

  1. 由于程序中使用了公共控件ListView,所以在WinMain的開頭需要對公共控件庫進行初始化:
    // 初始化公共控件先
    INITCOMMONCONTROLSEX init;
    init.dwSize = sizeof( init );
    init.dwICC = ICC_LISTVIEW_CLASSES;
    InitCommonControlsEx( &init );
    在此我有必要指出,對公共控件庫的初始化應該盡量使用InitCommonControlsEx,即使InitCommonControls貌似更加方便一些。我曾經做過測試,一個使用了DateTime控件并由InitCommonControls初始化的應用程序在WinXP sp2 + VC 6.0編譯完成后,在Win2K下是不能運行的。
  2. CMainDlg::OnRadioSex是為了演示COMMAND_RANGE_HANDLER而寫的一個消息處理函數,其實針對這個示例并不用編寫之——因為Windows系統會自動對Radio按鈕進行檢選狀態的處理;但如若考慮到多組Radio按鈕存在的情況,CMainDlg::OnRadioSex這樣的處理函數便會凸顯出它的用處。
  3. LListView::GetSelectionMark并不能用來準確判斷ListView的選中項,尤其是在選中項被刪除之后。

只有注冊用戶登錄后才能發表評論。
網站導航: 博客園   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>
            欧美国产精品久久| 欧美激情第六页| 亚洲九九精品| 欧美激情第五页| 久久露脸国产精品| 国产真实久久| 国产精品一区二区三区久久久 | 亚洲欧美日韩另类精品一区二区三区 | 欧美精品在线看| 欧美成人tv| 欧美高清在线一区二区| 女生裸体视频一区二区三区| 欧美成人综合| 欧美日韩国产丝袜另类| 欧美日在线观看| 国产精品自在线| 国模吧视频一区| 亚洲欧洲在线看| 一区二区三区免费看| 亚洲一区激情| 国产精品女人网站| 国产精品高潮呻吟| 国产亚洲高清视频| 一区二区三区色| 欧美怡红院视频| 免费在线欧美视频| 日韩午夜剧场| 久久免费高清视频| 欧美激情亚洲自拍| 亚洲一级黄色片| 乱码第一页成人| 午夜精品久久99蜜桃的功能介绍| 欧美一级免费视频| 欧美成黄导航| 国产欧美精品日韩精品| 亚洲高清在线精品| 羞羞答答国产精品www一本| 美女国内精品自产拍在线播放| 亚洲人成在线影院| 亚洲女同精品视频| 欧美精品videossex性护士| 国产偷国产偷精品高清尤物| 亚洲老司机av| 另类国产ts人妖高潮视频| 99国内精品久久| 欧美成人黄色小视频| 国产一区二区丝袜高跟鞋图片 | 欧美国产一区二区| 先锋影音国产精品| 欧美性生交xxxxx久久久| 亚洲欧洲久久| 欧美成人激情视频| 亚洲另类在线视频| 欧美成人免费在线视频| 激情久久影院| 久久久久久久欧美精品| 亚洲一区二区三区四区五区午夜| 欧美精品久久久久a| 午夜久久福利| 一本久道久久综合狠狠爱| 久久综合色播五月| 国产一区二区精品久久99| 午夜久久久久| 亚洲午夜视频| 国产精品久久97| 亚洲自拍啪啪| 亚洲天天影视| 国产精品久久久久毛片大屁完整版 | 欧美黄色影院| 亚洲精品中文在线| 亚洲欧洲精品成人久久奇米网 | 国产欧美91| 欧美一级在线视频| 亚洲欧美一区二区三区极速播放 | 欧美在线影院在线视频| 亚洲欧美www| 国产一区二区三区四区老人| 久久综合激情| 久久蜜桃av一区精品变态类天堂| 一区二区在线免费观看| 欧美承认网站| 欧美日韩中文另类| 性娇小13――14欧美| 欧美在线播放一区| 亚洲激情成人在线| av成人国产| 国产一区二区成人| 欧美高潮视频| 欧美性天天影院| 久久久久一区二区三区四区| 久久亚洲欧洲| 一本大道久久a久久精二百| 久久久久91| 麻豆精品在线观看| 亚洲特黄一级片| 久久精品视频在线看| 一区二区不卡在线视频 午夜欧美不卡在| 日韩亚洲国产欧美| 尤物99国产成人精品视频| 日韩亚洲欧美一区二区三区| 国产一区久久久| 99国产精品久久久| 伊人色综合久久天天| 999在线观看精品免费不卡网站| 国产日本欧美视频| 亚洲精品影院| 在线欧美三区| 午夜精品一区二区三区电影天堂| 亚洲精品视频免费在线观看| 欧美一区二区三区视频| 亚洲午夜女主播在线直播| 免费高清在线视频一区·| 国产精品成人一区二区三区吃奶| 亚洲第一成人在线| 亚洲一区二区三区涩| 亚洲精品国产精品国自产观看浪潮 | 亚洲欧洲综合| 精品动漫av| 亚洲天堂偷拍| av72成人在线| 久久婷婷国产综合精品青草 | 欧美国产精品劲爆| 久久久www成人免费无遮挡大片 | 亚洲第一久久影院| 99视频在线精品国自产拍免费观看| 国产日韩欧美中文| 亚洲区一区二| 国产一区二区成人久久免费影院| 久久久成人精品| 欧美日韩国产综合视频在线观看| 久久精品午夜| 99精品免费| 亚洲裸体视频| aa级大片欧美| 国产一区二区无遮挡| 亚洲欧美自拍偷拍| 亚洲深夜福利视频| 亚洲精品日本| 91久久精品国产| 亚洲人成网站精品片在线观看| 性色av一区二区三区| 亚洲少妇在线| 欧美在线观看天堂一区二区三区| 羞羞答答国产精品www一本| 99re6热在线精品视频播放速度| 亚洲第一精品福利| 亚洲国产高清在线观看视频| 国产日韩在线不卡| 激情91久久| 国产精品一区二区三区免费观看| 欧美性开放视频| 欧美午夜视频在线| 激情婷婷亚洲| 在线一区二区三区做爰视频网站| 欧美成人自拍视频| 91久久国产综合久久蜜月精品 | 久久久久久穴| 亚洲国产精品久久久久秋霞影院 | 一区二区三区欧美在线| 亚洲视频在线一区观看| 欧美一区二区三区四区视频| 久久中文久久字幕| 一本色道久久88综合日韩精品| 亚洲一区二区三区777| 欧美在线资源| 一本色道久久综合| 麻豆成人精品| 国产精品久久久久久久久久久久久久 | 免费欧美日韩国产三级电影| 亚洲人成人99网站| 久久国产精品一区二区| 亚洲精品一区二区三区99| 久久久亚洲一区| 国产欧美一区二区色老头| 日韩视频亚洲视频| 欧美福利影院| 久久久不卡网国产精品一区| 国产精品久久网站| 亚洲图片在线| 99xxxx成人网| 国产精品视区| 久久成人羞羞网站| 亚洲一区高清| 欧美三日本三级三级在线播放| 欧美主播一区二区三区| 国产情人综合久久777777| 亚洲欧美日韩在线| 午夜精品影院在线观看| 国产亚洲精品bv在线观看| 亚洲麻豆视频| 亚洲一区二区精品视频| 国产字幕视频一区二区| 美日韩在线观看| 欧美了一区在线观看| 亚洲一区二区在线| 久久久久.com| 亚洲午夜视频在线| 久久久久久网址| 亚洲欧洲一区二区三区| 亚洲精品黄网在线观看|