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

Win32APIでタイマーを作成しましたが
時間は正しく表示されましたが画面がチカチカしてしまいます
これを防止するにはどうすればよろしいのでしょうか?

よろしくお願いします

A 回答 (3件)

#include <windows.h>



/* このファイルで使用する定数 */
#define CASE   break;case
#define DEFAULT break;default
#
#define MAX_WIDTH (500) // 画面の横サイズ
#define MAX_HEIGHT (300) // 画面の縦サイズ
#define TID_CLOCK (9868) // タイマーID
#define TID_CYCLE (10)  // タイマー間隔

//ウィンドウプロシージャ
LRESULT CALLBACK WndProc( HWND hWnd, UINT msg, WPARAM wp, LPARAM lp )
{
 static HFONT hFont; // フォント
 static HDC  hMemDC; // メモリデバイスコンテキスト
 static HBITMAP hMemBMP; // ビットマップ
 
 switch ( msg ){
  CASE WM_CREATE:
  {
   HDC hDC;
   
   if ( (hDC = GetDC(hWnd)) != NULL ){
    // メモリデバイスコンテキストを作成
    hMemDC = CreateCompatibleDC( hDC );
    hMemBMP = CreateCompatibleBitmap( hDC, MAX_WIDTH, MAX_HEIGHT );
    SelectObject( hMemDC, hMemBMP );
    
    // メモリデバイスコンテキストの背景を真っ白に描画
    SelectObject( hMemDC, GetStockObject(NULL_PEN) );
    SelectObject( hMemDC, CreateSolidBrush(RGB(0xFF,0xFF,0xFF)) );
    Rectangle( hMemDC, 0, 0, MAX_WIDTH, MAX_HEIGHT );
    DeleteObject( SelectObject(hMemDC,GetStockObject(WHITE_BRUSH)) );
    
    // 解放
    ReleaseDC( hWnd, hDC );
   }
   hFont = create( 23, SHIFTJIS_CHARSET, TEXT("HGS明朝E") );
   SetTimer( hWnd, TID_CLOCK, TID_CYCLE, NULL );
  }
  CASE WM_CLOSE:
  {
   LPCTSTR lpTitle = TEXT("確認");
   LPCTSTR lpText = TEXT("終了してもよろしいですか");
   UINT uStyle = (MB_YESNO | MB_ICONQUESTION);
   
   if ( MessageBox(hWnd,lpText,lpTitle,uStyle) == IDYES ){
    if ( !KillTimer(hWnd,TID_CLOCK) ){
     MessageBox( hWnd, TEXT("KillTimerエラー"), TEXT("エラー"), MB_OK | MB_ICONQUESTION );
    }
    DestroyWindow( hWnd );
   }
  }
  CASE WM_DESTROY:
   DeleteObject( hFont );
   DeleteObject( hMemBMP );
   DeleteDC( hMemDC );
   PostQuitMessage( 0 );
  CASE WM_TIMER:
  {
   static LPCTSTR lpString1 = TEXT("プログラム開始時刻/または更新時刻は");
   static LPCTSTR lpString2 = TEXT("でした左クリックで更新");
   TCHAR szBuff[ 256 ];
   SYSTEMTIME st;
   
   // 時間取得と文字列作成
   GetLocalTime( &st );
   wsprintf( szBuff, TEXT("%02d:%02d:%02d.%03d"),
    st.wHour, st.wMinute, st.wSecond, st.wMilliseconds );
   
   // メモリデバイスコンテキストに描画
   SelectObject( hMemDC, hFont );
   TextOut( hMemDC, 100, 10, lpString1, lstrlen(lpString1) );
   
   SetTextColor( hMemDC, RGB(0,23,200) );
   TextOut( hMemDC, 150, 70, szBuff, lstrlen(szBuff) );
   
   SetTextColor( hMemDC, RGB(0,0,0) );
   TextOut( hMemDC, 185, 130, lpString2, lstrlen(lpString2) );
   
   // 再描画の指示(更新リージョンの追加)
   InvalidateRect( hWnd, NULL, FALSE );
  }
  CASE WM_PAINT:
  {
   PAINTSTRUCT ps;
   HDC hDC;
   
   // メモリ・デバイスコンテキストを画面のデバイスコンテキストに転送
   hDC = BeginPaint( hWnd, &ps );
   BitBlt( hDC, 0, 0, MAX_WIDTH, MAX_HEIGHT, hMemDC, 0, 0, SRCCOPY );
   EndPaint( hWnd, &ps );
  }
  CASE WM_LBUTTONDOWN:
   SendMessage( hWnd, WM_CLOSE, 0, 0 );
  DEFAULT:return DefWindowProc( hWnd, msg, wp, lp );
 }
 return 0;
}
    • good
    • 0
