dポイントプレゼントキャンペーン実施中!

 アニメーションするデスクトップアクセサリみたいなものを作ろうとしています。
しかし、SetWindowRgn()関数をうまく動作させる事が出来ないので質問させてください。
現在、
CRgn* _pRgns;
CBitmap* _pBitmap;
をメンバ変数として用意し、あらかじめビットマップの形をしたリージョンをフレーム枚数だけ_pRgnsに配列として作成しています。

onTimer() 関数内で、フレーム位置をインクリメントし、該当フレーム番号のビットマップとリージョンを適用後、描画させています。
この方法でアニメーションをさせた場合、ループ再生にしなければ問題なく動作するのですが、二回目のループになった時に、リージョンを再度SetWindowRgn()関数で設定すると失敗してしまいます。
(戻り値として0が帰ってきます。)

SetWindowRgn()関数の使い方がまずいのでしょうか。
ご存知の方おられましたら、教えていただけますでしょうか?
よろしくお願いします。

void TestAppDlg::OnTimer(UINT nIDEvent)
{
CString mes;

_frameNo++;
if ( _frameNo > 5 ) _frameNo = 0; // フレーム位置を先頭に戻す。

// ビットマップを選択
_pMemDC->SelectObject( _pBitmap + _frameNo );

// 非矩形ウィンドウの設定
int ret = SetWindowRgn( *(_pRgns + _frameNo), true );

if ( ret == 0 ){
// リージョンの設定に失敗
stopTimer();
}
// 描画
drawScene() ;
CDialog::OnTimer(nIDEvent);
}

開発環境:
Windows XP Professional SP1
Microsoft Visual C++ .NET

A 回答 (2件)

重要なことを思い出しました。


おそらく、アニメーションの一巡目までは正常終了ということなので次の理由でしょう。


SetWindowRgn()は成功すると引数で指定されたリージョンは、Windowsによって管理が行われるようになります。
#これにより、ウィンドウに設定したリージョンは破棄が不要となります。

そのため、何度も同じリージョンを使いまわして設定しようとしても、2回目以降は失敗します。

これを避けるには、SetWindowRgn()を呼ぶ前に、リージョンをコピーし、配列に入っているリージョンではなく、コピーしたリージョンをパラメータに設定する必要があります。
    • good
    • 0
この回答へのお礼

回答ありがとうございます。
早速試してみたところ、問題なく動作致しました。
アドバイスありがとうございました。

お礼日時:2004/07/27 18:01

第2引数はBOOL型なので、trueではなくTRUEを指定してください。



また、CWnd::SetWindowRgn()は内部でAPIを呼び出しているだけなので、NT系のOSならGetLastError()で詳細エラーを取得して調べてみてください。

あと怪しそうなのは、リージョンの作成方法ですかね。
コードがかかれていないのでわかりませんが。

この回答への補足

回答ありがとうございます。

早速、ご指摘いただいた箇所を改めました。
以下のコードを追加し、取得できたエラー文字列は、
『この操作を正しく終了しました。』でした。
ちなみに、エラーコード自身は0です。

// 非矩形ウィンドウの設定
int ret = SetWindowRgn( *(_pRgns + _frameNo), TRUE );

if ( ret == 0 ){
 FormatMessage( FORMAT_MESSAGE_FROM_SYSTEM |
         FORMAT_MESSAGE_IGNORE_INSERTS,
         NULL, GetLastError(), 0,
         ErrorMes, 1024, NULL);
 // リージョンの設定に失敗
 stopTimer();
}

リージョンの作成部分ですが、以下のような処理を行っています。

bool TestAppDlg::createRgn()
{
 unsigned char r, g, b;
 unsigned char* buff;
 COLORREF WHITE = RGB( 255, 255, 255 );

 _pRgns = new CRgn[ BITMAP_NUM ];
 if ( _pRgns == NULL ) return false;

 int bitSize = IMAGE_WIDHT * IMAGE_HEIGHT * 4;
 buff = new unsigned char[ bitSize ];

 // フレーム数分、リージョンを作成する。
 for ( int i=0; i<BITMAP_NUM; i++ ){
  memset( buff, '\0', sizeof(buff) );
  (_pBitmap + i)->GetBitmapBits( bitSize, buff );

  (_pRgns + i)->CreateRectRgn( 0, 0, 0, 0 );

  for( int y = 0; y < IMAGE_HEIGHT; y++ ){
   for( int x = 0; x < IMAGE_WIDHT; x++ ){
    int inx = (y * IMAGE_WIDHT) + x;
    COLORREF color = RGB(buff[ 4*inx ], buff[ 4*inx+1 ], buff[ 4*inx+2 ] );
    if ( color != WHITE ){
     CRgn rgn;
     rgn.CreateRectRgn( x, y, x + 1, y + 1 );
     (_pRgns + i)->CombineRgn( (_pRgns + i), &rgn, RGN_OR );
    }
   }
  }
 }
 delete[] buff ;
 return true ;
}

以上、何かお気づきの点がございましたらご教示ください。

補足日時:2004/07/27 14:51
    • good
    • 0

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!