windowsAPI〜画面がちらついてしまう

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
bonbo

windowsAPI〜画面がちらついてしまう

#1

投稿記事 by bonbo » 13年前

早速ですが質問させていただきます
WindowsApiを使ってアニメーションを試していたのですが
なぜか画面がちらついてしまいます。どうすれば直せるでしょうか。よろしくお願いします

コード:

#define ID_MYTIMER 100
#include <Windows.h>
LRESULT CALLBACK WndProc(HWND,UINT,WPARAM,LPARAM);
ATOM InitApp(HINSTANCE);
BOOL InitInstance(HINSTANCE,int);
LPCTSTR lpszClassName=TEXT("animation01");
TCHAR szCaption[64]=TEXT("szcaption");
int WINAPI WinMain(HINSTANCE hCurInst,HINSTANCE hPrecInst,LPSTR lpsCmdLine,int nCmdShow)
{
	MSG msg;
	BOOL bRet;

	if(!InitApp(hCurInst))
		return FALSE;
	if(!InitInstance(hCurInst,nCmdShow))
		return FALSE;
	while((bRet=GetMessage(&msg,NULL,0,0))!=0){
		if(bRet==-1){
			break;
		}else{
			TranslateMessage(&msg);
			DispatchMessage(&msg);
		}
	}
	return (int)msg.wParam;
}
ATOM InitApp(HINSTANCE hInst)
{
	WNDCLASSEX wc;
	wc.cbSize = sizeof(WNDCLASSEX);
	wc.style = CS_HREDRAW | CS_VREDRAW;
	wc.lpfnWndProc = WndProc;	//プロシージャ名
	wc.cbClsExtra = 0;
	wc.cbWndExtra = 0;
	wc.hInstance = hInst;//インスタンス
	wc.hIcon = (HICON)LoadImage(NULL,
		MAKEINTRESOURCE(IDI_APPLICATION),
		IMAGE_ICON,
		0,
		0,
		LR_DEFAULTSIZE | LR_SHARED);
	wc.hCursor = (HCURSOR)LoadImage(NULL,
		MAKEINTRESOURCE(IDC_ARROW),
		IMAGE_CURSOR,
		0,
		0,
		LR_DEFAULTSIZE | LR_SHARED);
	wc.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH);
	wc.lpszMenuName = NULL;	//メニュー名
	wc.lpszClassName = lpszClassName;
	wc.hIconSm = (HICON)LoadImage(NULL,
		MAKEINTRESOURCE(IDI_APPLICATION),
		IMAGE_ICON,
		0,
		0,
		LR_DEFAULTSIZE | LR_SHARED);

	return (RegisterClassEx(&wc));
}
BOOL InitInstance(HINSTANCE hInst, int nCmdShow)
{
	HWND hWnd;

	hWnd = CreateWindow(lpszClassName,
			TEXT("test"), //タイトルバーにこの名前が表示されます
			WS_OVERLAPPEDWINDOW&~WS_THICKFRAME&~WS_MAXIMIZEBOX, //ウィンドウの種類
			CW_USEDEFAULT,	//X座標
			CW_USEDEFAULT,	//Y座標
			CW_USEDEFAULT,	//幅
			CW_USEDEFAULT,	//高さ
			NULL, //親ウィンドウのハンドル、親を作るときはNULL
			NULL, //メニューハンドル、クラスメニューを使うときはNULL
			hInst, //インスタンスハンドル
			NULL);
	if (!hWnd)
		return FALSE;
	ShowWindow(hWnd, nCmdShow);
	HDC hdc;
	UpdateWindow(hWnd);
	hdc=GetDC(hWnd);
	ReleaseDC(hWnd,hdc);
	return TRUE;
}
LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wp, LPARAM lp)
{

	int id;
	static int ballx,bally,ballw,ballh,speed=1;
	static HBITMAP hBmp;
	static HDC hdc_mem;
	HDC hdc;
	static HBRUSH hBrush;
	static int direction = 0;
	PAINTSTRUCT ps;
	BITMAP bmp_info;
	switch (msg) {
		case WM_CREATE:
			hdc=GetDC(hWnd);
			hBmp=CreateCompatibleBitmap(hdc,640,480);
			hdc_mem=CreateCompatibleDC(NULL);
			SelectObject(hdc_mem,hBmp);
			hBrush = CreateSolidBrush(RGB(255,0,0));
			SelectObject(hdc_mem,hBrush);
			ballx=0;
			bally=0;
			ballw=20;
			ballh=20;
			Ellipse(hdc_mem,ballx,bally,ballx+ballw,ballx+ballh);
			ReleaseDC(hWnd,hdc);
			SetTimer(hWnd,ID_MYTIMER,0,NULL);
			break;
		case WM_LBUTTONDBLCLK:
			SendMessage(hWnd,WM_CLOSE,60,0);
			break;
		case WM_TIMER:
			PatBlt(hdc_mem,0,0,640,480,BLACKNESS);
			Ellipse(hdc_mem,ballx,bally,ballx+ballw,ballx+ballh);
			switch(direction){
			case 0:
				ballx+=speed;
				bally+=speed;
				if(bally>480-ballh)direction=1;
				if(ballx>640-ballw)direction=3;
				break;
			case 1:
				ballx+=speed;
				bally-=speed;
				if(bally)direction=2;
				if(ballx>600-ballw)direction=0;
				break;
			case 2:
				ballx-=speed;
				bally-=speed;
				if(bally<0)direction=1;
				if(ballx<0)direction=3;
				break;
			case 3:
				ballx-=speed;
				bally+=speed;
				if(bally>400-ballh)direction=0;
				if(ballx<0)direction=2;
				break;

			}
			InvalidateRect(hWnd,NULL,TRUE);
			break;
		case WM_PAINT:
			hdc = BeginPaint(hWnd, &ps);
			BitBlt(hdc,0,0,640,480,hdc_mem,0,0,SRCCOPY);
			EndPaint(hWnd, &ps);
			break;
		case WM_KEYDOWN:
			if(wp==VK_UP){
				speed++;
				if(speed>10)
					speed=10;
			}
			if(wp==VK_DOWN){
				speed--;
				if(speed<-10)
					speed=-10;
			}
			wsprintf(szCaption,TEXT("はやさ%d"),speed);
			SetWindowText(hWnd,szCaption);
			break;
		case WM_CLOSE:
			id = MessageBox(hWnd,
				TEXT("終了してもよろしいですか"),
				TEXT("確認"),
				MB_YESNO | MB_ICONQUESTION);
			if (id == IDYES)
				DestroyWindow(hWnd);
			break;
		case WM_DESTROY:
			KillTimer(hWnd,ID_MYTIMER);
			PostQuitMessage(0);
			break;

		default:
			return (DefWindowProc(hWnd, msg, wp, lp));

	}
	return 0;
}
環境はwindows7 corei3です

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 15年前
住所: 東海地方
連絡を取る:

