首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >为什么我的担架图像会褪色?

为什么我的担架图像会褪色?
EN

Stack Overflow用户
提问于 2022-06-18 15:09:07
回答 1查看 51关注 0票数 0

在正确填充带有显示器显示缩略图的CListCtrl方面,我遇到了一些困难。

在我的CDialog的右边,我有一个静态控件,我在白色画布上呈现这个图像,如下所示:

代码语言:javascript
运行
复制
void CCenterCursorOnScreenDlg::OnDrawItem(int nIDCtl, LPDRAWITEMSTRUCT lpDrawItemStruct)
{
    if (nIDCtl == IDC_STATIC_MONITOR && !m_imgPreview.IsNull())
    {
        // Set the mode
        SetStretchBltMode(lpDrawItemStruct->hDC, HALFTONE);

        // Wipe the canvas
        FillRect(lpDrawItemStruct->hDC, &lpDrawItemStruct->rcItem, static_cast<HBRUSH>(GetStockObject(WHITE_BRUSH)));

        // Get canvas rectangle
        const CRect rectCanvas(lpDrawItemStruct->rcItem);

        // Calculate ratio factors
        const float nRatioImage = m_imgPreview.GetWidth() / static_cast<float>(m_imgPreview.GetHeight());
        const float nRatioCanvas = rectCanvas.Width() / static_cast<float>(rectCanvas.Height());

        // Calculate new rectangle size
        // Account for portrait images (negative values)
        CRect rectDraw = rectCanvas;
        if (nRatioImage > nRatioCanvas)
            rectDraw.SetRect(0, 0, rectDraw.right, static_cast<int>(rectDraw.right / nRatioImage));
        else if (nRatioImage < nRatioCanvas)
            rectDraw.SetRect(0, 0, static_cast<int>((rectDraw.bottom * nRatioImage)), rectDraw.bottom);

        // Add a margin
        rectDraw.DeflateRect(5, 5);

        // Move to center
        const CSize ptOffset = rectCanvas.CenterPoint() - rectDraw.CenterPoint();
        rectDraw.OffsetRect(ptOffset);

        // Add a black frame
        FrameRect(lpDrawItemStruct->hDC, &lpDrawItemStruct->rcItem, static_cast<HBRUSH>(GetStockObject(BLACK_BRUSH)));

        // Draw
        m_imgPreview.Draw(lpDrawItemStruct->hDC, rectDraw);

        return;
    }

    CDialogEx::OnDrawItem(nIDCtl, lpDrawItemStruct);
}

上面的工作原理很好:

但是我对这些图像的CListCtrl版本有问题。例如,正如你所看到的那样,我正在失去色彩。

我的CImageList是这样创建的:

代码语言:javascript
运行
复制
m_ImageListThumb.Create(THUMBNAIL_WIDTH, THUMBNAIL_HEIGHT, ILC_COLOR32, 0, 1);
m_ListThumbnail.SetImageList(&m_ImageListThumb, LVSIL_NORMAL);

然后通过在DrawThumbnails()中调用OnInitDialog创建所有缩略图

代码语言:javascript
运行
复制
void CCenterCursorOnScreenDlg::DrawThumbnails()
{
    int monitorIndex = 0;

    m_ListThumbnail.SetRedraw(FALSE);

    for (auto& strMonitor : m_monitors.strMonitorNames)
    {
        CImage img;
        CreateMonitorThumbnail(monitorIndex, img, true);

        CBitmap* pImage = new CBitmap();
        pImage->Attach((HBITMAP)img);
        m_ImageListThumb.Add(pImage, nullptr);

        CString strMonitorDesc = m_monitors.strMonitorNames.at(monitorIndex);

        strMonitorDesc.AppendFormat(L" (Screen %d)", monitorIndex + 1);

        m_ListThumbnail.InsertItem(monitorIndex, strMonitorDesc, monitorIndex);


        monitorIndex++;

        delete pImage;
    }

    m_ListThumbnail.SetRedraw(TRUE);
}

CreateMonitorThumbnail函数:

代码语言:javascript
运行
复制
BOOL CCenterCursorOnScreenDlg::CreateMonitorThumbnail(const int iMonitorIndex, CImage &rImage, bool bSmall)
{
    const CRect rcCapture = m_monitors.rcMonitors.at(iMonitorIndex);

    // destroy the currently contained bitmap to create a new one
    rImage.Destroy();

    auto nWidth = rcCapture.Width();
    auto nHeight = rcCapture.Height();
    if (bSmall)
    {
        nWidth = THUMBNAIL_WIDTH;
        nHeight = THUMBNAIL_HEIGHT;
    }

    // create bitmap and attach it to this object 
    if (!rImage.Create(nWidth, nHeight, 32, 0))
    {
        AfxMessageBox(L"Cannot create image!", MB_ICONERROR);
        return FALSE;
    }


    // create virtual screen DC
    CDC dcScreen;
    dcScreen.CreateDC(_T("DISPLAY"), nullptr, nullptr, nullptr);

    // copy the contents from the virtual screen DC 

    BOOL bRet = FALSE;
    if (bSmall)
    {
        CRect rt(0, 0, nWidth, nHeight);

        //::FillRect(rImage.GetDC(), rt, static_cast<HBRUSH>(GetStockObject(WHITE_BRUSH)));
        bRet = ::StretchBlt(rImage.GetDC(), 0, 0, 
            nWidth, 
            nHeight, 
            dcScreen.m_hDC, 
            rcCapture.left, 
            rcCapture.top, 
            rcCapture.Width(), 
            rcCapture.Height(), SRCCOPY | CAPTUREBLT);

    }
    else
    {
        bRet = ::BitBlt(rImage.GetDC(), 0, 0, 
            rcCapture.Width(), 
            rcCapture.Height(),
            dcScreen.m_hDC, 
            rcCapture.left, 
            rcCapture.top, SRCCOPY | CAPTUREBLT);
    }

    // do cleanup and return
    dcScreen.DeleteDC();
    rImage.ReleaseDC();

    return bRet;
}

