我的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