目录

◆ 获取启动参数◆ 调整窗体大小◆ 关闭Dialog窗体◆ Dialog启动时指定控件为焦点◆ Dialog中禁止ESC回车关闭窗体◆ 回车后焦点自动跳到下一个控件◆ 窗体中某个控件捕获右键菜单◆ 获取指定窗体hWnd下的所有子窗体◆ MainFrame启动时居中◆ 非Dialog结构, 初始化时隐藏主窗口避免发生闪烁◆ 设置MainFrame标题栏, 不显示文档名称◆ CListCtrl 的使用1. Item失去焦点时也处于选中状态◆ CRichEditCtrl 的使用1. 设置字体格式◆ CComboBox 的使用1. CComboBox 为焦点时获取其ID2. 输入自动匹配功能的实现◆ CTreeCtrl 的使用1. 初始化时SetCheck无效2. 双击不展开或收缩节点的办法。3. 实现CTreeCtrl父子节点的联动选择◆ CMFCStatusBar 的使用◆ CDockablePane 的使用1. CDockablePane 的布局2. CDockablePane 的显示与隐藏3. 背景刷新问题.4. 如何自定义左右两个并列CDockablePane的大小

◆ 获取启动参数

在 XXXApp 类的 InitInstance 函数中通过宏 __argc 与 __targv 即可获取到程序的启动参数. 代码如下:

BOOL XXXApp::InitInstance()
{
for (int i = 0; i < __argc; i++)
{
AfxMessageBox(__targv[i]);
}

...

return FALSE;
}

◆ 调整窗体大小

使用 SetWindowPos 或 GetWindowRect 均可实现. 代码如下:

    // SetWindowPos 实现
CRect rc1(0, 0, 800, 600);
SetWindowPos(NULL, 0, 0, rc1.Width(), rc1.Height(), SWP_NOZORDER | SWP_NOMOVE);

// MoveWindow 实现
CRect rc2;
GetWindowRect(&rc2);
rc2.bottom += 100;
rc2.right += 100;
MoveWindow(&rc2);

◆ 关闭Dialog窗体

通过 PostMessage 函数发送消息实现. 代码如下:

// close dialog
::PostMessage(pDlg->GetSafeHwnd(), WM_CLOSE, 0, 0);

// end dialog with idok
::PostMessage(pDlg->GetSafeHwnd(), WM_COMMAND, IDOK, 0);

◆ Dialog启动时指定控件为焦点

在 OnInitDialog() 中调用 BringWindowToTop(). 代码如下:

GetDlgItem(IDC_EDIT_XXX)->BringWindowToTop();

◆ Dialog中禁止ESC回车关闭窗体

通过在 PreTranslateMessage(…) 中屏蔽对 VK_ESCAPE, VK_RETURN 的处理即可. 代码如下:

BOOL CDlgXXX::PreTranslateMessage(MSG* pMsg)
{
if (VK_RETURN == pMsg->wParam || VK_ESCAPE == pMsg->wParam)
{
return TRUE;
}

return CDialogEx::PreTranslateMessage(pMsg);
}

◆ 回车后焦点自动跳到下一个控件

通过在 PreTranslateMessage(…) 中对 WM_KEYDOWN, VK_RETURN 的处理来实现. 代码如下:

BOOL CDlgXXX::PreTranslateMessage(MSG* pMsg)
{
if (WM_KEYDOWN == pMsg->message && VK_RETURN == pMsg->wParam)
{
int id = GetFocus()->GetDlgCtrlID();
if (id == IDC_EDIT_X1)
{
// 两种方法都可以重置焦点
GotoDlgCtrl(GetDlgItem(IDC_EDIT_X2));
// GetDlgItem(IDC_EDIT_X2)->SetFocus();
}
else if (id == IDC_EDIT_X2)
{
OnBnClickedBtn();
}

return TRUE;
}

return CDialogEx::PreTranslateMessage(pMsg);
}

◆ 窗体中某个控件捕获右键菜单

处理消息 WM_CONTEXTMENU 来实现. 代码如下:

void CDlgXXX::OnContextMenu(CWnd* pWnd, CPoint point)
{
if (pWnd->m_hWnd == 控件.m_hWnd)
{
CMenu m;
m.LoadMenu(IDR_MENU);

CMenu* pPopMenu = menu.GetSubMenu(0);
if (!pPopMenu)
{
return ;
}

pPopMenu->TrackPopupMenu(TPM_LEFTALIGN | TPM_RIGHTBUTTON, point.x, point.y);
}
}

◆ 获取指定窗体hWnd下的所有子窗体

通过 GetWindow 可以实现, 代码如下:

HWND hwndChild = ::GetWindow(hWnd, GW_CHILD);    //列出所有控件
while (hwndChild)
{
hwndChild = ::GetWindow(hwndChild, GW_HWNDNEXT);
}

◆ MainFrame启动时居中

在 OnCreate 中调用 CenterWindow();

int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
...

CenterWindow()

...
}

◆ 非Dialog结构, 初始化时隐藏主窗口避免发生闪烁

  • 在应用程序构造函数 CxxxApp::CxxxApp(){} 中添加代码:
CXXXApp::CXXXApp()
{
EnableLoadWindowPlacement(FALSE);

...
}

  • 应用程序初始化 CETSPApp::InitInstance() 中设置
BOOL CMFCApplication1App::InitInstance()
{
...

// The one and only window has been initialized, so show and update it
// m_pMainWnd->ShowWindow(SW_SHOW);
m_pMainWnd->ShowWindow(SW_HIDE);

....

m_pMainWnd->UpdateWindow();
return TRUE;
}

  • 重载 CMainFrame 的 ActivateFrame 函数.
void CMainFrame::ActivateFrame(int nCmdShow)
{
nCmdShow = SW_HIDE;

CFrameWndEx::ActivateFrame(nCmdShow);
}


  • 要显示 MainFrame 时调用
ShowWindow(SW_SHOW)

◆ 设置MainFrame标题栏, 不显示文档名称

BOOL CMainFrame::PreCreateWindow(CREATESTRUCT& cs)
{
if( !CFrameWndEx::PreCreateWindow(cs) )
return FALSE;

cs.style &= ~(LONG)FWS_ADDTOTITLE;

return TRUE;
}

int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
...

SetWindowText(_T("xxx"));

...
}

◆ CListCtrl 的使用

1. Item失去焦点时也处于选中状态

设置 LVS_SHOWSELALWAYS. 代码如下:

m_ctrlList.ModifyStyle(0, LVS_SHOWSELALWAYS | LVS_XXX(其它需要的选项));

◆ CRichEditCtrl 的使用

要使用 CRichEditCtrl, 需要在 App 的 InitInstance 中调用 AfxInitRichEdit2 . 代码如下:

BOOL CXXXApp::InitInstance()
{
AfxInitRichEdit2();

...

return FALSE;
}

1. 设置字体格式

通过 GetDefaultCharFormat, SetDefaultCharFormat, SetWordCharFormat, SetSelectionCharFormat 这四个函数即可实现对 CRichEditCtrl 的字体设置(函数的功能与用法查询MSDN即可).

说明:

1.同一个函数中 SetSelectionCharFormat 之前一定要有一次 SetWordCharFormat, 否则第一次
SetSelectionCharFormat 不生效.

2.设置颜色时,CHARFORMAT2 结构中的 dwMask 要具有 CFM_COLOR 标志,dwEffects 要清除 CFE_AUTOCOLOR 标志(设置为0即可),crTextColor 指定颜色.

◆ CComboBox 的使用

1. CComboBox 为焦点时获取其ID

问题: 通过 GetFocus() 获取 CComboBox 的焦点时, 当焦点在编辑框和按钮上时没有问题,一旦焦点在 CComboBox 框上, GetFocus() 的返回就有问题,用 UINT ID = GetFocus()-> GetDlgCtrlID(); 得到的返回值始终是 1001.

原因: MSDN 上的解释 A combo box consists of a list box combined with either a static control or edit control. 所以上面问题中的第2种情况实际上获取到的是 static control 的 ID.

解决:

UINT ID = GetFocus()->GetParent()->GetDlgCtrlID();

2. 输入自动匹配功能的实现

