Forum: PC-Programmierung Kleines Problem bei C++ und WinAPI


von Pinguin (Gast)


Lesenswert?

Hallo, ich bin dabei, mich ein bisschen in die Themen C++, speziell mit 
der WinAPI einzulesen und habe folgendes Programm zum testen 
geschrieben.

Was kann ich machen, dass sich die beiden Kreise nicht selber übermalen?

Mfg
1
#include <windows.h>
2
#include <math.h>
3
4
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
5
6
#define ID_ERSTER_TIMER 1
7
8
wchar_t szAppName[] = L"Ball 'n rollin'";
9
10
int fahrt_v1 = 5;
11
int fahrt_h1 = 5;
12
13
int fahrt_v2 = 5;
14
int fahrt_h2 = 5;
15
16
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, int iCmdShow)
17
{
18
  MSG      msg;
19
  HWND    hWnd;
20
  WNDCLASS  wc;
21
22
  wc.cbClsExtra    = 0;
23
  wc.cbWndExtra    = 0;
24
  wc.hbrBackground  = (HBRUSH) GetStockObject(WHITE_BRUSH);
25
  wc.hCursor      = LoadCursor(NULL, IDC_CROSS);
26
  wc.hIcon      = LoadIcon(NULL, IDI_APPLICATION);
27
  wc.hInstance    = hInstance;
28
  wc.lpfnWndProc    = WndProc;
29
  wc.lpszClassName  = szAppName;
30
  wc.lpszMenuName    = NULL;
31
  wc.style      = CS_HREDRAW | CS_VREDRAW;
32
33
  RegisterClass(&wc);
34
35
  hWnd = CreateWindow( szAppName,
36
             szAppName,
37
             WS_OVERLAPPEDWINDOW,
38
             CW_USEDEFAULT,
39
             CW_USEDEFAULT,
40
             CW_USEDEFAULT,
41
             CW_USEDEFAULT,
42
             NULL,
43
             NULL,
44
             hInstance,
45
             NULL);
46
47
  ShowWindow(hWnd, iCmdShow);
48
  UpdateWindow(hWnd);
49
50
  while(GetMessage(&msg, NULL, 0, 0))
51
  {
52
    TranslateMessage(&msg);
53
    DispatchMessage(&msg);
54
  }
55
  return msg.wParam;
56
}
57
58
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
59
{
60
  static RECT    rect;
61
  static double  horizontal_1;
62
  static double  vertikal_1;
63
64
  static double  horizontal_2;
65
  static double  vertikal_2;
66
67
  switch(message)
68
  {
69
    case WM_CREATE:
70
    {
71
      SetTimer(hWnd, ID_ERSTER_TIMER, 1, NULL);
72
      return 0;
73
    }
74
75
    case WM_SIZE:
76
    {
77
      rect.right  = LOWORD(lParam);
78
      rect.bottom  = HIWORD(lParam);
79
      return 0;
80
    }
81
82
    case WM_PAINT:
83
    {
84
      PAINTSTRUCT  ps;
85
      HDC      hDC;
86
87
      hDC = BeginPaint(hWnd, &ps);
88
89
90
      {
91
        HBRUSH hOldBrush = (HBRUSH)SelectObject(hDC, CreateSolidBrush(RGB(0,0,255)));
92
93
        Ellipse(hDC, 
94
          0          +horizontal_1,
95
          0          +vertikal_1,
96
          50          +horizontal_1,
97
          50          +vertikal_1); //links, oben, rechts, unten
98
99
        Ellipse(hDC, 
100
          0          +horizontal_2,
101
          rect.bottom/2-25  +vertikal_2,
102
          50          +horizontal_2,
103
          rect.bottom/2+25  +vertikal_2);
104
105
        DeleteObject(SelectObject(hDC,hOldBrush));
106
      }
107
      EndPaint(hWnd, &ps);
108
      return 0;
109
    }
110
111
    case WM_TIMER:
112
    {
113
      switch(wParam)
114
      {
115
        case ID_ERSTER_TIMER:
116
        {
117
          RECT InvalRect1;
118
          RECT InvalRect2;
119
120
          if(horizontal_1 >= rect.right-50)
121
            fahrt_h1 = -5;
122
          
123
          if(horizontal_1 <= 0)
124
            fahrt_h1 = 5;
125
126
          if(vertikal_1 >= rect.bottom-50)
127
            fahrt_v1 = -5;
128
          
129
          if(vertikal_1 <= 0)
130
            fahrt_v1 = 5;
131
132
133
          if(horizontal_2 >= rect.right-50)
134
            fahrt_h2 = -5;
135
          
136
          if(horizontal_2 <= 0)
137
            fahrt_h2 =  5;
138
139
          if(vertikal_2 >= rect.bottom/2-25)
140
            fahrt_v2 = -5;
141
          
142
          if(vertikal_2 <= -rect.bottom/2+25)
143
            fahrt_v2 =  5;
144
145
          vertikal_1    += fahrt_v1;
146
          horizontal_1  += fahrt_h1;
147
148
          horizontal_2  += fahrt_h2;
149
          vertikal_2    += fahrt_v2;
150
151
          InvalRect1.left    =   0 + horizontal_2  -5;
152
          InvalRect1.top    =   0 + vertikal_2    -5;
153
          InvalRect1.right  =  50 + horizontal_2  +5;
154
          InvalRect1.bottom  =  50 + vertikal_2    +5;
155
156
          InvalRect2.left    =   0          + horizontal_2    -5;
157
          InvalRect2.top    =  rect.bottom/2-25  + vertikal_2    -5;
158
          InvalRect2.right  =  50          + horizontal_2    +5;
159
          InvalRect2.bottom  =  rect.bottom/2+25  + vertikal_2    +5;
160
161
          InvalidateRect(hWnd, &InvalRect1, TRUE);
162
          InvalidateRect(hWnd, &InvalRect2, TRUE);
163
164
          break;
165
        }
166
      }
167
      return 0;
168
    }
169
170
    case WM_DESTROY:
171
    {
172
      KillTimer(hWnd, ID_ERSTER_TIMER);
173
      PostQuitMessage(0);
174
      return 0;
175
    }
176
  }
177
  return DefWindowProc(hWnd, message, wParam, lParam);
178
}

