欧美性猛交XXXX免费看蜜桃,成人网18免费韩国,亚洲国产成人精品区综合,欧美日韩一区二区三区高清不卡,亚洲综合一区二区精品久久

打開(kāi)APP
userphoto
未登錄

開(kāi)通VIP,暢享免費電子書(shū)等14項超值服

開(kāi)通VIP
VC知識庫文章 - MFC程序員的WTL指南: Part V - 高級對話(huà)框用戶(hù)界面類(lèi)



原作 :Michael Dunn [英文原文]
翻譯 :Orbit(桔皮干了) [http://www.winmsg.com/cn]

下載演示程序代碼

本章內容 第五章介紹

在上一篇文章我們介紹了一些與對話(huà)框和控件有關(guān)的WTL的特性,它們和MFC的相應的類(lèi)作用相同。本文將介紹一些新類(lèi)實(shí)現高級界面特性新類(lèi):控件自畫(huà)和自定外觀(guān)控件,新的WTL控件,UI updating和對話(huà)框數據驗證(DDV)。

特別的自畫(huà)和外觀(guān)定制類(lèi)

由于自畫(huà)和定制外觀(guān)控件在圖形用戶(hù)界面中是很常用的手段,所以WTL提供了幾個(gè)嵌入類(lèi)來(lái)完成這些令人厭煩的工作。我接著(zhù)就會(huì )介紹它們,事實(shí)上我們在上一個(gè)例子工程ControlMania2的結尾部分已經(jīng)這么做了。如果你正隨著(zhù)我的講解用應用程序生成向導創(chuàng )建新工程,請不要忘了使用無(wú)模式對話(huà)框,為了使正常工作必須使用無(wú)模式對話(huà)框,我會(huì )在對話(huà)框中控件的UI Updating部分詳細解釋為什么這樣作。

COwnerDraw

控件的自畫(huà)需要響應四個(gè)消息:WM_MEASUREITEM, WM_DRAWITEM, WM_COMPAREITEM, 和WM_DELETEITEM,在atlframe.h頭文件中定義的COwnerDraw類(lèi)可以簡(jiǎn)化這些工作,使用這個(gè)類(lèi)就不需要處理這四個(gè)消息,你只需將消息鏈入COwnerDraw,它會(huì )調用你的類(lèi)中的重載函數。

如何將消息鏈入COwnerDraw取決與你是否將消息反射給控件,兩種方法有些不同。下面是COwnerDraw類(lèi)的消息映射鏈,它使得兩種方法的差別更加明顯:

template <class T> class COwnerDraw{public:  BEGIN_MSG_MAP(COwnerDraw<T>)    MESSAGE_HANDLER(WM_DRAWITEM, OnDrawItem)    MESSAGE_HANDLER(WM_MEASUREITEM, OnMeasureItem)    MESSAGE_HANDLER(WM_COMPAREITEM, OnCompareItem)    MESSAGE_HANDLER(WM_DELETEITEM, OnDeleteItem)  ALT_MSG_MAP(1)    MESSAGE_HANDLER(OCM_DRAWITEM, OnDrawItem)    MESSAGE_HANDLER(OCM_MEASUREITEM, OnMeasureItem)    MESSAGE_HANDLER(OCM_COMPAREITEM, OnCompareItem)    MESSAGE_HANDLER(OCM_DELETEITEM, OnDeleteItem)  END_MSG_MAP()};

注意,消息映射鏈的主要部分處理WM_*消息,而ATL部分處理反射的消息,OCM_*。自畫(huà)的通知消息就像WM_NOTIFY消息一樣,你可以在父窗口處理它們,也可以將它們反射會(huì )控件,如果你使用前一種方法,消息被直接鏈入COwnerDraw:

class CSomeDlg : public COwnerDraw<CSomeDlg>, ...{  BEGIN_MSG_MAP(CSomeDlg)    //...    CHAIN_MSG_MAP(COwnerDraw<CSomeDlg>)  END_MSG_MAP()   void DrawItem ( LPDRAWITEMSTRUCT lpdis );};

當然,如果你想要控件自己處理這些消息,你需要使用CHAIN_MSG_MAP_ALT宏將消息鏈入ALT_MSG_MAP(1)部分:

class CSomeButtonImpl : public COwnerDraw<CSomeButtonImpl>, ...{  BEGIN_MSG_MAP(CSomeButtonImpl)    //...    CHAIN_MSG_MAP_ALT(COwnerDraw<CSomeButtonImpl>, 1)    DEFAULT_REFLECTION_HANDLER()  END_MSG_MAP()   void DrawItem ( LPDRAWITEMSTRUCT lpdis );};

COwnerDraw類(lèi)將對消息傳遞的參數展開(kāi),然后調用你的類(lèi)中的實(shí)現函數。上面的例子中,我們自己的類(lèi)實(shí)現DrawItem()函數,當有WM_DRAWITEM或OCM_DRAWITEM消息被鏈入COwnerDraw時(shí),這個(gè)函數就會(huì )被調用。你可以重載的方法有:

void DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct);void MeasureItem(LPMEASUREITEMSTRUCT lpMeasureItemStruct);int  CompareItem(LPCOMPAREITEMSTRUCT lpCompareItemStruct);void DeleteItem(LPDELETEITEMSTRUCT lpDeleteItemStruct);

如果你不想處理某個(gè)消息,你可以調用SetMsgHandled(false),消息會(huì )被傳遞給消息映射鏈中的其他響應者。SetMsgHandled()事實(shí)上是COwnerDraw類(lèi)的成員函數,但是它的作用和在BEGIN_MSG_MAP_EX()中使用SetMsgHandled()一樣。

對于ControlMania2,它從ControlMania1中的樹(shù)控件開(kāi)始,添加了自畫(huà)按鈕處理反射的WM_DRAWITEM消息,下面是資源編輯器中的新按鈕:

現在我們需要一個(gè)新類(lèi)實(shí)現自畫(huà)按鈕:

class CODButtonImpl : public CWindowImpl<CODButtonImpl, CButton>,                      public COwnerDraw<CODButtonImpl>{public:    BEGIN_MSG_MAP_EX(CODButtonImpl)        CHAIN_MSG_MAP_ALT(COwnerDraw<CODButtonImpl>, 1)        DEFAULT_REFLECTION_HANDLER()    END_MSG_MAP()     void DrawItem ( LPDRAWITEMSTRUCT lpdis );};

DrawItem()使用了像BitBlt()這樣的GDI函數向按鈕的表面畫(huà)位圖,代碼應該很容易理解,因為WTL使用的類(lèi)名和函數名都和MFC類(lèi)似。

void CODButtonImpl::DrawItem ( LPDRAWITEMSTRUCT lpdis ){// NOTE: m_bmp is a CBitmap init‘‘ed in the constructor.CDCHandle dc = lpdis->hDC;CDC dcMem;     dcMem.CreateCompatibleDC ( dc );    dc.SaveDC();    dcMem.SaveDC();     // Draw the button‘‘s background, red if it has the focus, blue if not.    if ( lpdis->itemState & ODS_FOCUS )         dc.FillSolidRect ( &lpdis->rcItem, RGB(255,0,0) );    else        dc.FillSolidRect ( &lpdis->rcItem, RGB(0,0,255) );     // Draw the bitmap in the top-left, or offset by 1 pixel if the button    // is clicked.    dcMem.SelectBitmap ( m_bmp );     if ( lpdis->itemState & ODS_SELECTED )         dc.BitBlt ( 1, 1, 80, 80, dcMem, 0, 0, SRCCOPY );    else        dc.BitBlt ( 0, 0, 80, 80, dcMem, 0, 0, SRCCOPY );     dcMem.RestoreDC(-1);    dc.RestoreDC(-1);}

我們的按鈕看起來(lái)是這個(gè)樣子:

CCustomDraw

CCustomDraw類(lèi)使用和COwnerDraw類(lèi)相同的方法處理NM_CUSTOMDRAW消息,對于自定繪制的每個(gè)階段都有相應的重載函數:

DWORD OnPrePaint(int idCtrl, LPNMCUSTOMDRAW lpNMCD);DWORD OnPostPaint(int idCtrl, LPNMCUSTOMDRAW lpNMCD);DWORD OnPreErase(int idCtrl, LPNMCUSTOMDRAW lpNMCD);DWORD OnPostErase(int idCtrl, LPNMCUSTOMDRAW lpNMCD); DWORD OnItemPrePaint(int idCtrl, LPNMCUSTOMDRAW lpNMCD);DWORD OnItemPostPaint(int idCtrl, LPNMCUSTOMDRAW lpNMCD);DWORD OnItemPreErase(int idCtrl, LPNMCUSTOMDRAW lpNMCD);DWORD OnItemPostEraset(int idCtrl, LPNMCUSTOMDRAW lpNMCD); DWORD OnSubItemPrePaint(int idCtrl, LPNMCUSTOMDRAW lpNMCD);

這些函數默認都是返回CDRF_DODEFAULT,如果想自畫(huà)控件或返回一個(gè)不同的值,就需要重載這些函數:

你可能注意到上面的屏幕截圖將“道恩”(Dawn:女名)顯示成綠色,這是因為CBuffyTreeCtrl將消息鏈入CCustomDraw并重載了OnPrePaint()和OnItemPrePaint()方法。向樹(shù)控件中添加節點(diǎn)時(shí),節點(diǎn)的item data字段被設置成1,OnItemPrePaint()檢查這個(gè)值,然后改變文字的顏色。

DWORD CBuffyTreeCtrl::OnPrePaint(int idCtrl,                                  LPNMCUSTOMDRAW lpNMCD){    return CDRF_NOTIFYITEMDRAW;} DWORD CBuffyTreeCtrl::OnItemPrePaint(int idCtrl,                                      LPNMCUSTOMDRAW lpNMCD){    if ( 1 == lpNMCD->lItemlParam )        pnmtv->clrText = RGB(0,128,0);     return CDRF_DODEFAULT;}

CCustomDraw類(lèi)也有SetMsgHandled()函數,你可以像在COwnerDraw類(lèi)那樣使用這個(gè)函數。

WTL的新控件

WTL有幾個(gè)新控件,它們要么是其他封裝類(lèi)的擴展(像 CTreeViewCtrlEx),要么是提供windows標準控件沒(méi)有的新功能(像 CHyperLink)。

CBitmapButton

WTL的CBitmapButton類(lèi)聲明在atlctrlx.h中,它比MFC的同名類(lèi)使用起來(lái)要簡(jiǎn)單的多。WTL的CBitmapButton類(lèi)使用image list而不是單個(gè)的位圖資源,你可以將多個(gè)按鈕的圖像放到一個(gè)位圖文件中,減少GDI資源的占用。這對于使用很多圖片并需要在Windows 9X系統上運行的程序很有好處,因為使用太多的單個(gè)位圖將會(huì )很快耗盡GDI資源并導致系統崩潰。

CBitmapButton是一個(gè)CWindowImpl派生類(lèi),它又很多特色:自動(dòng)調整控件的大小,自動(dòng)生成3D邊框,支持hot-tracking,每個(gè)按鈕可以使用多個(gè)圖像分別表示按鈕的不同狀態(tài)。

在ControlMania2中,我們對前面的例子創(chuàng )建的自畫(huà)按鈕使用CBitmapButton類(lèi)?,F在CMainDlg對話(huà)框類(lèi)中添加CBitmapButton類(lèi)型的變量m_wndBmpBtn,調用SubclassWindow()函數或使用DDX將其和控件聯(lián)系起來(lái),將位圖裝載到image list并告訴按鈕使用這個(gè)image list,還要告訴按鈕每個(gè)圖像分別對應按鈕的什么狀態(tài)。下面是OnInitDialog()函數中建立和使用這個(gè)按鈕的代碼段:

    // Set up the bitmap buttonCImageList iml;     iml.CreateFromImage ( IDB_ALYSON_IMGLIST, 81, 1, CLR_NONE,                          IMAGE_BITMAP, LR_CREATEDIBSECTION );     m_wndBmpBtn.SubclassWindow ( GetDlgItem(IDC_ALYSON_BMPBTN) );    m_wndBmpBtn.SetToolTipText ( _T("Alyson") );    m_wndBmpBtn.SetImageList ( iml );    m_wndBmpBtn.SetImages ( 0, 1, 2, 3 );

默認情況下,按鈕只是引用image list,所以OnInitDialog()不能delete它所創(chuàng )建的image list。下面顯示的是新按鈕的一般狀態(tài),注意控件是如何根據圖像的大小來(lái)調整自己的大小。

因為CBitmapButton是一個(gè)非常有用的類(lèi),我想介紹一下它的公有方法。

CBitmapButton methods

CBitmapButtonImpl類(lèi)包含了實(shí)現一個(gè)按鈕的所有代碼,除非你想重載某個(gè)方法或消息處理,你可以對控件直接使用CBitmapButton類(lèi)。

CBitmapButtonImpl constructor
CBitmapButtonImpl(DWORD dwExtendedStyle = BMPBTN_AUTOSIZE,HIMAGELIST hImageList = NULL)

構造函數可以指定按鈕的擴展樣式(這與窗口的樣式不沖突)和圖像列表,通常使用默認參數就足夠了,因為可以使用其他的方法設定這些屬性。

SubclassWindow()
BOOL SubclassWindow(HWND hWnd)

SubclassWindow()是個(gè)重載函數,主要完成控件的子類(lèi)化和初始化控件類(lèi)保有的內部數據。

Bitmap button extended styles
DWORD GetBitmapButtonExtendedStyle()DWORD SetBitmapButtonExtendedStyle(DWORD dwExtendedStyle, DWORD dwMask = 0)

CBitmapButton支持一些擴展樣式,這些擴展樣式會(huì )對按鈕的外觀(guān)和操作方式產(chǎn)生影響:

BMPBTN_HOVER
使用hot-tracking,當鼠標移到按鈕上時(shí)按鈕被畫(huà)成焦點(diǎn)狀態(tài)。
BMPBTN_AUTO3D_SINGLE, BMPBTN_AUTO3D_DOUBLE
在按鈕圖像周?chē)詣?dòng)產(chǎn)生一個(gè)三維邊框,當按鈕擁有焦點(diǎn)時(shí)會(huì )顯示一個(gè)表示焦點(diǎn)的虛線(xiàn)矩形框。另外如果你沒(méi)有指定按鈕按下?tīng)顟B(tài)的圖像,將會(huì )自動(dòng)生成一個(gè)。BMPBTN_AUTO3D_DOUBLE樣式生成的邊框稍微粗一些,其他特征和BMPBTN_AUTO3D_SINGLE一樣。
BMPBTN_AUTOSIZE
按鈕調整自己的大小以適應圖像大小,這是默認樣式。
BMPBTN_SHAREIMAGELISTS
如果指定這個(gè)樣式,按鈕不負責銷(xiāo)毀按鈕使用的image list,如果不使用這個(gè)樣式,CBitmapButton的析構函數會(huì )銷(xiāo)毀按鈕使用的image list。
BMPBTN_AUTOFIRE
如果設置這個(gè)樣式,在按鈕上按住鼠標左鍵不放將會(huì )產(chǎn)生連續的WM_COMMAND消息。

