- 締切済み
C言語で画面がおかしくなる
最近C言語でプログラムを書き始めました。 二次関数を作るスクリプトなんですが、一定時間がたつと画面がおかしくなります。 どこが問題なのか探しても見つからないので、わかる方教えてください。 WinMainの部分は省いてます #include<windows.h> #include<stdio.h> #include <stdlib.h> #include<time.h> #define TIMER_ID 1 #define spy(num) (wy-num) int rnd(int r); void bset(HDC hdc, int x, int y); LRESULT CALLBACK WndProc(HWND hwnd , UINT msg , WPARAM wp , LPARAM lp) { HDC hDC; static int DesktopX ,DesktopY; static HDC hdc; static HDC Mhdc; static HBITMAP BMPhdc; PAINTSTRUCT paint; RECT Rect; LOGPEN lopnPen; POINT CursorP, ScreenP; char str[250]; int i; static int wx, wy ,ky; static double a ,b ,c ,x ,y ,n ,m ,s ,t; switch (msg) { case WM_DESTROY: DeleteObject( BMPhdc ); DeleteDC( Mhdc ); PostQuitMessage(0); return 0; case WM_CREATE: SetTimer(hwnd, TIMER_ID, 10, NULL); hDC = GetDC(hwnd); hdc = CreateCompatibleDC( hDC ); GetClientRect(GetDesktopWindow() ,&Rect); DesktopX = Rect.right ;DesktopY = Rect.bottom; BMPhdc = CreateCompatibleBitmap( hDC, DesktopX, DesktopY ); SelectObject( hdc, BMPhdc ); ReleaseDC( hwnd, hDC ); GetClientRect(hwnd, &Rect); wx = Rect.right ;wy = Rect.bottom; x = rnd(wx); y = rnd(wy); n = rnd(wx); m = rnd(wy); return 0; case WM_TIMER: ScreenP.x = LOWORD(lp); ScreenP.y = HIWORD(lp); GetClientRect(hwnd, &Rect); wx = Rect.right ;wy = Rect.bottom; if( ky == 1 ){ x = rnd(wx); y = rnd(wy); n = rnd(wx); m = rnd(wy); } ClientToScreen(hwnd ,&ScreenP); GetCursorPos(&CursorP); s = CursorP.x-ScreenP.x; t = wy-(CursorP.y-ScreenP.y); InvalidateRect(hwnd, NULL, FALSE); return 0; case WM_RBUTTONDOWN: ky = 1; return 0; case WM_RBUTTONUP: ky = 0; return 0; case WM_PAINT: Mhdc = BeginPaint(hwnd, &paint); SelectObject(hdc , CreateSolidBrush(RGB(255,255,255))); lopnPen.lopnStyle = PS_NULL; SelectObject(hdc , CreatePenIndirect(&lopnPen)); Rectangle(hdc , 0 , 0 , wx+1 , wy+1); SelectObject(hdc , CreateSolidBrush(RGB(255,0,0))); if ((s-n) != 0 && (n-x) != 0 && (s-x) != 0){ a = ((t-m)/(s-n) - (m-y)/(n-x)) / (s-x); b = (m-y)/(n-x) - a*(n+x); c = y - a*x*x -b*x; } bset(hdc, x,spy(y)); bset(hdc, n,spy(m)); bset(hdc, s,spy(t)); lopnPen.lopnStyle = PS_SOLID; lopnPen.lopnColor = RGB(0,0,255); SelectObject(hdc , CreatePenIndirect(&lopnPen)); MoveToEx(hdc , -1 , spy( a + b - c) , NULL); for(i = 0 ; i <= wx ;i++){ LineTo(hdc , i , spy( a*i*i - b*i - c)); } BitBlt(Mhdc, 0, 0, DesktopX, DesktopY, hdc, 0, 0, SRCCOPY ); EndPaint(hwnd, &paint); return 0; } return DefWindowProc(hwnd , msg , wp , lp); } int rnd(int r){ static int flag; if (flag == 0) { srand((unsigned int)time(NULL)); flag = 1; } return (int)(rand()*(r+1.0)/(1.0+RAND_MAX)); } void bset(HDC hdc, int x, int y){ static LOGPEN lopnPen; lopnPen.lopnStyle = PS_NULL; SelectObject(hdc , CreatePenIndirect(&lopnPen)); Rectangle(hdc , x-3 , y-3 , x+3 , y+3); return; }
- みんなの回答 (2)
- 専門家の回答
みんなの回答
- redfox63
- ベストアンサー率71% (1325/1856)
普通はDeleteObjectで削除します デバイスコンテキストに選択されているのであれば選択を外してから削除するようにします http://msdn.microsoft.com/library/ja/default.asp?url=/library/ja/jpgdi/html/_win32_createpenindirect.asp 何かしらの統合環境を使っているのであれば ブレークポイントを設けて怪しそうな部分をつぶしましょう 統合環境でないのであれば 右クリックなどのメッセージでMessageBoxなどを使用するなどして変数をチェックしてみましょう
- redfox63
- ベストアンサー率71% (1325/1856)
どのようにおかしくなるのかを具体的に説明しましょう ざっと見た感じでは CreateXXXIndirectでGDIオブジェクトを作りっぱなしな部分が多々見受けられます 使用後不要になったオブジェクトのハンドルは開放したほうがいいように思います
補足
おかしくなるところは、一定時間が経過すると画面が真っ赤になります。 そして、普通だと青い線も描画されますが、それも出ません。 CreateXXXIndirect は SelectObject の関数の中で実行しているから、 ハンドルを開封する必要がないんじゃないでしょうか?
補足
ペンなどのオブジェクトはDeleteObjectで削除しないといけなかったとは知りませんでした。 そこで、削除をしてみましたが症状は改善されませんでした。 変数の状態を調べてみても変わった様子もありません。 APIにエラーがあるのかと問題がありそうな関数の戻り値をすべて調べましたが、どれも異状なしでした。 わかったこと 自作の bset関数で設定している赤色が症状が発生したときに無視され その前の色で描画される