请参考 MFC Combobox 实现输入自动匹配

◆ CTreeCtrl 的使用

1. 初始化时SetCheck无效

对于对话框中的TreeView控件,如果想在初始化(OnInitDialog)中SetCheck,必须:

m_tree.ModifyStyle( TVS_CHECKBOXES, 0 );
m_tree.ModifyStyle( 0, TVS_CHECKBOXES );
m_tree.SetCheck(hItem, TRUE);

即即使在对话框编辑器中为 TreeView 增加了 Check Boxes 属性,也必须重新设一次 TVS_CHECKBOXES,SetCheck 才能起作用, 而对于非初始化中的SetCheck,则不受影响.

2. 双击不展开或收缩节点的办法。

void CTreeView::OnNMDblclk(NMHDR *pNMHDR, LRESULT *pResult)
{
*pResult = TRUE;
}

3. 实现CTreeCtrl父子节点的联动选择

请参考 实现CTreeCtrl父子节点的联动选择

◆ CMFCStatusBar 的使用

… 这个不得不吐槽下, 非常难用.

CMFCStatusBar m_wndStatusBar;

// 注意, 这些ID必须在资源的字符表里设置值, 要不然展现出来的效果是状态栏上对应的panel的背景色为黑色
static UNIT indicators[] =
{
IDS_STATUS_0,
IDS_STATUS_1,
IDS_STATUS_2,
IDS_STATUS_3,
IDS_STATUS_4,
};

// 创建
m_wndStatusBar.Create(this);
m_wndStatusBar.SetIndicators(indicators, sizeof(indicators) / sizeof(UNIT));

// 设置样式, 这里如果使用CStatusBar能实现相同效果的函数, 达不到预期效果
m_wndStatusBar.SetPanelStyle(0, SBPS_STRETCH);
m_wndStatusBar.SetPanelWidth(1, 80);

// 设置文字
m_wndStatusBar.SetPanelText
m_wndStatusBar.SetPanelTextColor
m_wndStatusBar.SetPanelBackgroundColor

// ... 最最重要的. 自定义的状态栏字体为灰色的问题
// 按网上的添加映射 ON_COMMAND(IDS_STATUS_0, NULL) 这样根本不能解决问题(第一个Panel始终为灰色, 后面的Panel可以解决)
// 方法如下:

// 通过更新UI的方式来解决
// IDS_STATUS_0 到 IDS_STATUS_4 不连续, 使用ON_UPDATE_COMMAND_UI分开实现即可
ON_UPDATE_COMMAND_UI_RANGE(IDS_STATUS_0, IDS_STATUS_4, &CMainFrame::OnUpdateStatusBar)

void CMainFrame::OnUpdateStatusBar(CCmdUI* pCmdUI)
{
pCmdUI->Enable(TRUE);
}

// 事件, 进度条, 图标 ... 暂时未使用, 遇到时添加

◆ CDockablePane 的使用

1. CDockablePane 的布局

请参考 CDockablePane使用心得

2. CDockablePane 的显示与隐藏

m_wndXXXPane.ShowPane(TRUE,FALSE,TRUE);     // 显示
m_wndXXXPane.ShowPane(FALSE,FALSE,FALSE); // 隐藏

3. 背景刷新问题.

在框架的 int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct)中创建了几个CDockablePane,里面是空的,运行,改变大小就会看到这些 CDockablePane 出现背景不会自动刷新.

重写 OnPanit()

void CPropertyPane::OnPaint()
{
CPaintDC dc(this); // device context for painting

CRect rc;
GetClientRect(rc);
CBrush brush;
brush.CreateSolidBrush(RGB(255, 255, 255));
dc.FillRect(&rc,&brush);

// Do not call CDockablePane::OnPaint() for painting messages
}

4. 如何自定义左右两个并列CDockablePane的大小

注:

  1. 本方法仅是通过重置窗体的属性来实现的, 如果您有好的方法请告知, 谢谢.
  2. 本方法同样适合设置上下两个并列CDockablePane的大小.

按系统默认的实现方式, 左右两个并列 CDockablePane 的布局会如下:

|------------|------------|

| | |

| pane1 | pane2 |