この回答へのお礼

説明、アドバイスありがとうございました。
ゲームのちらつき防止でパッときました(DxLibで体験しました)
ウィンドウプロージャのソース丸ごとつけてもらって助かりました。

お礼日時:2007/06/05 03:14

★アドバイス


・タイマー間隔が 10ms ですね。
 これって 1 秒間に最大 100 回の描画が行われることになります。
 普通にデバイスコンテキストに描画してしまうと間違いなく『ちらつき』ます。
・解決策はメモリ・デバイスコンテキストを用意してそこに描画します。
 そして WM_PAINT でメモリ・デバイスコンテキストの内容を画面のデバイスコンテキストに
 BitBlt() 関数などで転送します。この方法ならば『ちらつき』が発生しません。
 なお、このような方法はダブルバッファなどと呼ばれているものです。
 ゲームではお馴染みです。『ちらつき』を発生させない基本です。
・サンプルを次の回答で載せておきます。どうぞ。

その他:
・KillTimer() 関数は BOOL 型なので論理反転を使って判定した方が良いと思います。0 で比較するよりは。
 InvalidateRect() 関数の第3引数は FALSE にします。TRUE にすると『ちらつき』ます。
 メモリ・デバイスコンテキストをそのまま画面のデバイスコンテキストに転送しているので
 FALSE にしてかまいません。
・あと WM_TIMER の部分で今まで WM_PAINT で記述していた描画処理を記述します。
 今までは hDC に描画していましたが、メモリ・デバイスコンテキスト(hMemDC)に描画します。
 描画の方法は同じです。hDC→hMemDC にするだけです。
・あと strlen() ではなく lstrlen() 関数を使って下さい。strlen() は C関数のランタイムです。
 Win32 API では lstrlen、lstrcmp、lstrcpy、lstrcat などの関数群が用意されています。
・以上。参考に!
    • good
    • 0

★アドバイス


・スタティック・コントロールを文字列を1秒間に数回表示させるとチラツキます。
 でも、よく分かりませんのでソースを貼り付けて下さい。
・その後にアドバイスします。→プロシージャ関数の重要な部分のみでよい。

この回答への補足

//ウィンドウプロシージャ
LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wp, LPARAM lp)
{
static HFONT hFont;
static char jikan[64];
HDC hdc;
PAINTSTRUCT ps;
SYSTEMTIME st;
int id;


switch (msg)
{
case WM_CREATE:
SetTimer(hWnd , 9868 , 10 ,NULL);
hFont=create(23,SHIFTJIS_CHARSET,"HGS明朝E");
break;
case WM_TIMER:
GetLocalTime(&st);
wsprintf(jikan,"%d時%d分%d秒%d",st.wHour,st.wMinute,st.wSecond,st.wMilliseconds);
InvalidateRect(hWnd , NULL , true);
break;
case WM_LBUTTONDOWN:
SendMessage(hWnd , WM_CLOSE , 0 , 0);
break;
case WM_PAINT:
hdc=BeginPaint(hWnd , &ps);
SelectObject(hdc , hFont);
TextOut(hdc ,100 , 10 , "プログラム開始時刻/または更新時刻は" , 36);
SetTextColor(hdc , RGB(0, 23, 200) );
TextOut(hdc ,150 , 70 , jikan , (int)strlen(jikan));
SetTextColor(hdc , RGB(0, 0 , 0) );
TextOut(hdc ,185 , 130 , "でした左クリックで更新" , 22);
EndPaint(hWnd , &ps);
break;
case WM_CLOSE:
id = MessageBox(hWnd,
TEXT("終了してもよろしいですか"),TEXT("確認"),
MB_YESNO | MB_ICONQUESTION);
if (id == IDYES)
{
if(KillTimer(hWnd , 9868)==0){
MessageBox(hWnd , "KillTimerエラー" , "エラー", MB_OK | MB_ICONQUESTION);
}
DestroyWindow(hWnd);
}
break;
case WM_DESTROY:
DeleteObject(hFont);
PostQuitMessage(0);
break;
default:
return (DefWindowProc(hWnd, msg, wp, lp));
}
return 0;
}

ソースはりつけました。お願いします

補足日時:2007/06/04 01:23
    • good
    • 0

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