整体界面设计
MVC架构
文件列表
转码参数
图片水印(文字水印?)
转码进度
开始转码
整体界面设计
MVC架构
MVC(Model-View-Controller)框架
其实从字面意思来说,只能了解各大概,view应该是视图的意思,那Model和Controller究竟是什么?
Model: 处理数据逻辑和程序运行状态
View: 则只负责显示
Controller: 通常负责处理用户交互的部分,从视图读取数据与用户输入,并向模型发送数据;这里顺便提一下,在Qt里面我们并没有Controller的概念,而是Delegate(委托),意义很明显:控制器委托模型来处理数据,模型委托控制器来做数据的交互。
这样的框架好处是很明显的:
- 高重用性:一个模型可以有多个视图,同样一个视图也可以对应多个模型
- 低耦合:因为模型与视图分离,所以可以独立的拓展和修改而不产生相互的影响
- 快速开发和便捷部署
各个控件的布局与美化
Image:显示图片
选择“Add Resource...”,弹出“Add Resource”对话框:
然后在左侧的“Resource Type”中选择“Bitmap”,点按钮“Import”,显示一个文件对话框,我们选择res文件夹中的test.bmp图片文件,
Frame:显示一个无填充的矩形框,边框颜色可以通过Color属性的下拉列表设定
Etched Horz:显示一条横分割线
Etched Vert:显示一条竖分割线
Rectangle:显示一个填充的矩形框,矩形颜色可通过Color属性的下拉列表设定
Icon:显示一个图标(Icon),图标通过Image 下拉列表来设置图标资源ID
Bitmap:显示一个位图(Bitmap),位图通过Image 下拉列表来设置位图资源ID
Enhanced Metafile:显示一个加强的元数据文件(Metafile)
Owner Draw:自绘
Label:标签字体和颜色
实际的应用中,可以用WM_CTLCOLOR 消息改变mfc中控件的颜色,比如现在就来改变一个static text控件的
字体、字体大小、字体颜色和背景色。
例如对话框的类为CTestDlg.
1. 在对话框的类中添加两个变量.
方法:在classview选项卡中,选择CTestDlg,右键,add member variable.
CBrush m_brush;
CFont m_font;
在OnInitDialog()函数中添加:
// TODO: ……
m_font.CreatePointFont(150,"华文行楷");//代表15号字体,华文行楷
m_brush.CreateSolidBrush(RGB(0,255,0));//画刷为绿色
2 添加WM_CTLCOLOR 消息响应,添加的方法为:
add windows message handler->WM_CTLCOLOR->add and edit
3 在HBRUSH CTestDlg::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor) 函数中的todo后添加代码,即:
HBRUSH CYourDlg::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor)
{
HBRUSH hbr = CDialog::OnCtlColor(pDC, pWnd, nCtlColor);
// TODO: Change any attributes of the DC here
if (pWnd->GetDlgCtrlID() == IDC_STATICText)
{
pDC->SetBkColor(RGB(0,255,0));//背景色为绿色
pDC->SetTextColor(RGB(255, 0, 0));//文字为红色
pDC->SelectObject(&m_font);//文字为15号字体,华文行楷
return m_brush;
}
// TODO: Return a different brush if the default is not desired
return hbr;
}
CFileDialog:选择文件
CString strFile = _T("");
CFileDialog dlgFile(TRUE, NULL, NULL, OFN_HIDEREADONLY, _T("Describe Files (*.mp4)|*.mp4|All Files (*.*)|*.*||"), NULL);
if (dlgFile.DoModal())
{
strFile = dlgFile.GetPathName();
AfxMessageBox(strFile);
}
ComboBox :组合框控件
打开 Class Wizard,添加控件对应变量,如:CComboBoxm_cbExamble;
InsertString() 将 Item 插入指定位置 nIndex,如:
m_cbExample.InsertString( nIndex, “StringData” );
int nIndex = m_cbExample.GetCurSel();
CString strCBText;
m_cbExample.GetLBText( nIndex, strCBText);
CString转char*
注意:ASCII编码, 如果是unicode编码,请不要这么使用
char* buf;
CString str="hello";
buf=(LPSTR)(LPCTSTR)str;
文件列表
1、为控件添加变量:m_ctrFileList
2、将ListControl控件的View属性修改为Report
3、在OnInitDialog()函数中添加如下代码:
m_ctrFileList.SetExtendedStyle(LVS_EX_FULLROWSELECT | LVS_EX_GRIDLINES);
//设置ListControl样式,带网格
//添加列标题
m_ctrFileList.InsertColumn(0, "标题0", LVCFMT_LEFT, 130);
4、添加一行内容:
m_ctrFileList.InsertItem(0, _T("Java"));
m_ctrFileList.SetItemText(0, 1, _T("3"));
m_ctrFileList.SetItemText(0, 2, _T("1"));
//设改行文字背景颜色
m_ctrList.SetTextBkColor(RGB(255, 0, 0));
5、改变表项:
OnLvnItemchangedListFilelist:
LPNMLISTVIEW pNMLV = reinterpret_cast<LPNMLISTVIEW>(pNMHDR);
// TODO: 在此添加控件通知处理程序代码
*pResult = 0;
CString strLangName; // 选择语言的名称字符串
NMLISTVIEW *pNMListView = (NMLISTVIEW*)pNMHDR;
if (-1 != pNMListView->iItem) // 如果iItem不是-1,就说明有列表项被选择
{
// 获取被选择列表项第一个子项的文本
strLangName = m_ctrFileList.GetItemText(pNMListView->iItem, 2);
// 将选择的语言显示与编辑框中
AfxMessageBox(strLangName);
}
转码参数
private:
CComboBox m_EncodeVideoTypes;
CComboBox m_EncodeAudioTypes;
CComboBox m_MuxerTypes;
图片水印
开始转码
有一个坑:命令行解析
int split_commandline(OptionParseContext *octx, int argc, char *argv[],
const OptionDef *options,
const OptionGroupDef *groups, int nb_groups)
{
// 强制读取命令行参数:
/ by fyxy, 坑:强制读取命令行
argv_w = CommandLineToArgvW(GetCommandLineW(), &win32_argc);
/ by fyxy, prepare_app_arguments(&argc, &argv);
}
本地测试:直接转码
char *arrParams[10] = { 0 };
for (int k = 0; k < 10; k++) {
arrParams[k] = new char[64]();
}
strcpy(arrParams[0], "xxx_mainx_ffmpeg431");
strcpy(arrParams[1], "-i");
strcpy(arrParams[2], "D:\\_movies\\__test\\ande_302.mp4");
strcpy(arrParams[3], "-vcodec");
strcpy(arrParams[4], "libx264");
strcpy(arrParams[5], "-acodec");
strcpy(arrParams[6], "copy");
strcpy(arrParams[7], "-y");
strcpy(arrParams[8], "ande_302--test121.flv");
m_TCProgress.SetRange(0, 100);
//AfxMessageBox(m_ctrFileList.GetItemText(i, 5));
m_TCProgress.SetPos(100);
/// 准备参数
main_ffmpeg431(9, arrParams);
for (int k = 0; k < 10; k++) {
delete[] arrParams[k];
arrParams[k] = NULL;
}
开启一个独立的工作线程
//创建第一个线程ThreadProc,相对优先级THREAD_PRIORITY_IDLE面对任何等级调整为1
AfxBeginThread((AFX_THREADPROC)ThreadProc,&lparam,THREAD_PRIORITY_IDLE);
工作者线程的函数必须是全局函数或静态成员函数,不能是普通的成员函数
//坑:static DWORD __cdecl TCThreadProc(LPVOID pParam)
DWORD WINAPI ThreadProc(LPVOID pParam)
{
return 0;
}
又一个坑:exit_program(...)
/ by fyxy, 退出进程
void exit_program(int ret)
{
if (program_exit)
program_exit(ret);
exit(ret);
}
转码进度
进度条
CProgressCtrl
MFC定时器
在MFC中和定时器相关的有三个函数:
UINT SetTimer( UINT nIDEvent, UINT nElapse, void (CALLBACK EXPORT* lpfnTimer)( HWND, UINT, UINT, DWORD) );
afx_msg void OnTimer( UINT nIDEvent );
BOOL KillTimer( int nIDEvent );
(1)在resource.h中定义两个定时器的ID
#define IDTIMER1 1
#define IDTIMER2 2
(2)在CMainFrame的OnCreate函数中定义两个定时器的属性。
SetTimer(TIMEID1,5000,0);
SetTimer(TIMEID2,7000,0);
(3) CMainFrame中对WM_TIMER进行响应。
oid CMainFrame::OnTimer(UINT nIDEvent)
{
// TODO: Add your message handler code here and/or call default
switch(nIDEvent) {
case TIMEID1:
{
AfxMessageBox("定时器1!");
break;
}
case TIMEID2:
{
AfxMessageBox("定时器2!");
break;
}
default:
;
}
CFrameWnd::OnTimer(nIDEvent);
}
(4)在CMainFrame的析构函数中添加
KillTimer(IDTIMER1);
KillTimer(IDTIMER2);