| | |

|------------|------------|

为了实现下图的样式

|-------|-----------------|

| | |

| pane1 | pane2 |

| | |

|------ |-----------------|

请参考如下代码:

BOOL CMainFrame::CreateDockingWindows()
{
BOOL bNameValid;

...

// Create pane1 window
CString strPane1;
bNameValid = strPane1.LoadString(ID_PANE_1);
ASSERT(bNameValid);
if (!m_wndPane1.Create(strPane1, this, CRect(0, 0, 100, 100), TRUE, ID_PANE_1, WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CLIPCHILDREN | CBRS_BOTTOM | CBRS_FLOAT_MULTI))
{
TRACE0("Failed to create pane1 window\n");
return FALSE; // failed to create
}

// Create pane2 window
CString strPane2;
bNameValid = strPane2.LoadString(ID_PANE_2);
ASSERT(bNameValid);
if (!m_wndPane2.Create(strPane2, this, CRect(0, 0, 200, 200), TRUE, ID_PANE_2, WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CLIPCHILDREN | CBRS_BOTTOM | CBRS_FLOAT_MULTI))
{
TRACE0("Failed to create pane2 window\n");
return FALSE; // failed to create
}

...

return TRUE;
}

int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
// TRUE : 允许加载上次的docking状态
// FALSE: 不允许加载上次的docking状态
EnableLoadDockState(FALSE);

...

// create docking windows
if (!CreateDockingWindows())
{
TRACE0("Failed to create docking windows\n");
return -1;
}

// 记住 Dock 前 m_wndPane1 的位置与大小
CRect r1;
m_wndPane1.GetWindowRect(&r1);

// DockPane
DockPane(&m_wndPane1);
DockPane(&m_wndPane2);

// 让 m_wndPane1 在 m_wndPane2 的左边, 函数中会改变两个Pane的大小, 使其大小一致, 各占 CMainFrame 宽度的一半
m_wndPane1.DockToWindow(&m_wndPane2, CBRS_LEFT);

// 还原 m_wndPane1 的位置与大小
m_wndPane1.SetWindowPos(NULL, r1.left, r1.top, r1.Width(), r1.Height(), SWP_NOZORDER | SWP_NOMOVE);

...

return 0;
}

void CMainFrame::OnSize(UINT nType, int cx, int cy)
{
CRect r1;

if (m_wndPane1.GetSafeHwnd())
{
// 获取 Pane1 改变前的位置与大小
m_wndPane1.GetWindowRect(&r1);
}

// 会触发所有 Pane 的 WM_SIZE 消息, 将所有 Pane 的大小重置
// 还会调用 AdjustDockingLayout 重新计算停靠到框架窗口的所有窗格的布局
CFrameWndEx::OnSize(nType, cx, cy);

if (m_wndPane1.GetSafeHwnd())
{
// 获取 Pane2 的位置与大小, 使 Pane1 的 top, bottom 与 Pane2的一致
CRect r2;
m_wndPane2.GetWindowRect(&r2);
r1.top = r2.left;
r1.bottom = r2.bottom;

// 还原 m_wndPane1 的位置与大小
m_wndPane1.SetWindowPos(NULL, r1.left, r1.top, r1.Width(), r1.Height(), SWP_NOZORDER | SWP_NOMOVE);

// 重新计算停靠到框架窗口的所有窗格的布局
AdjustDockingLayout();
}
}

本文持续更新中...

