黒い玉がウィンドウの壁で跳ね返りながら動くプログラムです。
書籍のコードを改造してダブルバッファで描画させることで、ちらつきを無くしたいです。
しかし、相変わらずちらつきが起きます。ティアリングではないと思います。(瞬きするようにちらつく)
原因が分かりませんでした。
ディスプレイのリフレッシュに合うような書き方をしなくてはいけないのでしょうか?
そもそもダブルバッファになっていないかもしれません。お願いします。
#include <windows.h>
#define APP_NAME TEXT("Sample_MainWindow")
#define ELLIPSE_SIZE 50 //玉の直径
LRESULT CALLBACK WindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam){
HDC hdc;
PAINTSTRUCT ps;
static RECT rect; //ウィンドウサイズを格納するRECT
static POINT pt; //玉の位置
static BOOL xIncrease, yIncrease; //玉の跳ね返り用フラグ
static HDC hSecondDC; //裏画面用HDC
static HBITMAP hSecondBmp; //裏画面用HBITMAP
switch(uMsg){
case WM_DESTROY:
DeleteDC(hSecondDC);
DeleteObject(hSecondBmp) ;
PostQuitMessage(0);
return 0;
case WM_CREATE:
SetTimer(hWnd, 1, 20, NULL); //タイマーセット 20ms毎にWM_TIMERが発生する
GetClientRect(hWnd, &rect);
hdc = GetDC(hWnd);
hSecondDC = CreateCompatibleDC(hdc); //メインウィンドウと互換性のあるデバイスコンテキストをメモリ上に生成
hSecondBmp = CreateCompatibleBitmap(hdc, rect.right, rect.bottom); //裏画面用のビットマップを生成
ReleaseDC(hWnd, hdc);
SelectObject(hSecondDC, hSecondBmp);
return 0;
case WM_TIMER:
if(xIncrease) pt.x++; //玉の動きを計算
else pt.x--; //ウィンドウの端にぶつかると
//跳ね返る
if(yIncrease) pt.y++; //
else pt.y--; //
//
if(pt.x + ELLIPSE_SIZE > rect.right) xIncrease = FALSE; //
else if(pt.x < 0) xIncrease = TRUE; //
if(pt.y + ELLIPSE_SIZE > rect.bottom) yIncrease = FALSE; //
else if(pt.y < 0) yIncrease = TRUE; //
SelectObject(hSecondDC, GetStockObject(WHITE_BRUSH)); //裏画面を白で塗りつぶす
Rectangle(hSecondDC, 0, 0, rect.right, rect.bottom); //
SelectObject(hSecondDC, GetStockObject(BLACK_BRUSH)); //玉を黒で描画する
Ellipse(hSecondDC, pt.x, pt.y, pt.x + ELLIPSE_SIZE, pt.y + ELLIPSE_SIZE); //
InvalidateRect(hWnd, NULL, TRUE); //メインウィンドウを無効状態にする、WM_PAINTが発生する
return 0;
case WM_PAINT:
hdc = BeginPaint(hWnd, &ps);
BitBlt(hdc, 0, 0, rect.right, rect.bottom, hSecondDC, 0, 0, SRCCOPY); //裏画面を表画面にコピーする
EndPaint(hWnd, &ps);
return 0;
}
return DefWindowProc(hWnd, uMsg, wParam, lParam);
}
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd){
WNDCLASS wc;
MSG msg;
wc.style = CS_HREDRAW | CS_VREDRAW;
wc.lpfnWndProc = WindowProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = hInstance;
wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
wc.lpszMenuName = NULL;
wc.lpszClassName = APP_NAME;
if(!RegisterClass(&wc)) return 0;
if(CreateWindow(
APP_NAME, TEXT(__FILE__), WS_OVERLAPPEDWINDOW | WS_VISIBLE,
CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
NULL, NULL, hInstance, NULL) == NULL) return 0;
while(GetMessage(&msg, NULL, 0, 0) > 0){
DispatchMessage(&msg);
}
return msg.wParam;
}