Du bist nicht angemeldet.

Stilllegung des Forums
Das Forum wurde am 05.06.2023 nach über 20 Jahren stillgelegt (weitere Informationen und ein kleiner Rückblick).
Registrierungen, Anmeldungen und Postings sind nicht mehr möglich. Öffentliche Inhalte sind weiterhin zugänglich.
Das Team von spieleprogrammierer.de bedankt sich bei der Community für die vielen schönen Jahre.
Wenn du eine deutschsprachige Spieleentwickler-Community suchst, schau doch mal im Discord und auf ZFX vorbei!

Werbeanzeige

1

16.03.2006, 16:55

Fenster Anwendung funktioniert nicht

Hallo,

ich bin inzwischen bei der Windows Programmierung angekommen. Nun hab ich aber ein Problem, denn das erste Fenster funktioniert nicht:

Quellcode

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
// C++ für Spieleprogrammierer
// Listing 10.1
// Ein Windows-Grundgerüst
//
#include <windows.h>

// Prototyp der Callback-Funktion
LRESULT CALLBACK WindowProc (HWND hWnd, UINT message,
                             WPARAM wParam, LPARAM lParam);

// Hauptprogramm
//
int WINAPI WinMain (HINSTANCE hInst, HINSTANCE hPrevInst,
                    LPSTR lpcmdline, int ncmdshow)
{
  WNDCLASSEX windowclass; // Struktur für Fenstereigenschaften
  HWND       hWnd;        // Fenster-Handle
  MSG        message;     // Nachricht

  // Der Klassen-Name des Fensters ist frei wählbar
  const char szClassName[] = "Erstes Fenster";

  // Struktur mit gewünschten Eigenschaften füllen
  //

  // Größe der Struktur zwischenspeichern
  windowclass.cbSize = sizeof (WNDCLASSEX);

  // Fenster soll beim Verschieben neu gezeichnet werden
  windowclass.style = CS_HREDRAW | CS_VREDRAW;

  // Zeiger auf Callback-Funktion
  windowclass.lpfnWndProc = WindowProc;

  // Keine erweiterten Einstellungen
  windowclass.cbClsExtra = 0;
  windowclass.cbWndExtra = 0;

  // Instanz speichern
  windowclass.hInstance = hInst;

  // Icons und Cursor festlegen
  windowclass.hIcon   = LoadIcon (NULL, IDI_APPLICATION);
  windowclass.hIconSm = LoadIcon (NULL, IDI_APPLICATION);
  windowclass.hCursor = LoadCursor (NULL, IDC_ARROW);

  // Hintergrundfarbe festlegen
  windowclass.hbrBackground = (HBRUSH)COLOR_BACKGROUND+1;

  // Ein Menü brauchen wir nicht
  windowclass.lpszMenuName = NULL;

  // Klassenname angeben
  windowclass.lpszClassName = szClassName;

  // Fensterklasse registrieren
  if (!RegisterClassEx (&windowclass) )
    return (0);

  // Das Fenster erzeugen
  hWnd = CreateWindowEx (NULL,
                         szClassName,
                         "Das erste Fenster!",
                         WS_OVERLAPPEDWINDOW | WS_VISIBLE,
                         100, 100,
                         300, 250,
                         NULL,
                         NULL,
                         hInst,
                         NULL);

  // Prüfen, ob alles glatt ging
  if (hWnd == NULL)
    return (0);

  // Der "Herzschlag" des Programms.
  // Hier werden alle Nachrichten abgeholt,
  // übersetzt und weitergeleitet.
  while (GetMessage (&message, NULL, 0, 0) )
  {
    TranslateMessage (&message);
    DispatchMessage (&message);

  }

  // Programm beenden
  return (int)(message.wParam);

} // WinMain


// Callback-Funktion zur Nachrichtenverarbeitung
//
LRESULT CALLBACK WindowProc (HWND hWnd, UINT message,
                             WPARAM wParam, LPARAM lParam)
{
  // Messages auswerten
  switch (message)
  {
    // Fenster schließen? (Auch Alt-F4)
    case WM_DESTROY:
    {
      // Nachricht zum Beenden schicken
      PostQuitMessage (0);
      return (0);

    }

    // Wurde eine Taste gedrückt?
    case WM_KEYDOWN:
    {
      // Ja, also je nach Taste verzweigen
      switch (wParam)
      {
        // Wurde "Escape" gedrückt?
        case VK_ESCAPE:
        {
          // Ja, also Nachricht zum Beenden schicken
          PostQuitMessage (0);
          return (0);

        }
      }
    } break;
  } 

  // Die Nachricht wurde nicht von uns verarbeitet, also
  // von Windows verarbeiten lassen.
  return (DefWindowProc (hWnd, message, wParam, lParam) );

} // WindowProc


Beim kompilieren erscheinen folgende Fehlermeldungen:

Quellcode

1
2
3
4
f:\eigene dateien\visual studio 2005\projects\c++ für spieleprogrammierer\listing 10_1\listing 10_1.cpp(54) : error C2440: '=': 'const char [15]' kann nicht in 'LPCWSTR' konvertiert werden
        Die Typen, auf die verwiesen wird, sind nicht verknüpft; die Konvertierung erfordert einen reinterpret_cast-Operator oder eine Typumwandlung im C- oder Funktionsformat.
