wxScrollWindow as Draw and Drag Control

Are you writing your own components and need help with how to set them up or have questions about the components you are deriving from ? Ask them here.
Post Reply
LordLoser
In need of some credit
In need of some credit
Posts: 2
Joined: Tue Dec 01, 2009 7:05 pm

wxScrollWindow as Draw and Drag Control

Post by LordLoser » Tue Dec 01, 2009 9:45 pm

Hi,

to every one here in this Forum.

I'm new here and have a problem, which tourture me in the last time.

The search couldn't give me answers to the question, so i hope maby someone here can help me, please.

The question I have is, that i need a canvas( scrollwindow), which shows me in the background a picture.
When you resize the Window( Canvas) than the picture would be scaled to the canvas size.
( I can't need the scrollbars, they have to be disabled)
Futher more i have small arrows as pictures, these can be added to the canvas by buttons.
This arrows could be resize able( optional)
They should be drag able and rotate able. ( immportant)

The second thing the user should be able to do is to draw lines.

Some of the perosons, who read the article thought mayby he should use wxSF or wxArt2D.
Both of theme have parts i would like to use in my canvas.
But it would be very diffecult, to rewrite so many points of the source.

wxFS has the scrollbars, which i can't have.
You can't rotate the arrows, you have no background image(this could correcet easily)
You can't draw lines you have, but you have this lines, which are size able.( these are also ok)

wxArt2D has scrollbars and an zoom, both are bad.
you can rotate and resize the arrows.
you can draw lines.
you can't have a Bitmap as background.

I don't want to have a complete solution from you, but if you would have:D

I started my own tries, it works in the basics.
With this canvas you can have a Background bitmap, can display arrows.
The rotation works, is not the best, wxArt2D's soulotion is better.
you can drag the arrows, this works well.
you can't resize arrows or draw lines.

So if you have a idea or a solution for my pro.

This is my Canvas:
MyCanvas.h

Code: Select all

#ifndef MYCANVAS_H
#define MYCANVAS_H

#include <wx/dnd.h>
#include <wx/event.h>
#include <wx/statbmp.h>
#include <wx/filedlg.h>

#include <wx/log.h>

#include <wx/app.h>
#include <wx/scrolwin.h>
#include <wx/object.h>
#include <wx/dcclient.h>
#include <wx/dcmemory.h>
#include <wx/dragimag.h>
#include <wx/generic/dragimgg.h>
#include <wx/msgdlg.h>
#include <wx/aui/aui.h>
#include <wx/artprov.h>
#include <wx/menu.h>
#include <wx/file.h>
#include <wx/image.h>

#include <list>

#define TEST_DRAG_NONE     0
#define TEST_DRAG_START    1
#define TEST_DRAG_DRAGGING 2

class DragShape;
class MyDragImage;

class MyCanvas : public wxScrolledWindow
{
    public:
        MyCanvas(wxWindow* parnet, wxWindowID id, const wxPoint &pos, const wxSize &size);
        virtual ~MyCanvas( void);

        // setPicture
        void setzeBild( wxString Bild, bool gradeGeladen = false);

        void OnPaint( wxPaintEvent &event );
        void OnEraseBackground(wxEraseEvent& event);
        void OnMouseEvent(wxMouseEvent& event);

        void OnRotateBild( wxCommandEvent& event);
        void OnUebersicht( wxCommandEvent& event);
        void OnBearbeiten( wxCommandEvent& event);

        void DrawShapes(wxDC& dc);
        void EraseShape(DragShape* shape, wxDC& dc);
        void ClearShapes();
        DragShape* FindShape(const wxPoint& pt) const;

        wxList& GetDisplayList() { return m_displayList; }

        bool TileBitmap( wxRect& rect, wxDC& dc);

        wxBitmap gibHintergrund( void);

        void Resize( wxSizeEvent& event);

    protected:

    private:

        bool            m_beimZeichnen; // is drawing
        bool            m_gestartet;    // is start

        wxList          m_displayList; // A list of DragShapes
        int             m_dragMode;
        DragShape*      m_draggedShape;
        DragShape*      m_currentlyHighlighted; // The shape that's being highlighted
        wxPoint         m_dragStartPos;
        wxDragImage*    m_dragImage;
        DragShape*      ClickedShape;

        wxFileDialog* FileDialog1;

        wxBitmap        m_aktuellesBild; // currentPicture
        wxBitmap        m_aktuellesBild_echt; // currentPicture unscale
        bool            geladen; // can add arrows ( there is a Background

		bool            gespeichert; // is saved
		wxString        EinsatzkarteBildName; // Name of the Background
		wxString        EigentlicherPfad; // Path to the Background

        DECLARE_CLASS(MyCanvas)
        DECLARE_EVENT_TABLE()
};

class DnDDatei : public wxFileDropTarget
{
    public:

        DnDDatei( MyCanvas *gehoert);

        virtual bool OnDropFiles( wxCoord x, wxCoord y, const wxArrayString& filenames);
    private:

        MyCanvas*      Gehoert; // Parent
};

// Ways to drag a shape

#define SHAPE_DRAG_BITMAP       1

// Shape

class DragShape: public wxObject
{
public:
    DragShape(const wxBitmap& bitmap, int id, int farbe, int nummer);
    ~DragShape( void){};

//// Operations

    bool HitTest(const wxPoint& pt) const;
    bool Draw(wxDC& dc, bool highlight = false);

//// Accessors
    // Rotate arrow
    void DreheBild( int angle);
    // angle of arrow
    int  GibGedreht( void);

    wxPoint GetPosition() const { return m_pos; }
    void SetPosition(const wxPoint& pos) { m_pos = pos; }

    wxRect GetRect() const { return wxRect(m_pos.x, m_pos.y, m_bitmap.GetWidth(), m_bitmap.GetHeight()); }

    wxBitmap& GetBitmap() const { return (wxBitmap&) m_bitmap; }
    void SetBitmap(const wxBitmap& bitmap) { m_bitmap = bitmap; }

    int GetDragMethod() const { return m_dragMethod; }
    void SetDragMethod(int method) { m_dragMethod = method; }

    bool IsShown() const { return m_show; }
    void SetShow(bool show) { m_show = show; }

    int GetID( void);

    // GetColour
    int GetFarbe( void);
    // Getnumber
    int GetNummer( void);

protected:
    wxPoint     m_pos;
    wxBitmap    m_bitmap;
    int         m_id;
    int         m_dragMethod;
    bool        m_show;
    int         m_rotate;
    int         m_Farbe; // m_Colour
    int         m_Nummer; // m_Number
};

// MyDragImage
// A derived class is required since we're overriding UpdateBackingFromWindow,
// for compatibility with Mac OS X (Core Graphics) which does not support blitting
// from a window.

class MyDragImage: public wxDragImage
{
public:
    MyDragImage(MyCanvas* canvas): m_canvas(canvas) {}

    MyDragImage(MyCanvas* canvas, const wxBitmap& image, const wxCursor& cursor = wxNullCursor):
        wxDragImage(image, cursor), m_canvas(canvas)
    {
    }

    MyDragImage(MyCanvas* canvas, const wxIcon& image, const wxCursor& cursor = wxNullCursor):
        wxDragImage(image, cursor), m_canvas(canvas)
    {
    }

    MyDragImage(MyCanvas* canvas, const wxString& str, const wxCursor& cursor = wxNullCursor):
        wxDragImage(str, cursor), m_canvas(canvas)
    {
    }

    // On some platforms, notably Mac OS X with Core Graphics, we can't blit from
    // a window, so we need to draw the background explicitly.
    virtual bool UpdateBackingFromWindow(wxDC& windowDC, wxMemoryDC& destDC, const wxRect& sourceRect,
                    const wxRect& destRect) const;

protected:
    MyCanvas*   m_canvas;
};

#endif // MYCANVAS_H
MyCanvas.cpp

Code: Select all

#include "MyCanvas.h"

#include "DrehenDialog.h"  // Dialog to rotate the arrow
#include "BildVerwaltung.h" // Library to load a picture from dll
#include "EinsatzDaten.h"   // internel Datastructure
#include "NeueNotizDialog.h" 
#include "LogNeuMain.h"
#include "NotizVerwaltung.h"
#include "SpeicherVerwaltung.h"

IMPLEMENT_CLASS(MyCanvas, wxScrolledWindow)

BEGIN_EVENT_TABLE(MyCanvas, wxScrolledWindow)
  EVT_PAINT(MyCanvas::OnPaint)
  EVT_ERASE_BACKGROUND(MyCanvas::OnEraseBackground)
  EVT_MOUSE_EVENTS(MyCanvas::OnMouseEvent)
END_EVENT_TABLE()

MyCanvas::MyCanvas( wxWindow* parent, wxWindowID id, const wxPoint &pos, const wxSize &size)
: wxScrolledWindow( parent, id, pos, size, wxSUNKEN_BORDER )
{
    SetBackgroundColour(* wxWHITE);

    SetCursor(wxCursor(wxCURSOR_ARROW));

    m_dragMode = TEST_DRAG_NONE;
    m_draggedShape = (DragShape*) NULL;
    m_dragImage = (wxDragImage*) NULL;
    m_currentlyHighlighted = (DragShape*) NULL;

    FileDialog1 = new wxFileDialog(this, _("Bitte das zuladene Bild auswählen"), wxEmptyString, wxEmptyString, _("Alle Unterstützten Formate|*.bmp;*.jpg;*.jpeg;*.jpe;*.jfif;*.tif;*.tiff;*.gif;*.png|BMP Datei (*.bmp)|*.bmp|JPG Bild (*.jpg, *.jpeg, *.jpe, *.jfif)|*.jpg;*.jpeg;*.jpe;*.jfif|TIFF Bild( *.tif, *.tiff)|*.tif;*.tiff|Gif Bild (*.gif)|*.gif|PNG Bild (*.png)|*.png"), wxFD_DEFAULT_STYLE|wxFD_OPEN, wxDefaultPosition, wxDefaultSize, _T("wxFileDialog"));
}

MyCanvas::~MyCanvas()
{
    ClearShapes();

    if (m_dragImage)
        delete m_dragImage;
}

void MyCanvas::OnPaint( wxPaintEvent &WXUNUSED(event) )
{
    wxPaintDC dc( this );
    PrepareDC( dc );

    DrawShapes(dc);
}

void MyCanvas::OnRotateBild( wxCommandEvent& event)
{
    // New Rotate dialog to display
    DrehenDialog* Drehen = new DrehenDialog( this, ClickedShape);
    Drehen->SetPosition( wxPoint( ClickedShape->GetPosition().x-Drehen->GetSize().GetWidth()-3, ClickedShape->GetPosition().y));
    if( Drehen->GetPosition().x < 0)
        Drehen->SetPosition( wxPoint( 5, Drehen->GetPosition().y + 15));
    if( Drehen->GetPosition().y < 0)
        Drehen->SetPosition( wxPoint( Drehen->GetPosition().x + 15, 5));

    Drehen->SetzeGedreht( ClickedShape->GibGedreht());
    ClickedShape->DreheBild(Drehen->ShowModal());
    Frame->speichern( EinsatzDaten.GibPfad() + "Sicherung");
    Refresh();
}

void MyCanvas::OnUebersicht( wxCommandEvent& event)
{


}

void MyCanvas::OnBearbeiten( wxCommandEvent& event)
{
    // intern 
    NeueNotizDialog* AendereNotiz = new NeueNotizDialog( this, Frame->GibIndexGelb(), Frame->GibIndexRot(), Frame->GibIndexWeiss(), ClickedShape->GetFarbe(), ClickedShape->GetNummer(), true);
    //AendereNotiz->btnLoeschen->Enable( true);
    AendereNotiz->btnAbbrechen->Enable( true);
    AendereNotiz->NotizUeberschrift->SetLabel( "Verändern Sie die Notiz");
    int index = NotizVerwaltung.GibIndex( ClickedShape->GetFarbe(), ClickedShape->GetNummer())-1;
    AendereNotiz->setzeLade( index);
    AendereNotiz->txtNotiz->SetValue( NotizVerwaltung.GibNotiz( index));
    AendereNotiz->txtNotiz->SetForegroundColour( NotizVerwaltung.GibFarbe( index));
    AendereNotiz->txtNotiz->SetFocus();
    AendereNotiz->txtDetails->SetValue( NotizVerwaltung.GibDetails( index));

    int ende = AendereNotiz->ShowModal();

    if( ende == 1)
    {

        NotizVerwaltung.GibPanel( index)->setzeNotizaenderung(AendereNotiz->txtNotiz->GetValue(), AendereNotiz->txtDetails->GetValue(), EinsatzDaten.GibBearbeiter(), AendereNotiz->txtNotiz->GetForegroundColour(), NotizVerwaltung.GibErstellungsZeit( index), NotizVerwaltung.GibLetzteAenderung(index));
        NotizVerwaltung.aktuallisierescrollbar();
        SpeicherVerwaltung.speicherNotizen();
    }
    /*else if( ende == 2)
    {

        SpeicherVerwaltung.speicherNotizen();
        this->Destroy();
    }
    else if( ende == 3)
    {

        NotizVerwaltung.loescheNotiz( NotizIndex);
        SpeicherVerwaltung.speicherNotizen();
        NotizVerwaltung.aktuallisierescrollbar();
        this->Destroy();
    }*/
}

void MyCanvas::OnEraseBackground(wxEraseEvent& event)
{

    // Draw the Background picture

    if (m_aktuellesBild.Ok())
    {
        wxSize sz = GetClientSize();
        wxRect rect(0, 0, sz.x, sz.y);

        if (event.GetDC())
        {
            TileBitmap(rect, *(event.GetDC()));
        }
        else
        {
            wxClientDC dc(this);
            TileBitmap(rect, dc);
        }
    }
    else
        event.Skip(); // The official way of doing it
}

bool MyCanvas::TileBitmap( wxRect& rect, wxDC& dc)
{
    // to display the Picture
    int w = m_aktuellesBild.GetWidth();
    int h = m_aktuellesBild.GetHeight();

    int i, j;
    for (i = rect.x; i < rect.x + rect.width; i += w)
    {
        for (j = rect.y; j < rect.y + rect.height; j+= h)
            dc.DrawBitmap(m_aktuellesBild, i, j);
    }
    return true;
}

wxBitmap MyCanvas::gibHintergrund( void)
{

    return m_aktuellesBild;
}

void MyCanvas::Resize( wxSizeEvent &event)
{

    wxImage temp = m_aktuellesBild_echt.ConvertToImage();
    m_aktuellesBild = wxBitmap( temp.Scale( GetSize().GetWidth(), GetSize().GetHeight()));
    Refresh();
}

// set Background bitmap
void MyCanvas::setzeBild( wxString Bild, bool gradeGeladen)
{

    m_aktuellesBild = BildVerwaltung.GibBildAusDatei( Bild);
    m_aktuellesBild_echt = m_aktuellesBild;

    wxImage jo = m_aktuellesBild.ConvertToImage();
    m_aktuellesBild = wxBitmap( jo.Scale( GetSize().GetWidth(), GetSize().GetHeight()));
    geladen = true;
    EigentlicherPfad = Bild;
    if( !gradeGeladen)
        Frame->speichern( EinsatzDaten.GibPfad() + "Sicherung");
}

void MyCanvas::OnMouseEvent(wxMouseEvent& event)
{

    if( !EinsatzDaten.GibEnde())
    {

        if( event.LeftDClick())
        {

            if( FileDialog1->ShowModal() == wxID_OK)
            {
                // Load a Backgroudn and save in the Main frame
                Frame->setzeBild( FileDialog1->GetPath());
                setzeBild( FileDialog1->GetPath());
                this->Refresh(true);
            }
        }
        else if (event.LeftDown())
        {

            DragShape* shape = FindShape(event.GetPosition());
            if (shape)
            {
                // We tentatively start dragging, but wait for
                // mouse movement before dragging properly.

                m_dragMode = TEST_DRAG_START;
                m_dragStartPos = event.GetPosition();
                m_draggedShape = shape;
            }
        }
        else if (event.LeftUp() && m_dragMode != TEST_DRAG_NONE)
        {
            // Finish dragging

            m_dragMode = TEST_DRAG_NONE;

            if (!m_draggedShape || !m_dragImage)
                return;

            m_draggedShape->SetPosition(m_draggedShape->GetPosition()
                                        + event.GetPosition() - m_dragStartPos);

            m_dragImage->Hide();
            m_dragImage->EndDrag();
            delete m_dragImage;
            m_dragImage = NULL;

            m_draggedShape->SetShow(true);

            m_currentlyHighlighted = (DragShape*) NULL;

            m_draggedShape = (DragShape*) NULL;

            Refresh(true);
            Frame->speichern( EinsatzDaten.GibPfad() + "Sicherung");
        }
        else if( event.RightUp())
        {

            DragShape* shape = FindShape(event.GetPosition());
            if (shape)
            {
                // We tentatively start dragging, but wait for
                // mouse movement before dragging properly.
                wxMenu menuEinstellungen;
                wxMenuItem* m1 =  new wxMenuItem(&menuEinstellungen, 701, "Drehen");
                menuEinstellungen.Append(m1);
                wxMenuItem* m2 =  new wxMenuItem(&menuEinstellungen, 702, "Übersicht");
                menuEinstellungen.Append(m2);
                wxMenuItem* m3 =  new wxMenuItem( &menuEinstellungen);
                menuEinstellungen.Append(m3);
                wxMenuItem* m4 =  new wxMenuItem(&menuEinstellungen, 703, "Bearbeiten");
                menuEinstellungen.Append(m4);

                ClickedShape = shape;

                Connect( 701, wxEVT_COMMAND_MENU_SELECTED, (wxObjectEventFunction)&MyCanvas::OnRotateBild);
                Connect( 702, wxEVT_COMMAND_MENU_SELECTED, (wxObjectEventFunction)&MyCanvas::OnUebersicht);
                Connect( 703, wxEVT_COMMAND_MENU_SELECTED, (wxObjectEventFunction)&MyCanvas::OnBearbeiten);

                // line up our menu with the button

                PopupMenu(&menuEinstellungen, event.GetPosition());
            }
        }
        else if (event.Dragging() && m_dragMode != TEST_DRAG_NONE)
        {
            if (m_dragMode == TEST_DRAG_START)
            {
                // We will start dragging if we've moved beyond a couple of pixels

                int tolerance = 2;
                int dx = abs(event.GetPosition().x - m_dragStartPos.x);
                int dy = abs(event.GetPosition().y - m_dragStartPos.y);
                if (dx <= tolerance && dy <= tolerance)
                    return;

                // Start the drag.
                m_dragMode = TEST_DRAG_DRAGGING;

                if (m_dragImage)
                    delete m_dragImage;

                // Erase the dragged shape from the canvas
                m_draggedShape->SetShow(false);

                // redraw immediately
                Refresh(true);
                Update();

                switch (m_draggedShape->GetDragMethod())
                {
                    case SHAPE_DRAG_BITMAP:
                    {
                        m_dragImage = new MyDragImage(this, m_draggedShape->GetBitmap(), wxCursor(wxCURSOR_HAND));
                        break;
                    }
                    case SHAPE_DRAG_TEXT:
                    {
                        m_dragImage = new MyDragImage(this, wxString(_T("Dragging some test text")), wxCursor(wxCURSOR_HAND));
                        break;
                    }
                    case SHAPE_DRAG_ICON:
                    {
                        m_dragImage = new MyDragImage(this, wxICON(dragicon), wxCursor(wxCURSOR_HAND));
                        break;
                    }
                }

                bool fullScreen = false;

                // The offset between the top-left of the shape image and the current shape position
                wxPoint beginDragHotSpot = m_dragStartPos - m_draggedShape->GetPosition();

                // Now we do this inside the implementation: always assume
                // coordinates relative to the capture window (client coordinates)

                //if (fullScreen)
                //    beginDragHotSpot -= ClientToScreen(wxPoint(0, 0));

                if (!m_dragImage->BeginDrag(beginDragHotSpot, this, fullScreen))
                {
                    delete m_dragImage;
                    m_dragImage = (wxDragImage*) NULL;
                    m_dragMode = TEST_DRAG_NONE;

                } else
                {
                    m_dragImage->Move(event.GetPosition());
                    m_dragImage->Show();
                }
            }
            else if (m_dragMode == TEST_DRAG_DRAGGING)
            {
                // We're currently dragging. See if we're over another shape.
                DragShape* onShape = FindShape(event.GetPosition());

                bool mustUnhighlightOld = false;
                bool mustHighlightNew = false;

                if (m_currentlyHighlighted)
                {
                    if ((onShape == (DragShape*) NULL) || (m_currentlyHighlighted != onShape))
                        mustUnhighlightOld = true;
                }

                if (onShape && (onShape != m_currentlyHighlighted) && onShape->IsShown())
                    mustHighlightNew = true;

                if (mustUnhighlightOld || mustHighlightNew)
                    m_dragImage->Hide();

                // Now with the drag image switched off, we can change the window contents.
                if (mustUnhighlightOld)
                    m_currentlyHighlighted = (DragShape*) NULL;

                if (mustHighlightNew)
                    m_currentlyHighlighted = onShape;

                if (mustUnhighlightOld || mustHighlightNew)
                {
                    Refresh(mustUnhighlightOld);
                    Update();
                }

                // Move and show the image again
                m_dragImage->Move(event.GetPosition());

                if (mustUnhighlightOld || mustHighlightNew)
                     m_dragImage->Show();
            }
        }
    }
}

void MyCanvas::DrawShapes(wxDC& dc)
{
    wxList::compatibility_iterator node = m_displayList.GetFirst();
    while (node)
    {
        DragShape* shape = (DragShape*) node->GetData();
        if (shape->IsShown() && m_draggedShape != shape)
        {
            shape->Draw(dc, (m_currentlyHighlighted == shape));
        }
        node = node->GetNext();
    }
}

void MyCanvas::EraseShape(DragShape* shape, wxDC& dc)
{
    wxSize sz = GetClientSize();
    wxRect rect(0, 0, sz.x, sz.y);

    wxRect rect2(shape->GetRect());
    dc.SetClippingRegion(rect2.x, rect2.y, rect2.width, rect2.height);

    Frame->TileBitmap(rect, dc, Frame->gibHintergrund());

    dc.DestroyClippingRegion();
}

void MyCanvas::ClearShapes()
{
    wxList::compatibility_iterator node = m_displayList.GetFirst();
    while (node)
    {
        DragShape* shape = (DragShape*) node->GetData();
        delete shape;
        node = node->GetNext();
    }
    m_displayList.Clear();
}

DragShape* MyCanvas::FindShape(const wxPoint& pt) const
{
    wxList::compatibility_iterator node = m_displayList.GetFirst();
    while (node)
    {
        DragShape* shape = (DragShape*) node->GetData();
        if (shape->HitTest(pt))
            return shape;
        node = node->GetNext();
    }
    return (DragShape*) NULL;
}

// DragShape

DragShape::DragShape(const wxBitmap& bitmap, int id, int farbe, int nummer)
{
    m_bitmap = bitmap;
    m_pos.x = 0;
    m_pos.y = 0;
    m_dragMethod = SHAPE_DRAG_BITMAP;
    m_show = true;
    m_id = id;
    m_Farbe = farbe;
    m_Nummer = nummer;
    m_rotate = 0;
}

bool DragShape::HitTest(const wxPoint& pt) const
{
    wxRect rect(GetRect());
    return rect.Contains(pt.x, pt.y);
}

int DragShape::GetID( void)
{

    return m_id;
}

int DragShape::GetFarbe( void)
{

    return m_Farbe;
}

int DragShape::GetNummer( void)
{

    return m_Nummer;
}

bool DragShape::Draw(wxDC& dc, bool highlight)
{
    if (m_bitmap.Ok())
    {
        wxMemoryDC memDC;
        memDC.SelectObject(m_bitmap);

        dc.Blit(m_pos.x, m_pos.y, m_bitmap.GetWidth(), m_bitmap.GetHeight(),
            & memDC, 0, 0, wxCOPY, true);

        if (highlight)
        {
            dc.SetPen(*wxWHITE_PEN);
            dc.SetBrush(*wxTRANSPARENT_BRUSH);
            dc.DrawRectangle(m_pos.x, m_pos.y, m_bitmap.GetWidth(), m_bitmap.GetHeight());
        }

        return true;
    }
    else
        return false;
}

void DragShape::DreheBild( int angle)
{

    if(  angle != -1)
    {

        int temp_grad = m_rotate;

        m_rotate = angle - m_rotate;
        if( m_rotate == 360)
            m_rotate = 0;
        wxImage temp = m_bitmap.ConvertToImage();
        temp = temp.Rotate(-(3.14159)/180 * m_rotate, wxPoint(m_pos.x + m_bitmap.GetWidth()/2, m_pos.y - m_bitmap.GetHeight()/2));
        m_bitmap = wxBitmap( temp);
        m_rotate = temp_grad + m_rotate;
    }
}

int DragShape::GibGedreht( void)
{

    return m_rotate;
}

// MyDragImage

// On some platforms, notably Mac OS X with Core Graphics, we can't blit from
// a window, so we need to draw the background explicitly.
bool MyDragImage::UpdateBackingFromWindow(wxDC& WXUNUSED(windowDC), wxMemoryDC& destDC, const wxRect& WXUNUSED(sourceRect),
                    const wxRect& destRect) const
{
    destDC.SetClippingRegion(destRect);

    if ( m_canvas->gibHintergrund().Ok())
        m_canvas->TileBitmap((wxRect&)destRect, (wxDC&)destDC);

    m_canvas->DrawShapes(destDC);
    return true;
}

DnDDatei::DnDDatei( MyCanvas* gehoert)
{

    Gehoert = gehoert;
}

bool DnDDatei::OnDropFiles( wxCoord x, wxCoord y, const wxArrayString& filenames)
{

    size_t nFiles = filenames.GetCount();
    for( size_t n = 0; n < nFiles; n++)
    {

        wxString Endung = filenames[n].Mid( filenames[n].Find( '.', true)+1, wxSTRING_MAXLEN);
        if( Endung.CmpNoCase( "bmp")|| Endung.CmpNoCase( "jpg") || Endung.CmpNoCase( "tiff") || Endung.CmpNoCase( "gif"))
        {

            Frame->setzeBild( filenames[n]);
            Gehoert->Refresh();
        }

    }

    Frame->speichern( EinsatzDaten.GibPfad() + "Sicherung");
    return true;
}
this code is sample code and my thoughts.

the arrwos whould be added by the following:

Code: Select all

if( geladen)
        {
            // unimportant
            NeueNotizDialog* NeueNotiz = new NeueNotizDialog( Frame, indexGelb, indexRot, indexWeiss, 2, indexGelb-1, true);
            if( NeueNotiz->ShowModal())
            {
                // load the arrow from dll
                wxImage temp = BildVerwaltung.GibZeichen( ID_ZEICHEN_PFEIL2+indexGelb).ConvertToImage();
                // new DragShapeBitmap
                DragShape* newShape = new DragShape(wxBitmap(temp.Scale( 45, 45)), ID_ZEICHEN_PFEIL2+indexGelb, 2, indexGelb);
                newShape->SetPosition(wxPoint(50, 50));

                newShape->SetDragMethod(SHAPE_DRAG_BITMAP);
                // Einsatzkaret = MyCanvas
                Einsatzkarte->GetDisplayList().Append(newShape);
                Einsatzkarte->Refresh();
                // save the data from MyCanvas
                speichern( EinsatzDaten.GibPfad() + "Sicherung");
                // counter to the next arrow
                indexGelb++;
                // intern
                setzeAktuallisirung();
                UpdateNotizen( NotizVerwaltung.GibGroesse());
            }
        }
maybby someone can help my.

Oh i know my english isn't the best
and i don't know if i did something wrong.

Best wishes
Lord

LordLoser
In need of some credit
In need of some credit
Posts: 2
Joined: Tue Dec 01, 2009 7:05 pm

Post by LordLoser » Mon Dec 07, 2009 6:47 pm

hi,

it seasm to be that difficult.
Does anyone tries something?

mayby it will be simply to tell me how i can draw a line on a wxScrollwindow, in the event MouseLeftDown

or diffeculty to tell how to create a resize able line:D

i hope you know what i mean.

Lord

User avatar
doublemax
Moderator
Moderator
Posts: 15855
Joined: Fri Apr 21, 2006 8:03 pm
Location: $FCE2

Post by doublemax » Mon Dec 07, 2009 6:57 pm

There's just too much code to read, i don't think many people will do that (at least i didn't).

In wxWidgets 2.9.x is a new (totally undocumented) class wxOverlay. In the "drawing" sample it's used to display a selection rectangle. Maybe this might help you for your problem.
Use the source, Luke!

webmasterpdx
Knows some wx things
Knows some wx things
Posts: 27
Joined: Thu Jun 25, 2009 2:43 am
Location: Portland, Oregon
Contact:

Drawing scalable arrows.

Post by webmasterpdx » Sun Dec 19, 2010 4:08 pm

I had to create arrows in my own components in a different GUI once upon a time (QNX Photon) and creating arrows for components like a spincontrol or something like that can be very complex.
The problem is that if you draw an arrow using just line drawing and fill in the triangle, the result is distortion at certain scaling and rotations. Now, I can't remember if this trick works for rotations, but it does for resizing on horizontal and vertical arrows. The arrows remain clean looking as if it were something that came directly from Apple or something :-)
What you do is create an imaginary box into which you are going to draw the arrow. Lets say it's size is N pixels wide. You find the nearest number to N that makes sense, that is a perfect power of two. Lets call this M = 2^a. Then you center this box around the area where you must draw your arrow and draw the arrow fitting exactly into half this box....or the whole box. NOTE: I can't remember if it's 2^a or 2^a - 1 (i.e. if it is odd or even). If it was odd, you'd have the tilted edges of the arror triangle hit a single pixel at the vertex. If even, then the edges meet at a 2 pixel vertex.
The result is that the arrow size resizes in powers of 2. If you are trying to animate an arrow growing, you won't notice the distortions in the animation, as long as you end in a power of two size.
So, remember, your arrows need to be 4, 8, 16, 32, 64 pixels wide....or 3, 7, 15, 31, etc, pixels wide if odd (I just can't remember).

This is a trick worth remembering. Not many people know this trick. I had a lot of trouble trying to get my own component in QNX looking good until I discovered this. Incidentally, I did see the code for doing that in a different GUI, like Qt or something, and it used power of 2 sizes too, so I'm not the only one who knows this.

Good Luck

Post Reply