調用SetBitmapButtonExtendedStyle()時(shí),dwMask參數控制著(zhù)那個(gè)樣式將被改變,默認值是0,意味著(zhù)用新樣式完全替換舊的樣式。

Image list management
HIMAGELIST GetImageList()HIMAGELIST SetImageList(HIMAGELIST hImageList)

調用SetImageList()設置按鈕使用的image list。

Tooltip management
int  GetToolTipTextLength()bool GetToolTipText(LPTSTR lpstrText, int nLength)bool SetToolTipText(LPCTSTR lpstrText)

CBitmapButton支持顯示工具提示(tooltip),調用SetToolTipText()指定顯示的文字。

Setting the images to use
void SetImages(int nNormal, int nPushed = -1,int nFocusOrHover = -1, int nDisabled = -1)

調用SetImages()函數告訴按鈕分別使用image list的拿一個(gè)圖像表示那個(gè)狀態(tài)。nNormal是必須的,其它是可選的,使用-1表示對應的狀態(tài)沒(méi)有圖像。

CCheckListViewCtrl

CCheckListViewCtrl類(lèi)在atlctrlx.h中定義,它是一個(gè)CWindowImpl派生類(lèi),實(shí)現了一個(gè)帶檢查框的list view控件。它和MFC的CCheckListBox不同,CCheckListBox只是一個(gè)list box,不是list view。CCheckListViewCtrl類(lèi)非常簡(jiǎn)單,只添加了很少的函數,當然,它使用了一個(gè)新的輔助類(lèi)CCheckListViewCtrlImplTraits,它和CWinTraits類(lèi)的作用類(lèi)似,只是第三個(gè)參數是list view控件的擴展樣式屬性,如果你沒(méi)有定義自己的CCheckListViewCtrlImplTraits,它將使用沒(méi)默認的樣式:LVS_EX_CHECKBOXES | LVS_EX_FULLROWSELECT。

