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

12.11.2009, 21:48

Lösung zu Kapitel 10 / letzte Aufgabe

Hallo alle zusammen!

Hab mich mal im Forum umgeschaut, aber bis jetzt noch keine Lösung gefunden. Im Buch gibt es eine "inofizielle" Aufgabe zu Listing 10.3. Es sollen alle globalen Handles ersetzt werden. Konkret:

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
#include <windows.h>

// Prototypen

//

LRESULT CALLBACK WindowProc (HWND hWnd, UINT message,
                             WPARAM wParam, LPARAM lParam);

HWND ErstelleHauptfenster (HINSTANCE hInst);
void ErstelleSteuerelemente (HWND hWnd, HINSTANCE hInst);

// IDs der Child-Fenster

//

#define ID_STATICTEXT      4000
#define ID_EDITBOX         4001
#define ID_BTN_UEBERNEHMEN 4002
#define ID_BTN_BEENDEN     4003

// Globale Variablen

// Don't do this at home!

//

HWND hText;        // Handle für den statischen Text

HWND hEditBox;     // Handle für die Editbox

HWND hUebernehmen; // Handle für Button "Übernehmen"

HWND hBeenden;     // Handle für Button "Beenden"


Ich hab schon versucht die Callback Funktion zu überladen, dass die Funktion die Handles kennt, allerdings kommt dann der Fehler mit einem fehlenden Verweis und eine unaufgelöste Variable oder so.

Hat jemand diese Aufgabe schon von euch gelöst, weil ich würd gerne wissen, wie man das anstellen soll.

LG, Dome--
Errare humanum est.. leider oder zum Glück?

drakon

Supermoderator

Beiträge: 6 513

Wohnort: Schweiz

Beruf: Entrepreneur

  • Private Nachricht senden

2

12.11.2009, 21:50

Hast du denn auch eine Implementierung der Funktion geschrieben? Wenn ja. Bist du sicher, dass der Name korrekt ist?

Und die genaue Fehlermeldung wäre auch nicht schlecht.

3

12.11.2009, 22:01

Also wenn ich das mit dem Implementieren richtig verstanden hab, dann glaub ich hab ich das nicht gemacht^^ Aber könntest du mich kurz aufklären? Wäre echt nett, kenn mich nämlich noch nicht so gut aus. Also ich habs mir so überlegt:

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
#include <windows.h>

// Prototypen

//

LRESULT CALLBACK WindowProc (HWND hWnd, UINT message,
                             WPARAM wParam, LPARAM lParam);

LRESULT CALLBACK WindowProc (HWND hWnd, UINT message,
                             WPARAM wParam, LPARAM lParam, HWND *hText, HWND *hEditBox,
                             HWND *hUebernehmen, HWND *hBeenden);


HWND ErstelleHauptfenster (HINSTANCE hInst);
void ErstelleSteuerelemente (HWND hWnd, HINSTANCE hInst, HWND *hText, HWND *hEditBox, HWND *hUebernehmen, HWND *hBeenden); 


Also ich hab die normale und die überladnee Callback funktion. Die Handles erstell ich im Hauptprogramm mit new, also:

C-/C++-Quelltext

1
2
3
4
HWND *hText         = new HWND;      // Handle für den statischen Text

  HWND *hEditBox        = new HWND;     // Handle für die Editbox

  HWND *hUebernehmen    = new HWND;      // Handle für Button "Übernehmen"

  HWND *hBeenden        = new HWND;     // Handle für Button "Beenden"


Die Callback sieht dann so aus:

C-/C++-Quelltext

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
LRESULT CALLBACK WindowProc (HWND hWnd, UINT message,
                             WPARAM wParam, LPARAM lParam, HWND *hText, HWND *hEditBox, HWND *hUebernehmen, HWND *hBeenden)
                        
