开发者

C++ and GUIs for teaching [closed]

开发者_运维问答 As it currently stands, this question is not a good fit for our Q&A format. We expect answers to be supported by facts, references, or expertise, but this question will likely solicit debate, arguments, polling, or extended discussion. If you feel that this question can be improved and possibly reopened, visit the help center for guidance. Closed 10 years ago.

So, I've been tasked to teach a programming course which includes some stuff about GUI programming in C++. I was wondering, what would be the best setup for this? Linux, and GCC are my tools of choice.

I've never done a course like this, I'm a good C programmer but not a C++ programmer. I need C++ because the same course needs to cover OOP, and how hard can C++ be!? :)


If the OS and GUI toolkit are your choice, and it must be C++, and you prefer Linux -- then consider the Nokia Qt API.

It's free, open-source, cross-platform, and high-quality.


groans inwardly :) C++ is completely different from C, and not just about OOP...

You might want to teach them a cross-platform GUI framework like wxWidgets or Qt. But that will require you to seriously learn about them first. There's a good book on wxWidgets available as a free PDF (Cross-Platform GUI Programming Using wxWidgets) -- see http://ptgmedia.pearsoncmg.com/images/0131473816/downloads/0131473816_book.pdf.

The advantage of the cross-platform aspect of it is that you can use Linux and GCC all you like, and their skills will transfer to other platforms as necessary.

(Incidentally, you might want to teach them CMake as well, if you want to go down the whole portability line in a big way...)


You can do OOP and GUI in C. Have a look at GTK+.


I'm a fan of gtkmm and glade. The GUI is not particularly beautiful, but it's the best GUI library out there from the C++ programmer's perspective. It's very easy to use and it just makes sense. In fact, you can create nice GUI from scratch with nothing but a text editor and coding. On the other hand there's also the glade designer to create GUI with a GUI application. gtkmm plugs flawlessly with the standard C++ library, but it also provides the ustring class, a std::string compliant unicode-supporting string class. It also comes with libsigc++ for the event processing mechanism. libsigc++ is somewhat similar to Boost.Signals in design. The clear separation of the concerns in the library -- the framework, the GUI and the signals, also do good pedagogically.


FWITW, Bjarne Stropstrups uses FLTK for the same purpose: http://www.stroustrup.com/Programming/sw_stack.html


For the "some stuff" about GUI, which you describe as "Drawing, refreshing, event-based... ", i.e. basic concepts, consider the Windows API.

It's easy, it's concrete, and it allows your students to progress to wrapping it all in an OO way, which is very educational.

Example that does "Drawing, refreshing, event-based", drawing a dynamically sized ellipse (you need to define the three headers included at the top):

#include <winapi/wrapper/windows_h.h>
#include <cppSupport/error_handling.h>  // cppSupport::throwX, cppSupport::ExitCode
#include <cppSupport/anti_warnings.h>   // cppSupport::suppressUnusedWarningFor

#include <iostream>
#include <string>           // std::wstring

using cppSupport::throwX;
using cppSupport::ExitCode;
using cppSupport::suppressUnusedWarningFor;

RECT clientRectOf( HWND window )
{
    RECT    result;

    GetClientRect( window, &result );
    return result;
}

void drawEllipse( HDC dc, RECT const& boundingRect )
{
    RECT const& r = boundingRect;
    Ellipse( dc, r.left, r.top, r.right, r.bottom );
}

namespace mainWindow {

    namespace detail {

        void paint( HWND window, HDC dc )
        {
            drawEllipse( dc, clientRectOf( window ) );
        }

        void onWmDestroy( HWND window )
        {
            suppressUnusedWarningFor( window );
            PostQuitMessage( ExitCode::success() );
        }

        void onWmPaint( HWND window )
        {
            PAINTSTRUCT     info;
            HDC const deviceContext = BeginPaint( window, &info );

            paint( window, deviceContext );
            EndPaint( window, &info );
        }

        LRESULT CALLBACK messageHandler(
            HWND        window,
            UINT        messageId,
            WPARAM      wParam,
            LPARAM      lParam
            )
        {
            switch( messageId )
            {
            case WM_DESTROY:
                return HANDLE_WM_DESTROY( window, wParam, lParam, onWmDestroy );
            case WM_PAINT:
                return HANDLE_WM_PAINT( window, wParam, lParam, onWmPaint );
            default:
                return DefWindowProc( window, messageId, wParam, lParam );
            }
        }

        ATOM registerClass()
        {
            WNDCLASS const  info    =
            {
                CS_HREDRAW | CS_VREDRAW,    // UINT style;
                &messageHandler,            // WNDPROC lpfnWndProc;
                0,                          // int cbClsExtra;
                0,                          // int cbWndExtra;
                GetModuleHandle( 0 ),       // HINSTANCE hInstance;
                0,                          // HICON hIcon;
                LoadCursor( 0, IDC_ARROW ), //  HCURSOR hCursor;
                reinterpret_cast<HBRUSH>( COLOR_WINDOW + 1 ),   // HBRUSH hbrBackground;
                0,                          // LPCTSTR lpszMenuName;
                L"MainWindowClass"          // LPCTSTR lpszClassName;
            };

            ATOM const  result  = RegisterClass( &info );
            (result != 0)
                || throwX( "registerWindowClass: RegisterClass failed" );
            return result;
        }

        ATOM classAtom()
        {
            static ATOM const   theClassAtom    = registerClass();
            return theClassAtom;
        }
    }    // namespace mainWindow::detail

