九阳道人的MFC学习之旅
好记性不如烂笔头,MFC用过很多遍了,每次用完后就很久不去碰,之后就忘了怎么用MFC,现在特此记录。
环境:VS2017
?
1、修改程序版本信息
修改如图:
鼠标放在exe程序上时效果图如下: ?
2、截获和处理键盘鼠标消息
在MFC中,PreTranslateMessage是虚函数,是用来截获消息的,我们可以通过重载它来处理键盘和鼠标消息。
在资源的dialog界面按ctrl+shift+x调出类向导,双击添加PreTranslateMessage虚函数如图:
?
3、注册全局热键
OnInitDialog()是窗口初始化函数,初始化的东西都放在这个函数里面。
在OnInitDialog()中添加:
::RegisterHotKey(m_hWnd, 0x1230, MOD_CONTROL | MOD_SHIFT, '0');
在类向导生成函数PreTranslateMessage处理相应消息
if (pMsg->message == WM_HOTKEY && (pMsg->wParam == 0x1230))
{
LockWorkStation();
}
?
4、设置窗口名称
在OnInitDialog()中添加:
AfxGetMainWnd()->SetWindowText(L"九阳道人_HackerTool");
?
5、防双开
可以在类视图中添加函数,实现自己的功能。
if (IsAlreadyRun())
{
::MessageBox(0,L"已启动程序,请勿重复运行!",L"九阳道人",0);
::exit(0);
}
bool CHappyWorkDlg::IsAlreadyRun()
{
HANDLE hMutex = NULL;
hMutex = ::CreateMutex(NULL, FALSE, L"九阳道人");
if (hMutex)
{
if (ERROR_ALREADY_EXISTS == ::GetLastError())
{
return true;
}
}
return false;
}
?
6、调试程序方法
在多线程或者多计时器情况下,使用DbgView查看日志,输出日志函数如下:
OutputDebugStringA("当前文件全路径如下:");
?
7、类向导添加自定义消息
?
8、添加和处理菜单
1、首先在资源中添加菜单,然后取好名字 2、在菜单界面右键添加事件处理 3、修改填写相应选项
?
9、添加托盘图标显示效果
1、先在头文件定义一个托盘变量。
NOTIFYICONDATA m_Tray;
2、通过类向导生成WM_CREATE函数,在这个函数中初始化托盘图标变量。
int CHappyWorkDlg::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
if (CDialogEx::OnCreate(lpCreateStruct) == -1)
return -1;
wcscpy_s(m_Tray.szTip, L"快乐工作");
m_Tray.cbSize = sizeof(NOTIFYICONDATA);
m_Tray.hWnd = m_hWnd;
m_Tray.uID = 0x10086;
m_Tray.hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
m_Tray.uFlags = NIF_ICON | NIF_TIP | NIF_MESSAGE;
m_Tray.uCallbackMessage = WM_TRAY_ICON;
Shell_NotifyIcon(NIM_ADD, &m_Tray);
return 0;
}
3、通过类向导生成WM_DESTROY函数,程序退出时销毁托盘图标。
void CHappyWorkDlg::OnDestroy()
{
CDialogEx::OnDestroy();
Shell_NotifyIcon(NIM_DELETE, &m_Tray);
}
4、如上面第7步骤,先添加一个自定义消息,然后在窗口头文件xxxDlg.h文件中定义好该自定义消息。
#define WM_TRAY_ICON (WM_USER + 1)
最后处理好消息处理函数,wParam是自义定消息的资源ID,lParam是消息类型。
afx_msg LRESULT CHappyWorkDlg::OnTrayIcon(WPARAM wParam, LPARAM lParam)
{
if (wParam == 0x10086)
{
switch (lParam)
{
case WM_RBUTTONDOWN:
SetForegroundWindow();
break;
case WM_LBUTTONDOWN:
SetForegroundWindow();
}
}
return 0;
}
?
10、修改窗口名和程序名
1、窗口名在OnInitDialog中。
AfxGetMainWnd()->SetWindowText(L"九阳道人");
2、程序名在属性常规中直接修改
?
11、添加tab控件及其子窗口
1、首先在主窗口中用工具箱添加好tab控件。 2、在资源中新建子窗口,然后修改如下图3个属性。 3、调整好子窗口大小为tab控件的包容大小。 ?
12、tab控件,父子窗口的整体交互
1、添加静态文本用static_text。 2、布局好两个子窗口后,分别给两个子窗口创建一个类。 3、在父窗口的.h文件引用子类的头文件,然后定义出子窗口的变量,还有tab控件变量。
CTabCtrl m_nTab;
WindborneSpeed m_WindborneSpeed;
MostUrgent m_MostUrgent;
4、父窗口首先要在OnInitDlg初始化两个子窗口信息。
m_nTab.InsertItem(0, L" 快如风 ");
m_nTab.InsertItem(1, L" 急如火 ");
m_WindborneSpeed.Create(MAKEINTRESOURCEW(IDD_DIALOG1), &m_nTab);
m_MostUrgent.Create(MAKEINTRESOURCEW(IDD_DIALOG2), &m_nTab);
RECT rect;
m_nTab.GetClientRect(&rect);
rect.top += 22;
rect.left += 1;
rect.bottom -= 2;
rect.right -= 3;
m_WindborneSpeed.MoveWindow(&rect);
m_MostUrgent.MoveWindow(&rect);
m_WindborneSpeed.ShowWindow(SW_SHOW);
5、给tab控件添加事件处理函数。
void CHappyWorkDlg::OnTcnSelchangeTab1(NMHDR *pNMHDR, LRESULT *pResult)
{
int num = m_nTab.GetCurSel();
switch (num)
{
case 0:
m_WindborneSpeed.ShowWindow(SW_SHOW);
m_MostUrgent.ShowWindow(SW_HIDE);
break;
case 1:
m_WindborneSpeed.ShowWindow(SW_HIDE);
m_MostUrgent.ShowWindow(SW_SHOW);
break;
}
*pResult = 0;
}
?
13、禁止窗口被拉动变形,扩展为无应用图标模式
在OnCreate函数添加。
ModifyStyleEx(WS_EX_APPWINDOW, WS_EX_TOOLWINDOW);
ModifyStyle(WS_THICKFRAME, 0, 0);
?
14、本文控件和滑条控件
在类视图中相应的类可以添加自定义的函数。
1、在绑定static_text类型的控件变量时,需要先把文本控件ID给更改掉,然后选择值。
?
15、解决按ESC键或ENTER键窗口程序会退出问题
1、主窗口如下:
if (pMsg->message == WM_KEYDOWN && (pMsg->wParam == VK_ESCAPE || pMsg->wParam == VK_RETURN))
{
return TRUE;
}
2、每个子窗口都需要处理以下消息。
BOOL WindborneSpeed::PreTranslateMessage(MSG* pMsg)
{
if (pMsg->message == WM_KEYDOWN && (pMsg->wParam == VK_ESCAPE))
{
return TRUE;
}
return CDialogEx::PreTranslateMessage(pMsg);
}
?
16、复选框
绑定CButton类型变量,然后1是选中,0是为选,处理如下。
if (m_Check.GetCheck() == 0)
{
}
m_Check.SetCheck(1);
?
17、获取环境变量
CString str;
str.GetEnvironmentVariable(L"PATH");
AfxMessageBox(str);
|