von Uwe (Gast)


Lesenswert?

Du meinst ne Kollisionserkennung ? Oder mehr BitBlt ?

von Pinguin (Gast)


Lesenswert?

Nein, mein Problem ist, dass die Bereiche, wo der eine Kreis war, mit 
der Hintergrundfarbe überschrieben wurden und der zweite Kreis sich 
scheinbar hinter diesen bewegt.
Man muss den Code nur kurz kompilieren und sieht gleich, was mein 
Problem ist. ;)

von Pinguin (Gast)


Lesenswert?

Ach ja, es sollen eigentlich nur zwei "Bälle" über den Bildschirm 
hüpfen.

von MaWin (Gast)


Lesenswert?

Es gibt sicherlich eine Mange was man besser machen müsste,
aber zuerstmal:

InvalidateRect(hWnd, &InvalRect1, TRUE);
InvalidateRect(hWnd, &InvalRect2, TRUE);

muß im Timer auch passieren, BEVOR die Ellipsen verschoben wurden, damit 
beim WM_PAINT dann bei BeginPaint die dortigen Stellen mit der 
hbrBackground übermalt werden.

Daß man bei animierten Sachen prinzipiell nicht direkt auf den 
Bildschirm schreiben sollte, sondern erst in eine bildschirmkompatible 
Bitmap, und erst wenn alles gemalt wurde diese auf den Bildschirm 
blittet an Stelle des bisherigen Inhalts, sollte zur Vermeidung von 
Flimmereffekten klar sein - aber nicht mal Microsoft behrzigt dies 
immer.

Und daß man heute bei SCHNELLER Animation mit DirectX ein komplett 
anderes API verwenden muß, nennt Microsoft Fortschritt.

Die REIHENFOLGE der Ellipsen, also welche vorne zu liegen scheint und 
welche hinten, ist durch die Reihenfolge im WM_PAINT bestimmt (Z-Order), 
und falls man sie ändern will, muß man dort die Reihenfolge ändern.

Du hast keinen PEN selected, und daher nicht spezifziert wie die 
Umrandung der blau gefüllten Ellipse aussehen soll.

von Pinguin (Gast)


Lesenswert?

Ok, vielen Dank!
Dann werde ich das alles mal überarbeiten müssen.
Ich steh wie gerade noch ganz am Anfang, mich mit WinAPI auseinander zu 
setzen, DirectX wird der nächste Schritt sein.
Vielleicht finde ich ja noch ein gutes Tutorial in diesem Gebiet; das, 
wovon ich mein Programm abgeleitet habe, scheint dafür ja nicht 100% 
gemacht zu sein. ;)

Danke nochmal!

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.