    HWND create( std::wstring const& title )
    {
        HWND const  window  = CreateWindow(
            MAKEINTATOM( detail::classAtom() ), // LPCTSTR lpClassName,
            title.c_str(),                      // LPCTSTR lpWindowName,
            WS_OVERLAPPEDWINDOW,                // DWORD dwStyle,
            CW_USEDEFAULT,                      // int x,
            CW_USEDEFAULT,                      // int y,
            CW_USEDEFAULT,                      // int nWidth,
            CW_USEDEFAULT,                      // int nHeight,
            0,                                  // HWND hWndParent,
            0,                                  // HMENU hMenu,
            GetModuleHandle( 0 ),               // HINSTANCE hInstance,
            0                                   // LPVOID lpParam
            );
        (window != 0)
            || throwX( "createMainWindow: CreateWindow failed" );
        return window;
    }

}    // namespace mainWindow

bool getMessage( MSG& message, HWND window = 0 )
{
    int const   result  = GetMessage( &message, window, 0, 0 );
    (result != -1)
        || throwX( "getMessage: GetMessage failed" );
    return (result != 0);
}

ExitCode dispatchWindowMessages()
{
    MSG message;

    while( getMessage( message ) )
    {
        TranslateMessage( &message );
        DispatchMessage( &message );
    }

    assert( message.message == WM_QUIT );
    return ExitCode( message.wParam );
}

ExitCode cppMain()
{
    HWND const  window  = mainWindow::create( L"My main window" );

    ShowWindow( window, SW_SHOWDEFAULT );
    return dispatchWindowMessages();
}

int main()
{
    try
    {
        return cppMain();
    }
    catch( std::exception const& x )
    {
        std::cerr << "!" << x.what() << std::endl;
    }
    return ExitCode::failure();
}

EDIT: OK, perhaps I should best post those three headers. It's not a good (complete) answer without them. So.

[winapi/wrapper/windows_h.h]:

// Copyright (c) 2010 Alf P. Steinbach
#ifndef WINAPI_WRAPPER_WINDOWSH_H
#define WINAPI_WRAPPER_WINDOWSH_H

//#include <progrock/cppx/devsupport/better_experience.h>

#ifdef  _MBCS
#   error _MBCS was defined, only Unicode is supported.
#endif

#undef  UNICODE
#undef  _UNICODE
#undef  STRICT
#undef  NOMINMAX

#define UNICODE
#define _UNICODE
#define STRICT
#define NOMINMAX

#ifdef  _WIN32_WINNT
#   if _WIN32_WINNT < 0x5000
#       error _WIN32_WINNT < 0x5000, pre-Windows 2000 is not supported.
#   endif
#else
#   define _WIN32_WINNT 0x5000
#endif

#ifdef  _WIN32_IE
#   if _WIN32_IE < 0x5000
#       error _WIN32_IE < 0x5000, that old browser / Windows shell is not supported.
#   endif
#else
#   define _WIN32_IE 0x5000
#endif

#include <windows.h>
#include <windowsx.h>


//------------------------------------------------- g++ fixups:

#ifndef BS_TYPEMASK
#   define BS_TYPEMASK 0x0000000F
#endif

#ifndef BS_PUSHBOX
#   define BS_PUSHBOX           0x0000000AL
#endif

#ifndef EN_ALIGN_LTR_EC
#   define EN_ALIGN_LTR_EC      0x0700
#   define EN_ALIGN_RTL_EC      0x0701
#endif

#ifndef LBS_COMBOBOX
#   define LBS_COMBOBOX         0x8000L
#endif

#endif

[cppsupport/error_handling.h]:

#ifndef CPPSUPPORT_ERROR_HANDLING_H
#define CPPSUPPORT_ERROR_HANDLING_H

//-------------------------------- Dependencies:

#include <assert.h>             // assert
#include <stdexcept>            // std::runtime_error, std::exception
#include <stdlib.h>             // EXIT_SUCCESS, EXIT_FAILURE
#include <string>               // std::string, std::wstring


//-------------------------------- Interface:

namespace cppSupport {

    inline bool throwX( std::string const& s )
    {
        throw std::runtime_error( s );
    }

    struct ExitCode
    {
        int value;
        explicit ExitCode( int v ): value( v ) {}
        operator int() const { return value; }
        static ExitCode success() { return ExitCode( EXIT_SUCCESS ); }
        static ExitCode failure() { return ExitCode( EXIT_FAILURE ); }
    };

}    // namespace cppSupport
#endif

[cppsupport/anti_warnings.h]:

#ifndef CPPSUPPORT_ANTI_WARNINGS_H
#define CPPSUPPORT_ANTI_WARNINGS_H

//-------------------------------- Dependencies:

// -- None.


//-------------------------------- Interface:

namespace cppSupport {

    template< class Type >
    void suppressUnusedWarningFor( Type const& ) {}

}    // namespace cppSupport

#endif

Cheers & hth.


If you are using C++ and Linux, consider gtkmm. The GNOME Desktop environment is based on GTK+ and gtkmm is the official C++ wrapper for the GTK+ library. It comes with nice documentation and, what might be important for teaching, tries to use the C++ standard library as much as possible.

The other popular choice Qt (which is also a very good toolkit, especially if you need cross-platform compatibility) has reimplemented much of the standard library, which probably makes it a not-so-good choice if you are teaching standard C++.


For linux, I can recommend ultimate++ and qt. I personally use qt, and find it quite good, except for some real WTF things.

As for c++, I wouldn't judge it so easily. c and c++ are quite different.


OpenGL graphics with most languages is a great start. It's free, opensource, the concepts are easily explained, and the API is well tested, powerful, and even useable on mobile platforms like iPhone or Android. Highly recommend.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