Forum: PC-Programmierung WinApi Hauptschleife


von Peter (Gast)


Lesenswert?

Hallo,
ich habe gerade mit winapi angefangen und möchte mir eine oberfläche 
erstellen. Dazu habe ich ein Beispielprogramm gefunden, welches mir das 
Fenster erstellt
1
#include <windows.h>
2
#include <stdio.h>
3
4
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
5
6
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
7
                   PSTR szCmdLine, int iCmdShow)
8
{
9
   static TCHAR const szAppName[] = TEXT("Klassenname");
10
   HWND         hWnd;
11
   MSG          msg;
12
   WNDCLASSEX   wndclassex;
13
14
   wndclassex.cbSize        = sizeof (WNDCLASSEX);
15
   wndclassex.style         = CS_HREDRAW | CS_VREDRAW;
16
   wndclassex.lpfnWndProc   = &WndProc;
17
   wndclassex.cbClsExtra    = 0;
18
   wndclassex.cbWndExtra    = 0;
19
   wndclassex.hInstance     = hInstance;
20
   wndclassex.hIcon         = LoadIcon(NULL, IDI_APPLICATION);
21
   wndclassex.hCursor       = LoadCursor(NULL, IDC_ARROW);
22
   wndclassex.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
23
   wndclassex.lpszMenuName  = NULL;
24
   wndclassex.lpszClassName = szAppName;
25
   wndclassex.hIconSm       = wndclassex.hIcon;
26
27
   if (!RegisterClassEx(&wndclassex))
28
   {
29
      MessageBox(NULL, TEXT("RegisterClassEx fehlgeschlagen!"),
30
                 szAppName, MB_OK | MB_ICONERROR);
31
      return -1;
32
   }
33
34
   hWnd = CreateWindowEx(WS_EX_OVERLAPPEDWINDOW, // erweiterter Fensterstil
35
                  szAppName, // Name der Fensterklasse
36
                  TEXT("Fenstertitel"), // Fenstertitel
37
                  WS_OVERLAPPEDWINDOW, // Fensterstil
38
                  CW_USEDEFAULT, // X-Position des Fensters
39
                  CW_USEDEFAULT, // Y-Position des Fensters
40
                  CW_USEDEFAULT, // Fensterbreite
41
                  CW_USEDEFAULT, // Fensterhöhe
42
                  NULL, // übergeordnetes Fenster
43
                  NULL, // Menü
44
                  hInstance, // Programm-Kopiezähler (Programm-ID)
45
                  NULL); // zusätzliche Parameter
46
47
   ShowWindow(hWnd, iCmdShow);
48
   UpdateWindow(hWnd);
49
50
   for (;;)
51
   {
52
      int ret = GetMessage(&msg, NULL, 0, 0);
53
      if (ret == -1)
54
         return -1;
55
      else if (ret == 0)
56
         break;
57
      TranslateMessage(&msg);
58
      DispatchMessage(&msg);
59
   }
60
61
   UnregisterClass(szAppName, hInstance);
62
63
   return (int)msg.wParam;
64
}

Danach kommt die Hauptnachrichtenschleife
1
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
2
{
3
  static HWND hButton;
4
  static HWND lButton;
5
  HDC hdc;
6
  PAINTSTRUCT ps;
7
8
  switch (message)
9
  {
10
    case WM_PAINT:
11
    {
12
      hdc = BeginPaint(hWnd, &ps);
13
      TextOut(hdc, 0, 0, TEXT("Hello World!"), 12);
14
      EndPaint(hWnd, &ps);
15
      return 0;
16
    }
17
    case WM_CREATE:
18
    {
19
      hButton = CreateWindow(  "button",
20
                                  "Beenden",
21
                                  WS_CHILD | WS_VISIBLE,
22
                                  0, 0, 0, 0,
23
                                  hWnd,
24
                                  NULL,
25
                                  ((LPCREATESTRUCT) lParam) -> hInstance,
26
                                  NULL);
27
28
      lButton = CreateWindow( "button",
29
                  "Zweiter Button",
30
                  WS_CHILD | WS_VISIBLE,
31
                  0, 0, 0, 0,
32
                  hWnd,
33
                  NULL,
34
                  ((LPCREATESTRUCT) lParam) -> hInstance,
35
                  NULL);
36
      return 0;
37
    }
38
    case WM_SIZE:
39
    {
40
      MoveWindow(hButton, LOWORD(lParam) / 2 - 80, HIWORD(lParam) - 30, 160, 22, TRUE);
41
      MoveWindow(lButton, LOWORD(lParam) / 2, HIWORD(lParam) - 30, 160, 22, TRUE);
42
      return 0;
43
    }
44
    case WM_COMMAND:
45
    {
46
      if (lParam == (LPARAM)hButton)
47
      {
48
        if (HIWORD(wParam) == BN_CLICKED)
49
          SendMessage(hWnd, WM_CLOSE, 0, 0);
50
      }
51
      else if (lParam == (LPARAM)lButton)
52
      {
53
        if (HIWORD(wParam) == BN_CLICKED)
54
          SendMessage(hWnd, WM_CLOSE, 0, 0);
55
      }
56
      return 0;
57
    }
58
    case WM_CLOSE:
59
    {
60
      DestroyWindow(hWnd);
61
      break;
62
    }
63
    case WM_DESTROY:
64
    {
65
      PostQuitMessage(0);
66
      return 0;
67
    }
68
  }
69
  return DefWindowProc(hWnd, message, wParam, lParam);
70
}

