MFC控件和子类化介绍
1. 向导页
CPropertySheet
CPropertyPage
1) 自己的类继承CPropertySheet
2) 资源插入对话框,child, 无边框,生成的类继承自CPropertyPage
3) 使用AddPage将分页添加到向导对话框
4) 设置向导模式SetWizardMode
5) 向导对话框可以使用模态方式或者非模态方式显示
6) 在page里面重写虚函数onsetactive,使用SetWizardButtons来设置按钮
7) 在page里面设置标题
2. tab控件
1) 使用insertitem添加选项卡
2) 动态创建child 无边框风格的窗口,并移动到tab控件的位置
3) 在切换选项卡的时候, 手动控制窗口的显示和隐藏
3. 自定义消息
1) 定义自己的消息ID,必须大于WM_USER
2) 定义一个消息响应函数,声明为afx_msg LRESULT memberFxn(WPARAM, LPARAM);
3) 使用ON_MESSAGE将消息id和响应函数联系在一起
WM_XX 标准消息,一般来自系统,或则某些API(CreateWindow, UpdateWindow)
WM_COMMAND 命令消息, 来自于菜单,快捷键和控件
WM_NOTIFY 通告消息, 来自于某些复杂的控件,用来携带参数
4. 右键菜单
1) 使用loadmenu载入菜单资源,通过getsubmenu获取子菜单
2) 使用TrackPopupMenu弹出右键菜单,注意坐标转换
3) 标签菜单,需要自己保存菜单的状态,根据状态手动设置菜单
4) 对话框中可以直接在属性指定菜单的id
5) 通过Getmenu来获取菜单和操作菜单
6) 单文档中菜单需要通过AfxGetMainWnd获取主窗口,然后通过主窗口获取菜单
1. 子类化
1.1 SDK子类化
本质 对空间消息拦截做一些处理
劫持系统默认的窗口过程函数,对消息进行过滤处理.
SetWindowLong -- 修改窗口实例的属性
SetClassLong -- 修改窗口类的属性,只影响以后创建的窗口,之前已经存在的窗口不受影响
1.2 MFC子类化
方法一:
1. 实现自己的CMyEdit,继承自MFC的CEdit
2. 调用成员函数SubClassWindow,或者SubclassDlgItem来实现子类化
方法二:
1. 实现自己的CMyEdit,继承自MFC的CEdit
2. 对控件进行DDX,类别选择Control,
3. 将类向导生成的变量成员的类型从CEdit改为CMyEdit
常用控件
静态文本框, 单选框, 复选框, 下拉列表框,列表框, 列表控件, 文件对话框
单选框:只能选中一项命令。是图形用户界面上的一种控件。它容许用户在一组选项中选择其中一个。单选框的外观一般是一个空白的圆洞。而在它的旁边则通常有一个文字的标签。它的用途除了描述之外,还可用于选择该选择:当用户按下标签,所应的选择钮就会被选上
复选框是一种可同时选中多项的基础控件,也是基于计算机语言的编程代码框架,一般控制的方法是按住ctrl键,然后鼠标左击进行点选操作来完成复选多个目标
下拉列表框 :当用户选中一个选项后,该选单会向下延伸出具有其他选项的另一个选单。下拉式选单通常应用于把一些具有相同分类的功能放在同一个下拉式选单中,并把这个下拉式选单置于主选单的一个选项下。下拉菜单内的项目可以据需要设置为多选或单选,可以用来替代一组复选框(设置为多选)或单选框(设置为单选)。这样比复选框组或单选框组的占用位置小,但不如它们直观
列表控件: 在单选列表视图控件中显示一个简单的编程语言排行榜,然后在用鼠标左键选择某列表项时,将选中列表项的文本显示到编辑框中。下面是具体实现步骤:
1. 创建一个基于对话框的MFC工程,名称设置为“Example29”。
2. 在自动生成的对话框模板IDD_EXAMPLE29_DIALOG中,删除“TODO: Place dialog controls here.”静态文本控件、“OK”按钮和“Cancel”按钮。添加一个List Control控件,ID设置为IDC_PROGRAM_LANG_LIST,View属性设为Report,即为报表风格,Single Selection属性设为True。再添加一个静态文本控件和一个编辑框,静态文本控件的Caption属性设为“选择的语言:”,编辑框的ID设为IDC_LANG_SEL_EDIT,Read Only属性设为True。此时的对话框模板如下图:
3. 为列表视图控件IDC_PROGRAM_LANG_LIST添加CListCtrl类型的控件变量m_programLangList。
4. 在对话框初始化时,我们将编程语言排行榜加入到列表视图控件中,那么需要修改CExample29Dlg::OnInitDialog()函数为:
BOOL CExample29Dlg::OnInitDialog() { CDialogEx::OnInitDialog(); // Add "About..." menu item to system menu. // IDM_ABOUTBOX must be in the system command range. ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX); ASSERT(IDM_ABOUTBOX < 0xF000); CMenu* pSysMenu = GetSystemMenu(FALSE); if (pSysMenu != NULL) { BOOL bNameValid; CString strAboutMenu; bNameValid = strAboutMenu.LoadString(IDS_ABOUTBOX); ASSERT(bNameValid); if (!strAboutMenu.IsEmpty()) { pSysMenu->AppendMenu(MF_SEPARATOR); pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu); } } // Set the icon for this dialog. The framework does this automatically // when the application's main window is not a dialog SetIcon(m_hIcon, TRUE); // Set big icon SetIcon(m_hIcon, FALSE); // Set small icon // TODO: Add extra initialization here CRect rect; // 获取编程语言列表视图控件的位置和大小 m_programLangList.GetClientRect(&rect); // 为列表视图控件添加全行选中和栅格风格 m_programLangList.SetExtendedStyle(m_programLangList.GetExtendedStyle() | LVS_EX_FULLROWSELECT | LVS_EX_GRIDLINES); // 为列表视图控件添加三列 m_programLangList.InsertColumn(0, _T("语言"), LVCFMT_CENTER, rect.Width()/3, 0) m_programLangList.InsertColumn(1, _T("2012.02排名"), LVCFMT_CENTER, rect.Width()/3, 1); m_programLangList.InsertColumn(2, _T("2011.02排名"), LVCFMT_CENTER, rect.Width()/3, 2); // 在列表视图控件中插入列表项,并设置列表子项文本 m_programLangList.InsertItem(0, _T("Java")); m_programLangList.SetItemText(0, 1, _T("1")); m_programLangList.SetItemText(0, 2, _T("1")); m_programLangList.InsertItem(1, _T("C")); m_programLangList.SetItemText(1, 1, _T("2")); m_programLangList.SetItemText(1, 2, _T("2")); m_programLangList.InsertItem(2, _T("C#")); m_programLangList.SetItemText(2, 1, _T("3")); m_programLangList.SetItemText(2, 2, _T("6")); m_programLangList.InsertItem(3, _T("C++")); m_programLangList.SetItemText(3, 1, _T("4")); m_programLangList.SetItemText(3, 2, _T("3")); return TRUE; // return TRUE unless you set the focus to a control } 5. 我们希望在选中列表项改变时,将最新的选择项实时显示到编辑框中,那么可以使用NM_CLICK通知消息。为列表框IDC_PROGRAM_LANG_LIST的通知消息NM_CLICK添加消息处理函数CExample29Dlg::OnNMClickProgramLangList,并修改如下: C++代码 void CExample29Dlg::OnNMClickProgramLangList(NMHDR *pNMHDR, LRESULT *pResult) { LPNMITEMACTIVATE pNMItemActivate = reinterpret_cast<LPNMITEMACTIVATE>(pNMHDR); // TODO: Add your control notification handler code here *pResult = 0; CString strLangName; // 选择语言的名称字符串 NMLISTVIEW *pNMListView = (NMLISTVIEW*)pNMHDR; if (-1 != pNMListView->iItem) // 如果iItem不是-1,就说明有列表项被选择 { // 获取被选择列表项第一个子项的文本 strLangName = m_programLangList.GetItemText(pNMListView->iItem, 0); // 将选择的语言显示与编辑框中 SetDlgItemText(IDC_LANG_SEL_EDIT, strLangName); } }
6. 运行程序,弹出结果对话框,在对话框的列表框中用鼠标改变选中项时,编辑框中的显示会相应改变。效果图如下:
文件对话框:qfiledialog 用来打开文件路径 对文件操作的对话框
按钮自绘
新建项目添加一个类,继承CButton
owner draw属性设置改为true
为button添加一个变量 ,将变量类型改为新添加的类名
实现虚函数DrawItem
消息函数lbuttondown的重写 完成按钮绘