Re: windowsAPI〜画面がちらついてしまう

#2

投稿記事 by softya(ソフト屋) » 13年前

SetTimer(hWnd,ID_MYTIMER,0,NULL);
って0ms周期ですか?
それは無茶だと思います。50msなどを選ばれたほうが良いでしょう。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

bonbo

Re: windowsAPI〜画面がちらついてしまう

#3

投稿記事 by bonbo » 13年前

>soft屋さん
ありがとうございます
試してみるとわかるのですが、Settimerの第三引数を大きくしても(50でも)
なぜかちらつきはおこってしまうのです。
なにかほかに原因はないでしょうか

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 15年前
住所: 東海地方
連絡を取る:

Re: windowsAPI〜画面がちらついてしまう

#4

投稿記事 by softya(ソフト屋) » 13年前

bonbo さんが書きました:>soft屋さん
ありがとうございます
試してみるとわかるのですが、Settimerの第三引数を大きくしても(50でも)
なぜかちらつきはおこってしまうのです。
なにかほかに原因はないでしょうか
WM_ERASEBKGNDをキャッチして背景消去を止めさせればマシになるかなと思います。
あとは所詮WM_TIMERメッセージなので精度はあまり良くないかと。
液晶画面更新の周期と完全に一致させるのは困難です。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

bonbo

Re: windowsAPI〜画面がちらついてしまう

#5

投稿記事 by bonbo » 13年前

>soft屋さん
ありがとうございます
>WM_ERASEBKGNDをキャッチして背景消去を止めさせればマシになるかなと思います。
やってみます
>所詮WM_TIMERメッセージなので精度はあまり良くないかと。
別に似たメッセージがあるのですね。探してみます
>液晶画面更新の周期と完全に一致させるのは困難です。
以前DXライブラリというのを使って似たようなプログラムを作ったときは
こういう現象は起こらなかったのですが…あれもWindowsApiですよね
もしかして画面に出力する方法が違うのでしょうか…

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 15年前
住所: 東海地方
連絡を取る:

Re: windowsAPI〜画面がちらついてしまう

#6

投稿記事 by softya(ソフト屋) » 13年前

>>所詮WM_TIMERメッセージなので精度はあまり良くないかと。
>別に似たメッセージがあるのですね。探してみます

いや無いです。WindowsAPIで完全にはちらつき皆無は難しいです。

>以前DXライブラリというのを使って似たようなプログラムを作ったときは
>こういう現象は起こらなかったのですが…あれもWindowsApiですよね
>もしかして画面に出力する方法が違うのでしょうか…

あれはDirectXなので描画方式が全然違います。
DirectXには自動的に液晶画面の更新周期(垂直同期)に同期させる機能があります。
WindowsAPIにはありません。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

bonbo

Re: windowsAPI〜画面がちらついてしまう

#7

投稿記事 by bonbo » 13年前

>あれはDirectXなので描画方式が全然違います。
>DirectXには自動的に液晶画面の更新周期(垂直同期)に同期させる機能があります。
>WindowsAPIにはありません。
なるほど…WindowsAPIのみでグラフィックスを制御するのは困難なのですね…
何度もありがとうございました。もうすこし勉強してから出直してきます。

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 15年前
住所: 東海地方
連絡を取る:

Re: windowsAPI〜画面がちらついてしまう

#8

投稿記事 by softya(ソフト屋) » 13年前

bonbo さんが書きました:>あれはDirectXなので描画方式が全然違います。
>DirectXには自動的に液晶画面の更新周期(垂直同期)に同期させる機能があります。
>WindowsAPIにはありません。
なるほど…WindowsAPIのみでグラフィックスを制御するのは困難なのですね…
何度もありがとうございました。もうすこし勉強してから出直してきます。
ちなみにWindowsAPIで描画するとDirectXよりも相当遅いはずです。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

閉鎖

“C言語何でも質問掲示板” へ戻る