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
 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 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;
}
CRotateBmpDlg::~CRotateBmpDlg()
{
 /*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消息在消息队列的优先级低
//想让窗口立即重绘,可以sendmessage(WM_PAINT)或者
/*InvalidateRect(NULL, TRUE);*/ 
 /*UpdateWindow();*/
}
 
void CRotateBmpDlg::OnPaint()
{
 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;
  // 绘制图标
  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);
   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);
  }
  else
  {
   CDialogEx::OnPaint();//进去OnPaint()会调用BeginPaint()和EndPaint(),并从消息队列中清除WM_PAINT消息。
  }
 }
}
OnPaint()进去了后一定要清除队列的WM_PAINT这样才不会重复响应,所以每个分支必须调用且只能调用一次CPaintDC()或者CDialogEx::OnPaint();

以上是关于OnPaint的使用,让窗口立即重绘的方法,CPaintDC的使用及各种DC的使用的主要内容,如果未能解决你的问题,请参考以下文章

WM_PAINT消息在窗口重绘的时候产生,那什么时候窗口会重绘(异步工作方式,效率更高,灵活性更强)

MFC中的Invalidate、OnDraw、OnPaint函数的作用、区别和联系?

Qt重绘机制

mfc中,我想把自己的图片显示在窗口中,一定要在wm_paint重绘中实现??

当设备方向改变时导致子视图重绘的正确方法是啥?

基于c#的双缓冲技术画图