MFCでウィンドウ枠をアニメーションさせる方法

このQ&Aのポイント
  • VC++初心者の方がMFCでデスクトップマスコットを作成中です。現在、BMP画像の表示はC***ViewクラスのOnDraw関数で行っています。しかし、ウィンドウ枠の作成に問題があり、リージョンを使ってBMP画像の形のウィンドウを作成する方法を知りたいとのことです。また、OnDraw関数内でのSetWindowRgn関数の動作もうまくいっていないそうです。
  • CTestViewクラスのコンストラクタでは、ビットマップの読み込みとリージョンの設定が行われています。OnDraw関数内では、画像の表示とリージョンの切り替えが行われていますが、SetWindowRgn関数が正常に動作していないようです。
  • 質問者さんは、ウィンドウ枠をアニメーションさせたいというニーズを持っています。現在MFCを使用してデスクトップマスコットを作成中で、BMP画像の表示はOnDraw関数で行っていますが、ウィンドウ枠の作成に問題があります。具体的には、リージョンを使ってBMP画像の形のウィンドウを作成する方法が分からないため、質問をしています。また、SetWindowRgn関数の動作もうまくいっていないため、助けが必要だとのことです。
回答を見る
  • ベストアンサー

MFCでウィンドウ枠をアニメーションさせたい