MFC 常用功能总结的更多相关文章

  1. WebStorm 常用功能的使用技巧分享

    WebStorm 是 JetBrain 公司开发的一款 JavaScript IDE,使用非常方便,可以使编写代码过程更加流畅. 本文在这里分享一些常用功能的使用技巧,希望能帮助大家更好的使用这款强大 ...

  2. AVA正则表达式4种常用功能

    正则表达式在字符串处理上有着强大的功能,sun在jdk1.4加入了对它的支持 下面简单的说下它的4种常用功能: 查询: String str="abc efg ABC";  Str ...

  3. [转]WebPack 常用功能介绍

    概述 Webpack是一款用户打包前端模块的工具.主要是用来打包在浏览器端使用的javascript的.同时也能转换.捆绑.打包其他的静态资源,包括css.image.font file.templa ...

  4. FastReport.Net 常用功能总汇

    一.常用控件 文本框:输入文字或表达式 表格:设置表格的行列数,输入数字或表达式 子报表:放置子报表后,系统会自动增加一个页面,你可以在此页面上设计需要的报表.系统在打印处理时,先按主报表打印,当碰到 ...

  5. python3 字符串与列表常用功能

    一.字符串常用功能 1. capitalize(),将字符串的首字母变成大写,其余全部置为小写:如果字符串中有多个单词,也只是将第一个单词的首字母置为大写:例: >>> name = ...

  6. matlab进阶:常用功能的实现,常用函数的说明

    常用功能的实现 获取当前脚本所在目录 current_script_dir = fileparts(mfilename('fullpath')); % 结尾不带'/' 常用函数的说明 bsxfun m ...

  7. WebPack常用功能介绍

    概述 Webpack是一款用户打包前端模块的工具.主要是用来打包在浏览器端使用的javascript的.同时也能转换.捆绑.打包其他的静态资源,包括css.image.font file.templa ...

  8. JavaScript 常用功能总结

    小编吐血整理加上翻译,太辛苦了~求赞! 本文主要总结了JavaScript 常用功能总结,如一些常用的JS 对象,基本数据结构,功能函数等,还有一些常用的设计模式. 目录: 众所周知,JavaScri ...

  9. TeeChart控件的安装与常用 功能设置

    TeeChart控件的安装 TeeChart 7.0 With Source在Delphi 7.0中的安装 一.删除Delphi7自带TeeChart  1.Component -> insta ...

随机推荐

  1. 【转载】Layered Window(分层窗体,透明窗体)

    本文转载自花间醉卧<Layered Window(分层窗体,透明窗体)> //为窗体添加WS_EX_LAYERED属性,该属性使窗体支持透明 ModifyStyleEx(0, WS_EX_ ...

  2. office web app server部署和简单操作

    部署环境:windows server 2012 R2,服务器在AD域中 参考网址: https://msdn.microsoft.com/zh-cn/magazine/jj219455(office ...

  3. SQL Server T—SQL 语句【查】

    一 查询数据(关键字:select) (1)简单查询        select * from 表名                    ——查全表 select 列名 from 表名 select ...

  4. Linux-man命令(17)

    man命令是Linux下的帮助指令,通过man指令可以查看Linux中的指令帮助.配置文件帮助和编程帮助等信息 可以按章节来搜索手册: man 1: 用户命令(ls,cd,cp,rm,tar等) ma ...

  5. Redis哨兵(sentinel)模式搭建

    一.Sentinel介绍 之前骚了一波Redis的简介及应用场景,今天试了下他的哨兵模式: Sentinel是Redis的高可用性(HA)解决方案,由一个或多个Sentinel实例组成的Sentine ...

  6. JFace TableViewer性能改善 -- 使用VirtualTable

    前一篇提到了SWT中的table的通过使用virtual table性能得到很大的改善,那么如果既存的工程中使用的是TableViewer来创建的表,也能改成virtual table吗? 答案是肯定 ...

  7. java 传入list集合 返回树形菜单,for循环遍历

    public List<SysPermissionVO> getTreeMenu(List<SysPermissionVO> list,SysPermissionVO sysP ...

  8. oracle逐步学习总结之oracle数字函数和日期函数(基础四)

    原创作品,转自请注明出处:https://www.cnblogs.com/sunshine5683/p/10140716.html 继上篇总结,继续进行总结: 以下下数字函数: 1.abs(n):返回 ...

  9. 创建Cordova项目 报错Error: Unhandled "error" event

    cordova版本7.0以上版本 创建cordova项目错误信息 Error: Unhandled "error" event. (  Error from Cordova Fet ...

  10. 设计模式原则(4)--Interface Segregation Principle(ISP)--接口隔离原则

    作者QQ:1095737364    QQ群:123300273     欢迎加入! 1.定义: 使用多个专门的接口,而不使用单一的总接口,即客户端不应该依赖那些它不需要的接口. 2.使用场景: 类A ...