下面是一個(gè)定義list view擴展樣式屬性的例子,加入了一個(gè)使用這個(gè)樣式的新類(lèi)。(注意,擴展屬性必須包含LVS_EX_CHECKBOXES,否則會(huì )因起斷言錯誤消息。)

typedef CCheckListViewCtrlImplTraits<    WS_CHILD | WS_VISIBLE | LVS_REPORT,     WS_EX_CLIENTEDGE,    LVS_EX_CHECKBOXES | LVS_EX_GRIDLINES | LVS_EX_UNDERLINEHOT |      LVS_EX_ONECLICKACTIVATE> CMyCheckListTraits; class CMyCheckListCtrl :    public CCheckListViewCtrlImpl<CMyCheckListCtrl, CListViewCtrl,                                   CMyCheckListTraits>{private:    typedef CCheckListViewCtrlImpl<CMyCheckListCtrl, CListViewCtrl,                                    CMyCheckListTraits> baseClass;public:    BEGIN_MSG_MAP(CMyCheckListCtrl)        CHAIN_MSG_MAP(baseClass)    END_MSG_MAP()};
CCheckListViewCtrl methods SubclassWindow()

當子類(lèi)化一個(gè)已經(jīng)存在的list view控件時(shí),SubclassWindow()查看CCheckListViewCtrlImplTraits的擴展樣式屬性并將之應用到控件上。未用到前兩個(gè)參數(窗口樣式和擴展窗口樣式)。