{
  // Messages auswerten

  switch (message)
  {
    // Fenster schließen? (Auch Alt-F4)

    case WM_DESTROY:
    {
      // Nachricht zum Beenden schicken

      PostQuitMessage (0);
      return (0);

    }

    // Ab hier die Nachrichten unserer Child-Fenster bearbeiten

    case WM_COMMAND:
    {
      switch (wParam)
      {
        // Wurde "Übernehmen" angeklickt?

        case ID_BTN_UEBERNEHMEN:
        {
          char szText[256];

          // Text aus der Editbox holen

          GetWindowText (*hEditBox, szText, 256);

          // Diesen Text in das Label schreiben und

          // den Text der Editbox löschen

          SetWindowText (*hText, szText);
          SetWindowText (*hEditBox, "");

          return (0);

        }

        // Wurde "Beenden" angeklickt?

        case ID_BTN_BEENDEN:
        {
          int Resultat; // Rückgabewert der Messagebox


          // Messagebox für Sicherheitsabfrage

          Resultat = MessageBox (hWnd, "Wirklich beenden?",
                                 "Programm beenden",
                                 MB_YESNO | MB_ICONQUESTION);

          // Wurde "Ja" angeklickt?

          if (Resultat == IDYES)
          {
            // Ja, also Programm beenden

            PostQuitMessage (0);
            return (0);

          }

          // Nein, also ganz normal weiter

          return (0);

        }
      } break;
    } break;
  }

  // Die Nachricht wurde nicht von uns verarbeitet, also

  // von Windows verarbeiten lassen

  return (DefWindowProc (hWnd, message, wParam, lParam) );

} // WindowProc


Und der Fehler geht in etwa so:
1>Listing_10_3.obj : error LNK2019: Verweis auf nicht aufgelöstes externes Symbol ""long __stdcall WindowProc(struct HWND__ *,unsigned int,unsigned int,long)" (?WindowProc@@YGJPAUHWND__@@IIJ@Z)" in Funktion ""struct HWND__ * __cdecl ErstelleHauptfenster(struct HINSTANCE__ *)" (?ErstelleHauptfenster@@YAPAUHWND__@@PAUHINSTANCE__@@@Z)".
1>.\Debug/10_3.exe : fatal error LNK1120: 1 nicht aufgelöste externe Verweise.


Muss ich dann praktisch die Callbackfunktion noch einmal schreiben (also nicht nur deklarieren)? Und wenn ja, gibt es auch eine einfachere und bessere Möglichkeit, als die, die mir durchs Hirn gejagt ist?
Errare humanum est.. leider oder zum Glück?

drakon

Supermoderator

Beiträge: 6 513

Wohnort: Schweiz

Beruf: Entrepreneur

  • Private Nachricht senden

4

12.11.2009, 22:06

Jap. Das ist genau der Fehler, den ich vermutet habe. Sprich du hast eine Funktion deklariert und rufst sie auf, aber du definierst sie nirgendwo. Sprich du hast so etwas hier:

C-/C++-Quelltext

1
2
3
4
5
6
void foo (); 

int main ()
{
  foo (); // generiert den Linkerfehler 2019

}


Du musst also noch eine Implementierung der Funktion haben:

C-/C++-Quelltext

1
2
3
4
5
6
7
void foo ()
{} // das reicht schon


int main ()
{
  foo (); // ok

}

Also das in den {} Klammern. In diesem Beispiel ist alles in Ordnung es wird einfach in foo nichts gemacht.

Das auf dein Code zu übetragen überlasse ich jetzt mal dir, aber ich denke du weisst jetzt, wo das Problem liegt.

CBenni::O

1x Contest-Sieger

Beiträge: 1 145

Wohnort: Stuttgart

  • Private Nachricht senden

5

12.11.2009, 23:12

hy,
i.d.R. hilft es wenn man nach z.b. "C++ LNK 2019" oder so googelt^^
solche fragen werden in verschiedenen foren hundertfach gestellt...
ich wüsste keinen kompiler- oder linkerfehler, zu dem es keinen forumsbeitrag iwo gäbe :D

mfg CBenni::O
Ein Mitglied der VEGeiCoUndGraSonMaWiGeS Bewegung.
42!
Aufräumen kann jeder, nur das Genie überblickt das Chaos!
Metal will never die!
1. Sppro Gamecontest - mein Beitrag

6

13.11.2009, 11:24

Ok danke schonmal für die schnellen Antworten! Hab aber noch paar Fragen dazu;) Ich hab jetzt mal nen leeren Funktionsrumpf dazugeschrieben, dann kommt der Fehler, dass die Callback Funktion schon einen Funktionsrumpf hat, das heißt doch ich definiere sie durch den Aufruf der Callbackfunktion oder?

Ich glaub diese Aufgabe muss auch noch anders gelöst werden können.. weiß nur noch nicht wie^^
Errare humanum est.. leider oder zum Glück?

Werbeanzeige