当前位置: 首页 > Windows程序, 业余研究 > 正文

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

本文固定链接: http://www.latelee.org/programming-under-windows/yuvplayer-custom-resolution.html

目前暂无评论

发表评论

*

快捷键:Ctrl+Enter