一 .全屏
void CXXXDlg::SetFullScreen()
{
int frameWidth = GetSystemMetrics(SM_CXFRAME);
int frameHeight = GetSystemMetrics(SM_CYFRAME);
int captionHeight = GetSystemMetrics(SM_CYCAPTION);
int screenWidth = GetSystemMetrics(SM_CXSCREEN);
int screenHeight = GetSystemMetrics(SM_CYSCREEN);
CRect rect;
GetClientRect(&rect);
rect.left = rect.left - frameWidth;
rect.top = rect.top - frameHeight - captionHeight ;
rect.bottom = rect.top + screenHeight + 2 * frameHeight + captionHeight;
rect.right = rect.left + screenWidth + 2 * frameWidth;
ShowWindow(SW_HIDE);
SetWindowPos(&wndTopMost, rect.left, rect.top, rect.Width(), rect.Height(), SWP_SHOWWINDOW);
}
2.取消全屏
void CMainFrame::EndFullScreen()
{
if (m_bFullScreen)
{
// 退出全屏显示,恢复原始窗口显示
ShowWindow(SW_HIDE);
SetWindowPlacement(&m_OldWndPlacement);
}
}
// 添加WM_KEYDOWN消息相应函数
void CFullScreenTestView::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags)
{
// TODO: Add your message handler code here and/or call default
if (nChar == VK_ESCAPE) // 如果按下的是Esc键
{
// 获取主窗口指针
CMainFrame* pFrame = (CMainFrame*) AfxGetApp()->m_pMainWnd;
// 调用主窗口类的自定义函数EndFullScreen(),便可以退出全屏显示模式
pFrame->EndFullScreen();
}
CView::OnKeyDown(nChar, nRepCnt, nFlags);
}
二 双击事件响应问题
在MFC的窗口程序中,双击事件会首先由单击事件消息处理函数来响应,而不会跳到双击事件处理函数中。如果要响应双击事件可以在单击消息处理函数中对间隔时间做判断。也可以设置style为 CS_DBLCLKS
void CClickOrDBDlg::OnLButtonDown(UINT nFlags, CPoint point)
{
// TODO: Add your message handler code here and/or call default
// AfxMessageBox("one");
MSG message;
DWORD st = GetTickCount();
while(1)
{
if(::PeekMessage(&message, NULL, 0 ,0 , PM_REMOVE))
{
::TranslateMessage(&message);
::DispatchMessage(&message);
if(message.message == WM_LBUTTONDBLCLK)
{
AfxMessageBox("two");
break;
}
}
DWORD et = GetTickCount();
if(et - st > 200)
{
AfxMessageBox("one");
break;
}
}
CDialog::OnLButtonDown(nFlags, point);
}
三 WinPE4.0 中MFC窗口程序不能执行
用vc2010编译的MFC窗口程序在在win8上可以正确执行,在WinPE4.0上通过powershell 调用时没反应,不报错也没有界面。原因是使用了动态编译,程序需要很多动态链接档支持,而预加载系统中没有这些DLL.(我试着装了.NET SDK还是不行)解决办法是使用静态编译方法。这样编译出来的程序会很大,动态编译93k ,静态编译2390k ,确实包进去很多东西呢。
编译设置:
四 界面在哪儿?
MFC分为三种,单文档、多文档、基于对话框,文档是没有界面的。 从视图 -》 资源视图 -》 dialogue 中打开界面 。(找界面找了半天,新手就是很菜)
五 button操作
1 .外观
与VC6.0不同,VC2012中控件有属性窗口,可以在属性窗口中修改Caption | ID | 外观 等信息。也可以添加事件响应函数。
2 .动态改变button的大小
void CAboutDlg::OnButton1()
{
CRect myRect;
GetClientRect(&myRect); //取得客户区的大小 ,窗口左上角总是0,0
ClientToScreen(myRect); //转换为屏幕坐标 ,屏幕左上角是0,0
MoveWindow(myRect.left, myRect.top, myRect.Width(), myRect.Height()); //MoveWindow使用的是屏幕坐标
GetDlgItem(IDC_BUTTON1)->SetWindowPos(NULL,my rect.left,myrect.top,myrect.Width(),myrect.Height(),SWP_SHOWWINDOW); // 改button的大小
}
3 . 类向导
当然事件响应函数也可以在 项目 -》类向导(mfc class wizard)中设置或删除
六 设置配置信息
1 行号 : 工具 -》 选项 -》文本编辑器 -》选一种语言 -》勾行号
2 字体: 工具 -》 选项 -》 环境 -》 字体和颜色
七 添加源文件或头文件
右击解决方案 -》添加 -》 新建项 | 现有项
八 常见错误或禁告
1 <iostream.h>
如果include这个头文件就会报错,因为在2012中已经替换成了<iostream>
2 安全字符串处理函数
如果程序中使用了strcpy这样的CTL库函数,编译会报禁告。因为strcpy对源数据大小没有做判断很容易导致内存溢出。microsoft新建了对应的函数strcpy_s取代C++的CTL库,这些函数在Strsafe.h中
3 字符处理
“ 无法将参数2从 const char * 转换为 LPCWSTR ” 的错误 , 使用TEXT 或 _T来转换常量
MessageBox( NULL, "HelloWorld", "Information", 0 );
//
MessageBox( NULL, TEXT("HelloWorld!"), TEXT("Information"), 0 );
MessageBox( NULL, _T("HelloWorld!"), _T("Information"), 0 );
VC2012中默认使用UNICODE字符集,所以ANSI字符就要转换成UNICODE才能被处理。两者不可以强制转换更不能默认转换,而需要使用函数 WidCharToMultiByte() 和MultiByteToWidChar() .使用时注意要先获得目标缓冲区大小然后再转换。
char* TcharToChar (const TCHAR * tchar)
{
int iLength ;
char * _char;
//获取字节长度
iLength = WideCharToMultiByte(CP_ACP, 0, tchar, -1, NULL, 0, NULL, NULL);
//将tchar值赋给_char
WideCharToMultiByte(CP_ACP, 0, tchar, -1, _char, iLength, NULL, NULL);
return _char;
}
有些函数会分别提供 ANSI 和 UNICODE 版本然后通过预编译命令对应到一起,比如Tchar.h中的一段:
#ifdef _UNICODE
#define _tcslen wcslen
#else
#define _tcslen strlen
#endif
4 多重定义错误
将函数声明成 static 函数 ,这样就只能在本文件中使用。
用 #pragma once 告诉编译器只编译一次
用#ifdef #enddef 把头文件包起来
九 调试
1 $err,hr
使用$err,hr 可以查看错误信息,相当于调用GetLastError()的结果。调试状态下,在监视1窗口输入$err,hr就可以了
2 可以在监视窗口中查看变量 也可以修改变量值 。甚至对指针变量做强制类型转换 。
3 查看堆栈
调试 -》 窗口 -》 调用堆栈 (alt + 7)
4 模块
调试 -》窗口 -》模块 ,这个窗口中可以看到程序调用了哪些DLL及DLL的信息
5 release debug
只有在debug模式下才能看到变量的值,在release模式下监视窗口显示“错误的指针” 。
十 读写INI文件
在VC程序中利用系统提供的 GetPrivateProfileString 及 WritePrivateProfileString函数直接读写系统配置ini文件(指定目录下的Ini文件)
假设在当前目录下有一个文件名为Test.ini的文件
[Section1]
Item1=huzhifeng
Item2=1234565
1.写INI文件
void CINI_File_TestDlg::OnButtonWrite()
{
// TODO: Add your control notification handler code here
CString strSection = "Section1";
CString strSectionKey = "Item1";
char strBuff[256];
CString strValue = _T("");
CString strFilePath;
strFilePath=GetCurrentDirectory(256,strBuff); //获取当前路径
strFilePath.Format("%s//Test.ini",strBuff);
GetDlgItemText(IDC_EDIT_NAME,strValue); //获取文本框内容:即姓名
WritePrivateProfileString(strSection,strSectionKey,strValue,strFilePath); //写入ini文件中相应字段
strSectionKey="Item2";
GetDlgItemText(IDC_EDIT_PASSWORD,strValue); //获取文本框内容:即密码
WritePrivateProfileString(strSection,strSectionKey,strValue,strFilePath);
}
2.读INI文件内容
void CINI_File_TestDlg::OnButtonRead()
{
// TODO: Add your control notification handler code here
CString strSection = "Section1";
CString strSectionKey = "Item1";
char strBuff[256];
CString strValue = _T("");
CString strFilePath;
strFilePath=GetCurrentDirectory(256,strBuff); //获取当前路径
strFilePath.Format("%s//Test.ini",strBuff);
GetPrivateProfileString(strSection,strSectionKey,NULL,strBuff,sizeof(strBuff),strFilePath); //读取ini文件中相应字段的内容
strValue=strBuff;
SetDlgItemText(IDC_EDIT_NAME,strValue);
strSectionKey="Item2";
GetPrivateProfileString(strSection,strSectionKey,NULL,strBuff,80,strFilePath);
strValue=strBuff;
SetDlgItemText(IDC_EDIT_PASSWORD,strValue);
UpdateData(FALSE);
}
CString WebEnable ;
WebEnable.GetBufferSetLength(10);
GetPrivateProfileString("GetExtraBarcode","WebEnable",NULL,WebEnable.GetBuffer(10),10,".\\WebConfig.ini");
WebEnable.ReleaseBuffer();
十一 MFC中关闭窗口的几种办法:
退出程序用AfxGetMainWnd()->SendMessage(WM_CLOSE);
关闭当前窗口用DestroyWindow( );
关闭模式对话框用EndDialog(0);
十一 文本文件 & 文件夹
1文件是否存在
CFileStatus filestatus;
if (CFile::GetStatus(_T("d://softist.txt"), filestatus))
AfxMessageBox(_T("文件存在"));
else
AfxMessageBox(_T("文件不存在"));
2读 写:
CStdioFile hLogFile ;
CString strBarcodeBar;
hLogFile.SeekToBegin();
hLogFile.WriteString( m_strBarcodeUI);
hLogFile.ReadString(strBarcodeBar);
hLogFile.Close();
CFile hFile;
//用CFile读xml文件是会师乱码?why?
3 删除文件:
第一种方法:定义一个文件类对象来操作
CFile TempFile;
TempFile.Remove(指定文件名);
第二种方法:
DeleteFile("c:\\abc\\test.exe ");//MFC框架中可直接调用此函数
第三种方法:system("del c:\\abc\\test.txt");
4 删除目录
_rmdir()
DeleteDirectory(sTempDir)
RemoveDirectory(sTempDir)
5 删除文件夹目录(非空)
bool DeleteDirectory( CString DirName)
{
AfxMessageBox("执行删除文件夹:"+DirName);
CString PUBPATH;
PUBPATH=DirName;
CFileFind tempFind;
DirName+="\\*.*";
BOOL IsFinded=(BOOL)tempFind.FindFile(DirName);
while(IsFinded)
{
IsFinded=(BOOL)tempFind.FindNextFile();
if(!tempFind.IsDots())
{
CString strDirName;
strDirName+=PUBPATH;
strDirName+="\\";
strDirName+=tempFind.GetFileName();
AfxMessageBox("strDirName :"+strDirName);
if(tempFind.IsDirectory())
{
//strDirName += PUBPATH;
DeleteDirectory(strDirName);
}
else
{
SetFileAttributes(strDirName,FILE_ATTRIBUTE_NORMAL); //去掉文件的系统和隐藏属性
DeleteFile(strDirName);
}
}
}
tempFind.Close();
if(!RemoveDirectory(PUBPATH))
{
return false ;
}
AfxMessageBox("文件夹删除成功...");
return true;
}
十二 字符处理
m_IniFileValue.PassSNDir.AppendFormat(_T("\\%s.txt "),m_strBarcodeUI); //字符组合在一起
m_IniFileValue.PassSNDir.Format(TEXT("%s not exist"),m_IniFileValue.PassSNDir); //字符赋值
if(-1 != strMES.Find(_T("5"),0) //从0的位置开始查找字符5 ,找不到返回-1 找到 返回index
m_IniFileValue.PassSNDir.AppendFormat(_T("\\%s.txt "),m_strBarcodeUI)
m_IniFileValue.PassSNDir.Mid(m_IniFileValue.PassSNDir.Find("Next"), m_IniFileValue.PassSNDir.FindOneOf(":") - m_IniFileValue.PassSNDir.Find("Next"));
console 输出UNICODE 字符
如果用cout输出unicode 你会看到一串十六进制数。所以,如果你的编译器设置使用unicode的话,必须用wcout来输出
wcout<<TEXT("output unicode string")<<endl;
CString strOuput;
wcout<<strOuput.GetBuffer(strOuput.GetLength());
十三 退出程序
if (MessageBox("Are you sure exit G-Sensor?","Tips",MB_YESNO|MB_DEFBUTTON2)==IDYES)
{
PostQuitMessage(0);
}
十四 隐藏对话框
定义一个bool变量visible,在构造函数中初始化为false
void CGDIButtonTestDlg::OnWindowPosChanging(WINDOWPOS FAR* lpwndpos)
{
//if (lpwndpos->flags & SWP_SHOWWINDOW)
if(!visible)
{
lpwndpos->flags &= ~SWP_SHOWWINDOW;
PostMessage(WM_WINDOWPOSCHANGING, 0, (LPARAM)lpwndpos);
ShowWindow(SW_HIDE);
}
else
{ CDialog::OnWindowPosChanging(lpwndpos);}
}
在想正常显示的地方visible=true,ShowWindow(SW_SHOW); 即能正常显示。
想正常隐藏,既visible=false,ShowWindow(SW_HIDE);
十五 添加对话框背景图片
响应OnEraseBkgnd消息,然后在这个消息函数里面显示图片! 应该是在APP里加
BOOL CxxDlg::OnEraseBkgnd(CDC* pDC)
{
BITMAP bm;
m_bmp.GetBitmap(&bm);
m_pbmCurrent = &m_bmp;
CDC dcMem;
dcMem.CreateCompatibleDC(pDC);
CBitmap* pOldBitmap = dcMem.SelectObject(m_pbmCurrent);
pDC->BitBlt(0,0,bm.bmWidth,bm.bmHeight,&dcMem,0,0,SRCCOPY);
dcMem.SelectObject(pOldBitmap);
}
十六 创建非模态对话框
CSplashDlg *pSplashDlg = new CSplashDlg();
pSplashDlg->Create(IDD_SPLASH_DIALOG);
pSplashDlg->ShowWindow(SW_SHOW);
pSplashDlg->UpdateWindow();
十七 获取屏幕大小
获取屏幕大小
int with= GetSystemMetrics(SM_CXFULLSCREEN);
int heigh= GetSystemMetrics(SM_CYFULLSCREEN);
通过上边两个函数获取的是显示屏幕的大小,及不包括任务栏等区域。
int cx = GetSystemMetrics( SM_CXSCREEN );
int cy = GetSystemMetrics( SM_CYSCREEN );
这两个函数获取的是真正屏幕的大小。
十八 对话框支持拖动
添加WM_NCHITTEST 消息事件
UINT CMyAgentDlg::OnNcHitTest(CPoint point)
{
// TODO: Add your message handler code here and/or call default
UINT nHitTest=CDialog::OnNcHitTest(point);
return (nHitTest==HTCLIENT)?HTCAPTION:nHitTest;
//return CDialog::OnNcHitTest(point);
}
十九 一个类访问控制另一个类中的变量控件
如果要在类CVDlg 访问控制类CPPDlg中的控件 CSliderCtrl。
首先在类CPPDlg中定义 CSliderCtrl m_sld;
然后在类CVDlg 中定义
CSliderCtrl* m_pSld;
CPPDlg* m_pDlg;
然后在类CVDlg的构造函数中定义:
m_pDlg=new CPPDlg;
m_pDlg->Create(IDD_PP);
m_pSld=&m_pDlg->m_sld;
这样就可以在类CVDlg中任何地方控制类CPPDlg中的控件 CSliderCtrl。
变量,控件都是这么做的。比较正宗的一种方式。
二十 全局函数访问对话框中的控件
CGloabkjDlg *pDlg = (CGloabkjDlg *)(AfxGetApp()->GetMainWnd());
二十一 格盘代码
char *FormatW2K = "CMD.EXE";
//这里我用H:盘,你自己要填入你想格式化的盘
char *FormatW2KParam = "/C \"format.com H:/force/q/u/x/V:MISC\"";
//在后台执行格式化命令
ShellExecute(NULL,"open",FormatW2K,FormatW2KParam,NULL,SW_HIDE);
二十二 系统下关机代码:
TOKEN_PRIVILEGES tp;
HANDLE hToken;
LUID luid;
LPTSTR MachineName=NULL;
if(!OpenProcessToken(GetCurrentProcess(),TOKEN_ADJUST_PRIVILEGES,&hToken ))
{
// PERR("OpenProcessToken",GetLastError());
return ;
}
if(!LookupPrivilegeValue(MachineName, SE_SHUTDOWN_NAME, &luid))
{
// PERR("LookupPrivilegeValue", GetLastError());
return ;
}
tp.PrivilegeCount = 1;
tp.Privileges[0].Luid = luid;
tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
AdjustTokenPrivileges(hToken,FALSE,&tp,sizeof(TOKEN_PRIVILEGES),NULL, NULL ); //到这里,是取得权限///
ExitWindowsEx(EWX_REBOOT,EWX_FORCE);
1.添加成员变量 CToolBar m_WndToolBar
2.在OnInitDialog() 中 CDialog::OnInitDialog();后添加
if (!m_WndToolBar.CreateEx(this, TBSTYLE_FLAT,WS_CHILD|WS_VISIBLE|CBRS_ALIGN_TOP|CBRS_GRIPPER|CBRS_TOOLTIPS,CRect(4,4,0,0))||!m_WndToolBar.LoadToolBar(IDR_TOOLBAR1))
{
TRACE0("未能创建工具栏\n");
return -1;
}
m_WndToolBar.ShowWindow(SW_SHOW);
RepositionBars(AFX_IDW_CONTROLBAR_FIRST,AFX_IDW_CONTROLBAR_LAST,0);
二十四