Linker-Fehler mit dev-cpp [was: frage]



  • Das Menü wurde sehr wahrscheinlich ncht geladen, füge nach dem CreateWindow() noch einen LoadMenu()-Aufruf ein. Hoffentlich hilft dies.



  • GetMenu (hwnd);
    und
    LoadMenu(hInstance,szCmdLine)

    funzen net



  • Hallo, Techmech

    Du hast bei "Wndclass.lpszMenuName" immer noch "szAppName" stehen. szAppName ist kein Menü. Da muß MAKEINTRESOURCE() stehen (siehe mein Code oben im letztn Posting).



  • WNDCLASSEX wc;
    
        wndclass.style            = CS_HREDRAW | CS_VREDRAW;
        wndclass.lpfnWndProc      = WndProc;
        wndclass.cbClsExtra       = 0;
        wndclass.cbWndExtra       = 0;
        wndclass.hInstance        = hInstance;
        wndclass.hIcon            = LoadIcon(NULL, IDI_APPLICATION);
        wndclass.hCursor          = LoadCursor (NULL, IDC_ARROW);
        wndclass.hbrBackground    = (HBRUSH) GetStockObject (WHITE_BRUSH);      
        wc.lpszMenuName           = MAKEINTRESOURCE(IDM_MENU1);
        wndclass.lpszClassName    = szAppName;
    
        RegisterClassEx (&wc);
    

    `IDM_MENU' undeclared (first use this function)
    [Build Error] [Menudemo.o] Error 1

    -.-

    übrigens ich hbae das gefühl das meine .rc datei nicht benutzt wird. kann man die spezifisch einlinken?



  • Ist doch klar:

    In der .rc-Datei hast Du dein Menü mit

    MENUDEMO MENU DISCARDABLE
    

    "MENUDEMO" benannt, versuchst hier aber mit

    wc.lpszMenuName           = MAKEINTRESOURCE(IDM_MENU1);
    

    ein Menü namens "IDM_MENU1" einzbinden (vermutlich hast Du die Zeile einfach aus meinem Posting kopiert, ohne sie zu verstehen 😉 ).
    Außerdem fehlt in Deiner resource.h die Definition des IDs des Menüs. Vorschlag dafür:

    #define MENUDEMO 1
    

    (in der obersten Zeile einfügen).

    Mir scheint, Du hast einige Verständnisprobleme (ist keine Schande 🕶 ):

    Schau Dir Deine letzten Postings noch mal an. Um 12:42 hieß Deine WNDCLASSEX noch "wndclass", um 14:37 heißt sie "wc". 😮

    WNDCLASSEX wc;//wc oder wndclass???
    
        wndclass.style            = CS_HREDRAW | CS_VREDRAW;
        wndclass.lpfnWndProc      = WndProc;
        wndclass.cbClsExtra       = 0;
        wndclass.cbWndExtra       = 0;
        wndclass.hInstance        = hInstance;
        wndclass.hIcon            = LoadIcon(NULL, IDI_APPLICATION);
        wndclass.hCursor          = LoadCursor (NULL, IDC_ARROW);
        wndclass.hbrBackground    = (HBRUSH) GetStockObject (WHITE_BRUSH);    
    //**********************  
        wc.lpszMenuName           = MAKEINTRESOURCE(IDM_MENU1);//wc oder wndclass???
    //**********************
        wndclass.lpszClassName    = szAppName;
    
        RegisterClassEx (&wc);//wc oder wndclass???
    

    Dir sollte aufgefallen sein, daß bei API-Programmen alle VarialbenTYPEN mit Großbuchstaben geschrieben werden (UINT, HINSTANCE, WPARAM, LPARAM) die Benennung der Variablen aber klein bzw. gemischt (msg, hInstance, wParam). Das gilt aber nur für den cpp-Code, nicht für die Resourcenscripts und die IDs. In diesem Fall gibt es nur ungeschriebene Gesetze, Konventionen.

    Also zum Verständnis: msg ist der Name einer Variable vom Typ UINT.

    WNDCLASSEX ist eine Datensturktur (eigentlich eine mehrdimensionale Variable), in der die Fensterparameter festgelegt werden. "wc" oder "wndclass" ist der Name des Fensters, das aus diesen Daten aus der WNDCLASSEX-Struktur aufgebaut wird. Die Struktur kann also unter verschiedenen Namen mehrfach belegt werden. Der Name kann willkürlich gewählt werden (außer "WNDCLASSEX"), muß aber bei allen Parametern für jeweils ein Fenster gleich sein!

    Die rc-Datei kann man nicht spezifisch einlinken, sondern nur die .res-Datei (Resourcen-Datei im Binärformat, wird aus der rc-Datei kompiliert). Wenn Du eine integrierte Entwicklungsumgebung benutzt, sollte diese das Einbinden der .res selbständig vornehmen (evtl. mußt Du sie in einer Projektdatei angeben, das kann ich aber aus der Ferne nicht sagen). Bei einem Kommandozeilenkompiler mußt Du die .res-Datei als Kommandozeilenparameter angeben.

    Übrigens hast Du nach einer "afxres.h" gefragt. Kenne ich nicht, wofür soll die sein?

    So, das wars erstmal für heute.
    Viel Erfolg.



  • so habes jetzt so aber hm...

    #define MENUDEMO 1
    wndclass.lpszMenuName = MAKEINTRESOURCE(MENUDEMO);

    RegisterClassEx (&wc); da gehts ohne menü
    RegisterClass (&wndclass); da sagt der fehlermeldung unicode also habe ich wc genommen. eine rc datei habe ich nicht in eine res datei umgewandelt...

    so jetzt habe ich wiedereinaml ein fenster ohne menü...



  • guck mal in deinen dev-cpp ordner.....unter examples und dort dann in den ordner WinMenu, dann klickst auf WinMenu.dev und kompiliersts und startests.......dann siehst ne Windows-Anwendung mit Menü......und dann guckst dir den Code an und schaust ma was dort anders ist als bei Dir?

    viel Glück!



  • Du mußt ja auch nicht nur RegisterClass() ändern, sondern die Strukturdeklaration auch. "WNDCLASSEX wndclass"!!! Da steht immer noch wc. Schau noch mal in mein letztes Posting. Da habe ich im Code die Fehler kommentiert.

    Ist doch klar: Du initialisierst ein Fenster namens "wc", besetzt dann die Werte für ein Fenster namens "wndclass" 😮 (was nicht initialisiert ist) und registrierst wieder ein Fenster namens "wc". 😕 Paßt doch irgendwie nicht, oder?
    In diesem Fall erstellt Windows eben ein Fenster namens "wc" ohne Werte, also nur mit Default-Werten, und natürlich ohne Menü. :p

    Und die RC-Datei muß auch in eine .res umgewandelt werden, hilft nix.

    Übrigens habe ich herausgefunden, was afxres.h ist. Das ist die Header-Datei für die MFC (Microsoft Foundation Classes), die Klassenbliothek von MS, die die API objektorientiert kapselt. Petzold fügt die bei allen seinen Programmen ein, sagt aber auf Seite 402, daß die eigentlich gar nicht gebraucht wird. Kannst sie also weglassen.



  • könnte ma vll einer ein fertiges programm psoten das funktioniert?



  • Hier das Hauptprogramm:

    //Hauptprogramm
    #include <windows.h>
    #include "resource.h"
    
    LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM);
    
    int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR szCmdLine, int iCmdShow)
    {
       WNDCLASSEX	wc;//Typ der Fensterklasse
       HWND	hWnd; 	//Handle to a Window
       MSG	msg;		//Message
    
       const char szAppName[] = "ein Menü";
       wc.cbSize 		= sizeof(WNDCLASSEX);
       wc.style			= CS_HREDRAW| CS_VREDRAW; //Fensterstil
       wc.lpfnWndProc = WndProc;  //long Pointer to a function-speichert die Addresse der Function,
       									//die die Nachrichten bearbeiten soll.
       wc.cbClsExtra	= 0;//reserviert zusätzlich Speicher für die Fensterklasse.
       wc.cbWndExtra	= 0;//reserviert zusätzlich Speicher für das Fenster.
    
       wc.hInstance	= hInstance; //Handle der Programminstanz
       wc.hCursor		= LoadCursor(NULL,IDC_ARROW);//Typ des Cursers; NULL = kein Cursor bzw. Standard
       wc.hIcon			= LoadIcon(NULL,IDI_APPLICATION);//Programmsymbol; NULL = kein eigenes Symbol bzw. Standard.
       wc.hbrBackground  = (HBRUSH)GetStockObject(WHITE_BRUSH);//Hintergrundfarbe
       wc.hIconSm 			= LoadIcon(NULL, IDI_APPLICATION);
       wc.lpszClassName  = szAppName;//sz = string zero-terminated=String mit Abschlußzeichen 0
       									 //speichert den Namen der Fensterklasse.
       wc.lpszMenuName   = MAKEINTRESOURCE(IDM_MENU1);//Name des Menüs in der Ressourcen-Datei. NULL = kein Menü
    
       if (!RegisterClassEx (&wc))//Meldet das Fenster im Fenstermanager bei Windows an.
    	{
                LPVOID lpMsgBuf;
                FormatMessage (FORMAT_MESSAGE_ALLOCATE_BUFFER |
                    FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
                    NULL, GetLastError (),
                    MAKELANGID (LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
                    (LPTSTR) &lpMsgBuf, 0, NULL);
                MessageBox (NULL, (LPCTSTR)lpMsgBuf, "Error RegisterClass Main Window:",
                    MB_OK | MB_ICONSTOP);
                LocalFree (lpMsgBuf);
                return FALSE;//Diese Funktion gibt die Ursache eines Registrationsfehlers aus.
            }
    
    hWnd = CreateWindowEx(WS_EX_CLIENTEDGE, szAppName,/*Fenster erstellen*/ //Parameter: "lpClassName"
       		      "erstes Menü",    //Parameter: "lpWindowName", steht in der Titelleiste
                            WS_OVERLAPPEDWINDOW|WS_VISIBLE, //Parameter: "dwStyle"
                            CW_USEDEFAULT,	//X-Position auf dem Monitor, Parameter "x"
                            CW_USEDEFAULT,   //Y-Position auf dem Monitor, Parameter "y"
                            CW_USEDEFAULT,	//Fensterbreite, Parameter "nWidth
                            CW_USEDEFAULT,	//Fensterhöhe, Parameter "nHight"
                            NULL,					//Parameter "hMenu"
                            NULL,					//Parameter "hWindowParent", Elternfenster
                            hInstance,        //HINSTANCE
                            NULL);            //Parameter "lpPARAM"
       ShowWindow (hWnd, iCmdShow);	//"iCmdShow" legt die Darstellungsform des Fensters fest (z. B.
                                     //minimiert, maximiert, versteck o.ä.. Kann auch mit einer
                                     //Konstanten belegt werden, darf aber nur einmal mit der Übergabe
                                     //iCmdShow belegt werden.
       UpdateWindow (hWnd);	//Fenster neu zeichnen nach Veränderungen.
    	while (GetMessage(&msg, NULL,0,0))	//2. Parameter = hWnd = Handle des Fensters, dessen
       												//Botschaft überprüft werden soll. Wenn hWnd = NULL, werden
                                           //alle Fenster der Anwendung abgefragt.
       {
    		TranslateMessage(&msg);	//Nachrichtenschleife
          DispatchMessage(&msg);
       }
    	return msg.wParam;
    }
    LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
    
    {
    	char string[255];
    	switch (msg)
       {
       	case WM_CLOSE:
          	DestroyWindow(hWnd);
             break;
          case WM_DESTROY:
          	PostQuitMessage(0);
             return 0;
          case WM_COMMAND:
          	switch(LOWORD(wParam))
             {
             	case IDM_FILE_OPEN:
                	LoadString(GetModuleHandle(NULL), IDS_STRING_OPEN, string, sizeof(string));
                   MessageBox(hWnd, string, "Öffnen der Datei", MB_ICONINFORMATION);
                   break;
                case IDM_FILE_SAVE:
                	LoadString(GetModuleHandle(NULL), IDS_STRING_SAVE, string, sizeof(string));
                   MessageBox(hWnd, string, "Speichern der Datei", MB_ICONINFORMATION);
                   break;
                case IDM_HELP_\1:
                	LoadString(GetModuleHandle(NULL), IDS_STRING_ABOUT, string, sizeof(string));
                   MessageBox(hWnd, string, "geschrieben am 21.01.2006", MB_ICONINFORMATION);
                   break;
                case IDM_FILE_EXIT:
                	DestroyWindow(hWnd);
                	break;
          	}
       	break;
       }
    	return DefWindowProc(hWnd, msg, wParam, lParam);
    }
    

    Moduldefinitionsdatei:

    //w32App.def
    EXETYPE WINDOWS
    CODE PRELOAD MOVEABLE DISCARDABLE
    DATA PRELOAD MOVEABLE
    HEAPSIZE 8192
    STACKSIZE 8192
    

    Resourcenheader:

    //resource.h
    #define IDM_MENU1 1
    #define IDS_STRING_OPEN	102
    #define IDS_STRING_SAVE	103
    #define IDS_STRING_EXIT	108
    #define IDS_STRING_ABOUT 903
    
    #define IDM_FILE_OPEN 102
    #define IDM_FILE_SAVE 103
    #define IDM_FILE_EXIT 108
    #define IDM_HELP_ABOUT 903
    

    Resourcen\1:

    //erstes_Menü.RC
    #include "resource.h"
    
    IDM_MENU1 MENU DISCARDABLE
    BEGIN
     POPUP "&Datei"
     BEGIN
    /*Hier wurden nur die Konstanten statt der ID-Strings eingefügt. 
    Die Konstanten in "resource.h" sind definiert, daher ist beides möglich.*/
      MENUITEM "&Öffnen", 102
      MENUITEM "&Speichern", 103
      MENUITEM SEPARATOR
      MENUITEM "&Beenden", 108
     END
    
     POPUP "&Hilfe"
     BEGIN
      MENUITEM "&Über", 903
     END
    
    END
    
    STRINGTABLE 
    
    BEGIN
     102, "Datei öffnen"
     103, "Datei Speichern"
     108, "Programm Beenden"
     903, "Infos zum Programm"
    END
    


  • build error 1 :>



  • Kannitvastan. 😕 😮 Habe das Prog vorher noch kompiliert und überprüft (wie gesagt: Borland C++5.02), funzte einwandfrei. Vielleicht eine Spezialität Deines Kompilers.


Anmelden zum Antworten