「MFCの基礎 - 画面の描画」の版間の差分

提供:MochiuWiki : SUSE, EC, PCB
ナビゲーションに移動 検索に移動
(ページの作成:「== 概要 == MFCプログラムを作成すると画面描写に注意する必要がある。<br> 例えば、画面描写に不具合があると、画面からウイ…」)
 
(文字列「</source>」を「</syntaxhighlight>」に置換)
 
(2人の利用者による、間の4版が非表示)
32行目: 32行目:
* フォームを選択して、プロパティのメッセージからWM_CLOSEとWM_PAINTよりOnCloseイベントとOnPaintイベントを作成する。
* フォームを選択して、プロパティのメッセージからWM_CLOSEとWM_PAINTよりOnCloseイベントとOnPaintイベントを作成する。
<br>
<br>
あとは以下のようにコードをかいていきます。<br>
後は、以下のようにサンプルコードを記述する。<br>
  <source lang="c++">
  <syntaxhighlight lang="c++">
  // CDlgView.h
  // CDlgView.h
  // 下記の変数を追加する(private, public どちらでもよい)
  // 下記の変数を追加する(private, public どちらでもよい)
103行目: 103行目:
  }
  }
   
   
  void CDlg1View::OnClose()
  void CDlgView::OnClose()
  {
  {
     // TODO: ここにメッセージ ハンドラー コードを追加するか、既定の処理を呼び出します。
     // TODO: ここにメッセージ ハンドラー コードを追加するか、既定の処理を呼び出します。
112行目: 112行目:
     CFormView::OnClose();
     CFormView::OnClose();
  }
  }
  </source>
  </syntaxhighlight>
<br><br>
<br><br>


__FORCETOC__
__FORCETOC__
[[カテゴリ:MFC]]
[[カテゴリ:MFC]]

2021年11月24日 (水) 17:33時点における最新版

概要

MFCプログラムを作成すると画面描写に注意する必要がある。
例えば、画面描写に不具合があると、画面からウインドウが外れて再び表示されると途切れて描写される。
そこで、画面の再描写が必要なタイミングを知る必要がある。

MFCでは、画面の再描画のタイミングをOnPaintメソッドやOnDrawメソッドで知ることができる。


OnPaintメソッドとOnDrawメソッドの使い分け

OnPaintメソッドとOnDrawメソッドの使い分けを下記に記述する。

ダイアローグベース : OnPaintメソッド
ドキュメント・ビュークラス : OnDrawメソッド


OnPaintメソッドとOnDrawメソッドが呼ばれるタイミング

OnPaintメソッドとOnDrawメソッドが呼ばれるタイミングを下記に記述する。

  • アプリの起動時
  • 画面が隠れて再度表示する時
  • Invalidate関数、InvalidateRect関数が実行された時


画面全体を再描画させる場合はInvalidata関数を使い、指定した四角形領域だけを再描画する場合はInvalidateRect関数を使用する。


サンプルコード

ダイアローグベースのプログラムで、OnPaintメソッドを使った例を以下に記述する。
ここでは、ピクチャコントロールを塗って表示するプログラムを作成する。

  • ダイアログのコントロールにて、ピクチャコントロールとボタンを貼る。
  • ピクチャコントロールのIDをIDC_STATIC_PICT、タイプをオーナー描画とする。
  • ボタンコントロールのイベントを作成する。(OnBnClickedButtonメソッド)
  • フォームを選択して、プロパティのメッセージからWM_CLOSEとWM_PAINTよりOnCloseイベントとOnPaintイベントを作成する。


後は、以下のようにサンプルコードを記述する。

 // CDlgView.h
 // 下記の変数を追加する(private, public どちらでもよい)
 char  *m_pBuffer; // 画素データ
 CRect m_Rect;     // ピクチャコントロールのサイズ
 CDC   m_DC;       // 画面に表示する時に使用する仮想DC(一時保存)
 
 // CDlgView.cpp
 void CDlgView::OnInitialUpdate()
 {
    CFormView::OnInitialUpdate();
    GetParentFrame()->RecalcLayout();
    ResizeParentToFit();
 
    ((CStatic*)GetDlgItem(IDC_STATIC_PICT))->GetClientRect(m_Rect);
 
    // 表示画素データのメモリを確保する
    m_pBuffer = new char[m_Rect.Width() * m_Rect.Height() * 4];
    for(int i = 0; i < m_Rect.Width(); i++)
    {
       for(int j = 0; j < m_Rect.Height(); j++)
       {
          m_pBuffer[(i + j * m_Rect.Width()) * 4]     = 100;
          m_pBuffer[(i + j * m_Rect.Width()) * 4 + 1] = 100;
          m_pBuffer[(i + j * m_Rect.Width()) * 4 + 2] = 100;
        }
    }
 
    // ピクチャコントロールと同じDCを確保する
    CDC *pDC=((CStatic*)GetDlgItem(IDC_STATIC_PICT))->GetDC(); // ピクチャコントロールのDCを取得
    m_DC.CreateCompatibleDC(pDC);                              // pDCと同じDCを作成
    ((CStatic*)GetDlgItem(IDC_STATIC_PICT))->ReleaseDC(pDC);   // ピクチャコントロールのDCを解放
 }
 
 void CDlgView::OnPaint()
 {
    CPaintDC dc(this); // device context for painting
    // TODO: ここにメッセージ ハンドラー コードを追加します。
    // 描画メッセージで CFormView::OnPaint() を呼び出さないでください。
    CDC *pDC = ((CStatic*)GetDlgItem(IDC_STATIC_PICT))->GetDC(); //ピクチャコントロールのDCを取得
 
    // 画素データを読み取り、仮想DCにセットする
    CBitmap bitmap;
    bitmap.CreateBitmap(m_Rect.Width(), m_Rect.Height(), 1, 32, m_pBuffer);
    myDC.SelectObject(&bitmap);
 
    // 仮想DCからピクチャコントロールへ転送する
    pDC->BitBlt(1, 1, m_Rect.Width(), m_Rect.Height(), &m_DC, 0, 0, SRCCOPY);
 
    ::DeleteObject(bitmap);
    ((CStatic*)GetDlgItem(IDC_STATIC_PICT))->ReleaseDC(pDC);
 }
 
 void CDlgView::OnBnClickedButton()
 {
    // TODO: ここにコントロール通知ハンドラー コードを追加します。
    // m_pBufferを全て白色(255)に変更する
    for(int i = 0; i < m_Rect.Width(); i++)
    {
       for(int j = 0; j < m_Rect.Height(); j++)
       {
          m_pBuffer[(i + j * m_Rect.Width()) * 4]     = (char)255;
          m_pBuffer[(i + j * m_Rect.Width()) * 4 + 1] = (char)255;
          m_pBuffer[(i + j * m_Rect.Width()) * 4 + 2] = (char)255;
       }
    }
 
    Invalidate(); // OnPaintを呼ぶ
 }
 
 void CDlgView::OnClose()
 {
    // TODO: ここにメッセージ ハンドラー コードを追加するか、既定の処理を呼び出します。
    // DCとメモリの解放を行う
    DeleteDC(m_DC);
    delete[] m_pBuffer;
 
    CFormView::OnClose();
 }