MFC进行界面设计与编程
来源:互联网 发布:单片机pc地址 编辑:程序博客网 时间:2024/06/14 10:21
总体思路
由UI设计界面背景图片、相关按钮图片等,然后在代码中创建关联控件变量。对于无需变化的背景、按钮,可以不设控件变量关联。一般有以下几个步骤:
1.UI设计界面;
2.创建需要变动的控件变量与之关联,并设置透明;
3.加载图片;
4.创建控件相应消息响应函数。
控件开发
系统控件
创建
CStatic ctrl_record_;CRect rt_record_(614, 196, 794, 376);//创建控件ID,后续可以根据此ID找到控件GetDlgItem(IDC_INPUT_ID)->Invalidate(TRUE)//pWnd->GetDlgCtrlID() == IDC_RECORD#define IDC_RECORD 0x10001//SS_NOTIFY--能够接收消息ctrl_record_.Create(NULL, WS_CHILD | SS_CENTER | SS_CENTERIMAGE | WS_VISIBLE | SS_NOTIFY , rt_record_, this, IDC_RECORD);
透明&消息响应
//定义消息响应函数afx_msg HBRUSH OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor);//消息映射BEGIN_MESSAGE_MAP(CRiskEstimateDemoDlg, CDialogEx) ON_WM_CTLCOLOR() ON_STN_CLICKED(IDC_RECORD, &CRiskEstimateDemoDlg::OnRecordClicked)END_MESSAGE_MAP()//设置控件透明HBRUSH CRiskEstimateDemoDlg::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor){ HBRUSH hbr = CDialogEx::OnCtlColor(pDC, pWnd, nCtlColor); // TODO: 在此更改 DC 的任何特性 CFont font; // TODO: 如果默认的不是所需画笔,则返回另一个画笔 if (nCtlColor == CTLCOLOR_STATIC) { if (pWnd->GetDlgCtrlID() == IDC_DISPLAY_FACE || pWnd->GetDlgCtrlID() == IDC_RECORD ) { font.CreatePointFont(150, _T("Microsoft YaHei")); pDC->SelectObject(&font); pDC->SetBkMode(TRANSPARENT); //透明 pDC->SetTextColor(0xffffff); return (HBRUSH)GetStockObject(NULL_BRUSH); } } return hbr;}
图片加载
//resource.h#define IDB_PNG_BACKGROUND 110//*.rcIDB_PNG_BACKGROUND PNG "res\\bg.png"//加载各个控件图片,拖动会重刷BOOL CRiskEstimateDemoDlg::OnEraseBkgnd(CDC* pDC){ CDC *pDc = GetDC(); //加载背景图 LoadImageForCtrl(pDc, IDB_PNG_BACKGROUND, rt_background_.left, rt_background_.top); if (pDc) ReleaseDC(pDc); return TRUE;}
自定义继承控件
自定义控件可以解决频繁刷新整个界面闪烁的问题.
class CMyStatic : public CStatic{ DECLARE_DYNAMIC(CMyStatic)public: CMyStatic(); virtual ~CMyStatic(); virtual CMyStatic& SetText(const CString& strText); virtual CMyStatic& SetMyFont(int nSize,const CString& strFont); virtual CMyStatic& SetTextColor(COLORREF crText);protected: afx_msg LRESULT OnSetText(WPARAM,LPARAM); afx_msg HBRUSH CtlColor(CDC* /*pDC*/, UINT /*nCtlColor*/); afx_msg BOOL OnEraseBkgnd(CDC* pDC); DECLARE_MESSAGE_MAP()public: void SetImage(UINT id);private: BOOL GetImageById(CImage *pImage, UINT nResID, LPCTSTR lpTyp); BOOL GetImageInfo(CImage *pImage, UINT nResID, LPCTSTR lpTyp); void SetByteForImage(CImage &image); void Update();private: CBitmap bitmap_; CFont font_; COLORREF text_color_; BOOL bitmap_used_; static image_id_ stat_image_[IMAGE_NUM];};
ListBox 具有 LBS_OWNERDRAW 样式是没有文字的,除非再添加 LBS_HASSTRINGS 样式,并处理 WM_DRAWITEM 去绘制文字,否则肯定不会显示文字。
参考:让ListBox控件每一行显示不同的颜色为MFC中的ListBox添加水平滚动条
参考:为MFC中的ListBox添加水平滚动条
双缓冲区解决闪烁
//加载各个控件图片,拖动会重刷BOOL CRiskEstimateDemoDlg::OnEraseBkgnd(CDC* pDC){ // TODO: 在此添加消息处理程序代码和/或调用默认值 CDC *pDc = GetDC(); if (pDc == NULL){ return FALSE; } CDC memDC; //首先定义一个显示设备对象 CBitmap memBitMap;//定义一个位图对象 CImage image; //背景图片用来定义位图大小 CBitmap *pOldBmp; int width = rt_background_.Width(); int height = rt_background_.Height(); memDC.CreateCompatibleDC(pDc); //ASSERT(memDC.CreateCompatibleDC(pDc) != NULL);//这时还不能绘图,因为没有地方画 //下面建立一个与屏幕显示兼容的位图,至于位图的大小嘛,可以用窗口的大小,也可以自己定义 memBitMap.CreateCompatibleBitmap(pDc, width, height); //ASSERT(memBitMap.CreateCompatibleBitmap(pDc, width, height) != NULL); pOldBmp = memDC.SelectObject(&memBitMap);//将位图选入到内存显示设备中 //只有选入了位图的内存显示设备才有地方绘图,画到指定的位图上 ASSERT(pOldBmp != NULL); if (pOldBmp == NULL){ return FALSE; } //memDC.FillSolidRect(0, 0, image.GetWidth(), image.GetHeight(), RGB(255, 255, 255)); //绘图 DrawCtrl(memDC); pDc->BitBlt(0, 0, width, height, &memDC, 0, 0, SRCCOPY); //绘图完成后的清理,把前面的pOldBit选回来.在删除MemBitmap之前要先从设备中移除它 memDC.SelectObject(pOldBmp); DeleteObject(&memDC); memBitMap.DeleteObject(); if (pDc) ReleaseDC(pDc); return TRUE;}
MFC调用Bat文件
if (flag_record_) { //system("e:\\Workspaces\\Git\\FKDemo\\FKDemo\\record.bat"); WinExec("record.bat 001.flv", SW_HIDE); } else { WinExec("kill.bat", SW_HIDE); }
record.bat
@echo offffmpeg -f dshow -rtbufsize 200M -i video="Logitech HD Webcam C310":audio="Âó¿Ë·ç (HD Webcam C310)" -pix_fmt yuv420p -ar 48000 -vcodec libx264 -crf 23 -preset veryslow -x264opts b-adapt=2:bframes=0:aq-strength=1:psy-rd=0.8,0 -vsync vfr -acodec aac -bsf:a aac_adtstoasc -f flv %1pauseexit
kill.bat
@echo offtaskkill /f /im ffmpeg.exe
常见知识点
cstring、string、lpwstr、lpstr、char*之间相互转换;
cstring 转换为 *
/* cstring 转 string */CString cs(_T("cs")); string s; s = (LPCSTR)(CStringA)(cs); /* CString转换成LPCWSTR、LPWSTR、LPCSTR、LPSTR *///VS2005中CString已经改为宽字符型LPWSTR lpstr = (LPWSTR)(LPCWSTR)str;LPCSTR lpcstr = (LPCSTR)(LPCWSTR)str;LPSTR lpcstr = (LPSTR)(LPCWSTR)str;/* CString转换成char* 、TCHAR* */ char* p = (char*)str.GetBuffer(); //方法1 char* p = (LPSTR)(LPCTSTR)str; //方法2 TCHAR* pw = str.GetBuffer();
string 转换为 *
/* string 转 cstring *///方法1string s ="Hello World!中国"; CString cs(s.c_str()); //方法2,用c_str()确实比data()要好.CString.format(”%s”, string.c_str());/* string 转 lpcstr */std::string a="abc";LPCSTR str = a.c_str();/* string转换为LPWSTR */wstring widstr; std:string s("DanTeng"); widstr = std::wstring(s.begin(), s.end()); lvItem.pszText=(LPWSTR)widstr.c_str(); /* string转换为int、float */ //可以使用atoi,atof,atol等函数来完成。
LPCWSTR 转换为 *
/* LPCWSTR转换成CString */LPCWSTR lpcwStr = L"TestWStr"; CString str(lpcwStr);
LPWSTR 转换为 *
/* LPWSTR 转换成LPWSTR */LPWSTR lpwstr = (LPCSTR)lpstr;lpwstr = (LPWSTR)lpcstr;
LPCSTR 转换为 *
/* LPCSTR 转换成CString */ LPCSTR lpcStr = (LPCSTR)str;/* LPWSTR 转换成LPWSTR */LPWSTR lpwstr = (LPCSTR)lpstr;
LPSTR 转换为 *
/* LPSTR 转换成CString */ LPSTR lpStr = L"TestStr"; CString str(lpStr);/* LPSTR 转换成LPCSTR、LPWSTR 、LPCWSTR */ LPCSTR lpcstr = lpstr; LPWSTR lpwstr = (LPWSTR)lpstr; LPCWSTR lpcwstr = (LPCWSTR)lpstr;
char* 转换为 *
/* char* 转换成CString */ //方法1char* p = "test";CString str = ("%s",p);//方法2CString.format(”%s”, char*);/* char* 转换成string*/ string s(char *); //只能初始化,在不是初始化的地方最好还是用assign()./* char* 转换成LPSTR、LPCSTR */ char *p; LPSTR lpstr = p; LPCSTR lpcstr = p;/* char* 转换成WCHAR */ wchar_t ws[100];swprintf(ws, 100, L"%hs", "ansi string");
/* char* 转换成LPCWSTR */
参考:C++中char*转换为LPCWSTR的解决方案
TCHAR * /WCHAR* 转换为 *
/* TCHAR* 转换成char* */p = (char*)sex;/* WCHAR* 转换成TCHAR* */pw = (WCHAR*)name;/* WCHAR* 转换成char* */char output[256];WCHAR* wc = L"Hellow World" ;sprintf(output, "%ws", wc );
文件夹操作
遍历文件1
BrowseCurrentAllFile(CString strDir){ if(strDir == _T("")){ return; } else { if(strDir.Right(1) != _T("//")) strDir += L"//"; strDir =strDir+_T("*.*"); } CFileFind finder; CString strPath; BOOL bWorking = finder.FindFile(strDir); while(bWorking) { bWorking = finder.FindNextFile(); strPath = finder.GetFilePath(); if(finder.IsDirectory() && !finder.IsDots()) BrowseCurrentAllFile(strPath); //递归调用 else if(!finder.IsDirectory() && !finder.IsDots()) { //strPaht就是所要获取的文件路径 } }}//调用方式:BrowseCurrentAllFile(_T("D://test"));
遍历文件2
BOOL ProcessImage(cv::Mat& image){ CString strDir(PLOT_DATA_IMG_PATH); strDir += "*.jpg"; CString fileFullName; CFileFind finder; BOOL bWorking = finder.FindFile(strDir); if (!bWorking) { return FALSE; } bWorking = finder.FindNextFile(); fileFullName = finder.GetFilePath(); string s; s = (LPCSTR)(CStringA)(fileFullName); image = cv::imread(s); DeleteFile(fileFullName); //删除文件 return TRUE;}
目标文件是否存在
#include <shlwapi.h>#pragma comment(lib,"Shlwapi.lib") //如果没有这行,会出现link错误 if (PathFileExists(strDBPath)) { //存在 } else CreateDirectory(html_path_out1, NULL); //文件夹不存在//Cstring.Replace('/','\\'); //将地址中的'/'替换为'\\'
浏览文件夹目录
// 设置过滤器 TCHAR szFilter[] = _T("启动文件(*.avi)|*.avi|所有文件(*.*)|*.*||"); // 构造打开文件对话框 CFileDialog fileDlg(TRUE, _T("exe"), NULL, 0, szFilter, this); if (IDOK == fileDlg.DoModal()) { CString str = fileDlg.GetPathName(); replay_video_path_ = (LPCSTR)(CStringA)(str); ctrl_list_msg_.AddString(str); } else { return; }
MFC接收命令行参数的三种方法
/* 方法一:将获取到 "C:\test\app.exe -1 -2" */CString sCmdline = ::GetCommandLine(); AfxMessageBox(sCmdline); /*方法二:将获取到 将依次得到"C:\test\app.exe","-1", "-2"*/char buff[128] = { 0 }for (int i = 0; i < __argc; i++) { sprintf_s(buff, 128, "%ws", __targv[6]); g_Config.kBusinessEnd = atoi(buff)} /*方法三:将获取到 将获取到 "-1 -2 ",AfxGetApp()->m_lpCmdLine 只包含参数*/CString sCmdline = AfxGetApp()->m_lpCmdLine;
DEBUG模式测试如何设置:
菜单的: 项目->属性->配置属性->调试->命令行参数
命令行参数里可以直接写你的参数,例如在命令行是:test.exe per1 per2 , 这样在这里就直接写:per1 per2
MFC获取时间的几种方法
参考:MFC获取时间的几种方法
MFC 屏蔽ESC和ENTER键关闭对话框
VC MFC 屏蔽ESC和ENTER键关闭对话框
方法一:窗体头文件中加入:1 protected:2 virtual BOOL PreTranslateMessage(MSG* pMsg); // PreTranslateMessage是消息在送给TranslateMessage函数之前被调用的3 public:4 virtual void OnOK();在CPP中加入:复制代码 1 BOOL CColorDlgDlg::PreTranslateMessage(MSG* pMsg) 2 { 3 //屏蔽ESC关闭窗体/ 4 if(pMsg->message==WM_KEYDOWN && pMsg->wParam==VK_ESCAPE ) return TRUE; 5 //屏蔽回车关闭窗体,但会导致回车在窗体上失效. 6 //if(pMsg->message==WM_KEYDOWN && pMsg->wParam==VK_RETURN && pMsg->wParam) return TRUE; 7 else 8 return CDialog::PreTranslateMessage(pMsg); 9 }10 void CColorDlgDlg::OnOK()11 {12 //CDialogEx::OnOK();13 }复制代码方法二:窗体头文件中加入:public: virtual void OnOK(); virtual void OnCancel(); afx_msg void OnClose(); //响应关闭事件!在CPP中加入:复制代码void CFirstFZDlg::OnOK(){ return;}void CFirstFZDlg::OnCancel(){ return;}void CFirstFZDlg::OnClose(){ // TODO: 在此添加消息处理程序代码和/或调用默认值 CDialogEx::OnCancel(); //CDialogEx::OnClose();}复制代码MSG 结构体定义如下:typedef struct tagMSG { // msg HWND hwnd; // 窗口句柄 UINT message; // 消息 WPARAM wParam; // 消息附加信息,根据消息而定 LPARAM lParam; // 消息附加信息,根据消息而定 DWORD time; // 消息发送时间 POINT pt; // 消息发送时指针的位置(屏幕坐标)} MSG;
完全退出线程
UINT thread_testexit( PVOID pParam ) { while( g_bExtiThread ) { Sleep(1000); static int i = 0; CString str;str.Format( L"%d",i++); //AfxGetApp()->GetMainWnd()->SetWindowText( str ); } return 0; } void Ctmfc1Dlg::OnBnClickedButton1() { // TODO: 在此添加控件通知处理程序代码 pWinThreadtestexit = AfxBeginThread( thread_testexit, 0 ); } void Ctmfc1Dlg::OnBnClickedButton2() { // TODO: 在此添加控件通知处理程序代码 g_bExtiThread = 0; WaitForSingleObject( pWinThreadtestexit->m_hThread, INFINITE ); SetWindowText( L"线程已经停止" ); }
参考:MFC 线程的退出方法
常见错误
Error Cxxx
1.Error C1003: error count exceeds 100
A:在自定义源文件中要加入#include “stdafx.h”,且要加在首行。
应用程序无法正常启动0xc000007b解决方法
问题原因
依赖的库文件错误,需要排查更换。
解决方法
使用depends.exe检测错误的依赖库。并更换。
参考
1、(极好)VC++判断文件或文件夹是否存在
- MFC进行界面设计与编程
- mfc编程,界面设计
- MFC界面设计
- MFC界面设计
- 切分窗体:MFC界面设计
- MFC Ribbon界面设计
- MFC:Ribbon界面设计
- MFC界面设计入门篇
- MFC Ribbon界面设计
- MFC 与 HTTP编程
- MFC 与 HTTP编程
- MFC编程与SDK编程
- VC++6.0中用MFC进行COM编程
- VC使用MFC进行COM编程
- 使用 C++ 和 MFC 进行多线程编程
- 使用 C++ 和 MFC 进行多线程编程
- 使用 C++ 和 MFC 进行多线程编程
- MFC界面设计——AUDK
- 系统环境部署
- 微信小程序-picker
- 深度学习笔记之Andrew Ng(3)
- 算法学习第一周union find solution
- StringBuffer的常用方法
- MFC进行界面设计与编程
- flower?
- rpc 之序列化
- ngrok后台运行
- CentOS7 LVM扩容
- 优先队列的使用方法(自定义排序)
- Python学习——用Django建立一个博客
- Node.js调用模块
- 某 APP 跑步模块性能测试