文章目录
CString类的使用对象初始化对象基本操作对象拼接字符串比较字符串查找字符串替换与删除字符串提取字符串格式化
模态对话框 vs 非模态对话框内存分配的三种方式对话框之间的数据传递控件变量的绑定定时器的使用对话框响应响应鼠标及键盘消息全局热键注册控件自定义消息的响应
CString类的使用
对象初始化
CString str1
;
CString
str2(_T("hello"));
CString str3
= _T("hello");
TCHAR szBuf
[] = _T("ABC");
CString
str4(szBuf
);
CString str5
= szBuf
;
TCHAR
*pChar
= _T("CHINA");
CString
str6(pChar
);
CString str7
= pChar
;
CString
str8(str7
);
CString str9
= str7
;
对象基本操作
CString
str(_T("hello,kitty--中国"));
int len
= str
.GetLength();
bool flag1
= str
.IsEmpty();
bool flag2
= CString().IsEmpty();
str
.MakeUpper();
MessageBox(str
);
str
.MakeLower();
MessageBox(str
);
str
.MakeReverse();
MessageBox(str
);
对象拼接
CString str1
= TEXT("hello");
CString str2
= TEXT("kitty");
CString str3
= str1
+ TEXT(",") + str2
;
MessageBox(str3
);
str3
+= CString(TEXT(": china"));
MessageBox(str3
);
TCHAR szBuf
[] = TEXT("AAA");
str3
+= szBuf
;
MessageBox(str3
);
TCHAR
*pTChar
= TEXT("BBB");
str3
+= pTChar
;
MessageBox(str3
);
字符串比较
CString
s1(TEXT("ABC"));
CString s2
= TEXT("BBB");
TCHAR szBuf
[] = TEXT("ABC");
TCHAR
*pTChar
= TEXT("abc");
bool flag
= s1
== s2
;
flag
= s1
== szBuf
;
flag
= s1
== pTChar
;
int i
= 0;
i
= s1
.Compare(szBuf
);
i
= s1
.Compare(pTChar
);
i
= s1
.CompareNoCase(szBuf
);
i
= s1
.CompareNoCase(pTChar
);
字符串查找
CString str
= TEXT("ABDFCEDF0");
int index
= str
.Find(TEXT("DF"), 0);
index
= str
.ReverseFind(TEXT('D'));
CString str2
= TEXT("abcdabc");
index
= str2
.FindOneOf(TEXT("cda"));
字符串替换与删除
CString str1
= TEXT("abcdabc");
str1
.Replace(TEXT('b'), TEXT('k'));
MessageBox(str1
);
CString str2
= TEXT("abcdabc");
str2
.Replace(TEXT("bc"), TEXT("KF"));
MessageBox(str2
);
CString str
= TEXT("abcdabc");
TCHAR xch
= str
.GetAt(0);
str
.SetAt(0, TEXT('K'));
MessageBox(str
);
CString str3
= TEXT("abcdabc");
int count
= str3
.Remove(TEXT('b'));
MessageBox(str3
);
CString str4
= TEXT("abcdabc");
count
= str4
.Delete(1, 3);
MessageBox(str4
);
字符串提取
CString str
= TEXT("abcd");
MessageBox(str
.Left(2));
MessageBox(str
.Mid(2));
MessageBox(str
.Right(3));
字符串格式化
int num
= 6;
CString str1
;
str1
.Format(TEXT("%d"), num
);
MessageBox(str1
);
CString str2
= TEXT("101");
int i2
= _ttoi(str2
);
TCHAR
*p1
= str2
.GetBuffer();
MessageBox(p1
);
str2
.ReleaseBuffer();
MessageBox(p1
);
TCHAR
*p2
= (LPTSTR
)(LPCTSTR
)str2
;
MessageBox(p2
);
模态对话框 vs 非模态对话框
创建模态对话框:Dialog#DoModal()
#include "MyDialog.h"
void CDemo02Dlg
::OnBnClickedOk()
{
MyDialog dlg
;
dlg
.DoModal();
}
创建非模态对话框:Dialog#Create()
void CDemo02Dlg
::OnBnClickedCancel()
{
MyDialog dlg
;
dlg
.Create(MyDialog
::IDD
, this);
dlg
.ShowWindow(SW_SHOW
);
}
但是这样的创建非模态对话框:对话框闪一下就会退出:因为dlg对象是自动变量,且非模态对话框不会阻塞程序流程:自动变量离开作用域就被销毁:对象都被销毁了,对话框肯定不存在了:解决办法之一:使用全局变量或静态变量
MyDialog dlg
;
void CDemo02Dlg
::OnBnClickedCancel()
{
dlg
.Create(MyDialog
::IDD
, this);
dlg
.ShowWindow(SW_SHOW
);
}
虽然解决了一闪而过的问题:但是不能多次执行:第二次执行此段代码的时候,应用程序会崩溃:因为dlg是全局变量,每次执行{…}中的代码的时候都在重复创建对话框:所以导致程序崩溃:解决方案之一:就是在MyDialog对话框退出的代码中添加销毁非模态对话框的代码:DestroyWindow()
void MyDialog
::OnBnClickedCancel()
{
DestroyWindow();
}
非模态对话框的创建: (1)使用全局变量,即非模态对话框对象是全局变量 (2)使用成员变量,即非模态对话框对象是其他对话框类的成员变量,在OnInitDialog方法中创建非模态对话框,在需要的时候进行显示 (3)使用全局或成员指针变量
MyDialog
*pDlg
= NULL;
void CDemo02Dlg
::OnBnClickedCancel()
{
if (pDlg
== NULL) {
pDlg
= new MyDialog
;
}
pDlg
->Create(MyDialog
::IDD
, this);
pDlg
->ShowWindow(SW_SHOW
);
}
内存分配的三种方式
从静态存储区分配:内存的程序编译的时候就已经分配好,这块内存在程序的整个运行器件都存在:例如全局变量,static变量:全局static变量、局部static变量、static成员变量从栈区分配:在执行函数时,函数内局部变量的存储单元可以在栈上创建,函数执行结束时这些存储单元自动释放。栈内存分配运行内置处理器的指令集中:即从汇编代码中可以看出!效率很高,但是分配的内存容量有限从堆区分配:也称之为动态内存分配。程序运行的时候使用库函数malloc或关键字new申请任意数量的内存,程序员自己负责在何时使用库函数free或关键字delete释放内存:动态内存的生存期由程序员决定:使用非常灵活,但问题也最多
对话框之间的数据传递
全局变量法 主对话框法:AfxGetMainWnd() 父窗口法:GetParent 成员变量、成员函数法
控件变量的绑定
对话框控件不同类型成员变量的绑定DDX:Dialog Data Exchange:对话框数据交换DDV:Dialog Date Validate:对话框数据校验一个控件可以绑定多个不同类型的变量:控件类型与值类型 设置以后发生了什么? (1)在类定义文件中有了相关变量的声明:即对话框的头文件中 (2)在对话框实现文件中的DoDataExchange()方法中,进行了相关的绑定 那么知道了原理后就可以手动的添加代码:即不需要借助工具的条件下完成控件变量的绑定工作开源控件的使用:导入开源代码到目标工程中–>控件绑定变量(如果是控件类型,使用开源控件类定义变量即可:DoDataExchange()方法中代码不需要改变)–>使用开源控件:绑定控件类型变量,进行子类化操作
定时器的使用
定时器Timer在windows程序设计中很多地方都能用到:它主要用途就是按程序设定间隔时间,间歇性的产生WM_TIMER消息:发送到指定窗口之后,在窗口中对WM_TIMER消息进行处理,完成指定任务定时器相关的API函数
SetTimer(定时器id, 产生WM_TIMER消息时间间隔, 回调函数: 消息响应函数):启动定时器
OnTimer(定时器ID):定时器响应函数
KillTimer(定时器ID):关闭定时器
SetTimer(1, 1000, NULL);
void CDemo02Dlg
::OnTimer(UINT_PTR nIDEvent
)
{
CTime tm
= CTime
::GetCurrentTime();
CString str
= tm
.Format(TEXT("%Y-%m-%d %H:%M:%S"));
SetDlgItemText(IDC_STATIC
, str
);
CDialog
::OnTimer(nIDEvent
);
}
对话框响应响应鼠标及键盘消息
常见的鼠标消息
WM_MOUSEMOVE:鼠标移动
WM_LBUTTONDOWN:鼠标左键按下
WM_LBUTTONUP:鼠标左键抬起
WM_LBUTTONDBLCLK:鼠标左键双击
WM_RBUTTONDOWN:鼠标右键按下
WM_RBUTTONUP:鼠标右键抬起
WM_RBUTTONDBLCLK:鼠标右键双击
WM_MBUTTONDOWN:鼠标中键按下
WM_MBUTTONUP:鼠标中键抬起
WM_MBUTTONDBLCLK:鼠标中键双击
WM_MOUSEWHEEL:鼠标滚轮滚动
创建的键盘消息
WM_KEYDOWN:按键按下
WM_CHAR:可以打印的字符
WM_KEYUP:按键抬起
自定义一个按钮:可以响应鼠标左键按下与鼠标左键抬起的消息:在自动化软件中会经常使用此功能 在CMyButton类中添加WM_LBUTTONDOWN与WM_LBUTTONUP消息响应函数 给对话框中的按钮绑定控件类型变量
CMyBuuton m_btn;
DDX_Control(pDX, IDC_BUTTON1, m_btn);
对话框响应键盘消息:在虚函数PreTranslateMessage中进行安检的处理
virtual BOOL
PreTranslateMessage(MSG
* pMsg
);
BOOL CDemo02Dlg
::PreTranslateMessage(MSG
* pMsg
) {
switch (pMsg
->message
) {
case WM_KEYDOWN
:
SetDlgItemText(IDC_EDIT1
, TEXT("WM_KEYDOWN"));
break;
case WM_KEYUP
:
SetDlgItemText(IDC_EDIT1
, TEXT("WM_KEYUP"));
break;
default:
break;
}
return CDialog
::PreTranslateMessage(pMsg
);
}
WM_KEYDOWN消息中的wParam参数,即pMsg->wParam字符都是大写的:如果要判断按下的字符是大写还是小写,可以在WM_CHAR消息中使用ASCII码对pMsg->wParam进行判断:WM_KEYDOWN/WM_KEYUP与WM_CHAR他们的用途是不同的:前者是用来判断按键被按下与抬起:后者怎是检测哪个可见字符被按下了对话框程序响应组合键、快捷键:利用GetKeyState函数获得某一按键的按下与抬起的状态:该函数的返回值的最高位为1表示按键按下:为0表示按键抬起状态
#define IsKeyPressed(nVirtKey) ((GetKeyState(nVirtKey) & (1 << (sizeof(SHORT) * 8 - 1))) != 0)
#define IsKetToggled(nVirtKey) ((GetKeyState(nVirtKey) & 1) != 0)
BOOL CDemo02Dlg
::PreTranslateMessage(MSG
* pMsg
)
{
if (pMsg
->message
== WM_KEYDOWN
&& pMsg
->wParam
== 'Q' && IsKeyPressed(VK_CONTROL
)) {
MessageBox(TEXT("Ctrl + Q"));
}
return CDialog
::PreTranslateMessage(pMsg
);
}
通过载入快捷键(加速键)资源,并建立快捷键与消息映射的方法来实现
1. 添加快捷键资源
2. 修改快捷键资源中的组合键配置
3. 添加响应函数声明:格式:afx_msg void OnCtrlW()
4. 添加消息映射:ON_BTN_CLICKED(ID_ACC1, onOnCtrlW)或ON_BTN_CLICKED(ID_ACC1, &XXXDlg::onOnCtrlW)
5. 添加响应代码
6. 初始化快捷键资源:
HACCEL hAcc
= LoadAccelerators(AfxGetApp()->m_hInstance
, MAKEINTRESOURCE(IDR_ACCELERATOR1
));
在MFC中测试没有通过???在对话框中使用组合键:方法1就是在虚函数中PreTranslateMessage中实现;方法2使用资源:方法1比较直接,使用方便,但是一般只应用于快捷键比较少的应用程序;方法2比较使用,虽然实现起来代码量稍微大一些,但是适用于快捷键比较多的应用程序中:但是这两种方式在窗口隐藏或最小化的时候都是不能响应快捷键的
全局热键注册
全局热键的优点:即使窗口最小化或隐藏或窗口不是当前的活动窗口:也可以响应热键:例如QQ软件的默认呼出热键:Ctrl+Alt+Z就是注册了全局系统热键给窗口注册全局热键
BOOL suc
= RegisterHotKey(m_hWnd
, 100, MOD_CONTROL
, 'W');
第一个参数:窗口句柄
第二个参数:热键标识
第三个参数:组合键,可以是MOD_ALT、MOD_CONTROL、MOD_SHIFT、MOD_WIN任意组合
第三个参数:指定热键的虚拟键盘码,例如
'A'
UnregisterHotKey(m_hWnd
, 100);
第一个参数:窗口句柄
第二个参数:热键标识
给工作线程注册全局热键:没有窗口
static UINT __cdecl
ThreadProc(LPVOID lpParam
);
UINT __cdecl CDemo03Dlg
::ThreadProc(LPVOID lpParam
) {
RegisterHotKey(NULL, 100, MOD_CONTROL
, 'W');
MSG msg
= {0};
while (GetMessage(&msg
, NULL, 0, 0)) {
switch (msg
.message
) {
case WM_HOTKEY
:
{
int idHotKey
= (int) msg
.wParam
;
int fuModifiers
= (UINT
) LOWORD(msg
.lParam
);
int uVirtKey
= (UINT
) HIWORD(msg
.lParam
);
if (idHotKey
== 100 && fuModifiers
== MOD_CONTROL
&& uVirtKey
== 'W')
AfxMessageBox(TEXT("--------"));
}
break;
default:
break;
}
}
UnregisterHotKey(NULL, 100);
return 0;
}
AfxBeginThread(ThreadProc
, this);
GetMessage在没有消息的时候会阻塞线程,改为PeekMessage
UINT __cdecl CDemo03Dlg
::ThreadProc(LPVOID lpParam
) {
RegisterHotKey(NULL, 100, MOD_CONTROL
, 'W');
MSG msg
= {0};
for (;;) {
while (PeekMessage(&msg
, NULL, 0, 0, PM_REMOVE
)) {
switch (msg
.message
) {
case WM_HOTKEY
:
{
int idHotKey
= (int) msg
.wParam
;
int fuModifiers
= (UINT
) LOWORD(msg
.lParam
);
int uVirtKey
= (UINT
) HIWORD(msg
.lParam
);
if (idHotKey
== 100 && fuModifiers
== MOD_CONTROL
&& uVirtKey
== 'W')
AfxMessageBox(TEXT("--------"));
}
break;
default:
break;
}
}
}
Sleep(50);
UnregisterHotKey(NULL, 100);
return 0;
}
控件自定义消息的响应
按钮控件的右键消息
1. 向工程中添加一个派生自CButton类的子类CMyButton
2. 为按钮绑定一个CMyButton类型的空间类型变量
3. 响应CMyButton类的你想响应的消息