1. <nobr id="easjo"><address id="easjo"></address></nobr>

      <track id="easjo"><source id="easjo"></source></track>
      1. 
        

      2. <bdo id="easjo"><optgroup id="easjo"></optgroup></bdo>
      3. <track id="easjo"><source id="easjo"><em id="easjo"></em></source></track><option id="easjo"><span id="easjo"><em id="easjo"></em></span></option>
          貴州做網站公司
          貴州做網站公司~專業!靠譜!
          10年網站模板開發經驗,熟悉國內外開源網站程序,包括DEDECMS,WordPress,ZBlog,Discuz! 等網站程序,可為您提供網站建設,網站克隆,仿站,網頁設計,網站制作,網站推廣優化等服務。我們專注高端營銷型網站,企業官網,集團官網,自適應網站,手機網站,網絡營銷,網站優化,網站服務器環境搭建以及托管運維等。為客戶提供一站式網站解決方案?。?!

          MFC 最詳細入門教程

          來源:互聯網轉載 時間:2023-09-06 05:59:23

          ?

          From:https://blog.csdn.net/wang18323834864/article/details/78621633/

          Visual Studio 2019:https://visualstudio.microsoft.com/zh-hans/

          ?

          雞啄米?-----?VS2010/MFC編程入門教程之目錄和總結:http://www.jizhuomi.com/software/257.html

          ??????一、VS2010/MFC編程入門教程之目錄

          ???????第一部分:VS2010/MFC開發環境

          ???????VS2010/MFC編程入門之前言
          ???????VS2010/MFC編程入門之一(VS2010與MSDN安裝過程圖解)

          ???????第二部分:VS2010/MFC應用程序框架

          ???????VS2010/MFC編程入門之二(利用MFC向導生成單文檔應用程序框架)
          ???????VS2010/MFC編程入門之三(VS2010應用程序工程中文件的組成結構)
          ???????VS2010/MFC編程入門之四(MFC應用程序框架分析)
          ???????VS2010/MFC編程入門之五(MFC消息映射機制概述)

          ???????第三部分:對話框

          ???????VS2010/MFC編程入門之六(對話框:創建對話框模板和修改對話框屬性)
          ????? ?VS2010/MFC編程入門之七(對話框:為對話框添加控件)
          ???????VS2010/MFC編程入門之八(對話框:創建對話框類和添加控件變量)
          ???????VS2010/MFC編程入門之九(對話框:為控件添加消息處理函數)
          ???????VS2010/MFC編程入門之十(對話框:設置對話框控件的Tab順序)
          ???????VS2010/MFC編程入門之十一(對話框:模態對話框及其彈出過程)
          ???????VS2010/MFC編程入門之十二(對話框:非模態對話框的創建及顯示)
          ???????VS2010/MFC編程入門之十三(對話框:屬性頁對話框及相關類的介紹)
          ???????VS2010/MFC編程入門之十四(對話框:向導對話框的創建及顯示)
          ???????VS2010/MFC編程入門之十五(對話框:一般屬性頁對話框的創建及顯示)
          ???????VS2010/MFC編程入門之十六(對話框:消息對話框)
          ???????VS2010/MFC編程入門之十七(對話框:文件對話框)
          ???????VS2010/MFC編程入門之十八(對話框:字體對話框)
          ???????VS2010/MFC編程入門之十九(對話框:顏色對話框)

          ???????第四部分:常用控件

          ???????VS2010/MFC編程入門之二十(常用控件:靜態文本框)
          ???????VS2010/MFC編程入門之二十一(常用控件:編輯框Edit Control)
          ???????VS2010/MFC編程入門之二十二(常用控件:按鈕控件Button、Radio Button和Check Box)
          ???????VS2010/MFC編程入門之二十三(常用控件:按鈕控件的編程實例)
          ???????VS2010/MFC編程入門之二十四(常用控件:列表框控件ListBox)
          ???????VS2010/MFC編程入門之二十五(常用控件:組合框控件Combo Box)
          ???????VS2010/MFC編程入門之二十六(常用控件:滾動條控件Scroll Bar)
          ???????VS2010/MFC編程入門之二十七(常用控件:圖片控件Picture Control)
          ???????VS2010/MFC編程入門之二十八(常用控件:列表視圖控件List Control 上)
          ???????VS2010/MFC編程入門之二十九(常用控件:列表視圖控件List Control 下)
          ???????VS2010/MFC編程入門之三十(常用控件:樹形控件Tree Control 上)
          ???????VS2010/MFC編程入門之三十一(常用控件:樹形控件Tree Control 下)
          ???????VS2010/MFC編程入門之三十二(常用控件:標簽控件Tab Control 上)
          ???????VS2010/MFC編程入門之三十三(常用控件:標簽控件Tab Control 下)

          ???????第五部分:菜單、工具欄與狀態欄

          ???????VS2010/MFC編程入門之三十四(菜單:VS2010菜單資源詳解)
          ???????VS2010/MFC編程入門之三十五(菜單:菜單及CMenu類的使用)
          ???????VS2010/MFC編程入門之三十六(工具欄:工具欄資源及CToolBar類)
          ???????VS2010/MFC編程入門之三十七(工具欄:工具欄的創建、??颗c使用)
          ???????VS2010/MFC編程入門之三十八(狀態欄的使用詳解)

          ???????第六部分:文檔、視圖和框架

          ???????VS2010/MFC編程入門之三十九(文檔、視圖和框架:概述)
          ???????VS2010/MFC編程入門之四十(文檔、視圖和框架:各對象之間的關系)
          ???????VS2010/MFC編程入門之四十一(文檔、視圖和框架:分割窗口)

          ???????第七部分:MFC常用類

          ???????VS2010/MFC編程入門之四十二(MFC常用類:CString類)
          ???????VS2010/MFC編程入門之四十三(MFC常用類:CTime類和CTimeSpan類)
          ???????VS2010/MFC編程入門之四十四(MFC常用類:定時器Timer)
          ???????VS2010/MFC編程入門之四十五(MFC常用類:CFile文件操作類)
          ???????VS2010/MFC編程入門之四十六(MFC常用類:MFC異常處理)

          ???????第八部分:字體和文本輸出

          ???????VS2010/MFC編程入門之四十七(字體和文本輸出:CFont字體類)
          ???????VS2010/MFC編程入門之四十八(字體和文本輸出:文本輸出)

          ???????第九部分:圖形圖像

          ???????VS2010/MFC編程入門之四十九(圖形圖像:CDC類及其屏幕繪圖函數)
          ???????VS2010/MFC編程入門之五十(圖形圖像:GDI對象之畫筆CPen)
          ???????VS2010/MFC編程入門之五十一(圖形圖像:GDI對象之畫刷CBrush)

          ???????第十部分:Ribbon界面開發

          ???????VS2010/MFC編程入門之五十二(Ribbon界面開發:創建Ribbon樣式的應用程序框架)
          ???????VS2010/MFC編程入門之五十三(Ribbon界面開發:為Ribbon Bar添加控件)
          ???????VS2010/MFC編程入門之五十四(Ribbon界面開發:使用更多控件并為控件添加消息處理函數)

          ?

          ?

          文中截圖都是基于VS2019?

          ?

          ?

          1. 新建?MFC?項目

          ?

          • 1. 選擇菜單項? 文件->新建->項目,彈出 “新項目” 對話框。
          • 2. 選擇 MFC,點擊下一步,然后鍵入工程名稱,本例取名“Addition”,在設置工程的保存路徑。點“創建”。
          • 3.?在應用程序類型下拉框選擇?基于對話框,其他使用默認設置,點 “完成”。

          解決方案視圖 中看到,此工程的文件要比單文檔應用程序少的多,在 Class View 中主要有三個類:CAboutDlg、CAdditionAppCAdditionDlg?。

        1. CAboutDlg 是應用程序的 “關于” 對話框類,
        2. CAdditionApp 是由 CWinApp 派生的類,
        3. CAdditionDlg?是主對話框類,主對話框也就是此應用程序運行后顯示的主要界面。
        4. ?

          打開資源視圖

          在Resource View視圖中可以看到工程 Addition 的資源樹,展開Addition.rc,下面有四個子項:Dialog(對話框)、Icon(圖標)、String Table(字符串表)和Version(版本)。然后展開Dialog項,下面有兩個對話框模板,其ID分別為:IDD_ABOUTBOX和IDD_ADDITION_DIALOG,前者是“關于”對話框的模板,后者是主對話框的模板。ID是資源的唯一標識,本質上是一個無符號整數,一般ID代表的整數值由系統定義,我們無需干涉。

          可見對于主對話框來說,創建對話框第一步中的創建新的對話框模板已經由系統自動完成了。如果需要再添加創建新的對話框模板時,需要在Resource View 的“Dialog”節點上點右鍵,在右鍵菜單中選擇“Insert Dialog”,就會生成新的對話框模板,并且會自動分配ID。如圖:

          在Addition對話框模板上點右鍵,然后在右鍵菜單中選擇Properties,則在右側面板中會顯示對話框的屬性列表。如下圖:

          說明:

          • 1. ID? ? ? ? ?:對話框ID,唯一標識對話框資源,可以修改。此處為IDD_ADDITION_DIALOG,我們不修改它。
          • 2. Caption:對話框標題。此處默認為?空,我們將其修改為 “加法計算器” 。
          • 3. Border? :邊框類型。有四種類型:None、Thin、Resizing和Dialog Frame。我們使用默認的Dialog Frame。
          • 4. Maximize :是否使用最大化按鈕。我們使用默認的False。
          • 5. Minimize? :是否使用最小化按鈕。同樣我們使用默認的False。
          • 6. Style? ? ? ? :對話框類型。有三種類型:Overlapped(重疊窗口)、Popup(彈出式窗口)和Child(子窗口)。彈出式窗口比較常見。我們使用默認的Popup類型。
          • 7. System Menu:是否帶有標題欄左上角的系統菜單,包括移動、關閉等菜單項。我們使用默認的True。
          • 8.Title Bar? ? :是否帶有標題欄。我們使用默認的True。
          • 9.Font(Size) :字體類型和字體大小。如果將其修改為非系統字體,則Use System自動改為False。而如果Use System原來為False,將其修改為True,則Font(Size)自動設置為系統字體。這里我們使用默認的系統字體。

          修改了標題屬性。這時我們運行此程序后的界面如下:

          ?

          1.為對話框添加一個靜態文本框(Static Text),用于顯示字符串--“被加數”。

          對于自動添加的一個標題為“TODO:Place dialog controls here.”的靜態文本框,這里將它刪掉,繼續添加新的靜態文本框。
          刪除控件時,可以使用鼠標左鍵點擊選中它,選中后控件的周圍會出現虛線框,然后按Delete鍵就可以將其刪除了。在“Addition”工程的Resource View中打開上一講中創建的對話框模板IDD_ADDITION_DIALOG,自動添加的靜態文本框就可以使用這種方法刪除。
          在添加新的靜態文本框以前,先看看Toolbox視圖是否顯示了,如果沒有顯示,在菜單欄上點擊 View->Toolbox 即可。Toolbox視圖如下圖:

          ? ? ? ? Toolbox工具箱) 中列出了一些常用控件,其中有一個是 Static Text,即是我們要添加的控件。在 Toolbox 中的 Static Text 上點下鼠標左鍵不放開,并拖到 IDD_ADDITION_DIALOG 對話框模板上,模板上會出現一個虛線框,我們找到合適的位置松開鼠標左鍵放下它。

          ?????? 用鼠標左鍵選中控件后周圍出現虛線框,然后鼠標移到虛線框上幾個黑點的位置會變成雙向箭頭的形狀,此時就可以按下鼠標左鍵并拖動來改變控件大小了。我們可以這樣改變新添加的靜態文本框控件的大小,以更好的顯示標題。當然,整個對話框模板也可以用這種方法改變大小。

          ?????? 接下來就該修改靜態文本框的文字了。鼠標右鍵點擊靜態文本框,在右鍵菜單中選擇 “Properties”,Properties 面板就會顯示出來,在面板上修改 Caption 屬性為 “被加數”,ID 修改為 IDC_SUMMAND_STATIC。此時模板如下圖:

          ?

          2.為對話框添加一個編輯框(Edit Control),用來輸入被加數。

          添加編輯框的過程與靜態文本框類似,在Toolbox中選中Edit Control控件拖到對話框模板上,并使其與之前的靜態文本框水平對齊(為了美觀),然后調整其大小使之適合被加數的輸入。
          在編輯框上點右鍵,仍然在右鍵菜單中選擇“Properties”顯示出屬性(Properties)面板,修改其ID為IDC_SUMMAND_EDIT。此時模板如下圖:

          3. 按照1的方法添加一個標題為“加數”的靜態文本框,用于顯示字符串--“加數”。并將其ID改為IDC_ADDEND_STATIC。
          4. 按照2的方法添加一個ID為IDC_ADDEND_EDIT的編輯框,用來輸入加數。
          5. 按照1的方法添加一個標題為“和”的靜態文本框,用于顯示文字--“和”。并修改其ID為IDC_SUM_STATIC。
          6. 按照2的方法添加一個ID為IDC_SUM_EDIT的編輯框,用來顯示最終的加和。
          7. 類似的添加按鈕(Button)控件到對話框模板,用于在被點擊后觸發加法計算。修改其標題為“計算”,ID為IDC_ADD_BUTTON。

          到此,對話框模板如圖:

          8.刪除?確定?按鈕。打開?取消?按鈕的屬性面板,將標題改為 “退出”,并使其與“計算”按鈕水平對齊。
          9.根據控件的布局,適當調整整個對話框模板的大小,使其相對控件布局來說大小合適,界面美觀。
          這樣在對話框模板中就把我們在本例中需要用到的控件就添加完了。最終效果如下:

          運行截圖:

          ?

          ?

          創建對話框類

          因為?程序Addition 是基于對話框的程序,所以程序自動創建了對話框模板 IDD_ADDITION_DIALOG,并自動生成了對話框類CAdditionDlg,它是從 CDialogEx 類派生的。大家用過VC++ 6.0的可能記得,我們定義的對話框類都是從CDialog類派生的,但在VS2010中,一般對話框類都是繼承自CDialogEx類。

          如果是自己新添加的對話框模板,怎樣為它創建對話框類呢?

          • 1. 在Resource View的“Dialog”節點上右鍵,然后在右鍵菜單中選擇“Insert Dialog”創建一個新的對話框模板,ID就使用默認的 IDD_DIALOG1 。
          • 2. 在中間區域會顯示新建的對話框模板,然后選中此對話框模板,點右鍵,在右鍵菜單中選擇 Add Class。

          3.選擇“Add Class”后會彈出一個對話框,在對話框中“Class name”下的編輯框中寫入自定義的類名就可以了,例如CMyDialog。
          4.最后點“Finish”完成。

          最終你就可以在Class View中看到新生成的對話框類CMyDialog了,并且在Solution Explorer中有相應的MyDialog.h頭文件和MyDialog.cpp源文件生成。CMyDialog類同樣派生于CDialogEx類。
          注意,一般類名都以C打頭,又比如,CTestDlg。

          ?

          ?

          為對話框中的控件添加變量

          ? ? ? ? 上面步驟中?為對話框添加了幾個控件,包括三個靜態文本框,三個編輯框,一個按鈕控件。程序自動生成的?取消?按鈕保留,作為退出按鈕,而?確定?按鈕刪除掉了。

          ?????? 靜態文本框只是為了說明后面緊跟的編輯框中數據的意義,是被加數、加數還是和,所以它們是不會變的,我們就不為它們添加變量了。按鈕控件是用來操作的,這里也不為它們添加變量。編輯框中的數據可能會經常變化,有必要為它們每個控件關聯一個變量。

          ?

          首先為被加數的編輯框 IDC_SUMMAND_EDIT 添加變量。

          • 1. 在編輯框上點右鍵,在右鍵菜單中選擇“Add Variable”。彈出添加成員變量的向導對話框。
          • 2 .我們想為其添加值變量而不是控件變量,所以對話框中“Category”下的組合框中選擇Value。
          • 3. “Variable type”下的組合框此時默認選中的是“CString”,CString是字符串類,顯然不能進行加法運算。我們可以選擇double、float、int等。這里我們選擇double,即編輯框關聯一個double類型的變量。
          • 4. 在“Variable name”中寫入自定義的變量名。雞啄米為其取名m_editSummand。

          5.點“Finish”完成。

          注意,類的成員變量名一般以m_打頭,以標識它是一個成員變量。

          參照此方法,再分別為加數的編輯框IDD_ADDEND_EDIT添加double型變量m_editAddend、和的編輯框IDD_SUM_EDIT添加double型變量m_editSum。

          ?

          對話框類的數據交換和檢驗

          ?????? 在程序運行界面中,用戶往往會改變控件的屬性,例如,在編輯框中輸入字符串,或者改變組合框的選中項,又或者改變復選框的選中狀態等??丶膶傩愿淖兒驧FC會相應修改控件關聯變量的值。這種同步的改變是通過MFC為對話框類自動生成的成員函數DoDataExchange()來實現的,這也叫做對話框的數據交換和檢驗機制。

          ???????我們為三個編輯框添加了變量以后,在AdditionDlg.cpp 中 CAdditionDlg 的 DoDataExchange()函數的函數體中多了三條DDX_Text調用語句。下面是函數體代碼和雞啄米添加的注釋。

          ? ? ? ?再以 Addition 程序為例簡單說下數據交換機制。如果我們在程序運行界面中輸入被加數,則通過CAddition的DoDataExchange()函數可以將輸入的值保存到 m_editSummand 變量中,反之如果程序運行中修改了變量 m_editSummand 的值,則通過 CAddition 的 DoDataExchange() 函數也可以將新的變量值顯示到被加數的編輯框中。

          ?????? 但是這種數據交換機制中,DoDataExchange() 并不是被自動調用的,而是需要我們在程序中調用 CDialogEx::UpdateData()函數,由 UpdateData() 函數再去自動調用 DoDataExchange()的。

          ?????? CDialogEx::UpdateData() 函數的原型為:BOOL UpdateData(BOOL bSaveAndValidate = TRUE);

          ?????? 參數:bSaveAndValidate 用于指示數據傳輸的方向,TRUE 表示從 控件 傳給 變量FALSE 表示從 變量 傳給 控件。默認值是 TRUE,即從 控件 傳給 變量。

          ?????? 返回值:CDialogEx::UpdateData()函數的返回值表示操作是否成功,成功則返回TRUE,否則返回FALSE。

          ?????? 在下一講中將具體演示CDialogEx::UpdateData()函數如何使用。

          ?????? 雞啄米本節主要講的是新建對話框類和添加控件變量,控件的消息處理函數將在下一講詳細介紹。

          ?

          ?

          為控件添加消息處理函數。

          ?創建對話框類和添加控件變量在上面已經講過,這一講的主要內容是如何為控件添加消息處理函數。

          ?

          ???????MFC為對話框和控件等定義了諸多消息,我們對它們操作時會觸發消息,這些消息最終由消息處理函數處理。比如我們點擊按鈕時就會產生 BN_CLICKED 消息,修改編輯框內容時會產生 EN_CHANGE消息等。一般為了讓某種操作達到效果,我們只需要實現某個消息的消息處理函數。

          ?

          一.添加消息處理函數

          ?????? 雞啄米仍以前面的加法計算器的程序為例,說明怎樣為“計算”按鈕控件添加消息處理函數。添加方法列出4種:

          ???????

          • 1. 使用 Class Wizard 添加消息處理函數

          ???????用過的VC++?6.0的朋友應該對Class Wizard很熟悉了,添加類、消息處理函數等經常會用到它,可以說是一個很核心的功能。但從VS2002開始就見不到Class Wizard了,大部分功能都集成到對話框和控件等的屬性中了,使用很方便。到VS2010,久違的Class Wizard又回來了。但雞啄米已經習慣了使用屬性中的功能了,對于從VC++ 6.0直接轉VS2010的朋友可能覺得還是使用Class Wizard比較習慣。

          ?????? 大家應該記得,“計算” 按鈕的 ID 為 IDC_ADD_BUTTON,上圖中?命令 標簽下,對象 ID 列表中有此 ID,因為我們是想實現點擊按鈕后的消息處理函數,所以在?消息 列表中選擇 BN_CLICKED 消息,然后點右上方的?添加處理程序 就可以添加BN_CLICKED 消息處理函數 OnClickedAddButton 了。當然你也可以改名,但一般用的默認的就可以。

          ?

          • 2. 通過 “Add Event Handler...” 添加消息處理函數

          ???????在 “計算” 按鈕上點右鍵,然后在右鍵菜單中選擇菜單項“Add Event Handler...”,彈出 “Event Handler Wizard” 對話框,如下圖:

          可見 “消息類型” 中默認選中的就是 BN_CLICKED 消息,函數名 所在 類 都已經自動給出,直接點 “確定” 就可以了。

          ?

          • ??3.在按鈕的 屬性視圖 中 添加 消息處理函數

          ???????上面說過,從VS2002開始就主要從 屬性視圖 添加 消息處理函數了。我們在 “計算” 按鈕上點右鍵,在右鍵菜單中選擇“Properties”,右側面板中會顯示按鈕的屬性視圖。

          ???????我們可以像上圖中那樣,點屬性視圖的 “控制事件” 按鈕(類似 閃電標志),下面列出了 “計算” 按鈕的所有消息。我們要處理的是 BN_CLICKED 消息,點其右側空白列表項,會出現一個帶下箭頭的按鈕,再點此按鈕會出現 “<Add> OnBnClickedAddButton” 選項,最后選中這個選項就會自動添加 BN_CLICKED 處理函數了。

          ?

          • ?4. 雙擊按鈕添加消息處理函數

          ?????? 最直接最簡單的方法就是,雙擊 “計算” 按鈕,MFC會自動為其在CAdditionDlg類中添加 BN_CLICKED 消息的處理函數OnBnClickedAddButton()。

          ?

          ?

          在消息處理函數中添加自定義功能

          ?????? 在我們使用任意一種方法添加了消息處理函數以后,都只能得到一個空的OnBnClickedAddButton()函數的函數體,要實現我們想要的功能,還需要在函數體中加入自定義功能代碼。

          ???????在加法計算器程序中,我們想要“計算”按鈕實現的功能是,獲取被加數和加數的數值,然后計算它們的和并顯示到和的編輯框里。那么,OnBnClickedAddButton()的函數體就應修改為:

          void CAdditionDlg::OnClickedAddButton() {// TODO: 在此添加控件通知處理程序代碼// 將各控件中的數據保存到相應的變量 UpdateData(TRUE);// 將被加數和加數的加和賦值給m_editSum m_editSum = m_editSummand + m_editAddend;// 根據各變量的值更新相應的控件。和的編輯框會顯示m_editSum的值 UpdateData(FALSE); }

          ? ? ? ? 上面的代碼中已經添加注釋,大家應該很容易理解了。對于UpdateData()函數的說明在上一講中已經介紹過,如果忘了可以再回上一講了解了解。接下來我們運行下此應用程序。在運行結果界面中,輸入被加數 1.1,加數 2.2?,然后點“計算”:

          簡單分析下運行過程:輸入被加數和加數,點“計算”按鈕后產生點擊消息,從而調用 OnBnClickedAddButton()函數。進入此函數后,首先由 UpdateData(TRUE)函數將被加數的值5.1和加數的值2.3分別保存到變量m_editSummand和m_editAddend,然后通過語句m_editSum?=?m_editSummand?+?m_editAddend;計算出被加數和加數的和為7.4,并把7.4賦值給m_editSum。最后調用UpdateData(FALSE) 根據被加數、加數、和的值更新三個編輯框的顯示值,就得到了上圖中的結果。

          ?????? 到此,一個具有簡單的加法運算功能的加法計算器應用程序就基本完成了。

          ?

          ?

          對話框上控件的Tab順序如何調整。

          上一講為“計算”按鈕添加了消息處理函數后,加法計算器已經能夠進行浮點數的加法運算。但是還有個遺留的小問題,就是對話框控件的Tab順序問題。

          ?????? 運行加法計算器程序,顯示對話框后不進行任何操作,直接按回車,可以看到對話框退出了。這是因為“退出”按鈕是Tab順序為1的控件,也就是第一個接受用戶輸入的控件。但是按照我們的輸入習慣,應該是被加數的編輯框首先接受用戶輸入,然后是加數編輯框,再接下來是“計算”按鈕,最后才是“退出”按鈕。

          ?????? 先直觀的看看各個控件的Tab順序:打開 “資源視圖” ,然后在資源中找到對話框 IDD_ADDITION_DIALOG,雙擊ID后中間客戶區域出現其模板視圖。在主菜單中選擇 “Format”->"Tab Order",或者按快捷鍵Ctrl+D,對話框模板上就會顯示各個控件的Tab順序數字。如下圖:

          ?????? 上圖中每個控件左上角都有一個數字,這就是它的 Tab 響應順序。對話框剛打開時輸入焦點就在Tab順序為1的“退出”按鈕上,不做任何操作按下Tab鍵,輸入焦點就會轉移到Tab順序為2的“被加數”靜態文本框上,但是因為靜態文本框不接受任何輸入,所以輸入焦點繼續自動轉移到Tab順序為3的被加數編輯框,再按Tab鍵,輸入焦點又會轉移到Tab順序為4的“加數”靜態文本框上,同樣由于它是靜態文本框,輸入焦點不停留繼續轉移到加數編輯框,后面的控件同理。

          ?????? 我們認為這個順序不合理,那怎么修改呢?很簡單,從自己認為Tab順序應該為1的控件開始依次單擊,隨著單擊的完成,各控件的Tab響應順序也按我們的想法設置好了。

          ?????? 例如,此例中我們可以依次單擊被加數編輯框、“被加數”靜態文本框、加數編輯框、“加數”靜態文本框、和編輯框、“和”靜態文本框、“計算”按鈕和“退出”按鈕。設置完后如下圖:

          最后按ESC鍵,確認設置并退出對話框模板的Tab順序設置狀態。

          ?????? 現在我們再運行程序,可以看到對話框打開后最初的輸入焦點在被加數編輯框上,然后我們按Tab鍵,輸入焦點移到加數編輯框上,繼續多次按Tab鍵時,輸入焦點會按“和編輯框--‘計算’按鈕--‘退出’按鈕--被加數編輯框--加數編輯框--和編輯框......”的順序循環轉移。這樣就達到了我們的目的。

          ?

          ?

          模態對話框 和 非模態對話框,以及模態對話框怎樣彈出。

          ?

          一 .??模態對話框非模態對話框

          ?????? Windows對話框分為兩類:模態對話框非模態對話框。

        5. ?模態對話框是這樣的對話框:當它彈出后,本應用程序其他窗口將不再接受用戶輸入,只有該對話框響應用戶輸入,在對它進行相應操作退出后,其他窗口才能繼續與用戶交互。
        6. ?非模態對話框:非模態對話框是它彈出后,本程序其他窗口仍能響應用戶輸入。非模態對話框一般用來顯示提示信息等。
        7. ?????? 大家對Windows系統很了解,相信這兩種對話框應該都遇到過。之前的加法計算器對話框其實就是模態對話框。

          ?

          二 .? 模態對話框是怎樣彈出的

          ?????? 畢竟加法計算器程序大部分都是MFC自動生成的,對話框怎么彈出來的大家可能還不是很清楚。雞啄米下面簡單說說它是在哪里彈出來的,再重新建一個新的對話框并彈出它,這樣大家實踐以后就能更靈活的使用模態對話框了。

          ?????? 大家打開 Addition.cpp 文件,可以看到 CAdditionApp 類有個 InitInstance() 函數,在?MFC應用程序框架分析?中提到過此函數,不過那是單文檔應用程序 App類 中的,函數體不太相同,但都是進行App類實例的初始化工作。

          ????? ?InitInstance() 函數的?后半部分有一段代碼就是定義對話框對象并彈出對話框的,雞啄米下面給出這段代碼并加以注釋:

          CAdditionDlg dlg; // 定義對話框類CAdditionDlg的對象dlg m_pMainWnd = &dlg; // 將dlg設為主窗口 INT_PTR nResponse = dlg.DoModal(); // 彈出對話框dlg,并將DoModal函數的返回值(退出時點擊按鈕的ID)賦值給nResponse if (nResponse == IDOK) // 判斷返回值是否為OK按鈕(其ID為IDOK,雞啄米已經將它刪除) {// TODO: 在此放置處理何時用// “確定”來關閉對話框的代碼 } else if (nResponse == IDCANCEL) // 判斷返回值是否為Cancel按鈕(其ID為IDCANCEL,雞啄米將它的Caption改為了“退出”) {// TODO: 在此放置處理何時用// “取消”來關閉對話框的代碼 } else if (nResponse == -1) {TRACE(traceAppMsg, 0, "警告: 對話框創建失敗,應用程序將意外終止。\n");TRACE(traceAppMsg, 0, "警告: 如果您在對話框上使用 MFC 控件,則無法 #define _AFX_NO_MFC_CONTROLS_IN_DIALOGS。\n"); }

          彈出對話框比較關鍵的一個函數,就是對話框類的 DoModal() 函數。CDialog::DoModal() 函數的原型為:

          ???????virtual INT_PTR DoModal();   

          ???????返回值:整數值,指定了傳遞給CDialog::EndDialog(該函數用于關閉對話框)的nResult參數值。如果函數不能創建對話框,則返回-1;如果出現其它錯誤,則返回IDABORT。

          ???????調用了它,對話框就會彈出,返回值是退出對話框時所點的按鈕的 ID,比如,我們點了“退出”按鈕,那么 DoModal 返回值為IDCANCEL。

          ?

          ?三 .? 添加一個新對話框并彈出它

          為加法計算器程序添加一個對話框,在計算之前詢問用戶是否要進行計算。大家可以完整的看下對話框的添加和彈出過程。

          ???????1.在 Resource View 中的 “Dialog” 上點右鍵選擇 “Insert Dialog”,創建一個新的對話框模板,修改其ID為IDD_TIP_DIALOG,Caption改為“提示”,然后參考 “為對話框添加控件” 中所講,在對話框模板上添加一個靜態文本框(static text),Caption改為“您確定要進行加法計算嗎?”,接下來修改OK按鈕的Caption為“確定”,Cancel按鈕的Caption為“取消”,最后調整各個控件的位置和對話框的大小。最終的對話框模板如下圖:

          ???????2.根據“創建對話框類和添加控件變量”中創建對話框類的方法,在對話框模板上點右鍵選擇“Add Class...”,彈出添加類的對話框,設置“Class name”為CTipDlg,點“OK”。在Solution Explorer中可以看到生成了CTipDlg類的頭文件TipDlg.h和源文件TipDlg.cpp。

          ???????3.我們要在點“計算”按鈕之后彈出此提示對話框,那么就要在“計算”按鈕的消息處理函數OnBnClickedAddButton()中訪問提示對話框類,所以為了訪問CTipDlg類,在AdditionDlg.cpp中包含CTipDlg的頭文件:#include "CTipDlg.h"。

          ???????4.修改OnBnClickedAddButton()的函數體,在所有代碼前,構造CTipDlg類的對象tipDlg,并通過語句tipDlg.DoModal();彈出對話框,最后判斷DoModal()函數的返回值是IDOK還是IDCANCEL來確定是否繼續進行計算。OnBnClickedAddButton()函數修改后如下:

          void CAdditionDlg::OnClickedAddButton() {// TODO: Add your control notification handler code here INT_PTR nRes; // 用于保存DoModal函數的返回值 CTipDlg tipDlg; // 構造對話框類CTipDlg的實例 nRes = tipDlg.DoModal(); // 彈出對話框 if (IDCANCEL == nRes) // 判斷對話框退出后返回值是否為IDCANCEL,如果是則return,否則繼續向下執行 return;// 將各控件中的數據保存到相應的變量 UpdateData(TRUE);// 將被加數和加數的加和賦值給m_editSum m_editSum = m_editSummand + m_editAddend;// 根據各變量的值更新相應的控件。和的編輯框會顯示m_editSum的值 UpdateData(FALSE); }

          ???????5.測試。編譯運行程序后,在對話框上輸入被加數和加數,點“計算”,彈出提示對話框詢問是否進行計算,如果選擇“確定”,則提示對話框退出,并在主對話框上顯示被加數和加數的和,而如果選擇“取消”,則提示對話框也會退出,但主對話框顯示的和不變,即沒有進行加法計算。

          ?

          ?

          非模態對話框的創建及顯示。

          ?

          總結:主要步驟是,創建新對話框后,關聯一個類,然后用一個指針指向該類;接著用該指針創建對話框和顯示對話框,最后在虛構函數中銷毀該指針,釋放資源。

          ? ? ? ? 非模態對話框顯示后,程序其他窗口仍能正常運行,可以響應用戶輸入,還可以相互切換。將上一講中創建的Tip模態對話框改為非模態對話框,讓大家看下效果。

          ???????實際上,模態對話框非模態對話框 在創建對話框資源和生成對話框類上是沒有區別的,所以上一講中創建的IDD_TIP_DIALOG對話框資源和 CTipDlg 類都不需要修改。

          ???????需要修改的是,對話框類實例的創建和顯示,也就是之前在 CAdditionDlg::OnBnClickedAddButton() 函數體中添加的對話框顯示代碼。下面是具體步驟:

          • 1. 在 AdditionDlg.h 中包含 CTipDlg 頭文件并定義 CTipDlg類型的指針成員變量。詳細操作方法是,在 AdditionDlg.cpp中刪除之前添加的 #include "CTipDlg.h",而在 AdditionDlg.h 中添加 #include "CTipDlg.h",這是因為我們需要在AdditionDlg.h 中定義 CTipDlg 類型的 指針變量,所以要先包含它的頭文件;然后在 AdditionDlg.h 中為 CAdditionDlg類添加 private 成員變量 CTipDlg? *m_pTipDlg; 。
          • 2. 在CAdditionDlg類的構造函數中初始化成員變量m_pTipDlg。如果cpp文件中函數太多,我們可以在Class View上半個視圖中找到CAdditionDlg類,再在下半個視圖中找到其構造函數雙擊,中間客戶區域即可馬上切到構造函數的實現處。在構造函數體中添加m_pTipDlg = NULL;,這是個好習慣,雞啄米在C++編程入門系列的指針的賦值和指針運算中說到過,在任何指針變量使用前都初始化,可以避免因誤訪問重要內存地址而破壞此地址的數據。
          • 3. 將上一講中添加的模態對話框顯示代碼注釋或刪除掉,添加非模態對話框的創建和顯示代碼。VC++中注釋單行代碼使用“//”,注釋多行代碼可以在需注釋的代碼開始處添加“/*”,結束處添加“*/”。修改后的CAdditionDlg::OnBnClickedAddButton()函數如下:
          void CAdditionDlg::OnClickedAddButton() {// TODO: Add your control notification handler code here /*INT_PTR nRes; // 用于保存DoModal函數的返回值CTipDlg tipDlg; // 構造對話框類CTipDlg的實例nRes = tipDlg.DoModal(); // 彈出對話框if (IDCANCEL == nRes) // 判斷對話框退出后返回值是否為IDCANCEL,如果是則return,否則繼續向下執行return;*/// 如果指針變量m_pTipDlg的值為NULL,則對話框還未創建,需要動態創建 if (NULL == m_pTipDlg){// 創建非模態對話框實例 m_pTipDlg = new CTipDlg();m_pTipDlg->Create(IDD_TIP_DIALOG, this);}// 顯示非模態對話框 m_pTipDlg->ShowWindow(SW_SHOW);// 將各控件中的數據保存到相應的變量 UpdateData(TRUE);// 將被加數和加數的加和賦值給m_editSum m_editSum = m_editSummand + m_editAddend;// 根據各變量的值更新相應的控件。和的編輯框會顯示m_editSum的值 UpdateData(FALSE); }

          ??這樣,非模態對話框創建和顯示的代碼就添加修改完了。讓我們運行下看看效果吧。

          ??????在加法計算器對話框上輸入被加數和加數,然后點“計算”按鈕,依然像上節一樣彈出了提示對話框,但是先不要關閉它,你可以拖動它后面的加法計算器對話框試試,我們發現加法計算器對話框竟然可以拖動了,而且“和”編輯框里已經顯示了運算結果,這表明提示對話框顯示以后還沒有關閉,OnBnClickedAddButton()?就繼續向下執行了,不僅如此,加法計算器的每個編輯框還都可以響應輸入。

          這只是一個簡單的例子,非模態對話框的用處有很多,以后大家在軟件開發中會用到。

          ?

          ?

          屬性頁對話框

          ?

          屬性頁對話框的分類

          屬性頁對話框想必大家并不陌生,XP系統中桌面右鍵點屬性,彈出的就是屬性頁對話框,它通過標簽切換各個頁面。另外,我們在創建MFC工程時使用的向導對話框也屬于屬性頁對話框,它通過點擊“Next”等按鈕來切換頁面。
          屬性頁對話框就是包含一般屬性頁對話框和向導對話框兩類。它將多個對話框集成于一身,通過標簽或按鈕來切換頁面。
          屬性頁對話框相關類

          我們使用屬性頁對話框時,用到的類主要有兩個:CPropertyPage類 和 CPropertySheet 類。

          ?

          ?1.CPropertyPage 類

          ???????CPropertyPage類繼承自CDialog類,它被用于處理某單個的屬性頁,所以要為每個屬性頁都創建一個繼承自CPropertyPage的子類。大家可以在VS2010的MSDN中查找CPropertyPage類以及它的成員的詳細說明。下面雞啄米就為大家講解MSDN中列出的CPropertyPage類的部分主要成員函數。

          (1)構造函數這里講三個CProperty類的構造函數,函數原型為:CPropertyPage( );explicit CPropertyPage(UINT nIDTemplate,UINT nIDCaption = 0,DWORD dwSize = sizeof(PROPSHEETPAGE));explicit CPropertyPage(LPCTSTR lpszTemplateName,UINT nIDCaption = 0,DWORD dwSize = sizeof(PROPSHEETPAGE));第一個是沒有任何參數的構造函數。第二個構造函數中,參數nIDTemplate是屬性頁的對話框資源ID,參數nIDCaption是屬性頁對話框選項卡的標題所用字符串資源的ID,若設為0,則選項卡標題就使用該屬性頁的對話框資源的標題。第三個構造函數中,參數lpszTemplateName為屬性頁的對話框資源的名稱字符串,不能為NULL。參數nIDCaption同上。(2)CancelToClose()函數在模態屬性頁對話框的屬性頁進行了某不可恢復的操作后,使用CancelToClose() 函數將“OK”按鈕改為“Close”按鈕,并禁用“Cancel”按鈕。函數原型為:void CancelToClose( );(3)SetModified()函數調用此函數可激活或禁用“Apply”按鈕,函數原型為:void SetModified(BOOL bChanged = TRUE);(4)可重載函數CPropertyPage類提供了一些消息處理函數,來響應屬性頁對話框的各種消息。我們重載這些消息處理函數,就可以自定義對屬性頁對話框操作的處理??芍剌d的消息處理函數包括:OnApply:處理屬性頁的“Apply”按鈕被單擊的消息OnCancel:處理屬性頁的“Cancel”按鈕被單擊的消息OnKillActive:處理屬性頁當前活動狀態被切換的消息,常用于數據驗證OnOK:處理屬性頁的“OK”按鈕、“Apply”按鈕或者“Close”按鈕被單擊的消息OnQueryCancel:處理屬性頁的“Cancel”按鈕被單擊前發出的消息OnReset:處理屬性頁的“Reset”按鈕被單擊的消息OnSetActive:處理屬性頁被切換為當前活動頁的消息OnWizardBack:處理屬性頁的“Back”按鈕被單擊的消息,僅在向導對話框中有效OnWizardFinish:處理屬性頁的“Finish”按鈕被單擊的消息,僅在向導對話框中有效OnWizardNext:處理屬性頁的“Next”按鈕被單擊的消息,僅在向導對話框中有效

          ?

          2.CPropertySheet類

          ???????CPropertySheet類繼承自CWnd類,它是屬性表類,負責加載、打開或刪除屬性頁,并可以在屬性頁對話框中切換屬性頁。它跟對話框類似,也有模態和非模態兩種。下面雞啄米就講解CPropertySheet類的部分成員函數。

          (1)構造函數這里依然列出CPropertySheet類的三個構造函數:CPropertySheet( );explicit CPropertySheet(UINT nIDCaption,CWnd* pParentWnd = NULL,UINT iSelectPage = 0?);explicit CPropertySheet(LPCTSTR pszCaption,CWnd* pParentWnd = NULL,UINT iSelectPage = 0?);參數 nIDCaption:標題的字符串資源的ID。參數 pParentWnd:屬性頁對話框的父窗口,若設為NULL,則父窗口為應用程序的主窗口。參數 iSelectPage:初始狀態時,活動屬性頁的索引,默認為第一個添加到屬性表的屬性頁。參數 pszCaption:標題字符串。(2)GetActiveIndex()函數獲取當前活動屬性頁的索引。函數原型為:int GetActiveIndex( ) const;返回值:當前活動屬性頁的索引。(3)GetActivePage()函數獲取當前活動屬性頁對象。函數原型為:CPropertyPage* GetActivePage( ) const;返回值:當前活動屬性頁對象的指針。(4)GetPage()函數獲取某個屬性頁對象。函數原型為:CPropertyPage* GetPage(int nPage) const;參數nPage:目標屬性頁的索引。返回值:目標屬性頁對象的指針。(5)GetPageCount()函數獲取屬性頁的數量。函數原型為:int GetPageCount( ) const;返回值:屬性頁的數量。(6)GetPageIndex()函數獲取某屬性頁在屬性頁對話框中的索引。函數原型為:int GetPageIndex(CPropertyPage* pPage);參數pPage:要獲取索引的屬性頁對象的指針。返回值:屬性頁對象在屬性頁對話框中的索引。(7)SetActivePage()函數設置某個屬性頁為活動屬性頁。函數原型為:???BOOL SetActivePage(int nPage?);BOOL SetActivePage(CPropertyPage* pPage?);參數 nPage:要設置為活動屬性頁的索引。參數 pPage:要設置為活動屬性頁的對象指針。(8)SetWizardButtons()函數在向導對話框上啟用或禁用Back、Next或Finish按鈕,應在調用DoModal之前調用此函數。函數原型為:void SetWizardButtons(DWORD dwFlags?);參數dwFlags:設置向導按鈕的外觀和功能屬性??梢允且韵轮档慕M合:PSWIZB_BACK????????????????????啟用“Back”按鈕,如果不包含此值則禁用“Back”按鈕。PSWIZB_NEXT??????????????????? 啟用“Next”按鈕,如果不包含此值則禁用“Next”按鈕。PSWIZB_FINISH????????????????? 啟用“Finish”按鈕。PSWIZB_DISABLEDFINISH?? 顯示禁用的“Finish”按鈕。(9)SetWizardMode()函數設置屬性頁對話框為向導對話框模式,應在調用DoModal之前調用此函數。函數原型為:void SetWizardMode( );(10)SetTitle()函數設置屬性對話框的標題。函數原型為:void SetTitle(LPCTSTR lpszText,UINT nStyle = 0?);參數lpszText:標題字符串。參數nStyle:指定屬性表標題的風格。應當為 0 或 PSH_PROPTITLE。如果設為PSH_PROPTITLE,則單詞“Properties”會出現在指定標題之后。例如,SetTitle("Simple",PSH_PROPTITLE)這種調用會使得屬性表標題為 “Simple Properties”。(11)AddPage()函數為屬性對話框添加新的屬性頁。函數原型為:void AddPage(CPropertyPage *pPage?);參數pPage:要添加的新的屬性頁的對象指針。(12)PressButton()函數模擬按下某指定的按鈕。函數原型為:???void PressButton(int nButton?);參數nButton:要模擬按下的按鈕,它可以是下列值之一:PSBTN_BACK?? 選擇“Back”按鈕。?PSBTN_NEXT?? 選擇“Next”按鈕。PSBTN_FINISH?? 選擇“Finish”按鈕。PSBTN_OK?? 選擇“OK”按鈕。PSBTN_APPLYNOW?? 選擇“Apply”按鈕。PSBTN_CANCEL?? 選擇“Cancel”按鈕。PSBTN_HELP?? 選擇“幫助”按鈕。(13)RemovePage()函數刪除某屬性頁。函數原型為:void RemovePage(CPropertyPage *pPage?);void RemovePage(int nPage?);參數pPage:要刪除的屬性頁的對象指針。參數nPage:要刪除的屬性頁的索引。

          ?????? 屬性對話框和相關的兩個類雞啄米就先介紹到這,主要是為后面使用屬性頁對話框做準備。

          ?

          ?

          創建向導對話框

          ?

          ?????? 仍然以前面的“加法計算器”的例子為基礎,在其中加入向導對話框,我們可以用它來說明加法計算器的使用方法,一步一步引導用戶操作,這也是比較常見的用法。

          ?????? 加法計算器使用時大概可以分為三步:輸入被加數、輸入加數、點“計算”按鈕。

          ?????? 雞啄米就詳細說明向導對話框的創建步驟:

          ?

          1. 創建屬性頁對話框資源

          ?????? 根據創建對話框模板和修改對話框屬性中所講方法,在“Resource View”的Dialog”節點上點右鍵,然后在右鍵菜單中選擇“Insert Dialog”創建第一個對話框模板,對話框的ID屬性設置為IDD_SUMMAND_PAGE,Caption屬性改為“被加數頁”,Style屬性在下拉列表中選擇“Child”,Border屬性在下拉列表中選擇“Thin”。

          ?????? 刪除“OK”和“Cancel”按鈕,再按照為對話框添加控件中所講方法,添加一個靜態文本框,并修改靜態文本框的Caption屬性為“請先輸入double型被加數”。

          ?????? 按照上述步驟,繼續添加第二個和第三個對話框資源。第二個對話框模板的ID設為IDD_ADDEND_PAGE,Caption屬性改為“加數頁”,也添加一個靜態文本框,Caption設為“請繼續輸入double型加數”,其他屬性同第一個對話框。第三個對話框模板的ID設為IDD_ADD_PAGE,Caption屬性改為“計算頁”,添加靜態文本框的Caption屬性改為“最后請按下“計算”按鈕”,其他屬性也第一個對話框一樣。

          ?

          2. 創建屬性頁類

          ?????? 按照創建對話框類和添加控件變量中的方法,在第一個對話框模板上點右鍵,在右鍵菜單中選擇“Add Class”,彈出類向導對話框,在“Class name”編輯框中輸入類名“CSummandPage”,與之前不同的是,因為屬性頁類都應繼承于CPropertyPage類,所以要修改下面“Base class”的選項,在下拉列表中選擇“CPropertyPage”。

          ?????? 因為是第一個屬性頁,所以它應該有一個“下一步”按鈕,在哪里添加呢?上一講CPropertyPage類的可重載函數中提到,OnSetActive函數用于處理屬性頁被切換為當前活動頁的消息,所以我們可以在OnSetActive函數中進行相關設置。

          ???????那怎樣重載OnSetActive函數呢?我們可以在“Class View”中找到“CSummandPage”節點,點右鍵彈出右鍵菜單,選擇“Properties”,然后VS2010右側面板上會顯示對話框的屬性列表,屬性列表的工具欄上有個tip信息為“Overrides”的按鈕,按下它,下方列表中就列出了重載函數,找到“OnSetActive”,點其右側空白列表項出現向下箭頭,再點箭頭就在下面出現了“<Add>OnSetActive”的選項,選擇它就會自動在CSummandPage類中添加函數OnSetActive。

          ?? 我們只需在OnSetActive函數體中添加相關代碼就可以實現添加“下一步”按鈕的效果了。新的函數體如下:

          BOOL CSummandPage::OnSetActive() { // TODO: Add your specialized code here and/or call the base class // 獲得父窗口,即屬性表CPropertySheet類 CPropertySheet* psheet = (CPropertySheet*) GetParent(); // 設置屬性表只有“下一步”按鈕 psheet->SetWizardButtons(PSWIZB_NEXT); return CPropertyPage::OnSetActive(); }

          ???????為第二個和第三個對話框也分別添加屬性頁類CAddendPage和CAddPage。但第二個對話框的屬性頁不需要重載OnSetActive函數。第三個對話框是最后一個對話框,所以不需要“下一步”按鈕,而應該換成“完成”按鈕,所以也需要重載OnSetActive函數設置“完成”按鈕。重載后的OnSetActive如下:

          BOOL CAddPage::OnSetActive() { // TODO: Add your specialized code here and/or call the base class // 獲得父窗口,即屬性表CPropertySheet類 CPropertySheet* psheet = (CPropertySheet*) GetParent(); //設置屬性表只有“完成”按鈕 psheet->SetFinishText(_T("完成")); return CPropertyPage::OnSetActive(); }

          ?????? 上面的代碼段中,字符串“完成”前加了個_T,這是因為本工程創建的時候用的默認的Unicode字符集,而如果“完成”前不加_T就是ASCII字符串。_T實際上是一個宏,工程的字符集選擇為Unicode時字符串就轉為Unicode字符串,選擇為Muli-Byte時就轉為ASCII字符串。我們可以在Solution Explorer的Addition根節點上點右鍵,在右鍵菜單上選擇“Properties”,彈出工程的屬性對話框,Configuration Properties->General右側列表中的Character Set就顯示選擇的字符集。

          ???????那點了第三個屬性頁上的“完成”按鈕我們想進行某些處理的話,就重載OnWizardFinish函數,方法同OnSetActive函數。重載后的OnWizardFinish函數如下:

          BOOL CAddPage::OnWizardFinish() { // TODO: Add your specialized code here and/or call the base class // 提示向導完成 MessageBox(_T("使用說明向導已閱讀完!")); return CPropertyPage::OnWizardFinish(); }

          ?

          3. 創建屬性表類

          ?????? 屬性頁資源和屬性頁類創建完以后,還不能生成向導對話框,我們還需要一個屬性表類,來容納這些屬性頁。

          ?????? 在Solution Explorer視圖中的根節點“Addition”上點右鍵,在右鍵菜單中選擇Add->Class,彈出“Add Class”對話框,然后在中間區域中選擇“MFC Class”,點“Add”按鈕,彈出另一個類向導對話框,設置Class name為CAddSheet,Base class選擇“CPropertySheet”,點“Finish”按鈕,這樣就屬性表類就建好了。

          ?????? 接下來,在新生成的AddSheet.h中包含三個屬性頁類的頭文件:

          ?????? #include "SummandPage.h"
          ?????? #include "AddendPage.h"
          ?????? #include "AddPage.h"

          ?????? 之后在AddSheet.h中添加private變量:

          ?????? CSummandPage??? m_summandPage;C
          ?????? CAddendPage???? m_addendPage;
          ?????? CAddPage??????? m_addPage;

          ???????然后在AddSheet.cpp文件中修改CAddSheet的兩個構造函數為:

          CAddSheet::CAddSheet(UINT nIDCaption, CWnd* pParentWnd, UINT iSelectPage) :CPropertySheet(nIDCaption, pParentWnd, iSelectPage) { // 添加三個屬性頁到屬性表 AddPage(&m_summandPage); AddPage(&m_addendPage); AddPage(&m_addPage); } CAddSheet::CAddSheet(LPCTSTR pszCaption, CWnd* pParentWnd, UINT iSelectPage) :CPropertySheet(pszCaption, pParentWnd, iSelectPage) { // 添加三個屬性頁到屬性表 AddPage(&m_summandPage); AddPage(&m_addendPage); AddPage(&m_addPage); }

          ?

          4. 顯示向導對話框

          ??????? 我們在加法計算器對話框上添加一個按鈕,點擊它就打開向導對話框。此按鈕的ID設為IDC_INSTRUCT_BUTTON,Caption屬性設為“使用說明”。

          ??????? 按照為控件添加消息處理函數中所講方法,為IDC_INSTRUCT_BUTTON按鈕在CAdditionDlg類中添加點擊消息的處理函數OnBnClickedInstructButton。然后在AdditionDlg.cpp文件中包含CAddSheet的頭文件:#include "AddSheet.h"。最后修改OnBnClickedInstructButton函數如下:

          void CAdditionDlg::OnBnClickedInstructButton() { // TODO: Add your control notification handler code here // 創建屬性表對象 CAddSheet sheet(_T("")); // 設置屬性對話框為向導對話框 sheet.SetWizardMode(); // 打開模態向導對話框 sheet.DoModal(); }

          到此,向導對話框就完整的創建完成了,并可以在加法計算器對話框上點 “使用說明” 按鈕顯示出來。我們來看看效果吧:

          ?????? 上圖只是被加數頁的效果,點其上“下一步”按鈕就可以繼續顯示后面的兩個頁面。

          ?????? 是不是向導對話框沒有以前想象的那般復雜了?大家可以發揮想象,進行更復雜的修改,實現更完善的功能。依然歡迎朋友們到雞啄米博客來交流學習。

          ?

          ?

          屬性頁對話框的創建和顯示

          ?

          屬性頁對話框包括向導對話框和一般屬性頁對話框兩類,上一節雞啄米講了如何創建并顯示向導對話框,本節將繼續介紹一般屬性頁對話框的創建和顯示。

          ?????? 實際上,一般屬性頁對話框的創建和顯示過程和向導對話框是很類似的。雞啄米將上一節中的向導對話框進行少量修改,使其成為一般屬性頁對話框。

          ?????? 一般屬性頁對話框的創建步驟:

          ???????1. 創建屬性頁對話框資源

          ?????? 屬性頁對話框資源的創建方法同向導對話框是一樣的,上一講中的對話框資源不需進行任何修改。

          ???????2. 創建屬性頁類

          ?????? 屬性頁類的創建和向導對話框的屬性頁類也基本一樣,只是一般屬性頁對話框中不需要“下一步”和“完成”等按鈕,所以上一講中屬性頁類的OnSetActive和OnWizardFinish等重載函數可以去掉。即CSummandPage類中的OnSetActive函數、CAddPage類中的OnSetActive函數和OnWizardFinish函數可以刪除或注釋掉。其他部分不需作任何修改。

          ???????3. 創建屬性表類

          ???????創建屬性表類的過程同向導對話框屬性表類也是一樣的,所以上一講中的CAddSheet類不需修改。

          ???????4. 顯示一般屬性頁對話框

          ?????? 上一講向導對話框的顯示是在OnBnClickedInstructButton函數中實現的,其中語句sheet.SetWizardMode();旨在設置屬性表為向導對話框模式,所以顯示一般屬性頁對話框時不需調用SetWizardMode成員函數。另外,我們可以將屬性頁對話框的標題設為“使用說明”,在構造屬性表對象時將此字符串作為構造函數的參數傳入。OnBnClickedInstructButton函數修改如下:

          void CAdditionDlg::OnBnClickedInstructButton() { // TODO: Add your control notification handler code here // 創建屬性表對象 CAddSheet sheet(_T("使用說明")); // 打開模態一般屬性頁對話框 sheet.DoModal(); }

          這樣一般屬性頁對話框的創建和顯示就講完了,我們運行下程序,在結果對話框上點“使用說明”按鈕看看效果吧:

          ??? 再總結下,一般屬性頁對話框和向導對話框的創建和顯示的不同包括:是否需要OnSetActive和OnWizardFinish等重載函數,是否需要調用屬性表類的SetWizardMode函數設置為向導對話框模式。

          ?

          ?

          消息對話框

          ?

          前面幾節雞啄米講了屬性頁對話框,我們可以根據所講內容方便的建立自己的屬性頁對話框。本節講解Windows系統中最常用最簡單的一類對話框--消息對話框。

          ?????? 我們在使用Windows系統的過程中經常會見到消息對話框,提示我們有異常發生或提出詢問等。因為在軟件開發中經常用到消息對話框,所以MFC提供了兩個函數可以直接生成指定風格的消息對話框,而不需要我們在每次使用的時候都要去創建對話框資源和生成對話框類等。這兩個函數就是CWnd類的成員函數MessageBox()和全局函數AfxMessageBox()。

          ?

          一 .??CWnd::MessageBox()函數 和 AfxMessageBox()函數的用法

          ?????? 下面雞啄米就分別講解兩個函數的用法。

          ???????1 . CWnd::MessageBox()函數

          ?????? CWnd::MessageBox()的函數原型如下:?????

          ?int MessageBox(LPCTSTR lpszText,LPCTSTR lpszCaption = NULL,UINT nType = MB_OK);參數說明:lpszText:需要顯示的消息字符串。lpszCaption:消息對話框的標題字符串。默認值為NULL。取值為NULL時使用默認標題。nType:消息對話框的風格和屬性。默認為 MB_OK 風格,即只有“確定”按鈕。nType 的取值可以是下面兩個表中任取一個值,也可以是各取一個值的任意組合。即可以指定一個對話框類型,也可以指定一個對話框圖標,還可以兩者都設定。

          nType 的取值可以是下面兩個表中任取一個值,也可以是各取一個值的任意組合。即可以指定一個對話框類型,也可以指定一個對話框圖標,還可以兩者都設定。下面表格是?對話框類型表

          cellpadding="1" cellspacing="1" >
          nType 取值參數說明
          MB_ABORTRETRY有“終止”、“重試”和“忽略”按鈕
          MB_OK有“確定”按鈕
          MB_OKCANCEL有“確定”和“取消”按鈕
          MB_RETRYCANCEL有“重試”和“取消”按鈕
          MB_YESNO有“是”和“否”按鈕
          MB_YESNOCANCEL有“是”、“否”和“取消”按鈕

          下面表格是??對話框圖標表

          nType 取值顯示圖標
          MB_ICONEXCLAMTION
          MB_ICONWARNING
          MB_ICONASTERISK
          MB_ICONINFORMATION
          MB_ICONQUESTION
          MB_ICONHAND
          MB_ICONSTOP
          MB_ICONERROR

          ?????? 如果想要設置nType的值為類型和圖標的組合,可以像這樣取值:MB_OKCANCEL | MB_ICONQUESTION。按位取或就可以了。

          ?

          ???????2 . AfxMessageBox()函數

          ?????? AfxMessageBox()的函數原型為:

          ?????? int AfxMessageBox(LPCTSTR lpszText,UINT nType = MB_OK,UINT nIDHelp = 0);參數說明:lpszText:同CWnd::MessageBox()函數nType:CWnd::MessageBox()函數nIDHelp:此消息的幫助的上下文ID。默認值為0,取0時表示要使用應用程序的默認幫助上下文。

          ?

          二 .?CWnd::MessageBox() 和 AfxMessageBox() 的返回值

          ??????我們在調用了上面兩個函數后,都可以彈出模態消息對話框。消息對話框關閉后,我們也都可以得到它們的返回值。兩者的返回值就是用戶在消息對話框上單擊的按鈕的ID,可以是以下值:

          ????? IDABORT:單擊“終止”按鈕。
          ????? IDCANCEL:單擊“取消”按鈕。
          ????? IDIGNORE:單擊“忽略”按鈕。
          ????? IDNO:單擊“否”按鈕。
          ????? IDOK:單擊“確定”按鈕。
          ????? IDRETRY:單擊“重試”按鈕。
          ????? IDYES:單擊“是”按鈕。

          ?

          三?.?應用舉例

          ?????我們還是拿前面加法計算器的程序做例子。

          ?????? 大家是否記得,在模態對話框及其彈出過程中我們修改了CAdditionDlg::OnBnClickedAddButton()函數,在點了“計算”按鈕以后先彈出了一個模態對話框,詢問用戶是否確定要進行加法計算,并通過模態對話框DoModal函數的返回值判斷用戶選擇了“確定”還是“取消”。這些功能很明顯消息對話框完全能夠實現,雞啄米就使用消息對話框來替代原來的模態對話框。

          ?????? 在非模態對話框的創建及顯示中,雞啄米注釋了模態對話框的相關代碼,加入了非模態對話框的創建和顯示代碼,我們在加入消息對話框之前將非模態對話框的代碼也注釋或刪除掉,確保此函數中不再生成原來的模態對話框或非模態對話框。

          ?????? 修改后的CAdditionDlg::OnBnClickedAddButton()函數如下:

          void CAdditionDlg::OnBnClickedAddButton() { // TODO: Add your control notification handler code here INT_PTR nRes; // 顯示消息對話框 nRes = MessageBox(_T("您確定要進行加法計算嗎?"), _T("加法計算器"), MB_OKCANCEL | MB_ICONQUESTION); // 判斷消息對話框返回值。如果為IDCANCEL就return,否則繼續向下執行 if (IDCANCEL == nRes) return; // 將各控件中的數據保存到相應的變量 UpdateData(TRUE); // 將被加數和加數的加和賦值給m_editSum m_editSum = m_editSummand + m_editAddend; // 根據各變量的值更新相應的控件。和的編輯框會顯示m_editSum的值 UpdateData(FALSE); // 設置屬性對話框為向導對話框 //sheet.SetWizardMode(); }

          編譯運行,在運行結果對話框上點“計算”按鈕彈出以下消息對話框:

          大家也可以將MessageBox函數換為AfxMessageBox()函數,同時參數進行相應修改,運行下看看效果。

          ?

          ?

          文件對話框

          ?

          ??????文件對話框的分類

          ??????文件對話框分為 打開文件對話框保存文件對話框,相信大家在Windows系統中經常見到這兩種文件對話框。例如,很多編輯軟件像記事本等都有“打開”選項,選擇“打開”后會彈出一個對話框,讓我們選擇要打開文件的路徑,這個對話框就是打開文件對話框;除了“打開”選項一般還會有“另存為”選項,選擇“另存為”后往往也會有一個對話框彈出,讓我們選擇保存路徑,這就是保存文件對話框。

          ?????? 正如上面舉例說明的,打開文件對話框用于選擇要打開的文件的路徑,保存文件對話框用來選擇要保存的文件的路徑。

          ?

          ???????文件對話框類CFileDialog

          ??????MFC使用文件對話框類CFileDialog封裝了對文件對話框的操作。CFileDialog類的構造函數原型如下:

          explicit CFileDialog(BOOL bOpenFileDialog,LPCTSTR lpszDefExt = NULL,LPCTSTR lpszFileName = NULL,DWORD dwFlags = OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT,LPCTSTR lpszFilter = NULL,CWnd* pParentWnd = NULL,DWORD dwSize = 0,BOOL bVistaStyle = TRUE );

          ???????參數說明:

          ?????? bOpenFileDialog:指定要創建的文件對話框的類型。設為TRUE將創建打開文件對話框,否則將創建保存文件對話框。

          ???????lpszDefExt:默認的文件擴展名。如果用戶在文件名編輯框中沒有輸入擴展名,則由lpszDefExt指定的擴展名將被自動添加到文件名后。默認為NULL。

          ?????? lpszFileName:文件名編輯框中顯示的初始文件名。如果為NULL,則不顯示初始文件名。

          ????? ?dwFlags:文件對話框的屬性,可以是一個值也可以是多個值的組合。關于屬性值的定義,可以在MSDN中查找結構體OPENFILENAME,元素Flags的說明中包含了所有屬性值。默認為OFN_HIDEREADONLY和OFN_OVERWRITEPROMPT的組合,OFN_HIDEREADONLY表示隱藏文件對話框上的“Read Only”復選框,OFN_OVERWRITEPROMPT表示在保存文件對話框中如果你選擇的文件存在了,就彈出一個消息對話框,要求確定是否要覆蓋此文件。

          ???????lpszFilter:文件過濾器,它是由若干字符串對組成的一個字符串序列。如果指定了文件過濾器,則文件對話框中只有符合過濾條件的文件顯示在文件列表中待選擇。給大家看看VS2010 MSDN中給出的一個例子:

          ?????? static TCHAR BASED_CODE szFilter[] = _T("Chart Files (*.xlc)|*.xlc|Worksheet Files (*.xls)|*.xls|Data Files (*.xlc;*.xls)|*.xlc; *.xls|All Files (*.*)|*.*||");

          ?????? 這樣設置過濾器以后,文件對話框的擴展名組合框中將有四個選項:Chart Files (*.xlc)、Worksheet Files (*.xls)、Data Files(*.xlc;*.xls)和All Files (*.*),大家可以看到每種文件的擴展名規定都是一個字符串對,例如Chart Files的過濾字符串是Chart Files(*.xlc)和*.xlc成對出現的。

          ?????? pParentWnd:文件對話框的父窗口的指針。

          ???????dwSize:OPENFILENAME結構體的大小。不同的操作系統對應不同的dwSize值。MFC通過此參數決定文件對話框的適當類型(例如,創建Windows 2000文件對話框還是XP文件對話框)。默認為0,表示MFC將根據程序運行的操作系統版本來決定使用哪種文件對話框。

          ?????? bVistaStyle:指定文件對話框的風格,設為TRUE則使用Vista風格的文件對話框,否則使用舊版本的文件對話框。此參數僅在Windows Vista中編譯時適用。

          ?????? 文件對話框也是模態對話框,所以在打開時也需要調用CFileDialog類的DoModal()成員函數。在打開文件對話框中點了“打開”或者在保存文件對話框中點了“保存”以后,我們可以使用CFileDialog類的成員函數GetPathName()獲取選擇的文件路徑。

          ?????? 下面列出幾個CFileDialog類的成員函數,我們可以使用它們獲得文件對話框中的各種選擇。

          GetFileExt():獲得選定文件的后綴名。
          GetFileName():獲得選定文件的名稱,包括后綴名。
          GetFileTitle():獲得選定文件的標題,即不包括后綴名。
          GetFolderPath():獲得選定文件的目錄。
          GetNextPathName():獲得下一個選定的文件的路徑全名。
          GetPathName():獲得選定文件的路徑全名。
          GetReadOnlyPref():獲得是否“以只讀方式打開”。
          GetStartPosition():獲得文件名列表中的第一個元素的位置。

          ?

          ???????文件對話框實例

          ??????根據前面所講內容,雞啄米給大家做個文件對話框實例。

          ?????? 1.創建一個基于對話框的MFC應用程序工程,名稱設為“Example17”。

          ?????? 2.修改主對話框IDD_EXAMPLE17_DIALOG的模板,刪除自動生成的“TODO: Place dialog controls here.”靜態文本框,添加兩個編輯框,ID分別為IDC_OPEN_EDIT和IDC_SAVE_EDIT,再添加兩個按鈕,ID分別設為IDC_OPEN_BUTTON和IDC_SAVE_BUTTON,Caption分別設為“打開”和“保存”。按鈕IDC_OPEN_BUTTON用于顯示打開文件對話框,編輯框IDC_OPEN_EDIT顯示在打開文件對話框中選擇的文件路徑。按鈕IDC_SAVE_BUTTON用于顯示保存文件對話框,編輯框IDC_SAVE_BUTTON顯示在保存文件對話框中選擇的文件路徑。

          ?????? 3.分別為按鈕IDC_OPEN_BUTTON和IDC_SAVE_BUTTON添加點擊消息的消息處理函數CExample17Dlg::OnBnClickedOpenButton()和CExample17Dlg::OnBnClickedSaveButton()。

          ????? ?4.修改兩個消息處理函數如下:

          void CExample17Dlg::OnBnClickedOpenButton() { // TODO: Add your control notification handler code here // 設置過濾器 TCHAR szFilter[] = _T("文本文件(*.txt)|*.txt|所有文件(*.*)|*.*||"); // 構造打開文件對話框 CFileDialog fileDlg(TRUE, _T("txt"), NULL, 0, szFilter, this); CString strFilePath; // 顯示打開文件對話框 if (IDOK == fileDlg.DoModal()) { // 如果點擊了文件對話框上的“打開”按鈕,則將選擇的文件路徑顯示到編輯框里 strFilePath = fileDlg.GetPathName(); SetDlgItemText(IDC_OPEN_EDIT, strFilePath); } } void CExample17Dlg::OnBnClickedSaveButton() { // TODO: Add your control notification handler code here // 設置過濾器 TCHAR szFilter[] = _T("文本文件(*.txt)|*.txt|Word文件(*.doc)|*.doc|所有文件(*.*)|*.*||"); // 構造保存文件對話框 CFileDialog fileDlg(FALSE, _T("doc"), _T("my"), OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT, szFilter, this); CString strFilePath; // 顯示保存文件對話框 if (IDOK == fileDlg.DoModal()) { // 如果點擊了文件對話框上的“保存”按鈕,則將選擇的文件路徑顯示到編輯框里 strFilePath = fileDlg.GetPathName(); SetDlgItemText(IDC_SAVE_EDIT, strFilePath); } }

          ???????上面顯示編輯框內容時,雞啄米使用了Windows API函數SetDlgItemText,當然也可以先給編輯框關聯變量,然后再使用雞啄米在創建對話框類和添加控件變量中介紹的
          CDialogEx::UpdateData()函數,但是雞啄米比較習慣使用SetDlgItemText函數,感覺比較靈活。

          ?????? 5.運行此程序,在結果對話框上點“打開”按鈕,顯示打開文件對話框如下:

          點“保存”按鈕后,顯示保存文件對話框:

          在打開文件對話框和保存文件對話框都選擇了文件路徑后,主對話框如下:

          ??? 到此,文件對話框就講完了,是不是依然很簡單?如果忘記了文件對話框類構造函數的參數意義,可以回到雞啄米來看看或者在MSDN上查閱。

          ?

          ?

          字體對話框

          ?

          ?????? 字體對話框的作用是用來選擇字體。我們也經常能夠見到。MFC使用CFontDialog類封裝了字體對話框的所有操作。字體對話框也是一種模態對話框。

          ???????CFontDialog類的構造函數

          ?????? 我們先來了解CFontDialog類。它的常用構造函數原型如下:

          CFontDialog(LPLOGFONT lplfInitial = NULL,DWORD dwFlags = CF_EFFECTS | CF_SCREENFONTS,CDC* pdcPrinter = NULL,CWnd* pParentWnd = NULL );參數說明:lplfInitial:指向LOGFONT結構體數據的指針,可以通過它設置字體的一些特征。dwFlags:指定選擇字體的一個或多個屬性,詳情可在MSDN中查閱。pdcPrinter:指向一個打印設備上下文的指針。pParentWnd:指向字體對話框父窗口的指針。

          ?????? 上面的構造函數中第一個參數為LOGFONT指針,LOGFONT結構體中包含了字體的大部分特征,包括字體高度、寬度、方向、名稱等等。下面是此結構體的定義:

          typedef struct tagLOGFONT {LONG lfHeight;LONG lfWidth;LONG lfEscapement;LONG lfOrientation;LONG lfWeight;BYTE lfItalic;BYTE lfUnderline;BYTE lfStrikeOut;BYTE lfCharSet;BYTE lfOutPrecision;BYTE lfClipPrecision;BYTE lfQuality;BYTE lfPitchAndFamily;TCHAR lfFaceName[LF_FACESIZE]; } LOGFONT;

          ?

          ???????獲取字體對話框中所選字體

          ?????? 我們在字體對話框中選擇了字體后,如何獲取選定的字體呢?我們可以通過CFontDialog類的成員變量m_cf間接獲得選定字體的CFont對象。m_cf是CHOOSEFONT類型的變量,CHOOSEFONT結構體定義如下:

          typedef struct {DWORD lStructSize;HWND hwndOwner;HDC hDC;LPLOGFONT lpLogFont;INT iPointSize;DWORD Flags;COLORREF rgbColors;LPARAM lCustData;LPCFHOOKPROC lpfnHook;LPCTSTR lpTemplateName;HINSTANCE hInstance;LPTSTR lpszStyle;WORD nFontType;INT nSizeMin;INT nSizeMax; } CHOOSEFONT, *LPCHOOSEFONT;

          ?????? CHOOSEFON結構體中有個成員lpLogFont,它是指向LOGFONT結構體變量的指針,就像上面所說,LOGFONT中包含了字體特征,例如,我們可以通過LOGFONT的lfFaceName得知字體名。

          ?????? 我們最終要獲得的是所選擇字體的CFont對象,有了字體的LOGFONT怎樣獲得對應的CFont對象呢?使用CFont類的成員函數CreateFontIndirect可以達到此目的。函數原型如下:

          ?????? BOOL CreateFontIndirect(const LOGFONT* lpLogFont );

          ?????? 參數是LOGFONT指針類型,我們可以傳入CFontDialog類成員變量m_cf的lpLogFont成員,就可以得到所選字體的CFont對象了。

          ?

          ???????字體對話框應用實例

          ?????? 雞啄米給大家做一個字體對話框的實例。先介紹此實例要實現的功能,生成一個對話框,對話框中放置一個“字體選擇”按鈕和一個編輯框。點擊“字體選擇”按鈕將彈出字體對話框。編輯框用于顯示所選字體名,并以選定的字體來顯示字體名字符串,例如,如果選擇了宋體,則在編輯框中以宋體顯示字符串“宋體”。

          ???????以下是創建此實例的步驟:

          ?????? 1.創建一個基于對話框的MFC工程,名字為“Example18”。

          ?????? 2.在自動生成的主對話框IDD_EXAMPLE18_DIALOG的模板中,刪除“TODO: Place dialog controls here.”靜態文本框,添加一個按鈕,ID設為IDC_FONT_BUTTON,Caption設為“字體選擇”,用于顯示字體對話框來選擇字體,再添加一個編輯框,ID設為IDC_FONT_EDIT,用來以所選字體顯示字體名字符串。

          ?????? 3.在Example18Dlg.h中為CExample18Dlg類添加private成員變量:CFont m_font;,用來保存編輯框中選擇的字體。

          ?????? 4.為按鈕IDC_FONT_BUTTON添加點擊消息的消息處理函數CExample18Dlg::OnBnClickedFontButton()。

          ?????? 5.修改消息處理函數CExample18Dlg::OnBnClickedFontButton()如下:

          void CExample18Dlg::OnBnClickedFontButton() { // TODO: Add your control notification handler code here CString strFontName; // 字體名稱 LOGFONT lf; // LOGFONT變量 // 將lf所有字節清零 memset(&lf, 0, sizeof(LOGFONT)); // 將lf中的元素字體名設為“宋體” _tcscpy_s(lf.lfFaceName, LF_FACESIZE, _T("宋體")); // 構造字體對話框,初始選擇字體名為“宋體” CFontDialog fontDlg(&lf); if (IDOK == fontDlg.DoModal()) // 顯示字體對話框 { // 如果m_font已經關聯了一個字體資源對象,則釋放它 if (m_font.m_hObject) { m_font.DeleteObject(); } // 使用選定字體的LOGFONT創建新的字體 m_font.CreateFontIndirect(fontDlg.m_cf.lpLogFont); // 獲取編輯框IDC_FONT_EDIT的CWnd指針,并設置其字體 GetDlgItem(IDC_FONT_EDIT)->SetFont(&m_font); // 如果用戶選擇了字體對話框的OK按鈕,則獲取被選擇字體的名稱并顯示到編輯框里 strFontName = fontDlg.m_cf.lpLogFont->lfFaceName; SetDlgItemText(IDC_FONT_EDIT, strFontName); } }

          ?????? 6.最后,編譯運行程序。顯示結果對話框,點擊“字體選擇”按鈕,將彈出字體對話框,默認選擇為“宋體”,我們改而選擇“華文彩云”字體點“確定”,編輯框中會像如下顯示:

          ?????? 到此,我們又學會了字體對話框的使用,對于以后在界面開發中控制顯示的字體很有幫助。有問題歡迎在雞啄米留言。

          ?

          ?

          顏色對話框

          ?

          ?????? 顏色對話框大家肯定也不陌生,我們可以打開它選擇需要的顏色,簡單說,它的作用就是用來選擇顏色。MFC中提供了CColorDialog類封裝了顏色對話框的所有操作,我們可以通過它顯示顏色對話框,并獲取顏色對話框中選擇的顏色。顏色對話框跟字體對話框一樣,也是一種模態對話框。

          ???????CColorDialog類的構造函數

          CColorDialog(
          ?? COLORREF clrInit = 0,
          ?? DWORD dwFlags = 0,
          ?? CWnd* pParentWnd = NULL
          );

          ?????? 參數說明:

          ?????? clrInit:默認選擇顏色的顏色值,類型為COLORREF,實際上就是unsigned long類型。如果沒有設置它的值,則默認為RGB(0,0,0),即黑色。

          ?????? 注:RGB(r,g,b)是宏,可以計算顏色值。括號中的三個值分別為紅、綠、藍分量的值。

          ?????? dwFlags:自定義顏色對話框功能和外觀的屬性值。詳情可在MSDN中查閱。

          ?????? pParentWnd:顏色對話框的父窗口的指針。

          ???????獲取顏色對話框中所選顏色值

          ?????? 我們使用顏色對話框的最終目的還是要獲得在顏色對話框中選擇的顏色值。為此CColorDialog類的成員函數GetColor()能夠很好的實現我們的要求。GetColor()函數的原型為:

          ?????? COLORREF GetColor( ) const;

          ???????它返回所選顏色的COLORREF值。

          ?????? 如果我們想獲得R、G、B各分量的值呢?可以根據GetColor得到的COLORREF顏色值,通過使用GetRValue、GetGValue和GetBValue三個宏獲得。GetRValue的語法形式為:

          ?????? BYTE GetRValue(DWORD rgb);

          ???????參數rgb就是COLORREF顏色值,返回值即是R分量值。其他兩個宏的形式與之類似。例如,GetColor()函數返回的COLORREF為10000,則R分量值就是GetRValue(10000)。

          ???????顏色對話框應用實例

          ?????? 雞啄米下面給大家做一個顏色對話框的小例子。此例要實現的功能簡單介紹下:生成一個對話框,對話框中放置一個“顏色選擇”按鈕,四個靜態文本框和四個編輯框。四個靜態文本框分別顯示Color:、R:、G:、B:,每個靜態文本框后面跟一個編輯框,分別用來顯示顏色對話框中選擇的顏色值和所選顏色值的紅色分量、綠色分量、藍色分量。

          ???????以下是實例創建的步驟:

          ???????1.創建一個基于對話框的MFC工程,名字為“Example19”。

          ???????2.在自動生成的主對話框IDD_EXAMPLE19_DIALOG的模板中,刪除“TODO: Place dialog controls here.”靜態文本框,添加一個按鈕,ID設為IDC_COLOR_BUTTON,Caption設為“顏色選擇”,用于顯示顏色對話框來選擇顏色。再添加四個靜態文本框,ID分別為IDC_COLOR_STATIC、IDC_R_STATIC、IDC_G_STATIC、IDC_B_STATIC,Caption分別設為“Color:”、“R:”、“G:”、“B:”,然后每個靜態文本框后添加一個編輯框,四個編輯框的ID分別為IDC_COLOR_EDIT、IDC_R_EDIT、IDC_G_EDIT、IDC_B_EDIT,分別用來顯示顏色對話框中選擇的顏色值和所選顏色值的紅色分量、綠色分量、藍色分量。

          ?????? 3.為按鈕IDC_COLOR_BUTTON添加點擊消息的消息處理函數CExample19Dlg::OnBnClickedColorButton()。

          ?????? 4.修改消息處理函數CExample19Dlg::OnBnClickedColorButton()如下:

          void CExample19Dlg::OnBnClickedColorButton() { // TODO: Add your control notification handler code here COLORREF color = RGB(255, 0, 0); // 顏色對話框的初始顏色為紅色 CColorDialog colorDlg(color); // 構造顏色對話框,傳入初始顏色值 if (IDOK == colorDlg.DoModal()) // 顯示顏色對話框,并判斷是否點擊了“確定” { color = colorDlg.GetColor(); // 獲取顏色對話框中選擇的顏色值 SetDlgItemInt(IDC_COLOR_EDIT, color); // 在Color編輯框中顯示所選顏色值 SetDlgItemInt(IDC_R_EDIT, GetRValue(color)); // 在R編輯框中顯示所選顏色的R分量值 SetDlgItemInt(IDC_G_EDIT, GetGValue(color)); // 在G編輯框中顯示所選顏色的G分量值 SetDlgItemInt(IDC_B_EDIT, GetBValue(color)); // 在B編輯框中顯示所選顏色的B分量值 } }

          ?????? 5.最后編譯運行程序,在結果對話框中點擊“顏色選擇”按鈕,彈出顏色對話框。初始狀態下,選擇框在紅色上,我們選另一種顏色,此時的顏色對話框如下:

          點“確定”,主對話框上的四個編輯框中分別顯示了選擇的顏色值、R分量、G分量和B分量:

          ?

          ?

          ?

          網絡推廣與網站優化公司(網絡優化與推廣專家)作為數字營銷領域的核心服務提供方,其價值在于通過技術手段與策略規劃幫助企業提升線上曝光度、用戶轉化率及品牌影響力。這...

          在當今數字化時代,公司網站已成為企業展示形象、傳遞信息和開展業務的重要平臺。然而,對于許多公司來說,網站建設的價格是一個關鍵考量因素。本文將圍繞“公司網站建設價...

          在當今的數字化時代,企業網站已成為企業展示形象、吸引客戶和開展業務的重要平臺。然而,對于許多中小企業來說,高昂的網站建設費用可能會成為其發展的瓶頸。幸運的是,隨...

          天地圖是什么坐標系?天圖采用gcs2000坐標系。國家開始封禁,谷歌地球之后,這些,地理類頭條號還能生存嗎?我最近也發現了這個問題。谷歌地圖的推出可以促進中國地圖產業的提升。事實上,這是件好事。沒有必要禁止谷歌地圖。此外,我們在國外看到的更清楚。沒有必要禁止它。另外,我們在谷歌地球上看不到任何有價值的軍事機密。最好是向喜歡學習電子地理的朋友開放]總之,要禁止谷歌地圖,目前沒有對等的替代品,這是歷史...

          怎么充移動話費?手機充電的方式有很多種,具體如下:首先可以進入移動手持營業廳充話費,進入網上營業廳后點擊充值。然后選擇要充值的話費金額,點擊立即充值。其次,你可以在支付寶首頁找到充值中心,可以給你的手機和其他手機號充值。還有,你可以去微信,我的頁面,點擊支付,然后點擊手機充值的選項進行充值。也可以通過快速通充值,點擊首頁的充值中心進行手機號充值。交話費移動網上營業廳?下載的APP,用自己的手機號注...

          天津地鐵三號線都經過哪些站?天津地鐵3號線如下:南站-楊武莊-學府工業區-高新區-大學城-花園-王頂堤-紅旗南路-周鄧紀念館-天塔-吳家窯-西康路-營口路-和平路-津灣廣場-天津火車站-金石橋-中山路-北站-鐵東路-張興莊-宜興埠-天士力-華北集團天津地鐵3號線價格表?天津地鐵3號線,4個區間內乘坐5站(含5站)每人一張2元;4區間以上乘坐5站,9區間以下(含10站)乘坐10站,每站3元;9區間以...

          TOP
          国产初高中生视频在线观看|亚洲一区中文|久久亚洲欧美国产精品|黄色网站入口免费进人
          1. <nobr id="easjo"><address id="easjo"></address></nobr>

              <track id="easjo"><source id="easjo"></source></track>
              1. 
                

              2. <bdo id="easjo"><optgroup id="easjo"></optgroup></bdo>
              3. <track id="easjo"><source id="easjo"><em id="easjo"></em></source></track><option id="easjo"><span id="easjo"><em id="easjo"></em></span></option>