CWnd對象實際上並無把整個Windows對象都包裝在其中,它只是有一個窗口句柄。(在MSDN上查看CWnd類的成員變量,確實只有一個HWND hWnd,成員函數有Attach()和Dettach()、Create()等)。這個窗口句柄若是指向一個實際存在的窗口對象,那麼這個CWnd對象就是有效的;不然是空的。編輯器
若是你還不明白,請回憶一下,當咱們使用MFC建立一個窗口時,是分兩步進行的:ide
而若是你是用SDK方式,那麼只要建立一個WNDCLASS結構,而後調用Create或者CreateEx就建立了一 個窗口。函數
讓一個有效窗口句柄和一個CWnd對象關聯起來用Attach:就是讓一個CWnd對象的HWND成員等於這個窗口句柄;Attach,通俗地說,就是切斷一個CWnd對象和一個有效窗口的臍帶。由於CWnd是C++的對象,C++的對象有一個生存期的概念,脫離了該對象的做用域,這個對象就要被銷燬,可是窗口對象沒有這個特色,當銷燬 CWnd對象的時候,咱們不必定但願WNDCLASS一塊兒被銷燬,那麼在此以前,咱們就先要把這個「臍帶」剪斷,以避免「城門失火,殃及池魚」。動畫
不要在線程函數體內操做MFC控件,由於每一個線程都有本身的線程模塊狀態映射表,在一個線程中操做另外一個線程中建立的MFC對象,會帶來意想不到的問題。更不要在線程函數裏,直接調用UpdataData()函數更新用戶界面,這會致使程序直接crash。而應該經過發送消息給主線程的方式,在主線程的消息響應函數裏操做控件。this
MFC中一個類要訪問另一個類的的對象的成員變量值,就須要得到原來那個類對象的指針,其實有好幾種方法均可以實現。好比維護一個單例模式、設置靜態變量等等。這裏舉個例子,實現多個類之間的相互訪問。spa
(1)建立一個MFC對話框應用程序,命名爲Visit工程,對話框自己有一個主界面(CVisitDlg對話框),咱們再添加一個新界面CXXXDlg。.net
(2)在主界面CVisitDlg類的頭文件中,添加一個static CVisitDlg *s_pDialog;指針。因爲這個指針式靜態的,須要在類外初始化,那麼在CVisitDlg .cpp文件中,寫上一行初始化代碼,直接初始化爲空,以下:線程
CVisitDlg *CVisitDlg::s_pDialog = NULL; //注意要寫在類外,不要寫在類實現函數裏面
(3)而後須要在CVisitDlg主對話框生成的時候,給這個指針賦值爲主對話框指針,在CVisitDlg 類的構造函數或者OnInitDialog()函數裏面寫上以下一句代碼:指針
s_pDialog = this;
如今只要在其餘的類裏面得到這個靜態指針,就能夠訪問這個類裏面的全部數據了。code
(4)得到靜態指針,若是在CXXXDlg類中訪問CVisitDlg類的數據,以下代碼便可實現:
CVisitDlg *pDia = CVisitDlg::s_pDialog
注意:
初始化是賦一個初始值,而定義是分配內存。
靜態成員變量在類中僅僅是聲明,沒有定義,因此要在類的外面定義,其實是給靜態成員變量分配內存。
對於類來講,new一個類對象不只會分配內存,同時會調用構造函數進行初始化,因此類對象的定義和初始化老是關聯在一塊兒。
(1)VC++ 6.0開發的單文檔程序
在BOOL CXXXXApp::InitInstance()方法中添加以下代碼:
m_nCmdShow = SW_HIDE; if (!ProcessShellCommand(cmdInfo)) return FALSE;
即在"if (!ProcessShellCommand(cmdInfo))」在這一句的上方加一句代碼"m_nCmdShow = SW_HIDE;"便可
(2)VC2010開發的單文檔程序
//透明窗體 SetWindowLong(this->GetSafeHwnd(),GWL_EXSTYLE,GetWindowLong(this->GetSafeHwnd(),GWL_EXSTYLE)^0X80000); HINSTANCE hInst = LoadLibrary("User32.DLL"); if(hInst) { typedef BOOL (WINAPI *MYFUNC)(HWND,COLORREF,BYTE,DWORD); MYFUNC fun = NULL; //取得SetLayeredWindowAttributes函數指針 fun=(MYFUNC)GetProcAddress(hInst,"SetLayeredWindowAttributes"); if(fun) fun(this->GetSafeHwnd(),0,128,2); FreeLibrary(hInst); }
int pixelxperinch = dc.GetDeviceCaps(LOGPIXELSX);//每英寸水平邏輯像素數 int pixelyperinch = dc.GetDeviceCaps(LOGPIXELSY);//每英寸垂直邏輯像素數 int pixelx = dc.GetDeviceCaps(HORZRES);//水平像素總數 int pixely = dc.GetDeviceCaps(VERTRES);//垂直像素總數 int hmm = dc.GetDeviceCaps(HORZSIZE);//水平毫米數 int vmm = dc.GetDeviceCaps(VERTSIZE);//垂直毫米
以上三者的關係一般知足:HORZSIZE = 25.4 * HORZRES / LOGPIXELSX
獲取和設置顯示器屬性的代碼以下所示:
//建立顯示設備上下文 HDC hdc = CreateDC(_T("display"), NULL, NULL, NULL); //********** 獲取顯示器屬性 ********** //顏色深度 int nBitsPerPixel=GetDeviceCaps(hdc, BITSPIXEL); //水平分辨率 int nWidth = GetDeviceCaps(hdc, HORZRES); //垂直分辨率 int nHeight = GetDeviceCaps(hdc, VERTRES); //刷新率 int nDisplayFrequency = GetDeviceCaps(hdc, VREFRESH); //********** 設置顯示器屬性 ********** DEVMODE DevMode; //顏色深度 DevMode.dmBitsPerPel = 16; //分辨率 DevMode.dmPelsWidth = 800; DevMode.dmPelsHeight = 600; //刷新率 DevMode.dmDisplayFrequency = 60; //設置顯示屬性 LONG nResult = ChangeDisplaySettings(&DevMode, 0); if (nResult == DISP_CHANGE_SUCCESSFUL) { //用新的設置參數更新註冊表 ChangeDisplaySettings(&DevMode, CDS_UPDATEREGISTRY); AfxMessageBox(_T("設置顯示屬性成功。")); } else { //恢復默認設置 ChangeDisplaySettings(NULL, 0); AfxMessageBox(_T("設置顯示屬性失敗。")); } //設置顯示器爲省電模式 ::SendMessage(m_hWnd, WM_SYSCOMMAND, SC_MONITORPOWER, 1); //打開顯示器 ::SendMessage(m_hWnd, WM_SYSCOMMAND, SC_MONITORPOWER, -1); //關閉顯示器 ::SendMessage(m_hWnd, WM_SYSCOMMAND, SC_MONITORPOWER, 2);
1 int i; 2 i = GetSystemMetrics(SM_CLEANBOOT);//啓動方式 0 3 i = GetSystemMetrics(SM_CMONITORS);//顯示器數目 1 4 i = GetSystemMetrics(SM_CMOUSEBUTTONS);//鼠標上按鍵的數目 3 5 i = GetSystemMetrics(SM_CXBORDER);//窗口邊框的寬度,3D外觀下與SM_CXEDGE值相同 1 6 i = GetSystemMetrics(SM_CXCURSOR);//光標的寬度 32 7 i = GetSystemMetrics(SM_CXDLGFRAME);//與SM_CXFIXEDFRAME相同 3 8 i = GetSystemMetrics(SM_CXDOUBLECLK);//鼠標在某個矩形內連擊兩次被認爲是雙擊,該矩形的寬度 4 9 i = GetSystemMetrics(SM_CXDRAG);//鼠標在某個矩形內單擊移動被認爲是拖曳,該矩形的寬度 4 10 i = GetSystemMetrics(SM_CXEDGE);//SM_CXBORDER在3D外觀下的值 2 11 i = GetSystemMetrics(SM_CXFIXEDFRAME);//具備title bar和固定border的窗體的border的寬度 3 12 i = GetSystemMetrics(SM_CXFOCUSBORDER);//DrawFocusRect畫出的矩形的左右邊框的 1 13 i = GetSystemMetrics(SM_CXFRAME);//與SM_CXSIZEFRAME相同 4 14 i = GetSystemMetrics(SM_CXFULLSCREEN);//客戶區(工做區)的寬度 1280 15 i = GetSystemMetrics(SM_CXHSCROLL);//水平滾動條上箭頭位圖的寬度 17 16 i = GetSystemMetrics(SM_CXHTHUMB);//水平滾動條滑塊的寬度 17 17 i = GetSystemMetrics(SM_CXICON);//圖標的默認寬度,LoadIcon只能載入該寬度和SM_CYICON指定高度的icon 32 18 i = GetSystemMetrics(SM_CXICONSPACING);//icon view中各icon的所佔矩形的寬度,大於等於SM_CXICON 75 19 i = GetSystemMetrics(SM_CXMAXIMIZED);//最大化頂級窗口的寬度 1288 20 i = GetSystemMetrics(SM_CXMAXTRACK);//一個具備title bar和sizable的窗口所能達到的最大寬度 1292 21 i = GetSystemMetrics(SM_CXMENUCHECK);//菜單上位圖的寬度 13 22 i = GetSystemMetrics(SM_CXMENUSIZE);//菜單條按鈕的寬度,例如多文檔中ChildFrame(最大化時)右上角的關閉按鈕 19 23 i = GetSystemMetrics(SM_CXMIN);//窗體的最小寬度 123 24 i = GetSystemMetrics(SM_CXMINIMIZED);//最小化窗體的寬度 160 25 i = GetSystemMetrics(SM_CXMINSPACING);//各個最小化窗體所佔的矩形的寬度,大於等於SM_MINIMIZED 160 26 i = GetSystemMetrics(SM_CXMINTRACK);//窗口能拖拽的最小寬度 123 27 i = GetSystemMetrics(SM_CXSCREEN);//屏幕寬度 1280 28 i = GetSystemMetrics(SM_CXSIZE);//title bar上按鈕的寬度 25 29 i = GetSystemMetrics(SM_CXSIZEFRAME);//sizable窗體的橫向border的寬度 4 30 i = GetSystemMetrics(SM_CXSMICON);//推薦的小圖標(如title bar上的和icon view中的)的寬度 16 31 i = GetSystemMetrics(SM_CXSMSIZE);//caption中圖標的寬度 17 32 i = GetSystemMetrics(SM_CXVIRTUALSCREEN);//virutal screen的寬度 1280 33 i = GetSystemMetrics(SM_CXVSCROLL);//垂直滾動條的寬度 17 34 i = GetSystemMetrics(SM_CYBORDER);// 1 35 i = GetSystemMetrics(SM_CYCAPTION);// 26 36 i = GetSystemMetrics(SM_CYCURSOR);// 32 37 i = GetSystemMetrics(SM_CYDLGFRAME);// 3 38 i = GetSystemMetrics(SM_CYDOUBLECLK);// 4 39 i = GetSystemMetrics(SM_CYDRAG);// 4 40 i = GetSystemMetrics(SM_CYEDGE);// 2 41 i = GetSystemMetrics(SM_CYFIXEDFRAME);// 3 42 i = GetSystemMetrics(SM_CYFOCUSBORDER);// 1 43 i = GetSystemMetrics(SM_CYFRAME);// 4 44 i = GetSystemMetrics(SM_CYFULLSCREEN);// 744 45 i = GetSystemMetrics(SM_CYHSCROLL);// 17 46 i = GetSystemMetrics(SM_CYICON);// 32 47 i = GetSystemMetrics(SM_CYICONSPACING);// 75 48 i = GetSystemMetrics(SM_CYMAXIMIZED);// 778 49 i = GetSystemMetrics(SM_CYMAXTRACK);// 812 50 i = GetSystemMetrics(SM_CYMENU);// 20 51 i = GetSystemMetrics(SM_CYMENUCHECK);// 13 52 i = GetSystemMetrics(SM_CYMIN);// 34=4+4+26 53 i = GetSystemMetrics(SM_CYMINIMIZED);// 31 54 i = GetSystemMetrics(SM_CYMINSPACING);// 31 55 i = GetSystemMetrics(SM_CYMINTRACK);// 34 56 i = GetSystemMetrics(SM_CYSCREEN);// 800 57 i = GetSystemMetrics(SM_CYSIZE);// 25 58 i = GetSystemMetrics(SM_CYSIZEFRAME);// 4 59 i = GetSystemMetrics(SM_CYSMCAPTION);// 18 60 i = GetSystemMetrics(SM_CYSMICON);// 16 61 i = GetSystemMetrics(SM_CYSMSIZE);// 17 62 i = GetSystemMetrics(SM_CYVIRTUALSCREEN);// 800 63 i = GetSystemMetrics(SM_CYVSCROLL);// 17 64 i = GetSystemMetrics(SM_CYVTHUMB);// 17
GetWindowRect是取得窗口在屏幕座標系下的RECT座標(包括客戶區和非客戶區),這樣能夠獲得窗口的大小和相對屏幕左上角(0,0)的位置。
GetClientRect取得窗口客戶區(不包括非客戶區)在客戶區座標系下的RECT座標,能夠獲得窗口的大小,而不能獲得相對屏幕的位置,由於這個矩陣是在客戶區座標系下(相對於窗口客戶區的左上角)的。
ClientToScreen把客戶區座標系下的RECT座標轉換爲屏幕座標系下的RECT座標。
ScreenToClient把屏幕座標系下的RECT座標轉換爲客戶區座標系下的RECT座標。
咱們對同一個窗口先GetWindowRect取得一個RECT,再用ScreenToClient轉換到客戶座標系。而後 GetClientRect取得一個RECT,再用ClientToScreen轉換到屏幕座標系。顯然,GetWindowRect取得的矩陣不小於 GetClientRect取得的矩陣。由於前者包含了非客戶區,然後者包括了客戶區。
//刪除WS_CAPTION和WS_BORDER風格 ModifyStyle(WS_CAPTION, 0); ModifyStyle(WS_BORDER, 0); //得到屏幕長度和高度 int cx = GetSystemMetrics(SM_CXSCREEN); int cy = GetSystemMetrics(SM_CYSCREEN); //設置對話框位置和大小 SetWindowPos(NULL, 0, 0 , cx, cy, SWP_NOZORDER)
(1)組合按鍵
BOOL CMyDlg::PreTranslateMessage(MSG* pMsg) { if(pMsg->message == WM_KEYDOWN) { // 組合鍵響應keydown消息 if( pMsg->wParam == VK_SPACE && (GetKeyState(VK_SHIFT) & 0x8000)) { // 空格 + Shift } } }
(2)屏蔽ESC鍵
BOOL CColorDlgDlg::PreTranslateMessage(MSG* pMsg) { //屏蔽ESC關閉窗體/ if(pMsg->message==WM_KEYDOWN && pMsg->wParam==VK_ESCAPE ) return TRUE; //屏蔽回車關閉窗體,但會致使回車在窗體上失效. //if(pMsg->message==WM_KEYDOWN && pMsg->wParam==VK_RETURN && pMsg->wParam) return TRUE; else return CDialog::PreTranslateMessage(pMsg); }
(3)屏蔽Alt+F4
BOOL CTestApp::PreTranslateMessage(MSG* pMsg) { // TODO: 在此添加專用代碼和/或調用基類 if(pMsg->message == WM_SYSKEYDOWN && pMsg->wParam == VK_F4) return TRUE; return CWinAppEx::PreTranslateMessage(pMsg); }
爲窗口或其中的控件添加提示框,可使用MFC的類CToolTipCtrl,使用方法以下:
(1)在窗口的類定義中添加變量說明:
class CTooltipTestDlg : public Cdialog { public: CToolTipCtrl m_tt; }
(2)在對話框的OnInitDialog()函數中添加以下代碼:
EnableToolTips(TRUE); m_tt.Create(this); m_tt.Activate(TRUE); CWnd* pW=GetDlgItem(IDC_CHECK1);//獲得控件的指針 m_tt.AddTool(pW,L"Check1lakjsfasfdasfd");//爲此控件添加tip
(3)重載父窗口的 BOOL PreTranslateMessage(MSG* pMsg) ,在函數中調用 m_tt.RelayEvent(pMsg):
BOOL CTooltipTestDlg::PreTranslateMessage(MSG* pMsg) { // TODO: Add your specialized code here and/or call the base class if (NULL != m_tt.GetSafeHwnd()) { m_tt.RelayEvent(pMsg); } return CDialog::PreTranslateMessage(pMsg); }
這樣就完成了爲控件添加Tip。
若是想修改已添加的tip的內容,可使用UpdateTipText函數,以下
CWnd* pW=GetDlgItem(IDC_CHECK1);//獲得已添加tip控件 m_tt.UpdateTipText(L"asdflasdf",pW);//更新tip的內容
其餘控制函數具體可查MSDN的CToolTipCtrl類。
對於靜態文本框,要把Notify的屬性設爲TRUE;而若是靜態文本控件是動態建立的,必須給窗口風格添加SS_NOTIFY,如
m_StaticText.Create(_T("my static"), WS_CHILD|WS_VISIBLE|WS_BORDER|SS_NOTIFY,CRect(10,10,150,50),this);
//響應WM_SETCURSOR消息 BOOL CAboutDlg::OnSetCursor(CWnd* pWnd, UINT nHitTest, UINT message) { // TODO: 在此添加消息處理程序代碼和/或調用默認值 //m_hCursor=AfxGetApp()->LoadCursor(IDC_HAND); //文本框IDC_STATIC_HOMEPAGE_LINK的Notify設爲true if(pWnd==GetDlgItem(IDC_STATIC_HOMEPAGE_LINK)) { SetCursor(LoadCursor(NULL,IDC_HAND)); return true;//必須加上 } return CDialogEx::OnSetCursor(pWnd, nHitTest, message); }
HBITMAP hBitmap = (HBITMAP)LoadImage( NULL, _T(「xxx.bmp」), Image_Bitmap, 0,0, Lr_CreateDibSection|Lr_DefaultSize|Lr_LoadFromFile); PWnd->ModifyStytle(0,SS_BITMAP); PWnd->SetBitmap(hBitmap);
在對話框的OnEraseBkgnd(CDC *pDC) 函數中添加以下代碼:
HBITMAP hBitmap = (HBITMAP)Load Image( NULL, _T(「xxx.bmp」), Image_Bitmap, 0,0, Lr_CreateDibSection|Lr_DefaultSize|Lr_LoadFromFile); CBitmap bitmap; bitmap.Attach(hBitmap); //關聯位圖對象 BITMAP bmp; Bitmap.GetBitmap(&bmp); //獲取位圖信息 CDC compatibleDC; compatibleDC.CreateCompatibleDC(pDC); //內存 compatibleDC. SelectObject(&bitmap); //選取位圖對象 Crect rect; GetClientRect(&rect); pDC->StretchBlt( rect.left, rect.top, rect.right, rect.bottom, &compatibleDC, 0, 0, bmp.bmWidth, bmp.bmHeight, SRCCOPY); Return true;// 將OnEraseBkgnd(CDC *pDC) 函數中最後的return語句改成本句
StretchBlt函數縮放圖片後圖片失真嚴重,因此要用SetStretchBltMode函數來設置 StretchBlt(或StretchDIBits)函數的伸縮模式。具體用法是調用StretchBlt前調用:
SetStretchBltMode(pDC->m_hDC,STRETCH_HALFTONE);
(1)開始加入:
#include <comdef.h>//初始化一下com口 #include "GdiPlus.h" using namespace Gdiplus; #pragma comment(lib,"gdiplus.lib")
(2)添加成員變量
ULONG_PTR m_gdiplusToken;
(3)初始化時,啓動GDI+
GdiplusStartupInput gdiplusStartupInput;
GdiplusStartup(&m_gdiplusToken, &gdiplusStartupInput, NULL);
(4)退出時,結束GDI+
GdiplusShutdown(m_gdiplusToken);
(5)在OnPaint或OnDraw函數中,顯示圖片
CClientDC *pDC = new CClientDC(GetDlgItem(IDC_STATIC_PIC)); CRect rect; GetDlgItem(IDC_STATIC_PIC)->GetWindowRect(&rect); Image image(_T("1.png")); // Construct an image //或 Image::FromFile(strPath); Graphics graphics(pDC->m_hDC); // Create a GDI+ graphics object graphics.DrawImage(&image, 0, 0, image.GetWidth(), image.GetHeight()); delete pDC;//或ReleaseDC
RedrawWindow函數引起從新繪製,使用flags參數控制。
InvalidateRect直接無效某個區域,指定是否刷新背景。
若是您的繪製變化較多,有時有閃爍,能夠用LockWindowUpdate、UnlockWindowUpdate或者CWnd::SetRedraw控制,最後結束了,容許繪製,再無效待繪製區域Invalidate。
可視動畫控件ActiveMovie是Microsoft公司開發的ActiveX控件,從開始的1.0版、1.2版到如今的2.0版,功能上已經有了很大的改進。因爲該控件內嵌了Microsoft MPEG音頻解碼器和Microsoft MPEG視頻解碼器,因此可以很好地支持音頻文件和視頻文件,用其播放的VCD效果就很好。另外,播放時若用鼠標右鍵單擊畫面,能夠直接對畫面的播放、暫停、中止等進行控制,讀者還能夠自行在"屬性"欄中對影片播放進行控制設置,用起來很是方便。當前在Microsoft公司推出的Visual C++6.0中已經包含了ActiveMovie控件的2.0版。
在Visual C++6.0中,通常狀況都是在基於對話框的應用程序中使用ActiveMovie控件,可在菜單中依次選擇"project- >Add To Project- >Components And Controls",在出現的"Components And Controls Gallery"對話框中打開"Registered Active Controls"文件夾,選中"ActiveMovie Control Object"選項,按"Insert"按鈕後關閉該對話框,ActiveMovie控件便出如今程序編輯器的控件面板中。
但是我按本法操做,卻找不到此控件。
解決辦法:
打開"開始",運行 regsvr32 msdxm.ocx,有時候會發生註冊失敗的狀況,這時必須關掉VS6及相關的音頻播放軟件,才能註冊成功。
解決辦法:在new前添加全局做用域::
在沒有安裝 VC 的計算機上運行VC程序時要從 VC 中把 mscomm32.ocx、 msvcrt.dll、 mfc42.dll 拷到 Windows 目錄下的 System 子目錄中(win2000 爲 System32),對於尚未註冊的控件,例如本身開發出來的控件,能夠藉助regsvr32.exe註冊,具體作法是:開始菜單->運行->regsvr32.exe 控件文件名.ocx(或者是控件文件名.dll),注意控件文件名處須要用絕對路徑,例如regsvr32.exe C:/progrm files/myActiveXControl.ocx;你也能夠卸載已註冊的控件(也即反註冊),命令格式以下:regsvr32.exe/u 控件文件名.ocx(或者是控件文件名.dll)。
相關連接:http://blog.csdn.net/testcs_dn/article/details/26976555