fenster programmieren



  • Hallo Leute,

    ich möchte ein kleines Win32-Programm schreiben, allerdings habe ich keine Ahnung wie man das bei C++ macht. Habe bisher solche Programme immer nur mit Java (da gibt es für solche Dinge jede menge fertige Klassen) oder mit VB.Net (da gibt es einen sehr schönen Designer in der IDE) geschrieben. Mit C++ habe ich bisher nur Konsolenanwendungen geschrieben und habe deshalb noch keine Ahnung wo oder wie ich anfangen soll. Dazu kommt leider auch noch erschwerend, daß ich schon einige Zeit nichts mehr mit C++ zu tun hatte und ich meine alten Unterlagen wegen Umzugs und allgemeiner aufräumfaulheit gerade nicht finden kann 😞
    Ich benutze den Bloodshed Dev-C++ Compiler dessen Vorlage für ein Win32-Programm ich aber nicht so ganz verstehe:

    #include <windows.h>
    
    /* Declare Windows procedure */
    LRESULT CALLBACK WindowProcedure(HWND, UINT, WPARAM, LPARAM);
    /* Make the class name into a global variable */
    char szClassName[ ] = "WindowsApp";
    int WINAPI WinMain(HINSTANCE hThisInstance, HINSTANCE hPrevInstance, LPSTR lpszArgument, int nFunsterStil)
    {
        HWND hwnd;               /* This is the handle for our window */
        MSG messages;            /* Here messages to the application are saved */
        WNDCLASSEX wincl;        /* Data structure for the windowclass */
    
        /* The Window structure */
        wincl.hInstance = hThisInstance;
        wincl.lpszClassName = szClassName;
        wincl.lpfnWndProc = WindowProcedure;      /* This function is called by windows */
        wincl.style = CS_DBLCLKS;                 /* Catch double-clicks */
        wincl.cbSize = sizeof(WNDCLASSEX);
    
        /* Use default icon and mouse-pointer */
        wincl.hIcon = LoadIcon(NULL, IDI_APPLICATION);
        wincl.hIconSm = LoadIcon(NULL, IDI_APPLICATION);
        wincl.hCursor = LoadCursor(NULL, IDC_ARROW);
        wincl.lpszMenuName = NULL; /* No menu */
        wincl.cbClsExtra = 0;                      /* No extra bytes after the window class */
        wincl.cbWndExtra = 0;                      /* structure or the window instance */
        /* Use light-gray as the background of the window */
        wincl.hbrBackground = (HBRUSH) GetStockObject(LTGRAY_BRUSH);
    
        /* Register the window class, if fail quit the program */
        if(!RegisterClassEx(&wincl)) return 0;
    
        /* The class is registered, let's create the program*/
        hwnd = CreateWindowEx(
               0,                   /* Extended possibilites for variation */
               szClassName,         /* Classname */
               "Windows App",         /* Title Text */
               WS_OVERLAPPEDWINDOW, /* default window */
               CW_USEDEFAULT,       /* Windows decides the position */
               CW_USEDEFAULT,       /* where the window ends up on the screen */
               544,                 /* The programs width */
               375,                 /* and height in pixels */
               HWND_DESKTOP,        /* The window is a child-window to desktop */
               NULL,                /* No menu */
               hThisInstance,       /* Program Instance handler */
               NULL                 /* No Window Creation data */
               );
    
        /* Make the window visible on the screen */
        ShowWindow(hwnd, nFunsterStil);
        /* Run the message loop. It will run until GetMessage( ) returns 0 */
        while(GetMessage(&messages, NULL, 0, 0))
        {
               /* Translate virtual-key messages into character messages */
               TranslateMessage(&messages);
               /* Send message to WindowProcedure */
               DispatchMessage(&messages);
        }
    
        /* The program return-value is 0 - The value that PostQuitMessage( ) gave */
        return messages.wParam;
    }
    
    /* This function is called by the Windows function DispatchMessage( ) */
    LRESULT CALLBACK WindowProcedure(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
    {
        switch (message)                  /* handle the messages */
        {
               case WM_DESTROY:
               PostQuitMessage(0);        /* send a WM_QUIT to the message queue */
               break;
               default:                   /* for messages that we don't deal with */
               return DefWindowProc(hwnd, message, wParam, lParam);
        }
        return 0;
    }
    

    Was muss ich tun um auf dieser Form (nennt man das "Basisfenster" bei C++ überhaupt Form?) einfach irgendwo ein Text/Label Feld zu platzieren? Wo kann ich eine Übersicht über die verfügbaren Elemente (Listboxen, Dropdownmenüs etc pp) bekommen?
    Wäre bitte jemand so freundlich und gibt mir mal einen "Schubs" in die richtige Richtung (Am besten ein einfaches Beispiel wo ich sehen kann wie ich die Formelemente platzieren und ansprechen kann).

    Vielen dank im Voraus,

    Sternenstaub



  • wäre dieses thema nicht besser im winapi-forum aufgehoben? naja, ich antworte trotzdem mal auf die frage mit dem text, da sich sonst irgendwie niemand die mühe machen will 😉 ich habe bis jetzt noch überhaupt keine erfahrungen mit vb gemacht und java ist für mich sowas wie mfc, deshalb meide ich es auch...darum weiss ich jetzt nicht, welche vorkenntnisse du schon in der windows-programmierung hast.

    also, das grundsätzlichste mal vorweg: bei windows-programmen ist jedes angezeigte element ein fenster. buttons, textfelder, static-text, ... das sind alles fenster. diese fenster erstellt man mit der funktion CreateWindow oder CreateWindowEx (die beschreibung steht in der msdn). und das zweitgrundsätzlichste 😉 : windows kommuniziert mit den fenstern über nachrichten. wenn man z.b. mit der maus einen button anklickt, schickt ihm windows eine nachricht, dass geklickt wurde. die meisten nachrichten behandelt das programm automatisch ohne das hinzutun des programmierers. ein button zeichnet sich z.b. selbständig neu, wenn draufgeklickt wurde, das hauptfenster wird automatisch verschoben, wenn man es an der titelleiste zieht, etc. um dem programm funktionalität zu verleihen muss man aber selbständig auf die nachrichten reagieren. dein hauptfenster hat eine sogenannte hauptnachrichtenschleife (das while(GetMessage())-gebilde in der WinMain), die, falls eine nachricht ankommt, die funktion WindowProcedure mittels DispatchMessage aufruft. dort kannst du die nachrichten dann selber abfangen und darauf reagieren oder sie an die DefWindowProc weitergeben, damit der darauf reagiert. soviel mal zur theorie.

    nun das praktische 🙂 die nachricht WM_CREATE ist die erste nachricht, die dein programm empfängt. sie sagt dir quasi, das das hauptfenster erstellt wurde und du die ersten initialisierungen vornehmen kannst. an dieser stelle würde ich ein static-feld mit einem text ausgeben. der code sähe wie folgt aus:

    LRESULT CALLBACK WindowProcedure(...)
    {
    static HWND hWndStatic;
    
    ...
    
    case WM_CREATE:
       hWndStatic = CreateWindow(TEXT("STATIC"), TEXT("dein text"), WS_CHILD | WS_VISIBLE, 5, 5, 110, 30, hwnd, NULL, hInst, NULL);
       break;
    

    bei dieser variante müsstest du aber die hInstance deines programms in einer globalen variable hInst speichern.
    hWndStatic ist nun ein handle auf das fenster. ich habe sie hier als static deklariert, damit man bei einer anderen nachricht darauf zugreifen kann. z.b.

    WM_KEYDOWN:
       SetWindowText(hWndStatic, TEXT("eine taste wurde gedrückt");
       break;
    

    soweit mal meine kleine einführung in winapi 😉 ich würde an deiner stelle einige tuts im netz anschauen oder besser noch ein buch kaufen. die "windows-programmierung" vom petzold ist nicht schlecht...

    mfg
    puenktli



  • Vielen Dank Puenktli,

    hatte es schon fast aufgegeben auf eine Antwort zu hoffen.

    wäre dieses thema nicht besser im winapi-forum aufgehoben?

    Ich bin eigentlich davon ausgegangen, daß C++, wie auch Java, einige Klassen zur Programmierung von Fenstern bereitstellt. Daß es nicht so ist verkompliziert die Sache doch etwas 😉

    Naja, habe mir jetzt jedenfalls von einem Kumpel Unterlagen zur WinApi-Programmierung besorgt und werde dann mal versuchen das damit zu machen.

    Apropos WinApi, ich habe gestern irgendwas gelesen, daß man die nicht mehr benutzen solle weil es nicht gewährleistet ist, daß sie stabil bleibt. ABER wie soll ich sonst ein einfaches Windowsprogramm schreiben ohne irgendwelche .NET oder Java Geschichten auf dem Rechner auf dem es später laufen soll installieren zu müssen?

    Grüße,

    Sternenstaub



  • also zu dem mit den klassen: da müsstest du dich mal mit mfc auseinandersetzen, aber dann bräuchtest du visual c++. ist aber imho nicht sehr empfehlenswert, weil man so die grundlegenden zusammenhänge im hintergrund nicht zu verstehen lernt.

    zu .net: .net ist sozusagen die winapi der zukunft. ab windows longhorn soll .net die winapi ersetzen. heute läuft .net nur, wenn man das .net-framework installiert hat, das dann die .net-funktionen in winapi übersetzt. bei win longhorn (und den nachfolgern) wird es allerdings andersrum sein. dort wird dann .net die eigentliche api sein und die winapi wird bloss noch emuliert, was natürlich eine geschwindigkeitseinbusse bedeutet.

    mfg
    puenktli



  • Ansonsten schau dir doch ein Gui-Toolkit an,
    in der "Rund um die Programmierung -- FAQ" gibts darüber eine eigene Seite. 😉


Log in to reply