• <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編程常用小技巧

            1.        如何獲取系統日期

            CTime tm = CTime :: GetCurrentTime();

            CString strTime = tm.Format(_TEXT(“%Y-%M-%d %H:%M:%S));

            MessageBox(strTime);

             

            2.        動態分配二維數組

            int **array;

            array = new int*[col];

            if(array = = 0) exit(-1);

            for(int i=0; i<col; i++){

            array[i] = new int[row];

            if(array[i] = = 0)

                exit(-1); }

            //釋放

            for(i=0; i<col; i++){

             delete [] array[i]; }

            delete [] array;

             

            3.        如何定義一個二維字符串數組

                  char **str = “abcdef” ; //一維

                  char *str[row][col]={“abc”, “cdf”, “efg”…..}; //row×col

             

            4.        將一個十六進制”FF””FA”等字符串數組等轉化為十進制數組

            int array[32][32];

            int a,b, n=0;

            int result1;

            char *str;

            for(int i=0; i<32; i++)

            for(int j=0; j<32; j++){

                 str = str[i][j];

                 if(str[0] >= ‘A’ && str[1] >=’A’){ //”AF”

                    a = str[0] – ‘A’;

                    b= str[1] – ‘A’;

                    result1 = (a+10)*16+(b+10)*1;}

                 else if(str[0] >= ‘A’ && str[1] <’A’){ //”A9”

                    a = str[0] – ‘A’;

                    b = ‘A’  – str[1] +1;

                    result1 = (a+10)*16+b;}

                 else if(str[0] < ‘A’ && str[1] >=’A’){ //”8B”

                    a = ‘A’ – str[0]+1;

                    b = str[1] – ‘A’;

                    result1 = a*16+(b+10)*1;}

                 else{                       //”87”

                    a = ‘A’ – str[0]+1;

                    b = ‘A’  – str[1] +1;

                    result1 = a*16+b;}

                 array[i][j] = reslut1;

                 printf(“%5d”, array[i][j]);

                 n++;

                 if(n%32 = = 0) printf(“"n”); }

            將這個矩陣數組在屏幕上顯示:

            #i nclude < afxwin.h >

            #i nclude < afxext.h >

            #i nclude < afxdisp.h >

            #i nclude < afxdtctl.h >

            DWORD color_;

            HDC hMyDC = GetDC(NULL);

            for(i=0; i<32; i++)

            for(j=0; j<32; j++){

                 color_ = array[i][j];

                 color_ = color_*256*256 + color_*256+color_;

                 SetPixel(hMyDC, j, i, color_); }

             

            5.        將一個整型轉化為一個字符串 _itoa

            //將從位圖信息頭得到的圖像寬度和高度顯示出來

            char buffer1[20], buffer2[20];

            _itoa( width, buffer1, 10);

            _itoa( height, buffer2, 10);

            char str[80];

            strcpy(str, “width=”);

            strcat(str, buffer1);

            strcat(str, “, hight=”;

            strcat(str, buffer2);

            AfxMesageBox(str, MB_OK, 0);

             

            6.        當把二維數組地址用作參數傳遞,而又要此地址不斷遞增時,可以另外定義一個同類型指針,指向二維數組第一個元素的地址,把這個賦值放在循環外:

                 unsigned char *p;

                 p = &m_pImage[0][0];

               然后在循環中,可以p + m_count*4096;

             

            7.        改變最近打開文檔的個數

            InitInstance()中的LoadStdProfileSetting(8); //括號里是要設置的個數

            8.        打開調色板對話框

            CColorDialog dlg;

            dlg.Domodal();

             

            9.        如何添加工具欄,如何使用Slider?

            OnInitDialog()中添加:

            CSliderCtrl *pSliderCtrl=(CSliderCtrl*)GetDlgItem(IDC_SLIDER1);

            pSliderCtrl -> SetRange(0,255,TRUE); //設置滑動條的范圍

            pSliderCtrl -> SetPos(100); // 設置滑動條的初始位置

            Dlg類中響應WM_HSCROLL消息:

            CSliderCtrl *pSliderCtrl=(CSliderCtrl*)GetDlgItem(IDC_SLIDER1);

            m_nCur = pSliderCtrl - >GetPos(); //獲得當前的位置值

             

            10.     更改光標

            :: SetCursor(:: LoadCursor(NULL, IDC_SIZEALL));

            //如果是自己定義的光標資源,則要用MAKEINTRESOURCE 進行轉化,例如:

            :: SetCursor(:: LoadCursor(NULL, IDC_CURSOR_CUT));

             

            11.     設置文本顯示的一些函數

            CDC dc(this); 

            CPen pen(PS_SOLID, 2, #0000ff); //初始化一支筆

            CBrush *pBush = CBrush :: FromHandle((HBRUSH)GetStockObject(NULL_BRUSH));

            dc.SelectObject(pBrush);

            dc.SetTextColor(RGB(255,0 ,255));

            dc.SetBKMode(TRANSPARENT); //將文本背景設置為透明

             

            12.     將對話框中的圖像拷貝到剪貼板

            CWnd* pWnd = GetDlgItem(IDC_IMAGE_SELECT);

            WINDOWPLACEMENT *winPlacement;

            WinPlacement = new WINDOWPLACEMENT;

            pWnd -> GetWindowPlacement(winPlacement); //獲得一個控件的位置

            CDC *dcTemp;

            dcTemp= new CClientDC(FromHandle(m_hWnd));

            CDC memDC;

            memDC.CreateCompatibleDC(dcTemp); //創建一個兼容的DC

            CBitmap bm;

            CSize sz(lWidth, lHeight);

            bm.CreateCompatilbleBitmap(dcTemp, sz.cx, sz.cy); //創建一個兼容的位圖

            CBitmap* oldbm = memDC.SelectObject(&bm);

            memDC.BitBlt(0, 0, sz.cx, sz.cy, dcTemp, winPlacement ->rcNormalPosition.left,

                        winPlacement ->rcNormalPosition.top, SRCCOPY);

            pWnd -> OpenClipboard(); //打開剪貼板,不用pWnd->GetParent()->OpenClipard();

            :: EmptyClipard();

            :: SetClipardData(CF_BITMAP, bm.m_hObject); //粘貼到剪貼板

            CloseClipard();

            memDC.SelcetObject(oldbm);

            delete dcTemp;

             

            13.     VC里獲取一個文件夾路徑

            BROWSEINFO bi;

            TCHAR szDisplayName[MAX_PATH];

            LPITEMIDLIST pidl;

            LPMALLOC pMalloc = NULL;

            ZeroMemory(&bi, sizeof(bi));

            bi.hWndOwner = GetSafeHwnd();

            bih.pszDisplayName = szDisplayName;

            bi.lpszTitle = TEXT(“Please select a folder:”);

            bi.ulFlags = BIF_RETURNONLYFSDIRS;

            Pidl = SHBrowseForFolder(&bi);

            if(pidl) {

                  SHGetPathFromIDList(pidl, szDisplayName);

                  sPath = szDisplayName;

                  MessageBox(sPath); }

             

            14.     如何設置密碼輸入時顯示的是*

            #i nclude <iostream.h>

            #i nclude <conio.h>

            char a[8];

            void main() {

            int i=0;

            Cout<<”請輸入密碼:”<<endl;

            while(1) {

                 a[i] = getch();

                 if( i>=8 || a[i]= = 13)

                    break;

                 putch(‘*’);

                 i++; }

            cout<<endl<<a<<endl;

            getch(); }

             

            15.     設置菜單:可以使用CMenu:: EnableMenuItem()來設置菜單可用或禁用,但是在MFC中,要使該函數起作用,需要將CWnd :: m_bAutomenuEnable設置為FALSE.

            16.     關閉子窗口

            :: SendMessage(:: AfxGetMainWnd() -> m_hWnd, WM_COMMAND, ID_FILE_CLOSE,0);

            獲取主窗口的指針 CWinThread :: m_pMainWnd

            調用AfxGetMainWnd()可實現

               繼續上面的總結~! To making  it  count~!。。。。。。
             
            1.        獲取CMain類的指針

            CMain* pApp = ((CMain*)AfxGetApp()->m_pMainWnd);

            ASSERT_KINDOF(CMain, pAPP); //確保pAPPCMain的類對象

            2.        VC++如何獲取應用程序的實例句柄

            實例句柄保存在CWinApp m_hInstance

            HANDLE hInstance = AfxGetInstanceHandle();

            3.        VC++怎樣加載其他的應用程序 三個SDK函數WinExec, ShellExecute, CreateProcess.

                  WinExec最簡單,前一個指定路徑,后一個指定顯示方式;

                  ShellExecute(null, null, _T(“1.txt”), NULL, _T(“c:""temp”), SW_SHOWNORMAL);

                  STARTUPINFO stinfo; //啟動窗口的信息

            PROCESSINFO proinfo; //進程的信息

            CreateProcess(NULL,_T(“notepad.exe)”,NULL,NULL,FALSE,NORMAL_PRIORITY_CLASS,NULL,NULL,&stinfo,&proinfo);

             

            4.        如何確定頂層菜單所占據的菜單行數:首先,計算主窗口的高度和客戶區高度;其次,從主框窗口的高度中減去客戶區、框邊界以及標題的高度;最后,除以菜單欄的高度

            CRect rc, rcClient;

            GetWindowRect(rc);

            GetClientRect(rcClient);

            Int menuHeight;

            menuHeight = (rc.Height() – rcClicent.Height()–

            ::GetSystemMetrics(SM_CYCAPTION) – :: GetSystemMetrics(SM_CY)*2))

            -                                                                                                  / :: GetSystemMetrics(SM_CYMENU) ;

            5.        響應下拉菜單的消息為

            ON_CBN_SELECTDOK(ID_TOOL_ZOOM, OnSelectZoomed)

            6.        設置工具欄的標題

            m_wndTestBar.SetWindowText(“your toolbar title”);

             

            7.        如何獲得應用程序主窗口的指針

            CWnd pMainWnd = AfxGetApp() ->m_pMainWnd;

            CMain *pMain = ((CMain*)pMainWnd;

            CRect rect;

            CWnd* pParent = AfxGetApp()->GetMainWnd();

            pParent ->GetWindowRect(&rect); //得到應用程序窗口矩形

            //移到窗口

            pParent -> MoveWindow(rect.left, rect.top, rect.Width()+1,rect.Height()+1,TRUE);

            8.        獲得獲得子窗口

            CMDIChildWnd* pChild = (CMDIChildWnd*)GetActive();

            //或:CMDIChildWnd* pChild=MDIGetActive();

            9.        獲得活動子窗口的活動視圖

            CMyView* pView = (CMyView*)pChild->GetActiveView();

            獲取當前窗口的指針

            CWnd :: GetForegoundWindow();

            10.     從句柄轉換到指針

            HWND hwnd;

            hwnd = :: FindWindow(NULL, “TEST”);

            CWnd* pWnd = FromHandle(hwnd);

            11.     怎樣改變進度條控件的顏色,發送消息

            m_progress.SendMessage(PBM_SETBKCOLOR, 0, #ff0000); //背景色

            m_progress.SendMessage(PBM_SETBARCOLOR, 0, #00ff00); //前景色

            12.     定義char num[10];

                    sprintf(num, “%d”, calnum); //格式化數字

                    char unit[]=”矩形”;

                    sprintf(num, “%s”, unit); //格式化字符串

            13.     改變字符串的顯示字體和大小

            CFont font;

            font.CreatePointFont(300, “華文行楷”,NULL);

            CFont *pOldFont=dc.SelectObject(&font);

            dc.SelectObject(pOldFont);

             

            14.     將路徑中的單’"’變為’""’

            CMyDoc *pDoc=GetDocument();

            CString reportPath = pDoc -> strPathName;

            int lentemp = reportPath.GetLength();

            reportPath = reportPath.Left(lentemp-4);

            int lenpath = reportPath.GetLength();

            for(int i=0; i<lenpath-1; ) {

                 if(reportpath.GetAt(i) = = ‘""’) {

                     reportpath.Insert(i, ‘""’);

                     i+=2; }

                 i++; }

             

            15.     獲取屏幕分辨率

            HDC hSrcDC;

            hSrcDC = ::GetDC(AfxGetApp() -> m_pMainWnd->GetSafeHwnd());

            int xSrc, ySrc;

            xSrc = GetDeviceCaps(hSrcDC, HORIRES); //水平分辨率

            ySrc = GetDeviceCaps(hSrcDC, VERTRES); //垂直分辨率

             

            16.     Edit控件響應回車鍵:利用獲取消息來完成,調用虛函數

            PreTranslateMessage(MSG* pMsg) {

               If( pMsg ->message = = WM_KEYDOWN) {

                  switch(pMsg -> wParam) {

                     case VK_RETURN:

                        GetDlgItem(IDC_BTN_INPUT)->SendMessage(BM_CLICK, 0, 0);

                        return TRUE; } }    }

            17.     改變對話框的背景色:在InitInstance()中加入

            SetDialogBKColor(#a0b4dc, #ff0000); //后面是字體顏色

            18.     讓指定的矩形框重畫 InvalidateRect(&rect, TRUE);

            19.     怎樣選擇所選的List當前位置

            int iTem;

            POSITION pos=m_findCtrl.GetFirstSelectedItemPosition();

            if(pos = = 0) {

             MessageBox(“請選擇需要刪除的記錄”);

             return; }

            else {

            iTem = m_findCtrl.GetNextSelectedItem(pos); }

             //刪除List中的某行

             m_findCtrl.DeleteItem(iTem);

            m_findCtrl.Update(iTem);

             

            20.     動態創建控件

            CEdit m_edit;

            CRect rect(0,0,100,200);

            M_edit.Create(WS_CHILD | ES_AUTOHCROLL | WS_BORDER, rect, this, ID_EDIT_1);

            21.     列表控件的應用

            CListCtrl* m_list;

            CRect rect_list;

            this->GetCientRect(&rect_list);

            rect_list.top + =100;

            m_list -> Create(WS_CHILD | LVS_REPORT | WS_BORDER | LVS_SINGLESEL, rect_list, this, ID_TABLIST);

            this ->m_list->ModifyStyle(LVS_EDITABELS,0L); //禁止標題編輯

            m_list->ModifyStyle(0L ,LVS_REPORT); //設置為Report類型

            m_list->ModifyStyle(0L, LVS_SHOWSELALWAYS); //始終高亮顯示被選中的表項

            m_list->ModifyStyle(0L,LVS_NOSORTHEADER); //禁止標題編輯

            m_list->SetBkColor(#00c8c8); //設置背景顏色

            m_list->SetTextBkColor(#00c8c8); //設置文本背景顏色

            m_list->ModifyStyle(LVS_OWNERDRAWFIXED,0L);

            m_list->SetExtendedStyle(LVS_EX_FULLROWSELET //整行選中

                                 | LVS_EX_HEADERDARGDROP //允許整列拖動

                                 | LVS_EX_GRIDLINES   //畫出網格線

                                 | LVS_EX_FLATSB); // 扁平風格的滾動條

            22.     取得當前獲得焦點的窗口句柄

            HWND hwnd = ::GetFocus();

            int iID = :: GetDlgCtrlID(hwnd); // 根據句柄取得其資源符號

             

            23.     修改控件的字體

            CFont m_font;

            m_font.CreateFont(-12,0,0,0,400,FALSE,FALSE,0,GB2312_SHARSET,OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY, VARIABLE_PITCH | FF_, “楷體_GB2312”);

            //為想改變字體的控件改變

            m_editPh.SetFont(&m_font, true);

            1.        如何暫停主線程直到第二個線程的終止?

            void CMyTestDialog ::PeekMessageLoop() {

                  MSG msg;

                 while ( PeekMessage(&msg, NULL, NULL, NULL, NULL,NULL, PM_REMOVE)) {

                               TranslateMessage(&msg);

                               DispatchMessage(&msg); } }

            Void CMyTestDialog :: WaitForThreadToTerminate( HANDLE hThread) {

                      //將指示哪個線程需要等待并作進一步處理

                  DWORD dwRet;

                  Do {

                       dwRet = :: MsgWaitForMultipleObject(1, &hThread, FALSE, INFINITE, QS_ALLINPUT);

                       if(dwRef != WAIT_OBJET_0) {

                             PeekMessageLoop();   }

                     }while ( (dwRet != WAIT_OBJET_0) && (dwRet != WAIT_FAILED));

            //示例代碼:假設對話框上有一個按鈕,當點擊按鈕時,開始啟動第二個線程,等到第

            //二個線程完成后,我們再繼續主線程:

            void CMyTestDialog :: OnButton1() {

                  m_pUpdateThread = AfxBeginThread(UpdateDeviceContent, (LPVOID)this);

                  ifm_pUpdateThread {

                            WaitForThreadToTerminate(m_pUpdateThread->m_hThread); }

                  //這里可以加入自己的執行代碼

                 Do whatever you want after the action is finished. } 

            2.        改變列表框表頭的顏色和字體,發送一個HDM_GETITEM消息

            void CHeaderCtrlEx :: DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct) {

                 ASSERT(lpDrawItemStruct ->ctlType = =ODT_HEADER);

                 HDITEM hdi;

                 TCHAR lpBuffer[256];

                 Hdi.mask = HDI_TEXT;

                 Hdi.pszText = lpBuffer;

                 Hdi.uhTextMax = 256;

                 GetItem(lpDrawItemStruct->itemID,&hdi);

            //畫按鈕框

            :: DrawControl(lpDrawItemStruct->hdc, &lpDrawItemStruct->rcItem, DFC_BUTTOON, DFCS_BUTTONPUSH);

            COLORREF crOldColor = :: SetTextColor(lpDrawItemStruct->hdc, #ffff00);

            :: DrawText(lpDrawItemStruct->hdc, lpBuffer, strlen(lpBuffer), &lpDrawItemStruct->rcItem, DT_SINGLELINE | DT_VCENTER | DT_CENTER);

            :: SetTextColor(lpDrawItemStruct->hdc, crOldColor); } 

            3.        修改標題欄中“無標題-title

                  修改“無標題”部分,重載文檔中的虛函數SetTitle,加入:

            CDocument:: SetTitle”your title”;

                  修改后半部分:將字符串資源中的IDR_MAIN修改為

            我的程序"n"nChange"n"n"nChangeTitle.Document"nChange Document

            或者:在程序的任何地方調用如下語句:

            (AfxGetMainWnd()) -> SetWindowText(“your title”);

                  除去標題中間的”-“,可以通過重載CFramWnd類的OnUpdateTitle函數,這個函數在VC提供的幫助文件中找不到,必須手工添加:

            virtual void OnUpdateTitle(BOOL NaDa);

            void CMain :: OnUpdateTitle(BOOL NaDa) {

            CString csAppName;

            csAppName.Format(AFX_IDS_APP_TITLE);

            SetWindowText(csAppName); }

            //此時顯示的結果只有字符串資源AFX_IDS_APP_TITLE 所定義的字符串

                  另一種方法是在CMainPreCreateWindow函數中修改的窗口風格:

            BOOL CMain :: PreCreateWindow(CREATESTRUCT &cs) {

               cs.style &= ~ (LONG)FWS_ADDTOTITLE;

               return CWnd :: PreCreateWindow(cs); }

            //使用此方法,窗口的標題只顯示IDR_MAIN字符串中第一個"n之前的部分。

             

            ((CMainFram*)AfxGetMainWnd())->SetWindowText("****");     放在App類的InitInstance()函數里面

             

             

            4. const的一些用法

                int a=0;

                const int* b=&a; [1]   int const *b=&a;[2]   const int* const b=&a; [3]

                const char *p=”const”; [1] char const *p=”const”; [2] char const p=”const”; [4]

                const char* const p=”const”; [4]

             

                int a=0;

               const int &b=a; [1]   int const &b=a; [2]   int & const b=a; [3] const int & const b=a; [4]

                  如果const位于星號左側,則const用來修改指針所指向的變量,即指針指向的為不可變的;

                  如果const位于星號右側,const就是修飾指針本身,即指針本身是不可變的;

                  [3]中指針本身是不可變的,而指針所指向的內容是可變的,這種情況下不能對指針本身進行更改操作,如b++是錯誤的;

                  [4]中指針本身和指向的內容均為常量

            5. const作為參數用法

            void fun0( const A *a) 在函數體中,按照const所修飾的部分進行常量化,如形參為const A* a,則不能對傳遞進來的指針的內容進行改變,保護了原指針所指向的內容;

            void fun1(const A& a) 形參為const A& a,則不能對傳遞進來的引用對象進行改變,保護了原對象的屬性。[注:參數const通常用于參數為指針或引用的情況]

            const修飾返回值: const A fun2(); const A* fun3()

            一般用const修飾返回值為對象本身(非引用和指針)的情況多用于二目操作符重載函數,并產生新的對象的時候。

            [總結]: 一般情況下,函數的返回值為某個對象時,如果將其聲明為const時,多用于操作符的重載。通常,不建議用const修飾函數的返回值類型為某個對象或對某個對象引用的情況。

            6. 類成員函數中const的使用:一般放在函數體后void fun() const; 如果一個成員函數不會修改數據成員,那么最好將其聲明為const,因為const成員函數中不允許對數據成員進行修改,如果修改,編譯器會報錯,大大提高了程序的健壯性。

            7. 使用const的一些suggestioins

            要大膽地使用const,這將給你帶來無盡的益處,但前提是你必須搞清楚原委;

            在參數中使用const應使用引用或指針,而不是一般的對象實例;

            要避免最一般的賦值操作錯誤,如將const變量賦值;

            不要輕易地將函數的返回類型定為cosnt

                  除了重載操作符外一般不要將返回值類型定為某個對象的const引用 

            8. 讓應用程序只運行一個實例: AppInitInstance添加如下代碼:

                 HANDLE hSem = CreateSemaphore(NULL, 1, 1, m_pszAppName);

                 if(GetLastError() = = ERROR_ALREADY_EXISTS) { //信號量存在,則有一個在運行

                     CloseHandle(hSem); //關閉信號量句柄

                     // 尋找先前的實例窗口

                     HWND hWndPrevious = ::GetWindow(::GetDesktopWindow(), GW_CHILD);

                     While(:: IsWindow(hWndPrevious)) { //檢查窗口是否有預設的標記

                       if(::GetProp(hWndPrevious,m_pszAppName)) { //有,則尋找主窗口

                           if(:: IsIconic(hWndPrevious)) { //窗口最小化,則恢復其大小

                               ::SetForegroundWindow(hWndPrevious); //將主窗口激活

                               ::SetForgoundWindow(::GetLastActivePopup(hWndPrevious));

                               //將主窗口激活

                               ::ShowWindow(hWndPrevious, SW_NORMAL);

                               reurn FALSE; } //退出本實例

                       hWndPrevious = :: GetWindow(hWndPrevious, GW_HWNDNEXT); //繼續找 }

                 AfxMessageBox(“only one application program can run”);

                 return FALSE; } }

            1.獲取本機的IP地址

            #i nclude <stdio.h>

            #i nclude <winsock2.h>

            #pragma comment (lib, “ws2_32.lib”)

            Void CheckIP() {

               WSADATA wsadata;

            Char name[155];

            Char *ip;

            PHOSTENT hostinfo;

            If (WSAStartUp( MAKEWORD(2,0), &wsadate) = = 0) {

                 If ( gethostname( name, sizeof(name)) = = 0) {

                     If((hostinfo = gethostbyname(name)) != NULL) {//獲得IP的函數

                         Ip = inet_ntoa(*(struct in_addr*)*hostinfo -> h_addr_list);

                         Printf*”%s"n”, ip); } }

            WSACleanup(); }    }

             

            2. CWnd:: SetDlgItemInt(); 被對話框設定一個由字符串表示的整型值。

               CSemaphore ---à CSyncObject------àCObject

                 在一個進程或多個進程中允許訪問一種資源的允許線程數,CSemaphore對象維持當前獲取一種指定資源的線程個數。當計數大于0時,Semaphore對象的狀態是有信號狀態;典型應用是用Semaphore去限制使用一種資源的線程個數。用WaitforSingleObject等待有信號狀態,返回時則減少對Semaphore的計數。

            3. 得到計算機所有驅動函數GetAllDriverList()

                 CString tmp = _T(“A:""”), dir;

                 for(int i=1; i<=25; i++) {

                      dir = CString(‘A’+i)+ _T(“:""”);

                      if(GetDriveType(dir.GetBuffer(0)) = = DRIVE_NO_ROOT_DIR) continue;

                      tmp += “;” + dir; }

                 return tmp;

            4. 打開對話框,選擇文件路徑函數 OnBrowse()

            BROWSEINFO bi;

            char dispname[MAX_PATH], path[MAX_PATH];

            ITEMIDLIST    *pidl;

            bi.hwndOwner = m_hWnd;

            bi.pidlRoot = 0;

            bi.pszDisplayName = dispname;

            bi.ulFlags = BIF_RETUREONLYFSDIRS | BIF_EDITBOX | BIF_DONTGOBELOWDOMAIN;

            bi.lpfn = 0;

            bi.lParam = 0;

            bi.iImage = 0;

            if(pidl = SHBrowseForFolder(&bi)) { //顯示一個使用用戶可以選擇的文件打開對話框

             SHGetPathFromIDList(pidl, path); //把一個item identifier list轉化為一個文件系統路徑

             m_folder = CString(path);

             if(m_folder.IsEmpty() )   m_folder = GetAllDirverList();

             UpdateData(FALSE); }

            SHGetFileInfo(); 返回文件系統中對象的信息,比如文件、folder、路徑、驅動器

             

            5. 如何使用CImageList 

            CImageList m_iImageList;

            m_iImageList.Create(24,24,TRUE,1,0);

            HICON hIcon = NULL;

            hIcon = (HICON)::LoadImage(::AfxGetInstanceHandle(), MAKEINTRESOURCE(IDI_KEBIAO0, IMAGE_ICON,24,24,0);

            m_iImageList.Add(hIcon);

            m_FileTree.SetImageList(&m_iImageList, TVSIL_NORMAL); //m_FileTreeTreeList控件

            //或者這樣來創建:

            m_imageList.DeleteImageList();

            m_image.Create(16,16,ILC_COLORDDB,1,100);

            m_listCtrl.SetImageList(&m_iImageList, LVSIL_SMALL);

            6. 遍歷一個文件夾的文件

            OnFindFile(WPARAM wParam, LPARAM lParam) {

             CString strFilePath = *((CString*)wParam);

             if(strFilePath.Right(1) != “""”) {

                 strFilePath +=”""”; }

            strFilePath += “*.*”;

            CFileFind   finder;

            CString strFileName;

            BOOL isHave = finder.FindFile(strFilePath);

            while(isHave) {

                 isHave = finder.FindNextFile();

                 if(!finder.IsDirectory() && !finder.IsDots()) {

                     strFileName = finder.GetFilePath();

                     :: PostMessage((HWND)(GetMainWnd()->GetSafeHWnd()), WM_DISPLAY, (WPARAM)&strFileName, NULL); } }

            finder.Close();   }

            7. 如何來啟動這個查找線程

            新建一個類派生于CWinThreadCFindFileThread *pFindFileThread;

            pFindFileThread = (CFindFileThread*)AfxBeginThread(RUNTIME_CLASS(CFindFileThread);

            pFindFileThread -> PostThreadMessage(WM_FINDFILE, (WPARAM)&strFilePath,NULL);

             

            8. 找到一個則發送消息WM_DISPLAY,并把文件中全路徑作為參數返回

                 獲取一個文件的信息 OnDisplay(WPARAM wParam, LPARAM lParam) {

                 count++; //統計文件個數

                 CString strFileName = *((CString*)wParam);

                 CFileStatus status;

                 C: GetStatus(strFileName, status);

                 CString unit = “Byte”;

                 float flen = (float)status.m_size;

                 if(flen>1024) {

                       flen /= 1024;

                       if(flen < 1024)   unit = “KB”;

                       else {

                            flen /= 1024;

                            unit = “MB”; } }

                  CString size;

                  size.Format(“%1.2f”, flen);

                  int pos = strFileName.ReverseFind(‘""’);

                  SHFILEINFO sfi; //文件信息結構體

                  if(:: SHGetFileInfo(strFileName, FILE_ATTRIBUTE_NORMAL, &sfi,

                     Sizeof(SHFILEINFO), SHGFI_USEFILEATTRIBUTES |

                      SHGFI_DISPLAYNAME | SHGFI_TYPENAME | SHGFI_ICON

                          | SHGFI_SMALLICON)) {

                        m_imgList.Add(sfi.hIcon);

                        m_filelist.InsertItem(count-1, sfi.szDisplayName, count-1);

                        m_filelist.SetItemText(count-1, 1, strFileName, Mid(0,pos));

                      m_filelist.SetItemText(count-1, 2, (size+unit));

                      m_filelist.SetItemText(count-1, 3, sfi.szTypeName); }

                 m_filelist.Update(count-1); }
             

            9. 在圖片中隱藏信息的做法:加社會圖片文件為c:"s.jpg, 文字為d:"w.txt, 在命令行方式窗口中輸入命令   COPY /B C:"s.jpg + d:"w.txt   c:"d.jpg

            10. 獲得應用程序所在路徑

            char szCurPath[_MAX_PATH];

            HINSTANCE hInst = NULL;

            GetMoudleFileName( hInst, szCurPath, _MAX_PATH); //獲得應用程序所在路徑

            char *p = szCurPath;

            while( strchr(p, ‘""’)) {

                  p= strchr( p, ‘""’);

                  p++; }

            *p = ‘"0’;

            ShellExecute(NULL, NULL, _T(“Your.exe”), NULL, _T(szCurPath), SW_SHOWNORMAL);
             
            總結問題的解決方法,有助于獲得更多的實戰經驗,不斷地積累,在編程方面就會有長足的進步~!

            學習的過程是一個不斷積累的過程,只有學習的時間累積到一定的程度,才能發生質的提高。。。

             

             

            (1) 如何通過代碼獲得應用程序主窗口的 指針?
            主窗口的 指針保存在CWinThread::m_pMainWnd中,調用AfxGetMainWnd實現。
            AfxGetMainWnd() ->ShowWindow(SW_SHOWMAXMIZED)
            //使程序最大化.


            (2) 確定應用程序的路徑
            Use GetModuleFileName 獲得應用程序的路徑,然后去掉可執行文件名。
            Example:
            TCHAR
            exeFullPath[MAX_PATH] // MAX_PATH在API中定義了吧,好象是
            128
            GetModuleFileName(NULL,exeFullPath,MAX_PATH)

            (3) 如何在程序中獲得其他程序的 圖標?
            兩種方法:
            (1) SDK函數 SHGetFileInfo 或使用 ExtractIcon獲得圖標資源的 handle,
            (2) SDK函數 SHGetFileInfo 獲得有關文件的很多信息,如大小圖標,屬性, 類型等.
            Example(1):
            在程序窗口左上角顯示 NotePad圖標.
            void CSampleView:
            OnDraw(CDC * pDC)
            {
            if( :: SHGetFileInfo(_T("c:""pwin95""notepad.exe"),0,
            &stFileInfo,sizeof(stFileInfo),SHGFI_ICON))
            {
            pDC ->DrawIcon(10,10,stFileInfo.hIcon)
            }
            }
            Example(2):同樣功能,Use ExtractIcon Function
            void CSampleView:: OnDraw(CDC *pDC)
            {
            HICON hIcon=:: ExtractIcon(AfxGetInstanceHandle(),_T
            ("NotePad.exe"),0)
            if (hIcon &&hIcon!=(HICON)-1)
            pDC->DrawIcon(10,10,hIcon)
            }
                說明: 獲得notepad.exe的路徑正規上來說用GetWindowsDirectory函數得到, 如果是調用 win95下的畫筆,應該用訪問注冊表的方法獲得其路徑,要作成一個比較考究的程序,考慮應該全面點.

             


            (4) 獲得各種目錄信息
            Windows目錄: Use "GetWindowsDirectory"
            Windows下的system目錄: Use "GetSystemDirectory"
            temp目錄: Use "GetTempPath"
            當前目錄: Use "GetCurrentDirectory"

            請注意前兩個函數的第一個參數為目錄變量名,后一個為緩沖區后兩個相反.


            (5) 如何自定義消息
            1) 手工定義消息,可以這么寫
            #define WM_MY_MESSAGE(WM_USER+100),
            MS 推薦的至少是 WM_USER+100

            (2)寫消息處理函數,用
            WPARAM,LPARAM返回LRESULT.
            LRESULT CMainFrame::OnMyMessage(WPARAM wparam,LPARAM lParam)

            {
            temp目錄: Use "GetTempPath"
            //加入你的處理函數 irectory"
            }

            (6) 如何改變窗口的圖標?
            向窗口發送 WM_SECTION消息。
            Example:
            HICON hIcon=AfxGetApp() ->LoadIcon(IDI_ICON)
            ASSERT(hIcon)
            AfxGetMainWnd() ->SendMessage(WM_SECTION,TRUE,(LPARAM)hIcon)


            (7) 如何改變窗口的缺省風格?
            重載 CWnd:: PreCreateWindow 并修改CREATESTRUCT結構來指定窗口風格和其他創建信息.
            Example: Delete "Max" Button and Set Original
            Window's Position and Size

            BOOL CMainFrame:: PreCreateWindow
            (CREATESTRUCT &cs)
            {
            cs.style &=~WS_MAXINIZEMOX

            cs.x=cs.y=0
            cs.cx=GetSystemMetrics(SM_CXSCREEN/2)
            cs.cy=GetSystemMetrics(SM_CYSCREEN/2)

            return CMDIFramewnd ::PreCreateWindow(cs)
            }

            (8) 如何將窗口居中顯示?
            Call Function CWnd::
            Center Windows

            Example(1):
            Center Window( ) //Relative to it's parent
            // Relative
            to Screen
            Example(2):
            Center Window(CWnd:: GetDesktopWindow( ))
            //Relative to
            Application's MainWindow
            AfxGetMainWnd( ) ->
            Center Window( )


            (9) 如何讓窗口和 MDI窗口一啟動就最大化和最小化?
            先說窗口。
            在 InitStance 函數中設定 m_nCmdShow的取值.
            m_nCmdShow=SW_SHOWMAXMIZED //最大化
            m_nCmdShow=SW_SHOWMINMIZED //最小化
            m_nCmdShow=SW_SHOWNORMAL //正常方式

            MDI窗口:
            如果是創建新的應用程序,可以用MFC AppWizard 的Advanced 按鈕并在MDI子窗口風格組中檢測最大化或最小化還可以重載 MDI Window 的PreCreateWindow函數,設置WS_MAXMIZE or WS_MINMIZE

            如果從 CMDIChildWnd派生,調用 OnInitialUpdate函數中的 CWnd::Show Window來指定 MDI Child Window的風格。

            (10) 如何限制窗口的大小?
            也就是 FixedDialog形式。 Windows發送 WM_GETMAXMININFO消息來跟蹤, 響應它,在 OnGetMAXMININFO 中寫代碼:

            (11) 如何使窗口不可見?
            很簡單,用SW_HIDE 隱藏窗口,可以結合 FindWindow,ShowWindow控制.

            (12) 如何創建一個字回繞的CEditView
            重 載CWnd : : PreCreateWindow和修改CREATESTRUCT結構,關閉CEditView對象的ES_AUTOHSCROLL和WS_HSCROLL 風格位, 由于CEditView : : PreCreateWindow顯示設置cs. style,調用基類函數后要修改cs . style。

            BOOL CSampleEDitView : : PreCreateWindow (CREATESTRUCT&cs)
            {
            //First call basse class function .
            BOOL bResutl =CEditView : : PreCreateWindow (cs)

            // Now specify the new window style .
            cs.style &= ~ (ES_AUTOHSCROLL |WS_HSCROLL)
            return bResult
            }

            (13) 如何使程序保持極小狀態?
            這么辦: 在恢復程序窗體大小時,Windows會發送WM_QUERY-OPEN消息,用 ClassWizard設置成員函數
            OnQueryOpen() ,add following code:

            Bool CMainFrame:: OnQueryOpen( )
            {
            Return false
            }

            (14) 移動窗口
            調用CWnd : : SetWindowPos并指定SWP_NOSIZE標志。目的位置與父窗口有關(頂層窗口與屏幕有關)。調用CWnd : : MoveWindow時必須要指定窗口的大小。
            //Move window to positoin 100 , 100 of its parent window .
            SetWindowPos (NULL, 100 , 100 , 0 , 0 , SWP_NOSIZE |SWP_NOAORDER)

            (15) 通用控件的顯示窗口
            MFC 提供了幾個CView派生的視窗類, 封裝了通用控件的功能,但仍然使用工作框文檔顯示窗口體系結構:CEditView封裝了編輯控件,CTreeView保持了樹列表控 件,CListView封裝了列表顯示窗口控件,CRichEditView可以處理多種編輯控件。

            (16) 重置窗口的大小
            調用CWnd: : SetWindowPos并指定SWP_NOMOVE標志, 也可調用CWnd : : MoveWindow 但必須指定窗口的位置。
            // Get the size of the window .
            Crect reWindow
            GetWindowRect (reWindow )

            //Make the window twice as wide and twice as tall .
            SetWindowPos (NULL , 0 , 0 , reWindow . Width ( ) *2,

            reWindow . Height () * 2,
            SWP_NOMOVE |SWP_NOZORDER )

            (17) 如何單擊除了窗口標題欄以外的區域使窗口移動
            當 窗口需要確定鼠標位置時Windows向窗口發送WM_NCHITTEST信息,可以處理該信息使Windows認為鼠標在窗口標題上。對于對話框和基于 對話的應用程序,可以使用ClassWizard處理該信息并調用基類函數, 如果函數返回HTCLIENT 則表明鼠標在客房區域,返回HTCAPTION表明鼠標在Windows的標題欄中。
            UINT CSampleDialog : : OnNcHitTest (Cpoint point )
            {
            UINT nHitTest =Cdialog: : OnNcHitTest (point )
            return (nHitTest = =HTCLIENT)? HTCAPTION : nHitTest
            }

            上述技術有兩點不利之處,
            其一是在窗口的客戶區域雙擊時,窗口將極大;
            其二, 它不適合包含幾個視窗的主框窗口。
            還有一種方法,當用戶按下鼠標左鍵使主框窗口認為鼠標在其窗口標題上,使用ClassWizard在視窗中處理WM_LBUTTODOWN信息并向主框窗口發送一個WM_NCLBUTTONDOWN信息和一個單擊測試HTCAPTION。
            void CSampleView : : OnLButtonDown (UINT nFlags , Cpoint point
            )
            {
            CView : : OnLButtonDow (nFlags , pont )

            //Fool frame window into thinking somene clicked
            on
            its caption bar .
            GetParentFrame ( ) —> PostMessage (
            WM_NCLBUTTONDOWN ,
            HTCAPTION , MAKELPARAM (poitn .x , point .y) )

            }
            該技術也適用于對話框和基于對的應用程序,只是不必調用
            CWnd: :GetParentFrame 。
            void CSampleDialog : : OnLbuttonDown (UINT nFlags, Cpoint point )
            {
            Cdialog : : OnLButtonDow (nFlags, goint )
            //Fool dialog into thinking simeone clicked on its
            caption bar .
            PostMessage (WM_NCLBUTTONDOWN , HTCAPTION , MAKELPARM (point.x
            , point. y
            ) )
            }

            (18) 如何改變視窗的背景顏色
            Windows向窗口發送一個WM_ERASEBKGND消息通知該窗口擦除背景,可以使用ClassWizard重載該消息的缺省處理程序來擦除背景(實際是畫),并返回TRUE以防止Windows擦除窗口。
            //Paint area that needs to be erased.
            BOOL CSampleView : : OnEraseBkgnd (CDC* pDC)
            {
            // Create a pruple brush.
            CBrush Brush (RGB (128 , 0 , 128) )

            // Select the brush into the device context .
            CBrush* pOldBrush = pDC—>SelcetObject (&brush)

            // Get the area that needs to be erased .
            CRect reClip
            pDC—>GetCilpBox (&rcClip)
            //Paint the area.
            pDC—> PatBlt (rcClip.left , rcClip.top , rcClip.Width ( ) , rcClip.Height( ) , PATCOPY )

            //Unselect brush out of device context .
            pDC—>SelectObject (pOldBrush )

            // Return nonzero to half fruther processing .
            return TRUE
            }

            (19) 如何改變窗口標題
            調用CWnd : : SetWindowText可以改變任何窗口(包括控件)的標題。
            //Set title for application's main frame window .
            AfxGetMainWnd ( ) —> SetWindowText (_T("Application title") )

            //Set title for View's MDI child frame window .
            GetParentFrame ( ) —> SetWindowText ("_T ("MDI Child Frame new title")
            )

            //Set title for dialog's push button control.
            GetDigitem (IDC_BUTTON) —> SetWindowText (_T ("Button new title ") )
            如 果需要經常修改窗口的標題(注:控件也是窗口),應該考慮使用半文檔化的函數AfxSetWindowText。該函數在AFXPRIV.H中說明,在 WINUTIL.CPP中實現,在聯機幫助中找不到它,它在AFXPRIV.H中半文檔化, 在以后發行的MFC中將文檔化。
            AfxSetWindowText的實現如下:
            voik AFXAPI AfxSetWindowText (HWND hWndCtrl , LPCTSTR IpszNew )
            {
            itn nNewLen= Istrlen (Ipaznew)
            TCHAR szOld [256]
            //fast check to see if text really changes (reduces
            flash in the
            controls )
            if (nNewLen >_contof (szOld)
            || : : GetWindowText (hWndCrtl, szOld , _countof (szOld) !=nNewLen
            || Istrcmp (szOld , IpszNew)! = 0
            {
            //change it
            : : SetWindowText(hWndCtrl , IpszNew )
            }
            }

            (20) 如何防止主框窗口在其說明中顯示活動的文檔名
            創建主框窗口和MDI子窗口進通常具有FWS_ADDTOTITLE風格位,如果不希望在說明中自動添加文檔名, 必須禁止該風格位, 可以使用ClassWizard重置
            CWnd: : PreCreateWindow并關閉FWS_ADDTOTITLE風格。
            BOOL CMainFrame : : PreCreateWindow (CREATESTRUCT&cs)
            {
            //Turn off FWS_ADDTOTITLE in main frame .
            cs.styel & = ~FWS_ADDTOTITLE  
            return CMDIFrameWnd : : PreCreateWindow (cs )
            }
            關閉MDI子窗口的FWS _ADDTOTITLE風格將創建一個具有空標題的窗口,可以調用CWnd: : SetWindowText來設置標題。記住自己設置標題時要遵循接口風格指南。

            (21) 如何獲取有關窗口正在處理的當前消息的信息
            調用CWnd: : GetCurrentMessage可以獲取一個MSG指針。例如,可以使用ClassWizard將幾個菜單項處理程序映射到一個函數中,然后調用GetCurrentMessage來確定所選中的菜單項。
            viod CMainFrame : : OnCommmonMenuHandler ( )
            {
            //Display selected menu item in debug window .
            TRACE ("Menu item %u was selected . "n" ,

            (22) 如何在代碼中獲取工具條和狀態條的指針
            缺 省時, 工作框創建狀態條和工具條時將它們作為主框窗口的子窗口,狀態條有一個AFX_IDW_STATUS_BAR標識符,工具條有一個 AFX_IDW_TOOLBAR標識符,下例說明了如何通過一起調用CWnd: : GetDescendantWindow和AfxGetMainWnd來獲取這些子窗口的指針:
            //Get pointer to status bar .
            CStatusBar * pStatusBar = (CStatusBar *) AfxGetMainWnd ( )
            —> GetDescendantWindow(AFX_IDW_STUTUS_BAR)

            //Get pointer to toolbar .
            CToolBar * pToolBar = (CToolBar * ) AfxGetMainWnd ( )
            —> GetDescendantWindow(AFX_IDW_TOOLBAR)

            (23) 如何使能和禁止工具條的工具提示
            如 果設置了CBRS_TOOLTIPS風格位,工具條將顯示工具提示,要使能或者禁止工具提示,需要設置或者清除該風格位。下例通過調用 CControlBar : : GetBarStyle和CControlBar : : SetBarStyle建立一個完成此功能的成員函數:
            void CMainFrame : : EnableToolTips ( BOOL bDisplayTips )
            {
            ASSERT_VALID (m_wndToolBar)

            DWORD dwStyle = m _wndToolBar.GetBarStyle ( )

            if (bDisplayTips) dwStyle |=CBRS_TOOLTIPS

            else
            dwStyle & = ~CBRS_TOOLTIPS

            m_wndToolBar.SetBarStyle (dwStyle )
            }

            (24) 如何創建一個不規則形狀的窗口
            可以使用新的SDK函數SetWindowRgn。該函數將繪畫和鼠標消息限定在窗口的一個指定的區域,實際上使窗口成為指定的不規則形狀。 使用AppWizard創建一個基于對的應用程序并使用資源編輯器從主對話資源中刪除所在的缺省控件、標題以及邊界。
            給對話類增加一個CRgn數據成員,以后要使用該數據成員建立窗口區域。
            Class CRoundDlg : public CDialog
            {

            private :
            Crgn m_rgn : // window region

            }
            修改OnInitDialog函數建立一個橢圓區域并調用SetWindowRgn將該區域分配給窗口:
            BOOL CRoundDlg : : OnInitDialog ( )
            {
            CDialog : : OnInitDialog ( )

            //Get size of dialog .
            CRect rcDialog
            GetClientRect (rcDialog )

            // Create region and assign to window .
            m_rgn . CreateEllipticRgn (0 , 0 , rcDialog.Width( ) , rcDialog.Height ( ) )
            SetWindowRgn (GetSafeHwnd ( ) , (HRGN) m_ rgn ,TRUE )

            return TRUE
            }

            通過建立區域和調用SetWindowRgn,已經建立一個不規則形狀的窗口,下面的例子程序是修改OnPaint函數使窗口形狀看起來象一個球形體。
            voik CRoundDlg : : OnPaint ( )
            {
            CPaintDC de (this) // device context for painting
            .
            //draw ellipse with out any border
            dc. SelecStockObject (NULL_PEN)
            //get the RGB colour components of the sphere color
            COLORREF color= RGB( 0 , 0 , 255)
            BYTE byRed =GetRValue (color)
            BYTE byGreen = GetGValue (color)
            BYTE byBlue = GetBValue (color)

            // get the size of the view window
            Crect rect
            GetClientRect (rect)

            // get minimun number of units
            int nUnits =min (rect.right , rect.bottom )

            //calculate he horiaontal and vertical step size
            float fltStepHorz = (float) rect.right /nUnits
            float fltStepVert = (float) rect.bottom /nUnits


            int nEllipse = nUnits/3 // calculate how many to
            draw
            int nIndex
            // current ellipse that is being draw

            CBrush brush
            // bursh used for ellipse fill color
            CBrush *pBrushOld // previous
            brush that was selected into dc
            //draw ellipse , gradually moving towards upper-right
            corner
            for (nIndex = 0 nIndes < + nEllipse nIndes++)
            {
            //creat solid brush
            brush . CreatSolidBrush (RGB ( ( (nIndex*byRed ) /nEllipse ).
            ( ( nIndex * byGreen ) /nEllipse ), ( (nIndex * byBlue)
            /nEllipse ) ) )

            //select brush into dc
            pBrushOld= dc .SelectObject (&brhsh)

            //draw ellipse
            dc .Ellipse ( (int) fltStepHorz * 2, (int) fltStepVert * nIndex ,
            rect. right -( (int) fltStepHorz * nIndex )+ 1,
            rect . bottom -( (int) fltStepVert * (nIndex *2) ) +1)

            //delete the brush
            brush.DelecteObject ( )
            }
            }

            最后,處理WM_NCHITTEST消息,使當擊打窗口的任何位置時能移動窗口。
            UINT CRoundDlg : : OnNchitTest (Cpoint point )
            {
            //Let user move window by clickign anywhere on thewindow .
            UINT nHitTest = CDialog : : OnNcHitTest (point)
            rerurn (nHitTest = = HTCLIENT)? HTCAPTION: nHitTest

            }

            (25) 如何獲取應用程序的 實例句柄?
            應用程序的實例句柄保存在CWinApp m_hInstance 中,可以這么調用AfxGetInstancdHandle獲得句柄.
            Example: HANDLE hInstance=AfxGetInstanceHandle()

            (26) 如何編程結束應用程序?
            這是個很簡單又是編程中經常要遇到的問題.
            向窗口發送 WM_CLOSE消息,調用 CWnd::OnClose成員函數.允許對用戶提示是否保存修改過的數據.
            Example: AfxGetMainWindow()->SendMessage(WM_CLOSE)

            還可以創建一個自定義的函數 Terminate Window
            void Terminate Window(LPCSTR pCaption)
            {
            CWnd *pWnd=Cwnd::FindWindow(NULL,pCaption)

            if (pWnd)

            pWnd ->SendMessage(WM_CLOSE)
            }

                說 明: FindWindow函數不是提倡的做法,因為它無法處理標題欄自動改變,比如我們要檢測 Notepad是不是已運行而事先不知道Notepad的標題欄,這時FindWindow就無能為力了,可以通過枚舉 windows任務列表的辦法來實現。在機械出版社"Windows 95 API開發人員指南"一書有比較詳細的介紹,這里就不再多說樂。

            (27) 如何創建和使用無模式對話框
            MFC 將模式和無模式對話封裝在同一個類中,但是使用無模式對話需要幾個對話需要幾個額處的步驟。首先,使用資源編輯器建立對話資源并使用 ClassWizard創建一個CDialog的派生類。模式和無模式對話的中止是不一樣的:模式對話通過調用CDialog : : EndDialog 來中止,無模式對話則是調用CWnd: : DestroyWindow來中止的,函數CDialog : : OnOK和CDialog : : OnCancel調用EndDialog ,所以需要調用DestroyWindow并重置無模式對話的函數。
            void CSampleDialog : : OnOK ( )
            {
            // Retrieve and validate dialog data .
            if (! UpdateData (TRUE) )
            {
            // the UpdateData rountine
            will set focus to correct item TRACEO (" UpdateData failed during dialog termination ."n")
            return
            }

            //Call DestroyWindow instead of EndDialog .
            DestroyWindow ( )
            }

            void CSampleDialog : : OnCancel ( )
            {
            //Call DestroyWindow instead of EndDialog .
            DestroyWindow ( )
            }

            其 次,需要正確刪除表示對話的C++對象。對于模式對來說,這很容易,需要創建函數返回后即可刪除C++對象;無模式對話不是同步的,創建函數調用后立即返 回,因而用戶不知道何時刪除C++對象。撤銷窗口時工作框調用CWnd : : PostNcDestroy,可以重置該函數并執行清除操作,諸如刪除this指針。
            void CSampleDialog : : PostNcDestroy ( )
            {
            // Declete the C++ object that represents this dialog.
            delete this

            最后,要創建無模式對話。可以調用CDialog : : DoModal創建一個模式對放,要創建一個無模式對話則要調用CDialog: : Create。下面的例子說明 了應用程序是如何創建無模式對話的: 象;無模式對話不是同步的,創建函數調用后立即返回,
            void CMainFrame : : OnSampleDialog ( )
            {
            //Allocate a modeless dialog object .
            CSampleDilog * pDialog =new CSampleDialog
            ASSERT_VALID (pDialog) Destroy ( )

            //Create the modeless dialog . represents this dialog.
            BOOL bResult = pDialog —> Creste (IDD_IDALOG)
            ASSERT (bResult )
            }

            (28) 如何防止主框窗口在其說明中顯示活動的文檔名
            創建主框窗口和MDI子窗口進通常具有FWS_ADDTOTITLE風格位,如果不希望在說明中自動添加文檔名, 必須禁止該風格位, 可以使用ClassWizard重置
            CWnd: : PreCreateWindow并關閉FWS_ADDTOTITLE風格。
            BOOL CMainFrame : : PreCreateWindow (CREATESTRUCT&cs)
            {
            //Turn off FWS_ADDTOTITLE in main frame .
            cs.styel & = ~FWS_ADDTOTITLE  
            return CMDIFrameWnd : : PreCreateWindow (cs )
            }
            關閉MDI子窗口的FWS _ADDTOTITLE風格將創建一個具有空標題的窗口,可以調用CWnd: : SetWindowText來設置標題。記住自己設置標題時要遵循接口風格指南。

            (29) 如何在代碼中獲取工具條和狀態條的指針
            缺 省時, 工作框創建狀態條和工具條時將它們作為主框窗口的子窗口,狀態條有一個AFX_IDW_STATUS_BAR標識符,工具條有一個 AFX_IDW_TOOLBAR標識符,下例說明了如何通過一起調用CWnd: : GetDescendantWindow和AfxGetMainWnd來獲取這些子窗口的指針:
            //Get pointer to status bar .
            CStatusBar * pStatusBar = (CStatusBar *) AfxGetMainWnd ( )
            —> GetDescendantWindow(AFX_IDW_STUTUS_BAR)

            //Get pointer to toolbar .
            CToolBar * pToolBar = (CToolBar * ) AfxGetMainWnd ( )
            —> GetDescendantWindow(AFX_IDW_TOOLBAR)


            (30) 怎樣加載其他的應用程序?
            三個SDK函數 winexec, shellexecute,createprocess可以使用。
            WinExec最簡單,兩個參數,前一個指定路徑,后一個指定顯示方式.后一個參數值得說一下,比如泥用 SW_SHOWMAXMIZED方式去加載一個無最大化按鈕的程序,就是Neterm,calc等等,就不會出現正常的窗體,但是已經被加到任務列表里了。

            ShellExecute 較 WinExex靈活一點,可以指定工作目錄,下面的Example就是直接打開 c:"temp"1.txt,而不用加載與 txt文件關聯的應用程序,很多安裝程序完成后都會打開一個窗口,來顯示Readme or Faq,我猜就是這么作的啦.

            ShellExecute(NULL,NULL,_T("1.txt"),NULL,_T("c:""temp"),SW_SHOWMAXMIZED)

            CreateProcess最復雜,一共有十個參數,不過大部分都可以用NULL代替,它可以指定進程的安全屬性,繼承信息,類的優先級等等.來看個很簡單的Example:
            STARTUPINFO stinfo
            //啟動窗口的信息
            PROCESSINFO procinfo //進程的信息

            CreateProcess(NULL,_T("notepad.exe"),NULL,NULL.FALSE,
            NORMAL_PRIORITY_

            CLASS,NULL,NULL, &stinfo,&procinfo)

            (31) 如何在代碼中獲取工具條和狀態條的指針
            缺 省時, 工作框創建狀態條和工具條時將它們作為主框窗口的子窗口,狀態條有一個AFX_IDW_STATUS_BAR標識符,工具條有一個 AFX_IDW_TOOLBAR標識符,下例說明了如何通過一起調用CWnd: : GetDescendantWindow和AfxGetMainWnd來獲取這些子窗口的指針:
            //Get pointer to status bar .
            CStatusBar * pStatusBar = (CStatusBar *) AfxGetMainWnd ( )
            —> GetDescendantWindow(AFX_IDW_STUTUS_BAR)

            (32) 如何使能和禁止工具條的工具提示
            如 果設置了CBRS_TOOLTIPS風格位,工具條將顯示工具提示,要使能或者禁止工具提示,需要設置或者清除該風格位。下例通過調用 CControlBar : : GetBarStyle和CControlBar : : SetBarStyle建立一個完成此功能的成員函數:
            void CMainFrame : : EnableToolTips ( BOOL bDisplayTips )
            {
            ASSERT_VALID (m_wndToolBar)

            DWORD dwStyle = m _wndToolBar.GetBarStyle ( )

            if (bDisplayTips) dwStyle |=CBRS_TOOLTIPS

            else
            dwStyle & = ~CBRS_TOOLTIPS

            m_wndToolBar.SetBarStyle (dwStyle )
            }

            //Get pointer to toolbar .
            CToolBar * pToolBar = (CToolBar * ) AfxGetMainWnd ( )
            —> GetDescendantWindow(AFX_IDW_TOOLBAR)

            (33) 如何設置工具條標題
            工具條是一個窗口,所以可以在調用CWnd : : SetWindowText來設置標題,例子如下:
            int CMainFrame : : OnCreate (LPCREATESTRUCT lpCreateStruct )
            {

            // Set the caption of the toolbar .
            m_wndToolBar.SetWindowText (_T "Standdard")

            (34) 如何使窗口始終在最前方?
            BringWindowToTop(Handle)
            SetWindowPos函數,指定窗口的 最頂風格,用WS_EX_TOPMOST擴展窗口的風格

            Example:
            void ToggleTopMost(
            CWnd *pWnd)
            {
            ASSERT_VALID(pWnd)

            pWnd ->SetWindowPos(pWnd-> GetStyle( ) &WS_EX_TOPMOST)?

            &wndNoTopMOST: &wndTopMost,0,0,0,0,SSP_NOSIZE|WSP_NOMOVE)
            }

            (35) 如何在對話框中顯示一個位圖
            這要歸功于Win 32先進的靜態控件和Microsoft的資源編輯器,在對話框中顯示位圖是很容易的, 只需將圖形控件拖到對話中并選擇適當屬性即可,用戶也可以顯示圖標、位圖以及增強型元文件。

            (36) 如何改變對話或窗體視窗的背景顏色
            調用CWinApp : : SetDialogBkColor可以改變所有應用程序的背景顏色。第一個參數指定了背景顏色,第二個參數指定了文本顏色。下例將應用程序對話設置為藍色背景和黃色文本。
            BOOL CSampleApp : : InitInstance ( )
            {


            //use blue dialog with yellow text .
            SetDialogBkColor (RGB (0, 0, 255 ), RGB ( 255 ,255 , 0 ) )


            }

            需要重畫對話(或對話的子控件)時,Windows向對話發送消息WM_CTLCOLOR,通常用戶可以讓Windows選擇繪畫背景的刷子,也可重置該消息指定刷子。下例說明了創建一個紅色背景對話的步驟。

            首先,給對話基類增加一人成員變量
            CBursh :class CMyFormView : public CFormView
            {


            private :
            CBrush m_ brush // background brush


            }

            其次, 在類的構造函數中將刷子初始化為所需要的背景顏色。
            CMyFormView : : CMyFormView ( )
            {
            // Initialize background brush .
            m_brush .CreateSolidBrush (RGB ( 0, 0, 255) )
            }

            最后,使用ClassWizard處理WM_CTLCOLOR消息并返回一個用來繪畫對話背景的刷子句柄。注意:由于當重畫對話控件時也要調用該函數,所以要檢測nCtlColor參量。
            HBRUSH CMyFormView : : OnCtlColor (CDC* pDC , CWnd*pWnd , UINT nCtlColor
            )

            {
            // Determine if drawing a dialog box . If we are, return +handle to
            //our own background brush . Otherwise let windows handle it .
            if (nCtlColor = = CTLCOLOR _ DLG )
            return (HBRUSH) m_brush.GetSafeHandle ( )
            return CFormView : : OnCtlColor (pDC, pWnd , nCtlColor
            )
            }

            (37) 如何獲取一個對話控件的指針
            有兩種方法。其一,調用CWnd: : GetDlgItem,獲取一個CWnd*指針調用成員函數。下例調用GetDlgItem,將返回值傳給一個CSpinButtonCtrl*以便調用CSpinButtonCtrl : : SetPos 函數:
            BOOL CSampleDialog : : OnInitDialog ( )
            {
            CDialog : : OnInitDialog ( )

            //Get pointer to spin button .
            CSpinButtonCtrl * pSpin - ( CSpinButtonCtrl *) GetDlgItem(IDC_SPIN)
            ASSERT _ VALID (pSpin)
            //Set spin button's default position .
            pSpin —> SetPos (10)

            return TRUE
            }

            其 二, 可以使用ClassWizard將控件和成員變量聯系起來。在ClassWizard中簡單地選擇Member Variables標簽,然后選擇Add Variable …按鈕。如果在對話資源編輯器中,按下Ctrl鍵并雙擊控件即可轉到Add Member Variable對話。

            (38) 如何禁止和使能控件
            控件也是窗口,所以可以調用CWnd : : EnableWindow使能和禁止控件。
            //Disable button controls .
            m_wndOK.EnableWindow (FALSE )
            m_wndApply.EnableWindow (FALSE )

            (39) 如何改變控件的字體
            由于控件是也是窗口,用戶可以調用CWnd: : SetFont指定新字體。該函數用一個Cfont指針,要保證在控件撤消之前不能撤消字體對象。下例將下壓按鈕的字體改為8點Arial字體:
            //Declare font object in class declaration (.H file ).
            private : Cfont m_font
            // Set font in class implementation (.Cpp file ). Note m_wndButton is a
            //member variable added by ClassWizard.DDX routines hook the member
            //variable to a dialog button contrlo.
            BOOL CSampleDialog : : OnInitDialog ( )
            {

            //Create an 8-point Arial font
            m_font . CreateFont (MulDiv (8 , -pDC
            —> GetDeviceCaps(LOGPIXELSY) ,72). 0 , 0 , 0 , FW_NORMAL , 0 , 0,0, ANSI_CHARSER, OUT_STROKE_PRECIS ,

            CLIP_STROKE _PRECIS , DRAFT _QUALITY
            VARIABLE_PITCH |FF_SWISS, _T("Arial") )

            //Set font for push button .
            m_wndButton . SetFont (&m _font )


            }

            (40) 如何在OLE控件中使用OLE_COLOR數據類型
            諸 如COleControl : : GetFortColor和COleControl : : GetBackColor等函數返回OLE _COLOR數據類型的顏色,而GDI對象諸如筆和刷子使用的是COLORREF數據類型,調用COleControl : : TranslateColor可以很容易地將OLE_COLOR類型改為COLORREF類型。下例創建了一個當前背景顏色的刷子:

            void CSampleControl : : OnDraw (CDC* pdc
            const Crect& rcBounds , const Crect& rcInvalid
            )
            {
            //Create a brush of the cuttent background color.
            CBrush brushBack (TranslateColor (GetBackColor () ) )

            //Paint the background using the current backgroundcolor .
            pdc—> FilllRect (rcBounds , &brushBack)

            //other drawign commands


            }

             

             

            (41) 在不使用通用文件打開對話的情況下如何顯示一個文件列表
            調用CWnd: : DlgDirList或者CWnd: : DlgDirListComboBox,Windows 將自動地向列表框或組合框填充可用的驅動器名或者指定目錄中的文件,下例將Windows目錄中的文件填充在組合框中:
            BOOL CSampleDig : : OnInitDialog ( )
            {
            CDialog : : OnInitDialog ( )
            TCHAR szPath [MAX_PATH] = {"c:""windows"}
            int nReslt = DlgDirListComboBox (szPath, IDC_COMBO , IDC_CURIDIR, DDL_READWRITE |DDL_READONLY|DDL_HIDDEN| DDL_SYSTEM|DDL_ARCHIVE)
            return TRUE
            }

            (42) 為什么旋轉按鈕控件看起來倒轉
            需要調用CSpinCtrl : : SetRange 設置旋轉按鈕控件的范圍,旋轉按鈕控件的缺省上限為0,缺省下限為100,這意味著增加時旋轉按控件的值由100變為0。下例將旋轉按鈕控件的范圍設置為0到100:
            BOOL CAboutDlg : : OnInitDialog ( )
            {
            CDialog : : OnInitDialog ( )

            //set the lower and upper limit of the spin button
            m_wndSpin . SetRange ( 0 ,100 )

            return TRUE
            }

            Visual C++ 4.0 Print對話中的Copise旋轉按鈕控件也有同樣的問題:按下Up按鈕時拷貝的數目減少,而按下Down 按鈕時拷貝的數目增加。

            (43) 為什么旋轉按鈕控件不能自動地更新它下面的編輯控件
            如果使用旋轉按鈕的autu buddy特性, 則必須保證在對話的標記順序中buddy窗口優先于旋轉按鈕控件。從Layout菜單中選擇Tab Order菜單項(或者按下Crtl+D)可以設置對話的標簽順序。

            (44) 如何用位圖顯示下壓按鈕
            Windows 95按鈕有幾處新的創建風格,尤其是BS_BITMAP和BS_ICON,要想具有位圖按鈕,創建按鈕和調用CButton : : SetBitmap或CButton : : SetIcon時要指定BS_BITMAP或BS_ICON風格。

            首先,設置按鈕的圖標屬性。然后,當對話初始化時調用CButton: : SetIcon。注意:下例用圖標代替位圖,使用位圖時要小心,因為不知道背景所有的顏色——并非每個人都使用淺灰色。

            BOOL CSampleDlg : : OnInitDialog ( )
            {
            CDialog : : OnInitDialog ( )

            //set the images for the push buttons .
            BOOL CSampleDlg : : OnInitDialog ( )
            {
            CDialog : : OnInitDialog ( )

            //set the images for the push buttons .
            m_wndButton1.SetIcon (AfxGetApp ( ) —> LoadIcon (IDI _ IPTION1))
            m_wndButton2.SetIcon (AfxGetApp ( ) —> LoadIcon (IDI _ IPTION2))
            m_wndButton3.SetIcon (AfxGetApp ( ) —> LoadIcon (IDI _ IPTION3))

            return TRUE
            }

            (45) 如何一個創建三態下壓按鈕
            可以使用新的BS_PUSHBUTTON 風格位和檢測框以及按鈕來創建一個三態下壓按鈕。這很容易,只需將檢測框和按鈕拖拉到對話中并指定屬性Push—like即可。不用任何附加程序就可以成為三態下壓按鈕。

            (46) 如何動態創建控件
            分配一個控件對象的實例并調用其Create成員函數。開發者最容易忽略兩件事:忘記指定WS_VISBLE標簽和在棧中分配控件對象。下例動態地創建一個下壓按鈕控件:
            //In class declaration (.H file ).
            private : CButton* m _pButton

            //In class implementation (.cpp file ) .
            m_pButton =new CButton
            ASSERT_VALID (m_pButton)
            m_pButton —>Create (_T ("Button Title ") , WS_CHILD |WS_VISIBLE |BS_PUSHBUTTON. Crect ( 0, 0, 100 , 24) , this , IDC _MYBUTTON )

            (47) 如何限制編輯框中的準許字符
            如 果用戶在編輯控件中只允許接收數字,可以使用一個標準的編輯控件并指定新的創建標志ES_NUMBERS,它是Windows 95新增加的標志,該標志限制 編輯控件只按收數字字符。如果用戶需要復雜的編輯控件,可以使用Microsoft 的屏蔽編輯控件,它是一個很有用的OLE定制控件。
            如果希望不使用OLE 定制控件自己處理字符,可以派生一個CEdit類并處理WM_CHAR消息,然后從編輯控件中過濾出特定的字符。首先,使用ClassWizard建立一 個 CEdit的派生類,其次,在對話類中指定一個成員變量將編輯控件分類在OnInitdialog 中調用CWnd: : SubclassDlgItem .

            //In your dialog class declaration (.H file )
            private : CMyEdit m_wndEdit // Instance of your new edit control .

            //In you dialog class implementation (.CPP file )
            BOOL CSampleDialog : : OnInitDialog ( )
            {


            //Subclass the edit lontrod .
            m_wndEdit .SubclassDlgItem (IDC_EDIT,this)


            }

            使用ClassWizard處理WM_CHAR消息,計算nChar參量并決定所執行的操作,用戶可以確定是否修改、傳送字符。下例說明了如何顯示字母字符,如果字符是字母字符,則調用CWnd OnChar,否則不調用OnChar.
            //Only display alphabetic dharacters .
            void CMyEdit : : OnChar (UINT nChar , UINT nRepCnt , UITN nFlags )
            {
            //Determine if nChar is an alphabetic character.
            if (: : IsCharAlpha ( ( TCHAR) nChar ) )
            CEdit : : OnChar (nChar, nRepCnt , nFlags )
            }

            如 果要修改字符,則不能僅僅簡單地用修改過的nChar調用CEdit: : OnChar,然后CEdit: : OnChar調用CWnd: : Default獲取原來的wParam 和lParam 的值,這樣是不行的。要修改一個字符,需要首先修改nChar,然后用修改過的nChar調用CWnd: : DefWindowProc。下例說明了如何將字符轉變為大寫:
            //Make all characters uppercase
            void CMyEdit : : OnChar (UINT nChar , UINT nRepCnt , UINT nFlags )
            {
            //Make sure character is uppercase .
            if (: : IsCharAlpha ( .( TCHAR) nChar)
            nChar=: : CharUpper(nChar )

            //Bypass default OnChar processing and directly call
            //default window proc.
            DefWindProc (WM_CHAR, nChar , MAKELPARAM (nRepCnt, nFlags ))
            }

            (48) 如何改變控件的顏色
            有 兩種方法。其一,可以在父類中指定控件的顏色,或者利用MFC4.0新的消息反射在控件類中指定顏色。 當控件需要重新著色時,工作框調用父窗口(通常是對話框)的CWnd: : OnCrtlColor,可以在父窗口類中重置該函數并指定控件的新的繪畫屬性。例如,下述代碼將對話中的所有編輯控件文本顏色改為紅色:
            HBRUSH CAboutDig : : OnCtlColor (CDC * pDCM , CWnd * pWnd , UINT nCtlColor)

            {
            HBRUSH hbr = CDialog : : OnCtlColor (pDC, pWnd , nCtlColor )

            //Draw red text for all edit controls .
            if (nCtlColor= = CTLCOLOR_EDIT )
            pDC —> SetTextColor (RGB (255, 0 , 0 , ) )

            return hbr
            }

            然 而,由于每個父窗口必須處理通知消息并指定每個控件的繪畫屬性,所以,這種方法不是完全的面向對象的方法。控件處理該消息并指定繪畫屬性更合情合理。消息 反射允許用戶這樣做。通知消息首先發送給父窗口,如果父窗口沒有處理則發送給控件。創建一個定制彩色列表框控件必須遵循下述步驟。

            首先,使用ClassWizard 創建一個CListBox 的派生類并為該類添加下述數據成員。
            class CMyListBox publilc CListBox
            {

            private
            COLORREF m_clrFor // foreground color
            COLORREF m_clrBack //background color
            Cbrush m_brush //background brush

            }
            其次,在類的構造函數中,初始化數據中。
            CMyListBox : : CMyListBox ()
            {
            //Initialize data members .
            m_clrFore =RGB (255 , 255 , 0) //yellow text
            m_clrBack=RGB (0 , 0 , 255) // blue background
            m_brush . CreateSolidBrush (m _clrBack )
            }

            最后,使用ClassWizard處理反射的WM_CTLCOLOR(=WM_CTLCOLOR)消息并指定新的繪畫屬性。
            HBRUSH CMyListBox : : CtlColor (CDC* pDC, UINT nCtlColor )
            {
            pDC—>SetTextColor (m_clrFore)
            pDC—>SetBkColor (m_clrBack)

            return (HBRUSH) m_brush.GetSafeHandle ()
            }
            現在,控件可以自己決定如何繪畫,與父窗口無關。

            (49) 當向列表框中添加多個項時如何防止閃爍
            調 用CWnd::SetRedraw 清除重畫標志可以禁止CListBox(或者窗口)重畫。當向列表框添加幾個項時,用戶可以清除重畫標志,然后添加項,最后恢復重畫標志。為確保重畫列表 框的新項,調用SetRedraw (TRUE) 之后調用CWnd::Invalidate。

            //Disable redrawing.
            pListBox->SetRedraw (FALSE)

            //Fill in the list box gere
            //Enable drwing and make sure list box is redrawn.
            pListBox->SetRedraw (TRUE)
            pListBox->Invalidate ()

            (50) 如何向編輯控件中添加文本
            由于沒有CEdit:: AppendText函數,用戶只好自己做此項工作。調用CEdit:: SetSel移動到編輯控件末尾,然后調用CEdit:: ReplaceSel添加文本。下例是AppendText 的一種實現方法:

            void CMyEdit:: AppendText (LPCSTR pText)
            {
            int nLen=GetWindowTextLength ()
            SetFocus ()
            SetSel (nLen, nLen)

            ReplaceSel (pText)
            }

            (51) 如何訪問預定義的GDI對象
            可以通過調用CDC:: SlectStockObject使用Windows的幾個預定義的對象,諸如刷子、筆以及字體。下例使用了Windows預定義的筆和刷子GDI對象在視窗中畫一個橢圓。
            //Draw ellipse using stock black pen and gray brush.
            void CSampleView:: OnDraw (CDC* pDC)
            {
            //Determine size of view.
            CRect rcView
            GetClientRect (rcView)

            //Use stock black pen and stock gray brush to draw ellipse.
            pDC->SelectStockObject (BLACK_PEN)
            pDC->SelectStockObject (GRAY_BRUSH)
            //Draw the ellipse.
            pDC->Ellipse (reView)
            }

            也可以調用新的SDK函數GetSysColorBrush獲取一個系統顏色刷子,下例用背景色在視窗中畫一個橢圓:
            void CsampleView:: OnDraw (CDC* pDC)
            {
            //Determine size of view.
            CRect rcView
            GetClientRect (rcView)

            //Use background color for tooltips brush.
            CBrush * pOrgBrush=pDC->SelectObject ( CBrush ::FromHandle( ::GetSysColorBrush (COLOR_INFOBK)))

            //Draw the ellipse.
            pDC->Ellipse (rcView)

            //Restore original brush.
            pDC->SelectObject (pOrgBrush)
            }

            (52) 如何獲取GDI對象的屬性信息
            可以調用GDIObject:: GetObject。這個函數將指定圖表設備的消息寫入到緩沖區。下例創建了幾個有用的輔助函數。
            //Determine if font is bold.
            BOOL IsFontBold (const CFont&font)
            {
            LOGFONT stFont
            font.GetObject (sizeof (LOGFONT), &stFont)
            return (stFont.lfBold)? TRUE: FALSE
            }

            //Return the size of a bitmap.
            CSize GetBitmapSize (const CBitmap&bitmap)
            {
            BITMAP stBitmap
            bitmap.GetObject (sizeof (BITMAP), &stBitmap)
            return CSize (stBitmap.bmWidth, stBitmap.bmHeight)
            }

            //Create a pen with the same color as a brush.
            BOOL CreatePenFromBrush (Cpen&pen, cost Cbrush&brush)
            {
            LOGBRUSH stBrush
            brush.Getobject (sizeof (LOGBRUSH), &stBrush)
            return pen. Createpen (PS_SOLID, 0, stBrush.ibColor)
            }

            (53) 如何實現一個橡皮區矩形
            CRectTracker是一個很有用的類,可以通過調用CRectTracker::TrackRubberBand 響應WM_LBUTTONDOWN消息來創建一個橡皮區矩形。
            下例表明使用CRectTracker移動和重置視窗中的藍色橢圓的大小是很容易的事情。

            首先,在文件檔中聲明一個CRectTracker數據成員:
            class CSampleView : Public CView
            {

            public :
            CrectTracker m_tracker

            }

            其次,在文檔類的構造函數中初始化CRectTracker 對象:
            CSampleDoc:: CSampleDOC ()
            {
            //Initialize tracker position, size and style.
            m_tracker.m_rect.SetRect (0, 0, 10, 10)
            m_tracker.m_nStyle=CRectTracker:: resizeInside | CRectTracker ::dottedLine
            }

            然后,在OnDraw函數中畫橢圓和蹤跡矩形:
            void CSampleView:: OnDraw (CDC* pDC)
            {
            CSampleDoc* pDoc=GetDocument ()
            ASSERT_VALID (pDoc)

            //Select blue brush into device context.
            CBrush brush (RGB (0, 0, 255))
            CBrush* pOldBrush=pDC->SelectObject (&brush)

            //draw ellipse in tracking rectangle.
            Crect rcEllipse
            pDoc->m_tracker.GetTrueRect (rcEllipse)
            pDC->Ellipse (rcEllipse)

            //Draw tracking rectangle.
            pDoc->m_tracker.Draw (pDC)
            //Select blue brush out of device context.
            pDC->Selectobject (pOldBrush)
            }

            最后,使用ClassWizard處理WM_LBUTTONDOWN消息,并增加下述代碼。該段代碼根據鼠標擊鍵情況可以拖放、移動或者重置橢圓的大小。
            void CSampleView::OnLButtonDown (UINT nFlags, CPoint point)
            {
            //Get pointer to document.
            CSampleDoc* pDoc=GetDocument ()
            ASSERT_VALID (pDoc)

            //If clicked on ellipse, drag or resize it.Otherwise create a
            //rubber-band rectangle nd create a new ellipse.
            BOOL bResult=pDoc->m_tracker.HitTest (point)!= CRectTracker::hitNothing

            //Tracker rectangle changed so update views.
            if (bResult)
            {
            pDoc->m_tracker.Track (this,point,TRue)
            pDoc->SetModifiedFlag ()
            pDoc->UpdateAllViews (NULL)
            }

            else
            pDoc->m-tracker.TrackRubberBand(this,point,TRUE)
            CView:: onLButtonDown (nFlags,point)
            }

            (54) 如何更新翻轉背景顏色的文本
            調 用CDC:: SetBkmode并傳送OPAQUE用當前的背景顏色填充背景,或者調用CDC::SetBkMode并傳送TRANSPAARENT使背景保持不變, 這兩種方法都可以設置背景模式。下例設置背景模式為TRANSPARENT,可以兩次更新串,用花色帶黑陰影更新文本。黑色串在紅色串之后,但由于設置了 背景模式仍然可見。

            void CSampleView:: OnDraw (CDC* pDC)
            {
            //Determint size of view.
            CRect rcView
            GetClientRect (rcVieew)

            //Create sample string to display.
            CString str (_T ("Awesome Shadow Text..."))
            //Set the background mode to transparent.
            pDC->SetBKMode (TRANSPARENT)

            //Draw black shadow text.
            rcView.OffsetRect (1, 1)
            pDc->SetTextColor (RGB (0, 0, 0))
            pDC->DrawText (str, str.GetLength (), rcView, DT_SINGLELINE | DT_CENTER | DT_VCENTER)

            //Draw red text.
            rcView.OffsetRect (-1,-1)
            pDc->SetTextColor (RGB (255, 0, 0))
            pDC->DrawText (str, str.GetLength (), rcView, DT_SINGLELINE | DT_CENTER | DT_VCENTER)

            }

            (55) 如何創建一個具有特定點大小的字體
            可以指定字體邏輯單位的大小,但有時指定字體的點的大小可能會更方便一些。可以如下將字體的點轉換為字體的高度:

            int nHeigth=mulDiv (nPointSize, -dc.GetDeviceCaps (LOGPIXELSY), 72)
            下例創建了一個8點的Apial字體:

            CClientDC dc (AqfxGetMainWnd ())

            m_font. CreateFont (MulDiv (8, -dc.GetDeviceCaps (LOGPIXELSY), 72), 0, 0, 0, FW_NORMAL, 0, 0, 0, ANSI_CHARSET, OUT_STROKE_PRECIS, CLIP_STROKE_PRECIS, DRAFT_QUALITY, VARIABLE_PITCH | FF-SWISS,_T("Arial"))

            (56) 如何計算一個串的大小
            函數CDC:: Det text Extent 根據當前選擇的字體計算一個串的高度和寬度。如果使用的不是系統字體而是其他字體,則在調用GetTextExtent之前將字體選進設備上下文中是很重 要的,否則計算高度和寬度時將依據系統字體,由此得出的結果當然是不正確的。下述樣板程序當改變下壓按鈕的標題時動態調整按鈕的大小,按鈕的大小由按鈕的 字體和標題的大小而定。響應消息WM_SETTEXT時調用OnSetText,該消息使用ON_MESSAE宏指令定義的用戶自定義消息。

            LRESULT CMyButton:: OnSettext (WPARAM wParam, LPARAM lParam)
            {
            //Pass message to window procedure.
            LRESULT bResult=CallWindowProc (*GetSuperWndProcAddr(), m_hWnd, GetCurrentMessage() ->message,wParam,lParam)
            //Get title of push button.
            CString strTitle
            GetWindowText (strTitle)

            //Select current font into device context.
            CDC* pDC=GetDc ()
            CFont*pFont=GetFont ()
            CFont*pOldFont=pDC->SelectObject (pFont)

            //Calculate size of title.
            CSize size=pDC->GetTextExent (strTitle,strTitle.GetLength())

            //Adjust the button's size based on its title.
            //Add a 5-pixel border around the button.
            SetWindowPos (NULL, 0, 0, size.cx+10, size.cy+10, SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE)
            //Clean up.
            pDC->SelectFont (pOldFont)
            ReleaseDC (pDC)

            return bResult
            }

            (57) 如何顯示旋轉文本
            只 要用戶使用TrueType或者GDI筆或字體就可以顯示旋轉文本(有些硬件設備也支持旋轉光柵字體)。LOGFONT結構中的ifEscapement 成員指定了文本行和x軸的角度,角度的單位是十分之一度而不是度,例如,ifEscapement為450表示字體旋轉45度。為確保所有的字體沿坐標系 統的同一方向旋轉,一定要設置ifEscapement成員的CLIP_LH_ANGLES位,否則,有些字體可能反向旋轉。下例使用了14點Arial 字體每間隔15度畫一個串。
            void CSampleView:: OnDraw (CDC* pDC)
            {
            //Determine the size of the window.
            CRect rcClient
            GetClientRect (rcClient)

            //Create sample string.
            CString str (_T ("Wheeee...I am rotating!"))
            //Draw transparent, red text.
            pDC->SetBkMode (TRANSPARENT)
            pDC->SetTextColor (RGB (255,0,0))
            CFont font
            //font object
            LOGFONT stFont //font definition
            //Set font attributes that will not change.
            memset (&stFont, 0, sizeof (LOGFONT))
            stFont.ifheight=MulDiv (14, -pDC->GetDeviceCaps(LOGPIXELSY), 72)
            stFont.ifWeight=FW_NORMAL
            stFont.ifClipPrecision=LCIP_LH_ANGLES
            strcpy (stFont.lfFaceName, "Arial")

            //Draw text at 15degree intervals.
            for (int nAngle=0 nAngle<3600 nAngle+=150)
            {
            //Specify new angle.
            stFont.lfEscapement=nAngle

            //Create and select font into dc.
            font.CreateFontIndirect(&stfont)
            CFont* pOldFont=pDC ->SelectObject(&font)

            //Draw the text.
            pDC->SelectObject(pOldFont)
            font.DelectObjext()
            }
            }

            (58) 如何正確顯示包含標簽字符的串
            調 用GDI文本繪畫函數時需要展開標簽字符,這可以通過調用CDC:: TabbedTextOut或者CDC:: DrawText并指定DT_EXPANDTABS標志來完成。TabbedTextOut函數允許指定標簽位的數組,下例指定每20設備單位展開一個標 簽:

            void CSampleView:: OnDraw (CDC* pDC)
            {
            CTestDoc* pDoc=GetDocument ()
            ASSERT_VALID (pDoC)

            CString str
            str.Format (_T ("Cathy"tNorman"tOliver"))
            int nTabStop=20 //tabs are every 20 pixels
            pDC->TabbedtextOut (10, 10, str, 1, &nTabStop, 10)
            }

            (59) 如何快速地格式化一個CString對象
            調用CString:: Format,該函數和printf函數具有相同的參數,下例說明了如何使用Format函數:

            //Get size of window.
            CRect rcWindow
            GetWindowRect (rcWindow)
            //Format message string.
            CString strMessage
            strMessage.Format (_T ("Window Size (%d, %d)"),

            rcWindow.Width (), rcWindow.Height ())

            //Display the message.
            MessageBox (strmessage)

            (60) 串太長時如何在其末尾顯示一個省略號
            調用CDC:: DrawText并指定DT_END_ELLIPSIS標志,這樣就可以用小略號取代串末尾的字符使其適合于指定的邊界矩形。如果要顯示路徑信息,指定DT_END_ELLIPSIS標志并省略號取代串中間的字符。

            void CSampleView:: OnDraw (CDC* pDC)
            {
            CTestDoc* pDoc=GetDocument ()
            ASSERT_VALID (pDoc)

            //Add ellpsis to end of string if it does not fit
            pDC->Drawtext (CString ("This is a long string"), CRect (10, 10, 80, 30), DT_LEFT | DT_END_ELLIPSIS)

            //Add ellpsis to middle of string if it does not fit
            pDC->DrawText (AfxgetApp () ->m_pszhelpfilePath, CRect (10, 40, 200, 60), DT_LEFT | DT_PATH_ELLIPSIS)
            }

            (61) 為什么即使調用EnableMenuItem菜單項后,菜單項還處于禁止狀態
            需要將CFrameWnd:: m_bAutomenuEnable設置為FALSE,如果該數據成員為TRUE(缺省值),工作框將自動地禁止沒有ON_UPDATE_COMMAND_UI或者ON_COMMAND的菜單項。

            //Disable MFC from automatically disabling menu items.
            m_bAuoMenuEnable=FALSE
            //Now enable the menu item.
            CMenu* pMenu=GetMenu ()
            ASSERT_VALID (pMenu)

            pMenu->EnableMenuItem (ID_MENU_ITEM,MF_BYCOMMAND | MF_ENABLED)

            (62) 如何給系統菜單添加一個菜單項
            給系統菜單添加一個菜單項需要進行下述三個步驟:
            首先,使用Resource Symbols對話(在View菜單中選擇Resource Symbols...可以顯示該對話)定義菜單項ID,該ID應大于0x0F而小于0xF000;
            其次,調用CWnd::GetSystemMenu獲取系統菜單的指針并調用CWnd:: Appendmenu將菜單項添加到菜單中。下例給系統菜單添加兩個新的
            int CMainFrame:: OnCreate (LPCREATESTRUCT lpCreateStruct)
            {

            //Make sure system menu item is in the right range.
            ASSERT (IDM_MYSYSITEM &0xFFF0)==IDM_MYSYSITEM)
            ASSERT (IDM-MYSYSITEM<0xF000)

            //Get pointer to system menu.
            CMenu* pSysmenu=GetSystemmenu (FALSE)
            ASSERT_VALID (pSysMenu)
            //Add a separator and our menu item to system menu.
            CString StrMenuItem (_T ("New menu item"))
            pSysMenu->Appendmenu (MF_SEPARATOR)
            pSysMenu->AppendMenu (MF_STRING, IDM_MYSYSITEM, strMenuitem)


            }

            現在,選擇系統菜單項時用戶應進行檢測。使用ClassWizard處理WM_SYSCOMMAND消息并檢測用戶菜單的nID參數:
            void CMainFrame:: OnSysCommand (UINT nID,LPARAM lParam)
            {
            //Determine if our system menu item was selected.
            if ( (nID & 0xFFF0)==IDM_MYSYSITEM)
            {
            //TODO-process system menu item
            }

            else
            CMDIFrameWnd ::OnSysCommand (nID, lParam)
            }
            最后,一個設計良好的UI應用程序應當在系統菜單項加亮時在狀態條顯示一個幫助信息,這可以通過增加一個包含系統菜單基ID的串表的入口來實現。

            (63) 如何確定頂層菜單所占據的菜單行數
            這可以通過簡單的減法和除法來實現。首先,用戶需要計算主框窗口的高度和客戶區;其次,從主框窗口的高度中減去客戶區、框邊界以及標題的高度;最后,除以菜單欄的高度。下例成員函數是一個計算主框菜單所占據的行數的代碼實現。

            int CMainFrame:: GetMenuRows ()
            {
            CRect rcFrame,rcClient
            GetWindowRect (rcFrame)
            GetClientRect (rcClient)
            return (rcFrame.Height () -rcClient.Height () - :: GetSystemMetrics(SM_CYCAPTION) - (:: getSystemMetrics(SM_CYFRAME) *2)) / :: GetSystemMetrics(SM_CYMENU)
            }

            (64) 在用戶環境中如何確定系統顯示元素的顏色
            調用SDK函數GetSysColor可以獲取一個特定顯示元素的顏色。下例說明了如何在MFC函數CMainFrameWnd:: OnNcPaint中調用該函數設置窗口標題顏色。

            void CMiniFrameWnd:: OnNcPaint ()
            {

            dc.SetTextColor (:: GetSysColor (m_bActive ? COLOR_CAPTIONTEXT : COLOR_INACTIVECAPTIONTEXT))

            (65) 如何查詢和設置系統參數
            在Windows 3.1 SDK中介紹過SDK函數SystemParametersInfo,調用該函數可以查詢和設置系統參數,諸如按鍵的重復速率設置、鼠標雙擊延遲時間、圖標字體以及桌面覆蓋位圖等等。

            //Create a font that is used for icon titles.
            LOGFONT stFont
            ∶: SystemParametersInfo (SPIF_GETICONTITLELOGFONT, sizeof (LOGFONT), &stFont, SPIF_SENDWININICHANGE)
            m_font.CreateFontIndirect (&stFont)

            //Change the wallpaper to leaves.bmp.
            ∶ : SystemParametersInfo (SPI_SETDESKWALLPAPER, 0, _T (" forest.bmp"), SPIF_UPDATEINIFILE)

            (66) 如何確定當前屏幕分辨率
            調用SDK函數GetSystemMetrics,該函數可以檢索有關windows顯示信息,諸如標題大小、邊界大小以及滾動條大小等等。

            //Initialize CSize object with screen size.
            CSize sizeScreen (GetSystemMetrics (SM_CXSCREEN),
            GetSystemMetrics (SM_CYSCREEN))

            (67) 如何使用一個預定義的Windows光標
            調用CWinApp:: LoadStandardCursor并傳送光標標識符。
            BOOL CSampleDialog:: OnSetCursor (CWnd* pWnd,
            UINT nHitTest, UINT
            message)
            {
            //Display wait cursor if busy.
            if (m_bBusy)
            {
            SetCursor (AfxGetApp () ->LoadStandardCursor (IDC_WAIT))
            return TRUE
            }

            return CDialog:: OnSetCursor (pWnd. nHitTest,message)
            }

            (68) 如何檢索原先的Task Manager應用程序使用的任務列表
            原 先的Task Manager應用程序顯示頂層窗口的列表。為了顯示該列表,窗口必須可見、包含一個標題以及不能被其他窗口擁有。調用CWnd:: GetWindow可以檢索頂層窗口的列表,調用IsWindowVisible、GetWindowTextLength以及GetOwner可以確定 窗口是否應該在列表中。下例將把TaskManager窗口的標題填充到列表中。

            void GetTadkList (CListBox&list)
            {
            CString strCaption
            //Caption of window.

            list.ResetContent ()
            //Clear list box.

            //Get first Window in window list.
            ASSERT_VALID (AfxGetMainWnd ())
            CWnd* pWnd=AfxGetMainWnd () ->GetWindow (GW_HWNDFIRST)

            //Walk window list.
            while (pWnd)
            {
            // I window visible, has a caption, and does not have an owner?
            if (pWnd ->IsWindowVisible()
            && pWnd ->GetWindowTextLength ()
            &&! pWnd ->GetOwner ())
            {

            //Add caption o window to list box.

            pWnd ->GetWindowText (strCaption)

            list.AddString (strCaption)
            }
            //Get next window in window list.
            pWnd=pWnd ->GetWindow(GW_HWNDNEXT)
            }
            }

            (69) 如何確定Windows和Windows系統目錄
            有兩個SDK函數可以完成該功能。GetWindowsDirectory和GetSystemDirectory,下例說明了如何使用這兩個函數:

            TCHAR szDir [MAX_PATH]
            //Get the full path of the windows directory.
            ∶ : GetWindowsDirectory (szDir, MAX_PATH)
            TRACE ("Windows directory %s"n", szDir)
            //Get the full path of the windows system directory.
            ∶ : GetSystemDirectory (szDir, MAX_PATH)
            TRACE ("Windows system directory %s"n", szDir)

            (70) 在哪兒創建臨文件
            調用SDK函數GetTemPath可以確定臨時文件的目錄,該函數首先為臨時路徑檢測TMP環境變量:如果沒有指定TMP,檢測TMP環境變量,然后返回到當前目錄。下例說明了如何創建一個臨時文件。


            //get unique temporary file.
            CString strFile
            GetUniqueTempName (strFile)
            TRY
            {
            //Create file and write data.Note that file is closed
            //in the destructor of the CFile object.
            CFile file (strFile,CFile ::modeCreate | Cfile:: modeWrite)

            //write data
            }

            CATCH (CFileException, e)
            {
            //error opening file
            }
            END_CATCH


            Void GetuniqueTempName (CString& strTempName)
            {
            //Get the temporary files directory.
            TCHAR szTempPath [MAX_PATH]
            DWORD dwResult=:: GetTempPath (MAX_PATH, szTempPath)
            ASSERT (dwResult)

            //Create a unique temporary file.
            TCHAR szTempFile [MAX_PATH]
            UINT nResult=GetTempFileName (szTempPath, _T ("~ex"),0,szTempfile)
            ASSERT (nResult)

            strTempName=szTempFile
            }

            (71) 我怎樣才能建立一個等待光標?
            調 用 BeginWaitCursor 函 數 來 啟 動 等 待 光 標,調 用 EndWaitCursor 函 數 來 結 束 等 待 光 標。要 注 意,二 者 都 要 調 用 app 的 成 員 函 數,如 下 所 示:

                AfxGetApp()->BeginWaitCursor();
                // 要做的事
                AfxGetApp()->EndWaitCursor();

            (72) 我在MDI框架中有個 form 視窗。它有個取消按鈕,我需要當用戶按取消按鈕時可關閉form視窗。我應該如何關閉該文檔?
            調 用 OnCloseDocument 函 數。

            (73) 如何訪問桌面窗口
            靜態函數CWnd:: GetDesktopWindow 返回桌面窗口的指針。下例說明了MFC函數CFrameWnd::BeginModalStae是如何使用該函數進入內部窗口列表的。

            void CFrameWnd::BeginModalState ()
            {

            //first count all windows that need to be disabled
            UINT nCount=0
            HWND hWnd= :: GetWindow (:: GetDesktopWindow(), GW_CHILD)
            while (hWnd!=NULL)
            {
            if (:: IsWindowEnabled (hwnd)
            && CWnd::FromHandlePermanent (hWnd)!=NULL
            && AfxIsDescendant (pParent->m_hWnd, hWnd)
            && :: SendMessage (hWnd, WM_DISABLEMODAL, 0, 0)==0)
            {
            ++nCount
            }
            hWnd=:: GetWindow (hWnd, GW_HWNDNEXT)
            }

            (74) 什么是COLORREF? 我該怎樣用它?
            COLORREF 是 一 個 32-bit 整 型 數 值,它 代 表 了 一 種 顏 色。你 可 以 使 用 RGB 函 數 來 初 始 化 COLORREF。例 如:

                COLORREF color = #00ff00;
            RGB 函 數 接 收 三 個 0-255 數 值,一 個 代 表 紅 色, 一 個 代 表 綠 色, 一 個 代 表 藍 色。在 上 面的 例 子 中, 紅 色 和 藍 色 值 都 為 0,所 以 在 該 顏 色 中 沒 有 紅 色 和 藍 色。綠 色 為 最 大 值 255。所 以 該 顏 色 為 綠 色。0,0,0 為 黑 色,255,255,255 為 白 色。

            另 一 種 初 始 化 COLORREF 的 方 法 如 下 所 示:

                CColorDialog colorDialog;
                COLORREF color;

                if( colorDialog.DoModal() == IDOK )
                {
                    color = colorDialog.GetColor();
                }
            這 段 代 碼 使 用 了 MFC 中 的 顏 色 對 話 框,它 需 要 文 件。

            (75) AppWizard所產生的STDAFX文件是干什么用的?
            它 主 要 是 協 助 產 生 預 編 譯 頭 文 件 的。通 常 你 是 不 需 要 修 改 它 的。

            (76) 我在我的程序中是了CDWordArray。我向它添加了約10,000個整數,這使得它變得非常非常慢。為什么會這么糟?
            CDWordArray 是 很 好 用 的,只 是 因 為 你 沒 有 指 定 數 組 的最大尺寸。因 此,當 你 添 加 新 元 素 時,該 類 會 從 堆 中 重 新 分 配 空 間。不 幸 的 是,該 類 會 在 每 次 插 入 新 元 素 時 都 為 數 組 重 新 分 配 空 間。如 果 你 向 它 添 加 了 很 多 新 元 素,所 有 這 些 分 配 和 復 制 數 組 的 操 作 會 就 會 使 它 變 慢。解 決 該 問 題 的 方 法 是,你 可 以 使 用 SetSize 函 數 的 第 二 個 參 數 來 改 變 這 種 重 新 分 配 的 頻 率。例 如,如 果 你 把 該 參 數 設 置 為 500,則 每 次 數 組 空 間 超 出 時 它 才 重 新 分 配 并 添 加 500 個 新 空 間,而 不 是 1 個。這 樣 一 來,你 就 可 以 不 用 重 新 分 配 而 添 加 了 另 外 499 個 元 素 空 間,這 也 會 大 大 提 高 程 序 的 運 行 速 度。

            (77) 我該如何改變MDI框架窗口的子窗口的大小以使在窗口以一定的大小打開?
            在 視 中 的 OnInitialUpdate 函 數 中 調 用 GetParentFrame 函 數。GetParentFrame 會 返 回 一 指 向 一 保 存 有 該 視 的 框 架 窗 口 的 指 針。然 后 調 用 在 框 架 窗 口 上 調 用 MoveWindow。

            (78) 在我的程序的某些部分,我可以調用 MessageBox 函數來建立一個信息對話框,例如在視類中。但是,在其它部分我卻不能,如文檔類中。為什么?我怎樣才能在我的應用程序類中建立一個信息對話框?
            MessageBox 函 數 來 自 CWnd 類,所 以 你 只 能 在 從 CWnd 繼 承 的 類 ( 如 CView ) 中 調 用 它。但 是,MFC 也 提 供 了 AfxMessageBox 函 數,你 可 以 在 任 何 地 方 調 用 它。

            (79) 我需要在我的程序中設置全局變量,以使文檔中的所有類都能訪問。我應該吧它放到哪兒?
            把 該 變 量 放 到 該 應 用 程 序 類 的 頭 文 件 中 的 attribute 處。然 后,在 程 序 的 任 何 地 方,你 都 可 以 用 下 面 的 方 法 來 訪 問 該 變 量:

                CMyApp *app = (CMyApp *)AfxGetApp();
                app->MyGlobalVariable = ...

            (80) 我聽說MFC可以發現內存漏洞,我怎樣使用該特性?
            如 果 你 在 Debug 菜 單 中 的 Go 選 項 ( 不 是 Project 菜 單 中 的 Execute 選 項 ) 來 運 行 你 的 應 用 程 序,MFC 應 該 在 程 序 終 止 時 報 告 內 存 漏 洞。如 果 沒 有,那 么 試 試 運 行 MFC Tracer 工 具 程 序 ( 在 VC++ 程 序 組 中 ),并 啟 動 跟 蹤。然 后 返 回 應 用 程 序。

            (81) 我怎樣才能在我的應用程序中循環瀏覽已經打開的文檔?
            使用CDocTemplate中未公開的GetFirstDocPosition()和GetNextDoc()函數。

            (82)才能在我的應用程序中循環瀏覽已經打開的視?
            使 用 CDocument 中 未 公 開 的 GetFirstViewPosition() 和 GetNextView() 函 數。

            (83)數PreCreateWindow是干什么用的?
            PreCreateWindow 允 許 你 在 調 用 CreateWindow 之 前 來 改 變 窗 口 屬 性。

            (84)該怎樣防止MFC在窗口標題欄上把文檔名預置成應用程序名?
            在 PreCreateWindow 函 數 中 刪 除 FWS_PREFIXTITLE 標 志 的 窗 口 樣 式:

                cs.style &= ~FWS_PREFIXTITLE;

            (85) 我應該怎樣防止MFC在窗口標題欄上添加文檔名?
            在 PreCreateWindow 函 數 中 刪 除 FWS_ADDTOTITLE 標 志 的 窗 口 樣 式:

                cs.style &= ~FWS_ADDTOTITLE ;

            (86) 我應該如何改變視窗口的大小?
            因 為 視 窗 口 實 際 上 是 框 架 窗 口 的 子 窗 口,所 以 你 必 須 改 變 框 架 窗 口 的 大 小,而 不 是 改 變 視 窗 口。使 用 CView 類 中 的 GetParentFrame() 函 數 獲 得 指 向 框 架 窗 口 的 指 針,然 后 調 用 MoveWindow() 函 數 來 改 變 框 架 的 大 小。這 會 使 變 尺 寸 的 視 充 滿 框 架 窗 口。

            (87) 我有一無模式對話框。我怎樣才能在窗口退出時刪除CDialog對象?
            把“delete this”加 到 PostNcDestroy 中。這 主 要 用 在 需 要 自 動 刪 除 對 象 的 場 合。

            (88) 為什么把“delete this”放在PostNcDestroy中而不是OnNcDestroy?
            OnNcDestroy 只 被 已 建 立 的 窗 口 調 用。如 果 建 立 窗 口 失 敗 ( 如 PreCreateWindow ),則 沒 有 窗 口 處 來 發 送 WM_NCDESTROY 消 息。PostNcDestroy 是 在 對 象 窗 口 被 完 全 刪 除,在 OnNcDestroy 后,甚 至 在 窗 口 建 立 失 敗 之 后 調 用 的。

            (89) File菜單中的MRU列表是從哪兒來的?列表中的名字放在哪兒了?我怎樣才能改變列表中項目的最大值?
            在 應 用 程 序 類 的 InitInstance 函 數 中 對 LoadStdProfileSettings 的 調 用 中。該 調 用 接 受 一 個 參 數 ( 在 缺 省 情 況 下 如 果 沒 有 傳 遞 值 則 為 4 )。MRU 文 件 名 是 從 INI 文 件 中 調 用 的。如 果 你 有 帶 有 ID_FILE_MRU_FILE1 的 ID 的 菜 單 選 項,它 會 為 調 入 的 MRU 列 表 所 替 換。如 果 你 改 變 傳 遞 給 LoadStdProfileSettings 的 數 值 ( 最 大 為 16 ),則 你 就 改 變 了 所 裝 如 文 件 名 的 最 大 值。

            (90) 我在菜單中添加了新的項。但是,當我選該項時,在狀態欄上沒有出現任何提示信息。為什么?
            打 開 資 源 文 件 中 的 菜 單 模 板。打 開 新 菜 單 選 項 的 屬 性 對 話 框。在 對 話 框 的 底 部 的 Prompt 編 輯 框 中 ,你 可 以 如 下 指 定 狀 態 欄 上 的 提 示 信 息 和 工 具 欄 上 的 提 示 信 息 ( 如 果 你 已 經 建 立 的 工 具 欄 按 鈕 ):

                Status bar string"nFlying tag

            (91) 我怎樣才能在應用程序的缺省系統菜單中加上一些東西?
            系 統 菜 單 與 其 它 菜 單 類 似,你 可 以 添 加 或 刪 除 項 目,這 需 要 使 用 CMenu 類 的 成 員 函 數。下 面 的 代 碼 在 你 的 系 統 菜 單 后 面 添 加 一 個 新 菜 單 項:

                CMenu *sysmenu;
                sysmenu = m_pMainWnd->GetSystemMenu(FALSE);
                sysmenu->AppendMenu(MF_STRING, 1000, "xxx");
            參 見 MFC 幫 助 文 件 中 的 CMenu 類。

            (92) 我建立了一個對話框。但是當我顯示該對話框時,第一個編輯框總是不能獲得焦點,我必須單擊它來使它獲得焦點。我怎樣才能使第一個編輯框在對話框打開時就獲得焦點?
            打 開 資 源 編 輯 器 中 的 對 話 框 模 板。在 Layout 菜單 中 選 擇 Tab Order 選 項。按 你 的 需 求 單 擊 對 話 框 中 的 控 制 來 重 新 排 列 這 些 控 制 的 tab 順 序。

            (93) 我怎樣才能使一個窗口具有“always on top”特性?
            在 調 用 OnFileNew 后,在 你 的 InitInstance 函 數 中 加 上 下 面 的 代 碼:

            m_pMainWnd->SetWindowPos(&CWnd::wndTopMost,0,0,0,0, SWP_NOMOVE | SWP_NOSIZE);

            (94)   我要為我的form view添加文檔模板。我先建立了對話框模板,然后使用ClassWizard建立了基于CFormView的新類,它也是從CDocument繼承來 的。我還建立了相應的資源并在InitInstance中添加了新的文檔模板。但是,當我試圖運行該程序時,出現了Assertion信息。為什么?

            form 的 對 話 框 模 板 需 要 些 特 殊 設 置 以 便 可 用 于 CFromView。確 保 這 些 設 置 的 最 簡 單 方 法 是 使 用 AppWizard 來 建 立 CFormView 應 用 程 序,并 查 看 AppWizard 所 建 立 的 對 話 框 模 板 所 選 擇 的Styles Properties。你 會 發 現 該 對 話 框 模 板 具 有 下 列 樣 式:沒 有 標 題 欄、不 可 見 和“Child”。把 你 的 form view 的 對 話 框 屬 性 變 成 這 樣 就 可 以 了。

            (95)   我在一對話框中有一列表框,我需要tabbed列表框中的項目。但是,當我處理含有tab字符(用AddString添加的)的列表項時,tab被顯示成小黑塊而沒有展開。哪兒出錯了?

            在 對 話 框 模 版 中,打 開 列 表 框 的 屬 性。確 保 選 擇 了“Use Tabstops” 樣 式。然 后,確 保 在 對 話 框 類 中 OnInitDialog 函 數 中 調 用 SetTabStops。

            (96)  我建立了一個應用程序,并使用了CRecordset類。但是,當我運行該程序時,它試圖要訪問數據庫,并給出“Internal Application Error”對話框。我應該怎樣做?

            通 常 情 況 下,當 你 的 程 序 中 向 數 據 庫 發 送 信 息 的 SQL 語 句 出 現 問 題 時 才 出 現 該 對 話 框。例 如,參 見 下 面 的 例 子:

                set.m_strFilter = "(ZipCode = '27111')";
            如 果 ZipCode 列 被 定 義 為 字 符 串 時 不 會 出 現 問 題,如 果 定 義 為 long,則 會 出 現“Internal Application Error”對 話 框,這 是 由 于 類 型 不 匹 配 的 緣 故。如 果 你 刪 除 27111 的 單 引 號,則 不 會 出 現 問 題。當 你 看 到“Internal Application Error”時,最 好 檢 查 一 下 試 圖 要 發 送 給 數 據 庫 的 SQL 語 句。

            (97)   我用ClassWizard建立了一個類。但是,我把名字取錯了,我想把它從項目中刪除,應該如何做?

            在 ClassWizard 對 話 框 關 閉 后,用 文 件 管 理 器 刪 除 新 類 的 H 和 CPP 文 件。然 后 打 開 ClassWizard,它 會 提 示 丟 失 了 兩 個 文 件,并 詢 問 你 該 如 何 做。你 可 以 選 擇 從 項 目 中 刪 除 這 兩 個 問 的 按 鈕。

            (98)     當我打開應用程序中的窗口時,我要傳遞該窗口的矩形尺寸。該矩形指定了窗口的外圍大小,但是當我調用GetClientRect時,所得到的尺寸要比所希望的值要小(因為工具欄和窗口邊框的緣故)。有其它方法來計算窗口的尺寸嗎?

            參 見 CWnd::CalcWindowRect。

            (99)   我在文檔類中設置了一個整型變量。但是,當我試圖把該變量寫入Serialize函數中的archive文件中時,出現了類型錯誤。而文檔中的其它變量沒有問題。為什么?

            archive 類 只 重 載 某 些 類 型 的 >> 和 << 操 作 符。“int”類 型 沒 有 在 其 中,也 許 是 因 為 int 變 量 在 Windows 3.1 與 Windows NT/95 有 所 不 同 的 緣 故 吧。“long”類 型 得 到 了 支 持,所 以 你 可 以 把 int 類 型 改 成 long 型。參 見 MFC 幫 助 文 件 中 CArchive 類。


            (100)  如何控制菜單的大小?
            我用MFC的CMenu生成了一個動態菜單(例如File,Edit,View...Help), 我想控制這個菜單的大小(長+高).

            方法一:查找 WM_MEASUREITEM 和 MEASUREITEMSTRUCT.
            方法二:查詢系統::GetSystemMetric(SM_CXMENUSIZE).

                 /* 你可以通過如下代碼來獲得文本的大小:
                    (A)獲得被使用的字體 */

                   NONCLIENTMETRICS ncm;
                 HFONT hFontMenu;
                 SIZE size;
                 size.cy = size.cy = 0;

                 memset(&ncm, 0, sizeof(NONCLIENTMETRICS));
                 ncm.cbSize = sizeof(NONCLIENTMETRICS);
                 if (SystemParametersInfo(SPI_GETNONCLIENTMETRICS, sizeof(NONCLIENTMETRICS), &ncm, 0))
                 {
                      hFontMenu = CreateFontIndirect(&ncm.lfMenuFont);
                      /*
                      (B) 獲得菜單項的文本: */
                      char szText[_MAX_PATH];

                      pMenu->GetMenuString(0, szText, _MAX_PATH, MF_BYPOSITION);
                      /*
                      然后,獲得菜單項文本的高度: */
                      HFONT hFontOld;
                      HDC hDC;

                      hDC = ::GetDC(NULL);
                      hFontOld = (HFONT) ::SelectObject(hDC, hFontMenu);
                      GetTextExtentPoint32(hDC, szText, lstrlen(szText), &size);
                      SelectObject(hDC, hFontOld);
                      ::ReleaseDC(NULL, hDC);
                 }
                 /*此時,size.cy即為高度,size.cx為寬度,你可以給菜單加上自定義的高度和寬度,通過比較,我發現寬度為4

            比較合適。*/


            (101)  改變LVIS_SELECTED的狀態顏色?
            我想將CListCtrl項和CTreeCtrl項在LVIS_SELECTED狀態時的顏色變灰.

            方法一:查找函數CustomDraw,它是IE4提供的公共控制,允許有你自己的代碼.
            方法二:生成一個draw控件,然后在DrawItem中處理文本顏色.

            (102)   如何只存儲文檔的某一部分?
            我只想存儲文檔的某一部分,能否象使用文件一樣使用文檔?(也就是有定位函數).將每個CArchive類設置為CFile類的派生類,這樣你就能使用Seek等成員函數.

            (103)   保存工具條菜單有bug嗎?

            使 用浮動菜單條時,SaveBarState和LoadBarState出現了問題.如果菜單是浮動的,重起應用程序時它會出現在左上角,而它固定在屏幕其 它位置時,下一次啟動就會出現在該位置,這是什么原因?你試試這個 PToolBar->Create(this,...,ID_MYTOOLBAR);
            你的工具條需要包括id,而不是象默認的工具條那樣.

            (104)   Tip of the day的bug

            我 創建了一個簡單的mdi應用程序,使用.BSF(自定義的文檔擴展名)作為它的文檔我保存一個foo.bsf文檔后,可以在資源管理器中雙擊該文件打開 mdi應用程序同時打開foo.bsf文檔.但當我給mdi應用程序加上a tip of the day組件之后,從資源管理器中雙擊foo.bsf后,就會給我一個警告:ASSERT(::IsWindow(m_hWnd)),然后mdi應用程序就 死那了.

            當從dde啟動應用程序(例如:雙擊相關文檔)時,"Tip of the Day"是有bug的.你可以看看函數"ShowTipAtStartup",它在"InitInstance"中調用,可以看到tip of the day作為一個模式對話框顯示,在處理其它消息時它一直進行消息循環你可心修改ShowTipAtStartup使其從dde啟動時不出現tip of the day.
            void CTipOfApp::ShowTipAtStartup(void)
                    {
                            // CG: This function added by 'Tip of the Day' component.

                            CCommandLineInfo cmdInfo;
                            ParseCommandLine(cmdInfo);

                            if (
                                    cmdInfo.m_bShowSplash &&
                                    cmdInfo.m_nShellCommand != CCommandLineInf:FileDDE
                                    )
                            {
                                    CTipDlg dlg;
                                    if (dlg.m_bStartup)
                                            dlg.DoModal();
                            }
                    }
            如果還有其它bug,你可以設定cmdInfo.m_nShellCommand的過濾.

            (105)   如何可以讓我的程序可以顯示在其它的窗口上面?

            讓用戶選擇"總是在最上面"最好是在系統菜單里加入一個選項.可以通過修改WM_SYSCOMMAND消息來發送用戶的選擇.菜單的命令標識(id)會作為一個參數傳給OnSysCommand().要定義標識(id),將如下代碼加入到CMainFrame.CPP中:

                #define WM_ALWAYSONTOP WM_USER + 1
            將"總在最上面"的菜單項加入到系統菜單中,將如下代碼加入到函數CMainFrame::OnCreate()中:

                  CMenu* pSysMenu = GetSystemMenu(FALSE);
                  pSysMenu->AppendMenu(MF_SEPARATOR);
                  pSysMenu->AppendMenu(MF_STRING, WM_ALWAYSONTOP,
                                 "&Always On Top");
            使用ClassWizard,加入對WM_SYSCOMMAND消息的處理,你應該改變消息過濾器,使用系統可以處理這個消息.
            void CMainFrame::OnSysCommand(UINT nID, LPARAM lParam)
            {
                switch ( nID )
                {
                case WM_ALWAYSONTOP:

                    if ( GetExStyle() & WS_EX_TOPMOST )
                    {
                        SetWindowPos(&wndNoTopMost, 0, 0, 0, 0,
                            SWP_NOSIZE | SWP_NOMOVE);
                        GetSystemMenu(FALSE)->CheckMenuItem(WM_ALWAYSONTOP,
                            MF_UNCHECKED);
                    }
                    else
                    {
                        SetWindowPos(&wndTopMost, 0, 0, 0, 0,
                            SWP_NOSIZE | SWP_NOMOVE);
                        GetSystemMenu(FALSE)->CheckMenuItem(WM_ALWAYSONTOP,MF_CHECKED);
                    }

                    break;

                default:
                    CFrameWnd::OnSysCommand(nID, lParam);
                }
            }

            (106)    如何控制窗口框架的最大最小尺寸?

            要控制一個框架的的最大最小尺寸,你需要做兩件事情.在CFrameWnd的繼承類中處理消息WM_GETMINMAXINFO,結構MINMAXINFO設置了整個窗口類的限制,因此記住要考慮工具條,卷動條等等的大小.

            // 最大最小尺寸的象素點 - 示例
            #define MINX 200
            #define MINY 300
            #define MAXX 300
            #define MAXY 400

            void CMyFrameWnd::OnGetMinMaxInfo(MINMAXINFO FAR* lpMMI)
            {
                CRect rectWindow;
                GetWindowRect(&rectWindow);

                CRect rectClient;
                GetClientRect(&rectClient);

                  // get offset of toolbars, scrollbars, etc.
                int nWidthOffset = rectWindow.Width() - rectClient.Width();
                int nHeightOffset = rectWindow.Height() - rectClient.Height();

                lpMMI->ptMinTrackSize.x = MINX + nWidthOffset;
                lpMMI->ptMinTrackSize.y = MINY + nHeightOffset;
                lpMMI->ptMaxTrackSize.x = MAXX + nWidthOffset;
                lpMMI->ptMaxTrackSize.y = MAXY + nHeightOffset;
            }
            第二步,在CFrameWnd的繼承類的PreCreateWindow函數中去掉WS_MAXIMIZEBOX消息,否則在最大化時你將得不到預料的結果.

            BOOL CMyFrameWnd::PreCreateWindow(CREATESTRUCT& cs)
            {
                cs.style &= ~WS_MAXIMIZEBOX;
                return CFrameWnd::PreCreateWindow(cs);
            }

            (107)    如何改變窗口框架的顏色?

            MDI框架的客戶區被另一個窗口的框架所覆蓋.為了改變客戶區的背景色,你需要重畫這個客戶窗口.為了做到這點,你要處理消息WM_ERASEBKND產生一個新類,從CWnd繼承,姑且稱之為CMDIClient.給它加上一個成員變量,
            #include "MDIClient.h"
            class CMainFrame : public CMDIFrameWnd
            {
            ...
            protected:
            CMDIClient m_wndMDIClient;
            }
            在CMainFrame中重載CMDIFrameWnd::OnCreateClient
            BOOL CMainFrame::OnCreateClient(LPCREATESTRUCT lpcs, CCreateContext* pContext)
            {
                if ( CMDIFrameWnd::OnCreateClient(lpcs, pContext) )
                {
                    m_wndMDIClient.SubclassWindow(m_hWndMDIClient);
                    return TRUE;
                }
                else
                    return FALSE;
            }
            然后就可以加入對消息WM_ERASEBKGND的處理了.

            (108)    如何將應用程序窗口置于屏幕正中?

            要將你的應用程序窗口放置在屏幕正中央,只須在MainFrame的OnCreate函數中加入:
            CenterWindow( GetDesktopWindow() );

            posted on 2008-09-22 15:10 wrh 閱讀(3724) 評論(0)  編輯 收藏 引用

            導航

            <2008年9月>
            31123456
            78910111213
            14151617181920
            21222324252627
            2829301234
            567891011

            統計

            常用鏈接

            留言簿(19)

            隨筆檔案

            文章檔案

            收藏夾

            搜索

            最新評論

            閱讀排行榜

            評論排行榜

            av国内精品久久久久影院| 国产高潮国产高潮久久久| 色天使久久综合网天天| 人人妻久久人人澡人人爽人人精品| 99精品国产99久久久久久97| 久久精品视频网| 一本久久a久久精品综合香蕉| 国产精品久久久久久福利69堂| 午夜福利91久久福利| 国产成人久久精品激情| 久久这里只有精品首页| 国产精品美女久久久久AV福利| 一本久久知道综合久久| 久久精品国产只有精品66| 99久久无色码中文字幕| 国产偷久久久精品专区| 久久精品人妻一区二区三区| 精品久久久久久综合日本| 午夜天堂av天堂久久久| 久久久久久久免费视频| 久久99精品久久久久久野外| 久久国产精品久久| 性欧美丰满熟妇XXXX性久久久| 亚洲人成无码网站久久99热国产| www亚洲欲色成人久久精品| 国产成人精品久久免费动漫| 亚洲伊人久久大香线蕉综合图片| 亚洲精品成人网久久久久久| 久久这里只有精品视频99| 国产精品成人无码久久久久久| 麻豆精品久久精品色综合| 狠狠色丁香久久综合婷婷| 久久亚洲AV成人无码国产| 亚洲精品无码久久久久去q| 久久久久久亚洲精品影院| 97视频久久久| 久久亚洲AV成人无码软件| 久久久精品人妻一区二区三区蜜桃 | 狠狠干狠狠久久| 97久久精品无码一区二区天美| 午夜精品久久久久久久久|