こんにちは、VC++初心者です。 今MFCでデスクトップマスコットを作りたいと思っています。 MFCのSDIアプリでとりあえず作成している最中で、 BMP画像の表示はC***ViewクラスのOnDraw関数で表示させています。 問題はウィンドウ枠です。 スタイル指定をWS_POPUPにして、クライアント領域にのみ表示させていますが、 リージョンを使って、BMP画像を切り取った形のウィンドウにするのにてこずっています。 ちうか、そもそもOnDraw関数内でBMP表示とともに行っている、 SetWindowRgn関数がうまく動いてくれていない状態です(泣)。 ソースの一部をのせておきますで、どうかご判断ください。 宜しくお願いします。 CTestView::CTestView() { //コンストラクタでビットマップの読み込みとリージョンの設定 gazou.LoadBitmap( IDB_GAZOU); //CBitmapのメンバ変数 m_rgn[0].CreateEllipticRgn(0, 0, 48,48); //CRgnのメンバ変数1 m_rgn[1].CreateRectRgn(0, 0, 48,48); //CRgnのメンバ変数1 } void CTestView::OnDraw(CDC* pDC) { //画像表示及びリージョンの切り替え 中略... static int anim = 0; CDC dc; dc.CreateCompatibleDC( pDC); dc.SelectObject( gazou); pDC->BitBlt(0,0,48,48,&dc,0,0,SRCAND); //48*48ドットのBMP HRGN hrgn =(HRGN)m_rgn[anim].Detach(); SetWindowRgn( hrgn, true); dc.DeleteDC(); anim ^= 1; 中略... }

質問者が選んだベストアンサー

  • ベストアンサー
  • akinori_s
  • ベストアンサー率60% (21/35)
回答No.1

参考になるか分かりませんが昔似たようなものを作った時は 下記のようにしました 1.ダイアログベースで作成 2.OnInitDialogでSetWindowRgn/Timer設定 3.OnTimerでSetWindowRgn/リペイント 4.OnPaintで画像の表示 ってな感じでした。 SDIで作る場合にはViewの親ウィンドウのCMainFrameに対してもSetWindowRgnを行わないといけない気がします(自信ないですが・・・) あとOnDraw内でSetWindowRgnを行うのもあまりよくない気がします。

amoban
質問者

お礼

お答えありがとうございます。 あと、お返事が送れて、申し訳ありませんでした(ぺこり)。 SDIだとCMainFrameにもSetWindowRgnしないといけないというのは、 わかるようなきがします。(まだ試していませんが) やはり、ダイアログベースで作成しようかと思います。 それと、あるサンプルソースが手元にありますが、 私がVC++初心者ということもあり、それがダイアログで作られたのかどうか、 確かめるのにどうすればいいのかよくわかりません。 たとえば、「TEST」というプロジェクトで「TESTDLG.CPP」が作られていれば、 ダイアログベースで作成されたと思っていいのでしょうか? あつかましくお尋ねしてすみませんが、 よろしくお願いします。

その他の回答 (1)

  • akinori_s
  • ベストアンサー率60% (21/35)
回答No.2

>たとえば、「TEST」というプロジェクトで「TESTDLG.CPP」が>作られていれば、 >ダイアログベースで作成されたと思っていいのでしょうか? そうとも言えますけど、実際にはCWinApp::InitInstanceで ダイアログクラスを生成/表示していればダイアログベース なんじゃないでしょうか。

amoban
質問者

お礼

お答え、ありがとうございます。 そもそものアプリの構造を把握していないのは致命的ですね(汗)。 MFCの勉強をしつつ、目的のアプリを作れるよう頑張ってみますね。 お答え、本当に参考になりました。 ありがとうございました。

関連するQ&A

  • MFC VC++ 6.0 使用 

    CModel::OnDraw(CDC *pDC) { pDC->TextOut(0,0,"OK"); } というふうに OnDrawの中で pDC->TextOut()と 使って 実行画面に 文字を表示させることは できるのですが、例えば 自分が 追加した 関数 void CModel::On_Distance(){ } などで、実行画面に 文字をだしたいときは どうすればいいのでしょうか?pDC を 手に入れることが できるのであれば そのほうほう 教えてください。

  • MFC VC++ 6.0 使用 

    class patchmodel{ double a; double b; private: void Draw(); } void patchmodel::Draw(){ CDC DC; CDC* dc = GetDC(); dc->TextOut((int)a,(int)b,"HELLO"); ReleaseDC( dc ); } と 実行してみたところ エラーがでます。 error C2660: 'GetDC' : 関数が不正な 0 個の実引数をともなって呼び出されました。 error C2660: 'ReleaseDC' : 関数が不正な 1 個の実引数をともなって呼び出されました。 CModel::OnDraw(CDC* pDC) を あえて使わずに 実行したいので このように 簡単なもので 試して見たのですが、うまくいきません。 GetDC の使い方を まちがえているのでしょうか? お返事ください。

  • ダイアログアプリのウィンドウ領域について

    いつもお世話になります。 VC++6.0MFCダイアログベースでアプリを開発しているのですが、 ビットマップ画像(100×100)をダイアログに貼り付けています。 円の画像ですが、ビットマップなので四角の画像になっています。 そこで楕円のリージョンを作って、 // 楕円のリージョンを作る m_rgn.CreateEllipticRgn(0,0,100,100); // ウィンドウのリージョンを設定する SetWindowRgn((HRGN)m_rgn ,TRUE); こんな感じで表示したらウィンドウは丸くなっています。 そこで上記で作成したリージョンの上をマウスがオーバーしたら 画像を差し替えたいのですが、どうしても、ダイアログ の領域(四角)で反応してしまいます。 CPoint pos; CRect rect; GetCursorPos(&pos); GetWindowRect(&rect); if (rect.PtInRect(pos)) { // マウスが上に来ている m_bMouseOver = TRUE; } else { // マウスは上にはない m_bMouseOver = FALSE; } こんな感じでm_bMouseOverの中身を見て画像を差し替えています。 リージョンで作成した楕円の上だけで反応させるには どのようにすればいいのでしょうか? わかりにくいかもしれませんがアドバイスよろしくお願い致します。

  • オブジェクトの削除について

    環境 WIN98 VC++6.0 MFC にて オブジェクトを使い終わってから削除している場合としていない場合が有るのですが、どうしてなのですか? 作ったオブジェクトはなんでもかんでも削除したほうが無難な気がしますが、本にのっているコードで削除してない場合も良く見かけます。 <削除していない>//著名な本のコード void Cxxx::OnDraw(CDC* pDC) {  CBitmap bmp;  bmp.LoadBitmap(nID);  略  //bmp.DeleteObject(); //■この記述が無い } <削除している>//ネット上でみかけたコード void CMainFrame::_SetBmp(CWnd* pBox,int nID,int  width,int height) // 単品 {  CDC* pDC=pBox->GetDC();  CDC memDC;  CBitmap bmp;  bmp.LoadBitmap(nID);  memDC.CreateCompatibleDC(pDC);  CBitmap* pOldBmp=memDC.SelectObject(&bmp);  pDC->BitBlt(0,0,width,height,&memDC,0,0,SRCCOPY);  memDC.SelectObject(pOldBmp);  bmp.DeleteObject();  memDC.DeleteDC(); }

  • CFromViewの OnDrawメソッドについて

    MFC初心者です。VC2005でグラフィックスに挑戦しております。 まだよくクラスとか、MFCの作法などしらないのでトンチンカンな質問をしますが、 ドキュメント(で正しいでしょうか?)がCViewクラスの場合、 OnDraw(CDC* pDC)が定義されていたので、直接そこに描画コードを書きましたが、 CFromViewクラス(コントロール可能)の場合、 OnDraw(CDC* pDC)が見当たりませんので、定義にvoid OnDraw(CDC* pDC)を追加し、 以下のようにメソッドを追加して、無理やり表示させました。 この方法は普通でしょうか? void CtestView::OnDraw(CDC* pDC) { CBrush myBrush; CBrush* pOldBrush; myBrush.CreateSolidBrush(RGB(255,0,0)); // ソリッドブラシの作成 pOldBrush = pDC->SelectObject(&myBrush); // myBrushを選択 pDC->Ellipse(60,10,160,110); pDC->SelectObject(pOldBrush); // 元に戻す myBrush.DeleteObject(); // ブラシを削除 } //--------------------------------------------------- 以下クラス定義部 class CtestView : public CFormView { protected: // シリアル化からのみ作成します。 CtestView(); DECLARE_DYNCREATE(CtestView) public: enum{ IDD = IDD_test_FORM }; // 属性 public: CtestDoc* GetDocument() const; // 操作 public: // オーバーライド public: virtual BOOL PreCreateWindow(CREATESTRUCT& cs); protected: virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV サポート virtual void OnInitialUpdate(); // 構築後に初めて呼び出されます。 // 実装 public: virtual ~CtestView(); #ifdef _DEBUG virtual void AssertValid() const; virtual void Dump(CDumpContext& dc) const; #endif void OnDraw(CDC* pDC); /////////////////////////// ←勝手に追加 protected: // 生成された、メッセージ割り当て関数 protected: DECLARE_MESSAGE_MAP() }; #ifndef _DEBUG // testView.cpp のデバッグ バージョン inline CtestDoc* CtestView::GetDocument() const { return reinterpret_cast<CtestDoc*>(m_pDocument); } #endif

  • MFCのタイマーのつかい方を教えてください

    タイマーのつかい方が今ひとつ分かりません。 MFCでタイピングのゲームを作成しているのですが、 25問を解き、正解だった場合もしくは制限時間を超えてしまった場合、次の問題を表示したいと思っております。 下記がプログラム内容です。 void CProgramView::Loop1(CDC* pDC) { CProgramDoc* pDoc = GetDocument(); ASSERT_VALID(pDoc); if((m_nRight<26)|(0<m_nRight)) { m_nRight=0; //正解数 m_nQuestion=1; //問題数 } Haikei(pDC); //問題表示領域の枠表示 Tokei(pDC); //時計の秒針が表示される枠表示 Moji(pDC); //問題文表示 OnChar(ch, count,flags); //入力 if(m_fTimer==FALSE) { SetTimer(123,250,NULL); //タイマーをセット if(m_nQuestion<26) //25問以上問題を解いていないケース { m_fTimer = FALSE; } else m_fTimer = TRUE; //全問解いた場合 } Loop0(pDC); //秒針の描画クラス if(m_nx==715) //タイムアウトだった場合 { KillTimer(123); NGPaper(pDC); m_nQuestion++; //問題をカウント m_sAnser.Empty(); //回答文字列をクリア pDoc->GetNextSet(); //次の問題を取得する InvalidateRect(NULL); } if(m_nQuestion<m_nCount) //正解だった場合 { KillTimer(123); //タイマーを切る Tokei(pDC); //秒針の画像を消すために時計の画面を再描画 Right(pDC); //正解した場合の画像を描画 Haikei(pDC); //問題文・回答を消すために問題表示領域の枠を再描画 PartsPaper1(pDC); //正解した場合の壁紙を表示 m_nQuestion++; //問題数をカウント m_sAnser.Empty(); //回答文字列をクリアする pDoc->GetNextSet(); //次の問題を取得する InvalidateRect(NULL); } } そして、この動作を25問、解くまでループさせる関数として以下の関数を作成しました。 void CProgramView::Loop2(CDC* pDC) { if(m_fTimer==FALSE) { Loop1(pDC); } } //タイマーの内容 void CProgramView::OnTimer(UINT nIDEvent) { // TODO: この位置にメッセージ ハンドラ用のコードを追加するかまたはデフォルトの処理を呼び出してください if(nIDEvent == 123) { InvalidateRect(NULL); } CView::OnTimer(nIDEvent); } しかし、実際にこのプログラムを実行すると入力し、正解する間は次の問題が表示されるのですが、タイマーが切れません。 そして、制限時間になるとそこまで解いていた問題から凄い勢いで描画が始まり、止まりません。 おそらくタイマーが正常に使えていないという可能性が考えられるのですが・・・。 希望としては、25問を順次解き、解き終わった後は画像を描画し、次の問題を表示したいのですが、どうしたら良いか教えてください。

  • MFCで画像を表示させているのですが、透過表示する方法がわかりません。

    VC2005のMFCで画像を表示させているのですが、透過表示する方法がわかりません。 OnDraw(CDC* pDC) で、#include <atlimage.h>として、 CImage img; img.Load( "test.gif" ); CDC* pDCImg = CDC::FromHandle( img.GetDC() ); pDC->BitBlt( 60, 10, img.GetWidth(), img.GetHeight(), pDCImg, 0, 0, SRCCOPY ); img.ReleaseDC(); すればGIF画像が表示されましたが、このGIG画像は透過GIFですが そのまま表示されているので、背景が黒の場合透、明部分の白が見えて 四角い枠の画像となります。 GIF透過ファイルの場合、そのまま透過になる方法や、何か手段を用いて透過をさせたいです。

  • VC++2010(MFC)OnDraw以外での描画

    xxxView.cppファイル内のOnDraw以外の部分で、以下のコードを書きビルドしましたが、「'CWnd::GetDC' : 静的でないメンバー関数の呼び出しが正しくありません」というエラーと「'CWnd::ReleaseDC' : 関数に 0 個の引数を指定できません」というエラーが出てしまい、描画できません。エラーの出ない、正しいコードを教えて下さい。 CPaintDC* pDC; CWnd::GetDC(); pDC->TextOut(10,10,"テスト"); CWnd::ReleaseDC();

  • for文の処理に時間がかかっているか。MFC VC++ 6.0 使用

    今 私は MFC VC++ 6.0 を使用しています。 CModel::OnDraw(CDC *pDC) { (略) (ここから) for(int i=0;i<500000;i++){ なんらかの アルゴリズム } (ここまで) (略) } 上記に示した (ここから) (ここまで)に ドレくらい時間がかかっているか 時間を 計りたいのです。 かかったじかんを pDC->TextOut(・・・・・) と 画面に 表示させたいのですが、どうすればいいでしょうか? 参考書には 今の 時間(4時12分) などの現在の時刻を 表示させるものは 結構のってるのですが、私は 時刻ではなく for文を処理している 時間を しりたいのです。よければ 教えてください。

  • MFC XPでのTextOutのボヤケについて

    はじめまして。 質問させてください。 CImageを使用して OnPaint( )でBMP画像を描画するアプリを作成しております。 仕様といたしまして ダイアログのDC部にBMPを全体に描画して RGB( 255, 255, 255 )を透明化(背景が完全に見える)する ようにしております。 OnInitDialog( )で透過、透明処理をしています。 OnPaint( )で PaintDC PDC; //背景を透過 PDC.SetBkMode( TRANSPARENT ); PDC.SetTextColor( RGB( 255, 0, 0 ) ); PDC.SetBkColor( RGB( 255, 255, 255 ) ); PDC.TextOutW( 100, 100, _T( "TEST" ) ); 上記のように実装して、EXEで実行して確認しますと Windows2000の場合、正常に文字(TEST)が赤字で描画されるのですが WindowsXPの場合、赤字で描画されるのですが文字の周りがぼやけてしまいます。 イメージとしては文字描画部分が 2000の場合、BMP表示 XPの場合、JPG表示 のようになります。 これは仕様なのでしょうか? それとも何かコードレベルで解決できるのでしょうか? お詳しい方がおりましたらご教授お願いいたします。 よろしくお願いいたします。

専門家に質問してみよう