1. 程式人生 > >孫鑫 VC++深入詳解——學習筆記

孫鑫 VC++深入詳解——學習筆記

1課 Windows程式內部執行機制 1.MFC生成的C++原始檔中都有StdAfx.h,此檔案包含了常用的AFX函式的宣告,其中有afxwin.h,此檔案包含了CRECT,CPointCWnd等許多類及其方法的宣告。 2.Project->Setting->Debug可以加入命令列引數。 3.SDK中要加入"windows.h"stdio.h。因為LoadCursor,MessageBox等函式的宣告在這個檔案中。 4.建立一個完整的視窗的四個步驟SDK1設計視窗類,2註冊視窗類,3建立視窗,4顯示視窗 5.函式名可以代表函式程式碼的首地址,即可作為函式指標。
6.要檢視VC資料型別,可以在MSDN中輸入“BOOL”然後選擇“DATA TYPE”。 7.atof將字串轉化為float,atoi將字串轉化為int型。 8.所有從CWnd類派生的類都有m_hWnd控制代碼。 9.變數的生命週期:可以認為出了包含它的大括號,這個變數的生命週期結束。所以全域性變數的宣告位於所有大括號之外。但是用new宣告的變數和用static宣告的變數除外。 10.SDK示範程式,見下面。 11.sprintf格式化字元,其標頭檔案為stdio.h,MFC中格式化字元用CString.Format 12.GetDC()ReleaseDC()要成對使用,否則會記憶體洩漏。同樣,
BeginPaint()EndPaint()
13.GetStockObject()得到畫筆、畫刷、字型、調色盤的控制代碼,使用時必須用型別轉換。 14.什麼時候用NULL,什麼時候用0.答,對指標賦值時用NULL,對變數賦值時用0. 15.什麼是野指標?答:將指標指向的變數的記憶體釋放後,此指標即變成野指標!如何避免野指標?答:將此指標指向NULL即可。p=NULL; 16.SDK程式碼流程: #include "windows.h"//包含標頭檔案LoadCursor,TextOut等函式 #include "stdio.h"//包含sprintf,printf等函式 LRESULT CALLBACK MyProc(...);//
宣告回撥函式 int WINAPI WinMain() { WNDCLASS wndcls;//設計視窗類 wndcls.hcursor=LoadCursor();//初始化 .... RegisterClass(&wndcls);//註冊視窗類 hwnd=CreateWindow(...);//建立視窗 ShowWindow(..);//顯示視窗 UpdateWindow(..); MSG msg;//定義訊息結構體 while(GetMessage(...))//訊息迴圈 { ... } return 0; } LRESULT CALLBACK MyProc(...)//實現回撥函式 { switch(uMsg) { case WM_CHAR: break; ... } }

2課 掌握C++

1.定義結構體和類時別忘記在最後加入""號!例如Class Point{int x;int y;}; 2.#include <xxx.h>#include "xxx.h"的區別:<>不查詢執行時目錄,""查詢執行時目錄! 3.類的定義中,如果未指明成員型別,則預設為private.而結構體中則預設為public. 4.引用:引用經常用在函式的傳參上。另外數值交換函式也經常用引用。例 change(int &x,int &y){int temp;temp=x;x=y;y=x}呼叫時即可以用int a=3;int b=4;change(a,b);一般不用指標來作為引數進行數值交換。因為會引起歧義。 5.通常將類的定義放.h檔案,而將其實現放在cpp檔案中,別忘記了在cpp檔案中#include "xxx.h" 6.如何防止類的重複定義? #inndef Point_H_H #define Point_H_H class Point{}; #endif來防止 7.原始檔cpp檔案單獨編譯成obj檔案。最後由連結器將與將要使用到的C++標準庫類連結成exe檔案,標頭檔案不參加編譯。所以在cpp檔案中別忘記了加入#include "xxx.h" 8.函式的覆蓋,在子類中重寫父類的函式,此時採用早期繫結的方法。如果加入了virtual,則將採用遲繫結的技術,在執行時根據物件的型別確定呼叫哪一個函式。此遲繫結技術是MFC的類的繼承的精髓。 9.強制型別轉換。如果CFishCAnimal派生而來。則可以將魚的物件轉換為CAnimal的物件,而反之則不行。從現實中理解也是正常的,魚可以是動物,而動物卻不是魚。再如int可以強制轉換成char型。而反之則出錯。 10包含標頭檔案時,<>””是不同的。<>表示編譯器從系統目錄下開始搜尋,然後再搜尋PATH環境變數所列出的目錄,不搜尋當前目錄,找不到就出錯。而””則表示先從當前目錄搜尋,然後才是系統目錄和PATH環境變數列出的目錄。所以,如果標頭檔案在系統目錄下,就用<>,如果標頭檔案在當前目錄下,就用””,這樣可以加快搜索速度。 11在類的標頭檔案(*.h)的開頭,一般定義有如下巨集: #ifndef ANIMAL_H_H #define ANIMAL_H_H Class *** …… #endif 這麼做就是為了避免類重複定義。

3課 MFC框架程式

1.mainWinMain之前,全域性變數(物件)已經被分配記憶體並初始化了。 2.MFC中在WinMain之前有個theApp全域性變數先被構造並被初始化,而由於子類建構函式執行前,其父類的建構函式先被執行,所以CTestApp的父類CWinAPP的建構函式先執行。產生了theApp物件後,在WinMain()中的指標*pThread*pApp就有了內容。 知識點:Afx字首的函式代表應用程式框架(Application Framework)函式,都是全域性函式,在程式的任何地方都可以呼叫它。 3.MFC大致流程: CTestApp theApp;//構造全域性物件 WinMain() { AfxWinMain();//呼叫下面的函式 } AfxWinMain() { pThread->Initinstance();//初始化工作和註冊視窗類,視窗顯示和更新 pThread->Run();//訊息迴圈 } 而在BOOL CTestApp::InitInstance()中的程式碼  CSingleDocTemplate* pDocTemplate;  pDocTemplate = new CSingleDocTemplate(   IDR_MAINFRAME,   RUNTIME_CLASS(CTestDoc),   RUNTIME_CLASS(CMainFrame),       // main SDI frame window   RUNTIME_CLASS(CTestView));  AddDocTemplate(pDocTemplate); 完成了將這三個類關聯起來的工作。 4.如何在單文件檔案中顯示一個CButton的物件? CMainFrame::OnCreate()中定義一個CButton的物件btn;然後呼叫btn.Create("維新",WS_DISABLED   |WS_CHILD | WS_VISIBLE | BS_AUTO3STATE,   CRect(0,0,300,100),/*GetParent(),*/this,123); 注意點:      (1).此處btn不能是區域性變數,否則它的生命週期太短,將不能顯示。      (2).create函式的第二個引數中加入WS_VISIBLE引數才行。否則必須呼叫ShowWindow 也可以在viewOnCreate訊息響應函式中加入      (3).CButton類的定義標頭檔案在afxwin.h中,而stdafx.h包含了afxwin.h,所以可以直接使用。因為MFC中的每一個類中都有#include "stdafx.h"的宣告。 5一個單文件視窗(多文件),標題欄和選單欄位於MainFrame的非客戶區,而工具欄位於MainFrame的客戶區。而檢視位於MainFrame的客戶區。

4課 簡單繪圖

1.在單文件中view擋在MainFrame的前面(View-牆紙,MainFrame-)。此時如果編寫針對MainFramemouseClick事件,將不會有反應。 2.訊息響應會在3處修改程式碼, 1)在標頭檔案中, //{{AFX_MSG(CDrawView) afx_msg void OnLButtonDown(UINT nFlags, CPoint point); //}}AFX_MSG DECLARE_MESSAGE_MAP() 2cpp檔案的begin MessageMapEnd MessageMap之間, BEGIN_MESSAGE_MAP(CDrawView, CView) //{{AFX_MSG_MAP(CDrawView) ON_WM_LBUTTONDOWN() //}}AFX_MSG_MAP END_MESSAGE_MAP() 3)最後是要有函式實現的程式碼。 void CDrawView::OnLButtonDown(UINT nFlags, CPoint point) { // TOD Add your message handler code here and/or call default m_ptOrigin=m_ptOld=point; m_bDraw=TRUE; CView::OnLButtonDown(nFlags, point); } 3.畫線:定義一個成員變數儲存mouseDown的點m_Point   1)API函式方法畫線用HDC   2)CDC類成員函式畫線。此時別忘記ReleaseDC   3)CClientDC   4)CWindowDC,用它甚至可以整個螢幕區域畫線。 下面是上面4種方法的程式碼 (1) /*HDC hdc; hdc=::GetDC(m_hWnd); MoveToEx(hdc,m_ptOrigin.x,m_ptOrigin.y,NULL); LineTo(hdc,point.x,point.y); ::ReleaseDC(m_hWnd,hdc);必須成對使用。*/ (2) /*CDC *pDC=GetDC(); pDC->MoveTo(m_ptOrigin); pDC->LineTo(point); ReleaseDC(pDC);必須成對使用。*/ (3) //CClientDC dc(this); /*CClientDC dc(GetParent()); dc.MoveTo(m_ptOrigin); dc.LineTo(point);此處不需要ReleaseDC,因為CClientDC會自動釋放DC*/ (4) //CWindowDC dc(this); //CWindowDC dc(GetParent()); /*CWindowDC dc(GetDesktopWindow());//此時可以在整個螢幕上畫線。 dc.MoveTo(m_ptOrigin); dc.LineTo(point);*/ /*CPen pen(PS_DOT,1,RGB(0,255,0)); CClientDC dc(this); CPen *pOldPen=dc.SelectObject(&pen); dc.MoveTo(m_ptOrigin); dc.LineTo(point); dc.SelectObject(pOldPen);*/   5)Bitmap填充所畫的矩形。 CBitmap bitmap; bitmap.LoadBitmap(IDB_BITMAP1); CBrush brush(&bitmap); CClientDC dc(this); dc.FillRect(CRect(m_ptOrigin,point),&brush); //CBRUSH::FromHandle是靜態成員函式,所以可以用下面的方法呼叫。 CBrush *pBrush=CBrush::FromHandle((HBRUSH)GetStockObject(NULL_BRUSH));//NULL_BRUSH表示透明畫刷,畫出來的圖形的背景就是透明的 CBrush *pOldBrush=dc.SelectObject(pBrush); dc.Rectangle(CRect(m_ptOrigin,point)); dc.SelectObject(pOldBrush); m_bDraw=FALSE;   6)