用于教学的C ++和GUI

时间:2010-12-11 17:15:59

标签: c++ user-interface

所以,我的任务是教授一门编程课程,其中包括一些关于C ++中GUI编程的知识。我想知道,最好的设置是什么? Linux和GCC是我的首选工具。

我从未做过这样的课程,我是一名优秀的C程序员,但不是C ++程序员。我需要C ++,因为相同的课程需要涵盖OOP,C ++有多难! :)

9 个答案:

答案 0 :(得分:10)

如果您选择操作系统和GUI工具包,并且它必须是C ++,并且您更喜欢Linux - 那么请考虑使用Nokia Qt API。

它是免费的,开源的,跨平台的,高质量的。

答案 1 :(得分:3)

向内呻吟 :) C ++与C完全不同,而不仅仅是OOP ......

您可能希望教他们一个跨平台的GUI框架,如wxWidgets或Qt。但这需要你先认真了解它们。有一本关于wxWidgets的好书,作为免费的PDF(使用wxWidgets进行跨平台GUI编程) - 请参阅http://ptgmedia.pearsoncmg.com/images/0131473816/downloads/0131473816_book.pdf

跨平台方面的优势在于您可以使用所有您喜欢的Linux和GCC,并且他们的技能将根据需要转移到其他平台。

(顺便说一句,你可能也想教他们CMake,如果你想要大规模地延伸整个可移植性线......)

答案 2 :(得分:3)

您可以在C中进行OOP和GUI。查看GTK+

答案 3 :(得分:3)

我是gtkmmglade的粉丝。 GUI并不是特别漂亮,但从C ++程序员的角度来看,它是最好的GUI库。它非常易于使用,它只是有意义。实际上,除了文本编辑器和编码之外,您可以从头开始创建漂亮的GUI 。另一方面,还有用于使用GUI应用程序创建GUI的glade设计器。 gtkmm使用标准C ++库完美插件,但它还提供了ustring类,一个std::string兼容的支持unicode的字符串类。它还附带libsigc++用于事件处理机制。 libsigc ++在设计上有点类似于Boost.Signals。图书馆中关注点的明确分离 - 框架,GUI和信号,在教学上也很好。

答案 4 :(得分:1)

关于GUI的“一些东西”,你描述为“绘图,刷新,基于事件......”,即基本概念,请考虑使用Windows API。

这很简单,它是具体的,它允许你的学生以OO的方式进行包装,这是非常有教育意义的。

执行“绘图,刷新,基于事件”的示例,绘制动态大小的椭圆(您需要定义顶部包含的三个标题):

#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();
}

编辑:好的,也许我应该发布这三个标题。没有它们,这不是一个好的(完整的)答案。如此。

<强> [WINAPI /包装/ 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

干杯&amp;第h

答案 5 :(得分:1)

如果您使用的是C ++和Linux,请考虑使用gtkmm。 GNOME桌面环境基于GTK +,gtkmm是GTK +库的官方C ++包装器。它附带了很好的文档,对于教学可能很重要,尝试尽可能多地使用C ++标准库。

另一个受欢迎的选择Qt(这也是一个非常好的工具包,特别是如果你需要跨平台兼容性)已经重新实现了很多标准库,如果你正在教授标准,这可能会使它成为一个不太好的选择C ++。

答案 6 :(得分:1)

FWITW,Bjarne Stropstrups将FLTK用于同一目的:http://www.stroustrup.com/Programming/sw_stack.html

答案 7 :(得分:0)

对于Linux,我可以推荐ultimate++qt。我个人使用qt,并且发现它非常好,除了一些真正的WTF之外。

对于c ++,我不会这么容易判断。 c和c ++完全不同。

答案 8 :(得分:0)

使用大多数语言的OpenGL图形是一个很好的开始。它是免费的,开源的,概念很容易解释,API经过充分测试,功能强大,甚至可以在iPhone或Android等移动平台上使用。强烈推荐。