我的YUV播放器MFC小笔记:添加删除自定义分辨率
在最初设计YUV播放参数时,就考虑参数的保存,即使用注册表方式,前文已述。但直到后来才解决几个技术问题,方得以写此文章。
分辨率使用下拉框形式,在程序启动时初始化,不在资源中写死。注册表使用一个string字段保存,用分号“;”隔开。读取后分词,放到CStringArray中,使用combox的AddString添加至下拉框。
代码初始化片段:
CString strTemp;
// default
if (!ExistRegistration())
{
SetRegistration(m_strAddedSize, m_nWidth,m_nHeight, m_nFpsIndex, m_nYuvFormat, m_fLoop);
}
// read
GetRegistration(m_strAddedSize, m_nWidth, m_nHeight, m_nFpsIndex, m_nYuvFormat, m_fLoop);
int pos = 0;
strTemp = m_strAddedSize.Tokenize(_T(";"), pos);
m_strArrAddedSize.Add(strTemp);
while (strTemp != _T(""))
{
strTemp = m_strAddedSize.Tokenize(_T(";"), pos);
m_strArrAddedSize.Add(strTemp);
}
// 不知为何,最后一个是空的,这里删除,否则后面再添加时会多一个空字符串
m_strArrAddedSize.RemoveAt(m_strArrAddedSize.GetCount()-1);
int nResolutionIdx = -1;
for (int i = 0; i < m_strArrAddedSize.GetCount(); i++)
{
m_cbResolution.AddString(m_strArrAddedSize[i]);
int width = 0;
int height = 0;
swscanf_s(m_strArrAddedSize[i].GetBuffer(), _T("%dx%d"), &width, &height);
if (width == m_nWidth && height == m_nHeight)
nResolutionIdx = i;
}
m_cbYuvFormat.SetCurSel(m_nYuvFormat);
m_cbFps.SetCurSel(m_nFpsIndex);
m_cbResolution.SetCurSel(nResolutionIdx);
m_nYuvFormat = m_cbYuvFormat.GetCurSel();
m_cbResolution.GetWindowText(strTemp);
m_cbFps.GetWindowText(strTemp);
swscanf_s(strTemp.GetBuffer(), _T("%d"), &m_nFps);
添加自定义分辨率,首先检查是否已经存在该分辨率,如是则不操作。如不是,则在CStringArray类型变量尾部添加。然后将其排列,再重新更新下位框,这样做到实时变化。
// 向注册表添加一种分辨率
void CSettingDlg::OnBnClickedBtAdd()
{
CString strTemp;
CString strAddedSize;
UpdateData();
for (int i = 0; i < m_strArrAddedSize.GetCount(); i++)
{
int width = 0;
int height = 0;
swscanf_s(m_strArrAddedSize[i].GetBuffer(), _T("%dx%d"), &width, &height);
if (width == m_nWidth && height == m_nHeight)
return;
}
strTemp.Format(_T("%dx%d"), m_nWidth, m_nHeight);
// 尾部添加
m_strArrAddedSize.Add(strTemp);
// 排序
BubbleSort(m_strArrAddedSize);
// 先清空
m_strAddedSize.Empty();
m_cbResolution.ResetContent();
// 再添加
for (int i = 0; i < m_strArrAddedSize.GetCount(); i++)
{
m_cbResolution.AddString(m_strArrAddedSize[i].GetBuffer());
strTemp.Format(_T("%s;"), m_strArrAddedSize[i].GetBuffer());
m_strAddedSize += strTemp;
}
UpdateRes();
//return;
//MessageBox(m_strAddedSize);
return;
// todo 在Add时,到底要不要写注册表?还是等到apply时才做?
SetRegistration(m_strAddedSize, m_nWidth,m_nHeight, m_nFpsIndex, m_nYuvFormat, m_fLoop);
}
本来不想做排序的,但因为有可能添加宽高较小的分辨率,如果放到后面,不太好看,故而排序。msdn上有关于CStringArray的排序,但不符合要求,于是就自己根据实际情况写了个冒泡排序,十分简单,代码如下:
// 根据宽高排序
void BubbleSort(CStringArray &ca)
{
int len = ca.GetCount();
int width1 = 0;
int height1 = 0;
int width2 = 0;
int height2 = 0;
CString tmp;
for (int i = 0; i < len; i++)
{
for (int j = i; j < len; j++)
{
swscanf_s(ca[i].GetBuffer(), _T("%dx%d"), &width1, &height1);
swscanf_s(ca[j].GetBuffer(), _T("%dx%d"), &width2, &height2);
if ((width1 > width2) || (width1 == width2 && height1 > height2))
{
tmp = ca.GetAt(i);
ca.SetAt(i, ca.GetAt(j));
ca.SetAt(j, tmp);
}
}
}
}
删除分辨率代码如下:
// 在注册表删除一种分辨率
void CSettingDlg::OnBnClickedBtDel()
{
UpdateData();
wchar_t szRes[32] = {0};
m_cbResolution.GetWindowText(szRes,32);
for (int i = 0; i < m_strArrAddedSize.GetCount(); i++)
{
if (!m_strArrAddedSize[i].CompareNoCase(szRes))
{
m_strArrAddedSize.RemoveAt(i);
}
}
CString strTemp;
m_strAddedSize.Empty();
m_cbResolution.ResetContent();
for (int i = 0; i < m_strArrAddedSize.GetCount() ; i++)
{
m_cbResolution.AddString(m_strArrAddedSize[i].GetBuffer());
strTemp.Format(_T("%s;"), m_strArrAddedSize[i].GetBuffer());
m_strAddedSize += strTemp;
}
UpdateRes();
SetRegistration(m_strAddedSize, m_nWidth,m_nHeight, m_nFpsIndex, m_nYuvFormat, m_fLoop);
}
似乎这个代码可以做到更优。
李迟 2015.8.19
近来经济拮据,如本文对阁下有帮助,可慷慨解囊赞助笔者以输出更多好文章。
支付宝[email protected] 或 微信fly_camel_fly 均可。感谢!
本文固定链接: /programming-under-windows/yuvplayer-custom-resolution.html