得到Combobox的狀態:向ComboBox發送CB_GETDROPPEDSTATE消息.ios
格式化字串:char buff[10] ; sprintf(buff,」1+1=%d」,1+1); Sprintf會返回格式化的字符串的長度。 程序員
C區別大小寫。 編程
窗口大部份狀況都要處理WM_PAINT,WM_PAINT處理幾乎老是從BeginPaint開始,以EndPaint結束。 windows
獲取字符串長度:strlen wcslen(unicode長度); 數組
退出程序:DestroyWindow 緩存
文件拖放相關API:DragAcceptFiles,DragQueryFile以及消息WM_DROPFILES 服務器
設置定時器:SetTimer刪除定時器:KillTimer 網絡
LOWORD:返回含低16位;HIWORD:返回高16位,相似的還有LOBYTE,HIBYTE 架構
Cout,cerr與<<一塊兒完成輸出與標準錯誤檢出。Cin與>>完成輸入操做.endl表示換行。使用他們須要#include <iostream.h>。例如:cout<<」a」<<endl<<」b」<<endl. app
當子類建立時,會先調用基類的構造函數,而後再調用子類函數。在Delphi中若是不顯示使用inherited則不會調用基類的構造函數。另外C++的繼承和Delphi也不樣,C++可用Public,Protected,private指定繼承級別。
Class AA
{
AA(int i);
......
}
Class BB:AA
{
BB(int i);
......
}
//這裏會先執行父類AA的構造函數,再執行子類BB的構造函數
BB::BB(int i):AA(int i)
{
……
}
純虛函數,在最後加上=0;如virtual void aa()=0;,擁有純虛函數的類稱爲抽象類。
避免重複定義類
#inndef xxxx
#define xxxx
類包含的內容
#endif
在WM_PAINT最前面用ValidateRect(hwnd,NULL)可以使顯示區域有效且不會重繪,由於顯示區域無效纔會重繪
GetTextMetrics取得字體大小,GetSystemMetrics函式以取使用者介面上各種視覺元件大小的資訊
Stdafx:包含了一些必需的頭文件,是MFC編程的必需文件,它還會調用windows.h
AppWizard生成的典型源文件:
Project.cpp
MainFrm.capp:控制程序的主窗口
projectView.cpp
projectDoc.cpp
stdafx.cpp
project.rc:包含資源文件
resource.h:用來定義宏
m_hWnd:MFC裏窗口類的句柄
IsDlgButtonChecked判斷CheckBox是否按下
UpdateData(bSaveAndValidate)若是bSaveAndValidate=false則初始化對話框,若是bSaveAndValidate=true則從新獲取對話框的數據,默認爲True
GetCurSel:獲取ComboBox,ListBox的當前選擇項目,若是返回CB_ERR則沒有項目被選中
CWnd::SetDlgItemText:Sets the caption or text of a control owned by a window or dialog box.
CWnd::GetDlgItemText:Call this member function to retrieve the title or text associated with a control in a dialog box.
void CheckRadioButton( int nIDFirstButton, int nIDLastButton, int nIDCheckButton );
Selects (adds a check mark to) a given radio button in a group and clears (removes a check mark from) all other radio buttons in the group.
CComboBox::GetDroppedState:判斷CComboBox是否處於下拉狀態
若是要使一個static Text響應消息,必須設置一個惟一ID,並勾選屬性裏面的notify
Vector:至關於一個容器,是一個可以存聽任意類型的動態數組,可以增長和壓縮數據。
Vector<int> test;//聲明一個存放int類型的容器
Test.pushback(66);//在vector的最後放入66
Test.pushbak(88); //在vector的最後放入88
MFC程序入口點WinMain
DefWindowProc:對未被處理的消息提供默認響應。
去除一個屬性:當前屬性結合與上須要去除屬性取反後的值,如 styles & ~style1
關閉程序流程:
點擊右上角的叉叉->產生WM_CLOSE消息->在WM_CLOSE裏能夠判斷是否須要關閉,若是須要關閉則調用DestroyWindow()(做用是銷燬Windows窗體)->當窗體銷燬後產生一個WM_DESTROY消息->在WM_DESTROY裏調用PostQuitMessage(0) ->產生WM_QUIT消息(GetMessage()若是獲取到的消息是WM_QUIT就會返回0,這樣就退出消息循環)->退出消息循環,程序結束
當收到WM_DESTROY消息後,必須調用PostQuitMessage,不然消息循環不會中止,程序也永遠不會結束。PostQuitMessage會產生一個WM_QUIT消息,當應用程序收到WM_QUIT消息後就退出循環了。
DefWindowProc:缺省窗口處理過程,不須要本身處理的消息都由這個過程處理
m_前綴表明是一個類的成員變量
標準輸入輸出流(#include iostream.h):
cin>>xxxx
cout<<xxx
cerr<<xxx
在輸出時可使用endl,至關於C語言的’\n’, 表示換行
若是以一個類未提供構造函數,則C++會提供一個默認的構造函數,這個構造函數沒有參數,只負責建立對象,而不作任何的初始化工做.
只要定義了一個構造函數,C++就再也不提供默認的構造函數,若是還想要沒有參數的構造函數,則必須本身定義.
this是一個隱含的指針,它指向對象自己,表明了對象的地址.
句柄 :HWND,HICON,HCURSOR,HBRUSH等等.
Windows程序是一種基於事件驅動的程序,主要是基於消息.
在Win32程序中,WinMain函數的hPrevInstance老是NULL.
SendMessage直接將消息發到窗口,消息處理完成後才返回.
PostMessage將消息發到應用程序的消息隊列裏,並當即返回.
類成員在默認狀況下是私有的.
當以MyClass obj ;聲明一個對象時,會默認調用無參數構造函數.
在聲明一個對象時,如MyClass obj時,對象就已經建立.若是須要使用帶參數的構建函數,則在聲明對象時應該這樣 : MyClass obj(x,y)
子類聲明 :
Class fish : public animal
{
......
}
分配內存 :pName = new char[20] ;
釋放內存 :delete[] pName ;
只有返回類型不一樣是不能構成函數重載的.
在函數重載時,要注意帶有默認值參數的狀況.
子類的構造函數會先調用父類的構造函數.
子類的析構函數則相反,子類先析構,父類後析構.
當子類調用父類有不一樣參數的構造函數時,須要這樣 :
Fish(void) :animal(100,200)
{
......
}
在父類沒有和子類參數同樣的構造函數時,必須這樣處理.
C++支持多重繼承 :
Class b :public class c,public class d
{
......
}
B繼承於c和d .
初始化時按照基類表說明順序來進行的.析構函數則是按照說明順序的相反方向進行的.
子類調用父類函數(若是子類沒有調用父類的函數,則不會執行父類的虛擬函數) :
class fish:public animal
{
public:
virtual void eate(void)
{
animal::eate();
cout<<"bigfish eate"<<endl;
}
};
聲明一個純虛函數:
Virtual void eate(void) = 0;
凡是含有純虛函數的類成爲抽象類,這種類不能實例化,只是做爲基類爲派生類服務.在派生類必須所有實現基類的純虛函數,不然派生類也變成了抽象類.
當基類和子類出現兩個參數和名稱徹底同樣的函數,而且基類函數沒有使用virtual標示符,則基類的的函數將被隱藏.
當基類和子類出現兩個參數不同,但名稱徹底同樣的函數時,無論基類是否使用了virtual標示符,基類的函數都將被隱藏.
C分配類存的函數:
Malloc(),calloc(),realloc()
使用free釋放分配的內存
C++分配內存:
Int *p = new int;//單個對象
Int *q = new int[100];數組
釋放內存:
Delete p;
Delete[] q;
聲明一個引用:
int a = 5;
int &b = a;//初始化引用,表明b和a使用同一內存.
若是b = 3,則a也等於3.
引用一旦初始化後,不再能表明別的內存.
通常狀況下都不用引用,而使用指針.
每一個MFC都只有1個派生於應用程序類(CWinApp)的theApp全局變量,用來惟一標識應用程序的實例,標示了應用程序自己.
Afx前綴表明應用程序框架(Application Framework),以Afx前綴開頭的函數都是全局函數.好比AfxMessageBox。
MFC程序的全局變量都是放在Globals分支下.
在加載WinMain以前,全局對象/變量就已經初始化OK了.
Memset:填充內存爲某一ASCII值,和Delphi的FillChar相似.
MFC中後綴名爲Ex的函數都是擴展函數.
尋找WinMain:
1. APPMODUL.CPP
_tWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
LPTSTR lpCmdLine, int nCmdShow)
{
// call shared/exported WinMain
return AfxWinMain(hInstance, hPrevInstance, lpCmdLine, nCmdShow);
}
2. 每一個MFC應用程序有且只有一個繼承於CWinApp的theApp對象,表明此應用程序.
3. 由於基類的構造函數會調用父類的構造函數,因此請看CwinApp的構造函數(APPCORE.CPP),
其中有一句pModuleState->m_pCurrentWinApp = this
4. 接下來再回來看第1步的_tWinMain函數中的AfxWinMain.
5. 在WINMAIN.CPP裏找到AfxWinMain的實現代碼.注意此函數定義裏的幾句代碼:
{
……
CWinThread* pThread = AfxGetThread();
CWinApp* pApp = AfxGetApp();
……
if (pApp != NULL && !pApp->InitApplication())//完成MFC內部管理工做
……
if (!pThread->InitInstance())//實際上調用的是咱們本身的應用程序對象的//InitInstance,
……
nReturnCode = pThread->Run();
}
經查看AfxGetThread實現代碼(THRDCORE.APP)可知, AfxGetThread函數最終調用了AfxGetApp()並返回,因此pThread和pApp這兩個指針是同樣的.
再來看AfxGetApp()的實現代碼:
_AFXWIN_INLINE CWinApp* AFXAPI AfxGetApp()
{ return afxCurrentWinApp; }
看下afxCurrentWinApp的實現(AFXWIN.H):
#define afxCurrentWinApp AfxGetModuleState()->m_pCurrentWinApp
從第3步以及本步的以上描述能夠得出:實際上pThread和pApp這兩個指針實際上就是this指針,this指針指向實際應用程序,也就是theApp.
6. InitInstance()函數:
再看第5步的AfxWinMain的實現,其中的pThread->InitInstance爲咱們本身程序的xxxApp(其實也能夠說是theApp)的方法.
7. 註冊類的函數AfxEndDeferRegisterClass(WINCORE.CPP).
8. MFC應用程序實際上有兩個窗口,其中一個是CMainFrame類的對象表明的應用程序框架窗口,該類有一個PreCreateWindow,它在窗口產生以前被調用.CmainFram只是僅僅調用了父類CFrameWnd的PreCreateWindow(WINFRM.CPP),在父類CframeWnd的PreCreateWindow函數裏又調用了AfxEndDeferRegisterClass方法註冊類(第7步).因此能夠看出, PreCreateWindow能夠再建立窗體以前能夠改變它的註冊類的各項參數,從而也改變了窗體的樣式等屬性.
9. 查看CWnd::CreateEx函數,此函數用於初始化窗口註冊類,並調用而來第8步的PreCreateWindow(因此說PreCreateWindow在建立窗體以前留給了程序員一條用於修改窗體屬性的通道),最後使用了CreateWindowEx來建立窗體.
10. 又是誰調用CreateEx呢,它就是CFrameWnd::Create(WINFRM.CPP).
11. 再往上刨刨,看看CFrameWnd::Create又是誰調用的,原來是CFrameWnd::LoadFrame.
Create -> CreateEx -> PreCreateWindow
CWnd::SetIcon:爲窗口設置一個圖標
以::開始的方法是全局函數.
定義類成員變量時,通常用m_前綴開頭.
建立一個按鈕:
m_btn1.Create("ViewBtn1",WS_CHILD | WS_VISIBLE,CRect(0,0,300,300),this,0);
GetParent()得到父窗口.
消息映射有三個地方相關:
1. 頭文件,相似於:
//{{AFX_MSG(CDrawView)
afx_msg void OnLButtonDown(UINT nFlags, CPoint point);
//}}AFX_MSG
DECLARE_MESSAGE_MAP()
2. 源文件有兩處,相似於:
第一處:
BEGIN_MESSAGE_MAP(CDrawView, CView)
//{{AFX_MSG_MAP(CDrawView)
ON_WM_LBUTTONDOWN()//它是一個宏,綁定了消息和其響應方法
//}}AFX_MSG_MAP
……
END_MESSAGE_MAP()
第二處:
void CDrawView::OnLButtonDown(UINT nFlags, CPoint point)
{
// TODO: Add your message handler code here and/or call default
CView::OnLButtonDown(nFlags, point);
}
消息->窗口句柄和對象指針一一對應的對照表->根據消息中的句柄找到對象->把消息傳給應用程序框架類->調用WindowProc
CWnd的WindowProc會調用一個OnWndMsg函數,此函數負責對消息路由分派(一一對消息判斷,而後處理).
OnWndMsg會根據上面所述的消息映射方法,到子類的頭文件的DECLARE_MESSAGE_MAP()之上,
//{{AFX_MSG(CDrawView)和//}}AFX_MSG之間查找是否有相應的消息響應函數原型聲明,再到子類的源文件的BEGIN_MESSAGE_MAP(CDrawView, CView)和END_MESSAGE_MAP()之間查看是否有相應的消息映射宏.
若是找到了消息響應函數,就調用消息響應函數處理消息.若是子類沒有找到消息響應函數,就交給父類處理.
CclientDC:客戶區域DC,在構造或釋放時自動調用GetDC和ReleaseDC.
CwindowDC:客戶訪問整個窗口區域.包括標題欄菜單.
SetROP2:設置繪圖模式
得到一個透明背景的畫刷CBrush::FromHandle((HBRUSH)GetStockObject(NULL_BRUSH))
建立並顯示一個插入符:
CreateSolidCaret(20,100);
ShowCaret();
SetCaretPos:設置插入符的位置
得到字體的度量信息:
BOOL GetTextMetrics(
HDC hdc, // handle to device context
LPTEXTMETRIC lptm // pointer to text metrics structure
);
使用CDC的GetTextExtent來得到字符串的寬度和高度
路徑層(Path bracket):
使用CDC的BeginPath和EndPath來建立及銷燬路徑層.須要配合Rectangles, Ellipse等使用, Rectangle, Ellipse等畫出了當前路徑層的範圍
當前路徑層的做用須要SelectClipPath來肯定模式.
裁剪區域(Clipping region):繪圖操做侷限於在裁剪區域.
CDC的SelectClipPath: 爲設備上下文選擇當前路徑做爲剪切區,並使用指定模式組合新區域與已存在的剪切區.
例子: pDC->BeginPath();//路徑層
CSize size = pDC->GetTextExtent(m_strText);//得到m_strText的寬度
//這裏的Rectangle標識除了路徑層的範圍
pDC->Rectangle(CRect(0,0,size.cx,size.cy));//
pDC->EndPath();
//RGN_DIFF:排除路徑層內容,也就是下面畫的線不會顯示在當前路徑層
pDC->SelectClipPath(RGN_DIFF);
//畫線,這裏就能夠看出效果了
for (int i=0;i<300;i+=10)
{
pDC->MoveTo(0,i);
pDC->LineTo(300,i);
pDC->MoveTo(i,0);
pDC->LineTo(i,300);
}
效果以下,畫的線未影響文字部分
Cfont:構造後還要初始化才能使用.好比用CreateFont等.
若是要使用這個字體,還必須選入設備描述符.
CeditView和CrichEditView這兩個類用來實現文字處理.
OnDraw:每單重繪時都會調用OnDraw(我的以爲應該是在WM_PAINT裏面調用的)
CCmdTarget類及其派生類能夠接受命令消息(WM_COMMAND),通告消息,但不能接收標準消息
CWnd類及其派生類能夠接收標準消息(WM_XXXX),又因Cwnd派生於CCmdTarget,因此也能夠接收命令消息,通告消息
注:
標準消息:除WM_COMMAND外,全部以WM_開頭的消息
命令消息:來自菜單,加速鍵,工具欄的消息,以WM_COMMAND的形式呈現.
通告消息:是由控件產生的消息,例如按鈕的單擊,列表框的選擇等,通告消息也是以WM_COMMAND形式呈現.
得到程序的主菜單:Cwnd的GetMenu();
得到子菜單:Cmenu的GetSubMenu;
標記菜單:
//勾選(標記)菜單,根據索引
this->GetMenu()->GetSubMenu(4)->CheckMenuItem(0,MF_BYPOSITION | MF_CHECKED);
//勾選(標記)菜單,根據ID號
this->GetMenu()->GetSubMenu(4)->CheckMenuItem(IDM_TEST3,MF_BYCOMMAND | MF_CHECKED);
//每一個子菜單隻能有一個缺省菜單
//設置缺省菜單,根據索引
this->GetMenu()->GetSubMenu(4)->SetDefaultItem(2,TRUE);
//設置缺省菜單,根據ID號
this->GetMenu()->GetSubMenu(4)->SetDefaultItem(IDM_TEST5,FALSE);
//設置菜單顯示圖形
int xMenu = GetSystemMetrics(SM_CXMENUCHECK);
int yMenu = GetSystemMetrics(SM_CYMENUCHECK);
CString str;
str.Format("菜單圖標的大小爲:長:%d寬%d",xMenu,yMenu);
//圖標的大小不能超過xMenu,yMenu
MessageBox(str);
CBitmap *pBitmap = new CBitmap;
pBitmap->LoadBitmap(IDB_MENU);
this->GetMenu()->GetSubMenu(4)->SetMenuItemBitmaps(3,MF_BYPOSITION,pBitmap,pBitmap);
//手動控制菜單是否可用
m_bAutoMenuEnable = FALSE;
//將"打開"設置爲不可用
this->GetMenu()->GetSubMenu(0)->EnableMenuItem(1,MF_BYPOSITION | MF_DISABLED | MF_GRAYED);
//手動設置菜單
this->SetMenu(NULL);//這裏菜單會消息
//而後再從新設置新菜單
CMenu menu;
menu.LoadMenu(IDR_MAINFRAME);
//須要從新設置菜單的屬性
menu.GetSubMenu(0)->EnableMenuItem(1,MF_BYPOSITION | MF_DISABLED | MF_GRAYED);
this->SetMenu(&menu);
menu.Detach();//必須斷開與HMENU的聯繫,不然會出錯
若是要手動更改菜單的啓用或禁用或變灰狀態,須要在框架構建函數裏設置m_bAutoMenuEnable爲False.
UPDATE_COMMAND_UI消息用於改變菜單項的狀態,經過映射的方法可更改菜單項的狀態(只適用於子菜單).
把Toolbar工具欄的某項的ID號設置得和菜單同樣,他們就關聯到一塊兒了.
多個菜單項可使用同一個處理函數(注意消息映射).
彈出菜單:
CMenu menu;
menu.LoadMenu(IDR_MENUPOP);
CMenu *popMenu = menu.GetSubMenu(0);
ClientToScreen(&point);//窗口座標轉屏幕座標,由於TrackPopupMenu須要使用屏幕座標
popMenu->TrackPopupMenu(TPM_LEFTALIGN| TPM_RIGHTBUTTON,point.x,point.y,this);
重繪菜單: 框架類DrawMenuBar();動態編輯菜單後,須要重繪菜單反應效果.
動態添加一個菜單:
m_menu.CreatePopupMenu();
GetParent()->GetMenu()->AppendMenu(MF_POPUP,(UINT)m_menu.m_hMenu,"PhoneBook");
GetParent()->DrawMenuBar();
能夠用CWnd的虛函數OnCommand攔截菜單消息.
對於動態添加的菜單的響應能夠集中在OnCommand裏處理
GetActiveView():獲取CView
模態對話框:
打開:DoModal();
關閉:EndDialog();
例:
CDialog1 dialog ;
dialog.DoModal();
非模態對話框:
打開:Create
ShowWindow
CTestDlg *pDlg = new CTestDlg();
pDlg->Create(IDD_DIALOG1,this);
pDlg->ShowWindow(SW_SHOW);
若是在非模態對話框中實現OK按鈕,必須覆蓋OnOK成員函數,並在其中調用DestoryWindow。不能調用基類成員函數,那將會調用EndDialog,使對話框雖然存在但不可視:
void CTestDlg::OnOK()
{
DestroyWindow();//非模態調用,並註釋基類成員函數(以下)
//CDialog::OnOK();//模態調用
}
定義一個指針,分配到堆上,生命週期和整個應用程序的生命週期同樣.
CRect.IsRectNull():4個座標都爲0
CRect.IsRectEmpty():矩形大小爲0,座標爲非0
GetClientRect和GetWindowRect的區別:
GetWindowRect() 獲得的是在屏幕座標系下的RECT;(即以屏幕左上角爲原點)
GetClientRect() 獲得的是在客戶區座標系下的RECT; (即以所在窗口左上角爲原點)
先調用GetWindowRect後再調用ScreenToClient,這個時候獲得的rect和直接使用GetClientRect獲得的值是相等的。
WS_EX_TOPMOST:頂層窗口
BringWindowToTop:把一個窗口放置到Z次序的頂部.
SetForeground:設置前臺窗口(相對於同一個應用程序)
SetWindowPos:設置窗口大小,位置等
WM_INITDIALOG:Dialog及其子控件建立完成,將要顯示前產生此消息
指定的窗口數據是在緩存中保存的,所以在調用SetWindowLong以後再調用SetWindowPos函數才能使SetWindowLong函數所做的改變生效。
改變一個Button的WM_MOUSEMOVE消息的響應(假設這個Button名字爲btn1):
1. 新建一個CButton的子類,假設爲CMyButton
2. 根據須要,從新實現CMyButton的WM_MOUSEMOVE消息響應函數
3. btn1關聯一個類型爲CButton的控件變量m_btn1,
4. 如今btn1的WM_MOUSEMOVE就由CMyButton來響應了
使用PropertyPage(相似Delphi的TabSheet):
1. 在資源裏添加N個IDD_PROPPAGE_XXXX(Dialog子項)
2. 爲對應的IDD_PROPPAGE_XXXX資源添加類(CPropertyPage的子類)
3. 聲明這些類的對象
4. 建立一個CPropertySheet對象.
5. CPropertySheet對象使用AddPage把第3步這些對象添加到CPropertySheet對象裏
6. 若是須要嚮導模式,則CPropertySheet對象使用SetWizardMode()方法.
7. CPropertySheet對象使用DoModal模式顯示或者Create普通顯示
8. 經過覆蓋第2步這些CPropertyPage子類的虛擬方法virtual BOOL CProp1::OnSetActive(),能夠控制顯示哪些按鈕,如只顯示」下一步」能夠在OnSetActive方法裏這樣:
((CPropertySheet *)this->GetParent())->SetWizardButtons(PSWIZB_NEXT);
關於RadioButton的分組:
將第一個RadioButton的Group勾選上,別的同組RadioButton不用勾選.爲第一個RadioButton關聯一個int類型變量,這個變量的值指示了本組哪個RadioButton本選中,-1:沒有RadioButton被選中,0:第一個RadioButton被選中,1:第二個被選中,以此類推.
下一組的第一個RadioButton的Group勾上,就做爲新的組了.
Dialog的初始化能夠放到WM_INITDIALOG消息響應函數OnInitDialog()裏
改變MFC窗口的標題
//改變窗口的標題
//需先把FWS_ADDTOTITLE去掉
cs.style &= ~FWS_ADDTOTITLE;
cs.lpszName = "窗口外觀定製";
如下爲說明的都在PreCreateWindow裏實現:
能夠用GetWindowLong,SetWindowLong修改窗口風格
能夠經過建立一個新WNDCLASS修改窗口類風格
能夠經過AfxRegisterWndClass註冊一個新窗口類來修改風格
能夠用SetClassLong改變窗口類風格,可在多處地方調用
判斷一個窗口是否可見: IsWindowVisible()
從新設置CFrameWnd對象的控件條的位置
ShowControlBar:顯示或隱藏一個ControlBar對象
在View裏設置StatusBar的文本:
1.((CMainFrame *)GetParent())->m_wndStatusBar.SetWindowText(str);
2.((CMainFrame *)GetParent())->SetMessageText(str);
3.((CMainFrame *)GetParent())->GetMessageBar()->SetWindowText(str);
4.GetParent()->GetDescendantWindow(AFX_IDW_STATUS_BAR)->SetWindowText(str);
int idx = m_wndStatusBar.CommandToIndex(IDS_TIMER);//根據字符串資源得到狀態欄某項的序號
m_wndStatusBar.SetPaneInfo(idx,IDS_TIMER,SBPS_NORMAL100); //從新設置狀態欄某項的寬度
m_wndStatusBar.SetPaneText(idx,str,TRUE);//在狀態欄的某一格顯示文字
Dll導出函數方法:
1. 在頭文件裏聲明:extern "C" int __declspec(dllexport)add(int x, int y);
2. 添加一個*.def文件,文件內容以下:
LIBRARY dllTest
EXPORTS
add @ 1
Dll的靜態調用:
1.將dllTest1.lib拷貝到callDllTest2工程目錄
2.將dllTest1.dll拷貝到callDllTest2的Debug目錄
3.將dllTest1的h頭文件拷貝到工程目錄(本項目略過)
4.使用語句導入dllTest1,以下:
#pragma comment(lib,"dllTest1.lib")
extern "C" int __declspec(dllimport) add(int x,int y);
Dll的動態調用:
#include <stdio.h>
#include <windows.h>
typedef int(*lpAddFun)(int, int); //宏定義函數指針類型
int main(int argc, char *argv[])
{
HINSTANCE hDll; //DLL句柄
lpAddFun addFun; //函數指針
hDll = LoadLibrary("..\\Debug\\dllTest.dll");
if (hDll != NULL)
{
addFun = (lpAddFun)GetProcAddress(hDll, "add");
if (addFun != NULL)
{
int result = addFun(2, 3);
printf("%d", result);
}
FreeLibrary(hDll);
}
return 0;
}
Dll的入口函數:
//DLL的入口函數
BOOL APIENTRY DllMain(HANDLE hMoudle,
DWORD ul_reason_for_call,
LPVOID lpReserved)
{
switch(ul_reason_for_call){
case DLL_PROCESS_ATTACH:
printf("DLL_PROCESS_ATTACH\n");
break;
case DLL_PROCESS_DETACH:
printf("DLL_PROCESS_DETACH\n");
break;
case DLL_THREAD_ATTACH:
printf("DLL_THREAD_ATTACH\n");
break;
case DLL_THREAD_DETACH:
printf("DLL_THREAD_DETACH\n");
break;
}
return TRUE;
}
若是經過VC++編寫的DLL欲被其餘語言編寫的程序調用,應將 函數的調用方式聲明爲__stdcall方式
C/C++缺省的調用方式卻爲__cdecl
Windows編程中常見的幾種函數類型聲明宏都是與__stdcall和__cdecl有關的(節選自windef.h):
#define CALLBACK __stdcall //這就是傳說中的回調函數
#define WINAPI __stdcall //這就是傳說中的WINAPI
#define WINAPIV __cdecl
#define APIENTRY WINAPI //DllMain的入口就在這裏
#define APIPRIVATE __stdcall
#define PASCAL __stdcall
通常在Dll文件裏這樣聲明:
int __stdcall add(int x,int y){
return x + y;
}
並定義def文件,輸出函數,def文件內容以下:(經測試,若是Delphi須要調用VC寫的Dll必須用def文件導出函數)
LIBRARY dllMain
EXPORTS
add @ 1
若是要在Dll中導出變量,在def文件裏:(DATA標誌很重要)
dllGlobalVar DATA
使用dll的變量:
#include <stdio.h>
#pragma comment(lib,"dllTest.lib")
extern int _declspec(dllimport) dllGlobalVar; //用_declspec(dllimport)導入
int main(int argc, char *argv[])
{
printf("%d ", dllGlobalVar);
dllGlobalVar = 1; //這裏就能夠直接使用, 無須進行強制指針轉換
printf("%d ", dllGlobalVar);
return 0;
}
若是C++調用一個C語言編寫的.DLL時,當包括.DLL的頭文件或聲明接口函數時,應加extern "C" { }
string轉 char *:string.c_str();一樣適用於string轉LPCSTR
memset:填充緩衝
注意互斥對象在擁有Mutex時的計數。請求次數和釋放次數要相等,別的線程才能使用這個互斥對象。
當一個線程終止時,即使擁有Mutex沒有釋放,操做系統也會自動釋放線程擁有的Mutex。
在作HID的DLL時,因爲死鎖形成了不能退出線程。在線程裏調用ReadBuff回調函數,若是這時ReadBuff回調函數裏調用Close,因爲Close會等待線程結束,而線程在等待ReadBuff返回,因而形成了死鎖。
Delphi調用vc寫的dll時,須要注意調用順序,通常統一爲stdcall
CObject給子類提供了3個重要的特性:
1. 串行化支持
2. 運行時類信息支持(RTCI,和RTTI不同)
3. 診斷和調試支持
Afx函數:全局函數:
AfxGetApp:返回指向應用程序對象的指針
AfxGetMainWnd:返回指向應用程序主窗口的指針
AfxGetInstanceHandle:得到實例句柄
經常使用Afx函數見MFC Windows程序設計13頁
消息映射:
在類的最後加上DECLARE_MESSAGE_MAP(),若是在DECLARE_MESSAGE_MAP()後又定義了成員,須要從新指明訪問類型:public,protected等
而後在在.cpp文件裏BEGIN_MESSAGE_MAP(…)和裏END_MESSAGE_MAP()裏註明映射,如:
BEGIN_MESSAGE_MAP(CMaindWindows,CFrameWnd)
ON_WM_PAINT()
END_MESSAGE_MAP()
「用該成員變量去存儲你的線程主窗口對象。當和m_pMainWnd 相關的窗口被關閉後,MFC會自動終止你的線程。若是該線程是應用程序主線程,程序也將會被終止。若是該數據成員爲NULL,應用程序CWinApp對象的主窗口將用來決定何時去終止線程。m_pMainWnd是一個CWnd*類型的public變量(CWinApp類裏定義)。
MFC應用程序的核心就是基於CWinApp類的應用程序對象。CWinApp提供了消息循環來檢索消息並將消息調度給應用程序窗口,它還包括能夠被覆蓋的,用來自定義應用程序行爲的主要虛函數。一旦頭文件包括Afxwin.h,就能夠將CWinApp以及其餘MFC類引入應用程序中。
CWinApp對象的InitInstace虛方法在程序開始運行後,窗口建立前被調用
除非InitInstace建立一個窗口,不然應用程序是不會有窗口的,這正是爲何MFC應用程序必須從CWinApp派生出一個類並覆蓋CWinApp::InitInstace的緣由。通常應用程序的初始化工做均可以放在InitInstace方法裏。若是InitInstace返回false將關閉程序
通常狀況下,在InitInstance裏調用ShowWindow時,傳遞m_nCmdShow(執行這個程序時由外部指定),而不是SW_值。
當你從CWinApp繼承應用程序類的時候,應重載InitInstance成員函數以建立應用程序的主窗口對象。
若是在InitInstance裏分配了資源,能夠在ExitInstance裏釋放這些資源,他們都是在CWinApp的虛擬函數,在CwinApp子類裏可被覆蓋.
其餘CWinApp可被覆蓋的函數有:OnIdle,Run,PreTranslateMessage.
應用程序空閒時調用OnIdle,能夠覆蓋Run來自定義消息循環,若是想在消息被調度前執行一些專門的預處理,則能夠覆蓋PreTranslateMessage.
若是MFC沒有提供某個消息的映射,能夠自定義消息映射:
ON_MESSAGE(WM_SetText,OnSetText);
……
afx_msg LRESUT OnSetText(WPARAM wPram,LPARAM lParam);
若是要調用常規API,須要在API函數前使用 :: 符號。
MessageBox(L"hello, world");
MessageBox(_T"hello, world");
L"hello, world" 這個字符串保存的是wchar的
_T"hello, world" 若是工程定義了_UNICDE則這個字符串是按wchar方式保存的,若是沒有定義則是按char方式保存的
若是想使應用程序不關心字符集,除了用_T外,還須要注意:
1. 使用TCHAR而不是char
2. 使用TCHAR*或者更佳的LPSTR和LPCSTR
3. 使用Tchar.h裏面的字符串處理函數
在AfxWinMain運行前,應用程序對象(CWinApp)必須在內存中存在。
SetWindowLong:改變窗口特徵
MoveWindow:移動窗口
DestroyWindow:退出窗口
SetWindowText:改變窗口標題欄的名稱
LoadMenu :載入一個菜單
AfxGetInstanceHandle:得到應用程序的實例
AfxRegisterWndClass (0):一個很是通常的窗口類
銷燬一個窗口:
pWnd->DestroyWindow();//刪除Windows窗口
delete pWnd;//銷燬pWnd
AfxGetApp( )->LoadCursor (xx):裝載一個光標
GetDesktopWindow:得到桌面窗口
WindowFromPoint():經過座標獲取窗口
覆蓋PreCreateWindow方法可在建立窗體前更改窗體樣式
在用到RECT的地方,能夠直接用CRect類替換
在建立窗體時,若是pParentWnd爲NULL,則此窗口的全部者就是桌面。
CWnd的Create方法用於建立一個Windows窗體
CDC類封裝了Windows設備環境。
CPaintCDC派生於CDC,用於繪製屏幕,它只在WM_PAINT消息裏使用。
CPaintCDC的構造函數調用BeginPaint,析構函數調用EndPaint。
在建立了CPaintCDC對象後,OnPaint將構造一個表明矩形的CRect對象,此時能夠調用CWnd::GetClientRect以使用窗口的客戶區的座標來初始化這個矩形。
StringCbCopy
strcpy, wcscpy, _tcscpy
lstrcpy
StrCpy
StringCbCopy函數原型以下:
HRESULT StringCbCopy(
__out LPTSTR pszDest, //目標字符串緩衝區
__in size_t cbDest, //目標緩衝區大小(字節),這個值必須考慮pszSrc加上空中止符’/0’的大小;
//最大運行的字節數是STRSAFE_MAX_CCH * sizeof(TCHAR)
__in LPCTSTR pszSrc //源字符串緩衝區,必須以’/0’結尾
);
函數返回&#20540;以下(強烈建議應用SUCCEEDED和FAILED宏來測試返回&#20540;):
S_OK //一切OK
STRSAFE_E_INVALID_PARAMETER //目標緩衝區中&#20540;的大小要麼是0,要麼大於最大允許&#20540;
STRSAFE_E_INSUFFICIENT_BUFFER //目標緩衝區大小不敷,數據被截斷;
//當允許數據截斷時,這不算是錯誤
Carray:數組類
其中定義了一些專用數組類:
CByteArray,CWordArray,CUIntArray,CDWordArray,CStringArray,CObArray,CPtrArray
使用數組前,需引用afxtempl.h
CArray <CPoint,CPoint&> m_Array:傳遞參數時傳遞的是指針,推薦使用
CArray <CPoint,CPoint> m_Array:傳遞參數時傳遞的是對象.
m_Array.SetSize(10,10): SetSize函數設定數組的大小,該函數有兩個參數,第一個參數設定數組的大小;第二個參數設定數組增加時內存分配的大小,缺省值是-1,使用缺省值能夠保證內存分配得更加合理
您能夠隨時使用SetSize函數設定數組的大小,若是第一個參數值小於數組已有成員數量,多於第一個參數值的成員將被截去並釋放相應內存
在使用CArray數組前,最好先使用SetSize肯定其大小並申請存儲空間。若是不這樣作,向數組中增長元素時,須要不斷地移動和拷貝元素形成運行的低效率和內存碎塊
GetWindowsDC:能夠在窗體任一位置畫圖
CDC的子類:
CPaintDC:響應WM_PAINT消息
CClientDC:客戶區域
CWindowDC:客戶區域+非客戶區域,並不經常使用.通常藉助OnNcPaint處理程序捕獲WM_NCPAINT消息
CMetaFileDC
當使用new建立設備描述符表時,須要親自釋放,如:
CPaintDC *pDC = new CPaintDC(thils);
…
Delete pDC;
得到真個屏幕的設備描述表
CClientDC dc(NULL);(或者CWindowDC dc(NULL);)
背景透明:dc.SetBKMode(TRANSPARENT)
得到設備信息:
如:得到屏幕的的寬,以像素點數目計算:
CClientDC dc(this);
Int cx = dc.GetDeviceCaps(HORZRES);//寬度
Int cy = dc.GetDeviceCaps(VERTRES);//高度
Polyline:須要5個點來畫一個矩形,其中第一個點做爲矩形的起點
PolylineTo:只須要4個點,由於第一個點是使用設備描述符的當前位置(如先使用MoveTo肯定起點), PolylineTo返回最後一個點的位置
CPen:
若是要改變畫線方式,則需建立一個畫筆(CPen),並由CDC::SelectObject選入設備描述符.
建立畫筆有三種方式:
1. 直接使用構造函數
2. 使用CPen::CreatePen
3. 使用Cpen::CreatePenIndirect
畫筆的3個特性:樣式,寬度,顏色
MFC程序執行流程:
1. 全局對象(CWinApp的子類)theApp
2. CWinApp構造函數
3. theApp的構造函數
4. AfxWinMain
5. 窗體PreCreateWindow()(給了窗口建立前修改窗口的機會)
6. 應用程序InitInstance()(窗口類註冊,窗口建立,窗口顯示等工做)
7. 應用程序Run()(消息循環,處理消息)
WM_CTLCOLOR:
OnCtlColor響應WM_CTLCOLOR.
pWnd->GetDlgCtrlID():得到窗口的ID
改變對話框上按鈕的顏色:
1. 新建一個CButton的子類.
2. 覆蓋DrawItem方法
3. 在DrawItem裏修改顏色等…..
4. 創建一個和這個按鈕關聯的成員變量(類型爲新建的類)
5. 在圖形界面勾選按鈕的Style爲Owner draw
自定義背景
BOOL CBitmapDCView::OnEraseBkgnd(CDC* pDC)
{
// TODO: Add your message handler code here and/or call default
CBitmap bitmap;
bitmap.LoadBitmap(IDM_BACKGROUND);//加載一幅位圖
CDC dcCompatible;
dcCompatible.CreateCompatibleDC(pDC);//建立兼容DC
dcCompatible.SelectObject(&bitmap);//將位圖選入兼容dc
CRect rect;
this->GetClientRect(&rect);
//拷貝位圖到當前dc
pDC->BitBlt(0,0,rect.Width(),rect.Height(),&dcCompatible,0,0,SRCCOPY);
return TRUE;
//return CView::OnEraseBkgnd(pDC);
}
CPtrArray:
設備座標:以像素爲單位
邏輯座標:單位能夠是像素,毫米,英寸等.
OnInitialUpdate:窗口建立以後第一個被調用的函數,在第一次調用OnDraw以前調用OnInitialUpdate
SetScrollSizes:設置窗口滾動大小
指向常量的指針:
char ch [5] = 「abcd」;
//const在char的前面或後面是同樣的,因此等同於 char const * pStr = ch,通常都是把const放//在char前面.他們都表示指針指向的對象是常量
const char * pStr = ch;
*pStr = ‘w’ //error
pStr = 「xyz」 //ok
指針常量
char ch[5] = 「abcd」;
char * const pStr=ch;
//指針自己是常量,不能修改
pStr = 「xyz」; //error
//可是指針指向的內容是能夠修改的
*pStr = ‘x’; //ok
文件寫入:
FILE * file = fopen("1.txt","w");
char buffer[10];
for (int i=0;i<10;i++)
{
buffer[i] = i + 0x30;
}
fwrite(buffer,sizeof(char),10,file);
//fseek(file,0,SEEK_SET);//移動到文件的開始處
//fwrite("abcde",sizeof(char), lstrlen("abcde"),file);//這裏會覆蓋以前寫的內容
//fflush(file);//將緩衝的內容寫入磁盤文件,這樣就不用每次都使用fclose關閉文件了
fclose(file);
文件讀取:
FILE * file = fopen("1.txt","r");
char buffer[10];
fread(buffer,sizeof(char),10,file);
fclose(file);
fseek:移動文件的指針
ftell:獲取文件的當前位置
rewind:將文件指針移動到文件開始處
itoa:整形轉爲字符串
atoi:字符串轉整形
ofstream:寫文件
ifstream:讀文件
須要引用fstream.h
CreateFile,FileRead,FileWrite:API函數,可讀寫文件
MFC的Cfile:MFC的一個文件類(推薦),用於操做文件.
CFile::modeNoTruncate:在CFile構建函數的第二個參數使用CFile::modeCreate | CFile::modeNoTruncate,可不用刪除之前的文件.
初始化一個字符數組(優勢:數組大小可爲一個變量)
Char * pBuff;
pBuff = new char[100];
CDocument::SetTitle: 設置文檔的標題
也能夠經過修改IDR_MAINFRAME字符串資源的第二項來設置文檔的標題(默認爲空)
得到IDR_MAINFRAME裏的字符串:
CDocTemplate::GetDocString
Doc文檔的Serialize函數用於處理輸入輸出文件.
使一個類具備串行持久性的步驟:
1. 繼承於Cobject
2. 覆蓋Serialize成員函數(實現首先要調用基類的Serialize)
3. 在類申明的地方(頭文件)定義 DECLARE_SERIAL(CGraph)
4. 定義一個不帶參數的構造函數
5. 在類實現定義 IMPLEMENT_SERIAL(CGraph,CObject,1)
6. 而後在文檔類(doc)的Serialize函數裏保存或讀取類
在Doc文檔類裏得到視類View:
POSITION pos = GetFirstViewPosition();
if (pos != NULL)
{
CView * view = GetNextView(pos);
……
}
在View類裏獲的Doc類的指針:
直接調用view類的m_pDocument
CobArray:支持串行化,在文檔類的Serialize函數裏直接調用CobArray對象的Serialize函數,並把ar傳遞給CobArray對象的Serialize.,固然CobArray存儲的對象必須具備串行化持久性
DeleteContents:在新建或者打開文檔時會調用這個函數,用戶需覆蓋這個虛函數,從而執行清除數據工做
IP地址由4個8位點分數字表示
Port端口由一個16位數字表示,1024如下爲系統保留使用.
Socket服務器程序流程:
1 |
建立套接字(socket) |
2 |
將套接字綁定到一個本地地址和端口上(bind) |
3 |
將套接字設爲監聽模式,準備接收客戶請求(listen) |
4 |
等待客戶請求到來.當請求到來後,接受鏈接請求,返回一個新的對應於這次鏈接的套接字(accept) |
5 |
用返回的套接字和客戶端進行通訊(send/recv) |
6 |
返回,等待另外一個客戶請求 |
7 |
關閉套接字 |
Socket客戶端程序流程
1 |
建立套接字(socket) |
2 |
向服務器發出鏈接請求(connect) |
3 |
和服務器端進行通訊(send/recv) |
4 |
關閉套接字 |
UDP服務器程序流程
1 |
建立套接字(socket) |
2 |
將套接字綁定到一個本地地址和端口上(bind) |
3 |
等待接收數據(recvfrom) |
4 |
關閉套接字 |
UDP客戶端程序流程
1 |
建立套接字(socket) |
2 |
向服務器發送數據(sendto) |
3 |
關閉套接字 |
ALT+F8:調整代碼的格式
inet_addr:將一個十進制點分格式的字符串轉換爲一個in_addr能用的u_long類型.
inet_ntoa:而此函數和inet_addr正好相反,它將一個in_addr類型轉換爲十進制點分格式的字符串.( in_addr需爲網絡字節順序)
htonl: 將一個u_long轉換爲TCP/IP網絡字節順序(大端模式,低位放高字節)
htons: 將一個u_short轉換爲TCP/IP網絡字節順序(大端模式,低位放高字節)
gets: 從stdio流中讀取字符串,直至接受到換行符或EOF時中止,並將讀取的結果存放在buffer指針所指向的字符數組中。換行符不做爲讀取串的內容,讀取的換行符被轉換爲null值,並由此來結束字符串。
和cin效果同樣
n 程序是計算機指令的集合,它以文件的形式存儲在磁盤上。
n 進程:一般被定義爲一個正在運行的程序的實例,是一個程序在其自身的地址空間中的一次執行活動。
n 進程是資源申請、調度和獨立運行的單位,所以,它使用系統中的運行資源;而程序不能申請系統資源,不能被系統調度,也不能做爲獨立運行的單位,所以,它不佔用系統的運行資源。
n 進程由兩個部分組成:
1、操做系統用來管理進程的內核對象。內核對象也是系統用來存放關於進程的統計信息的地方。
2、地址空間。它包含全部可執行模塊或DLL模塊的代碼和數據。它還包含動態內存分配的空間。如線程堆棧和堆分配空間。
n 進程是不活潑的。進程歷來不執行任何東西,它只是線程的容器。若要使進程完成某項操做,它必須擁有一個在它的環境中運行的線程,此線程負責執行包含在進程的地址空間中的代碼。
n 單個進程可能包含若干個線程,這些線程都「同時」 執行進程地址空間中的代碼。
n 每一個進程至少擁有一個線程,來執行進程的地址空間中的代碼。當建立一個進程時,操做系統會自動建立這個進程的第一個線程,稱爲主線程。此後,該線程能夠建立其餘的線程。
AfxSocketInit: 初始化socket,調用WSAStartup,並保證在程序結束前調用WSAClear. 在InitInstance裏調用這個函數.(須引用afxsock.h)
一個線程的回調函數能夠設爲類的內部函數,這個函數必須是靜態的.
當線程建立後,需立刻使用CloseHandle關閉句柄,減小線程引用計數
當CreateEvent的第二個參數爲FALSE, WaitForSingleObject執行後事件爲變爲無信號,但不會自動設置事件爲有信號,必須使用SetEvent設置事件爲有信號.
WSAAsyncSelect:將一個網絡事件和一個消息關聯.通常用於異步操做.WSASelectEvent結合WSAWaitForMultipleEvents也能夠異步操做.
若是出現了不該該編譯不過得狀況,能夠嘗試刪除DEBUG文件夾
可使用WSAAsyncSelect來異步處理SOCKET數據:
1. 使用WSAAsyncSelect,將一個網絡事件和一個自定義消息相關聯
2. 將自定義消息映射到一個函數
3. 在消息響應函數里根據事件的類型,分別處理. Wparam指定發生事件的socket, lparam低半子指定事件類型(好比FD_READ,FD_WRITE,FD_CLOSE之類的), lparam高半子指示了錯誤代碼.
gethostbyname: 根據主機名得到IP地址
gethostbyaddr:根據IP地址得到主機名
進程間通訊:
1. 剪貼板
2. 匿名管道
3. 命名管道
4. 郵槽
得到鼠標按鍵的數目:
GetSystemMetrics(SM_CMOUSEBUTTONS)
CalcWindowRect:根據客戶區域大小,計算出須要的窗口大小.必須在窗口建立以後使用.
CDC:: DeflateRect: 經過將CRect的邊向其中心移動來縮小它
CRect::PtInRect: 判斷某點是否位於RECT內
MB_SYSTEMMODAL: 若是MessageBox使用了MB_SYSTEMMODAL標誌,則對話框在全部窗口的最上面,即使切換到了其餘程序.
AfxGetApp()->LoadStandardCursor(IDC_ARROW):得到windows預約義的光標
AfxGetApp()->LoadStandardIcon(IDI_WINLOGO):得到windows預約義的圖標
AfxRegisterWndClass: 註冊一個窗口類.其中的背景顏色能夠用(HBRUSH)(COLOR_3DFACE + 1)這種方式得到windows預約義的顏色,這裏的顏色就是COLOR_3DFACE,注意要+1;
GetSysColor: 經過windows預約義顏色的序號得到RGB表示的顏色.
CreateEx: 若是要使窗口不能縮放,須要從dwStyle中移除WS_THICKFRAME
非客戶區鼠標消息:相似於客戶區鼠標消息,只是加了一個NC,如WM_NCLBUTTONDOWN,對應的處理函數爲OnNcLButtonDown, 處理函數能夠捕獲鼠標是否在標題欄,關閉按鈕,菜單欄,最大化按鈕,邊框等位置.
若是類要從CWnd派生,須要覆寫PostNcDestroy函數,並在函數實現裏刪除自身delete this.
WM_NCHITTEST: 窗口在接收到一個客戶區或非客戶區鼠標消息前,先接收到光標的屏幕座標和WM_NCHITTEST消息,基於這點,能夠在處理鼠標消息前作更多的工做.
TrackMouseEvent: 能夠捕獲鼠標的離開和必定時間靜止未動.在使用前須要引用winuser.h,並引入函數: extern "C" WINUSERAPI BOOL WINAPI TrackMouseEvent(LPTRACKMOUSEEVENT lpEventTrack); 在響應了WM_MOUSELEAVE和WM_MOUSEHOVER消息後必須從新調用TrackMouseEvent.
SystemParametersinfo: 得到系統參數.
SetCapture: 捕獲鼠標.捕獲鼠標後即便光標移出了窗口,仍然能夠接收鼠標消息.,通常在XbuttonDown裏SetCapture,xButtonUp裏ReleaseCapture;
dc.SetROP2(R2_NOT):一次擦除背景色,兩次還原背景色
在移動鼠標時,windows經過重畫光標的背景把光標從舊位置上清除,而後給窗口發送包含命中測試代碼的WM_SETCURSOR消息,對此消息系統的默認響應是調用::SetCursor.
改變光標的兩種方法:
1. 在註冊WNDCLASS時
2. 使用SetCursor來響應WM_SETCURSOR
SetTextAlign:設置文本對齊方式.
顯示與隱藏光標: ShowCursor(TRUE),ShowCursor(FALSE)
得到光標的位置: GetCursorPos, GetMessagePos, 他們返回的是屏幕座標,能夠用ScreenToClient轉換爲客戶區座標.
將光標固定在一個區域: ClipCursor,釋放時ClipCursor(NULL);
WM_SETFOCUS: 得到焦點
WM_KILLFOCUS: 失去焦點
wmd.SetFocus(): 設置焦點
CWnd::GetFocus(): 得到焦點
通常按鍵消息的順序:
1. WM_KEYDOWN
2. WM_CHAR
3. WM_KEYUP
ALT和F10是」系統鍵」,他們只會產生WM_SYSKEYDOWN和WM_SYSKEYUP.在ALT按着的同時,別的鍵被按下,也會產生WM_SYSKEYDOWN和WM_SYSKEYUP消息.
GetKeyState: 檢查某個鍵的狀態,若是是按下返回負值,不然返回非負值.當用來檢查Num Look,Caps Lock,Scroll Lock是否處於激活狀態能夠這樣:::GetKeyState(VK_NUMLOCK) & 0X01,返回非零值說明按鍵激活.
GetKeyState只能在鍵盤消息處理程序裏使用.若是要在別的地方得到按鍵狀態,要使用GetAsyncKeyState.
在VS2012裏,devguid.h定義了經常使用的GUID。
調用dll的兩種方法:
1.鏈接lib (#pragma comment(lib,"xxx.lib")),包含對應的.h頭文件(#include "xxx.H").lib文件在編譯dll文件時自動生成
2.使用LoadLibrary加載dll文件,使用GetProcAddress得到函數.使用FreeLibrary釋放由LoadLibrary加載的dll文件
CONTAINING_RECORD(address, type, field):根據成員的地址獲得結構的地址,如:
struct CIOCPBuffer //per-i/o { WSAOVERLAPPED ol; SOCKET sClient; //AcceptEx接受的客戶方套接字 char *buff; //I/O緩衝區(使用的)大小 int nLen; ULONG nSequenceNumber; //此I/O序列號 int nOperation; //操做類型 #define OP_ACCEPT 1 #define OP_WRITE 2 #define OP_READ 3 CIOCPBuffer *pNext; }; CIOCPBuffer * pBuffer = CONTAINING_RECORD(lpol,CIOCPBuffer,ol);