Dazu habe ich eine Frage, kommen alle Elemente die ich in der Oberfläche 
erstelle in die selbe Callback Funktion (LRESULT CALLBACK WndProc)? Oder 
kann man das noch irgendwie aufteilen? Also pro element eine Funktion 
oder ähnlich?
Momentan habe ich nur zwei Buttons dort drinn. Aber wenn noch mehr 
Elemente (z.B. RadioButton oder Tastatureingabe oder schreibfenster oder 
...) kommen, kann das ja ziemlich unübersichtlich werden.

von marais (Gast)


Lesenswert?

Ich weiss ja nicht, wie komplex Deine Oberfläche werden soll, aber für 
alles, was über zwei Knöpfe hinausgeht, würde ich nicht winapi 
verwenden. Es ist natürlich sinnvoll, das Beispielprogramm zu verstehen, 
um zu wissen, wie die Hauptnachrichtenschleife in Windows-Programmen 
funktioniert. Für den eigentlichen Job würde ich aber ein Framework 
verwenden. Das nimmt Dir viel Arbeit ab und kapselt viele Details (wie 
eben auch die Nachrichtenschleife).

Ich mache das mit MFC, einfach weil ich das vor 20 Jahren gelernt habe 
und Portabilität auf andere Plattformen normalerweise kein Thema ist. 
Ich trenne allerdings strikt GUI-Code und den eigentlichen Arbeitscode, 
um eben doch portieren zu können, falls erforderlich.


Zu den möglichen Frameworks hat jeder seine Meinung. Konsens ist wohl, 
dass ein Neueinsteiger heute nicht mehr mit MFC anfangen sollte, sondern 
eher Qt lernen sollte. Für kleinere Projekte gibt es einfachere 
Alternativen. Du sagst auch nicht, ob Du einen Compiler kaufen kannst 
(MFC gibt's soweit ich weiss nur in der kommerziellen Version von Visual 
Studio, Qt ist umsonst) oder ob alles umsonst sein muss.


Dann gibt's noch die Frage, ob Du Dich auf C# und .net einlassen 
möchtest (und damit an Microsoft-Technologie gebunden bist) - dann 
stehen andere Alternativen offen. Für mich musste ich diese Frage mit 
Nein beantworten, aber jeder Jeck iss anders.


Und falls Du wirklich nur zwei Knöpfe und ein Eingabefeld brauchst: 
Mach's mit winapi, Du lernst auf jeden Fall was dabei.

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

Wenn Du tatsächlich den sehr steinigen Weg gehen möchtest, 
Windows-GUI-Anwendungen mit der Win32-API zu schreiben, kann ich Dir nur 
die Lektüre eines Buches nahelegen:

Charles Petzold "Windows-Programmierung: Das Entwicklerhandbuch zur 
WIN32-API".

ISBN 3860631888

(das ist zwar fast zwanzig Jahre alt, aber die API für 
GUI-Programmierung und die dahinterstehenden Konzepte haben sich seitdem 
nicht geändert)

Üblicherweise empfehle ich keine übersetzten Bücher, hier aber stammt 
die Übersetzung von Arne Schäpers, der bereits das deutsche Handbuch von 
Borlands Turbo-C 2.0 geschrieben hatte, und das war exzellent.

Das englischsprachige Original des Petzold ("Programming Windows®, Fifth 
Edition") findest Du unter der ISBN 157231995X.

Beide Bücher sind natürlich nur noch antiquarisch erhältlich.

--

Ich verdiene seit über einem Vierteljahrhundert meinen Lebensunterhalt 
unter anderem mit der Windows-Programmierung, und ich bin sehr froh, 
GUI-Anwendungen nicht auf diese Art und Weise schreiben zu müssen. Das 
habe ich in den ersten paar Jahren (beginnend mit Windows 3.0) gemacht, 
und es ist sicherlich gutes Grundlagenwissen, das einem hilft, zu 
verstehen, warum eine bestimmte C++-Klassenbibliothek auf eine bestimmte 
Art und Weise aufgebaut ist --- aber nicht jedes Grundlagenwissen, das 
in einem Computer steckt, muss man unbedingt haben, wenn man einfach nur 
Programme dafür schreiben will.

Windows-GUI-Anwendungen würde ich mit einer C++-Klassenbibliothek 
schreiben, und da das Thema "Portabilität" nicht komplett uninteressant 
ist, würde ich eine auf mehreren Plattformen verfügbare Bibliothek 
wählen. Die "Platzhirsche" sind hier QT und wxwidgets.

Ich selbst arbeite überwiegend mit der nicht portierbaren MFC; die zu 
lernen rate ich nicht. Daß ich sie nutze, ist historisch bedingt; als 
ich damit anfing, gab es keine Alternativen. Als "Exit-Strategie" sehe 
ich in diesem Fall wxwidgets, weil einige strukturelle Konzepte der MFC 
ähneln und von daher der Umdenkaufwand nicht so groß ist, wie er es bei 
QT wäre.

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.