• <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>

            使用VC編程來(lái)操縱Office。你可以實(shí)現(xiàn)諸如:Word文件打印、傳送數(shù)據(jù)到Word文檔、發(fā)送E-MAIL、自動(dòng)產(chǎn)生表格、Excel數(shù)據(jù)統(tǒng)計(jì)、圓餅圖,直方圖顯示、自動(dòng)報(bào)表生成、播放幻燈、doc,txt,HTML,rtf文件轉(zhuǎn)換、中文簡(jiǎn)繁體轉(zhuǎn)換、拼音或筆畫排序......只要是Office能夠?qū)崿F(xiàn)的功能,都可以在你寫的程序中調(diào)用。仔細(xì)閱讀下面的說(shuō)明,并下載源文件進(jìn)行參考,你就可以一步一步地掌握這個(gè)技術(shù)。祝朋友們學(xué)習(xí)快樂(lè)。

            一、概念
              Microsoft 的 Office 產(chǎn)品中,都提供了OLE Automation 自動(dòng)化程序的接口。如果你使用VB,VBA 和 Script 腳本調(diào)用 Office 功能的話,其實(shí)比使用 VC 調(diào)用要簡(jiǎn)單的多。比如在 WORD 中,調(diào)出菜單“工具(T)\宏(M)\錄制新宏(R)”,這時(shí)候它開始記錄你在 WORD 中任何菜單和鍵盤的操作,把你的操作過(guò)程保存起來(lái),以便再次重復(fù)調(diào)用。而保存這些操作的記錄,其實(shí)就是使用了 VBA 程序(Visual Basic for Application)。而我們下面要實(shí)現(xiàn)的功能,也同樣要參考 VBA 的方法。

            二、結(jié)構(gòu)層次
              為了更有邏輯,更有層次地操作 Office,Microsoft 把應(yīng)用(Application)按邏輯功能劃分為如下的樹形結(jié)構(gòu)

            Application(WORD 為例,只列出一部分)
              Documents(所有的文檔)
                    Document(一個(gè)文檔)
                        ......
              Templates(所有模板)
                    Template(一個(gè)模板)
                        ......
              Windows(所有窗口)
                    Window
                    Selection
                    View
              Selection(編輯對(duì)象)
                    Font
                    Style
                    Range
                    ......
              ......

            只有了解了邏輯層次,我們才能正確的操縱 Office。舉例來(lái)講,如果給出一個(gè)VBScript語(yǔ)句是:
                  application.ActiveDocument.SaveAs "c:\abc.doc"
            那么,我們就知道了,這個(gè)操作的過(guò)程是:第一步,取得Application;第二步,從Application中取得ActiveDocument;第三步,調(diào)用 Document 的函數(shù) SaveAs,參數(shù)是一個(gè)字符串型的文件名。

            三、基本步驟
            (1)創(chuàng)建(或打開已有的)一個(gè) MFC 的程序工程
            (2)Ctrl+W 執(zhí)行 ClassWizard(本文按照 VC6 操作,例子程序也是在VC6 下編寫測(cè)試的)
            (3)Add Class...\From a type Library... 在 Office 目錄中,找到你想使用的類型庫(kù)。(我使用的是 Office2000,其Word 的類型庫(kù)文件,保存在 C:\Program Files\Microsoft Office\Office\MSWORD9.OLB)根據(jù)你 Office 的版本,可以使用下表列出的類型庫(kù)文件

            Office 版本和類型

            類型庫(kù)文件

            Office 版本和類型

            類型庫(kù)文件

            Access 97 Msacc8.olb PowerPoint 2000 Msppt9.olb
            Jet Database 3.5 DAO350.dll Word 2000 Msword9.olb
            Binder 97 Msbdr8.olb Access 2002 Msacc.olb
            Excel 97 Excel8.olb Excel 2002 Excel.exe
            Graph 97 Graph8.olb Graph 2002 Graph.exe
            Office 97 Mso97.dll Office 2002 MSO.dll
            Outlook 97 Msoutl97.olb Outlook 2002 MSOutl.olb
            PowerPoint 97 Msppt8.olb PowerPoint 2002 MSPpt.olb
            Word 97 Msword8.olb Word 2002 MSWord.olb
            Access 2000 Msacc9.olb Office Access 2003 Msacc.olb
            Jet Database 3.51 DAO360.dll Office Excel 2003 Excel.exe
            Binder 2000 Msbdr9.olb Graph 2003 Graph.exe
            Excel 2000 Excel9.olb Office 2003 MSO.dll
            Graph 2000 Graph9.olb Office Outlook 2003 MSOutl.olb
            Office 2000 Mso9.dll Office PowerPoint 2003 MSPpt.olb
            Outlook 2000 Msoutl9.olb Office Word 2003 MSWord.olb

            (4)選擇類型庫(kù)文件后,在彈出的對(duì)話窗中繼續(xù)選擇要添加的類。具體選擇什么類,要看你將來(lái)在程序中打算調(diào)用什么功能。當(dāng)然,你也可以不用考慮這么多,用鼠標(biāo)和Shift鍵配合,全部選擇也可以。
            (5)初始化COM。方法一,找到App的InitInstance()函數(shù),在其中添加 AfxOleInit()函數(shù)的調(diào)用;方法二,在需要調(diào)用COM功能的地方 CoInitialize(NULL),調(diào)用完畢后 CoUninitialize()。
            (6)在你需要調(diào)用 Office 功能函數(shù)的 cpp 文件中
                 #include <atlbase.h>  // 為了方便操作 VARIANT 類型變量,使用 CComVariant 模板類
                 #include "頭文件.h"   // 具體的頭文件名,是由裝載類型庫(kù)的文件名決定的。(鼠標(biāo)雙點(diǎn)包裝類的文件,就可以看到)
                                       // 比如使用 msword9.olb類型庫(kù),那么頭文件是 msword9.h
            (7)好了,現(xiàn)在開始寫程序吧。另外要說(shuō)明的是,步驟3和4,其實(shí)也可以使用 #import 方式引入類型庫(kù)。

            四、實(shí)現(xiàn)技巧
                在書寫調(diào)用 Office 函數(shù)的過(guò)程中,最困難的是確定函數(shù)的參數(shù),一般情況下,參數(shù)都是 VARIANT 類型的變量指針。那么到底具體我們應(yīng)該怎么寫那?推薦兩個(gè)方法,其一是閱讀有關(guān) VBA 的書籍;其二,是使用 Office 中自帶的“宏”功能。強(qiáng)烈推薦大家使用第二個(gè)方法,把你要完成的功能,在 Office 的操作環(huán)境中,用宏錄制下來(lái),然后觀察分析錄制后的函數(shù)和參數(shù),就可以在 VC 中使用了。舉一個(gè)例子:

                  ActiveDocument.SaveAs FileName:="Hello.doc", FileFormat:=wdFormatDocument _
            , LockComments:=False, Password:="", AddToRecentFiles:=True, _
            WritePassword:="", ReadOnlyRecommended:=False, EmbedTrueTypeFonts:=False, _
            SaveNativePictureFormat:=False, SaveFormsData:=False, SaveAsAOCELetter:= _
            False
            以上是在 Word 中錄制的一個(gè)保存文件的宏,而在 VC 中對(duì)應(yīng)的函數(shù)原型為
                  void _Document::SaveAs(VARIANT* FileName, VARIANT* FileFormat, VARIANT* LockComments,
            VARIANT* Password, VARIANT* AddToRecentFiles, VARIANT* WritePassword,
            VARIANT* ReadOnlyRecommended, VARIANT* EmbedTrueTypeFonts, VARIANT* SaveNativePictureFormat,
            VARIANT* SaveFormsData, VARIANT* SaveAsAOCELetter)
            分析對(duì)照后,我們就能看出,參數(shù) FileName 是字符串 VARIANT(VT_BSTR),參數(shù) LockComments 是布爾VARIANT(VT_BOOL),等等。參數(shù) FileFormat := wdFormatDocument 是什么類型那?其實(shí)這是一個(gè)表示保存的時(shí)候指定文件類型的常量,而且顯然是 DWORD 類型VARIANT(VT_I4)。那么常量的數(shù)值又是多少那?很簡(jiǎn)單,寫一個(gè)宏,調(diào)用函數(shù) MsgBox 顯示一下不就都知道啦?!

            五、步步為營(yíng)
              特別提示一:編譯執(zhí)行前,一定要先關(guān)閉 KV 實(shí)時(shí)監(jiān)視病毒的功能(KV 的程序會(huì)干擾我們的調(diào)用,瑞星的則沒(méi)關(guān)系)。
               特別提示二:在例子程序中,為了表現(xiàn)程序的關(guān)鍵部分,沒(méi)有或很少使用了條件判斷。為了實(shí)現(xiàn)你程序的健壯性,請(qǐng)自己加上條件判斷和異常處理。

            Step1:如何啟動(dòng)和關(guān)閉 WORD,及 VARIANT 的最基本的使用方法
            Step2:和 Step1 同樣功能,用 CComVariant 改進(jìn)了 VARIANT 的使用方式
            Step3:在 Step2 的基礎(chǔ)上,新建一個(gè) WORD 文檔,并從程序中傳送一些字符到 WORD
            Step4:在 Step3 的基礎(chǔ)上,保存 WORD 文檔
            Step5:一個(gè)小應(yīng)用舉例,把輸入的漢字按照“筆畫”排序
            Step6:一個(gè)小應(yīng)用舉例,盜竊正在使用的 WORD 文檔
              以上這6個(gè)小程序中,都有詳細(xì)的注釋。大家閱讀后慢慢體會(huì)并實(shí)驗(yàn),你就可以自由地操縱任何一個(gè) Office 啦。
            posted @ 2008-04-27 15:28 wrh 閱讀(253) | 評(píng)論 (0)編輯 收藏
            在工業(yè)生產(chǎn)控制系統(tǒng)中,有許多需要定時(shí)完成的操作,如定時(shí)顯示當(dāng)前時(shí)間,定時(shí)刷新屏幕上的進(jìn)度條,上位 機(jī)定時(shí)向下位機(jī)發(fā)送命令和傳送數(shù)據(jù)等。特別是在對(duì)控制性能要求較高的實(shí)時(shí)控制系統(tǒng)和數(shù)據(jù)采集系統(tǒng)中,就更需要精確定時(shí)操作。
              眾所周知,Windows 是基于消息機(jī)制的系統(tǒng),任何事件的執(zhí)行都是通過(guò)發(fā)送和接收消息來(lái)完成的。 這樣就帶來(lái)了一些問(wèn)題,如一旦計(jì)算機(jī)的CPU被某個(gè)進(jìn)程占用,或系統(tǒng)資源緊張時(shí),發(fā)送到消息隊(duì)列 中的消息就暫時(shí)被掛起,得不到實(shí)時(shí)處理。因此,不能簡(jiǎn)單地通過(guò)Windows消息引發(fā)一個(gè)對(duì)定時(shí)要求 嚴(yán)格的事件。另外,由于在Windows中已經(jīng)封裝了計(jì)算機(jī)底層硬件的訪問(wèn),所以,要想通過(guò)直接利用 訪問(wèn)硬件來(lái)完成精確定時(shí),也比較困難。所以在實(shí)際應(yīng)用時(shí),應(yīng)針對(duì)具體定時(shí)精度的要求,采取相適 應(yīng)的定時(shí)方法。
              VC中提供了很多關(guān)于時(shí)間操作的函數(shù),利用它們控制程序能夠精確地完成定時(shí)和計(jì)時(shí)操作。本文詳細(xì)介紹了 VC中基于Windows的精確定時(shí)的七種方式,如下圖所示:


            圖一 圖像描述

              方式一:VC中的WM_TIMER消息映射能進(jìn)行簡(jiǎn)單的時(shí)間控制。首先調(diào)用函數(shù)SetTimer()設(shè)置定時(shí) 間隔,如SetTimer(0,200,NULL)即為設(shè)置200ms的時(shí)間間隔。然后在應(yīng)用程序中增加定時(shí)響應(yīng)函數(shù) OnTimer(),并在該函數(shù)中添加響應(yīng)的處理語(yǔ)句,用來(lái)完成到達(dá)定時(shí)時(shí)間的操作。這種定時(shí)方法非常 簡(jiǎn)單,可以實(shí)現(xiàn)一定的定時(shí)功能,但其定時(shí)功能如同Sleep()函數(shù)的延時(shí)功能一樣,精度非常低,最小 計(jì)時(shí)精度僅為30ms,CPU占用低,且定時(shí)器消息在多任務(wù)操作系統(tǒng)中的優(yōu)先級(jí)很低,不能得到及時(shí)響 應(yīng),往往不能滿足實(shí)時(shí)控制環(huán)境下的應(yīng)用。只可以用來(lái)實(shí)現(xiàn)諸如位圖的動(dòng)態(tài)顯示等對(duì)定時(shí)精度要求不高的情況。如示例工程中的Timer1。
              方式二:VC中使用sleep()函數(shù)實(shí)現(xiàn)延時(shí),它的單位是ms,如延時(shí)2秒,用sleep(2000)。精度非常 低,最小計(jì)時(shí)精度僅為30ms,用sleep函數(shù)的不利處在于延時(shí)期間不能處理其他的消息,如果時(shí)間太 長(zhǎng),就好象死機(jī)一樣,CPU占用率非常高,只能用于要求不高的延時(shí)程序中。如示例工程中的Timer2。
              方式三:利用COleDateTime類和COleDateTimeSpan類結(jié)合WINDOWS的消息處理過(guò)程來(lái)實(shí)現(xiàn)秒級(jí)延時(shí)。如示例工程中的Timer3和Timer3_1。以下是實(shí)現(xiàn)2秒的延時(shí)代碼:
                  COleDateTime      start_time = COleDateTime::GetCurrentTime();
            COleDateTimeSpan  end_time= COleDateTime::GetCurrentTime()-start_time;
            while(end_time.GetTotalSeconds()< 2) //實(shí)現(xiàn)延時(shí)2秒
            {
            MSG   msg;
            GetMessage(&msg,NULL,0,0);
            TranslateMessage(&msg);
            DispatchMessage(&msg);
            //以上四行是實(shí)現(xiàn)在延時(shí)或定時(shí)期間能處理其他的消息,
                   //雖然這樣可以降低CPU的占有率,
            //但降低了延時(shí)或定時(shí)精度,實(shí)際應(yīng)用中可以去掉。
            end_time = COleDateTime::GetCurrentTime()-start_time;
            }//這樣在延時(shí)的時(shí)候我們也能夠處理其他的消息。      
              方式四:在精度要求較高的情況下,VC中可以利用GetTickCount()函數(shù),該函數(shù)的返回值是  DWORD型,表示以ms為單位的計(jì)算機(jī)啟動(dòng)后經(jīng)歷的時(shí)間間隔。精度比WM_TIMER消息映射高,在較 短的定時(shí)中其計(jì)時(shí)誤差為15ms,在較長(zhǎng)的定時(shí)中其計(jì)時(shí)誤差較低,如果定時(shí)時(shí)間太長(zhǎng),就好象死機(jī)一樣,CPU占用率非常高,只能用于要求不高的延時(shí)程序中。如示例工程中的Timer4和Timer4_1。下列代碼可以實(shí)現(xiàn)50ms的精確定時(shí):
                   DWORD dwStart = GetTickCount();
            DWORD dwEnd   = dwStart;
            do
            {
            dwEnd = GetTickCount()-dwStart;
            }while(dwEnd <50);
            為使GetTickCount()函數(shù)在延時(shí)或定時(shí)期間能處理其他的消息,可以把代碼改為:
                   DWORD dwStart = GetTickCount();
            DWORD dwEnd   = dwStart;
            do
            {
            MSG   msg;
            GetMessage(&msg,NULL,0,0);
            TranslateMessage(&msg);
            DispatchMessage(&msg);
            dwEnd = GetTickCount()-dwStart;
            }while(dwEnd <50);
            雖然這樣可以降低CPU的占有率,并在延時(shí)或定時(shí)期間也能處理其他的消息,但降低了延時(shí)或定時(shí)精度。
              方式五:與GetTickCount()函數(shù)類似的多媒體定時(shí)器函數(shù)DWORD timeGetTime(void),該函數(shù)定時(shí)精 度為ms級(jí),返回從Windows啟動(dòng)開始經(jīng)過(guò)的毫秒數(shù)。微軟公司在其多媒體Windows中提供了精確定時(shí)器的底 層API持,利用多媒體定時(shí)器可以很精確地讀出系統(tǒng)的當(dāng)前時(shí)間,并且能在非常精確的時(shí)間間隔內(nèi)完成一 個(gè)事件、函數(shù)或過(guò)程的調(diào)用。不同之處在于調(diào)用DWORD timeGetTime(void) 函數(shù)之前必須將 Winmm.lib  和 Mmsystem.h 添加到工程中,否則在編譯時(shí)提示DWORD timeGetTime(void)函數(shù)未定義。由于使用該 函數(shù)是通過(guò)查詢的方式進(jìn)行定時(shí)控制的,所以,應(yīng)該建立定時(shí)循環(huán)來(lái)進(jìn)行定時(shí)事件的控制。如示例工程中的Timer5和Timer5_1。
              方式六:使用多媒體定時(shí)器timeSetEvent()函數(shù),該函數(shù)定時(shí)精度為ms級(jí)。利用該函數(shù)可以實(shí)現(xiàn)周期性的函數(shù)調(diào)用。如示例工程中的Timer6和Timer6_1。函數(shù)的原型如下:
                   MMRESULT timeSetEvent( UINT uDelay,
            UINT uResolution,
            LPTIMECALLBACK lpTimeProc,
            WORD dwUser,
            UINT fuEvent )
              該函數(shù)設(shè)置一個(gè)定時(shí)回調(diào)事件,此事件可以是一個(gè)一次性事件或周期性事件。事件一旦被激活,便調(diào)用指定的回調(diào)函數(shù), 成功后返回事件的標(biāo)識(shí)符代碼,否則返回NULL。函數(shù)的參數(shù)說(shuō)明如下:
                   uDelay:以毫秒指定事件的周期。
            Uresolution:以毫秒指定延時(shí)的精度,數(shù)值越小定時(shí)器事件分辨率越高。缺省值為1ms。
            LpTimeProc:指向一個(gè)回調(diào)函數(shù)。
            DwUser:存放用戶提供的回調(diào)數(shù)據(jù)。
            FuEvent:指定定時(shí)器事件類型:
            TIME_ONESHOT:uDelay毫秒后只產(chǎn)生一次事件
            TIME_PERIODIC :每隔uDelay毫秒周期性地產(chǎn)生事件。      
              具體應(yīng)用時(shí),可以通過(guò)調(diào)用timeSetEvent()函數(shù),將需要周期性執(zhí)行的任務(wù)定義在LpTimeProc回調(diào)函數(shù) 中(如:定時(shí)采樣、控制等),從而完成所需處理的事件。需要注意的是,任務(wù)處理的時(shí)間不能大于周期間隔時(shí)間。另外,在定時(shí)器使用完畢后, 應(yīng)及時(shí)調(diào)用timeKillEvent()將之釋放。
              方式七:對(duì)于精確度要求更高的定時(shí)操作,則應(yīng)該使用QueryPerformanceFrequency()和 QueryPerformanceCounter()函數(shù)。這兩個(gè)函數(shù)是VC提供的僅供Windows 95及其后續(xù)版本使用的精確時(shí)間函數(shù),并要求計(jì)算機(jī)從硬件上支持精確定時(shí)器。如示例工程中的Timer7、Timer7_1、Timer7_2、Timer7_3。
            QueryPerformanceFrequency()函數(shù)和QueryPerformanceCounter()函數(shù)的原型如下:
                   BOOL  QueryPerformanceFrequency(LARGE_INTEGER *lpFrequency);
            BOOL  QueryPerformanceCounter(LARGE_INTEGER *lpCount);
              數(shù)據(jù)類型ARGE_INTEGER既可以是一個(gè)8字節(jié)長(zhǎng)的整型數(shù),也可以是兩個(gè)4字節(jié)長(zhǎng)的整型數(shù)的聯(lián)合結(jié)構(gòu), 其具體用法根據(jù)編譯器是否支持64位而定。該類型的定義如下:
                   typedef union _LARGE_INTEGER
            {
            struct
            {
            DWORD LowPart ;// 4字節(jié)整型數(shù)
            LONG  HighPart;// 4字節(jié)整型數(shù)
            };
            LONGLONG QuadPart ;// 8字節(jié)整型數(shù)
            }LARGE_INTEGER ;
              在進(jìn)行定時(shí)之前,先調(diào)用QueryPerformanceFrequency()函數(shù)獲得機(jī)器內(nèi)部定時(shí)器的時(shí)鐘頻率, 然后在需要嚴(yán)格定時(shí)的事件發(fā)生之前和發(fā)生之后分別調(diào)用QueryPerformanceCounter()函數(shù),利用兩次獲得的計(jì)數(shù)之差及時(shí)鐘頻率,計(jì)算出事件經(jīng) 歷的精確時(shí)間。下列代碼實(shí)現(xiàn)1ms的精確定時(shí):
                   LARGE_INTEGER litmp;
            LONGLONG QPart1,QPart2;
            double dfMinus, dfFreq, dfTim;
            QueryPerformanceFrequency(&litmp);
            dfFreq = (double)litmp.QuadPart;// 獲得計(jì)數(shù)器的時(shí)鐘頻率
            QueryPerformanceCounter(&litmp);
            QPart1 = litmp.QuadPart;// 獲得初始值
            do
            {
            QueryPerformanceCounter(&litmp);
            QPart2 = litmp.QuadPart;//獲得中止值
            dfMinus = (double)(QPart2-QPart1);
            dfTim = dfMinus / dfFreq;// 獲得對(duì)應(yīng)的時(shí)間值,單位為秒
            }while(dfTim<0.001);
              其定時(shí)誤差不超過(guò)1微秒,精度與CPU等機(jī)器配置有關(guān)。 下面的程序用來(lái)測(cè)試函數(shù)Sleep(100)的精確持續(xù)時(shí)間:
                   LARGE_INTEGER litmp;
            LONGLONG QPart1,QPart2;
            double dfMinus, dfFreq, dfTim;
            QueryPerformanceFrequency(&litmp);
            dfFreq = (double)litmp.QuadPart;// 獲得計(jì)數(shù)器的時(shí)鐘頻率
            QueryPerformanceCounter(&litmp);
            QPart1 = litmp.QuadPart;// 獲得初始值
            Sleep(100);
            QueryPerformanceCounter(&litmp);
            QPart2 = litmp.QuadPart;//獲得中止值
            dfMinus = (double)(QPart2-QPart1);
            dfTim = dfMinus / dfFreq;// 獲得對(duì)應(yīng)的時(shí)間值,單位為秒     
              由于Sleep()函數(shù)自身的誤差,上述程序每次執(zhí)行的結(jié)果都會(huì)有微小誤差。下列代碼實(shí)現(xiàn)1微秒的精確定時(shí):
                   LARGE_INTEGER litmp;
            LONGLONG QPart1,QPart2;
            double dfMinus, dfFreq, dfTim;
            QueryPerformanceFrequency(&litmp);
            dfFreq = (double)litmp.QuadPart;// 獲得計(jì)數(shù)器的時(shí)鐘頻率
            QueryPerformanceCounter(&litmp);
            QPart1 = litmp.QuadPart;// 獲得初始值
            do
            {
            QueryPerformanceCounter(&litmp);
            QPart2 = litmp.QuadPart;//獲得中止值
            dfMinus = (double)(QPart2-QPart1);
            dfTim = dfMinus / dfFreq;// 獲得對(duì)應(yīng)的時(shí)間值,單位為秒
            }while(dfTim<0.000001);
            其定時(shí)誤差一般不超過(guò)0.5微秒,精度與CPU等機(jī)器配置有關(guān)。(完)
            posted @ 2008-04-27 15:19 wrh 閱讀(231) | 評(píng)論 (0)編輯 收藏
            有三個(gè)API函數(shù)可以運(yùn)行可執(zhí)行文件WinExec、ShellExecute和CreateProcess。CreateProcess因?yàn)槭褂脧?fù)雜,比較少用。 
            WinExec主要運(yùn)行EXE文件。如:WinExec(’Notepad.exe Readme.txt’, SW_SHOW); 

            ShellExecute不僅可以運(yùn)行EXE文件,也可以運(yùn)行已經(jīng)關(guān)聯(lián)的文件。

            首先必須引用shellapi.pas單元:uses ShellAPI; 

            1.標(biāo)準(zhǔn)用法 

              ShellExecute函數(shù)原型及參數(shù)含義如下: 

              function ShellExecute(hWnd: HWND; Operation, FileName, Parameters,Directory: PChar; ShowCmd: Integer): HINST; stdcall; 

              ●hWnd:用于指定父窗口句柄。當(dāng)函數(shù)調(diào)用過(guò)程出現(xiàn)錯(cuò)誤時(shí),它將作為Windows消息窗口的父窗口。例如,可以將其設(shè)置為應(yīng)用程序主窗口句柄,即Application.Handle,也可以將其設(shè)置為桌面窗口句柄(用GetDesktopWindow函數(shù)獲得)。 

              ●Operation:用于指定要進(jìn)行的操作。其中“open”操作表示執(zhí)行由FileName參數(shù)指定的程序,或打開由FileName參數(shù)指定的文件或文件夾;“print”操作表示打印由FileName參數(shù)指定的文件;“explore”操作表示瀏覽由FileName參數(shù)指定的文件夾。當(dāng)參數(shù)設(shè)為nil時(shí),表示執(zhí)行默認(rèn)操作“open”。 

              ●FileName:用于指定要打開的文件名、要執(zhí)行的程序文件名或要瀏覽的文件夾名。 

              ●Parameters:若FileName參數(shù)是一個(gè)可執(zhí)行程序,則此參數(shù)指定命令行參數(shù),否則此參數(shù)應(yīng)為nil或PChar(0)。 

              ●Directory:用于指定默認(rèn)目錄。 

              ●ShowCmd:若FileName參數(shù)是一個(gè)可執(zhí)行程序,則此參數(shù)指定程序窗口的初始顯示方式,否則此參數(shù)應(yīng)設(shè)置為0。 

              若ShellExecute函數(shù)調(diào)用成功,則返回值為被執(zhí)行程序的實(shí)例句柄。若返回值小于32,則表示出現(xiàn)錯(cuò)誤。 

              上述僅僅是ShellExecute函數(shù)的標(biāo)準(zhǔn)用法,下面將介紹它的特殊用法。 

            2.特殊用法 

              如果將FileName參數(shù)設(shè)置為“http:”協(xié)議格式,那么該函數(shù)將打開默認(rèn)瀏覽器并鏈接到指定的URL地址。若用戶機(jī)器中安裝了多個(gè)瀏覽器,則該函數(shù)將根據(jù)Windows 9x/NT注冊(cè)表中http協(xié)議處理程序(Protocols Handler)的設(shè)置確定啟動(dòng)哪個(gè)瀏覽器。 

              格式一:http://網(wǎng)站域名。 

              如:ShellExecute(handle, ‘open’, http:// ; 

            www.neu.edu.cn’, nil, nil, SW_SHOWNORMAL); 

              格式二:http://網(wǎng)站域名/網(wǎng)頁(yè)文件名。 

              如:ShellExecute(handle, ‘open’, http:// ; 

            www.neu.edu.cn/default.htm’,nil,nil, 

            SW_SHOWNORMAL); 

              如果將FileName參數(shù)設(shè)置為“mailto:”協(xié)議格式,那么該函數(shù)將啟動(dòng)默認(rèn)郵件客戶程序,如Microsoft Outlook(也包括Microsoft Outlook Express)或Netscape Messanger。若用戶機(jī)器中安裝了多個(gè)郵件客戶程序,則該函數(shù)將根據(jù)Windows 9x/NT注冊(cè)表中mailto協(xié)議處理程序的設(shè)置確定啟動(dòng)哪個(gè)郵件客戶程序。 

              格式一:mailto: 

              如:ShellExecute(handle,‘open’, ‘mailto:’, nil, nil, SW_SHOWNORMAL);打開新郵件窗口。 

              格式二:mailto:用戶賬號(hào)@郵件服務(wù)器地址 

              如:ShellExecute(handle, ‘open’,‘ mailto:who@mail.neu.edu.cn’, nil, nil, SW_SHOWNORMAL);打開新郵件窗口,并自動(dòng)填入收件人地址。若指定多個(gè)收件人地址,則收件人地址之間必須用分號(hào)或逗號(hào)分隔開(下同)。 

              格式三:mailto:用戶賬號(hào)@郵件服務(wù)器地址?subject=郵件主題&body=郵件正文 

              如:ShellExecute(handle, ‘open’, ‘ mailto:who@mail.neu.edu.cn?subject=Hello&Body=This is a test’, nil, nil, SW_SHOWNORMAL);打開新郵件窗口,并自動(dòng)填入收件人地址、郵件主題和郵件正文。若郵件正文包括多行文本,則必須在每行文本之間加入換行轉(zhuǎn)義字符%0a。 

            例子(delphi): 

            在一個(gè)應(yīng)用程序調(diào)用c:\Project1.exe; 

            ShellExecute(handle, ’open’,’c:\Project1.exe’,’字串內(nèi)容’,nil, SW_SHOWNORMAL); 

            在Project1.exe里可以調(diào)用: 

            procedure TForm1.FormCreate(Sender: TObject); 

            var i:integer; 

            begin 

            for i:=1 to paramcount do 

            if ParamStr(i)<>’’ then showmessage(ParamStr(i)); 

            end;

             

            最后的那個(gè)參數(shù),為窗口指定可視性方面的一個(gè)命令。 

            請(qǐng)用下述任何一個(gè)常數(shù) 

            SW_HIDE 隱藏窗口,活動(dòng)狀態(tài)給令一個(gè)窗口 

            SW_MINIMIZE 最小化窗口,活動(dòng)狀態(tài)給令一個(gè)窗口 

            SW_RESTORE 用原來(lái)的大小和位置顯示一個(gè)窗口,同時(shí)令其進(jìn)入活動(dòng)狀態(tài) 

            SW_SHOW 用當(dāng)前的大小和位置顯示一個(gè)窗口,同時(shí)令其進(jìn)入活動(dòng)狀態(tài) 

            SW_SHOWMAXIMIZED 最大化窗口,并將其激活 

            SW_SHOWMINIMIZED 最小化窗口,并將其激活 

            SW_SHOWMINNOACTIVE 最小化一個(gè)窗口,同時(shí)不改變活動(dòng)窗口 

            SW_SHOWNA 用當(dāng)前的大小和位置顯示一個(gè)窗口,不改變活動(dòng)窗口 

            SW_SHOWNOACTIVATE 用最近的大小和位置顯示一個(gè)窗口,同時(shí)不改變活動(dòng)窗口 

            SW_SHOWNORMAL 與SW_RESTORE相同
            posted @ 2008-04-26 15:46 wrh 閱讀(1217) | 評(píng)論 (0)編輯 收藏
            如果你是一個(gè)使用VB編程的程序員,要在程序中顯示JPG或者GIF圖像簡(jiǎn)直易如反掌,將圖像控件拖到Form中,分分鐘即可搞掂。但是C++程序員要顯示同樣的圖形卻沒(méi)有那么輕松,那么是不是要自己編寫JPG解壓縮代碼呢?當(dāng)然不用那么復(fù)雜啦!本文將針對(duì)這個(gè)問(wèn)題討論如何在MFC中顯示JPG或者GIF圖像。
                用VB寫圖像顯示程序之所以如此輕松,完全是利用了琳瑯滿目的圖像處理控件,把你想要做的事情都一一搞掂。而C++程序員為了實(shí)現(xiàn)相同的功能必須忙乎半天。其實(shí),C/C++程序員也能使用那些VB程序員所用的(或者說(shuō)幾乎一樣的)圖像控件。VB用的圖像控件實(shí)際上都基于一個(gè)系統(tǒng)級(jí)COM類——IPicture。下面是有關(guān) IPicture 的方法描述:
            方法 描述
            get_Handle  返回圖像對(duì)象的Windows GDI句柄 
            get_Hpal  返回圖像對(duì)象當(dāng)前使用的調(diào)色板拷貝
            get_Type 返回當(dāng)前圖像對(duì)象的的圖像類型
            get_Width  返回當(dāng)前圖像對(duì)象的圖像寬度
            get_Height  返回當(dāng)前圖像對(duì)象的圖像高度
            Render  在指定的位置、指定的設(shè)備上下文上繪制指定的圖像部分
            set_Hpal  設(shè)置當(dāng)前圖像的調(diào)色板
            get_CurDC  返回當(dāng)前選中這個(gè)圖像的設(shè)備上下文
            SelectPicture  將一個(gè)位圖圖像選入給定的設(shè)備上下文,返回選中圖像的設(shè)備上下文和圖像的GDI句柄
            get_KeepOriginalForma  返回圖像對(duì)象KeepOriginalFormat 屬性的當(dāng)前值
            put_KeepOriginalFormat  設(shè)置圖像對(duì)象的KeepOriginalFormat 屬性
            PictureChanged  通知圖像對(duì)象它的圖像資源改變了
            SaveAsFile  將圖像數(shù)據(jù)存儲(chǔ)到流中,格式與存成文件格式相同
            get_Attributes  返回圖像位屬性當(dāng)前的設(shè)置

                從上面這個(gè)表可以看出,IPicture操縱著圖像對(duì)象及其屬性。圖像對(duì)象提供對(duì)位圖的抽象,而Windows負(fù)責(zé)BMP、JPG和GIF位圖的標(biāo)準(zhǔn)實(shí)現(xiàn)。程序員要做的只是實(shí)例化IPicture,然后調(diào)用其Render函數(shù)。與通常使用接口的方式不同,這里實(shí)例的創(chuàng)建我們不用CoCreateInstance函數(shù),而是用一個(gè)專門的函數(shù)OleLoadPicture。

            IStream* pstm = // 需要一個(gè)流(stream)
            IPicture* pIPicture;
            hr = OleLoadPicture(pstm, 0, FALSE, IID_IPicture, (void**)&pIPicture);      
            OleLoadPicture從流中加載圖像并創(chuàng)建一個(gè)可用來(lái)顯示圖像的新IPicture對(duì)象。
            rc = // 顯示圖像的矩形
            // 將rc 轉(zhuǎn)換為 HIMETRIC
            spIPicture->Render(pDC, rc);      
                IPicture 負(fù)責(zé)處理所有瑣事,以便確定圖形之格式,如 Windows 位圖、JPEG或者GIF文件——甚至是圖標(biāo)和元文件(metafiles)。當(dāng)然啦,所有這些的實(shí)現(xiàn)細(xì)節(jié)是需要技巧的,為此我寫了一個(gè)Demo程序Myimgapp(如圖二)來(lái)示范這些IPicture的使用方法。


            圖一 Myimgapp的運(yùn)行畫面

                Myimgapp是個(gè)典型的MFC文檔/視圖程序,在編寫這個(gè)程序之前,我首先對(duì) IPicture COM接口進(jìn)行封裝,之所以要這么做,主要是考慮到并不是每一個(gè)程序員都能熟練運(yùn)用COM接口進(jìn)行編程,另外將IPicture的主要功能封裝在C++類中可以使我們的問(wèn)題更容易解決,我封裝的這個(gè)C++類名字叫做CPicture。它的定義和實(shí)現(xiàn)細(xì)節(jié)請(qǐng)參考本文提供的源代碼。
                我在這個(gè)類中將復(fù)雜而陌生的COM風(fēng)格的參數(shù)映射成MFC程序員更為熟悉的類型。例如,CPicture可以讓你直接從文件名加載一幅圖像,CFile或者CArchive,而不用去處理流,CPicture::Render替你完成了IPicture中所有令人討厭的但又是必須的HIMETRIC平滑轉(zhuǎn)換工作。CPicture甚至具備了一個(gè)Load函數(shù),它可以從資源數(shù)據(jù)中加載圖像,所以你只要用下面的代碼就可以顯示資源中的圖像:
               CPicture pic(ID_MYPIC); // 加載圖像
            CRect rc(0,0,0,0);      // 使用缺省的rc
            pic.Render(pDC, rc);    // 顯示圖像      
            CPicture::Render提供一個(gè)顯示圖片的矩形。IPicture 對(duì)圖像進(jìn)行延伸處理。如果傳遞一個(gè)空矩形,則CPicture用圖像本身的大小--不進(jìn)行延伸處理。對(duì)于圖像本身而言,CPicture查找"IMAGE"類型的資源,所以在資源文件中你必須要加入下面的代碼:
               IDR_MYPIC IMAGE MOVEABLE PURE "res\\MyPic.jpg"      
                CPicture是個(gè)很棒的傻瓜類,它具備一個(gè) ATL 智能指針CComQIPtr指向IPicture接口,通過(guò)調(diào)用OleLoadPicture來(lái)初始化不同的Load函數(shù)。CPicture提供了常用的打包函數(shù)來(lái)調(diào)用底層的IPicture。CPicture只封裝了那些在Demo例子程序中要用到的方法。如果你需要調(diào)用IPicture::get_Handle或其它一些很少用到的IPicture方法,你可以自己嘗試編寫相應(yīng)的打包代碼。 另外,在編寫完CPicture之后,我發(fā)現(xiàn)了一個(gè)現(xiàn)成的MFC類——CPictureHolder,這個(gè)類的功能幾乎與CPicture完全一樣,你可以在afxctl.h文件中找到它的定義。 前面說(shuō)過(guò),Demo例子是個(gè)典型的MFC文檔/視圖應(yīng)用程序,因此它肯定少不了與文檔和視圖類相對(duì)應(yīng)的CPictureDoc 和CPictureView:
            CPictureDoc類沒(méi)有什么特別的處理代碼,它用CPicture對(duì)象存儲(chǔ)圖像:
            class CPictureDoc : public CDocument {
            protected:
            CPicture m_pict; // the picture
            };      
            并且CPictureDoc::Serialize 調(diào)用CPicture::Load 從MFC存檔的數(shù)據(jù)中讀取圖像。
            void CPictureDoc::Serialize(CArchive& ar)
            {
            if (ar.IsLoading()) {
            m_pict.Load(ar);
            }
            }      
            為了使Myimgapp程序更實(shí)用,CPictureDoc::OnNewDocument從程序資源數(shù)據(jù)加載了一幅圖像。為了顯示這幅圖像,CPictureView::OnDraw要調(diào)用CPicture::Render。這樣程序一啟動(dòng)便會(huì)顯示一幅默認(rèn)的圖像。
            void CPictureView::OnDraw(CDC* pDC)
            {
            CPictureDoc* pDoc = GetDocument();
            CPicture* ppic = pDoc->GetPicture();
            CRect rc;
            GetImageRect(rc);
            ppic->Render(pDC,rc);
            }
                GetImageRect是CPictureView類的一個(gè)成員函數(shù),作用是根據(jù)當(dāng)前Myimgapp的縮放比率(可用25%、33%、50%、75%、100%或自適應(yīng)方式)獲取圖像矩形。GetImageRect調(diào)用CPicture::GetImageSize來(lái)獲得真正的圖像大小,然后根據(jù)比率顯示。 CPictureView其余的部分完全和CScrollView的做法差不多,初始化視圖并設(shè)置滾動(dòng)大小,處理命令等等。唯一讓人操心的是IPicture::Render中HIMETRIC的處理問(wèn)題,因?yàn)闃?biāo)準(zhǔn)的MFC應(yīng)用程序都使用MM_TEXT映射模型。不用擔(dān)心,CPicture::Render和CPicture::GetImageSize會(huì)將這一切轉(zhuǎn)換過(guò)來(lái),所以你不必為這些事情傷神。 CPictureView有一個(gè)消息處理器值得一提:它就是OnEraseBkgnd,當(dāng)要顯示的圖像比客戶區(qū)小的時(shí)候,這個(gè)函數(shù)必須繪制空白區(qū)域,如圖二,OnEraseBkgnd創(chuàng)建一個(gè)與圖像大小相等的切邊(clip)矩形,然后將客戶區(qū)填成黑色。之所以要?jiǎng)?chuàng)建切邊矩形,主要是避免當(dāng)改變窗口大小時(shí)出現(xiàn)的抖動(dòng)——FillRect不繪制切邊矩形內(nèi)的區(qū)域,此乃Windows圖形處理的常識(shí)。


            圖二 OnEraseBkgnd 填充修剪的圖像

                IPicture/CPicture簡(jiǎn)化了圖像的顯示。它甚至可以實(shí)現(xiàn)調(diào)色板的識(shí)別這樣復(fù)雜的處理。你完全可以拋開老式DIB 圖像繪制方法,如加載調(diào)色板、BitBlts、StretchBlts等等——這一切IPicture全都可以搞掂。如果你未曾用IPicture顯示過(guò)圖像,那么現(xiàn)在試試吧。 CPictureView完成圖像瀏覽的任務(wù)看來(lái)不是什么難事了。但是如果要把一幅圖像添加到一個(gè)對(duì)話框或者其它的什么窗口中怎么辦呢?為此我創(chuàng)建了另外一個(gè)類——CPictureCtrl。
            CPictureCtrl 使你可以在任何對(duì)話框或窗口中把圖像作為子窗口顯示。例如:
            class CAboutDialog : public CDialog {
            protected:
            CPictureCtrl m_wndPict;
            virtual BOOL OnInitDialog();
            };
            BOOL CAboutDialog::OnInitDialog()
            {
            m_wndPict.SubclassDlgItem(IDC_MYIMAGE,this);
            return CDialog::OnInitDialog();
            }      
                假設(shè)你的對(duì)話框中有一個(gè)靜態(tài)控制,它的ID=IDC_IMAGE,并且有一幅IMAGE資源的ID與之相同。則從CStaticLink派生出的CPictureCtrl還可以指定一個(gè)URL超鏈接(或者創(chuàng)建一個(gè)ID與此控制或圖像的ID相同的串資源)。如果你指定了一個(gè)URL,則在圖像上單擊鼠標(biāo)將啟動(dòng)默認(rèn)瀏覽器訪問(wèn)URL。真是酷呆了。CPicture控制著CPicture對(duì)象并改寫WM_PAINT消息處理例程,調(diào)用CPicture::Render代替通常的靜態(tài)控制處理例程。處理細(xì)節(jié)請(qǐng)參見代碼。打開Myimgapp程序的“關(guān)于”對(duì)話框就知道了。
            posted @ 2008-04-26 11:10 wrh 閱讀(1203) | 評(píng)論 (0)編輯 收藏
            很多程序員都喜歡讓自己的代碼運(yùn)行效果與眾不同。Windows系統(tǒng)的應(yīng)用程序打開某個(gè)文件一般使用的都是默認(rèn)的CFileDialog。但是這個(gè)默認(rèn)的CFileDialog往往滿足不了用戶的要求。我就碰到一個(gè)這樣的用戶,他的要求如下:
            • 1、在默認(rèn)的CFileDialog對(duì)話框中加一個(gè)預(yù)覽窗格,以便在選中ASCII文件時(shí)能看到所選文件的內(nèi)容,也就是用*.txt作為文件過(guò)濾條件。
            • 2、在默認(rèn)的CFileDialog對(duì)話框中加一個(gè)"全部"按鈕來(lái)選擇某個(gè)目錄中所有的.txt文件。
            • 3、如果選擇的目錄中沒(méi)有.txt文件時(shí),要將"全部"按鈕disable,也就是置灰這個(gè)按鈕。
               實(shí)現(xiàn)上面這些需求必須要改裝CFileDialog對(duì)話框。當(dāng)最后寫完程序時(shí),功能到是全都實(shí)現(xiàn)了,但在Windows 2000環(huán)境測(cè)試中,用戶發(fā)現(xiàn)了這樣一個(gè)問(wèn)題:如果先選中某個(gè)文件,然后再去選某個(gè)文件夾,預(yù)覽窗格仍然顯示的那個(gè)文件的內(nèi)容。盡管在OnFileNameChange中對(duì)CDN_SELCHANGE進(jìn)行了處理,為了獲取所選的文件/路徑名,也調(diào)用了CFileDialog::GetPathName。但是即使是選中了文件夾,GetPathName仍然返回的是文件的名字。即便嘗試用其它的通知消息和函數(shù),比如 CDN_FOLDERCHANGE 和 GetFileName,但仍舊存在同樣的問(wèn)題。必須承認(rèn)在Windows 2000中,CFileDialog是個(gè)不完美的對(duì)話框,確實(shí)存在上述問(wèn)題。正是有這些不完美,程序員們才忙得個(gè)不亦樂(lè)乎......那么到底如何判斷用戶選中的是文件還是文件夾呢?下面就讓我們從用戶需求開始,一個(gè)一個(gè)解決所碰到的問(wèn)題。
                首先簡(jiǎn)單介紹下本文引入的三個(gè)輔助類:CFileDialogHook;CFileDialogOwnerHook和CFileDlgHelper,這三個(gè)類很簡(jiǎn)單,其功能分別是:子類化文件對(duì)話框;子類化文件對(duì)話框的父窗口或宿主窗口,這兩個(gè)類只在CFileDlgHelper類中使用,一些重要的處理都在CFileDlgHelper中。它的使用方法很簡(jiǎn)單,實(shí)例化CFileDlgHelper以后調(diào)用Init即可。
            class CMyOpenDlg ... {
            protected:
            CFileDlgHelper m_dlghelper;//實(shí)例化
            };
            BOOL CMyOpenDlg::OnInitDialog()
            {
            m_dlghelper.Init(this)//初始化
            ……
            }     
                初始化CFileDlgHelper以后,便可以用它來(lái)獲取列表控制以及判斷選項(xiàng)是否有文件夾屬性,例如:
            CListCtrl* plc = m_dlghelper.GetListCtrl();
            POSITION pos = plc->GetFirstSelectedItemPosition();
            while (pos) {
            int i = plc->GetNextSelectedItem(pos);
            if (fdh.IsItemFolder(i)) {
            // 顯示"(FOLDER)"……
            } else {
            // 顯示其它內(nèi)容
            }
            }

                毫無(wú)疑問(wèn),要改裝CFileDialog對(duì)話框,必須建立一個(gè)它的派生類以及一個(gè)新的對(duì)話框資源。“全部”按鈕的實(shí)現(xiàn)代碼是這樣的:

            void CMyOpenDlg::OnSelectAll()
            {
            CListCtrl* plc = m_dlghelper.GetListCtrl();
            for (int i=0; i<plc->GetItemCount(); i++) {
            CString fn = plc->GetItemText(i,0);
            if (IsTextFileName(fn)) {
            plc->SetItemState(i,LVIS_SELECTED,
            LVIS_SELECTED);
            }
            }
            plc->SetFocus();
            }
                當(dāng)所選目錄中沒(méi)有.txt文件時(shí),要disable“全部”按鈕的處理稍微麻煩一些,要用到ON_UPDATE_COMMAND_UI消息。回顧一下MFC有關(guān)UI更新的基本方法,通常是在主消息循環(huán)處于空閑狀態(tài)時(shí)候——也就是說(shuō)在消息隊(duì)列中沒(méi)有待處理的消息。但對(duì)話框則有所不同,尤其是運(yùn)行模式對(duì)話框時(shí),MFC啟動(dòng)另外一個(gè)消息循環(huán)。當(dāng)沒(méi)有消息等待處理的時(shí)候,CWnd::DoModal向?qū)υ捒虬l(fā)送一個(gè)WM_KICKIDLE消息。所以要想讓對(duì)話框處理UI,常用的方式是這樣的:
            LRESULT CMyDialog::OnKickIdle(WPARAM wp, LPARAM lp)
            {
            UpdateDialogControls(this, TRUE);
            return 0;
            }      
                CWnd::UpdateDialogControls將神奇的CN_UPDATE_COMMAND_UI消息發(fā)送到對(duì)話框,觸發(fā)ON_UPDATE_COMMAND_UI處理例程??上н@個(gè)方法對(duì)CFileDialog對(duì)話框不靈。原因是CFileDialog重寫了DoModal,它不會(huì)以正常方式運(yùn)行某個(gè)消息循環(huán),而是調(diào)用::GetOpenFileName (或::GetSaveFileName)。這些API函數(shù)都有自己消息循環(huán),并且你無(wú)法鉆進(jìn)去進(jìn)行消息空閑處理。無(wú)論什么時(shí)候,每當(dāng)模式對(duì)話框處于等待消息狀態(tài)時(shí),對(duì)話框發(fā)送自己的WM_ENTERIDLE消息。從這里進(jìn)去才可以處理UI更新事宜。但有幾個(gè)細(xì)節(jié)需要注意。首先,Windows只發(fā)送WM_ENTERIDLE消息到對(duì)話框的所有者——此處為主框架——所以必須在那里捕獲這個(gè)消息。然后,只要對(duì)話框仍然處于空閑狀態(tài),則Windows繼續(xù)發(fā)送WM_ENTERIDLE,但只需要調(diào)用UpdateDialogControls一次,此間可以進(jìn)行常規(guī)的標(biāo)志設(shè)置。那到底什么時(shí)候設(shè)置標(biāo)志呢?無(wú)論何時(shí),UI狀態(tài)的改變,都是在對(duì)話框獲得到WM_COMMAND 或 WM_NOTIFY消息之后。所以還必須在CFileDialog派生的對(duì)話框中截獲這些消息。 因?yàn)檫@些都是一些繁瑣的細(xì)節(jié),所以最好將它們封裝到在一個(gè)新類中,這就是CFileDlgHelper的來(lái)由。只要從CFileDialog派生的對(duì)話框OnInitDialog函數(shù)中調(diào)用CFileDlgHelper的Init,便不用操心ON_UPDATE_COMMAND_UI的處理細(xì)節(jié)。CFileDlgHelper是如何實(shí)現(xiàn)的呢?告訴你吧,利用萬(wàn)能類CSubclassWnd,這個(gè)類可以用Windows的方式子類化任何窗口,通過(guò)在某個(gè)窗口過(guò)程之前安裝一個(gè)新的窗口過(guò)程來(lái)實(shí)現(xiàn)消息的捕獲。實(shí)際上,CFileDlgHelper 用了兩個(gè)CSubclassWnds派生類:一個(gè)用來(lái)截獲發(fā)送到對(duì)話框父窗口的WM_ENTERIDLE消息,另一個(gè)用來(lái)截獲發(fā)送到對(duì)話框本身的WM_COMMAND 或 WM_NOTIFY。當(dāng)主窗口得到WM_ENTERIDLE消息時(shí),CFileDialogOwnerHook解釋它并更新對(duì)話框控制:
            LRESULT CFileDialogOwnerHook::WindowProc(...)
            {
            if (msg==WM_ENTERIDLE) {
            if (m_pHelper->m_bUpdateUI) {
            m_pDlg->UpdateDialogControls(m_pDlg, FALSE);
            m_pHelper->m_bUpdateUI=FALSE;
            }
            }
            return CSubclassWnd::WindowProc(msg, wp, lp);
            }
            當(dāng)對(duì)話框得到WM_NOTIFY 或者WM_COMMAND消息時(shí),CFileDialogHook重置標(biāo)志。
            LRESULT CFileDialogHook::WindowProc(UINT msg, WPARAM wp, LPARAM lp)
            {
            if (msg==WM_COMMAND || msg==WM_NOTIFY) {
            m_pHelper->m_bUpdateUI = TRUE;
            }
            return CSubclassWnd::WindowProc(msg, wp, lp);
            }     
            一旦知道了其中的奧秘,一切就這么簡(jiǎn)單。注意從CSubclassWnd派生了兩個(gè)類——CFileDialogOwnerHook和CFileDialogHook,一個(gè)用來(lái)對(duì)付主框架,另一個(gè)用來(lái)對(duì)付對(duì)話框本身,它們都在隱含在CFileDlgHelper類中。有了它,“按鈕”的UI更新就會(huì)象你所期望的那樣:
            void CMyOpenDlg::OnUpdateSelectAll(CCmdUI* pCmdUI)
            {
            CFileDlgHelper& fdh = m_dlghelper;
            CListCtrl* plc = fdh.GetListCtrl();
            for (int i=0; i<plc->GetItemCount(); i++) {
            if (IsTextFileName(fdh.GetItemName(i))) {
            pCmdUI->Enable(TRUE);
            return;
            }
            }
            pCmdUI->Enable(FALSE);
            }      
               以上是用戶需求的實(shí)現(xiàn),下面來(lái)解決Window 2000環(huán)境測(cè)試出現(xiàn)的問(wèn)題:如何確定在列表框中選擇的是文件還是文件夾。
                要想解決這個(gè)問(wèn)題,就必須關(guān)注對(duì)話框中的列表控制(ListCtrl/ListView),許多普通的對(duì)話框里的控制都有明確的IDs,如靜態(tài)文本控制有stc1,以及列表框有l(wèi)st1,這些符號(hào)都定義在文件中。你可以把列表控制看成是lst1,但用Spy++察看后,如圖一所示:


            圖一 Spy++

            你會(huì)發(fā)現(xiàn)列表控制實(shí)際上被包含在另一個(gè)窗口類SHELLDLL_DefView中。SHELLDLL_DefView窗口的ID為lst2,其項(xiàng)下的列表控制(SysListView32)的子ID為1。所以,為了要得到這個(gè)列表控制,可以這樣編碼:

            // 在自己的CFileDialog 派生類中
            CListCtrl* plc = (CListCtrl*)GetParent()->GetDlgItem(lst2)->GetDlgItem(1);      
                記住,在定制CFileDialog時(shí),它實(shí)際上是一個(gè)實(shí)際對(duì)話框的子對(duì)話框,這就是必須用GetParent的原因。更多的細(xì)節(jié)請(qǐng)參考MSDN中的相關(guān)文章。強(qiáng)制類型轉(zhuǎn)換 CListCtrl* 與每一個(gè)常見的MFC訣竅一樣,因?yàn)镃ListCtrl既沒(méi)有數(shù)據(jù)成員也沒(méi)有虛擬函數(shù)成員,它是一個(gè)純粹的包裝類(因?yàn)镚etDlgItem返回一個(gè)臨時(shí)的CWnd指針,而不是CListCtrl,每次碰到這種情況,常常都會(huì)讓人感到沮喪,其實(shí)這很正常)。 一旦你有了列表控制的指針,便可以做任何想做事情——例如獲取選中的路徑名,調(diào)用CListCtrl::GetItemText并添加結(jié)果到當(dāng)前打開的文件夾(GetFolderPath/CDM_GETFOLDERPATH)。有了路徑名,如何知道它到底時(shí)文件還是文件夾呢?方法如下:
            #include 
            // 檢查路徑名是不是文件夾
            static BOOL IsFolder(LPCTSTR pathname)
            {
            struct stat st;
            return stat(pathname, &st)==0 && (st.st_mode & _S_IFDIR);
            }
                這里需要注意的是:不管怎樣,如果路徑名不是文件夾,你也不能因此就斷定它就是一個(gè)文件!因?yàn)樗€可能是其它的外殼對(duì)象,如"網(wǎng)上鄰居"或者"我的電腦"之類的東西。 詳細(xì)做法可以參考本文的例子程序 OpenFileDlg,它還示范了如何建立預(yù)覽對(duì)話框。這個(gè)程序可以進(jìn)行多項(xiàng)選擇,如果只選中一個(gè).txt文件,則預(yù)覽窗格顯示文件的開始幾行。程序還帶一個(gè)調(diào)試窗口,窗口中列出選中的條目,如果選中的是文件夾,則在它的旁邊會(huì)有“FOLDER”說(shuō)明。如圖二所示。


            圖二運(yùn)行中的OpenFileDlg

                如果選中的是文件夾,則OpenFileDlg會(huì)清空預(yù)覽格,這樣就解決了本文所提出的預(yù)覽問(wèn)題。當(dāng)然,如果運(yùn)行環(huán)境是Windows XP,而非Windows 2000,那么就不會(huì)碰上這個(gè)問(wèn)題!在Windows XP中,OnFileNameChange/CDN_SELCHANGE會(huì)返回正確的文件名和文件夾名字。但仍然可以用CFileDlgHelper類獲取列表控制,選項(xiàng)名稱等。并且仍然需要IsFolder來(lái)檢查路徑名是不是文件夾。
                其實(shí),在OnSelectAll處理代碼中,IsTextFileName的功能是查找以.txt結(jié)尾文件名字。這個(gè)函數(shù)真的能實(shí)現(xiàn)這個(gè)功能嗎?其實(shí),在程序中有個(gè)致命的問(wèn)題——如果用戶定制了資源管理器來(lái)隱藏已知文件類型的擴(kuò)展名。那么,.txt就不會(huì)出現(xiàn)在列表框中。也就是說(shuō)CFileDlgHelper::GetItemName返回foo,而不是foo.txt。實(shí)際上,如果擴(kuò)展名被隱藏,那么象foo.txt、foo.jpg和foo.doc等等這樣的文件都以名字foo出現(xiàn)(試一下就知道了)。如此一來(lái),怎么知道這個(gè)foo文件到底是此foo,還是彼foo呢?問(wèn)題真是解決不完啊,搞掂這個(gè)問(wèn)題,又出那個(gè)問(wèn)題。唉,好累啊,下次再說(shuō)吧......

            posted @ 2008-04-26 08:10 wrh 閱讀(912) | 評(píng)論 (0)編輯 收藏
            使用rand函數(shù)獲得隨機(jī)數(shù)。rand函數(shù)返回的隨機(jī)數(shù)在0-RAND_MAX(32767)之間。
                例子:
                /* RAND.C: This program seeds the random-number generator
                
            * with the time, then displays 10 random integers.
                
            */
                
                
            #include <stdlib.h>
                
            #include <stdio.h>
                
            #include <time.h>
                
                
            void main( void )
                
            {
                
            int i;
                
                
            /* Seed the random-number generator with current time so that
                
            * the numbers will be different every time we run.
                
            */
                
            srand( (unsigned)time( NULL ) );
                
                
            /* Display 10 numbers. */
                
            for( i = 0; i < 10;i++ )
                
            printf( " %6d\n", rand() );
                
            }
                
                

                在調(diào)用這個(gè)函數(shù)前,最好先調(diào)用srand函數(shù),如srand( (unsigned)time( NULL ) ),這樣可以每次產(chǎn)生的隨機(jī)數(shù)序列不同。
                如果要實(shí)現(xiàn)類似0-1之間的函數(shù),可以如下:
                double randf()
                
            {
                
            return (double)(rand()/(double)RAND_MAX);
                
            }
                
                

                如果要實(shí)現(xiàn)類似Turbo C的random函數(shù),可以如下:
                int random(int number)
                
            {
                
            return (int)(number/(float)RAND_MAX * rand());
                
            }
            posted @ 2008-04-15 13:56 wrh 閱讀(1669) | 評(píng)論 (0)編輯 收藏

            1.檢測(cè)程序中的括號(hào)是否匹配
            把光標(biāo)移動(dòng)到需要檢測(cè)的括號(hào)(如大括號(hào){}、方括號(hào)[]、圓括號(hào)()和尖括號(hào)<>)前面,鍵入快捷鍵“Ctrl+]”。如果括號(hào)匹配正確,光標(biāo)就跳到匹配的括號(hào)處,否則光標(biāo)不移動(dòng),并且機(jī)箱喇叭還會(huì)發(fā)出一聲警告聲。

            bbs.bitsCN.com

             

            2.查看一個(gè)宏(或變量、函數(shù))的宏定義
            把光標(biāo)移動(dòng)到你想知道的一個(gè)宏上,就比如說(shuō)最常見的DECLARE_MAP_MESSAGE上按一下F12(或右鍵菜單中的Go To Defition Of …),如果沒(méi)有建立Browse files,會(huì)出現(xiàn)提示對(duì)話框,確定,然后就會(huì)跳到定義那些東西的地方。
            相當(dāng)可喜的是,它也可以看到Microsoft定義的系統(tǒng)宏,非常good.

            BBS.bitsCN.com網(wǎng)管論壇


            3.格式化一段亂七八糟的源代碼
            選中那段源代碼,按ATL+F8。 [bitsCN_com]


            4.在編輯狀態(tài)下發(fā)現(xiàn)成員變量或函數(shù)不能顯示
            刪除該項(xiàng)目擴(kuò)展名為.ncb文件,重新打開該項(xiàng)目。 bitsCN.nET*中國(guó)網(wǎng)管博客


            5.如何整理ClassView視圖中大量的類
            可以在classview 視圖中右鍵新建文件夾(new folder),再把具有相近性質(zhì)的類拖到對(duì)應(yīng)的文件夾中,使整個(gè)視圖看上去清晰明了. bbs.bitsCN.com


            6.定位預(yù)處理指定
            在源文件中定位光標(biāo)到對(duì)稱的#if, #endif,使用Ctrl+K.

            bbs.bitsCN.com中國(guó)網(wǎng)管論壇

             

            7.如何添加系統(tǒng)中Lib到當(dāng)前項(xiàng)目
            在Project | Settings | Link | Object/library modules:輸入Lib名稱,不同的Lib之間用空格格開. bbs.bitsCN.com


            8.如何添加系統(tǒng)中的頭文件(.h)到當(dāng)前項(xiàng)目.
            #include <FileName.h>,告訴編譯到VC系統(tǒng)目錄去找;使用#include "FileName.h",告訴編譯在當(dāng)前
            目錄找.

            bbs.bitsCN.com

             

            9.如何在Studio使用匯編調(diào)試
            在WorkBench的Debugger狀態(tài)下按CTRL+F7. www@bitscn@com


            10.怎樣處理ClassZiard找不到的系統(tǒng)消息
            如果要在ClassWizard中處理WM_NCHITTEST等系統(tǒng)消息,請(qǐng)?jiān)贑lassWizard中Class Info頁(yè)中將
            Message filter改為Window就有了.

            bitsCN~com


            11.如何干凈的刪除一個(gè)類
            先從Workspace中的FileView中刪除對(duì)應(yīng)的.h和.cpp文件,再關(guān)閉項(xiàng)目,從實(shí)際的文件夾中刪除對(duì)應(yīng)的.h和.cpp文件與.clw文件。

            bbs.bitsCN.com中國(guó)網(wǎng)管論壇


            12.在Studio中快速切換兩個(gè)文件
            有時(shí),我們需要在最近使用的兩個(gè)文件中快速切換,換Ctrl+F6。這在兩個(gè)文件不相今的時(shí)候就有用的. bitsCN.nET*中國(guó)網(wǎng)管博客

            13.取得源程序預(yù)處理后的結(jié)果:
            在Studio里,可以在->PROJECT->SETTINGS->C/C++->Project Options中,在最后加上 /P /EP這兩個(gè)編譯開關(guān)即可做到"只進(jìn)行預(yù)處理".就可以了。編譯以后就可以在源程序目錄中發(fā)現(xiàn)“文件名.I ”的文本文件。這就是預(yù)處理后的結(jié)果。
            (注意注:區(qū)分大小定,請(qǐng)用大定/P)

            [bitsCN.Com]


            14.在Debug模式中查看WINAPI調(diào)用后的返回值:
            很簡(jiǎn)單,且實(shí)用:在watch中加入@hr,err。在CSDN的文檔中心有一篇講得更細(xì),請(qǐng)參考。

            www@bitscn@com


            15.產(chǎn)生指定源程序文件的匯編代碼:
            從IDE菜單的Project->Setting打開項(xiàng)目設(shè)置,按如下文件做:
            1.先在左邊選擇指定文件,可以多選。
            2. 在右邊的C++屬性頁(yè)中,在category中選擇List Files,接著在下面的List Files Type中選擇Assembly and source code(或選擇其它),最后在List File Name中輸入在個(gè)C/C++源文件產(chǎn)生的相應(yīng)的匯編代碼的文件。
            3.編譯整個(gè)工程。

            DL@bitsCN_com網(wǎng)管軟件下載

             

            16.手工編譯純資源成dll:
            Rc.exe /v data.rc
            Cvtres.exe /machine:ix86 data.res
            Link /SUBSYSTEM:WINDOWS /DLL /NOENTRY data.res ;編譯成DLL文件
            這種方式創(chuàng)建的DLL是最小的,比起你用Win 32 Dynamic Libray等產(chǎn)生的更小。 [bitsCN.Com]

            17:怎樣快速生成一個(gè)與現(xiàn)有項(xiàng)目除了項(xiàng)目名外完全相同的新項(xiàng)目? bitsCN.nET*中國(guó)網(wǎng)管博客

            利用File菜單下生成新項(xiàng)目中的Custom AppWizard ,選擇 An existing Project ,然后選擇現(xiàn)有項(xiàng)目的項(xiàng)目文件名(*.dsp)Finish,編譯后就生成一個(gè)可以生成與現(xiàn)有項(xiàng)目相同但可以重新取名的項(xiàng)目的AppWizard。你可以象用MFC AppWizard一樣用它。如果不想用了,可以在VC 安裝目錄下Common\MSDev98\Template目錄中刪除該Wizard中.awx和 .pdb文件。    bbs.bitsCN.com

            18:如果想把整個(gè)項(xiàng)目拷貝到軟盤,那些文件可以刪掉?   bbs.bitsCN.com

              除了項(xiàng)目文件夾中debug文件夾可以刪除外,.ncb,.clw,.opt 等文件也可以刪除,這些文件Rebuilt all后可以重新生成。   

            19.如果讓控制臺(tái)應(yīng)用程序支持mfc類庫(kù)
                可以在控制臺(tái)應(yīng)用程序中include 來(lái)引入mfc庫(kù),但是控制臺(tái)應(yīng)用程序缺省是單線程的,mfc是多線程的,為解決該矛盾,在project setting->c/c++ 選項(xiàng),選擇code generation,在use run-time library 下拉框中選擇debug multithread。
             
            20.如何漢化只有可執(zhí)行代碼的.exe 文件
                在nt下利用vc open file 以resources方式打開*.exe 文件,直接修改資源文件,然后保存即可。
            [注:我一般是用exescope編輯的]
             


            附:VC項(xiàng)目文件說(shuō)明
            .dsp 項(xiàng)目參數(shù)配置文件,這個(gè)文件太重要,重點(diǎn)保護(hù)對(duì)象。.
            .dsw 工作區(qū)文件,重要性一般,因?yàn)樗畔⒉晃遥菀谆謴?fù)。
            以下文件在項(xiàng)目中是可丟棄的,有些文件刪除后,VC會(huì)自動(dòng)生成的。
            .clw ClassWizard信息文件,實(shí)際上是INI文件的格式,有興趣可以研究一下.有時(shí)候ClassWizard出問(wèn)題,手工修改CLW文件可以解決.如果此文件不存在的話,每次用ClassWizard的時(shí)候繪提示你是否重建.
            .ncb 無(wú)編譯瀏覽文件(no compile browser)。當(dāng)自動(dòng)完成功能出問(wèn)題時(shí)可以刪除此文件。build后會(huì)自動(dòng)生成。
            .opt 工程關(guān)于開發(fā)環(huán)境的參數(shù)文件。如工具條位置等信息;(可丟棄)
            .aps (AppStudio File),資源輔助文件,二進(jìn)制格式,一般不用去管他.
            .plg 是編譯信息文件,編譯時(shí)的error和warning信息文件(實(shí)際上是一個(gè)html文件),一般用處不大.在Tools->Options里面有個(gè)選項(xiàng)可以控制這個(gè)文件的生成.
            .hpj (Help Project)是生成幫助文件的工程,用microsfot Help Compiler可以處理.
            .mdp (Microsoft DevStudio Project)是舊版本的項(xiàng)目文件,如果要打開此文件的話,會(huì)提示你是否轉(zhuǎn)換成新的DSP格式.
            .bsc 是用于瀏覽項(xiàng)目信息的,如果用Source Brower的話就必須有這個(gè)文件.如果不用這個(gè)功能的話,可以在Project Options里面去掉Generate Browse Info File,可以加快編譯速度. bitsCN.nET*中國(guó)網(wǎng)管博客
            .map 是執(zhí)行文件的映像信息紀(jì)錄文件,除非對(duì)系統(tǒng)底層非常熟悉,這個(gè)文件一般用不著.
            .pch (Pre-Compiled File)是預(yù)編譯文件,可以加快編譯速度,但是文件非常大.
            .pdb (Program Database)記錄了程序有關(guān)的一些數(shù)據(jù)和調(diào)試信息,在調(diào)試的時(shí)候可能有用.
            .exp 只有在編譯DLL的時(shí)候才會(huì)生成,記錄了DLL文件中的一些信息.一般也沒(méi)什么用.

            posted @ 2008-04-13 19:31 wrh 閱讀(243) | 評(píng)論 (0)編輯 收藏
            如何干凈的刪除一個(gè)類?
            1、先刪除項(xiàng)目中對(duì)應(yīng)的.h.cpp文件,(選中后用Delete鍵刪除)
            2
            、保存后退出項(xiàng)目,到文件夾中刪除實(shí)際的.h.cpp文件;
            3
            、刪除.clw文件;
            4
            、重新進(jìn)入項(xiàng)目,進(jìn)行全部重建(rebuild all)。

            如何建立一個(gè)新類?
                
            插入”(Insert)菜單中選擇新建類”(New Class),在彈出的對(duì)話框中選擇基類(Base class),在Name中輸入新類的名字(一般都以C開頭)即可。
            如果想要建立一個(gè)沒(méi)有基類的自定義類,則在New Class對(duì)話框中把Class type設(shè)置為generic,再輸入類名即可。

            如何把外來(lái)文件添加到項(xiàng)目中?
                
            先把外來(lái)文件復(fù)制到當(dāng)前項(xiàng)目的目錄下,從項(xiàng)目”(Project)菜單下選擇添加項(xiàng)目”(Add to Project)下的“Files”菜單項(xiàng),從彈出的打開文件對(duì)話框中把外來(lái)文件打開即可。

            如何在一個(gè)工作區(qū)中打開多個(gè)項(xiàng)目?
                
            一般編程者都有這樣的經(jīng)歷:做了一個(gè)項(xiàng)目,由于不滿意,想從頭重做,但又想把舊項(xiàng)目的一些可用內(nèi)容拷到新項(xiàng)目中來(lái),以免做重復(fù)工作,這時(shí)就需要在新項(xiàng)目中打開舊項(xiàng)目。
                
            先打開新項(xiàng)目,從項(xiàng)目”(Project)菜單下選擇插入項(xiàng)目到工作區(qū)”(Insert Project into Workspace),從彈出的打開文件對(duì)話框中打開舊項(xiàng)目的.asp文件即可。
                
            之后,可以利用項(xiàng)目”(Project)菜單下的設(shè)置活動(dòng)項(xiàng)目”(Select Active Project)的選項(xiàng)中切換各打開的項(xiàng)目。
            注意:在一個(gè)工作區(qū)中打開的各項(xiàng)目不能同名。

            如何把項(xiàng)目中的文件分類存放?
            當(dāng)我們往項(xiàng)目中添加新類時(shí),它會(huì)把源文件放在Source Files下,頭文件放在Header Files下。當(dāng)項(xiàng)目中文件很多時(shí),管理不便,最好添加新節(jié)點(diǎn),把文件分類放置。
            右擊項(xiàng)目節(jié)點(diǎn)樹的根節(jié)點(diǎn),選擇“New Folder...”,在彈出的對(duì)話框中填入新節(jié)點(diǎn)名,則新節(jié)點(diǎn)就建立了,用鼠標(biāo)節(jié)點(diǎn)樹中的文件拖入新節(jié)點(diǎn),就可以把文件分類了。
            以上分類只是在項(xiàng)目的節(jié)點(diǎn)樹中分類,它不影響文件在磁盤上的位置,所有.cpp文件和.h文件仍在項(xiàng)目的根目錄下,最好文件本身也能分類存放在不同文件夾中。
            Windows下,用新建文件夾在項(xiàng)目的根目錄下建立子文件夾,如DialogClass,把所有對(duì)話框類的.cpp文件和.h文件拖入其中。
            回到VC下,右鍵單擊項(xiàng)目樹中更改了路徑的節(jié)點(diǎn),選擇“Properties”,在彈出的對(duì)話框中修改文件路徑,如:把原路徑“.\Dialog1.cpp”改為“.\DialogClass\Dialog1.cpp”
            打開Dialog1.cpp文件,修改它包含的文件路徑。如:
            #include "stdafx.h"
            #include "PluckBox.h"
            #include "Dialog1.h"
            改為:
            #include "stdafx.h"
            #include "..\\PluckBox.h"
            #include "Dialog1.h"
            打開ClassWizard,它會(huì)提示你文件不存在,單擊確定后,從對(duì)話框中用“Browse...”選擇文件所在路徑,則ClassWizard也可正常使用了。



            編輯
            編輯代碼時(shí),跟隨提示消失了怎么辦?
            單 擊工具”(Tools)菜單中的設(shè)置”(Options)菜單項(xiàng),在彈出的Options對(duì)話框中選擇Editor制表頁(yè),把它最下方的四個(gè)復(fù)選框都 選中(Auto list member、Auto type infoCode comments、Auto parameter info),這樣,當(dāng)用戶輸入“->”“.”時(shí),會(huì)自動(dòng)顯示跟隨提示,減少了輸入負(fù)擔(dān)。



            對(duì)話框
            如何修改對(duì)話框的背景色
            在對(duì)話框的OnPaint()函數(shù)中加入下面語(yǔ)句:
            CRect rect;
            GetClientRect(&rect); //
            計(jì)算對(duì)話框的尺寸
            dc.FillSolidRect(&rect,RGB(192,248,202)); //
            繪制對(duì)話框背景色

            如何讓彈出式對(duì)話框具有統(tǒng)一的背景色
            在應(yīng)用程序類CxxxAppInitInstance()函數(shù)中加入下面的語(yǔ)句:
            SetDialogBkColor( RGB(192,248,202) );
            則所有用戶定義的彈出式對(duì)話框都以RGB(192,248,202)為背景色,就不需要逐個(gè)進(jìn)行設(shè)置了。


            如何讓打開文件對(duì)話框能進(jìn)行多項(xiàng)選擇
            在定制打開文件對(duì)話框時(shí),增加OFN_ALLOWMULTISELECT屬性,就可以使打開文件對(duì)話框進(jìn)行多選了。
            如:
            CFileDialog m_Dlg( TRUE, NULL, NULL, OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT
            | OFN_ALLOWMULTISELECT, NULL, NULL );
            之后,用GetStartPosition()函數(shù)獲取選擇的起始文件位置,用GetNextPathName()函數(shù)獲取各位置上的文件名。
            如:
            if( m_Dlg.DoModal() == IDOK )
            {
            POSITION pos;
            pos = m_Dlg.GetStartPosition();
            while( pos )
            {
            m_Path = m_Dlg.GetNextPathName(pos);
            …………
            }
            }

            為什么用打開文件對(duì)話框選擇多個(gè)文件到一定數(shù)目時(shí),文件沒(méi)有打開?
            CFileDialog
            為文件列表設(shè)置有緩沖區(qū),當(dāng)選擇文件過(guò)多時(shí),會(huì)造成緩沖區(qū)溢出,造成一些文件沒(méi)有被打開??梢圆捎米远x大緩沖區(qū)代替系統(tǒng)緩沖區(qū)的方法解決。
            如:
            CFileDialog m_Dlg( TRUE, NULL, NULL, OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT
            | OFN_ALLOWMULTISELECT, NULL, NULL );//
            定制打開文件對(duì)話框
            char* pBuf = new char[20480]; //
            申請(qǐng)緩沖區(qū)
            m_Dlg.m_ofn.nMaxFile = 20480; //
            pBuf代替CFileDialog緩沖區(qū)
            m_Dlg.m_ofn.lpstrFile = pBuf;
            m_Dlg.m_ofn.lpstrFile[0] = NULL;
            …………
            delete []pBuf; //
            回收緩沖區(qū)

            提示對(duì)話框(MessageBox
            在視類和對(duì)話框類中可使用MFC函數(shù)中用的MessageBox()函數(shù)彈出提示對(duì)話框。這個(gè)函數(shù)原型為:
            int MessageBox(LPCTSTR lpszText,LPCTSTR lpsCaption=NULL,UINT nType=MB_OK);
            參數(shù):lpszText 顯示的字符串
            lpsCaption
            對(duì)話框的標(biāo)題
            nType
            風(fēng)格,可為如下值的組合:
            指定下列標(biāo)志中的一個(gè)來(lái)顯示消息框中的按鈕,標(biāo)志的含義如下。
            MB_ABORTRETRYIGNORE
            :消息框含有三個(gè)按鈕:Abort,RetryIgnore
            MB_OK
            :消息框含有一個(gè)按鈕:OK。這是缺省值。
            MB_OKCANCEL
            :消息框含有兩個(gè)按鈕:OKCancel。
            MB_RETRYCANCEL
            :消息框含有兩個(gè)按鈕:RetryCancel
            MB_YESNO
            :消息框含有兩個(gè)按鈕:YesNo。
            MB_YESNOCANCEL
            :消息框含有三個(gè)按鈕:Yes,NoCancel
            指定下列標(biāo)志中的一個(gè)來(lái)顯示消息框中的圖標(biāo):標(biāo)志的含義如下。
            MB_ICONEXCLAMATION:
            MB_ICONWARNING
            :一個(gè)驚嘆號(hào)出現(xiàn)在消息框。
            MB_ICONINFORMATION

            MB_ICONASTERISK
            :一個(gè)圓圈中小寫字母i組成的圖標(biāo)出現(xiàn)在消息框。
            MB_ICONOUESTION:
            一個(gè)問(wèn)題標(biāo)記圖標(biāo)出現(xiàn)在消息框。
            MB_ICONSTOP:
            MB_ICONERROR

            MB_ICONHAND
            :一個(gè)停止消息圖標(biāo)出現(xiàn)在消息框。
            指定下列標(biāo)志中的一個(gè)來(lái)指定缺省的按鈕:標(biāo)志的含義如下。
            MB_DEFBUTTON1
            :第一個(gè)按鈕為缺省按鈕。如果MB_DEFBUTTON2,MB_DEFBUTTON3,MB_DEFBUTTON4沒(méi)有被指定,則MB_DEFBUTTON1為缺省值。
            MB_DEFBUTTON2
            ;第二個(gè)按鈕為缺省按鈕。
            MB_DEFBUTTON3
            :第三個(gè)按鈕為缺省按鈕。
            MB_DEFBUTTON4
            :第四個(gè)按鈕為缺省按鈕。
            例:提示文件是否存盤:
            int t;
            t=MessageBox(m_PathName+"
            的文字已經(jīng)改變,要存盤嗎?",
            "
            警告",MB_YESNOCANCEL | MB_ICONWARNING);
            if(t==0 || t==IDCANCEL)
            return;
            if(t==IDYES)
            OnFileSave();
            在文檔類等其它類中不能使用MFC中的MessageBox()函數(shù),只能使用API函數(shù)中的MessageBox()函數(shù):
            int MessageBox(HWND hWnd,LPCTSTR lpszText,LPCTSTR lpCaption,UINT UType);
            hWnd:
            標(biāo)識(shí)將被創(chuàng)建的消息框的擁有窗口。如果此參數(shù)為NULL,則消息框沒(méi)有擁有窗口。
            后三個(gè)參數(shù)與視類的MessageBox相同,但沒(méi)有缺省值,必須設(shè)置。
            例:::MessageBox(NULL,m_PathName+"的文字已經(jīng)改變,要存盤嗎?",
            "
            警告",MB_YESNOCANCEL | MB_ICONWARNING);



            調(diào)試
            error C2146: syntax error : missing ';' before identifier ……
            如果出現(xiàn)這個(gè)錯(cuò)誤且錯(cuò)誤數(shù)目很多,通常并不是缺失了分號(hào)引起的,而是忘記了添加某頭文件引起的。
            最常見的是新加入了對(duì)話框,然后用它的類定義了一個(gè)對(duì)象,再編譯出現(xiàn)上面的錯(cuò)誤。
            解決方法是在引用新類的文件中加入#include "類名.h",再編譯,錯(cuò)誤消失。

            fatal error C1010: unexpected end of file while looking for precompiled header directive
            在一個(gè)項(xiàng)目中,如果用“New”向工程中添加了一個(gè).cpp文件,編譯,出錯(cuò)。
            解決方法:
                               1)   在新建的.cpp文件的開頭加入#include "stdafx.h"。
                               2)   可以使用右鍵點(diǎn)擊項(xiàng)目工程中的該cpp文件,選擇setting,在c/c++欄,選擇PreCompiled headers,然后設(shè)置第一選項(xiàng),選擇不使用預(yù)編譯頭,解決這個(gè)問(wèn)題。發(fā)布
            Debug
            模式和Release模式
            早就發(fā)現(xiàn)用VC編譯出來(lái)的.exe文件比用Turbo C編譯出來(lái)的文件大了許多,于是就認(rèn)為VC編譯時(shí)一定加了很多沒(méi)用的東西,記得當(dāng)時(shí)還做過(guò)把VC自動(dòng)生成的項(xiàng)目中自認(rèn)為沒(méi)用的函數(shù)都刪掉的傻事。后來(lái)才從網(wǎng)上的文章中了解到還有編譯模式一說(shuō)。
            Debug
            模式是用來(lái)調(diào)試用的,它生成的執(zhí)行文件中含有大量調(diào)試信息,所以很大;
            Release
            模式生成的執(zhí)行文件消除了這些調(diào)試信息,可用來(lái)作為成品發(fā)布。
            默 認(rèn)情況下是Debug模式,切換方法是在編譯”(Build)菜單中選設(shè)置項(xiàng)目配置”(Set Active Configure)。從彈出的對(duì)話框中選擇Win32 Release模式,然后再重新編譯。這時(shí)在工作目錄下會(huì)多出一個(gè)Release目錄,其中的exe文件比Debug目錄下的那個(gè)要小得多。

            動(dòng)態(tài)鏈接庫(kù)和靜態(tài)鏈接庫(kù)
            VC 做好了一個(gè)程序,拿到別人那里卻不能運(yùn)行,這也是很多編程者都經(jīng)歷過(guò)的,這樣的軟件只能在安裝有VC的機(jī)器上運(yùn)行,也不應(yīng)拿出去發(fā)布。實(shí)際上如果你沒(méi)有使 用ActiveX控件和自定義的動(dòng)態(tài)DLL技術(shù),只需把MFC的動(dòng)態(tài)鏈接庫(kù)打包到你的程序里就可以了,也就是使用靜態(tài)鏈接庫(kù)。
            設(shè)置方法:從項(xiàng)目”(Project)菜單下選擇設(shè)置” (Settings),在彈出的對(duì)話框中的General選項(xiàng)卡下,把“User MFC in a Shared DLL”改為“User MFC in a Static Library”,關(guān)閉對(duì)話框后重新編譯即可。
            在靜態(tài)鏈接庫(kù)下編譯的文件比動(dòng)態(tài)鏈接庫(kù)的要大很多,不過(guò),如果使用Release模式編譯,一般也就幾百K,它就可以在沒(méi)有安裝VC的機(jī)器上運(yùn)行了。

            發(fā)布VC源代碼時(shí),哪些文件可以刪除?
            AfxGetMainWnd()->SetWindowText("文檔標(biāo)題"+" - "+"程序標(biāo)題");

            四、設(shè)置默認(rèn)按鈕:
            在定義控件變量時(shí),ClassWizard在構(gòu)造函數(shù)中會(huì)把變量初值設(shè)為-1,只需把它改為其它值即可。
            如:
            //{{AFX_DATA_INIT(CWEditView)
            m_Ridio1 = 0; //
            初始時(shí)第一個(gè)單選按鈕被選中
            m_Ridio4 = 0; //
            初始時(shí)第四個(gè)單選按鈕被選中
            //}}AFX_DATA_INIT

            旋轉(zhuǎn)控件(Spin)的使用
            當(dāng)單擊旋轉(zhuǎn)控件上的按鈕時(shí),相應(yīng)的編輯控件值會(huì)增大或減小。其設(shè)置的一般步驟為:
            一、在對(duì)話框中放入一個(gè)Spin控件和一個(gè)編輯控件作為Spin控件的伙伴窗口
            設(shè)置Spin控件屬性:Auto buddySet buddy integer、Arrow keys
            設(shè)置文本控件屬性:Number
            二、用ClassWizardSpin控件定義變量m_Spin,為編輯控件定義變量m_Edit,定義時(shí)注意要把m_Edit設(shè)置為int型。
            三、在對(duì)話框的OnInitDialog()函數(shù)中加入語(yǔ)句:
            BOOL CMyDlg::OnInitDialog()
            {
            CDialog::OnInitDialog();

            m_Spin.SetBuddy( GetDlgItem( IDC_EDIT1 ) ); //
            設(shè)置編輯控件為Spin控件的伙伴窗口
            m_Spin.SetRange( 0, 10 ); //
            設(shè)置數(shù)據(jù)范圍為0-10
            return TRUE;
            }
            四、用ClassWizard為編輯控件添加EN_CHANGE消息處理函數(shù),再加入語(yǔ)句:
            void CMyDlg::OnChangeEdit1()
            {
            m_Edit = m_Spin.GetPos(); //
            獲取Spin控件當(dāng)前值
            }

            UpdateData()
            對(duì)于可以接收數(shù)據(jù)的控件,如編輯控件來(lái)說(shuō),UpdateData()函數(shù)至關(guān)重要。當(dāng)控件內(nèi)容發(fā)生變化時(shí),對(duì)應(yīng)的控件變量的值并沒(méi)有跟著變化,同樣,當(dāng)控件變量值變化時(shí),控件內(nèi)容也不會(huì)跟著變。
            UpdateData()
            函數(shù)就是解決這個(gè)問(wèn)題的。
            UpdateData(true);
            把控件內(nèi)容裝入控件變量
            UpdateData(false);
            用控件變量的值更新控件
            如:有編輯控件IDC_EDIT1,對(duì)應(yīng)的變量為字符串m_Edit1
            1
            、修改變量值并顯示在控件中:
            m_Edit1 = _T("結(jié)果為50");
            UpdateData(false);
            2
            、讀取控件的值到變量中:
            ClassWizardIDC_EDIT1添加EN_CHANGE消息處理函數(shù),這個(gè)函數(shù)在編輯控件內(nèi)容發(fā)生變化時(shí)執(zhí)行。
            void CEditView::OnChangeEdit1()
            {
            UpdateData(true); //
            更新變量值
            }



            其它
            如何獲取程序所在的路徑
            也就是獲取你這個(gè)程序本身所在的路徑。
            在應(yīng)用程序類CxxApp的頭文件中定義一個(gè)變量CString m_exePath;用來(lái)放置程序的路徑名,在應(yīng)用程序類CxxAppInitInstance()函數(shù)中加入如下語(yǔ)句:
            TCHAR m_Path[MAX_PATH];
            GetModuleFileName( NULL, m_Path, MAX_PATH ); //
            獲取程序路徑(包括程序名)
            int i = 0, j;
            while( m_Path[i]!=0 )
            {
            if( m_Path[i]=='\\' )
            j = i;
            i++;
            }
            m_Path[j+1] = '\0';
            m_exePath.Format( "%s", m_Path ); //
            分離路徑名(去掉程序名)
            這段程序執(zhí)行后,字符串變量m_exePath中放置的就是程序所在路徑,其中不包括程序名。
            獲取程序的位置有什么用呢?
            1
            、打開與應(yīng)用程序在一起放置的數(shù)據(jù)文件:
            如果你運(yùn)行程序過(guò)程中使用過(guò)打開文件對(duì)話框打開過(guò)其它路徑下的文件,這時(shí)系統(tǒng)的默認(rèn)路徑就發(fā)生了改變,有可能使你原定的數(shù)據(jù)文件打不開了,如果采用以下方法就可以沒(méi)問(wèn)題了:
            CFile file;
            file.Open( m_exePath+"
            數(shù)據(jù)文件名", CFile::modeRead );
            2
            、放置程序運(yùn)行中的臨時(shí)文件:
            同樣,當(dāng)系統(tǒng)的默認(rèn)路徑發(fā)生改變后,程序中生成的臨時(shí)文件就會(huì)放得到處都是,成了一個(gè)個(gè)垃圾文件,采用以下方法可使臨時(shí)文件只放在程序所在路徑下:
            CFile file;
            file.Open( m_exePath+"
            臨時(shí)文件名", CFile::modeCreate | CFile::modeWrite );
            ……
            程序結(jié)束時(shí),用下面的方法刪除臨時(shí)文件:
            CFile::Remove( m_exePath+"
            臨時(shí)文件名" );

            如何在你的程序中執(zhí)行其它程序
            在自己的程序中調(diào)用其它程序的方法有好幾種,這里我介紹我用過(guò)的兩種:
            一、WinExec()函數(shù):
            一般用法:WinExec(m_PathName,SW_SHOWNORMAL);
            m_PathName
            為執(zhí)行程序的路徑名,必須為可執(zhí)行文件。
            如:WinExec("C:\\Program Files\\Internet Explorer\\iexplore.exe",SW_SHOWNORMAL);為打開IE瀏覽器

            二、ShellExecute()函數(shù):
            一般用法:ShellExecute(NULL,NULL,m_PathName,NULL,_T("c:\\temp"),SW_SHOWNORMAL);
            m_PathName
            為打開的程序路徑名;
            _T("c:\\temp")
            為工作目錄;
            WinExec()不同的是ShellExecute()函數(shù)也可以打開非可執(zhí)行文件,比如你指定的文件為.txt,結(jié)果會(huì)打開記事本裝入該文件。我用這種方法調(diào)用自己制作的幫助文件(.chm)效果很好。

            如果不使用串行化,如何在程序結(jié)束時(shí)保存文件?
            在文檔-視圖結(jié)構(gòu)中,用串行化自動(dòng)保存文件在各種VC書上都有介紹?,F(xiàn)在的問(wèn)題是我不使用串行化,而是自己動(dòng)手保存,當(dāng)點(diǎn)擊窗口的關(guān)閉按鈕時(shí),如何提示并保存文檔。
            ClassWizard在文檔類(CxxDoc)中添加函數(shù)CanCloseFrame(),再在其中加入保存文件的語(yǔ)句就可以了。
            例:
            //
            退出程序
            BOOL CEditDoc::CanCloseFrame(CFrameWnd* pFrame)
            {
            CFile file;
            if(b_Flag) //b_Flag
            為文檔修改標(biāo)志,在修改文檔時(shí)將其置為True
            {
            int t;
            t=::MessageBox(NULL,"
            文字已經(jīng)改變,要存盤嗎?","警告",
            MB_YESNOCANCEL | MB_ICONWARNING); //
            彈出提示對(duì)話框
            if(t==0 || t==IDCANCEL)
            return false;
            if(t==IDYES)
            {
            CString sFilter="Text File(*.txt)|*.txt||";
            CFileDialog m_Dlg(FALSE,"txt",NULL,OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT,(LPCTSTR)sFilter,NULL); //
            定制文件對(duì)話框
            int k=m_Dlg.DoModal(); //
            彈出文件對(duì)話框
            if(k==IDCANCEL || k==0)
            return false;
            m_PathName=m_Dlg.GetPathName(); //
            獲取選擇的文件路徑名

            file.Open(m_PathName,CFile::modeCreate | CFile::modeWrite);
            file.Write(m_Text,m_TextLen); //
            數(shù)據(jù)寫入文件
            file.Close();
            }
            }
            return CDocument::CanCloseFrame(pFrame);
            }
            這樣當(dāng)你單擊窗口上的關(guān)閉按鈕時(shí),如果數(shù)據(jù)已修改了,就會(huì)彈出一個(gè)提示保存數(shù)據(jù)的對(duì)話框,提示你保存數(shù)據(jù)。
            程序中的b_Flag是數(shù)據(jù)修改標(biāo)志,應(yīng)該在修改數(shù)據(jù)時(shí)進(jìn)行設(shè)置,m_Text是準(zhǔn)備保存的數(shù)據(jù),放在文檔內(nèi)。

            POSITION
            怎么用?
            POSITION
            類型數(shù)據(jù)用于表征各種列表中元素的位置,它類似于數(shù)組的下標(biāo),但又有所不同。主要區(qū)別是:
            我們不能訪問(wèn)POSITION型數(shù)據(jù)的值,也不能對(duì)POSITION數(shù)據(jù)型數(shù)據(jù)進(jìn)行加減、比較等運(yùn)算。
            POSITION型數(shù)據(jù)訪問(wèn)列表時(shí),都是采用迭代法,一般格式為:
            POSITION pos; //
            定義pos型變量
            pos = GetHeadPosition(); //
            獲取列表起始元素位置
            while( pos )
            {
            x = GetNext(pos); //
            獲取pos處的列表值,同時(shí)修改pos為下一個(gè)元素位置
            }
            GetNext()
            就是一種迭代,其格式為:
            TYPE GetNext(POSITION& rPosition);
            首先,它返回當(dāng)前pos位置處的元素;再就是把pos值修改為下一個(gè)元素位置。這樣循環(huán)時(shí),可依次取得列表中各元素的值;當(dāng)?shù)竭_(dá)列表尾時(shí),posNULL,循環(huán)結(jié)束。
            所以使用POSITION型數(shù)據(jù)時(shí),你不要試圖用加減等操作去修改它,只能用GetNext()(向后迭代)或GetPrev()(向前迭代)反復(fù)迭代來(lái)修改它的值。
            如果你想直接到達(dá)指定值,還可以用Find()函數(shù)或FindIndex()函數(shù)獲得指定值的POSITION值。
            POSITION Find(TYPE Value);
            用于在列表中查找值為Value的元素的POSITION值;
            POSITION FindIndex(int nIndex);
            用于獲取列表中第nIndex個(gè)元素的POSITION值,nIndex0開始。
            如:
            pos = FindIndex(5); //
            求列表中第5個(gè)元素的位置
            x = GetNext(pos); //
            讀取元素的值
            總之,POSITION類型在多種涉及列表的類中提供,不同的類提供的函數(shù)有所不同,但用法都是類似的。

            如何從完整的文件路徑中分離文件名和路徑名?
            從路徑中分離文件名:

            CString GetFileName(CString pathname)
            {
            for( int i=pathname.GetLength()-1; i>=0; i-- )
            {
            if( pathname[i]=='\\' )
            break;
            }
            return pathname.Mid( i+1 );
            }
            從路徑中分離路徑名(去除文件名):

            CString GetPath(CString pathname)
            {
            int i = 0, j;
            while( i<pathname.GetLength() )
            {
            if( pathname[i]=='\\' )
            j = i;
            i++;
            }
            return pathname.Left( j+1 );
            }
             
            posted @ 2008-04-13 11:37 wrh 閱讀(421) | 評(píng)論 (0)編輯 收藏
            單選鈕用來(lái)表示一系列的互斥選項(xiàng),這些互斥項(xiàng)常常被分成若干個(gè)組,每組僅允許用戶選擇一個(gè)選項(xiàng);復(fù)選框與單選按鈕相象,不同之處是復(fù)選框代表多重選擇,用戶可以選擇一個(gè)或多個(gè)選項(xiàng)。

              對(duì)話框編輯器中各組控件的對(duì)齊

              按下Ctrl鍵并單擊要對(duì)齊的各個(gè)控件,同時(shí)選中。最后選中的控件是對(duì)齊的基準(zhǔn),仔細(xì)觀察,它周圍的8個(gè)小方框是實(shí)心的,而其它被選控件周圍的小方框是空心的。

              在Layout菜單中選擇Make Same Size的Both,可以統(tǒng)一控件尺寸,所選控件尺寸與基準(zhǔn)控件相同。在Layout菜單中選擇Align的Left,可以使所有被選控件的左邊與基準(zhǔn)控件對(duì)齊。選擇Layout菜單中Align的Space Evenly的Down,可以使被選控件垂直間距相等。

              單選按鈕和復(fù)選框的使用
              為了方便說(shuō)明,我們假定創(chuàng)建了基于對(duì)話框的MFC應(yīng)用程序,工程名為RadioAndCheckButton。對(duì)話框資源加入兩個(gè)組框 ,第一個(gè)組框‘性別’,內(nèi)有‘男’,‘女’兩個(gè)單選鈕;第二個(gè)組框是‘愛好’,內(nèi)有‘足球’‘排球’‘藍(lán)球’三個(gè)復(fù)選框,如下表:

            控件類型 ID 標(biāo)題(Caption) 其它屬性
            組框 缺省 性別 缺省
            單選鈕 IDC_SEX1 Group
            單選鈕 IDC_SEX2 缺省
            組框 缺省 愛好 缺省
            復(fù)選框 IDC_HOBBY1 足球 缺省
            復(fù)選框 IDC_HOBBY2 排球 缺省
            復(fù)選框 IDC_HOBBY3 藍(lán)球 缺省

              設(shè)置控件的Tab Order

              單擊Layout菜單下的Tab Order命令,設(shè)置控件的TAB鍵順序(Tab Order),保證單選鈕的Tab Order連續(xù)。

              以Tab Order為序,從Group屬性為真的控件開始(包括該控件),到下一個(gè)Group屬性為真的控件結(jié)束(不包括該控件),所有的這些控件將組成一個(gè)組。對(duì)于單選鈕,同一組內(nèi)同時(shí)只能有一個(gè)處于被選中狀態(tài)。對(duì)于由資源編輯器生成的單選按鈕控件,在默認(rèn)情況由Windows自動(dòng)處理同組控件之間的互斥關(guān)系。

              具體使用單選鈕和復(fù)選框

              1、調(diào)用 CButton的成員函數(shù)SetCheck設(shè)置單選鈕和復(fù)選框的選中狀態(tài)。該成員函數(shù)帶有一個(gè)類型為整形的參數(shù),該參數(shù)為0表示清除選中按鈕的選中狀態(tài),參數(shù)為1表示設(shè)置選中按鈕的選中狀態(tài)。參數(shù)為2表示把三態(tài)復(fù)選框設(shè)為不確定狀態(tài)。

              復(fù)選框的Tristate屬性:創(chuàng)建三態(tài)復(fù)選框。除了處于“選中”和“不選中”狀態(tài)外,三態(tài)復(fù)選框還可以處于變灰狀態(tài)。通常,復(fù)選框的變灰狀態(tài)表示其選中狀態(tài)不確定。在很多軟件的安裝程序中,變灰往往表示僅選中該組件的一部分。

              注意,如果我們?cè)诔绦蛑姓{(diào)用SetCheck設(shè)置同一組中某一單選鈕為選中狀態(tài),并不意味著同時(shí)清除同一組中其它單選鈕的選中狀態(tài)。否則,將導(dǎo)致同一組中的兩個(gè)按鈕同時(shí)處于選中狀態(tài)。這是應(yīng)該避免的。因此,如果我們通過(guò)代碼改變了單選鈕的選中狀態(tài),一定要記得同時(shí)清除同組的其它單選鈕的選中狀態(tài)。

              2、調(diào)用 CButton的成員函數(shù)GetCheck返回單選鈕的選中狀態(tài)。該函數(shù)的函數(shù)原型是

            int GetCheck( ) const;

              返回值可以是0、1、2,分別代表按鈕處于未選中狀態(tài)、選中狀態(tài)或中間狀態(tài)(對(duì)三態(tài)復(fù)選框而言)。

              3、調(diào)用類CWnd的成員函數(shù)GetCheckedRadioButton返回同一組單選鈕中哪一個(gè)被選中。該成員函數(shù)原型如下:

            int GetCheckedRadioButton(int nIDFirstButton,int nIDLastButton);

              第一個(gè)參數(shù)nIDFirstButton是同一組中的第一個(gè)單選鈕控件的ID,nIDLastButton是同一組中最后一個(gè)單選鈕控件的ID。成員函數(shù)GetCheckedRadioButton返回指定組中所選中的單選鈕的ID,如果沒(méi)有按扭被選中,則返回0。

              注意,若干個(gè)單選鈕是否屬于同一組是以其Tab順序來(lái)排定的,而GetCheckedRadioButton函數(shù)是以ID順序來(lái)檢查按鈕的選定狀態(tài)的。因此,如果傳遞給函數(shù)GetCheckedRadioButton的第一個(gè)參數(shù)的值大于第二個(gè)參數(shù)的值時(shí),其返回值總是為0,而事實(shí)上由這兩個(gè)參數(shù)指定的單選鈕的Tab順序可能恰恰相反。因此,一般情況下我們應(yīng)該盡量保證同一組單選鈕的資源ID是連續(xù)遞增的。通常這些資源ID是在頭文件Resource.h中定義的。如果你同一組的單選鈕不是一次創(chuàng)建的,那么它們的資源ID可能不是連續(xù)遞增的,甚至可能是相反的。我們可以手動(dòng)的修改資源頭文件中的宏定義,以保證GetCheckedRadioButton函數(shù)得到正確的結(jié)果。

              例:
            UINT nSex=GetCheckedRadioButton(IDC_SEX1,IDC_SEX2); Switch(nSex) { Case IDC_SEX1: ; ……

              4、使用ClassWizard為單選鈕或復(fù)選框添加變量,來(lái)使用單選鈕或復(fù)選框

              一般,一組單選按鈕的第一個(gè)屬性選中Group,注意,只有選中Group屬性的單選鈕的ID 才能在ClassWizard中添加變量。

              在對(duì)話框類給一組單選鈕加入一個(gè)成員變量,單選鈕(組中的第一個(gè)按鈕)的數(shù)據(jù)變量類型是int,0表示選擇了組中的第一個(gè)單選鈕,1表示選擇了第二個(gè),-1表示沒(méi)有一個(gè)被選中。例如:給單選鈕IDC_SEX1添加int型變量m_nSex,并在執(zhí)行文件中加入如下代碼:

            ……
            UpdateData(TRUE);
            if(m_nSex==0) //選中‘男’
            ;
            else if(m_nSex==1) //選中‘女’
            ;
            else
            ;
            ……

              復(fù)選框的數(shù)據(jù)變量類型是BOOL,TRUE表示選中,F(xiàn)ALSE表示未選中。例如:給復(fù)選框IDC_HOBBY1添加BOOL型變量m_hobby1,并在執(zhí)行文件中加入如下代碼:

            ……
            m_hobby1=TRUE;
            UpdateData(FALSE);
            ……

              5、使用消息映射宏ON_CONTROL_RANGE

              單選鈕和復(fù)選框都可以響應(yīng)BN_CLICKED消息,如果一組中有多個(gè)單選鈕,分別創(chuàng)建消息處理函數(shù)就比較麻煩了,利用MFC的消息映射宏ON_CONTROL_RANGE可以避免這種麻煩,該映射宏把多個(gè)ID連續(xù)的控件發(fā)出的消息映射到同一個(gè)處理函數(shù)上,這樣,我們只要編寫一個(gè)消息處理函數(shù)就可以對(duì)一組單選鈕的BN_CLICKED消息作出響應(yīng),ClassWizard不支持該宏,必須手工創(chuàng)建。

              ON_CONTROL_RANGE消息映射宏的第一個(gè)參數(shù)是控件消息碼,第二和第三個(gè)參數(shù)分別指明了一組連續(xù)的控件ID中的頭一個(gè)和最后一個(gè)ID,最后一個(gè)參數(shù)是消息處理函數(shù)名。注意,起始、 終止ID號(hào)必須是連續(xù)的,如果不能確定該組控件的ID是否是連續(xù),請(qǐng)用View->Resource Symbols…命令檢查控件的ID值,如果發(fā)現(xiàn)兩個(gè)ID是不連續(xù)的,讀者可以改變對(duì)ID的定義值使之連續(xù),但要注意改動(dòng)后的值不要與別的ID值發(fā)生沖突。

              在BEGIN_MESSAGE_MAP 和 END_MESSAGE_MAP之間 //}}AFX_MSG_MAP之后加入

            ON_CONTROL_RANGE(BN_CLICKED,IDC_SEX1,IDC_SEX2,OnSexClicked)

              然后在對(duì)話框類的頭文件的AFX_MSG 塊中聲明消息處理函數(shù),

            ……
            //{{AFX_MSG(CMyView)
            ……
            //}}AFX_MSG
             afx_msg void OnSexClicked (UINT nCmdID); 
            DECLARE_MESSAGE_MAP()
            ……
              最后,在對(duì)話框類所在CPP文件的最后插入消息處理函數(shù),如下所示:
            CRadioAndCheckButtonDialog:: OnSexClicked,
             void CRadioAndCheckButtonDialog:: OnSexClicked (UINT nCmdID)  
             { 
            ……
            switch(nID)
            {
            case IDC_SEX1:
            AfxMessageBox("IDC_SEX1");
            break;
            case IDC_SEX2:
            AfxMessageBox("IDC_SEX2");
            break;
            ……
            }        
              6、使用IsDlgButtonChecked 函數(shù)判斷單選鈕或復(fù)選框是否被選中

              CWnd::IsDlgButtonChecked函數(shù),用來(lái)判斷單選按鈕或檢查框是否被選擇,該函數(shù)的聲明為
            UINT IsDlgButtonChecked(int nIDButton) const;

              參數(shù)nIDButton為按鈕的ID。若按鈕被選擇,則函數(shù)返回1,否則返回0,若按鈕處于不確定狀態(tài),則返回值為2。

            ……
             if(IsDlgButtonChecked(IDC_SEX1)) 
            ……

              以上是使用單選鈕和復(fù)選框最常用的幾種方法。

            posted @ 2008-04-12 19:23 wrh 閱讀(641) | 評(píng)論 (0)編輯 收藏

            1、改變下拉框大?。合赛c(diǎn)向下的箭頭,就可以調(diào)整下拉框大小

            2、如果 ComboBox 的 Sorted 屬性設(shè)置為 true,
               則新添加項(xiàng)將按字母順序插入到列表中。
               否則,在列表的結(jié)尾處插入項(xiàng)。

            3、要立即響應(yīng)選擇框的改變(即選擇框一改變選項(xiàng),就立刻將結(jié)果傳遞進(jìn)去)!
               響應(yīng)他的哪個(gè)消息比較好?

               如果是只能選擇的響應(yīng)ON_CBN_SELCHANGE
               如果是可以編輯的,那么要立刻響應(yīng)編輯就是ON_CBN_EDITCHANGE

            4、CBN_SELENDOK是什么作用?
               This notification message is sent when the user clicks a list item,
               or selects an item and then closes the list.
               It indicates the user's selection is to be processed

            5、介紹一下列表框幾種常用的消息映射宏:

               ON_CBN_DBLCLK 鼠標(biāo)雙擊
               ON_CBN_DROPDOWN 列表框被彈出
               ON_CBN_KILLFOCUS / ON_CBN_SETFOCUS 在輸入框失去/得到輸入焦點(diǎn)時(shí)產(chǎn)生
               ON_CBN_SELCHANGE 列表框中選擇的行發(fā)生改變
               ON_CBN_EDITUPDATE 輸入框中內(nèi)容被更新
               使用以上幾種消息映射的方法為定義原型如:afx_msg void memberFxn( );的函數(shù),
               并且定義形式如ON_Notification( id, memberFxn )的消息映射。
               如果在對(duì)話框中使用組合框,Class Wizard會(huì)自動(dòng)列出相關(guān)的消息,并能自動(dòng)產(chǎn)生消息映射代碼。

            6、改變ComboBox的下拉列表框?qū)挾?br>   一般情況下,列表框的寬度和選擇框是一樣寬的,為了讓列表框變的更寬,可以用
               m_Combobox.setdroppedwidth(int width); 來(lái)調(diào)整 他的寬度

            7、如何使控鍵ComboBox不能輸入只能在下拉菜單中選擇?
               VC6中style屬性設(shè)為csDropDownList
               VC2005中Type屬性設(shè)為Drop List

            8、設(shè)置當(dāng)前項(xiàng)或得到當(dāng)前是第幾項(xiàng)
               
               m_ComboBox1.SetCurSel(N);    //SetCurSel函數(shù)可改變標(biāo)簽控件當(dāng)前選定的項(xiàng)目
                //這個(gè)N可以是-1,表示無(wú)選擇,0表示第一項(xiàng),1表示第二項(xiàng)。。
               m_ComboBox1.GetCurSel();     //得到當(dāng)前是第幾項(xiàng).0是第一項(xiàng),1是第二項(xiàng)

            posted @ 2008-04-12 18:53 wrh 閱讀(1486) | 評(píng)論 (0)編輯 收藏
            僅列出標(biāo)題
            共25頁(yè): First 17 18 19 20 21 22 23 24 25 

            導(dǎo)航

            <2025年7月>
            293012345
            6789101112
            13141516171819
            20212223242526
            272829303112
            3456789

            統(tǒng)計(jì)

            常用鏈接

            留言簿(19)

            隨筆檔案

            文章檔案

            收藏夾

            搜索

            最新評(píng)論

            閱讀排行榜

            評(píng)論排行榜

            亚洲av日韩精品久久久久久a| 亚洲欧洲中文日韩久久AV乱码| 狠狠色综合网站久久久久久久高清 | 久久线看观看精品香蕉国产| 日本免费久久久久久久网站| 欧美日韩精品久久久免费观看| 天天躁日日躁狠狠久久| 国产精品一区二区久久国产| 国产精品成人久久久久久久| 亚洲精品白浆高清久久久久久| 久久精品中文字幕久久| 久久大香萑太香蕉av| 国产免费久久久久久无码| 久久综合鬼色88久久精品综合自在自线噜噜 | 激情伊人五月天久久综合| 久久99久久成人免费播放| 精品伊人久久大线蕉色首页| 久久精品国产免费| 亚洲精品无码久久久久去q | 国产精品一区二区久久国产| 一97日本道伊人久久综合影院| 久久99久久99小草精品免视看| 久久精品无码一区二区WWW| 亚洲国产成人久久精品动漫| 久久无码人妻一区二区三区午夜| 一本久道久久综合狠狠躁AV| 久久无码精品一区二区三区| 久久精品国产亚洲麻豆| 精品乱码久久久久久久| 亚洲人成网亚洲欧洲无码久久 | 2020久久精品国产免费| 伊人久久大香线蕉综合影院首页| 性做久久久久久久久久久| 97精品国产97久久久久久免费| 久久不射电影网| 日本道色综合久久影院| 成人免费网站久久久| 婷婷综合久久狠狠色99h| …久久精品99久久香蕉国产| 91久久精品91久久性色| 91精品国产乱码久久久久久|