SetCheckState() and GetCheckState()

這些方法實(shí)際上是在CListViewCtrl中,SetCheckState()使用行的索引和一個(gè)布爾類(lèi)型參數,該布爾參數的值表示是否check這一行。GetCheckState()以行索引未參數,返回改行的checked狀態(tài)。

CheckSelectedItems()

這個(gè)方法使用item的索引作為參數,它翻轉這個(gè)item的check狀態(tài),這個(gè)item必須是被選定的,同時(shí)還將其他所有被選擇的item設置成相應狀態(tài)(譯者加:多選狀態(tài)下)。你大概不會(huì )用到這個(gè)方法,因為CCheckListViewCtrl會(huì )在check box被單擊或用戶(hù)按下了空格鍵時(shí)設置相應的item的狀態(tài)。

下面是ControlMania2中的CCheckListViewCtrl的樣子:

CTreeViewCtrlEx and CTreeItem

有兩個(gè)類(lèi)使得樹(shù)控件的使用簡(jiǎn)化了很多:CTreeItem類(lèi)封裝了HTREEITEM,一個(gè)CTreeItem對象含有一個(gè)HTREEITEM和一個(gè)指向包含這個(gè)HTREEITEM的樹(shù)控件的指針,使你不必每次調用都引用樹(shù)控件;CTreeViewCtrlEx和CTreeViewCtrl一樣,只是它的方法操作CTreeItem而不是HTREEITEM。例如,InsertItem()函數返回一個(gè)CTreeItem而不是HTREEITEM,你可以使用CTreeItem操作新添加的item。下面是一個(gè)例子:

