參考: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();
否則整個界面就只畫這一張圖了