MFC总结

1、MFC主窗口调用子窗口显示问题

①主窗口显示问题可以在init初始化函数中

②子窗口显示问题可以利用消息事件PAINT来进行初始化(可以添加一个成员变量flag,让消息事件只执行一次)

2、线程的创建、打开文件、显示图片

①一个窗口都会有一个.h和一个.cpp文件

②在头文件中添加

//类中成员函数
CWinThread* pThread; //创建线程对象,
//类外
struct threadInfo   //线程执行参数
{
	CDC *pDC;       
	CRect rect;
};
UINT PlayVideo(LPVOID lpParam);   //线程执行函数

③在源程序中添加(IDC_VideoFrame是控件的ID

threadInfo Info;       //结构体变量
Info.pDC = GetDlgItem(IDC_VideoFrame)->GetDC();//保存根据ID获得窗口指针再获取与该窗口关联的上下文指针
GetDlgItem(IDC_VideoFrame)->GetClientRect(&Info.rect); //获得控件窗口大小
pThread = AfxBeginThread(PlayVideo, &Info);//启动线程
UINT PlayVideo(LPVOID lpParam)
{
	threadInfo* pInfo = (threadInfo*)lpParam;
	HDC hdc = pInfo->pDC->GetSafeHdc();// 获取设备上下文句柄
	CString csFilter = "AVI Files(*.AVI)|*.AVI||";
	CFileDialog FileDlg(true, NULL, NULL, OFN_HIDEREADONLY, csFilter);
	if (FileDlg.DoModal() == IDOK)
	{//  选择了文件名
		bIsRunning = true;
		strFileName = FileDlg.m_ofn.lpstrFile;
		if (FileDlg.m_ofn.nFileExtension == 0)
		{  //  无文件后缀
			strFileName = strFileName + ".avi";//  加文件后缀
		}
		CvCapture *capture = cvCreateFileCapture(strFileName);
		//函数给指定文件中的视频流分配和初始化CvCapture结构。	
		double fps = cvGetCaptureProperty(capture, CV_CAP_PROP_FPS);
		//获得摄像头或者视频文件的指定属性。
		vfps = 1000 / fps;                                  //计算每帧播放的时间
		int countframe = cvGetCaptureProperty(capture, CV_CAP_PROP_FRAME_COUNT);
		m_ctrlSlider.SetRange(0, countframe);          //初始化滑块范围
		m_ctrlSlider.SetPos(0);                        //初始化滑块位置
		CvvImage cimg;
		while (bIsRunning)
		{
			m_ctrlSlider.SetPos(num);
			if (num <= countframe - 2) {
				cvSetCaptureProperty(capture, CV_CAP_PROP_POS_FRAMES, num);
				frame = cvQueryFrame(capture);  //从摄像头或者文件中抓取一帧,然后解压并返回这一帧
				//if (!frame)break;
				cimg.CopyOf(frame, frame->nChannels);//从img复制图像到当前的对象中
				cimg.DrawToHDC(hdc, &pInfo->rect);
				Sleep(vfps - 25);
				num++;
				while (flag == 1){

				}
			}
			else{
				num = 0;
				m_ctrlSlider.SetPos(0);
			}
		}
		cvReleaseCapture(&capture);//释放由cvCaptureFromFile 或者cvCaptureFromCAM申请的CvCapture结构。
	}
	else{
		//  没有选择文件
		strFileName = "../video.png";//  显示一张警告图片
		IplImage *image = cvLoadImage(strFileName);
		CvvImage cimg;
		cimg.CopyOf(image, image->nChannels);
		cimg.DrawToHDC(hdc, &pInfo->rect);
	}
	return 0;
}
④滑块的使用,我在以前的博客上写过

⑤线程创建,不一定要建立结构体存储和创建一个函数。也可以定义两个变量即可,如显示一张图片

CDC *pDC;
CRect rect;
pDC = GetDlgItem(IDC_ImgShow)->GetDC();//保存根据ID获得窗口指针再获取与该窗口关联的上下文指针
GetDlgItem(IDC_ImgShow)->GetClientRect(&rect); //获得picture控件窗口大小
HDC hdc = pDC->GetSafeHdc();// 获取设备上下文句柄
CvvImage cimgg;
IplImage *image = cvLoadImage(address);
cimgg.CopyOf(image, image->nChannels);
cimgg.DrawToHDC(hdc, &rect);

3、选择保存路径

BROWSEINFO  bi;
bi.hwndOwner = NULL;
bi.pidlRoot = NULL;
bi.pszDisplayName = NULL;
bi.lpszTitle = NULL;
bi.ulFlags = 0;
bi.lpfn = NULL;
bi.iImage = 0;
LPCITEMIDLIST pidl = SHBrowseForFolder(&bi);
if (!pidl)
	return;
TCHAR  szDisplayName[255];
SHGetPathFromIDList(pidl, szDisplayName);
CString path(szDisplayName);
//路径path下,创建一个目录
str = ((LPCTSTR)strFileNameAuto);
int position = str.find_last_of("\\");
string spiltName = str.substr(position + 1, str.length() - position - 1);
string s = "\\";
concatNameAuto = (LPCTSTR)path + s + spiltName;
reportPathAuto = concatNameAuto;
if (_access(concatNameAuto.c_str(), 0) == 0){  //如果文件存在,返回0,不存在,返回-1。
	myDeleteDirectory(concatNameAuto);
}
CreateDirectory(concatNameAuto.data(), 0);//不存在则创建 
void myDeleteDirectory(string directory_path)   //删除一个文件夹下的图片,嵌套文件夹不行
{
	try
	{
		__finddata64_t file;
		intptr_t handle = _findfirst64(string(directory_path + "\\*").data(), &file);
		if (handle == -1)
		{}
		else
		{
			do
			{
				//file.attrib用于表示文件的属性,_A_SUBDIR表示子文件夹
				if (file.attrib == _A_SUBDIR)
				{
					//文件名为. or ..
					if (string(file.name).compare(".") == 0 || string(file.name).compare("..") ==0)		
					{
						continue;  //查找下一个文件名
					}
					else{}
				}
				//用来检索子串在字符串中首次出现的位置
				else if (strstr(file.name, ".bmp") || strstr(file.name, ".BMP") || strstr(file.name, ".JPG") || strstr(file.name, ".jpg"))
				{
					string abc = directory_path + "/" +  file.name;
					DeleteFile(abc.c_str());
				}
			}while((_findnext64(handle, &file) == 0));
		}
		RemoveDirectory(directory_path.c_str());
		_findclose(handle);
	}
	catch (exception& e)
	{}
}

4、复选框的使用

①复选框的使用很简单,就是一个简单的标记,若单击或者选中的时候进行标记即可。

②复选框圆圈和正方形的区别是,前者只能单选,后者可以多选。

5、下拉框的使用

①为Conbobox添加变量

②是通过右键控件添加变量(m_chosecom)

③初始化

//主界面时,在init中下
//子界面时,在PAINT消息函数中写
m_chosecom.AddString("hello");
m_chosecom.AddString("world");
④控件函数中可以判断选择的值(先获取id,再获取str)

CString str;
int nSel = m_chosecom.GetCurSel();
m_chosecom.GetLBText(nSel, str);

6、编辑框的使用

CEdit* pBoxOne;
pBoxOne = (CEdit*)GetDlgItem(IDC_EDIT1);   //ID
pBoxOne->SetWindowText("hello world"); //赋值

7、按钮的显示和隐藏

GetDlgItem(IDC_BUTTON1)->ShowWindow(SW_HIDE);
GetDlgItem(IDC_BUTTON1)->ShowWindow(SW_SHOW);

8、String和CString的区别及转换

①一个头文件是《iostream》

②一个头文件是《afx.h》

strs.c_str()、_T()、LPCTSTR可以实现转化

9、视频流的截取

①ffmpeg下载地址:https://ffmpeg.zeranoe.com/builds/

②包含三个版本,都需要下载,Static提供exe,Shared提供dll和exe 、Dev提供include

③Static和Shared二选一即可(一个是完全封装成exe,一个是不完全封装,一般选择Static即可)

④创建工程,配置环境(配置库include、配置链接库lib,都是dev提供)

⑤调节字符编码

⑥ffmpeg.exe拷贝到运行目录下(源码所在目录,要么使用Static中exe,要么使用Shared中的dll和exe)

Static和Shared中都有ffmpeg.exe但是大小不一样,前者大一些。要么直接使用Static中的exe,要么把Shared中的dll和exe都拷贝到源码相当路径下。

⑦源码

vector<string> vecShowPic;
//保持在一个位置
string str ="..\\test.avi";
string path = "..\\pic";        //pic文件夹必须事先创建好
vecShowPic.clear();
string ass = "ffmpeg.exe -i " + str + " -f image2 -an -r 0.1 " + path + "/image%03d.jpg ";
system(ass.c_str());    //抽帧结束
//读取路径,放在vector中
CFileFind cf;
CString filePath;
CString fileName;
path += "\\";
path += "*.*";
BOOL res = cf.FindFile(path.c_str());
while (res)
{
	res = cf.FindNextFileA();
	filePath = cf.GetFilePath();
	fileName = cf.GetFileName();
	if (!cf.IsDirectory() && !cf.IsDots())
	{
		if (fileName.Right(3) == "jpg"){
			vecShowPic.push_back((LPCTSTR)filePath);
		}
	}
}
cf.Close();


  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值