理想情况下,我想拥有与右边完全相同的视觉图像,但明显地缩小了尺寸。我该怎么解决这个问题?

我简化了从CImageCBitmap的转换,但没有什么区别:

代码语言:javascript
运行
复制
void CCenterCursorOnScreenDlg::DrawThumbnails()
{
    int monitorIndex = 0;

    // Stop redrawing the CListCtrl
    m_ListThumbnail.SetRedraw(FALSE);

    // Loop monitor info
    for (auto& strMonitor : m_monitors.strMonitorNames)
    {
        // Create the thumbnail image
        CImage monitorThumbnail;
        CreateMonitorThumbnail(monitorIndex, monitorThumbnail, true);

        // Convert it to a CBitmap
        CBitmap* pMonitorThumbnailBitmap = CBitmap::FromHandle(monitorThumbnail);

        // Add the CBitmap to the CImageList
        m_ImageListThumb.Add(pMonitorThumbnailBitmap, nullptr);

        // Build the caption description
        CString strMonitorDesc = m_monitors.strMonitorNames.at(monitorIndex);
        strMonitorDesc.AppendFormat(L" (Screen %d)", monitorIndex + 1);

        // Add the item to the CListCtrl
        m_ListThumbnail.InsertItem(monitorIndex, strMonitorDesc, monitorIndex);

        monitorIndex++;
    }

    // Start redrawiung the CListCtrl again
    m_ListThumbnail.SetRedraw(TRUE);
}

如果我将代码更改为传递最后一个参数的false,那么它将使用原始捕获的图像,而不进行缩放:

那里的颜色是上帝,所以当我这样做的时候:

代码语言:javascript
运行
复制
if (bSmall)
{
    CRect rt(0, 0, nWidth, nHeight);

    //::FillRect(rImage.GetDC(), rt, static_cast<HBRUSH>(GetStockObject(WHITE_BRUSH)));
    bRet = ::StretchBlt(rImage.GetDC(), 0, 0, 
        nWidth, 
        nHeight, 
        dcScreen.m_hDC, 
        rcCapture.left, 
        rcCapture.top, 
        rcCapture.Width(), 
        rcCapture.Height(), SRCCOPY | CAPTUREBLT);

}

把事情搞砸了。

EN

回答 1

Stack Overflow用户

发布于 2022-06-18 16:42:06

我的问题是与OnDrawItem没有任何关系。我仅仅是为了说明右边的图像是如何呈现的。我想作为背景资料可能会有所帮助。但它可能混淆了这个问题,从长远来看,我可能会把它拿出来!

基于这些评论,我想起了SetStretchBltMode,它在CreateMonitorThumbnail中丢失了。所以,我现在有一个函数:

代码语言:javascript
运行
复制
BOOL CCenterCursorOnScreenDlg::CreateMonitorThumbnail(const int iMonitorIndex, CImage &rImage, bool bResizeAsThumbnail)
{
    const CRect rcCapture = m_monitors.rcMonitors.at(iMonitorIndex);

    // Destroy the currently contained bitmap to create a new one
    rImage.Destroy();

    // Massage the dimensions as we want a thumbnail
    auto nWidth = rcCapture.Width();
    auto nHeight = rcCapture.Height();
    if (bResizeAsThumbnail)
    {
        nWidth = m_iThumbnailWidth;

        auto dRatio = rcCapture.Width() / nWidth;
        //nHeight = m_iThumbnailHeight;
        nHeight = static_cast<int>(rcCapture.Height() / dRatio);

        if (nHeight > m_iThumbnailHeight)
        {
            AfxMessageBox(L"Need to investigate!");
        }
    }

    // Create bitmap and attach it to this object 
    if (!rImage.Create(nWidth, nHeight, 32, 0))
    {
        AfxMessageBox(L"Cannot create image!", MB_ICONERROR);
        return FALSE;
    }


    // Create virtual screen DC
    CDC dcScreen;
    dcScreen.CreateDC(L"DISPLAY", nullptr, nullptr, nullptr);

    // Copy (or resize) the contents from the virtual screen DC 

    BOOL bRet = FALSE;
    auto dcImage = rImage.GetDC();
    if (bResizeAsThumbnail)
    {
        // Set the mode first!
        SetStretchBltMode(dcImage, COLORONCOLOR);

        CPen penBlack;
        penBlack.CreatePen(PS_SOLID, 3, RGB(0, 0, 0));
        ::Rectangle(dcImage, 0, 0, m_iThumbnailWidth, m_iThumbnailHeight);

        int iTop = (m_iThumbnailHeight - nHeight) / 2;

        // Copy (and resize)
        bRet = ::StretchBlt(dcImage, 0, iTop,
            nWidth, 
            nHeight, 
            dcScreen.m_hDC, 
            rcCapture.left, 
            rcCapture.top, 
            rcCapture.Width(), 
            rcCapture.Height(), SRCCOPY | CAPTUREBLT);
    }
    else
    {
        // Copy
        bRet = ::BitBlt(dcImage, 0, 0, 
            rcCapture.Width(), 
            rcCapture.Height(),
            dcScreen.m_hDC, 
            rcCapture.left, 
            rcCapture.top, SRCCOPY | CAPTUREBLT);
    }

    // Do cleanup and return
    dcScreen.DeleteDC();
    rImage.ReleaseDC();

    return bRet;
}

这是用正确的颜色显示缩略图的关键:

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/72670330

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档