Ein kleines Problem



  • Hallo zusammen,

    ich bin nicht ganz unbeholfen was das Prorammieren im Allgemeinen angeht (SPS, Roboter, ein klein wenig VB).
    Ich möchte nun die C++ Sprache lernen wofür ich mir das MicrosoftVisualC++ angeschafft habe. Dazu ein wenig Literatur mit Übungsaufgabe.
    Eine dieser kleinen Proggies will nicht laufen. Anhand einer Musterlösung kann ich keinen Fehler in meinem Code erkennen. Trotzdem bekomme ich beim Erstellen folgenden Fehler:

    *Linker-Vorgang läuft...
    setWorld.obj : error LNK2001: Nichtaufgeloestes externes Symbol _setWorld
    Debug/setWorld.exe : fatal error LNK1120: 1 unaufgeloeste externe Verweise
    Fehler beim Ausführen von link.exe.

    setWorld.exe - 2 Fehler, 0 Warnung(en)*

    Ich habe beim Durchsuchen des Forums gesehen, daß das Problem des öfteren auftritt. Leider konnte ich keine für mich passende Antwort finden und nerve euch deshalb.

    Der Code dazu:

    *void setWorld (HWND hWnd, HDC hdc, long xMin, long xMax, long yMin, long yMax);
    LRESULT CALLBACK WndProc (HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)

    {
    switch (message)
    {
    case WM_PAINT:
    {
    long xMin = -80, xMax = 150, yMin = -40, yMax = 120;
    PAINTSTRUCT ps;
    HDC hdc;
    HPEN hPen1, hPen2, hOldPen;
    HGDIOBJ hBr = GetStockObject (HOLLOW_BRUSH);

    hdc = BeginPaint (hWnd, &ps);
    setWorld (hWnd, hdc, xMin, xMax, yMin, yMax);

    MoveToEx (hdc, xMin, 0, NULL);
    LineTo (hdc, xMax, 0);
    MoveToEx (hdc, xMax-4, 2, NULL);
    LineTo (hdc, xMax, 0);
    LineTo (hdc, xMax-4, -2);
    TextOut (hdc, xMax -4, -2, "x", 1);

    MoveToEx (hdc, yMin, 0, NULL);
    LineTo (hdc, 0, yMax);
    MoveToEx (hdc, -2, yMax-4, NULL);
    LineTo (hdc, 0, yMax);
    LineTo (hdc, 2, yMax-4);
    TextOut (hdc, 2, yMax -4, "y", 1);

    TextOut (hdc, 2, -1, "(0,0)", 5);

    hPen1 = CreatePen (PS_DASHDOT, 0, RGB (0, 0, 255));
    hOldPen = SelectObject (hdc, hPen1);
    SelectObject (hdc, hBr);

    Rectangle (hdc, -100, -100, 100, 100);

    hPen2 = CreatePen (PS_SOLID, 1, RGB (255, 0, 0));
    SelectObject (hdc, hPen2);
    Ellipse (hdc, 0, 0, 100, 100);
    Ellipse (hdc, -100, -100, 0, 0);

    SelectObject (hdc, hOldPen);
    DeleteObject (hPen1);
    DeleteObject (hPen2);

    EndPaint (hWnd, &ps);
    break;
    }

    case WM_DESTROY:
    PostQuitMessage (0);
    break;

    default:
    return DefWindowProc (hWnd, message, wParam, lParam);
    }
    return 0;
    }*



  • Hat deine setWorld-Funktion auch eine Definition? Falls nein, Fall erledigt 😉 Falls ja, dann findet der Linker sie nicht. Ist dein Programm auf mehrere Dateien aufgeteilt?

    BTW solltest du dir überlegen, ob du wirklich von Anfang an Windows-Programmierung betreiben willst. Beim Verstehen von C++ hilft dir das nicht wirklich. Ich würde sagen, einen Schritt nach dem anderen ... wobei WinAPI nicht notwendigerweise der zweite Schritt sein muss.



  • Danke für die schnelle Antwort 👍
    Mhm... in der Musterlösung wird die setWorld-Funktion auch nicht extra definiert 😮
    Da wurde das einfach genauso nach der WinMain(), InitApplication() und InitInstance() angehängt.

    Das Programm besteht nur aus einer Datei und ist nicht aufgeteilt.

    Vermutlich hast du Recht was Windows und WinApi angeht.
    Ich versuch`S mal weiter.

    Danke!



  • Ist die setWorld() vielleicht bereits vorgegeben und du hast vergessen, die entsprechende(n) Datei(en) in dein Projekt einzubinden?



  • Hallo nochmals,

    ich hab jetzt dieses Musterprogramm eingegeben.
    Derselbe Fehler 😕

    @Cocaine
    Nein, die setWorld ist noch nicht vorgegeben.

    Wenn ich die Funktion definiere kommt die gleiche Fehlermeldung. Wobei ich nicht ausschliessen will, daß meine Definition nicht richtig ist.
    Wie definiert man(n) diese Funtion denn eigentlich richtig?



  • Wenn du c++ lernen willst dann empfehle

    1.) Mach c++ Programme und erstmal finger weg von der winapi
    2.) kopiere nicht einfach code und versuche ihn zum laufen zu bringen

    Sieht so aus als ob du dir irgendwo source gezogen hast (von einem spiel) und versuchst das zu compilieren.



  • hjgjgh schrieb:

    Wenn du c++ lernen willst dann empfehle

    1.) Mach c++ Programme und erstmal finger weg von der winapi
    2.) kopiere nicht einfach code und versuche ihn zum laufen zu bringen

    Sieht so aus als ob du dir irgendwo source gezogen hast (von einem spiel) und versuchst das zu compilieren.

    Ich habe mir keine source gezogen.
    Dies ist eine Übungsaufgabe die in einem Begleitbuch für C++ steht.
    Hab ich Buchstabe für Buchstabe selber eingegeben. Wie gesagt funktioniert auch die Musterlösung nicht.
    Ergo -> fehlerhafter Code.
    Deshalb frage ich hier nach.
    Weil ich als Anfänger diesen Fehler wahrscheinlich nicht finde.
    Vielleicht ist es auch etwas schwieriger als "älterer Mensch" so schnell zu lernen oder kapieren wie das mal war.



  • Roland.K schrieb:

    Ergo -> fehlerhafter Code

    Der Code ansich ist nicht fehlerhaft, sonst hättest du Compilerfehler.

    Roland.K schrieb:

    Wenn ich die Funktion definiere kommt die gleiche Fehlermeldung. Wobei ich nicht ausschliessen will, daß meine Definition nicht richtig ist.
    Wie definiert man(n) diese Funtion denn eigentlich richtig?

    void setWorld(HWND hWnd, HDC hdc, long xMin, long xMax, long yMin, long yMax);
    

    Das ist die Deklaration der Funktion. Sowas brauchst du normalerweise nur für Forwärts-Deklaration oder wenn die Funktion in einer anderen Übersetzungseinheit benötigt wird. Die Definition (oder auch Implementierung) der Funktion stellt dann den eigentlichen Code dar.

    void setWorld(HWND hWnd, HDC hdc, long xMin, long xMax, long yMin, long yMax)
    {
        // was immer auch die Funktion machen soll
    }
    

    Und der Linker-Fehler besagt einfach, dass die Funktion benutzt wird aber keine Implementierung gefunden werden kann. Schau nochmals deine Literatur durch, manchmal sind Funktionen in einem früheren oder späteren Kapitel zu finden, weil dann nochmals explizit darauf eingegangen wird.

    btw:
    Benutze das nächste mal bitte Code-Tags, sonst ist der Code einfach unleserlich.



  • Sorry, ich will nicht nerven, aber egal was ich verändere, auch wenn ich es so mache wie groovemaster2002 gepostet hat, ändert sich nichts.
    Der Compiler gibt keinen Fehler, der Linker will nicht 😞
    Ich habe jetzt einmal die Originalfassung des Buchautors nochmals abgetippt.

    #include <windows.h>
    
    //Globale Variablen deklarieren:
    
    HINSTANCE hInst   = 0;										//Instanz-Handle
    char szAppName[]  = "setWorld-Test";						//Name der Applikation
    char szTitle[]    = "setWorld-Test";						//Titel des Fensters
    
    //Prototypen eigener Funktionen:
    
    BOOL InitApplication();
    BOOL InitInstance(int);
    LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM);
    
    //Hier wird in das Programm eingestiegen
    
    int WINAPI WinMain( HINSTANCE hInstance,
    				    HINSTANCE hPrevInstance,
    					LPSTR     lpCmdLine,
    					int       nCmdShow)
    {
    	MSG msg;												//Platzhalter für eine Message
    	hInst = hInstance;										//Handle der Instanz an eine
    															//globale Variable zuweisen
    	if (!InitApplication () )								//Fenster registrieren
    		return FALSE;
    	if (!InitInstance (nCmdShow) )							//Hauptfenster erzeugen
    		return FALSE;
    	while (GetMessage (&msg,NULL,0,0) )						//Schleife für Messages
    	{
    		TranslateMessage (&msg);
    		DispatchMessage (&msg);
    	}
    	return (msg.wParam);
    }
    
    BOOL InitApplication()
    {
    
    	WNDCLASSEX  wc;											//Definiert die Fensterklasse
    
    	//Hier werden die Eigenschaften der Fensterklasse festgelegt:
    	wc.cbSize        = sizeof (WNDCLASSEX);					//Anzahl der Bytes dieser Struktur
    	wc.style         = CS_HREDRAW | CS_VREDRAW;				//Fensterstil
    	wc.lpfnWndProc   = (WNDPROC)WndProc;					//Fensterprozedur
    	wc.cbClsExtra    = 0;									//Hier kann zusaetzlicher Speicher
    	wc.cbWndExtra    = 0;									//für das Programm reserviert werden
    	wc.hInstance     = hInst;								//Handeln der Instanz
    	wc.hIcon         = LoadIcon (NULL, IDI_APPLICATION);	//Standart_Icon
    	wc.hCursor       = LoadCursor (NULL, IDC_ARROW);		//Standart-Cursor
    	wc.hbrBackground = (HBRUSH)GetStockObject(LTGRAY_BRUSH);	//Hintergrundfarbe
    	wc.lpszMenuName  = NULL;								//Menue-Name. NULL = keine Name
    	wc.lpszClassName = szAppName;							//Name der Fensterklasse
    	wc.hIconSm       = LoadIcon (NULL, IDI_APPLICATION);	//Satndart-Icon (klein)
    
    	//Die Fensterklaase wird hier registriert und das Ergebnis zurückgegeben
    	return RegisterClassEx (&wc);
    }
    
    BOOL InitInstance (int nCmdShow)
    {
    	HWND hWnd;
    	//In diesem Abschnitt wird das Fenster kreiert
    	hWnd = CreateWindow (
    			szAppName,										//Name der Fensterklasse
    			szTitle,										//Titel des Fensters
    			WS_OVERLAPPEDWINDOW,							//Fensterstil (standart)
    			//Hier wird die Lage des Fensters definiert
    			CW_USEDEFAULT,									//X-Koordinate
    			0,												//Y-Koordinate
    			CW_USEDEFAULT,									//Fensterbreite
    			0,												//Fensterhöhe
    			NULL,											//Handle: Elternfenster
    			NULL,											//Handle: Menue
    			hInst,											//Handle des Programms
    			NULL);											//Zeiger auf zusätzlich Daten
    	if ( !hWnd)
    		return FALSE;
    	ShowWindow (hWnd, nCmdShow);							//Fenster anzeigen
    	UpdateWindow (hWnd);									//WM_Paint-Meldung
    	return (TRUE);
    }
    
    void setWorld (HWND hWnd, HDC hdc, long xMin, long xMax, long yMin, long yMax);
    LRESULT CALLBACK WndProc (HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
    
    {
    	switch (message)
    	{
    	case WM_PAINT:
    		{
    			long xMin = -80, xMax = 150, yMin = -40, yMax = 120;
    			PAINTSTRUCT ps;
    			HDC hdc;
    			HPEN hPen1, hPen2, hOldPen;
    			HGDIOBJ hBr = GetStockObject (HOLLOW_BRUSH);
    
    			hdc = BeginPaint (hWnd, &ps);
    			setWorld (hWnd, hdc, xMin, xMax, yMin, yMax);
    
    			MoveToEx (hdc, xMin, 0, NULL);
    			LineTo (hdc, xMax, 0);
    			MoveToEx (hdc, xMax-4, 2, NULL);
    			LineTo (hdc, xMax, 0);
    			LineTo (hdc, xMax-4, -2);
    			TextOut (hdc, xMax -4, -2, "x", 1);
    
    			MoveToEx (hdc, yMin, 0, NULL);
    			LineTo (hdc, 0, yMax);
    			MoveToEx (hdc, -2, yMax-4, NULL);
    			LineTo (hdc, 0, yMax);
    			LineTo (hdc, 2, yMax-4);
    			TextOut (hdc, 2, yMax -4, "y", 1);
    
    			TextOut (hdc, 2, -1, "(0,0)", 5);
    
    			hPen1 = CreatePen (PS_DASHDOT, 0, RGB (0, 0, 255));
    			hOldPen = SelectObject (hdc, hPen1);
    			SelectObject (hdc, hBr);
    
    			Rectangle (hdc, -100, -100, 100, 100);
    
    			hPen2 = CreatePen (PS_SOLID, 1, RGB (255, 0, 0));
    			SelectObject (hdc, hPen2);
    			Ellipse (hdc, 0, 0, 100, 100);
    			Ellipse (hdc, -100, -100, 0, 0);
    
    			SelectObject (hdc, hOldPen);
    			DeleteObject (hPen1);
    			DeleteObject (hPen2);
    
    			EndPaint (hWnd, &ps);
    			break;
    		}
    
    	case WM_DESTROY:
    		PostQuitMessage (0);
    		break;
    
    	default:
    		return DefWindowProc (hWnd, message, wParam, lParam);
    	}
    	return 0;
    }
    

    In der Hoffnung, daß mir jemand weiterhelfen kann 😮
    Vielen Dank

    Roland.K



  • Du hast bestimmt ein Include vergessen. void setWorld wird nirgends definiert. Am besten suchst du mal nach der Implementation von setWorld. Wenn sie in keiner Datei zu finden ist, kannst du das ganze Programm in die Tonne kippen...

    mfg h4xX0r



  • Sodele, jetzt läuft das Ganze.
    Wenn man als Anfänger Fehler macht ist das verzeihbar, aber wenn man zu blöde zum Lesen ist 🙄

    So etwas in der Art hat gefehlt:

    void setWorld(HWND hWnd, HDC hdc, long xMin, long xMax, long yMin, long yMax)
    {
        RECT rc;
        long breite = xMax - xMin,
             hoehe  = yMax - yMin;
    
        GetClientRect(hWnd, &rc);
    
        SetMapMode(hdc, MM_ANISOTROPIC);
    
        SetWindowExtEx(hdc, breite, hoehe, NULL);
        SetViewportExtEx(hdc, rc.right, -rc.bottom, NULL);
    
        SetWindowOrgEx(hdc, xMin, yMax, NULL);  
    }
    

Anmelden zum Antworten