// Using plain HTREEITEMs:HTREEITEM hti, hti2;     hti = m_wndTree.InsertItem ( "foo", TVI_ROOT, TVI_LAST );    hti2 = m_wndTree.InsertItem ( "bar", hti, TVI_LAST );    m_wndTree.SetItemData ( hti2, 100 ); // Using CTreeItems:CTreeItem ti, ti2;     ti = m_wndTreeEx.InsertItem ( "foo", TVI_ROOT, TVI_LAST );    ti2 = ti.AddTail ( "bar", 0 );    ti2.SetData ( 100 );

CTreeViewCtrl對HTREEITEM的每一個(gè)操作,CTreeItem都有與之對應的方法,正像每一個(gè)關(guān)于HWND的API都有一個(gè)CWindow方法與之對應一樣。查看ControlMania2的代碼可以看到更多的CTreeViewCtrlEx和CTreeItem類(lèi)的方法的演示。

CHyperLink

CHyperLink是一個(gè)CWindowImpl派生類(lèi),它子類(lèi)化一個(gè)static text控件,使之變成可點(diǎn)擊的超鏈接。CHyperLink根據用戶(hù)的IE使用的顏色畫(huà)鏈接對象,還支持鍵盤(pán)導航。CHyperLink類(lèi)的構造函數沒(méi)有參數,下面是其它的公有方法。

