所以,我的任务是教授一门编程课程,其中包括一些关于C ++中GUI编程的知识。我想知道,最好的设置是什么? Linux和GCC是我的首选工具。
我从未做过这样的课程,我是一名优秀的C程序员,但不是C ++程序员。我需要C ++,因为相同的课程需要涵盖OOP,C ++有多难! :)
答案 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)
我是gtkmm和glade的粉丝。 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等移动平台上使用。强烈推荐。