mfc在编写桌面客户端应用应用程序,在设计界面时,如果像一般的界面,实施人员或者适配人员使用(特定的用户群体)对界面要求没有那么高,只要软件功能正常,稳定就行,我们在做这些界面时,通常使用原生的控件,其实这些控件和QT的差不多,都是些常用的控件,当然为为了界面美观,也可以自己封装界面或者皮肤库或者消息框弹框库等等,笔者这里说下基本的常用控件,这里它们的基本属性就不赘述了,那比较简单,从书上或者入门视频上都可以学到,这里说明下它们的特殊场景或者一些使用技巧吧,避免以后再踩坑。
一、CComboBox
1.使用该控件时,如果下拉框内容过多,切记选择后,然后再设计区拖拽拉长,如果只是放置的话,它有默认高度,这样会使添加的内容显示不完全。
2.如果需要动态变换下拉框的内容,可以先清空,然后重设,具体实例代码如下:
这种场景一般在多级级联时需要实现这样的功能(eg:班级,人名),不同的班级有不同的人。
while (m_comboBox.GetCount() > 0)
{
m_comboBox.DeleteString(0);
}
CString str;
for(int i = 1; i <= GROUP_NUM; i++){
str.Format("%d", i);
m_comboBox.AddString("移动" + str);
m_comboBox.SetCurSel(0);
}
效果如下:
3.内容过长时,可以设置tips,鼠标悬浮到其上面时,可以显示完整内容:
像上面这种,测试反手上去就是一个bug,那具体怎么做呢,比较简单:
具体实现分四部:
3.1 声明变量: CToolTipCtrl m_ToolTipCtrl;
3.2 构造函数中初始化:
m_ToolTipCtrl.Create(this);
m_ToolTipCtrl.Activate(TRUE);
3.3 消息分发函数中过滤:
BOOL CMFCWizardDlg::PreTranslateMessage(MSG* pMsg)
{
// TODO: 在此添加专用代码和/或调用基类
if (NULL != m_ToolTipCtrl.GetSafeHwnd())
{
switch (pMsg->message)
{
case WM_MOUSEMOVE:
m_ToolTipCtrl.RelayEvent(pMsg);
break;
default:
break;
}
}
return CDialogEx::PreTranslateMessage(pMsg);
}
3.4 内容变化时,动态设置tips内容:
void CMFCWizardDlg::OnCbnSelchangeCombo1()
{
// TODO: 在此添加控件通知处理程序代码
m_comboBox.GetLBText(m_comboBox.GetCurSel(), m_strComboBox);
//增加Tip提示
CString strTipName = m_strComboBox;
CWnd* pWnd = GetDlgItem(IDC_COMBO1);
m_ToolTipCtrl.AddTool(pWnd, strTipName);
}
一、CEdit
1.只能输入固定字符(eg:只能输入数字【这当然包含正负数和零了】,有的人可能把富数忘记了);
这时就需要集成CEdit重新实现OnChar方法了,实例代码如下:
#pragma once
// CNumEdit
class CNumEdit : public CEdit
{
DECLARE_DYNAMIC(CNumEdit)
public:
CNumEdit();
virtual ~CNumEdit();
protected:
virtual BOOL PreTranslateMessage(MSG* pMsg);
DECLARE_MESSAGE_MAP()
public:
afx_msg void OnChar(UINT nChar, UINT nRepCnt, UINT nFlags);
void setRange(double min, double max);
bool IsSave();
bool m_bSaveFlag;
private:
double maxValue;
double minValue;
};
// NumEdit.cpp : 实现文件
//
#include "../stdafx.h"
#include "NumEdit.h"
// CNumEdit
IMPLEMENT_DYNAMIC(CNumEdit, CEdit)
CNumEdit::CNumEdit()
{
maxValue = CHAR_MAX;
minValue = 0;
m_bSaveFlag = false;
}
CNumEdit::~CNumEdit()
{
}
BEGIN_MESSAGE_MAP(CNumEdit, CEdit)
ON_WM_CHAR()
END_MESSAGE_MAP()
// CNumEdit 消息处理程序
BOOL CNumEdit::PreTranslateMessage(MSG* pMsg)
{
return CEdit::PreTranslateMessage(pMsg);
}
void CNumEdit::OnChar(UINT nChar, UINT nRepCnt, UINT nFlags)
{
// 保证负号只能出现一次,并且只能出现在第一个字符
if(nChar=='-')
{
CString str;
GetWindowText(str);
// 还没有输入任何字符串
if(str.IsEmpty())
{
CEdit::OnChar(nChar, nRepCnt, nFlags);
}
else
{
int nSource,nDestination;
GetSel(nSource,nDestination);
// 此时选择了全部的内容
//if(nSource==0 && nDestination == str.GetLength())
//{
// CEdit::OnChar(nChar, nRepCnt, nFlags);
//}
//else
//{
//}
if (0 == nSource)
{
CEdit::OnChar(nChar, nRepCnt, nFlags);
}
m_bSaveFlag = true;
}
}
// 除了负号,还允许输入数字,Backspace,Delete
else if((nChar >= '0' && nChar <= '9')||(nChar == 0x08)||(nChar == 0x10)||(nChar == 0x16)||(nChar == 0x03)||(nChar == 0x01)) // VK_DELETE
{
m_bSaveFlag = true;
CEdit::OnChar(nChar, nRepCnt, nFlags);
}
// 其它的键,都不响应
else
{
m_bSaveFlag = false;
}
}
void CNumEdit::setRange(double min, double max )
{
maxValue = max;
minValue = min;
}
bool CNumEdit::IsSave()
{
return m_bSaveFlag;
}
2.默认为0,只能输入0-1000,输入其它非法数字时变成0;
这个比较简单,本身有输入数字的属性,只不过判断其它值时将其值设置成0,(这里需要注意的是,设置完后,记得处理光标位置【特别是多个控件连锁反应判断时,需要注意处理完后,需要恢复光标位置,否则感觉光标跳转】)。
1-1000可以使用正则:
#define TRACE_PERIOD_REGEX "^([1-9][0-9]{0,2}|1000)$"
3.输入非法字符变红色(这种一般在数据库中查找,能找到说明是合法了,正常颜色,如果找不到为非法,变为红色);
4.根据另一个输入控件的变量类型来变颜色(eg: bool int sint real lreal uint short ushort等等);
5.和另一个CComboBox做切换效果的展示(可以使用下面两个属性,当然可以根据当前实现的是哪个控件来处理业务逻辑。
m_beginSymbol_bool_combox.EnableWindow(FALSE);
m_beginSymbol_bool_combox.ShowWindow(SW_HIDE);
6. 编辑框默认好像能允许输入3万多个字符,但在实际中应该对用户输入的字符数量做一个限制,因为一旦无效了,再输入再也没有意义了。