undefined reference to `ChooseColorA@4'
-
Hallo, ich hab mal wieder ein Problem. Da ich keine Ahnung hab, wo der Fehler ist, kommt erstmal ne Menge Quellcode. Ich wäre sehr dankbar, wenn ihr euch das mal Anschauen würdet.
Stein und Spalte sind selbst geschriebene Klassen.
Wenn ich den Teil mit ChooseColor rausmache wirds problemlos kompiliert.
Ein Beispielprogramm aus meinem Buch, das die Funktion verwendet funktioniert
Edit: Der wichtige Teil ist in LRESULT CALLBACK WndProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam){ ab Zeile 894 Gewinnt.h
// Windows Header Files: #include <windows.h> #include <commdlg.h> //C++ Runtime Header Files #include <string> #include <vector> #include <iostream> //eigene Header Files #include "Spalte.h" #include "Resource.h" //verwendete Konstanten const int MAXSTEINE = 6; const int ANZSPALTEN = 7; //globale Variablen //zweidimensionales Array zum Speichern der gesetzten Steine; //0 heisst kein Stein; 1 heißt Stein von Spieler 1; 2 heißt Stein von Spieler 2; static BYTE byZustSteine[ANZSPALTEN][MAXSTEINE]={{0}}; //verwendeter Funktionen LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM) ; LRESULT CALLBACK SpalteWndProc (HWND, UINT, WPARAM, LPARAM); BOOL CALLBACK AboutDlgProc (HWND, UINT, WPARAM, LPARAM); BOOL CALLBACK SpGwnDlgProc (HWND hDlg, UINT message,WPARAM wParam, LPARAM lParam); //überprüft ob ein Spieler gewonnen hat bool HatGewonnen(BYTE[][MAXSTEINE],BYTE, const int, const int); BOOL ChooseColor(LPCHOOSECOLOR lpcc); //eigene Nachrichten //WPARAM enthält wessen Farbe geändert wurde //LPARAM enthält die Farbe UINT PN_CLRCHANGED=WM_APP+1;4 Gewinnt.cpp
/*----------------------------------------------------------------------- Vier Gewinnt von Jonas Peter. Dieses Programm befindet sich noch in der Entwicklung -----------------------------------------------------------------------*/ #include "4 Gewinnt.h" #include <windows.h> #include <commdlg.h> using namespace std; int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, int iCmdShow) { static string sAppName = TEXT ("Vier Gewinnt") ; HWND hwnd ; MSG msg ; WNDCLASS wndclass ; wndclass.style = CS_HREDRAW | CS_VREDRAW ; wndclass.lpfnWndProc = WndProc ; wndclass.cbClsExtra = 0 ; wndclass.cbWndExtra = 0; wndclass.hInstance = hInstance ; wndclass.hIcon = LoadIcon(hInstance,MAKEINTRESOURCE(IDI_VIERGEWINNT)) ; wndclass.hCursor = LoadCursor (NULL, IDC_ARROW) ; wndclass.hbrBackground = (HBRUSH) GetStockObject (WHITE_BRUSH) ; wndclass.lpszMenuName = MAKEINTRESOURCE(IDR_MENUE) ; wndclass.lpszClassName = sAppName.c_str(); if (!RegisterClass (&wndclass)) { // UNICODE-Compilierung ist die einzige realistische Fehlermöglichkeit MessageBox (NULL, TEXT ("Programm arbeitet mit Unicode und setzt Windows NT voraus!"), sAppName.c_str(), MB_ICONERROR) ; return 0 ; } wndclass.lpfnWndProc =SpalteWndProc; //Für jedes Childfenster extra Speicherbereich für einen Zeiger vom Typ Spalte anfordern wndclass.cbWndExtra =sizeof(long); wndclass.hIcon=NULL; wndclass.lpszClassName="Spalte"; wndclass.hbrBackground = (HBRUSH) GetStockObject (LTGRAY_BRUSH) ; RegisterClass (&wndclass); hwnd = CreateWindow (sAppName.c_str(), // Name der Fensterklasse TEXT ("Vier Gewinnt"), // Fenstertitel WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, // X-Position des Fensters CW_USEDEFAULT, // Y-Position des Fensters CW_USEDEFAULT, // Fensterbreite CW_USEDEFAULT, // Fensterhöhe NULL, // übergeordnetes Fenster NULL, // Menü hInstance, // Programm-Kopiezähler (Programm-ID) NULL); // zusätzliche Parameter ShowWindow (hwnd, iCmdShow) ; UpdateWindow (hwnd) ; while (GetMessage (&msg, NULL, 0, 0)) { TranslateMessage (&msg) ; DispatchMessage (&msg) ; } return msg.wParam ; } LRESULT CALLBACK WndProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam){ //Handles für die Childfenster static HWND hwndSpalte[ANZSPALTEN]; //Größenangaben für die Spalten const int lSpalteBreite=50, lSpalteHoehe=lSpalteBreite*MAXSTEINE; //für die Farbauswahl static CHOOSECOLOR cc; static COLORREF acrCustColors[16]; static COLORREF crCurrent=0; cc.lStructSize = sizeof (CHOOSECOLOR) ; cc.hwndOwner = NULL ; cc.hInstance = NULL ; cc.rgbResult = RGB (0x80, 0x80, 0x80) ; cc.lpCustColors = acrCustColors ; cc.Flags = CC_RGBINIT | CC_FULLOPEN ; cc.lCustData = 0 ; cc.lpfnHook = NULL ; cc.lpTemplateName = NULL ; switch (message) { case WM_CREATE: static HINSTANCE hInstance; hInstance=((LPCREATESTRUCT) lParam)->hInstance; //Spalten Erzeugen for(int i=1;i<=ANZSPALTEN;i++) { hwndSpalte[i]=CreateWindow("Spalte",NULL,//KlassenName , Titelleiste WS_CHILDWINDOW|WS_VISIBLE, //Fensterstil (i*lSpalteBreite),lSpalteBreite, //Position lSpalteBreite, lSpalteHoehe, //Breite, Höhe hwnd,(HMENU) (i), //Parent Handle, ChildID (HINSTANCE) GetWindowLong(hwnd, GWL_HINSTANCE), //KopieZähler NULL);//Extras } return 0 ; case WM_SYSCOMMAND: switch (wParam) { //Nach Maximieren zum neu zeichnen auffordern case SC_MAXIMIZE: InvalidateRect(hwnd,NULL,false); UpdateWindow(hwnd); break; default: DefWindowProc(hwnd,message,wParam,lParam); break; } return 0; case WM_COMMAND: switch (LOWORD( wParam )) { case IDM_\1: DialogBox( hInstance, MAKEINTRESOURCE(IDD_ABOUT), hwnd, AboutDlgProc ); return 0; case IDM_OPTIONEN_FARBESP1: if (ChooseColor(&cc)==TRUE) { crCurrent = cc.rgbResult; //Alle Spalten über die Farbänderung informieren for(int i=0;i<ANZSPALTEN;i++) { SendMessage(hwndSpalte[i],PN_CLRCHANGED,(WPARAM)1,(LPARAM)crCurrent); } } return 0; } return 0; case WM_DESTROY: PostQuitMessage (0) ; return 0 ; } return DefWindowProc (hwnd, message, wParam, lParam) ; } LRESULT CALLBACK SpalteWndProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam){ HDC hdc ; RECT rect ; PAINTSTRUCT ps; //Zeiger auf den jeweiligen Speicherbereich, in dem die Daten der Spalten sind Spalte *pspSpalte=NULL; static COLORREF crSteinFarbe=0x0; const COLORREF crSteinRot=RGB(200,0,0),crSteinBlau=RGB(0,0,200); static BYTE byAktSpieler=1; //zweidimensionales Array zum Speichern der gesetzten Steine; //0 heisst kein Stein; 1 heißt Stein von Spieler 1; 2 heißt Stein von Spieler 2; switch (message) { case WM_CREATE: //Größe des Childfensters rausfinden GetClientRect(hwnd,&rect); //Speicherbereich für eine Spalte in der größe des Childfensters anfordern. //im extra angeforderten Speicher einen Zeiger auf diesen Bereich speichern SetWindowLong(hwnd,0,(long)new Spalte(hwnd, MAXSTEINE, rect.right, rect.bottom,RGB(0,200,0))); return 0 ; case WM_PAINT: pspSpalte=(Spalte*)GetWindowLong(hwnd,0); hdc = BeginPaint(hwnd, &ps); pspSpalte->zeichne(hdc); EndPaint(hwnd, &ps); return 0; case WM_LBUTTONUP: //Überprüfen welcher Spielr Aktiv ist und entsprechende Farbe setzen if(1==byAktSpieler) { crSteinFarbe=crSteinRot; } else { crSteinFarbe=crSteinBlau; } //Zeiger auf das Spaltenobjekt holen, der zum aktuellen Fenster gehört pspSpalte=(Spalte*)GetWindowLong(hwnd,0); //Stein in der aktuellen Farbe setzen //Wenn die Spalte voll ist, wird der Funktionsaufruf beendet, //ohne dass byZustSteine geändert wird und byAktSpieler if(!pspSpalte->setzeStein(crSteinFarbe)) { return 0; } //In byZustSteine speichern, wo der Stein gesetzt wurde byZustSteine[GetWindowLong(hwnd,GWL_ID)][pspSpalte->getFuellHoehe()]=byAktSpieler; //Fenster zum neu zeichnen auffordern InvalidateRect(hwnd,NULL,false); UpdateWindow(hwnd); //Steine zu testzwecken ausgeben for(int j=0;j<MAXSTEINE;j++) { cout << endl; for(int i=0;i<ANZSPALTEN;i++) { cout << (int)byZustSteine[i][j]; } } //Überprüfen, ob der Spieler gewonnen hat. Wenn ja Programm beenden if(HatGewonnen(byZustSteine,byAktSpieler,GetWindowLong(hwnd,GWL_ID),pspSpalte->getFuellHoehe())) { //Wenn Spieler 1 Aktiv SP1GWN Dialogbox aufrufen if(1==byAktSpieler) { DialogBox((HINSTANCE)GetWindowLong(hwnd, GWL_HINSTANCE), MAKEINTRESOURCE(IDD_SP1GWN), hwnd, SpGwnDlgProc ); } //Wenn Spieler 2 Aktiv SP2GWN Dialogbox auffrufen else { DialogBox((HINSTANCE)GetWindowLong(hwnd, GWL_HINSTANCE), MAKEINTRESOURCE(IDD_SP2GWN), hwnd, SpGwnDlgProc ); } SendMessage(GetParent(hwnd), WM_DESTROY, 0, 0); } //anderen Spieler als aktiv setzen if(1==byAktSpieler) { byAktSpieler=2; } else { byAktSpieler=1; } return 0; case WM_DESTROY: pspSpalte=(Spalte*)GetWindowLong(hwnd,0); delete pspSpalte; PostQuitMessage (0) ; return 0 ; } return DefWindowProc (hwnd, message, wParam, lParam) ; } //Prozedur für den About dialog BOOL CALLBACK AboutDlgProc (HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) { switch (message) { case WM_INITDIALOG : return TRUE ; case WM_COMMAND : switch (LOWORD (wParam)) { case IDOK : case IDCANCEL : EndDialog (hDlg, 0) ; return TRUE ; } break ; } return FALSE ; } //Prozedur für den About dialog BOOL CALLBACK SpGwnDlgProc (HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) { switch (message) { case WM_INITDIALOG : return TRUE ; case WM_COMMAND : switch (LOWORD (wParam)) { case IDOK : case IDCANCEL : EndDialog (hDlg, 0) ; return TRUE ; } break ; } return FALSE ; }Buildlog
-------------- Build: Debug in Vier Gewinnt ---------------
Compiling: 4 Gewinnt.cpp
E:\99VerlegtvonC\Eigene Dateien\Schule\IT Projekt\Vier Gewinnt\4 Gewinnt.cpp:19: warning: unused parameter 'hPrevInstance'
E:\99VerlegtvonC\Eigene Dateien\Schule\IT Projekt\Vier Gewinnt\4 Gewinnt.cpp:19: warning: unused parameter 'szCmdLine'
E:\99VerlegtvonC\Eigene Dateien\Schule\IT Projekt\Vier Gewinnt\4 Gewinnt.cpp:286: warning: unused parameter 'lParam'
E:\99VerlegtvonC\Eigene Dateien\Schule\IT Projekt\Vier Gewinnt\4 Gewinnt.cpp:308: warning: unused parameter 'lParam'
Linking console executable: bin\Debug\Vier Gewinnt.exe
obj\Debug\4 Gewinnt.o: In function `Z7WndProcP6HWND__jjl':E:/99VerlegtvonC/Eigene Dateien/Schule/IT Projekt/Vier Gewinnt/4 Gewinnt.cpp:149: undefined reference to `ChooseColorA@4'
collect2: ld returned 1 exit status
Process terminated with status 1 (0 minutes, 2 seconds)
1 errors, 4 warningsHeld
-
http://msdn2.microsoft.com/en-us/library/ms646912.aspx sagt du musst Comdlg32.lib einbinden!
-
Die müsste ich irgendwo in den Einstellungen bei Codeblocks schon eingebunden haben. Ein anderes Programm, dass diese Funktion benutzt funktioniert ja ohne Probleme mit den selben Einstellungen. Deshalb bin ich ja so ratlos.
Ich erstell jetzt mal ein neues Projekt mit Standardeinstellungen und schau ob's funktioniert.Edit: geht immer noch nicht. Ich hab mal das ganze Projekt hochgeladen.
http://rapidshare.com/files/35458358/Vier_Gewinnt.rar.html
Ich wäre wirklich froh, wenn sich jemand die Zeit nähme sich das mal anzuschauen.Held
-
Buildlog schrieb:
undefined reference to `ChooseColorA@4'
Der sucht den "ChooseColor ()", den Du in der "4 Gewinnt.h" zwar deklariert hast, aber nirgendwo definiert.
Kommentiere die Deklaration mal aus :// in 4 Gewinnt.h // BOOL ChooseColor(LPCHOOSECOLOR lpcc);
-
Wie geeky schon schrieb, du musst die comdlg32.lib einbinden.
Ansonsten kannst Du die Deklaration von BOOL ChooseColor(LPCHOOSECOLOR lpcc); auch weglassen. Die ist ja in der commdlg.h schon drin.
-
Ich hab die Bibliothek nochmal explizit beim Linker angegeben und jetzt funktioniert's auch. Ich dachte, es reicht wenn ich den übergeordneten Ordner angebe.
Ich frage mich nur noch, warum dieses Programm funktioniert, ohne dass ich die Bibliothek einbinde./*--------------------------------------------------- COLORS3.C -- COLORS3.C -- Farbauswahl über COMMDLG (c) Charles Petzold, 1998 ---------------------------------------------------*/ #include <windows.h> #include <commdlg.h> int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, int iCmdShow) { static CHOOSECOLOR cc ; static COLORREF crCustColors[16] ; cc.lStructSize = sizeof (CHOOSECOLOR) ; cc.hwndOwner = NULL ; cc.hInstance = NULL ; cc.rgbResult = RGB (0x80, 0x80, 0x80) ; cc.lpCustColors = crCustColors ; cc.Flags = CC_RGBINIT | CC_FULLOPEN ; cc.lCustData = 0 ; cc.lpfnHook = NULL ; cc.lpTemplateName = NULL ; return ChooseColor (&cc) ; }
-
In diesem Programm sehe ich aber nicht welche Linker Optionen Du angegeben hast.
Zusätzlich gint es auch #pragma comment(lib,...) was ich imer verwende.
-
Du kannst es bei dir mal ausprobieren. Ich bin mir ziemlich sicher, dass ich die Bibliothek beim Linker nicht explizit angegeben habe. Aber eigentlich ist es egal, Hauptsache mein Programm läuft.
Danke für die geduldige Hilfe.