Assertion Failed! -22ページ目

[BMP]ビットマップ表示

ビットマップを表示する


[作成環境]

・Visual Studi 2008 Standart Edition

・MFC-ダイアログベース


Assertion Failed!

※ 使われている題材はあまり気にしないでください。



簡単のため、全てOnPaint()関数内で処理します。

必要な情報は適当にクラス化などして。


void CSampleDlg::OnPaint()
{
  if (IsIconic())
  {
    ・・・中略

  }
  else
  {
    CDialog::OnPaint();


    // 描画するビットマップをロードし、ハンドル取得

    HBITMAP hbmp = (HBITMAP)LoadImage(0,
                               _T("C:\\sample.bmp"),
                               IMAGE_BITMAP,
                               0,
                               0,
                               LR_LOADFROMFILE);


    // 取得したビットマップハンドルからビットマップオブジェクトを生成

    CBitmap *bmp = bmp->FromHandle(hbmp);


    // デバイスコンテキスト取得

    CDC *pDC = GetDC();

    

    // メモリデバイスコンテキストを作成

    CDC dcMem;
    dcMem.CreateCompatibleDC(pDC);


    // メモリDCにビットマップオブジェクトを割り当てる

    // (元のオブジェクトも保持)

    CBitmap *old = dcMem.SelectObject(bmp);


    // メモリDCからDCへ、ビットマップをコピー

    pDC->BitBlt(0,

             0,

             500,

             500,

             &dcMem,

             0,

             0,

             SRCCOPY);


    // 元のビットマップオブジェクトに戻し、各DC、オブジェクトを破棄

    dcMem.SelectObject(old);

    bmp->DeleteObject();
    old->DeleteObject();
    dcMem.DeleteDC();

    ReleaseDC(pDC);
  }
}

[用語]デバイスコンテキスト

デバイスコンテキスト(DC)


デバイス(ディスプレイとかプリンタとか)に依存しないで

描画を行うためのWindowsのデータ構造体。


いわゆる、プログラムとデバイスの中継ぎのようなもの。


このDCに描画のためのオブジェクトをもたせることで、

実際にデバイスへの描画が可能になっている(多分)。


描画のためのオブジェクトは基本、以下の6つ。


 CPen

 CBrush

 CBitmap

 CFont

 CPalette

 CRgn


メモリデバイスコンテキスト(メモリDC)


上記のDCに対して、デバイスとのつながりが切り離されたもの。

なので、メモリ上にのみ存在し、描画されるということはない。


リアルタイムで常に画像が更新される処理なんかだと、

画面のちらつきや、ティアリングのようなものがおこるのだと思われる。(未確認)


バックグラウンドで次に必要が画像を用意し、更新処理時に

一気に画像をメモリDCからDCに送ってやることでちらつきを防ぐ。


コレもまた多分だけど、バックグラウンドでの画像処理に時間がかかるのであれば

今度は当然更新処理が遅くなるという事体が発生するのではないでしょうか。

[MFC]タイマー処理

特定時間経過したらメッセージが投げられ、

それを受け取るメッセージハンドラ。


メッセージは WM_TIMER


WM_TIMERからOnTimer()というメッセージハンドラが

作成されるので、この中にタイマー満了時の処理を

書けばよい。


例えば時計などのとき、リアルタイムに描画を

更新したいときは次のようにすればおk。


void CClockDlg::OnTimer(UINT_PTR nIDEvent)
{
  if(nIDEvent == 123) //受け取ったメッセージIDのときのみ描画更新
  {
    InvalidateRect(NULL);
  }
  CDialog::OnTimer(nIDEvent);
}


InvalidateRect()関数で自分自身に描画更新のメッセージを投げる。

とっても便利。

第2引数はデフォルトでTRUEだけど、FALSEを与えると背景の更新は行わない。


ダイアログベースのアプリだと、OnPaint()関数に処理が移る。



タイマーを起動させるには、SetTimer()関数を使う。


/*

第1引数:タイマーID

第2引数:タイマー時間(ms)

第3引数:調べてないから不明。基本NULL

*/

SetTimer(123, 500, NULL);


タイマーは起動したら動き続けるので、

動作を完了させるために KillTimer()関数を使う。


/*

第1引数:タイマーID

*/

KillTimer(123);


多分使う機会は結構あるのではないかと思う。

[日記]忘年会

新しい会社の忘年会。


ほとんど名前も知らない人ばっかりなので終始困る。


そもそも自分が今の会社に内定もらえたのは奇跡らしい。


ポテンシャルのみの採用。


やっぱり。



ちなみにフグをはじめて食べた。


高級といわれる料理は基本的にうまくない。

[MFC]背景色の設定2

昨日 に続いてこんなやり方もあった。

こっちのほうがよいと思う。


・ダイアログクラスにCBrushクラスのメンバ変数を持たせる。

・OnInitDialogで以下のように初期化


BOOL CSampleDlg::OnInitDialog()
{

 ・・・
 // TODO: 初期化をここに追加します。
 m_Brush.CreateSolidBrush(RGB(0,0,0));

 return TRUE; // フォーカスをコントロールに設定した場合を除き、TRUE を返します。
}


HBRUSH CSampleDlg::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor)
{
 HBRUSH hbr = CDialog::OnCtlColor(pDC, pWnd, nCtlColor);

 // TODO: ここで DC の属性を変更してください。
 switch(nCtlColor)
 {
 case CTLCOLOR_DLG:
  return (HBRUSH )m_Brush;

 default:
  break;
 }
 // TODO: 既定値を使用したくない場合は別のブラシを返します。
 return hbr;
}