由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
//*.rc
IDB_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;
}
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 off
ffmpeg -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 %1
pause
exit
kill.bat
@echo off
taskkill /f /im ffmpeg.exe
遍历文件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
#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;
}
/* 方法一:将获取到 "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获取时间的几种方法
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 线程的退出方法
1.Error C1003: error count exceeds 100
A:在自定义源文件中要加入#include “stdafx.h”,且要加在首行。
问题原因
依赖的库文件错误,需要排查更换。
解决方法
使用depends.exe检测错误的依赖库。并更换。
1、(极好)VC++判断文件或文件夹是否存在