九阳道人的MFC学习之旅
好记性不如烂笔头,MFC用过很多遍了,每次用完后就很久不去碰,之后就忘了怎么用MFC,现在特此记录。
文章目录
- 九阳道人的MFC学习之旅
- 1、修改程序版本信息
- 2、截获和处理键盘鼠标消息
- 3、注册全局热键
- 4、设置窗口名称
- 5、防双开
- 6、调试程序方法
- 7、类向导添加自定义消息
- 8、添加和处理菜单
- 9、添加托盘图标显示效果
- 10、修改窗口名和程序名
- 11、添加tab控件及其子窗口
- 12、tab控件,父子窗口的整体交互
- 13、禁止窗口被拉动变形,扩展为无应用图标模式
- 14、本文控件和滑条控件
- 15、解决按ESC键或ENTER键窗口程序会退出问题
- 16、复选框
- 17、获取环境变量
- 18、本文框显示到末尾
- 19、局部更新控件
- 20、子窗口给父窗口发送消息
- 21、限制编辑框Edit的内容长度
- 22、控件字体和背景颜色设置
- 23、响应F1帮助
- 24、组合框
- 25、调试时程序能运行,但随即会崩溃
- 26、响应拖拽
- 27、打开文件
- 28、单选框
- 29、多字节和宽之间之间的转换
- 30、显示隐藏,使不使能控件
- 30、按钮实现打开组合框下拉列表
- 31、遍历队列
- 32、遍历文件
- 32、UAC管理员权限运行(图标带盾牌)
环境:VS2017
1、修改程序版本信息
修改如图:
鼠标放在exe程序上时效果图如下:
2、截获和处理键盘鼠标消息
在MFC中,PreTranslateMessage是虚函数,是用来截获消息的,我们可以通过重载它来处理键盘和鼠标消息。
在资源的dialog界面按ctrl+shift+x调出类向导,双击添加PreTranslateMessage虚函数如图:
3、注册全局热键
OnInitDialog()是窗口初始化函数,初始化的东西都放在这个函数里面。
在OnInitDialog()中添加:
//注册快捷键 ctrl+shift+0
::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()
{
// TODO: 在此处添加实现代码.
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函数,在这个函数中初始化托盘图标变量。
// WM_CREATE
int CHappyWorkDlg::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
if (CDialogEx::OnCreate(lpCreateStruct) == -1)
return -1;
// 以下初始化托盘图标参数,不能在构造函数初始化,因为构造中m_hWnd=NULL;
wcscpy_s(m_Tray.szTip, L"快乐工作"); // 当鼠标放在tray icon上面的时候显示的文字
m_Tray.cbSize = sizeof(NOTIFYICONDATA); // 指定结构体大小
m_Tray.hWnd = m_hWnd; // 指定接收通告消息的窗口句柄.系统就是通过hWnd和uID来辨别当Shell_NotifyIcon函数调用的时候操作的是哪个托盘图标
m_Tray.uID = 0x10086; // 应用程序定义的任务栏图标表示符。一个hWnd可以有很多的图标与之关联,这是通过指定不同的uID实现的
m_Tray.hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME); // 要操作(添加、删除、修改)的图标句柄
m_Tray.uFlags = NIF_ICON | NIF_TIP | NIF_MESSAGE; // 标记那些成员有效
m_Tray.uCallbackMessage = WM_TRAY_ICON; // 当鼠标在图标区域内发生了事件,比如单击、双击时,
// 系统会把这个消息发送到hWnd成员对应的窗口,然后该窗口可以处理该事件。
// 这里可以不是WM_COMMAND,可以自定义消息,然后响应这个消息
// 显示托盘图标
Shell_NotifyIcon(NIM_ADD, &m_Tray);
return 0;
}
3、通过类向导生成WM_DESTROY函数,程序退出时销毁托盘图标。
void CHappyWorkDlg::OnDestroy()
{
CDialogEx::OnDestroy();
// TODO: 在此处添加消息处理程序代码
// 销毁托盘图标
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)
{
// TODO: 在此添加专用代码和/或调用基类
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; // tab 变量
WindborneSpeed m_WindborneSpeed; // 快如风
MostUrgent m_MostUrgent; // 急如火
4、父窗口首先要在OnInitDlg初始化两个子窗口信息。
// 以下初始化tab控件
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.top += 26; // 老版win10
rect.left += 1;
rect.bottom -= 2;
rect.right -= 3;
m_WindborneSpeed.MoveWindow(&rect);
m_MostUrgent.MoveWindow(&rect);
// 显示默认的子窗口
m_WindborneSpeed.ShowWindow(SW_SHOW);
5、给tab控件添加事件处理函数。
// 处理tab应该显示哪个子窗口
void CHappyWorkDlg::OnTcnSelchangeTab1(NMHDR *pNMHDR, LRESULT *pResult)
{
// TODO: 在此添加控件通知处理程序代码
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、主窗口如下:
// 禁止按ESC键或回车就退出窗口
if (pMsg->message == WM_KEYDOWN && (pMsg->wParam == VK_ESCAPE || pMsg->wParam == VK_RETURN))
{
return TRUE;
}
2、每个子窗口都需要处理以下消息。
// 类向导添加虚函数处理消息,解决按ESC键退出问题
BOOL WindborneSpeed::PreTranslateMessage(MSG* pMsg)
{
// 禁止按ESC键就退出窗口
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);
18、本文框显示到末尾
单行本文太长时需要显示到最后内容,绑定EDIT控件,然后编辑如下
// 将文本框显示到末尾
int nLen = m_edit8.GetWindowTextLength();
m_edit8.SetSel(nLen, nLen, FALSE);
m_edit8.SetFocus();
19、局部更新控件
有时有很多控件,定时器用UpdateData就全部刷新了,但我现在只需要刷新部分控件,所以不用UpdateData,用如下方法。
GetDlgItem(IDC_ALL_MEM)->SetWindowText(m_All); // 从内部设置数据到控件
GetDlgItem(IDC_EDIT1)->GetWindowText(m_strNum); // 从控件获取值到字符串
20、子窗口给父窗口发送消息
在工程中,若父窗口创建了子窗口对象,那么所有的子窗口操作都应该由父窗口的类对象中完成。
假设MFC工具需要保存配置参数,既要保存父窗口的参数,又要保存子窗口的参数,那么子窗口只需要实现保存参数的成员函数就行了,保存的行为由父窗口进行。子窗口只是工具人,只需要发送相应消息给父窗口就行了。
1、定义自定义消息
// 父窗口.h
#define WM_TORTOISE (WM_USER + 1) // 自定义消息
2、在父窗口创建自定义消息处理函数,操作如步骤7
3、父窗口处理消息
// 自定義小海龜消息
afx_msg LRESULT CHappyWorkDlg::OnTortoise(WPARAM wParam, LPARAM lParam)
{
if (wParam == 0x11 && lParam == 0x12)
{
// 干活
}
return 0;
}
4、子窗口发送消息
不要用GetParent()->xxx,应该用如下操作:
// 获取主对话框
CHappyWorkDlg *main = (CHappyWorkDlg*)AfxGetMainWnd();
WPARAM a = (WPARAM)0x11;//子窗体的本身的实例指针
LPARAM b = (LPARAM)0x12; //一个int
::SendMessage(main->m_hWnd, WM_TORTOISE , a, b);
21、限制编辑框Edit的内容长度
在OnInitDialog函数中初始化
m_edit5.SetLimitText(256);
22、控件字体和背景颜色设置
转载于https://blog.csdn.net/qq_27092931/article/details/82844371?spm=1001.2014.3001.5502
通过MFC的类向导,添加WM_CTLCOLOR、WM_PAINT、WM_DRAWITEM消息,对应的函数分别如下:
1、控件颜色 HBRUSH CMain::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor)
可以设置编辑框、静态文本等的背景颜色,同时也可以设置文本颜色
HBRUSH CMain::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor)
{
HBRUSH hbr = CDialogEx::OnCtlColor(pDC, pWnd, nCtlColor);
if(pWnd->GetDlgCtrlID( ) == (IDC_STATIC)) //主界面
{
//pDC->SetBkMode(TRANSPARENT);
pDC->SetTextColor(RGB(30,100,200)); //设置文本颜色
pDC->SetBkColor(RGB(200,230,255)); //字体背景色
return HBRUSH(GetStockObject(HOLLOW_BRUSH));
}
return hbr;
}
2、背景颜色 void CMain::OnPaint()
void CMain::OnPaint()
{
CRect rect;
CPaintDC dc(this);
GetClientRect(rect);
dc.FillSolidRect(rect,RGB(200,230,255)); //设置背景颜色
}
3、按钮颜色 void CMain::OnDrawItem(int nIDCtl, LPDRAWITEMSTRUCT lpDrawItemStruct)
按钮属性需要改为Owner Draw,这种方法只能实现很简陋的按键立体效果和颜色的更改,同时也可以更改按钮字体的颜色
void CMain::OnDrawItem(int nIDCtl, LPDRAWITEMSTRUCT lpDrawItemStruct)
{
CDC dc;
dc.Attach(lpDrawItemStruct->hDC);//得到绘制的设备环境CDC
ASSERT(lpDrawItemStruct->CtlType == ODT_BUTTON);
CString strText;
((CButton *)GetDlgItem(nIDCtl))->GetWindowText(strText);
SetBkMode(lpDrawItemStruct->hDC, TRANSPARENT);//透明
if(nIDCtl==IDC_Main_FFGL)
{
if(GetDlgItem(IDC_Main_FFGL)->IsWindowEnabled()) //当按钮不操作 & 按钮可用
{
CBrush brush(RGB(30, 200, 255)); //内背景画刷
CPen m_BoundryPen(0,2,RGB(80,80,80)); //边框画笔
CBrush m_BackgroundBrush=RGB(140,200,255); //大背景画刷
dc.FillRect(&(lpDrawItemStruct->rcItem), &m_BackgroundBrush);//利用画刷brush,填充大矩形框
CRect rect = lpDrawItemStruct->rcItem;
CDC *pDC=CDC::FromHandle(lpDrawItemStruct->hDC);
POINT pt;
//画按钮的外边框,它是一个半径为10的圆角矩形
pt.x = 10;
pt.y = 10;
CPen* hOldPen = pDC->SelectObject(&m_BoundryPen);
pDC->RoundRect(&rect, pt);
pDC->SelectObject(hOldPen);
rect.DeflateRect(3, 3, 3, 3); //缩进
CBrush *pOldBrush = pDC->SelectObject(&m_BackgroundBrush);
pDC->Rectangle(rect); //画矩形
pDC->SelectObject(pOldBrush);
pDC->FillRect(rect,&brush ); //填充内矩形
//因为这里进行了重绘,所以文字也要重绘
DrawText(lpDrawItemStruct->hDC, strText, strText.GetLength(),&lpDrawItemStruct->rcItem, DT_SINGLELINE | DT_VCENTER | DT_CENTER);
}
if(lpDrawItemStruct->itemState&ODS_SELECTED & GetDlgItem(IDC_Main_FFGL)->IsWindowEnabled()) //如果按钮可用 & 点击
{
CBrush brush(RGB(0, 160, 230)); //内背景画刷
CPen m_BoundryPen(0,1,RGB(80,80,80)); //边框画笔
CBrush m_BackgroundBrush=RGB(140,200,255); //大背景画刷
dc.FillRect(&(lpDrawItemStruct->rcItem), &m_BackgroundBrush);//利用画刷brush,填充矩形框
CRect rect = lpDrawItemStruct->rcItem;
CDC *pDC=CDC::FromHandle(lpDrawItemStruct->hDC);
POINT pt;
//画按钮的外边框,它是一个半径为5的圆角矩形
pt.x = 10;
pt.y = 10;
CPen* hOldPen = pDC->SelectObject(&m_BoundryPen);
pDC->RoundRect(&rect, pt);
pDC->SelectObject(hOldPen);
rect.DeflateRect(4, 4, 3, 3);
CBrush *pOldBrush = pDC->SelectObject(&m_BackgroundBrush);
pDC->Rectangle(rect);
pDC->SelectObject(pOldBrush);
pDC->FillRect(rect,&brush );
//因为这里进行了重绘,所以文字也要重绘
DrawText(lpDrawItemStruct->hDC, strText, strText.GetLength(),&lpDrawItemStruct->rcItem, DT_SINGLELINE | DT_VCENTER | DT_CENTER);
}
if(!GetDlgItem(IDC_Main_FFGL)->IsWindowEnabled()) //不可用,显示灰色
{
CBrush brush(RGB( 190, 190, 200)); //内背景画刷
CPen m_BoundryPen(0,2,RGB(80,80,80)); //边框画笔
CBrush m_BackgroundBrush=RGB(140,200,255); //大背景画刷
dc.FillRect(&(lpDrawItemStruct->rcItem), &m_BackgroundBrush);//利用画刷brush,填充矩形框
CRect rect = lpDrawItemStruct->rcItem;
CDC *pDC=CDC::FromHandle(lpDrawItemStruct->hDC);
POINT pt;
//画按钮的外边框,它是一个半径为5的圆角矩形
pt.x = 10;
pt.y = 10;
CPen* hOldPen = pDC->SelectObject(&m_BoundryPen);
pDC->RoundRect(&rect, pt);
pDC->SelectObject(hOldPen);
rect.DeflateRect(3, 3, 3, 3);
CBrush *pOldBrush = pDC->SelectObject(&m_BackgroundBrush);
pDC->Rectangle(rect);
pDC->SelectObject(pOldBrush);
pDC->FillRect(rect,&brush );
//因为这里进行了重绘,所以文字也要重绘
pDC->SetTextColor(RGB(255,255,255)); //设置文本颜色
DrawText(lpDrawItemStruct->hDC, strText, strText.GetLength(),&lpDrawItemStruct->rcItem, DT_SINGLELINE | DT_VCENTER | DT_CENTER);
}
dc.Detach();
}
}
23、响应F1帮助
在类向导重写虚函数WinHelp。
// 虚函数F1帮助响应
void CHappyWorkDlg::WinHelp(DWORD dwData, UINT nCmd)
{
// TODO: 在此添加专用代码和/或调用基类
m_WindborneSpeed.OnBnClickedButton5();
// CDialogEx::WinHelp(dwData, nCmd);
}
24、组合框
绑定CComboBox类型变量,处理如下。
// 初始化列表选项
m_com.AddString(L"Bouday");
m_com.AddString(L"Aouday");
m_com.AddString(L"Zouday");
添加列表消息响应函数
// 操作列表字符 msg
void CMFC6组合框Dlg::OnCbnSelchangeCombo1()
{
// TODO: 在此添加控件通知处理程序代码
CString msg;
m_com.GetLBText(m_com.GetCurSel(), msg);//把文本内容给字符串
AfxMessageBox(msg);
}
25、调试时程序能运行,但随即会崩溃
往往是刷新的控件不存在,或者绑定的控件ID错误
26、响应拖拽
首先把当前窗口设置未接受拖拽文件,之后再类向导消息中点击WM_DROPFILES生成响应函数。
// 响应拖拽
void AutoRun::OnDropFiles(HDROP hDropInfo)
{
// TODO: 在此添加消息处理程序代码和/或调用默认值
TCHAR szStr[MAX_PATH] = {};
::DragQueryFile(hDropInfo, 0, szStr, MAX_PATH);
m_ExePath = szStr;
UpdateData(FALSE);
CDialogEx::OnDropFiles(hDropInfo);
}
27、打开文件
// 打开按钮
void AutoRun::OnOpenFileButton()
{
// TODO: 在此添加控件通知处理程序代码
CFileDialog dlg(TRUE, //TRUE为OPEN对话框,FALSE为SAVE AS对话框
NULL,
NULL,
OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT,
(LPCTSTR)_TEXT("exeFile (*.exe)|*.exe|all file(*.*)|*.*||"),
NULL);
if (dlg.DoModal() == IDOK)
{
// 打开成功,保存文件路径
m_ExePath = dlg.GetPathName();
}
else
{
m_ExePath = _T("打开文件失败!");
}
UpdateData(FALSE);
}
28、单选框
单选框在有多个的时候,绑定的值类型改为int
29、多字节和宽之间之间的转换
(1)A2W的用法:char* ——> WCHAR*
USES_CONVERSION;
CString cstring;
char* achar = "qwer";
const WCHAR* wchar = A2W(achar);
cstring = wchar;
(2)W2A的用法:WCHAR*——> char*
USES_CONVERSION; CString cstring;
WCHAR* wchar = _T("qwer");
const char* achar = W2A(wchar);
cstring = wchar;
// 更高级骚操作
CString strW;
CStringA strA;
strW = strA;
30、显示隐藏,使不使能控件
edit->ShowWindow(FALSE); //隐藏该控件
edit->ShowWindow(TRUE)://显示该控件
edit->EnableWindow(FALSE);//控件不可用,其颜色变成灰色
edit->EnableWindow(TRUE); //控件可用,其颜色正常
30、按钮实现打开组合框下拉列表
//m_cbIP.ShowWindow(TRUE);
//m_cbIP.ShowWindow(FALSE);
// 组合无论是否被隐藏都会显示下拉列表
m_cbIP.ShowDropDown();
31、遍历队列
int nSize = num.size();
for (int i = 0; i < nSize; i++)
{
printf("%d ", num.front());
num.push(num.front());
num.pop();
}
32、遍历文件
windows遍历文件一般都是用递归,今天我写工具对公司的项目(10多个G)进行文件遍历,因为我之前写过好几次递归遍历,轻车熟路,怀着快乐的心情写完代码正想自己在自己面前装逼的时候结果特么的直接把硬盘搞挂了,早就知道递归害人,我居然还用递归,傻叉了。最后研究出用层序遍历算法遍历文件,才得以搞定。
递归遍历算法如下:
// 遍历文件信息,遍历的文件不多用这个
void WindborneSpeed::EnumFileInfo(CString Path)
{
WIN32_FIND_DATA fileInfo = {};
// 查找第一个文件
HANDLE hFile = ::FindFirstFile(Path + L"\\*", &fileInfo);
// 遍历文件夹内的所有文件
if (hFile != INVALID_HANDLE_VALUE)
{
do
{
// 若是文件夹则递归
if (fileInfo.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
{
// 排除当前目录和上层目录
if (fileInfo.cFileName != CString(".") && fileInfo.cFileName != CString(".."))
{
EnumFileInfo(Path + L"\\" + fileInfo.cFileName);
}
}
else // 是文件时
{
// 操作要操作的
}
} while (FindNextFile(hFile, &fileInfo));
::FindClose(hFile);
}
}
层序遍历算法如下:
// 遍历文件信息,公司项目文件太他妈多了,不能用递归,爷爷被递归坑了半小时,研究出循环算法
void WindborneSpeed::EnumFileInfo(CString Path)
{
std::vector<CString> vecCurrent = { Path };
std::vector<CString> vecNext = {};
while (!vecCurrent.empty()) {
for (size_t i = 0; i < vecCurrent.size(); ++i) {
WIN32_FIND_DATA fileInfo = {};
// 查找第一个文件
HANDLE hFile = ::FindFirstFile(vecCurrent[i] + L"\\*", &fileInfo);
CString tempName;
// 遍历文件夹内的所有文件
if (hFile != INVALID_HANDLE_VALUE)
{
do
{
// 若是文件夹则装入下一层目录容器
if (fileInfo.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
{
tempName = fileInfo.cFileName;
if (-1 != tempName.Find(L"."))
continue;
else
vecNext.push_back(vecCurrent[i] + L"\\" + fileInfo.cFileName);
}
else // 是文件时
{
// 操作要操作的
}
} while (FindNextFile(hFile, &fileInfo));
::FindClose(hFile);
}
}
vecCurrent = vecNext;
vecNext.clear();
}
}
32、UAC管理员权限运行(图标带盾牌)
在vs 属性里面设置,可以自己选择