CHyperLink methods

CHyperLinkImpl類(lèi)內含實(shí)現一個(gè)超鏈接的全部代碼,如果不需要重載它的方法或處理消息的話(huà),你可以直接使用CHyperLink類(lèi)。

SubclassWindow()
BOOL SubclassWindow(HWND hWnd)

重載函數SubclassWindow()完成控件子類(lèi)化,然后初始化該類(lèi)保有的內部數據。

Text label management
bool GetLabel(LPTSTR lpstrBuffer, int nLength)bool SetLabel(LPCTSTR lpstrLabel)

獲得或設置控件顯示的文字,如果不指定顯示文字,控件會(huì )顯示資源編輯器指定給控件的靜態(tài)字符串。

Hyperlink management
bool GetHyperLink(LPTSTR lpstrBuffer, int nLength)bool SetHyperLink(LPCTSTR lpstrLink)

獲得或設置控件關(guān)聯(lián)超鏈接的URL,如果不指定超鏈接URL,控件會(huì )使用顯示的文字字符串作為URL。

Navigation
bool Navigate()

導航到當前超鏈接的URL,該URL或者是由SetHyperLink()函數指定的URL,或者就是控件的窗口文字。

Tooltip management

沒(méi)有公開(kāi)的方法設置工具提示,所以需要直接使用CToolTipCtrl成員m_tip。

下圖顯示的就是ControlMania2對話(huà)框中的超鏈接控件:

在OnInitDialog()函數中設置URL:

    m_wndLink.SetHyperLink ( _T("http://www.codeproject.com/") );
對話(huà)框中控件的UI Updating

對話(huà)框中的的UI updating控制比MFC中簡(jiǎn)單得多,在MFC中,你需要響應未公開(kāi)的WM_KICKIDLE消息,處理這個(gè)消息并觸發(fā)控件的updating,在WTL中,沒(méi)有這個(gè)詭計,不過(guò)向導存在一個(gè)BUG,需要手工添加一行代碼解決這個(gè)問(wèn)題。

首先需要記住的是對話(huà)框必須是無(wú)模式的,因為CUpdateUI需要在程序的消息循環(huán)控制下工作。如果對話(huà)框是模式的,系統處理消息循環(huán),我們程序的空閑處理函數就不會(huì )被調用,由于CUpdateUI是在空閑時(shí)間工作的,所以沒(méi)有空閑處理就沒(méi)有UI updating。

ControlMania2的對話(huà)框是非模式的,類(lèi)定義的開(kāi)始部分很像是一個(gè)框架窗口類(lèi):

