OnPaint的使用,让窗口立即重绘的方法,CPaintDC的使用及各种DC的使用
Posted xiaomi-daming
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了OnPaint的使用,让窗口立即重绘的方法,CPaintDC的使用及各种DC的使用相关的知识,希望对你有一定的参考价值。
// CRotateBmpDlg 对话框
class CRotateBmpDlg : public CDialogEx
{
// 构造
public:
CRotateBmpDlg(CWnd* pParent = NULL); // 标准构造函数
virtual ~CRotateBmpDlg();
// 对话框数据
#ifdef AFX_DESIGN_TIME
enum { IDD = IDD_ROTATEBMP_DIALOG };
#endif
class CRotateBmpDlg : public CDialogEx
{
// 构造
public:
CRotateBmpDlg(CWnd* pParent = NULL); // 标准构造函数
virtual ~CRotateBmpDlg();
// 对话框数据
#ifdef AFX_DESIGN_TIME
enum { IDD = IDD_ROTATEBMP_DIALOG };
#endif
protected:
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV 支持
//LPVOID lpSrcBits;
//LONG SrcHeight;
//LONG SrcWidth;
HBITMAP m_hBitmap;
CBitmap m_bitmap;
// 实现
protected:
HICON m_hIcon;
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV 支持
//LPVOID lpSrcBits;
//LONG SrcHeight;
//LONG SrcWidth;
HBITMAP m_hBitmap;
CBitmap m_bitmap;
// 实现
protected:
HICON m_hIcon;
// 生成的消息映射函数
virtual BOOL OnInitDialog();
afx_msg void OnSysCommand(UINT nID, LPARAM lParam);
afx_msg void OnPaint();
afx_msg HCURSOR OnQueryDragIcon();
DECLARE_MESSAGE_MAP()
public:
afx_msg void OnBnClickedButton1();
CString strFilePath;
};
virtual BOOL OnInitDialog();
afx_msg void OnSysCommand(UINT nID, LPARAM lParam);
afx_msg void OnPaint();
afx_msg HCURSOR OnQueryDragIcon();
DECLARE_MESSAGE_MAP()
public:
afx_msg void OnBnClickedButton1();
CString strFilePath;
};
初始化m_hBitmap;m_bitmap;strFilePath;
CRotateBmpDlg::CRotateBmpDlg(CWnd* pParent /*=NULL*/)
: CDialogEx(IDD_ROTATEBMP_DIALOG, pParent)
{
m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
strFilePath = "";
m_hBitmap = NULL;
}
: CDialogEx(IDD_ROTATEBMP_DIALOG, pParent)
{
m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
strFilePath = "";
m_hBitmap = NULL;
}
CRotateBmpDlg::~CRotateBmpDlg()
{
/*if (lpSrcBits)
{
delete lpSrcBits;
}*/
if (m_bitmap.m_hObject)
{
m_bitmap.Detach();
}
DeleteObject(&m_hBitmap);
DeleteObject(&m_bitmap);
}
{
/*if (lpSrcBits)
{
delete lpSrcBits;
}*/
if (m_bitmap.m_hObject)
{
m_bitmap.Detach();
}
DeleteObject(&m_hBitmap);
DeleteObject(&m_bitmap);
}
void CRotateBmpDlg::OnBnClickedButton1()
{
CFileDialog dlgFileOpen(TRUE, NULL, _T("*.bmp"), OFN_HIDEREADONLY,
_T("打印文件(*.bmp)|*.bmp|所有文件(*.*)|*.*|"), this);
if (dlgFileOpen.DoModal() == IDCANCEL)
{
return;
}
strFilePath = dlgFileOpen.GetPathName();
CRect rect;
this->GetClientRect(rect);
m_hBitmap = (HBITMAP)LoadImage(NULL, strFilePath, IMAGE_BITMAP, rect.Width(), rect.Height() - 60, LR_LOADFROMFILE | LR_CREATEDIBSECTION);
Invalidate();//使窗口无效,产生WM_PAINT消息,WM_PAINT消息在消息队列的优先级低
{
CFileDialog dlgFileOpen(TRUE, NULL, _T("*.bmp"), OFN_HIDEREADONLY,
_T("打印文件(*.bmp)|*.bmp|所有文件(*.*)|*.*|"), this);
if (dlgFileOpen.DoModal() == IDCANCEL)
{
return;
}
strFilePath = dlgFileOpen.GetPathName();
CRect rect;
this->GetClientRect(rect);
m_hBitmap = (HBITMAP)LoadImage(NULL, strFilePath, IMAGE_BITMAP, rect.Width(), rect.Height() - 60, LR_LOADFROMFILE | LR_CREATEDIBSECTION);
Invalidate();//使窗口无效,产生WM_PAINT消息,WM_PAINT消息在消息队列的优先级低
//想让窗口立即重绘,可以sendmessage(WM_PAINT)或者
/*InvalidateRect(NULL, TRUE);*/
/*UpdateWindow();*/
/*UpdateWindow();*/
}
void CRotateBmpDlg::OnPaint()
{
if (IsIconic())
{
CPaintDC dc(this); // 用于绘制的设备上下文
{
if (IsIconic())
{
CPaintDC dc(this); // 用于绘制的设备上下文
SendMessage(WM_ICONERASEBKGND, reinterpret_cast<WPARAM>(dc.GetSafeHdc()), 0);
// 使图标在工作区矩形中居中
int cxIcon = GetSystemMetrics(SM_CXICON);
int cyIcon = GetSystemMetrics(SM_CYICON);
CRect rect;
GetClientRect(&rect);
int x = (rect.Width() - cxIcon + 1) / 2;
int y = (rect.Height() - cyIcon + 1) / 2;
int cxIcon = GetSystemMetrics(SM_CXICON);
int cyIcon = GetSystemMetrics(SM_CYICON);
CRect rect;
GetClientRect(&rect);
int x = (rect.Width() - cxIcon + 1) / 2;
int y = (rect.Height() - cyIcon + 1) / 2;
// 绘制图标
dc.DrawIcon(x, y, m_hIcon);
}
else
{
dc.DrawIcon(x, y, m_hIcon);
}
else
{
if (strFilePath.GetLength() > 4 && m_hBitmap)
{
if (m_bitmap.m_hObject)
{
m_bitmap.Detach();
}
m_bitmap.Attach(m_hBitmap);
{
if (m_bitmap.m_hObject)
{
m_bitmap.Detach();
}
m_bitmap.Attach(m_hBitmap);
CPaintDC dc(this);//构造会调用BeginPaint()和析构EndPaint(),并从消息队列中清除WM_PAINT消息。
CRect rect;
GetClientRect(rect);
CDC memDC;
memDC.CreateCompatibleDC(&dc);
BITMAP bmp;
m_bitmap.GetBitmap(&bmp);
CBitmap *pBmpOld = memDC.SelectObject(&m_bitmap);
/* int panelsize = 0;
if (bitmapinfo.bmBitsPixel < 16)
{
panelsize = pow(2, bitmapinfo.bmBitsPixel) * sizeof(RGBQUAD);
}*/
dc.StretchBlt(0, 0, bmp.bmWidth, bmp.bmHeight, &memDC, 0, 0, bmp.bmWidth, bmp.bmHeight, SRCCOPY);
memDC.SelectObject(pBmpOld);
DeleteDC(memDC);
CRect rect;
GetClientRect(rect);
CDC memDC;
memDC.CreateCompatibleDC(&dc);
BITMAP bmp;
m_bitmap.GetBitmap(&bmp);
CBitmap *pBmpOld = memDC.SelectObject(&m_bitmap);
/* int panelsize = 0;
if (bitmapinfo.bmBitsPixel < 16)
{
panelsize = pow(2, bitmapinfo.bmBitsPixel) * sizeof(RGBQUAD);
}*/
dc.StretchBlt(0, 0, bmp.bmWidth, bmp.bmHeight, &memDC, 0, 0, bmp.bmWidth, bmp.bmHeight, SRCCOPY);
memDC.SelectObject(pBmpOld);
DeleteDC(memDC);
}
else
{
CDialogEx::OnPaint();//进去OnPaint()会调用BeginPaint()和EndPaint(),并从消息队列中清除WM_PAINT消息。
}
}
}
else
{
CDialogEx::OnPaint();//进去OnPaint()会调用BeginPaint()和EndPaint(),并从消息队列中清除WM_PAINT消息。
}
}
}
OnPaint()进去了后一定要清除队列的WM_PAINT这样才不会重复响应,所以每个分支必须调用且只能调用一次CPaintDC()或者CDialogEx::OnPaint();
以上是关于OnPaint的使用,让窗口立即重绘的方法,CPaintDC的使用及各种DC的使用的主要内容,如果未能解决你的问题,请参考以下文章
WM_PAINT消息在窗口重绘的时候产生,那什么时候窗口会重绘(异步工作方式,效率更高,灵活性更强)
MFC中的Invalidate、OnDraw、OnPaint函数的作用、区别和联系?