Programm reagiert nicht auf Nachricht (WM_TIMER)



  • Hi Leute, ich programmiere zu lernzweken ein kleines Moorhuhn ähnliches Prog. Ein Fadenkreutz und und eine Rechteckige Zielscheibe hab ich schon. Das Fadenkreutz bewegt sich schon ganz gut mit der Maus mit :). Die Zielscheibe soll sich im Timertackt bewegen. Leider scheint das Fenster irgendwie nicht auf den Timer zu reagieren. Wiso nicht?
    Hier der Code:

    #include <windows.h>
    #include <stdlib.h>
    
    #define CX_FADENKREUTZ (cxClient/7)
    #define CY_FADENKREUTZ CX_FADENKREUTZ
    
    #define CX_ZIELSCHEIBE (cxClient/6)
    #define CY_ZIELSCHEIBE CX_ZIELSCHEIBE
    #define TIMER_ZIELSCHEIBE 1
    
    LRESULT CALLBACK WindowProcedure (HWND, UINT, WPARAM, LPARAM);
    
    RECT DrawFadenkreutz(HWND, int, int);
    RECT DrawZielscheibe(HWND, int, int);
    
    int cxClient, cyClient;
    
    char szClassName[ ] = "WindowsApp";
    
    int WINAPI WinMain (HINSTANCE hThisInstance,
                        HINSTANCE hPrevInstance,
                        LPSTR lpszArgument,
                        int nFunsterStil)
    
    {
        HWND hwnd;               
        MSG messages;            
        WNDCLASSEX wincl;        
    
        wincl.hInstance = hThisInstance;
        wincl.lpszClassName = szClassName;
        wincl.lpfnWndProc = WindowProcedure;
        wincl.style = CS_VREDRAW|CS_HREDRAW;           
        wincl.cbSize = sizeof (WNDCLASSEX);
        wincl.hIcon = LoadIcon (NULL, IDI_APPLICATION);
        wincl.hIconSm = LoadIcon (NULL, IDI_APPLICATION);
        wincl.hCursor = LoadCursor (NULL, IDC_ARROW);
        wincl.lpszMenuName = NULL; 
        wincl.cbClsExtra = 0;      
        wincl.cbWndExtra = 0;                      
        wincl.hbrBackground = (HBRUSH) GetStockObject(WHITE_BRUSH);
    
        if (!RegisterClassEx (&wincl))
            return 0;
    
        hwnd = CreateWindowEx (
               0,                   /* Extended possibilites for variation */
               szClassName,         /* Classname */
               "Shooter1",       /* Title Text */
               WS_OVERLAPPEDWINDOW, /* default window */
               CW_USEDEFAULT,       /* Windows decides the position */
               CW_USEDEFAULT,       /* where the window ends up on the screen */
               544,                 /* The programs width */
               375,                 /* and height in pixels */
               HWND_DESKTOP,        /* The window is a child-window to desktop */
               NULL,                /* No menu */
               hThisInstance,       /* Program Instance handler */
               NULL                 /* No Window Creation data */
               );
    
        ShowWindow (hwnd, SW_SHOW);
    	UpdateWindow(hwnd);
    
        while (GetMessage (&messages, NULL, 0, 0))
        {
            TranslateMessage(&messages);
            DispatchMessage(&messages);
        }
    
        return messages.wParam;
    }
    
    LRESULT CALLBACK WindowProcedure (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
    {
    	static RECT rectFadenkreutz, rectZielscheibe;
    	static POINT pntFadenkreutz, pntZielscheibe;
    
        switch (message)                  
        {
            case WM_DESTROY:
                PostQuitMessage (0);       
                break;
    		case WM_CREATE:
    			SetTimer(hwnd, TIMER_ZIELSCHEIBE, 1000, NULL);
    			break;
    		case WM_TIMER:
    			MessageBeep(0);
    			pntZielscheibe.x += (rand() % 10);
    			pntZielscheibe.y += (rand() % 10);
    			InvalidateRect(hwnd, &rectZielscheibe, TRUE);
    			break; 
    		case WM_MOUSEMOVE:
    			pntFadenkreutz.x = LOWORD(lParam);
    			pntFadenkreutz.y = HIWORD(lParam);
    			InvalidateRect(hwnd, &rectFadenkreutz, TRUE);
    			break;
    		case WM_PAINT:
    			rectFadenkreutz = DrawFadenkreutz(hwnd, 
    				pntFadenkreutz.x, pntFadenkreutz.y);
    			rectZielscheibe = DrawZielscheibe(hwnd,
    				pntZielscheibe.x, pntZielscheibe.y);
    			break;
    		case WM_SIZE:
    			cxClient = LOWORD(lParam);
    			cyClient = HIWORD(lParam);			
    			break;
            default:                      
                return DefWindowProc (hwnd, message, wParam, lParam);
        }
    
        return 0;
    }
    
    RECT DrawFadenkreutz(HWND hwnd, int xPos, int yPos)
    {
    	HDC hdc;
    	RECT rect;
    
    	hdc = GetDC(hwnd);
    
    	rect.left	= xPos - CX_FADENKREUTZ/2;
    	rect.top	= yPos - CY_FADENKREUTZ/2;
    	rect.right	= xPos + CX_FADENKREUTZ/2;
    	rect.bottom	= yPos + CX_FADENKREUTZ/2;
    	Arc(hdc, rect.left, rect.top, rect.right, rect.bottom, 0, 0, 0, 0);
    	MoveToEx(hdc, rect.left + CX_FADENKREUTZ/2, rect.top, NULL);
    	LineTo(hdc, rect.left + CX_FADENKREUTZ/2, rect.bottom);
    	MoveToEx(hdc, rect.left, rect.top + CY_FADENKREUTZ/2, NULL);
    	LineTo(hdc, rect.right, rect.top + CY_FADENKREUTZ/2);
    
    	ReleaseDC(hwnd, hdc);
    
    	return(rect);
    }
    
    RECT DrawZielscheibe(HWND hwnd, int xPos, int yPos)
    {
    	HDC hdc;
    	RECT rect;
    	POINT pnt[5];
    
    	hdc = GetDC(hwnd);
    	rect.left	= xPos;
    	rect.top	= yPos;
    	rect.right	= xPos + CX_ZIELSCHEIBE;
    	rect.bottom = yPos + CY_ZIELSCHEIBE;
    
    	pnt[0].x = rect.left;
    	pnt[0].y = rect.top;
    	pnt[1].x = rect.right;
    	pnt[1].y = rect.top;
    	pnt[2].x = rect.right;
    	pnt[2].y = rect.bottom;
    	pnt[3].x = rect.left;
    	pnt[3].y = rect.bottom;
    	pnt[4] = pnt[0];
    
    	Polyline(hdc, pnt, 5);
    
    	ReleaseDC(hwnd, hdc);
    
    	return(rect);
    }
    

    Wenn ich bei WM_PAINT einen hdc mittels BeginPaint erstelle, und jeweils nur die hdc an die Zeichenfunktionen übergeben, funzt der timer. Leider sind dann die Zeichenfunktionen nicht wie gewünscht 😞 .
    Für eure Hilfe wäre ich Euch sehr dankbar.

    Gruss 🙂



  • Leider sind dann die Zeichenfunktionen nicht wie gewünscht

    Dann beheb dort den Fehler. BeginPaint/EndPaint oder ValidateRect brauchst du in WM_PAINT oder du wirst nur noch mit WM_PAINT zugeballert.



  • ballermann schrieb:

    BeginPaint/EndPaint oder ValidateRect brauchst du in WM_PAINT oder du wirst nur noch mit WM_PAINT zugeballert.

    Vielen Dank für den Tip 🙂 Das hat mich schon weitergebracht. Mein WM_PAINT sieht nun wie folgt aus:

    case WM_PAINT:
    			BeginPaint(hwnd, &ps);
    			EndPaint(hwnd, &ps);
    			rectFadenkreutz = DrawFadenkreutz(hwnd, 
    				pntFadenkreutz.x, pntFadenkreutz.y);
    			rectZielscheibe = DrawZielscheibe(hwnd,
    				pntZielscheibe.x, pntZielscheibe.y);
    			break;
    

    Der Timer funzt jetzt. Doch ein Problem gibt es jetzt. Das alte Rechteck (das wird ja mittels timer immer verschoben/neugezeichnet) wird nicht gelöscht. Das wundert mich jedoch, da bei WM_TIMER ja InvalidateRect() mit TRUE aufgerufen wird. Wo steckt da das Problem?

    gruss 🙂



  • Es wird aber eben nur der über rectZielscheibe angegebene Bereich gelöscht und neugezeichnet...



  • es muss so aussehen:

    PAINTSTRUCT ps;
    HDC hDC = BeginPaint(hWnd, &ps);
    DrawFadenkreutz(hDC, 10, 10);
    EndPaint(hWnd, &ps;
    

    In DrawFadenkreutz machst du GetDC und ReleaseDC ganz raus.


Anmelden zum Antworten