class CMainDlg : public CDialogImpl<CMainDlg>, public CUpdateUI<CMainDlg>,                 public CMessageFilter, public CIdleHandler{public:    enum { IDD = IDD_MAINDLG };     virtual BOOL PreTranslateMessage(MSG* pMsg);    virtual BOOL OnIdle();     BEGIN_MSG_MAP_EX(CMainDlg)        MSG_WM_INITDIALOG(OnInitDialog)        COMMAND_ID_HANDLER_EX(IDOK, OnOK)        COMMAND_ID_HANDLER_EX(IDCANCEL, OnCancel)        COMMAND_ID_HANDLER_EX(IDC_ALYSON_BTN, OnAlysonODBtn)    END_MSG_MAP()     BEGIN_UPDATE_UI_MAP(CMainDlg)    END_UPDATE_UI_MAP()//...};

注意CMainDlg類(lèi)從CUpdateUI派生并含有一個(gè)update UI鏈。OnInitDialog()做了這些工作,這和前面介紹的框架窗口中的代碼很相似:

    // register object for message filtering and idle updates    CMessageLoop* pLoop = _Module.GetMessageLoop();    ATLASSERT(pLoop != NULL);    pLoop->AddMessageFilter(this);    pLoop->AddIdleHandler(this);     UIAddChildWindowContainer(m_hWnd);

只是這次我們不是調用UIAddToolbar()或UIAddStatusBar(),而是調用UIAddChildWindowContainer(),它告訴CUpdateUI我們的對話(huà)框含有需要updating的字窗口,只要看看OnIdle(),你會(huì )懷疑少了寫(xiě)什么:

BOOL CMainDlg::OnIdle(){    return FALSE;}

你可能猜想這里應該調用另一個(gè)CUpdateUI的方法做一些實(shí)在的updating工作,你是對的,應該是這樣的,向導在OnIdle()中漏掉了一行代碼,現在加上:

BOOL CMainDlg::OnIdle(){    UIUpdateChildWindows();    return FALSE;}

為了演示UI updating,我們設定鼠標點(diǎn)擊左邊的位圖按鈕,使得右邊的按鈕變得可用或禁用。先在update UI鏈中添加一個(gè)消息入口,使用UPDUI_CHILDWINDOW標志表示此入口是子窗口類(lèi)型:

    BEGIN_UPDATE_UI_MAP(CMainDlg)        UPDATE_ELEMENT(IDC_ALYSON_BMPBTN, UPDUI_CHILDWINDOW)    END_UPDATE_UI_MAP()

在左邊的按鈕的單擊事件處理中,我們調用UIEnable()來(lái)翻轉另一個(gè)按鈕的使能狀態(tài):

void CMainDlg::OnAlysonODBtn ( UINT uCode, int nID, HWND hwndCtrl ){static bool s_bBtnEnabled = true;    s_bBtnEnabled = !s_bBtnEnabled;    UIEnable ( IDC_ALYSON_BMPBTN, s_bBtnEnabled );}
DDV

WTL的對話(huà)框數據驗證(DDV)比MFC簡(jiǎn)單一些,在MFC中你需要分別使用DDX(對話(huà)框數據交換)宏和DDV(對話(huà)框數據驗證)宏,在WTL中只需一個(gè)宏就可以了,WTL包含基本的數據驗證支持,在DDV鏈中可以使用三個(gè)宏:

DDX_TEXT_LEN
和DDX_TEXT一樣,只是還要驗證字符串的長(cháng)度(不包含結尾的空字符)小于或等于限制長(cháng)度。
DDX_INT_RANGE and DDX_UINT_RANGE
和DDX_INT,DDX_UINT一樣,還加了對數字的最大最小值的驗證。
DDX_FLOAT_RANGE
除了像DDX_FLOAT一樣完成數據交換之外,還驗證數字的最大最小值。

ControlMania2有一個(gè)ID是IDC_FAV_SEASON的edit box,它和成員變量m_nSeason相關(guān)聯(lián)。

由于有效的值是1到7,所以使用這樣的數據驗證宏:

    BEGIN_DDX_MAP(CMainDlg)    //...        DDX_INT_RANGE(IDC_FAV_SEASON, m_nSeason, 1, 7)    END_DDX_MAP()

OnOK()調用DoDataExchange()獲得season的數值,并驗證是在1到7之間。

處理DDV驗證失敗

如果控件的數據驗證失敗,CWinDataExchange會(huì )調用重載函數OnDataValidateError(),默認到處理是驅動(dòng)PC喇叭發(fā)出聲音,你可能想給出更友好的錯誤指示。OnDataValidateError()的函數原型是:

void OnDataValidateError ( UINT nCtrlID, BOOL bSave, _XData& data );

_XData是一個(gè)WTL的內部數據結構,CWinDataExchange根據輸入的數據和允許的數據范圍填充這個(gè)數據結構。下面是這個(gè)數據結構的定義:

struct _XData{    _XDataType nDataType;    union    {        _XTextData textData;        _XIntData intData;        _XFloatData floatData;    };};

nDataType指示聯(lián)合中的三個(gè)成員那個(gè)是有意義的,nDataType 的取值可以是:

enum _XDataType{    ddxDataNull = 0,    ddxDataText = 1,    ddxDataInt = 2,    ddxDataFloat = 3,    ddxDataDouble = 4};

在我們的例子中,nDataType的值是ddxDataInt,這表示_XData中的_XIntData成員是有效的,_XIntData是個(gè)簡(jiǎn)單的數據結構:

struct _XIntData{    long nVal;    long nMin;    long nMax;};

我們重載OnDataValidateError()函數,顯示錯誤信息并告訴用戶(hù)允許的數值范圍:

void CMainDlg::OnDataValidateError ( UINT nCtrlID, BOOL bSave, _XData& data ){CString sMsg;     sMsg.Format ( _T("Enter a number between %d and %d"),                  data.intData.nMin, data.intData.nMax );     MessageBox ( sMsg, _T("ControlMania2"), MB_ICONEXCLAMATION );     ::SetFocus ( GetDlgItem(nCtrlID) );}

_XData中的另外兩個(gè)結構_XTextData和_XFloatData的定義在atlddx.h中,感興趣的話(huà)可以打開(kāi)這個(gè)文件查看一下。

改變對話(huà)框的大小

WTL引起我的注意的第一件事是對可調整大小對話(huà)框的內建的支持。在這之前我曾寫(xiě)過(guò)一篇關(guān)于這個(gè)主題的文章,詳情請參考這篇文章。簡(jiǎn)單的說(shuō)就是將CDialogResize類(lèi)添加到對話(huà)框的集成列表,在OnInitDialog()中調用DlgResize_Init(),然后將消息鏈入CDialogResize。

繼續

下一章,我將介紹如何在對話(huà)框中使用ActiveX控件和如何處理控件觸發(fā)的事件。

參考

Using WTL‘‘s Built-in Dialog Resizing Class - Michael Dunn

Using DDX and DDV with WTL - Less Wright

修改記錄

2003年4月28日,本文第一次發(fā)表。



 
本站僅提供存儲服務(wù),所有內容均由用戶(hù)發(fā)布,如發(fā)現有害或侵權內容,請點(diǎn)擊舉報。
打開(kāi)APP,閱讀全文并永久保存 查看更多類(lèi)似文章
猜你喜歡
類(lèi)似文章
MiniGUI學(xué)習筆記
WTL自畫(huà)按鈕的實(shí)現
自繪按鈕補遺
MFC控件使用大全
【mfc】03 基本對話(huà)框程序——加法器
技法:對你的應用添加鍵盤(pán)加速鍵
更多類(lèi)似文章 >>
生活服務(wù)
分享 收藏 導長(cháng)圖 關(guān)注 下載文章
綁定賬號成功
后續可登錄賬號暢享VIP特權!
如果VIP功能使用有故障,
可點(diǎn)擊這里聯(lián)系客服!

聯(lián)系客服

欧美性猛交XXXX免费看蜜桃,成人网18免费韩国,亚洲国产成人精品区综合,欧美日韩一区二区三区高清不卡,亚洲综合一区二区精品久久