mfc動態顯示圖片(bmp以及png)


參考:https://blog.csdn.net/pudongdong/article/details/69396600

 

之前寫過win32動態顯示圖片的博客(程序線程檢測圖片變動自動刷新,而非按按鈕再刷新的情況),這次用到了mfc。原理是一樣的。

 

OnInitDialog函數初始化

BOOL CXxxDlg::OnInitDialog()
{
    CDialog::OnInitDialog();
    if (m_bmp.m_hObject != NULL)
        m_bmp.DeleteObject();
    /*載入圖片*/
    HBITMAP hbmp = (HBITMAP)::LoadImage(AfxGetInstanceHandle(),L"initPic.bmp", IMAGE_BITMAP, 0, 0, LR_CREATEDIBSECTION | LR_LOADFROMFILE);
    if (hbmp == NULL)
        return FALSE;
    /*取得加載的BMP的信息*/
    m_bmp.Attach(hbmp);
    DIBSECTION ds;
    BITMAPINFOHEADER &bminfo = ds.dsBmih;
    m_bmp.GetObject(sizeof(ds), &ds);
    int cx = bminfo.biWidth; 
    int cy = bminfo.biHeight; 
    /*得到了圖像的寬度和高度后,對圖像大小進行適應,即調整控件的大小,讓它正好顯示一張圖片*/
    CRect rect;
    GetDlgItem(IDC_PIC_ZONE)->GetWindowRect(&rect);
    ScreenToClient(&rect);
    /*調整大小*/
    GetDlgItem(IDC_PIC_ZONE)->MoveWindow(rect.left, rect.top, cx, cy, true);
    return TRUE; 
}

 

OnPaint具體畫圖。

IDC_PIC_ZONE為picture control控件。
void CXxxDlg::OnPaint()
{
    if (m_bmp.m_hObject != NULL)
        m_bmp.DeleteObject();
    /*重新載入圖片,因為可能刷新*/
    HBITMAP hbmp = (HBITMAP)::LoadImage(AfxGetInstanceHandle(), L"initPic.bmp", IMAGE_BITMAP, 0, 0, LR_CREATEDIBSECTION | LR_LOADFROMFILE);
    if (hbmp == NULL)
        return;
    /*取得加載的BMP的信息*/
    m_bmp.Attach(hbmp);
    DIBSECTION ds;
    BITMAPINFOHEADER &bminfo = ds.dsBmih;
    m_bmp.GetObject(sizeof(ds), &ds);
    /*若用此句,得到的是對話框的DC,圖片將被繪制在對話框上*/
    //CPaintDC dc(this);    
    /*用此句,得到picture控件的DC,圖像將被繪制在控件上  */
    CPaintDC dc(GetDlgItem(IDC_PIC_ZONE));
    /*若用此兩句,得到的是屏幕的DC,圖片將被繪制在屏幕上*/
    //  CDC dc;
    //  dc.m_hDC=::GetDC(NULL);  
    CRect rcclient;
    GetDlgItem(IDC_PIC_ZONE)->GetClientRect(&rcclient);
    CDC memdc;
    memdc.CreateCompatibleDC(&dc);
    CBitmap bitmap;
    bitmap.CreateCompatibleBitmap(&dc, rcclient.Width(), rcclient.Height());
    memdc.SelectObject(&bitmap);
    CWnd::DefWindowProc(WM_PAINT, (WPARAM)memdc.m_hDC, 0);
    CDC maskdc;
    maskdc.CreateCompatibleDC(&dc);
    CBitmap maskbitmap;
    maskbitmap.CreateBitmap(rcclient.Width(), rcclient.Height(), 1, 1, NULL);
    maskdc.SelectObject(&maskbitmap);
    maskdc.BitBlt(0, 0, rcclient.Width(), rcclient.Height(), &memdc,
        rcclient.left, rcclient.top, SRCCOPY);
    CBrush brush;
    brush.CreatePatternBrush(&m_bmp);
    dc.FillRect(rcclient, &brush);
    dc.BitBlt(rcclient.left, rcclient.top, rcclient.Width(), rcclient.Height(),
        &memdc, rcclient.left, rcclient.top, SRCPAINT);
    brush.DeleteObject();
}

 

這個程序功能是在設備上按手指后,界面自動刷新指靜脈的圖片

所以界面的刷新要自己寫代碼刷新(刷新區域在RECT里設置,不要刷新面積太大,否則整個界面都閃爍):

void CXxDlg::refreshImg()
{
    RECT        rect;
    //idcPicZone.GetWindowRect(&rect);
    SetRect(&rect, 10, 10, 520, 230);
    InvalidateRect( &rect, true);
    UpdateWindow();
}

 

 

注意,要想程序運行到OnPaint方法,需要在BEGIN_MESSAGE_MAP注冊ON_WM_PAINT()

 

效果:

 

 

 


 

 

上面程序那樣寫。是由特定需求決定的:程序檢測圖片更新后自動刷新圖片,而非按了什么按鈕產生事件響應。另外,還進行了位圖的轉化

由於不觸發事件,需要自己手動刷新界面

 

實際上,如果是按按鈕就刷新界面的話,寫法就簡單了:

void CXxDlg::_setPic()
{
    CImage image;
    CWnd* pWnd = GetDlgItem(IDC_SKIN_SHOW);
    CDC* pDC = pWnd->GetDC();
    HDC hDC = pDC->m_hDC;
    CRect rect_frame;
    pWnd->GetClientRect(&rect_frame);
    image.Load(L"xxx\\xxx.png");
    ::SetStretchBltMode(hDC, HALFTONE);
    ::SetBrushOrgEx(hDC, 0, 0, NULL);
    image.Draw(hDC, rect_frame);
    ReleaseDC(pDC);
    image.Destroy();
}

在事件響應函數里加入這樣代碼就可以刷新圖片了(圖片是load的路徑)

因為有事件響應,界面自動刷新

 

不過有個問題,如果是想打開程序后,初始界面顯示一張圖片的話,把上面的代碼寫在OnInitDialog()函數里是沒用效果的

必須要把上面的代碼寫在OnPaint()里:

void CXxDlg::OnPaint()
{
    /*默認顯示第一張預覽圖*/
    ………………………………
    __super::OnPaint();
}

注意要寫__super::OnPaint();

否則整個界面就只畫這一張圖了

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM