一、概念 1 MFC的入口在哪里??
CWinApp的InitInstance里面。
编写MFC程序,需要做的事情是实现一个CWinApp的派生类,然后实现一个InitInstance这个虚函数。
在InitInstance这个函数,去创建一个窗口,并将窗口的对象的指针赋值给m_pMainWnd这个指针。
需要定义一个CWinApp的派生类的全局对象。
2 MFC有几种编程模型?单文档,多文档,对话框。我们的课程主要讲解的是对话框编程。
3 如何创建一个对话框。
3.1 首先要有一个对话框资源。
3.2 有一个CDialog类的对象objDlg。
3.3.1 调用objDlg的DoModal函数创建模态对话框
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 #include <afxwin.h> #include <afxdialogex.h> #include "resource.h" class CMyApp :public CWinApp{ public : virtual BOOL InitInstance () ; }; BOOL CMyApp::InitInstance () { CDialogEx obj (IDD_DIALOG1) ; obj.DoModal(); return CWinApp::InitInstance(); } CMyApp g_obj;
调用objDlg的Create函数创建非模态对话框
4 MFC程序的窗口是如何处理消息的??
4.1 MFC是通过消息映射机制去处理消息的。
消息是我们自己程序员写代码处理的。我们实现窗口处理消息,实际上就是在给CDialogEx去添加功能。那么给CDialogEx增加功能,应该用什么机制实现呢?
使用继承的方式。
4.2 假如你已经有了一个继承自CDialogEx的类了,怎么实现消息映射呢?
4.2.1 在类的声明中加一个 DECLARE_MESSAGE_MAP()
4.2.2 在类外加一个
BEGIN_MESSAGE_MAP(类名,父类名)
//。。。要处理什么消息,就添加对应消息的处理宏
END_MESSAGE_MAP()
二、MFC控件详解 注意:请绑定控件后操作
标准控件 按钮 在工具箱中拖拽到对话框中后,双击拖拽的控件会自动跳转到编译器生成的函数(单机响应)
在该函数了面可以写单机按钮后想要响应的消息
复选框 绑定变量(右击拖拽的控件选择添加变量,输入变量名确定即可),之后使用UpdateData函数就可以获取
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 void CMy01StdControlsTestDlg::OnBnClickedButton1 () { UpdateData(TRUE); if (m_bCheck1==TRUE) { MessageBox(_T("记住密码" )); } if (m_bCheck2 == TRUE) { MessageBox(_T("记住账号" )); } if (m_bCheck3 == TRUE) { MessageBox(_T("自动换IP" )); } }
单选框 注意分组
绑定的时候,只能绑定到Group属性为true的那个控件上。
1 2 3 4 5 6 7 8 void CMy01StdControlsTestDlg::OnBnClickedButton4 () { UpdateData(TRUE); CString strInfo; strInfo.Format(_T("Group1:%d Group2:%d " ), m_bRadioGroup1, m_bRadioGroup2); MessageBox(strInfo); }
编辑框 编辑框中有一个字段是Multiline是可以多行显示
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 void CMy01StdControlsTestDlg::OnBnClickedButton7 () { CString str ; UpdateData(TRUE); static int nNum = 0 ; str.Format(_T("测试文本%d\r\n" ), nNum); nNum++; m_strEdit2 += str; UpdateData(FALSE); DWORD dwCount = m_objEdit.GetLineCount(); m_objEdit.LineScroll(dwCount); }
静态文本框 绑定变量之后,可以方便的去更改内容。
例子:动态刷新鼠标坐标
1 2 3 4 5 6 7 8 void CMy01StdControlsTestDlg::OnMouseMove (UINT nFlags, CPoint point) { m_strStatic.Format(_T("x坐标为%d,y坐标为%d" ),point.x, point.y); UpdateData(FALSE); CDialogEx::OnMouseMove(nFlags, point); }
图片控件与计时器 计时器:能够让咱们程序,每间隔一个固定的时间,去处理一个事情。
SDK:响应这个WM_TIMER消息 SetTimer()
MFC: 在窗口初始化的时候,去调用一下SetTimer这个函数
要手动在initDialog初始化函数中设置计时器
1 2 3 4 5 6 7 // 设置计时器 SetTimer( 1, //自定义的Timer的ID 500, //间隔的毫秒数 NULL //回调函数,如果设置了,每隔500毫秒调这个回调函数 //如果没有设置,就是给主窗口发WM_TIMER消息 );
响应计时器OnTimer函数可在类向导中添加
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 void CMy01StdControlsTestDlg::OnTimer (UINT_PTR nIDEvent) { if (nIDEvent == 1 ) { CString str; UpdateData(TRUE); static int nNum = 0 ; str.Format(_T("测试文本%d\r\n" ), nNum); nNum++; m_strEdit2 += str; UpdateData(FALSE); DWORD dwCount = m_objEdit.GetLineCount(); m_objEdit.LineScroll(dwCount); } else if (nIDEvent == 2 ) { static BOOL bSign = 0 ; CBitmap Bit1; Bit1.LoadBitmapW(IDB_BITMAP1); CBitmap Bit2; Bit2.LoadBitmapW(IDB_BITMAP2); if (bSign == 0 ) { m_objPic.SetBitmap(Bit1); bSign = 1 ; } else { m_objPic.SetBitmap(Bit2); bSign = 0 ; } } CDialogEx::OnTimer(nIDEvent); }
下拉框 1 2 3 4 5 6 7 8 9 10 static int nNum = 0 ;CString str; str.Format(L"测试文本%d" , nNum); nNum++; m_strComBox1 = str; m_ComBox1.AddString(str); UpdateData(FALSE);
菜单 下拉菜单 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 void CMy03MenuDlg::OnRButtonDown(UINT nFlags, CPoint point) { // TODO: 在此添加消息处理程序代码和/或调用默认值 //1 需要将客户区坐标转换为屏幕坐标 ClientToScreen(&point); //2 需要载入菜单资源 CMenu obj; obj.LoadMenuW(IDR_MENU2); //3 获取一个下拉菜单 CMenu * pSubMenu1 = obj.GetSubMenu(0); pSubMenu1->AppendMenuW(MF_ENABLED, 32783, _T("添加线程")); //4 弹出菜单 pSubMenu1->TrackPopupMenu(TPM_LEFTALIGN, point.x, point.y, this); CDialogEx::OnRButtonDown(nFlags, point); }
弹出菜单 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 void CMyDlg1::OnRclickList1 (NMHDR* pNMHDR, LRESULT* pResult) { LPNMITEMACTIVATE pNMItemActivate = reinterpret_cast <LPNMITEMACTIVATE>(pNMHDR); CMenu obj; obj.LoadMenuW(IDR_MENU1); POINT pt = { pNMItemActivate->ptAction.x,pNMItemActivate->ptAction.y }; ClientToScreen(&pt); CMenu* pSubMenu1 = obj.GetSubMenu(0 ); pSubMenu1->TrackPopupMenu(TPM_LEFTALIGN,pt.x, pt.y, this ); int item = pNMItemActivate->iItem; CString strPid = m_ProcessList.GetItemText(item, 1 ); nID = _wtoi(strPid); const char * cs = { "右击了进程!!!" }; SendDiyMessage(cs); *pResult = 0 ; } void CMyDlg1::OnRangeCmds1 (UINT nMenuID) { const char * cs; HANDLE Process = OpenProcess(PROCESS_TERMINATE, FALSE, nID); switch (nMenuID) { case ID_32771: break ; case ID_32772: TerminateProcess(Process, -1 ); cs = { "结束了一个进程!!!" }; SendDiyMessage(cs); break ; default : break ; } }
通用控件(复杂控件) 滑块 1 2 3 4 5 6 7 8 9 10 11 12 void CMFCAppTestDlg::OnNMCustomdrawSlider1 (NMHDR* pNMHDR, LRESULT* pResult) { LPNMCUSTOMDRAW pNMCD = reinterpret_cast <LPNMCUSTOMDRAW>(pNMHDR); UpdateData(TRUE); CString str; str.Format(L"滑块的值为:%d" , m_Huakuai1); m_strStaticText2.SetString(str); UpdateData(FALSE); }
进度条 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 void CMFCAppTestDlg::OnBnClickedButton6 () { static int addProess = 0 ; addProess=m_objProgress2.GetPos(); addProess += 10 ; m_objProgress2.SetPos(addProess); if (addProess == 100 ) addProess = 0 ; } void CMFCAppTestDlg::OnBnClickedButton7 () { UpdateData(TRUE); static int delProcess = 0 ; delProcess=m_objProgress2.GetPos(); delProcess -= 10 ; m_objProgress2.SetPos(delProcess); }
列表框 1 2 3 4 5 6 7 8 9 10 11 12 13 m_objCtrlList1.SetExtendedStyle(LVS_EX_FULLROWSELECT | LVS_EX_GRIDLINES | LVS_EX_CHECKBOXES); m_objCtrlList1.InsertColumn(0 , L"姓名" , 0 , 90 ); m_objCtrlList1.InsertColumn(1 , L"年龄" , 0 , 90 ); m_objCtrlList1.InsertColumn(2 , L"身高" , 0 , 90 ); m_objCtrlList1.InsertColumn(3 , L"体重" , 0 , 90 ); m_objCtrlList1.InsertItem( 0 , L"" ); m_objCtrlList1.SetItemText(0 ,0 ,L"小米" ); m_objCtrlList1.SetItemText(0 , 1 , L"14" ); m_objCtrlList1.SetItemText(0 , 2 , L"122" ); m_objCtrlList1.SetItemText(0 , 3 , L"23" );
Tab控件 封装函数拿走
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 void CMyTabCtrl::InitTab (int nCount, ...) { va_list vl; va_start(vl, nCount); for (int i = 0 ; i < nCount; i++) { wchar_t * szTabItemName = va_arg(vl, wchar_t *); CDialogEx* pDlg = va_arg(vl, CDialogEx*); DWORD dwId = va_arg(vl, DWORD); InsertItem(i, szTabItemName); pDlg->Create(dwId, this ); CRect rc = {}; GetClientRect(&rc); rc.DeflateRect(1 , 23 , 1 , 1 ); pDlg->MoveWindow(rc); m_vecDlg.push_back(pDlg); } m_vecDlg[0 ]->ShowWindow(SW_SHOW); va_end(vl); } m_MainTabCtrl.InitTab(4 , L"进程" , new CMyDlg1(), IDD_DIALOG1, L"VS清理" , new CMyDlg2(), IDD_DIALOG2, L"窗口" , new CMyDlg3(),IDD_DIALOGWND, L"计算机总览" , new CMyTreeDlg(), IDD_DIALOGTREE );
树控件 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 HTREEITEM hBj = m_objTree.InsertItem(_T("北京" )); m_objTree.InsertItem(_T("昌平区" ), hBj); m_objTree.InsertItem(_T("朝阳区" ), hBj); m_objTree.InsertItem(_T("海淀区" ), hBj); m_objTree.InsertItem(_T("东城区" ), hBj); m_objTree.InsertItem(_T("西城区" ), hBj); HTREEITEM hTj = m_objTree.InsertItem(_T("天津" )); HTREEITEM hDl = m_objTree.InsertItem(_T("东丽区" ), hTj); m_objTree.InsertItem(_T("天安象屿智慧城" ), hDl); m_objTree.InsertItem(_T("南开区" ), hTj); m_objTree.InsertItem(_T("河西区" ), hTj); m_objTree.InsertItem(_T("河东区" ), hTj); m_objTree.InsertItem(_T("北辰区" ), hTj); m_objTree.InsertItem(_T("和平区" ), hTj); HTREEITEM hHb = m_objTree.InsertItem(_T("河北" )); m_objTree.InsertItem(_T("石家庄" ), hHb); m_objTree.InsertItem(_T("廊坊" ), hHb); m_objTree.InsertItem(_T("雄安新区" ), hHb);
使用案例-遍历硬盘 .h头文件
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 #include <vector> #include <string.h> #include "CMyFilePopDlg.h" using std::vector; // CMyTreeDlg 对话框 typedef struct _MYDISKHEADINFO { CString csDiskHead; //盘符 UINT uAllSize; //盘符总大小 UINT uAbouleSize; //盘符可用大小 UINT uUsed; //已经用了多少 CString attribute; //盘符属性 }MyDiskHeadInfo,*pDisk; class CMyTreeDlg : public CDialogEx { DECLARE_DYNAMIC(CMyTreeDlg) public: CMyTreeDlg(CWnd* pParent = nullptr); // 标准构造函数 virtual ~CMyTreeDlg(); // 对话框数据 #ifdef AFX_DESIGN_TIME enum { IDD = IDD_DIALOGTREE }; #endif protected: virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV 支持 DECLARE_MESSAGE_MAP() public: CTreeCtrl m_objTree; CImageList m_ImageList; vector<_MYDISKHEADINFO *>Disk; virtual BOOL OnInitDialog(); void GetDistHeadInfo();//遍历盘符 HTREEITEM m_Root; CString GetFullPath(HTREEITEM hCurrent); void AddSubDir(HTREEITEM hParent); ; afx_msg void OnDblclkTree1(NMHDR* pNMHDR, LRESULT* pResult); afx_msg void OnSelchangedTree1(NMHDR* pNMHDR, LRESULT* pResult); protected: CListCtrl m_objList; HTREEITEM hOldTree;//记录最后一次的树节点 CMyFilePopDlg m_objFilePopDlg; public: afx_msg void OnDblclkList1(NMHDR* pNMHDR, LRESULT* pResult); };
.cpp文件
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 BOOL CMyTreeDlg::OnInitDialog () { CDialogEx::OnInitDialog(); DWORD dwStyle = GetWindowLong(m_objTree.m_hWnd, GWL_STYLE); dwStyle |= TVS_HASBUTTONS | TVS_HASLINES | TVS_LINESATROOT; SetWindowLong(m_objTree.m_hWnd, GWL_STYLE, dwStyle); GetDistHeadInfo(); m_Root = m_objTree.InsertItem(L"我的电脑" ); for (unsigned int i = 0 ; i < Disk.size(); i++) { HTREEITEM hDiskHead = m_objTree.InsertItem(Disk[i]->csDiskHead, m_Root); } m_objList.SetExtendedStyle(LVS_EX_FULLROWSELECT | LVS_EX_GRIDLINES | LVS_EX_CHECKBOXES); m_objList.InsertColumn(0 , L"文件名" , 0 , 300 ); m_objList.InsertColumn(1 , L"文件大小" , 0 , 100 ); m_objList.InsertColumn(2 , L"文件大小" , 0 , 100 ); m_objList.InsertColumn(3 , L"文件大小" , 0 , 100 ); return TRUE; } void CMyTreeDlg::GetDistHeadInfo () { TCHAR buf[100 ] = {}; TCHAR* pTemp = buf; DWORD 总容量; DWORD 空闲容量; GetLogicalDriveStrings(100 , buf); setlocale(LC_ALL, "chs" ); int Flag = 0 ; while (pTemp[0 ] != 0 ) { MyDiskHeadInfo* pds = new MyDiskHeadInfo; DWORD dwType = GetDriveType(pTemp); switch (dwType) { case DRIVE_REMOVABLE: pds->attribute = L"可移动设备" ; break ; case DRIVE_FIXED: pds->attribute = L"硬盘" ; break ; case DRIVE_REMOTE: pds->attribute = L"远程设备" ; break ; case DRIVE_CDROM: pds->attribute = L"光驱" ; break ; default : break ; } DWORD 每簇的扇区数量 = 0 ; DWORD 每个扇区的容量 = 0 ; DWORD 空闲簇的总量 = 0 ; DWORD 全部簇的总量 = 0 ; GetDiskFreeSpace(pTemp, &每簇的扇区数量, &每个扇区的容量, &空闲簇的总量, &全部簇的总量 ); pds->uAllSize = (((全部簇的总量 / 1024.0 ) * 每簇的扇区数量 * 每个扇区的容量) / 1024 ) / 1024 ; pds->uAbouleSize = (((空闲簇的总量 / 1024.0 ) * 每簇的扇区数量 * 每个扇区的容量) / 1024 ) / 1024 ; pds->uUsed = pds->uAllSize - pds->uAbouleSize; pds->csDiskHead = pTemp; Disk.push_back(pds); pTemp += wcslen(buf) + 1 ; Flag++; } } CString CMyTreeDlg::GetFullPath (HTREEITEM hCurrent) { CString strTemp; CString strReturn = L"" ; while (hCurrent != m_Root) { strTemp = m_objTree.GetItemText(hCurrent); if (strTemp.Right(1 ) != "\\" ) strTemp += "\\" ; strReturn = strTemp + strReturn; hCurrent = m_objTree.GetParentItem(hCurrent); } return strReturn; } void CMyTreeDlg::AddSubDir (HTREEITEM hParent) { CString strPath = GetFullPath(hParent); if (strPath.Right(1 ) != "\\" ) strPath += "\\" ; strPath += "*.*" ; CFileFind file; BOOL bContinue = file.FindFile(strPath); while (bContinue) { bContinue = file.FindNextFile(); if (file.IsDirectory() && !file.IsDots()) m_objTree.InsertItem(file.GetFileName(), hParent); } } void CMyTreeDlg::OnDblclkTree1 (NMHDR* pNMHDR, LRESULT* pResult) { CPoint point; GetCursorPos(&point); m_objTree.ScreenToClient(&point); UINT uFlags = 0 ; HTREEITEM hCurItem; hCurItem = m_objTree.HitTest(point, &uFlags); hOldTree = hCurItem; if (hCurItem == m_Root) { return ; } AddSubDir(hCurItem); *pResult = 0 ; } void CMyTreeDlg::OnSelchangedTree1 (NMHDR* pNMHDR, LRESULT* pResult) { m_objList.DeleteAllItems(); NM_TREEVIEW* pNMTreeView = (NM_TREEVIEW*)pNMHDR; TVITEM item = pNMTreeView->itemNew; if (item.hItem == m_Root) return ; CString str = GetFullPath(item.hItem); if (str.Right(1 ) != "\\" ) str += "\\" ; str += "*.*" ; CFileFind file; BOOL bContinue = file.FindFile(str); while (bContinue) { bContinue = file.FindNextFile(); if (!file.IsDirectory() && !file.IsDots()) { m_objList.InsertItem(0 ,file.GetFileName()); } } *pResult = 0 ; } void CMyTreeDlg::OnDblclkList1 (NMHDR* pNMHDR, LRESULT* pResult) { LPNMITEMACTIVATE pNMItemActivate = reinterpret_cast <LPNMITEMACTIVATE>(pNMHDR); int item = pNMItemActivate->iItem; CString strFileName = m_objList.GetItemText(item, 0 ); if (strFileName.GetLength()) { CString cs; cs.Format(L"%s%s" , GetFullPath(hOldTree), strFileName); MessageBox(cs); } *pResult = 0 ; }
工具栏 添加资源后创建
1 2 3 4 5 6 7 8 9 10 11 m_objToolBar.Create(this ); m_objToolBar.LoadToolBar(IDR_TOOLBAR1); RepositionBars(AFX_IDW_CONTROLBAR_FIRST, AFX_IDW_CONTROLBAR_LAST, 0 ); return TRUE;
响应工具栏消息
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 ON_COMMAND_RANGE(ID_BUTTON32771,ID_BUTTON32774,&CMToolBarDlg::OnRangeCmds); void CMToolBarDlg::OnRangeCmds (UINT nID) { switch (nID) { case ID_BUTTON32771: break ; case ID_BUTTON32772: break ; case ID_BUTTON32773: break ; case ID_BUTTON32774: break ; default : break ; } }
窗口的枚举与图标 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 BOOL CALLBACK EnumWindowsProc (HWND hWnd ,LPARAM lParam) { static int i = 0 ; CMyDlg3* t = (CMyDlg3*)lParam; TCHAR buff[200 ]; GetWindowText(hWnd, buff, 200 ); static HICON hIcon = LoadIcon(AfxGetApp()->m_hInstance, MAKEINTRESOURCE(IDR_MAINFRAME)); if (hIcon != 0 ) { t->m_vecIcon.push_back(hIcon); } if (IsWindowVisible(hWnd) == TRUE && wcslen(buff) != 0 ) { CString cs; cs.Format(L"%s" , buff); t->m_objWndList.InsertItem(i, cs,i); } i++; return TRUE; } EnumWindows(EnumWindowsProc, (LPARAM)this ); m_objIma.Create(32 , 32 , ILC_COLOR32, 4 , 1 ); for (int i = 0 ; i < m_vecIcon.size(); i++) { m_objIma.Add(m_vecIcon[i]); } m_objWndList.SetImageList(&m_objIma, LVSIL_SMALL);