版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進行舉報或認領(lǐng)
文檔簡介
第2章簡單的Windows程序設(shè)計(1)基本概念2.1VisualC++概述Visualstdio是微軟公司提供的專門用于開發(fā)Windows應(yīng)用程序的集成開發(fā)環(huán)境。從VisualStudio2002開始,Visualstdio就引入了一種新的計算平臺——Microsoft.NET。Visualstdio.NET是一種支持多種語言的應(yīng)用程序開發(fā)平臺,在Visualstdio.NET中可以使用VB.NET、C#.NET、VC++.NET等語言開發(fā)程序,甚至你可以用其中一種語言開發(fā)應(yīng)用程序的一部分,用另外的語言開發(fā)程序的其他部分。VisualC++是VisualStudio中的重要一員,通常簡稱為VC。VC盡管是屬于VS中的一個工具,但實際上VC的發(fā)布要早于VS。VisualC++最初的幾個版本發(fā)布時還沒有VisualStudio,是與VisualBasic等并列的獨立開發(fā)工具,后來微軟將它們整合在一起才形成了VisualStudio。從問世至今,VS已推出了多個版本,我們將使用較新的VS2017作為例題開發(fā)工具。2.1.1使用VisualC++開發(fā)控制臺應(yīng)用程序VC++2017是不能單獨編譯一個.CPP或者一個.c文件的,它們必須依存于某一個“項目”(Project),因此,在編寫程序代碼之前必須要先創(chuàng)建一個項目。創(chuàng)建項目有的方法有多種,可以通過點擊VS主窗口的菜單命令“文件”→“新建”→“項目”,也可以通過點擊VS主窗口工具欄的“新建項目”按鈕,還可以直接點擊起始頁面中“新建項目”一欄的“創(chuàng)建新項目...”。“新建項目對話框”是用戶進行項目類型選擇、項目名稱輸入和項目存儲位置輸入等的交互界面。在這里我們要創(chuàng)建的是Windows控制臺應(yīng)用程序,因此要選擇的程序模板是“Windows控制臺應(yīng)用程序”。代碼編輯器窗口將代碼編輯器中的代碼改寫為如下代碼,然后點擊菜單“調(diào)試”→“開始執(zhí)行(不調(diào)試)”:#include"pch.h"#include<iostream>usingnamespacestd;intmain(){cout<<"HelloWorld!\n";}2.1.2創(chuàng)建圖形界面應(yīng)用程序使用MicrosoftVisualstdio中的任何一種語言都既可以開發(fā)字符界面的控制臺應(yīng)用程序,也可以開發(fā)具有圖形界面的Windows應(yīng)用程序。在使用VisualC++開發(fā)具有圖形用戶界面的Windows應(yīng)用程序可以采用以下三種方法之一。(1)使用WindowsAPI函數(shù)(2)使用MFC(3)使用VisualC++.NET我們主要學(xué)習(xí)使用VisualC++創(chuàng)建基于MFC的對話框應(yīng)用程序相關(guān)的基本概念和基本方法。2.2VisualC++的數(shù)據(jù)類型在使用VisualC++編寫Windows程序時,除了可以直接使用標(biāo)準(zhǔn)C++中的數(shù)據(jù)類型外,為了提高程序的可讀性,VisualC++還定義了一些自己特有的數(shù)據(jù)類型,這些數(shù)據(jù)類型大都是標(biāo)準(zhǔn)C++中的數(shù)據(jù)類型的重新定義。數(shù)據(jù)類型對應(yīng)的基本數(shù)據(jù)類型說明BOOLbool布爾值BSTRunsignedshort*16位字符指針BYTEunsigned
char8位無符號整數(shù)DWORDunsignedlong32位無符號整數(shù),段地址和相關(guān)的偏移地址LONGlong32位帶符號整數(shù)LPARAMlong作為參數(shù)傳遞給窗口過程或回調(diào)函數(shù)的32位值LPCSTRconstchar*指向字符串常量的32位指針LPSTRchar*指向字符串的32位指針LPVOIDvoid*指向未定義的類型的32位指針UNITunsignedint32位無符號整數(shù)WORDunsignedshort16位無符號整數(shù)WPARAMunsigned
int當(dāng)作參數(shù)傳遞給窗口過程或回調(diào)函數(shù)的32位值VC++中的數(shù)據(jù)類型都是以大寫字符出現(xiàn)的,這主要是為了與標(biāo)準(zhǔn)C++的基本數(shù)據(jù)類型相區(qū)別。VC++中的數(shù)據(jù)類型的命名也是有規(guī)律的,從數(shù)據(jù)類型的名字基本可以看出數(shù)據(jù)類型的意義。指針類型的命令方式一般是在其指向的數(shù)據(jù)類型前加“LP”或“P”,比如指向DWORD的指針類型為“LPDWORD”和“PDWORD”;無符號類型一般是以“U”開頭,比如“INT”是符號類型,“UINT”是無符號類型。VC++還提供一些宏來處理基本數(shù)據(jù)類型:LOBYTE和HIBYTE這兩個宏分別用來獲取16位數(shù)值中的低位和高位字節(jié);LOWORD和HIWORD分別用來獲取32位數(shù)值中的低16位和高16位字;MAKEWORD則是將兩個16位無符號數(shù)合成一個32位無符號數(shù),等等。字符串類型字符串類型CString本質(zhì)上是VC++提供的一個字符串類。它提供了很多非常有用的操作和成員函數(shù),使用CString可以方便地對字符串進行處理。例如,你可以利用如下方法連接字符串:CStringgray("Gray");CStringcat("Cat");CStringgraycat=gray+cat;
//執(zhí)行后graycat的值為"GrayCat"利用格式化可以把其它不是CString類型的數(shù)據(jù)轉(zhuǎn)化為CString類型例:把一個整數(shù)轉(zhuǎn)化成CString類型
CStrings;
s.Format("%d",total);將char*轉(zhuǎn)化為CString則直接可采用如下方法:char*p="Thisisatest";CStrings=p;CStrings(p);或CStrings="Thisisatest";獲取存儲字符串的存儲區(qū)的指針(char*類型),調(diào)用GetBuffer()則可,調(diào)用getlength()則可獲得字符串長度。常用到的成員函數(shù)還包括:BOOLIsEmpty();//測試CString類對象包含的字符串是否為空。voidEmpty();//使CString類對象包含的字符串為空字符串。TCHARGetAt(intnIndex);//獲取字符串中指定位置(由nIndex指定)的字符。voidSetAt(intnIndex,TCHARch);//將字符串指定的位置處的字符設(shè)定為ch。CStringLeft(intnCount);//截取字符串左邊nCount長度的字符串。CStringRight(intnCount);//截取字符串右邊nCount長度的字符串。CString用于存儲字符串的存儲區(qū)是動態(tài)分配的,即它支持動態(tài)內(nèi)存分配,因此完全不用擔(dān)心CString的大小。另外,如果項目選擇使用UNICODE字符集,則CString對象將采用UNICODE字符,否則則使用ANSI字符。CString的聲明位于頭文件"atlstr.h"中,在程序中如果要使用CString,通常需要添加:#include<atlstr.h>。在MFC程序中,由于MFC的頭文件中已包含了該文件,因此一般不再需要在包含此文件。#include<iostream>#include<atlstr.h>usingnamespacestd;intmain(){ CStrings=L"HelloWorld!\n"; charss[30]; strcpy_s(ss,s.GetBuffer()); for(inti=0;ss[i]!=0;i++)cout<<ss[i]; char*p=s.GetBuffer(); cout<<endl; while(*p!=0){ cout<<*p;p++; } return0;}句柄類型句柄類型是Windows程序設(shè)計中的一種特殊數(shù)據(jù)類型,是Windows用來唯一標(biāo)識應(yīng)用程序所建立或使用的對象的一個32位的無符號整數(shù)值。Windows程序中需要使用句柄標(biāo)識的對象包括應(yīng)用程序?qū)嵗?、窗口、位圖、內(nèi)存塊,文件、任務(wù)等。各種句柄類型的命名方式一般都是在對象名前加“H”,比如位圖(BITMAP)對應(yīng)的句柄類型為“HBITMAP”。句柄本質(zhì)上是一種指向指針的指針應(yīng)用程序啟動后,該程序的各對象都是駐留在內(nèi)存的。理論上只要獲知對象所在的內(nèi)存首地址就能訪問該對象。但為了優(yōu)化內(nèi)存,Windows內(nèi)存管理器會經(jīng)常移動內(nèi)存中的對象,對象移動就意味著其首地址的變化。為了能找到首地址經(jīng)常變化的對象,Windows系統(tǒng)為各應(yīng)用程序預(yù)留了一些內(nèi)存空間,專門用于登記各對象在內(nèi)存中的地址變化,這些預(yù)留空間的地址是不變的,句柄就是指這些預(yù)留空間的地址。Windows內(nèi)存管理器在移動了對象后,會把對象的新地址保存于句柄對應(yīng)的存儲單元,這樣只需記住句柄地址就可以間接地知道對象在內(nèi)存中的位置了。句柄是在對象被裝載(Load)到內(nèi)存中時由系統(tǒng)分配的,當(dāng)系統(tǒng)卸載(Unload)該對象時,句柄將被釋放給系統(tǒng)。Windows應(yīng)用程序幾乎總是通過調(diào)用一個WINDOWSAPI函數(shù)來獲得一個句柄,當(dāng)我們調(diào)用WINDOWSAPI函數(shù)獲取某個對象時,API函數(shù)通常會給該對象分配一個確定的句柄,并將該句柄返回給應(yīng)用程序,然后應(yīng)用程可通過句柄來對該對象進行操作。在WINDOWS編程中會用到大量的句柄,比如:HINSTANCE(實例句柄),HBITMAP(位圖句柄),HDC(設(shè)備描述表句柄),HICON(圖標(biāo)句柄)等。教材中的表2.3列出了一些常見的句柄類型。除此之外,還有一個經(jīng)常用到的通用的句柄,就是HANDLE。2.3UNICODE字符集計算機最早使用的字符集是標(biāo)準(zhǔn)ASCII碼字符,但標(biāo)準(zhǔn)ASCII碼字符不能滿足中國、日本等亞洲國家的需求,于是各國便針對本國的語言文字制定了相應(yīng)的字符編碼標(biāo)準(zhǔn),如GB2312、BIG5、JIS等。這些字符編碼標(biāo)準(zhǔn)統(tǒng)稱為ANSI編碼標(biāo)準(zhǔn)。通常,ANSI編碼標(biāo)準(zhǔn)都與ASCII碼兼容,并且字符數(shù)目要比ASCII字符多很多,因此必需使用多個字節(jié)來表示一個字符。ANSI字符集只規(guī)定了本國或地區(qū)所使用的語言的“字符”,并未考慮其他國家或地區(qū)的ANSI碼,導(dǎo)致各種ANSI編碼空間重疊,使得同一個二進制編碼在使用不同的ANSI字符集的系統(tǒng)中被解釋成不同的符號,這會導(dǎo)致使用不同ANSI編碼標(biāo)準(zhǔn)的系統(tǒng)交換信息時出現(xiàn)亂碼。Unicode組織聯(lián)合國際標(biāo)準(zhǔn)化組織,制定了Unicode字符集,其目的是將世界上絕大多數(shù)國家的文字符號都編入其中,并為每種語言的每個字符設(shè)定唯一的一個二進制編碼,以滿足跨語言、跨平臺進行文本傳輸和處理的要求。Unicode是UniversalMultiple-OctetCodedCharacterSet的縮寫,中文翻譯為“通用多八位編碼字符集”。從1991年10月的Unicode1.0到2014年6月的Unicode7.0,Unicode總共已發(fā)布了20個版本。這20個版本從2.0開始,都保是向后兼容的,也就是說,新版本只是增加字符,對原有字符不作任何改動。Unicode編碼與UTFUnicode是一種多字節(jié)編碼方案,最初的版本采用兩個字節(jié)來表示一個字符,即UCS-2(UniversalCharacterSetcodedin2octets),其取值范圍為U+0000~U+FFFF。這個范圍中的每個數(shù)都稱為一個碼位(codepoint),每個碼位對應(yīng)一個字符,UCS-2最多只能表示65536個字符。為了能表示更多的文字,后來的Unicode版本采用四個字節(jié)來表示代碼點,即UCS-4,即它的范圍為U+00000000~U+7FFFFFFF,其中U+00000000~U+0000FFFF同UCS-2完全一樣,書寫時通常也不寫前面全0的兩個字節(jié),因此,UCS-4可以看成是在UCS-2基礎(chǔ)上又增加了一些4字節(jié)表示的字符。UCS-2和UCS-4只規(guī)定了代碼點和字符的對應(yīng)關(guān)系,但并沒有規(guī)定代碼點在計算機中如何存儲。比如,“計算機”三個漢字的Unicode代碼分別是U+8BA1、U+7B97和U+673A,那么在計算機中存儲這三個漢字時是存為“8BA17B97673A”還是“A18B977B3A67”?回答是都有可能,因為人們在發(fā)明計算機之初,對雙字節(jié)數(shù)據(jù)的存儲就存在有兩種方案,大端順序(BigEndian)和小端順序(LittleEndian),前者,即字節(jié)存儲順序跟書寫順序一致的是大端順序,后者稱為小端順序。對Unicode編碼的字符,在具體現(xiàn)實時到底是采用大端順序還是小端順序,必須要給出一個規(guī)定。規(guī)定代碼點在計算機中存儲方式的是Unicode轉(zhuǎn)換格式(UnicodeTransformationFormat,UTF)編碼。事實上,提出UTF的原因并不只是“大端順序”和“小端順序”,還有一個原因是為了節(jié)省存儲空間。例如,英文字母字及英文標(biāo)點符號所對應(yīng)的Unicode編碼均是2個字節(jié),而且編碼第一字節(jié)的8位均為0,第二字節(jié)則是相應(yīng)得ASCII編碼,如果要使用原始Unicode編碼存儲一篇只包含純英文字符的文章,顯然就會造成比較大的浪費,因為一半的存儲空間存儲的都是字節(jié)0。目前常用的UTF編碼包括UTF-8、UTF-16、UTF-16BE(BigEndian)、UTF-16LE(LittleEndian)。VisualC++對ANSI和Unicode兩種字符集都支持,UTF-16是Windows默認的Unicode編碼方式,默認采用小端順序存儲。在一個已打開的VC++項目中,可以修改它所使用的字符集。當(dāng)在程序中使用ANSI字符集時,使用單字節(jié)字符(char類型)數(shù)組存儲字符或字符串。如果在程序中使用Unicode字符集,則使用雙字節(jié)(16位)字符類型,也稱為寬字符類型,其類型符為wchar_t。無論項目使用的是ANSI字符集還是Unicode字符集,程序中用雙引號引起來的字符串常量都是單字節(jié)字符串,如果需要以雙字節(jié)字符存儲,則需要在字符串前加上L。例:定義并初始化一個寬字符數(shù)組wchar_tStr[]=L"HelloWorld!";如果將L丟掉,寫成wchar_tStr[]="HelloWorld!";程序編譯就不會通過,會出現(xiàn)這樣的錯誤提示:errorC2440:“初始化”:無法從“constchar[13]”轉(zhuǎn)換為“wchar_t[]”。在控制臺應(yīng)用程中,雙字節(jié)字符串與單字節(jié)字符串所使用的輸入輸出函數(shù)是不同的,輸入、輸出雙字節(jié)字符數(shù)據(jù)的函數(shù)分別是wscanf()和wprintf(),這兩個函數(shù)使用方法與scanf和printf類似,請看下面的例子:wchar_ta[20];wscanf(L"%s",a);wprintf(L"%s\n",a);不僅僅是輸入輸出函數(shù),其它的一些字符串處理函數(shù),對寬體字符與單字節(jié)字符也是不同的。所有的Unicode字符串函數(shù)均以wcs開頭,wcs是寬字符串的英文縮寫。若要調(diào)用Unicode函數(shù)只需用前綴wcs來取代ANSI字符串函數(shù)的前綴str即可。不難看出,使用不同字符集時程序代碼的差別是比較大的。為了實現(xiàn)同樣的代碼既適用于寬體字符也適用于窄體字符,微軟將這兩套字符集的操作進行了統(tǒng)一,對兩套字符集所使用的不同的關(guān)鍵字和庫函數(shù)名,都定義了一致的宏來替代,并使用條件編譯來控制。例如,無論使用那種字符集,字符類型的定義符可使用TCHAR,因為如果要使用窄體字符,則不定義_UNICODE宏,此時TCHAR就是char;如果使用寬體字符,則必須定義_UNICODE宏,這時TCHAR就是wchar_t。雙引號引起的字符串常量可寫為_T("HelloWorld!"),當(dāng)定義了_UNICODE宏,就相當(dāng)于L"HelloWorld!",沒定義則相當(dāng)于"HelloWorld!"。相關(guān)的字符串操作函數(shù)也都有對應(yīng)的替換函數(shù),比如,tcslen()函數(shù),在定義了_UNICODE宏時它就相當(dāng)于wcslen(),沒定義時則相當(dāng)于strlen()。這些宏的定義都在頭文件tchar.h中,因此,在程序前面需要有編譯預(yù)處理命令#include<tchar.h>。但在VisualC++中,通常是不需要手工添加的。由于大家大都只熟悉在ANSI字符集下的編程,因此本課程中的所有例題,均使用ANSI字符集,如果沒有特別說明,相關(guān)代碼都是ANSI字符集下的寫法。2.4MFC對話框應(yīng)用程序?qū)υ捒颍―ialogBox)是一種特殊的窗口,主要功能是顯示輸出信息或者接收用戶輸入。對話框應(yīng)用程序是指主窗口樣式為“對話框”的應(yīng)用程序。對話框是一種簡單的框架窗口,只有標(biāo)題欄和邊框,沒有菜單條、工具條和狀態(tài)條等,通常包含若干控件(Control),通這些控件,它可以接收用戶的輸入和選擇、向用戶顯示信息或者響應(yīng)用戶各種操作??丶侵复翱谏系木庉嬁颍‥ditControl)、命令按鈕(CommandButton)、下拉列表框(ListBox)等具有一定輸入輸出功能的小部件??丶举|(zhì)上也是一種簡單窗口,只不過它必須存在于一個稱為其父窗口的窗口內(nèi),在對話框中,對話框窗口就是其上各種控件的父窗口。使用VisualStdio的應(yīng)用程序向?qū)В梢詣?chuàng)建一個簡單的對話框應(yīng)用程序框架。2.4.1對話框應(yīng)用程序的創(chuàng)建2.4.2VisualC++2017開發(fā)環(huán)境2.4.3MFC對話框應(yīng)用程序結(jié)構(gòu)MFC應(yīng)用程序向?qū)詣由扇齻€類:CaboutDlg,ClxApp,ClxDlgClxApp是最重要的一個類,該類派生于CWinApp類。CWinApp是MFC的主應(yīng)用程序類,用于控制應(yīng)用程序的初始化、運行和終止。MFC應(yīng)用程序向?qū)傻膽?yīng)用程序必須有且僅有一個從CWinApp派生的類的對象,該對象在創(chuàng)建窗口之前構(gòu)造。ClxDlg類的聲明如下:classClxDlg:publicCDialog它是CDialog類的派生類,而CDialog又是CWnd的派生類,因此在CLXDlg類的實現(xiàn)中,可以使用CDialog類以及CWnd類的所有方法。2.4.4設(shè)置對話框的屬性對話框窗口的外觀和行為特性可通過修改它的屬性值進行改變。對話框窗口的屬性可以通過“屬性窗口”設(shè)置。要設(shè)置對話框?qū)傩?,首先打開“對話框資源編輯器”和“屬性窗口”,在新建項目中,這兩個窗口默認是被打開的。常用的對話框?qū)傩訧D:ID是應(yīng)用程序用來唯一標(biāo)識該對話框資源的標(biāo)識符,通常使用默認值,也可以對它進行修改。Caption:對話框的標(biāo)題,即對話框窗口標(biāo)題欄顯示的文字。默認值為項目名稱,通常需要改為編程者認為合適的文字。Font:在“屬性窗口”中該屬性的屬性值編輯框后有一按鈕,單擊此按鈕可彈出字體對話框,通過該對話框可選擇對話框窗口中控件上顯示的文字的字體、字形和字號。Border:用于確定窗口的邊框類型,有四個值可選,None無邊框,不顯示標(biāo)題欄;Thin細邊框,也不顯示標(biāo)題欄;DialogFram,對話框邊框,程序運行時窗口大小不可改變;Resizing,可調(diào)整尺寸,程序運行時對話框窗口的大小可用鼠標(biāo)拖曳調(diào)整。Systemmenu:該屬性用于指定是否為對話框創(chuàng)建系統(tǒng)菜單。該屬性值為Bool類型,缺省值為True。Minimizebox/Maximizebox:指定對話框是否有最小化/最大化按鈕,這兩個屬性值均為Bool類型,缺省值為False。當(dāng)對話框無標(biāo)題欄時,即Border屬性值為None或Thin時,這兩個屬性無效。2.5Windows控件一個完整的控件包括兩部分,一是控件資源,即在其父窗口上繪出的控件的圖形,另一部分則是封裝有控件屬性和方法的控件類。MFC提供了眾多的控件類,每一個類都封裝一種控件。在對話框中創(chuàng)建控件后,需要為控件定義一個對應(yīng)控件類的變量(對象)對它進行控制。2.5.1創(chuàng)建控件控件的創(chuàng)建有靜態(tài)創(chuàng)建和動態(tài)創(chuàng)建兩種。靜態(tài)創(chuàng)建是指使用對話框模板創(chuàng)建控件,并通過屬性窗口設(shè)置控件的屬性,當(dāng)打開對話框時,系統(tǒng)將自動按預(yù)設(shè)的屬性創(chuàng)建控件。動態(tài)創(chuàng)建則是指在程序的運行中根據(jù)需要,通過預(yù)先定義的控件類對象調(diào)用CreateWindow()函數(shù)創(chuàng)建控件。這里我們只簡單介紹控件的靜態(tài)創(chuàng)建方法。第一步是打開“對話框資源編輯器”和“工具箱”。第二步,在“工具箱”中單擊選中要創(chuàng)建的控件,然后將鼠標(biāo)移到“對話框資源編輯器”中的對話框上,按下鼠標(biāo)左鍵進行拖曳,在相應(yīng)位置畫出控件。第三步,選中畫好的控件,通過鼠標(biāo)拖曳調(diào)整控件的大小和位置。第四步,使用“屬性窗口”設(shè)置控件的屬性。設(shè)置控件屬性每個控件都有一個屬性集,通過設(shè)置控件的屬性可以控制控件的外觀和行為等。對于靜態(tài)創(chuàng)建的控件,可以在對話框模板中打開控件的屬性對話框直接設(shè)置控件的初始屬性值,也可以通過程序代碼動態(tài)設(shè)置控件屬性值??丶膶傩酝泻芏?,但編程時并不是每個屬性的值都需要設(shè)置,多數(shù)情況下使用默認值就可以了。不同類型的控件有不同的屬性,但是也有一些屬性是共有的。屬性功能ID程序通過控件ID來訪問一個控件。控件創(chuàng)建后系統(tǒng)會自動生成一個ID,可修改。除靜態(tài)控件外,同一程序中的控件的ID必須互不相同。Visible該屬性決定程序運行時控件是否可見。屬性值是布爾型,默認為TRUE。Disabled設(shè)置當(dāng)對話框在打開時該控件是否不可用,也是布爾類型,默認為FALSE??丶?個常用的共有屬性靜態(tài)控件是指一組控件類型,包括靜態(tài)文本(StaticText)控件、圖片控件(PictureControl)和組框(GroupBox),這些控件主要用來顯示文本或圖形信息。同一應(yīng)用程序中的多個靜態(tài)控件可以使用相同的ID,通常是它們的默認ID——IDC_STATIC。如果需要在程序中區(qū)分和操縱各個不同的靜態(tài)控件,必須重新為它們分別指定一個唯一的ID。2.5.2常用控件靜態(tài)文本(StaticText)控件:要用來顯示文字,要顯示的文本串為該控件的屬性Caption的屬性值。該屬性值可以靜態(tài)修改,也可以在程序中用賦值語句動態(tài)修改。編輯控件(EditControl):又稱編輯框,通常與靜態(tài)文本控件一起使用,用于數(shù)據(jù)的輸入和輸出。通過設(shè)置不同的屬性值,編輯控件可以表現(xiàn)為多行編輯框、密碼編輯框、只讀編輯框等多種不同類型的樣式。命令按鈕(Button):命令按鈕在被按下時會立即執(zhí)行某個命令。該命令所執(zhí)行的操作,是由命令按鈕的消息處理函數(shù)規(guī)定的。命令按鈕上顯示的文字是由Caption屬性指定的,通過修改Caption屬性的值可改變命令按鈕上顯示的文字。列表框(ListBox):常用來顯示類型相同的一系列清單,如文件、字體和用戶等,適用于從若干數(shù)據(jù)項中進行選擇的場合。列表框是一個矩形窗口,包含若干列表項(每項為一個字符串)??丶QMFC類功能描述靜態(tài)控件CStatic用來顯示一些幾乎固定不變的文字或圖形按鈕CButton用來產(chǎn)生某些命令或改變某些選項,包括單選按鈕、復(fù)選框和組框編輯框CEdit用于完成文本和數(shù)字的輸入和編輯列表框CListBox顯示一個列表,讓用戶從中選取一個或多個項組合框CComboBox是一個列表框和編輯框組合的控件滾動條CScrollBar通過滾動塊在滾動條上的移動和滾動按鈕來改變某些量進展條CProgressCtrl用來表示一個操作的進度滑動條CSliderCtrl通過滑動塊的移動來改變某些量,并帶有刻度指示日期時間控件CDateTimeCtrl用于選擇指定的日期和時間圖像列表CImageList一個具有相同大小的圖標(biāo)或位圖的集合標(biāo)簽控件CTabCtrl類似于一個文件柜上的標(biāo)簽,使用它可以將一個窗口或?qū)υ捒虻南嗤瑓^(qū)域定義為多個頁面2.6消息驅(qū)動與消息映射Windows程序是通過操作系統(tǒng)發(fā)送的消息來處理用戶輸入的。所有Windows應(yīng)用程序都是消息驅(qū)動的,消息處理是所有Windows應(yīng)用程序的核心部分。無論是系統(tǒng)產(chǎn)生的動作或是應(yīng)用程序產(chǎn)生的動作,都稱為事件(Events)產(chǎn)生的消息(Message)。在應(yīng)用程序中,通過接收消息、分發(fā)消息、處理消息來和用戶進行交互。系統(tǒng)中許多消息都經(jīng)過了嚴格的定義,并且適用于所有的應(yīng)用程序。2.6.1Windows的消息驅(qū)動機制當(dāng)用戶單擊鼠標(biāo)、敲擊鍵盤或調(diào)整窗口大小時,都將向?qū)?yīng)的窗口發(fā)送消息。每個消息都對應(yīng)于某個特定的事件,比如單擊鼠標(biāo)事件、雙擊鼠標(biāo)事件、鼠標(biāo)移動事件等。Windows系統(tǒng)將應(yīng)用程序的輸入事件轉(zhuǎn)換為消息,并將消息發(fā)送給應(yīng)用程序的窗口,這些窗口通過調(diào)用消息處理函數(shù)來接收和處理這些消息。消息處理函數(shù)通常是窗口類的成員函數(shù),編寫消息處理函數(shù)是編寫MFC應(yīng)用程序的主要任務(wù)。Windows消息大致可分為標(biāo)準(zhǔn)Windows消息、控件通知和命令消息等類型。標(biāo)準(zhǔn)Windows消息通常由窗口類處理,也就是說,這類消息的處理函數(shù)通常是MFC窗口類的成員函數(shù)。除WM_COMMAND消息外,所有以“WM_”為前綴的消息都是標(biāo)準(zhǔn)Windows消息。標(biāo)準(zhǔn)Windows消息都有默認的的處理函數(shù),這些函數(shù)是CWnd類的成員函數(shù),函數(shù)的名稱都是“On”開頭,后跟去掉“WM_”前綴的消息名稱。命令消息包括來自菜單選項、工具欄按鈕、快捷鍵等用戶接口界面的WM_COMMAND通知消息,屬于用戶應(yīng)用程序自己定義的消息。通過消息映射機制,MFC框架把命令消息按一定的路徑分發(fā)給多種類型的的對象來處理,這些對象包括文檔、文檔模板、應(yīng)用程序?qū)ο?、以及窗口和試圖等。能處理消息映射的類必定是從MFC的CCmdTarget類派生的??丶ㄖ怯煽丶鹘o父窗口的消息,但也有一個例外,當(dāng)用戶單擊“命令按鈕”按鈕控件時,發(fā)出的BN_CLICKED消息將作為命令消息來處理??丶⑼ǔR彩怯蒑FC窗口類處理的。2.6.2消息映射應(yīng)用程序運行之后,當(dāng)控件的狀態(tài)發(fā)生改變時,控件就會向其父窗口發(fā)送消息,這個消息稱為“控件通知消息”。Windows是通過調(diào)用相應(yīng)消息處理函數(shù)來處理每一條消息的,編程時,如何讓一條消息與其消息處理函數(shù)建立關(guān)聯(lián)關(guān)系呢?答案是通過消息映射。實現(xiàn)消息映射MFC是通過“類向?qū)А睅椭鷮崿F(xiàn)消息映射的類向?qū)陬惖亩x(頭文件)里增加消息處理函數(shù)聲明,并添加一行聲明消息映射的宏DECLARE_MESSAGE_MAP。還會自動在類的實現(xiàn)文件(CPP文件)中添加消息映射的內(nèi)容,并添加消息處理函數(shù)的實現(xiàn)框架(具體功能代碼需要由編程者自己編寫)。一般情況下,消息處理函數(shù)的聲明和實現(xiàn)框架均是由MFC的類向?qū)ё詣犹砑雍途S護的。2.7使用控件變量訪問控制控件控件的主要功能就是完成輸入輸出,也就是使用戶可以與程序交流信息;對話框中某個控件上輸入的數(shù)據(jù)可以保存到程序中的某個變量中,程序中某個變量的值也可以在對話框中的某個控件上輸出顯示,就是所謂控件與變量的數(shù)據(jù)交換。對話框內(nèi)的控件使用基于ID的變量映射來實現(xiàn)數(shù)據(jù)交換。通過類向?qū)?,我們可以將一個變量和一個控件進行關(guān)聯(lián)(映射)來實現(xiàn)數(shù)據(jù)交換,并且可設(shè)置其數(shù)據(jù)范圍。與控件關(guān)聯(lián)的變量通常都被稱為“控件變量”。變量的類別對命令按鈕來說只有“Control”一種,但對于文本框則會有“Control”和“Value”兩種?!癈ontrol”類別的控件變量在程序中代表控件本身,通過該類變量可直接引用該控件類的各種方法,并可以對控件的各種屬性直接操作。只有那些用于輸入數(shù)據(jù)和輸出數(shù)據(jù)的控件才能關(guān)聯(lián)“Value”類別的控件變量,該類控件變量只用于存放控件輸出或輸入的數(shù)據(jù)。對“Control”類別的控件變量,其變量類型只有一種,即該控件對應(yīng)的控件類。而“Value”類別的變量類型則可以是任何該控件所能輸入或輸出的數(shù)據(jù)類型,對文本框而言,數(shù)值類型可以是CString、int、UINT、long、DWORD、float、double、BYTE、short、BOOL等。當(dāng)為一個控件添加了一個Value類別的控件變量后,可以使用CWnd::UpdateData函數(shù)實現(xiàn)該控件變量與控件的數(shù)據(jù)交換。該函數(shù)是CWnd類的成員函數(shù),其原型如下:BOOLUpdateData(BOOLbSaveAndValidate=TRUE);該函數(shù)只有一個BOOL類型的參數(shù),調(diào)用UpdateData(FALSE)時,數(shù)據(jù)由控件變量向控件傳輸,當(dāng)調(diào)用UpdateData(TRUE)或不帶參數(shù)的UpdateData時,數(shù)據(jù)從控件向相關(guān)聯(lián)的成員變量復(fù)制。函數(shù)執(zhí)行成功則返回TRUE,否則返回FALSE。如果為一個控件添加了一個“Control”類別的控件變量,也可以使用該“Control”類型的變量調(diào)用控件類從CWnd類繼承來的成員函數(shù)SetWindowText和GetWindowText來改變或獲取控件顯示的文字。
2.8用戶自定義消息VisualC++允許用戶自己定義并發(fā)送消息,對自定義的消息用戶也必須為其添加消息處理函數(shù)。第一步,在resource.h或stdax.h或主對話框類的定義文件中添加如下代碼定義一個自己的消息:#defineWM_MY_MESSAGE
WM_USER+100其中WM_USER是為了防止用戶定義的消息ID與系統(tǒng)的消息ID沖突VisualC++提供的一個宏,小于WM_USER的ID被系統(tǒng)使用,大于WM_USER的ID才可以被用戶使用。因此自定義消息一般是WM_USER+XXX的形式,XXX表示任意一個正整數(shù)。然后,打開“MFC類向?qū)А?,選擇要處理消息的對話框類,選中“消息”選項卡。單擊選項卡下部的“添加自定義消息”按鈕,彈出“添加自定義消息”對話框。分別填入自定義消息和消息處理函數(shù)的名稱,自定義消息一定是第一步中定義的消息,輸入自定義消息后,向?qū)詣由梢粋€缺省的消息處理函數(shù)名,一般直接采用這個缺省的消息處理函數(shù)名則可,當(dāng)然也可以重新命名該函數(shù)。單擊確定返回“MFC類向?qū)А?,這時在現(xiàn)有處理程序一列發(fā)現(xiàn)剛添加的自定義消息及消息處理函數(shù)。除了函數(shù)實現(xiàn)代碼外,類向?qū)н€在消息處理函數(shù)所在的類的頭文件中添加了如下的消息處理函數(shù)的聲明代碼:afx_msgLRESULTOnMyMessage(WPARAMwParam,LPARAMlParam);在消息處理函數(shù)所在的類的cpp文件中的消息映射添加類似下面的消息映射代碼:BEGIN_MESSAGE_MAP(ClxDlg,CDialogEx)…… ON_MESSAGE(WM_MY_MESSAGE,&ClxDlg::OnMyMessage)END_MESSAGE_MAP()發(fā)送自定義消息用戶可以在需要的地方通過PostMessage或SendMessage函數(shù)來發(fā)送自定義消息,例如:PostMessage(WM_MY_MESSAGE);
PostMessage只把消息放入消息隊列,不管消息處理程序是否處理該函數(shù)都返回,然后繼續(xù)執(zhí)行,也就是說該函數(shù)是一個異步消息發(fā)送函數(shù);SendMessage則必須等待消息處理函數(shù)處理完了消息之后才返回調(diào)用該函數(shù)處繼續(xù)執(zhí)行,這是個同步消息發(fā)送函數(shù);PostMessage的返回值表示PostMessage函數(shù)是否正確執(zhí)行,而SendMessage的返回值表示消息處理函數(shù)的返回值。
2.9MFC的文件操作在MFC中,與文件處理關(guān)系較為密切的類有兩個,一個是CFile類,另一個是CFileDialog類。CFile類是MFC文件類的基類,它封裝了幾乎所有的用于文件訪問的Win32API,提供基本的文件輸入、輸出操作。CFileDialog類并不參與文件的處理,它只是封裝了應(yīng)用程序中經(jīng)常會使用的Windows的文件對話框。文件對話框提供了一種簡單的與Windows標(biāo)準(zhǔn)相一致的文件打開和文件存盤的對話框功能,它只提供“選擇(或輸入)要打開或保存的文件路徑”的功能。2.9.1CFile類要使用CFile類操作文件,首先要構(gòu)造CFile對象。使用缺省構(gòu)造函數(shù)構(gòu)造CFile類對象:缺省構(gòu)造函數(shù)僅僅構(gòu)造一個沒有關(guān)聯(lián)文件的空CFile對象,必須使用Open成員函數(shù)來打開文件。BOOLCFile::Open(LPCTSTRlpszFileName,UINTnOpenFlags,CFileException*pError=NULL);lpszFileName:帶路徑的文件名,指定要打開的文件。nOpenFlags:指定的文件打開方式,nOpenFlags的取值可以是多個標(biāo)志的組合,例如:
CFile::modeCreate|CFile::modeWrite。常用的文件打開方式標(biāo)志CFile::modeCreate調(diào)用構(gòu)造函數(shù)構(gòu)造一個新文件,如果文件已存在,則長度變成0。CFile::modeNoTruncate此值與modeCreate組合使用。如果所創(chuàng)建的文件已存在則其長度不變?yōu)?;若不存在則由modeCreate標(biāo)志創(chuàng)建一個新文件。CFile::modeRead以只讀方式打開文件。CFile::modeReadWrite以讀、寫方式打開文件。CFile::modeWrite以只寫方式打開文件。CFile::modeNoInherit阻止文件被子進程繼承。pError:該參數(shù)為一個指向CFileException對象的指針,指向的CFileException對象用于保存打開文件出錯時拋出的異常,該參數(shù)常缺省。例:CFilefile;//創(chuàng)建對象file.Open(“d:\\a.txt”,CFile::modeRead);
//以讀寫方式打開文件使用構(gòu)造函數(shù)創(chuàng)建對象時直接打開文件CFile(LPCTSTRlpszFileName,UINTnOpenFlags)lpszFileName指定的文件名nOpenFlags指定的文件打開方式例:CFilefile("d:\\a.txt",CFile::modeRead);
//以只讀方式打開D:盤根目錄上的文件并構(gòu)造CFile對象file。例:CFilefileOpen; try { fileOpen.Open("d:\\a.txt",CFile::modeRead); inti=fileOpen.GetLength(); fileOpen.Read(s,i); fileOpen.Close(); } catch(CFileException*e) { CStringstr; str.Format("讀取數(shù)據(jù)失敗的原因是:%d",e->m_cause); MessageBox(str); fileOpen.Abort(); e->Delete(); }文件讀取CFile類中讀取文件的函數(shù)是Read(),該函數(shù)的格式如下:virtualUINTRead(void*lpBuf,UINTnCount);lpBuf:指向用戶提供的緩沖區(qū)以接收從文件中讀取的數(shù)據(jù)。nCount:允許從文件中讀出的字節(jié)數(shù)的最大值,對文本模式的文件,回車換行作為一個字符。函數(shù)的返回值是實際讀取到緩沖區(qū)的字節(jié)數(shù),如果讀到文件尾,則返回值可能比參數(shù)nCount指定的值小。如果函數(shù)出錯,則會拋出CFileException異常。文件寫入寫文件的成員函數(shù)為Write(),該函數(shù)的格式如下:virtualvoidWrite(constvoid*lpBuf,UINTnCount);lpBuf:指向用戶提供的緩沖區(qū),包含將寫入文件中的數(shù)據(jù)。nCount:要寫入的字節(jié)數(shù)。對文本模式的文件,回車換行作為一個字符。該函數(shù)將數(shù)據(jù)從緩沖區(qū)寫入與CFile對象相關(guān)聯(lián)的文件。如果函數(shù)出錯,則會拋出CFileException異常。Write在幾種情況下均產(chǎn)生異常,包括磁盤滿的情況。
例:CFilefileSave;CStringm_Edit1(“aaaaaabbb\ncccccddddddd\neeeee”);try { fileSave.Open("d:\\a.txt",CFile::modeCreate|CFile::modeWrite); fileSave.Write(m_Edit1,m_Edit1.GetLength()); fileSave.Close(); } catch(CFileException*e) { CStringstr; str.Format("保存數(shù)據(jù)失敗的原因是:%d",e->m_cause); MessageBox(str); fileSave.Abort(); e->Delete(); }文件的讀寫定位virtualLONGSeek(LONGlOff,UINTnFrom);lOff:指定針移動的字節(jié)數(shù)。nFrom:指針移動的模式,可為以下值之一:CFile::begin從文件開始,把指針向后移動lOff字節(jié)。CFile::current從當(dāng)前位置開始,把指針向后移動lOff字節(jié)。CFile::end從文件尾開始,把指針向前移動lOff字節(jié)。注意,此時lOff應(yīng)為負。如果為正值,則超出文件尾。該函數(shù)在一個已打開的文件中重新定位文件位置指針。如果要求移動道德的位置合法,則返回位置指針從文件開始起的新的偏移量。否則,位置指針將不移動并拋出CFileException異常。用于定位文件讀寫位置的成員函數(shù)還有:voidSeekToBegin();將文件指針指向文件開始處。DWORDSeekToEnd();//返回文件長度(字節(jié)數(shù))將文件指針指向文件邏輯尾部文件關(guān)閉CFile類用于關(guān)閉文件的成員函數(shù)有兩個,一個是Close(),一個是Abort()。voidClose();voidAbort();Abort()與Close()區(qū)別在于Abort()忽略失敗,不會因失敗而拋出異常而Close()遇到錯誤則會拋出CFileException異常;2.9.2
CFileDialog類CFileDialog類并不參與文件的處理,它只是封裝了應(yīng)用程序中經(jīng)常會使用的Windows的文件對話框。文件對話框提供了一種簡單的與Windows標(biāo)準(zhǔn)相一致的文件打開和文件存盤的對話框功能只提供“選擇或輸入要打開或保存的文件路徑”的功能,真正的實現(xiàn)文件打開或保存還需要編寫另外的代碼。要使用CFileDialog提供的文件對話框,首先要定義一個CFileDialog類的對象。CFileDialog類的構(gòu)造函數(shù)CFileDialog(BOOLbOpenFileDialog,LPCTSTRlpszDefExt=NULL,LPCTSTRlpszFileName=NULL,DWORDdwFlags=OFN_HIDEREADONLY|OFN_OVERWRITEPROMPT,LPCTSTRlpszFilter=NULL,CWnd*pParentWnd=NULL);參數(shù)說明:bOpenFileDialg:如果為TRUE,則創(chuàng)建一個文件打開對話框;如果為FALSE,則構(gòu)造一個FileSaveAs(另存為)對話框。lpszDefExt:缺省文件擴展名,如果用戶在文件名編輯框中不包含擴展名,則lpszDefExt定義的擴展名自動加到文件名后。如果為NULL,則不添加擴展名。lpszFileName:初始顯示于文件名編輯框中的文件名,如果為NULL,則不顯示初始文件名。dwFlags:一個或多個標(biāo)志的組合,使你可定制對話框。相關(guān)標(biāo)志的使用請讀者自己查閱相關(guān)資料。lpszFilter:一列字符串對,指定可以應(yīng)用到文件的過濾器。如果指定過濾器,僅被過濾器允許的文件顯示于文件列表框中。pParentWnd:指向文件對話框?qū)ο蟮母复翱诨驌碛姓叽翱?。對LpszFilter參數(shù)的進一步說明:該參數(shù)用于指定哪些類型的文件可在文件列表框中顯示。文件的類型決定于擴展名。該參數(shù)為一字符串,可同時指定多個要顯示的文件類型,每個類型由“文件類型描述”和“文件擴展名”兩部分組成,“文件類型描述”和“擴展名”間用“|”分隔,同種類型文件的多個擴展名間可以用“;”分割,每種文件類型間也是用“|”分隔,字符串的末尾用“||”指明。例如,MirosoftExcel允許用戶用.XLC擴展名(表)或.XLS(工作表)打開文件,Excel過濾器應(yīng)如下:charszFilter[]=″ChartFiles(*.
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 校本課程國際課程設(shè)計
- 2025年山東淄博市市屬事業(yè)單位綜合類崗位招聘工作人員65人歷年管理單位筆試遴選500模擬題附帶答案詳解
- 2025年山東濟寧市屬事業(yè)單位“優(yōu)才”選聘歷年管理單位筆試遴選500模擬題附帶答案詳解
- 年會董事長致辭
- 2025年山東濟南市槐蔭區(qū)所屬事業(yè)單位招聘51人歷年管理單位筆試遴選500模擬題附帶答案詳解
- 2025年山東濟南信息工程學(xué)校招聘人員17人管理單位筆試遴選500模擬題附帶答案詳解
- 2025年山東棗莊工程技師學(xué)院招聘備案制工作人員30人管理單位筆試遴選500模擬題附帶答案詳解
- 2025年山東文化廳所屬事業(yè)單位招考工作人員管理單位筆試遴選500模擬題附帶答案詳解
- 機械原理課程設(shè)計網(wǎng)球
- 微課程設(shè)計花鐘
- 個人租房合同協(xié)議書(5篇)
- 新修訂中華人民共和國行政許可法全文解讀學(xué)習(xí)
- 廣東省廣州市花都區(qū)2024年七年級上學(xué)期期末數(shù)學(xué)試題【附答案】
- 期末測試模擬練習(xí) (含答案) 江蘇省蘇州市2024-2025學(xué)年統(tǒng)編版語文七年級上冊
- 品質(zhì)年度總結(jié)及來年計劃
- 學(xué)生體質(zhì)健康存在的主要問題及改進措施
- 2024年執(zhí)業(yè)藥師資格繼續(xù)教育定期考試題庫(附含答案)
- 建筑幕墻工程檢測知識考試題庫500題(含答案)
- 鋼棚鋼結(jié)構(gòu)施工方案
- 新版第三類醫(yī)療器械分類目錄
- 安防主管崗位招聘面試題及回答建議(某大型集團公司)2025年
評論
0/150
提交評論