f:\eigene dateien\visual studio 2005\projects\c++ für spieleprogrammierer\listing 10_1\listing 10_1.cpp(70) : error C2664: 'CreateWindowExW': Konvertierung des Parameters 2 von 'const char [15]' in 'LPCWSTR' nicht möglich
        Die Typen, auf die verwiesen wird, sind nicht verknüpft; die Konvertierung erfordert einen reinterpret_cast-Operator oder eine Typumwandlung im C- oder Funktionsformat.


Das seltsame dabei ist, dass ich noch nach anderen WinApi Tutorials im Internet und in der MSDN geschaut habe, und überall müsste das so funktionieren wie es oben steht. Ich kann mir echt nicht erklären, was daran falsch sein soll.

Anonymous

unregistriert

2

16.03.2006, 17:09

Mach mal aus

C-/C++-Quelltext

1
const char szClassName[] = "Erstes Fenster";


folgendes:

C-/C++-Quelltext

1
LPCWSTR szClassName = L"Erstes Fenster";


Klappt das dann?

Stefan

riCo

Treue Seele

Beiträge: 165

Beruf: Student

  • Private Nachricht senden

3

16.03.2006, 17:16

Also ich hab auf meinem Notebook VS2003 und VS2005 drauf. Mit dem VS2003er klappt es, das VS2005 hat einige Funktionen nicht gefunden. Ich hatte nur die Standardinstallation drauf und noch nichts daran verändert.

https://www.spieleprogrammierer.de/phpBB…&highlight=2005
Wenn du die 2 Dateien änderst so wie weiter unten in diesem Thread beschrieben geht es im VS2005 auch. Den Ressourceeditor kann man nicht zufällig noch freischalten? ;) Werd ich mir wohl doch aus der BA mal die Prof-Version besorgen müssen. Keine Lust mir da selbst Klassen zu schreiben.
Wir leben alle unter dem Sternenhimmel, aber wir haben nicht alle den gleichen Horizont.

4

16.03.2006, 17:31

Ah danke, jetz klappt das.
Aber ich verstehe nicht ganz, was das soll. Könnte mir das jemand erklären?

@riCo:
Ich habe VC2005 genau nach dieser Anleitung installiert. Deshalb verstehe ich ja auch nicht, warum es so wie es oben steht nicht funktioniert hat.

Anonymous

unregistriert

5

16.03.2006, 17:36

Zitat von »"Manuel"«

Ah danke, jetz klappt das.
Aber ich verstehe nicht ganz, was das soll. Könnte mir das jemand erklären?


Ich vermute, dass es daran liegt, dass LPCWSTR ein Zeiger auf einen
Unicode-String ist und char * ein Zeiger auf einen normalen String und der
Compiler diese Umwandlung nicht ohne expliciten cast zulässt. Dies ist auch
richtig, denn ein Unicode-String ist von der Bytezahl oft länger als der
ISO-8859-1 codierte Standard-char*-String und damit sind beide nicht
1:1 austauschbar.

Der Compiler schreibt ja:

Zitat

die Konvertierung erfordert einen reinterpret_cast-Operator oder eine Typumwandlung im C- oder Funktionsformat.


Grüße
Stefan

6

16.03.2006, 17:38

Ah, und das "L" zeigt dann an, dass es ich um einen Unicode-String handelt?

Anonymous

unregistriert

7

16.03.2006, 18:01

Jep :)

Stefan

__stdcall*

Treue Seele

Beiträge: 101

Wohnort: Dauchingen

Beruf: Schüler

  • Private Nachricht senden

8

16.03.2006, 18:12

jenau :)

Unicodestrings sind vom Typ wchar_t* (besser: std::basic_string<wchar_t>)
ASCII-Strings vom Typ char* (sollte man nicht mehr benutzen ;) )

so, hier nun etwas Code um das zu verdeutlichen:

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#include <windows.h>    // Für die WinAPI Funktionen

#include <string>       // Für basic_string


int __stdcall WinMain(::HINSTANCE__* instance, ::HINSTANCE__* prevInstance,
                       char* cmdLine, int cmdShow)
{
    std::basic_string<wchar_t> unicodeString;   // Deklaration eines Unicode-Strings


    unicodeString = L"Test-String";             // Zuweißung


        // den String ausgeben =)

    ::MessageBoxW(NULL, unicodeString.c_str(), L"Nachricht:", MB_OK);

    return 0;
}


Wenn du mit basic_string arbeitest musst du bei jeder Funktion die einen String entgegennimmt es so schreiben:

C-/C++-Quelltext

1
unicodeString.c_str();


das gibt einen konstanten Zeiger auf die Stringdaten zurück.

Wenns net stimmt bitte korrigieren ^^

__stdcall*
[ICQ: 194-584-442 | MSN: nos4_9@hotmail.de | X-Fire: shadowstalker45]

koschka

Community-Fossil

Beiträge: 2 862

Wohnort: Dresden

Beruf: Student

  • Private Nachricht senden

9

16.03.2006, 21:15

Im Normalfall muss man aber #define UNICODE aktivieren....

das L steht für LONG... 16Bit, also die Größe eines UniCode Zeichens

10

17.03.2006, 14:03

Na dann ist mir jetzt alles klar. Ich finds echt toll wie schnell und kompetent einem hier geholfen wird. :)

Werbeanzeige