[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