[wxMSW 2.8.7] wxGraphicsContext sample and problem during create
Werner Smekal
smekal at iap.tuwien.ac.at
Tue May 20 00:56:01 PDT 2008
Hi,
since I ran into trouble using wxGraphicsContext I looked for a demo how =
to use it (in C++). I found nothing except this:
http://svn.wxwidgets.org/viewvc/wx/wxPython/branches/WX_2_8_BRANCH/demo/Gra=
phicsContext.py?revision=3D47392&view=3Dmarkup
and "ported" it to C++. The code is attached if anyone is interested. =
It's based on the minimal sample so just replace minimal.cpp with that =
code and it should compile (tested only with Visual C++ 2008). Don't =
forget the USE_GDIPLUS=3D1 option.
Anyway, not to my surprise this code worked (in opposition to mine) and =
eventually I found out, that the problem was, that I created the =
wxGraphicsContext from a pointer(!) to a wxPaintDC not by reference. The =
same happens with wxGCDC, but ... why is it possible to create a wxGCDC =
from a pointer to wxPaintDC when the constructors are
public:
wxGCDC(const wxWindowDC& dc);
#ifdef __WXMSW__
wxGCDC( const wxMemoryDC& dc);
#endif
wxGCDC();
There should be an error message from the compiler, or? And if not, why =
doesn't it work?
Thanks for any insight,
Werner
-- =
Dr. Werner Smekal
Institut fuer Allgemeine Physik
Technische Universitaet Wien
Wiedner Hauptstr 8-10
A-1040 Wien
Austria
email: smekal at iap.tuwien.ac.at
web: http://www.iap.tuwien.ac.at/~smekal
phone: +43-(0)1-58801-13463 (office)
+43-(0)1-58801-13469 (laboratory)
fax: +43-(0)1-58801-13499
-------------- next part --------------
///////////////////////////////////////////////////////////////////////////=
//
// Name: minimal.cpp
// Purpose: wxGraphicsContext demo
///////////////////////////////////////////////////////////////////////////=
//
// For compilers that support precompilation, includes "wx/wx.h".
#include "wx/wxprec.h"
=
#ifdef __BORLANDC__
#pragma hdrstop
#endif
// for all others, include the necessary headers (this file is usually all =
you
// need because it includes almost all "standard" wxWidgets headers)
#ifndef WX_PRECOMP
#include "wx/wx.h"
#endif
// the application icon (under Windows and OS/2 it is in resources and even
// though we could still include the XPM here it would be unused)
#if !defined(__WXMSW__) && !defined(__WXPM__)
#include "../sample.xpm"
#endif
// don't compile if wxGraphicsContext is not available
#include "wx/graphics.h"
#if wxUSE_GRAPHICS_CONTEXT =3D=3D 0
#error wxGraphicsContext not available
#endif
// Conversion form HSV to RGB (obtained from http://alvyray.com/Papers/hsv2=
rgb.htm)
#define RETURN_HSV(h, s, v) {HSV.H =3D h; HSV.S =3D s; HSV.V =3D v; return =
HSV;}
#define RETURN_RGB(r, g, b) {RGB.R =3D r; RGB.G =3D g; RGB.B =3D b; return =
RGB;}
#define UNDEFINED -1
// Theoretically, hue 0 (pure red) is identical to hue 6 in these transform=
s. Pure
// red always maps to 6 in this implementation. Therefore UNDEFINED can be
// defined as 0 in situations where only unsigned numbers are desired.
typedef struct {float R, G, B;} RGBType;
typedef struct {float H, S, V;} HSVType; =
RGBType HSV_to_RGB(HSVType HSV)
{
// H is given on [0, 6] or UNDEFINED. S and V are given on [0, 1].
// RGB are each returned on [0, 1].
float h =3D HSV.H, s =3D HSV.S, v =3D HSV.V, m, n, f;
int i;
RGBType RGB;
if(h=3D=3DUNDEFINED)
RETURN_RGB(v, v, v);
i =3D floor(h);
f =3D h-i;
if(!(i&1))
f =3D 1-f; // if i is even
m =3D v*(1-s);
n =3D v*(1-s*f);
switch(i) {
case 6:
case 0: RETURN_RGB(v, n, m);
case 1: RETURN_RGB(n, v, m);
case 2: RETURN_RGB(m, v, n)
case 3: RETURN_RGB(m, n, v);
case 4: RETURN_RGB(n, m, v);
case 5: RETURN_RGB(v, m, n);
}
} =
// Define a new application type, each program should derive a class from w=
xApp
class MyApp : public wxApp
{
public:
virtual bool OnInit();
};
class MyCanvas;
// Define a new frame type: this is going to be our main frame
class MyFrame : public wxFrame
{
public:
MyFrame(const wxString& title);
void OnQuit(wxCommandEvent& event);
void OnAbout(wxCommandEvent& event);
MyCanvas *m_canvas;
private:
DECLARE_EVENT_TABLE()
};
// define a canvas for drawing onto
class MyCanvas: public wxWindow
{
public:
MyCanvas( MyFrame* parent );
void OnPaint(wxPaintEvent &event);
private:
DECLARE_EVENT_TABLE()
};
// IDs for the controls and the menu commands
enum
{
Minimal_Quit =3D wxID_EXIT,
Minimal_About =3D wxID_ABOUT
};
BEGIN_EVENT_TABLE(MyFrame, wxFrame)
EVT_MENU(Minimal_Quit, MyFrame::OnQuit)
EVT_MENU(Minimal_About, MyFrame::OnAbout)
END_EVENT_TABLE()
BEGIN_EVENT_TABLE(MyCanvas, wxWindow)
EVT_PAINT (MyCanvas::OnPaint)
END_EVENT_TABLE()
IMPLEMENT_APP(MyApp)
// 'Main program' equivalent: the program execution "starts" here
bool MyApp::OnInit()
{
if ( !wxApp::OnInit() )
return false;
// create the main application window
MyFrame *frame =3D new MyFrame(_T("Minimal wxWidgets App"));
frame->Show(true);
return true;
}
// frame constructor
MyFrame::MyFrame(const wxString& title)
: wxFrame(NULL, wxID_ANY, title )
{
// set the frame icon
SetIcon(wxICON(sample));
=
// set frame size
SetSize(wxSize(530, 450));
#if wxUSE_MENUS
// create a menu bar
wxMenu *fileMenu =3D new wxMenu;
// the "About" item should be in the help menu
wxMenu *helpMenu =3D new wxMenu;
helpMenu->Append(Minimal_About, _T("&About...\tF1"), _T("Show about dia=
log"));
fileMenu->Append(Minimal_Quit, _T("E&xit\tAlt-X"), _T("Quit this progra=
m"));
// now append the freshly created menu to the menu bar...
wxMenuBar *menuBar =3D new wxMenuBar();
menuBar->Append(fileMenu, _T("&File"));
menuBar->Append(helpMenu, _T("&Help"));
// ... and attach this menu bar to the frame
SetMenuBar(menuBar);
#endif // wxUSE_MENUS
m_canvas =3D new MyCanvas( this );
}
void MyFrame::OnQuit(wxCommandEvent& WXUNUSED(event))
{
// true is to force the frame to close
Close(true);
}
void MyFrame::OnAbout(wxCommandEvent& WXUNUSED(event))
{
wxMessageBox(wxString::Format(
_T("Welcome to %s!\n")
_T("\n")
_T("This is the wxGraphicsContext sample\n")
_T("running under %s."),
wxVERSION_STRING,
wxGetOsDescription().c_str()
),
_T("About wxWidgets minimal sample"),
wxOK | wxICON_INFORMATION,
this);
}
MyCanvas::MyCanvas(MyFrame* parent) : wxWindow(parent, wxID_ANY)
{
}
void MyCanvas::OnPaint(wxPaintEvent &WXUNUSED(event))
{
wxPaintDC dc(this);
=
const double base =3D 80.0; // sizes used in shapes drawn below
const double base2 =3D base/2.0;
const double base4 =3D base/4.0;
wxGraphicsContext* gc =3D wxGraphicsContext::Create(dc);
wxFont font =3D wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT);
font.SetWeight(wxBOLD);
gc->SetFont(font, *wxBLACK);
// make a path that contains a circle and some lines, centered at 0,0
wxGraphicsPath path =3D gc->CreatePath();
path.AddCircle(0, 0, base2);
path.MoveToPoint(0, -base2);
path.AddLineToPoint(0, base2);
path.MoveToPoint(-base2, 0);
path.AddLineToPoint(base2, 0);
path.CloseSubpath();
path.AddRectangle(-base4, -base4/2, base2, base4);
// Now use that path to demonstrate various capbilites of the grpahics =
context
gc->PushState(); // save current translation/scale/other st=
ate =
gc->Translate(60, 75); // reposition the context origin
gc->SetPen(wxPen("navy", 1));
gc->SetBrush(wxBrush("pink"));
// show the difference between stroking, filling and drawing
wxDouble w, h, d, l;
gc->GetTextExtent("StrokePath", &w, &h, &d, &l);
gc->DrawText("StrokePath", -w/2, -base2-h-4);
gc->StrokePath(path);
gc->Translate(2*base, 0);
gc->GetTextExtent("FillPath", &w, &h, &d, &l);
gc->DrawText("FillPath", -w/2, -base2-h-4);
gc->FillPath(path);
gc->Translate(2*base, 0);
gc->GetTextExtent("DrawPath", &w, &h, &d, &l);
gc->DrawText("DrawPath", -w/2, -base2-h-4);
gc->DrawPath(path);
gc->Translate(2*base, 0);
gc->PopState(); // restore saved state
gc->PushState(); // save it again
gc->Translate(60, 200); // offset to the lower part of the window
=
gc->DrawText("Scale", 0, -base2);
gc->Translate(0, 20);
// for testing clipping
//gc->Clip(0, 0, 100, 100)
//rgn =3D wx.RegionFromPoints([ (0,0), (75,0), (75,25,), (100, 25),
// (100,100), (0,100), (0,0) ])
//gc->ClipRegion(rgn);
//gc->ResetClip();
=
gc->SetBrush(wxBrush(wxColour(178, 34, 34, 128))); // 128 =3D=3D ha=
lf transparent
for(int i=3D0; i<8; i++) {
gc->Scale(1.08, 1.08); // increase scale by 8%
gc->Translate(5,5); =
gc->DrawPath(path);
}
gc->PopState(); // restore saved state
gc->PushState(); // save it again
gc->Translate(400, 200);
gc->DrawText("Rotate", 0, -base2);
=
gc->Translate(0, 75);
HSVType hsv;
RGBType rgb;
for(double angle=3D0.0; angle<360.0; angle+=3D30.0) {
gc->PushState(); // save this new current state so we can p=
op back to =
// it at the end of the loop
hsv.H =3D 6.0*angle/360.0;
hsv.S =3D 1.0;
hsv.V =3D 1.0;
rgb =3D HSV_to_RGB(hsv);
gc->SetBrush(wxBrush(wxColour((int)(rgb.R*255), (int)(rgb.G*255), (=
int)(rgb.B*255), 64)));
// use translate to artfully reposition each drawn path
gc->Translate(1.5 * base2 * cos(angle/180.0*M_PI),
1.5 * base2 * sin(angle/180.0*M_PI));
// use Rotate to rotate the path
gc->Rotate(angle/180.0*M_PI);
// now draw it
gc->DrawPath(path);
gc->PopState();
}
gc->PopState();
}
More information about the wx-users
mailing list