[wxWidgets] Frame und Tray-Icon



  • Hallo zusammen!

    Seit einiger Zeit frische ich meine (kläglichen 🙂 ) C++ Kenntnisse aus meiner Studienzeit wieder ein wenig auf und versuche mich auch an einfachen GUI-Anwendungen.
    Dazu verwende ich CodeBlocks 10.05 und wxWidgets 2.8

    Aktuell beschäftige ich mich mit den Tray-Icons, komme da aber gar nicht zu Potte. Das wxWidgets-Beispiel 'taskbar' im Ordner 'samples' überfordert mich ein wenig... 🙄
    Ich hoffe ich verlange nicht zu viel, aber wäre es möglich ein minimales Beispiel eines Frames zu bekommen das nichts weiter tut als zusätzlich zum Frame beim Start ein Icon in der Taskleiste zu ezeugen? Sozusagen ein Einstiegsbeispiel an dem ich nachvollziehen kann wie ein solches Icon erzeugt wird. Alles weitere, z.B. ein popup-menü bei Mausklicks auf das Icon und dergleichen, könnte ich dann Schritt für Schritt hinzufügen und so Schritt für Schritt lernen wie diese Icons funktionieren.
    Ich habe Schwierigkeiten den schon erwähnten Beispielcode der wxWidgets-samples nachzuvollziehen da dieses Beispiel doch schon sehr viel "Fleisch auf den Rippen" hat.

    Ich poste der Vollständigkeit wegen mal den Code für einen minimalen Frame und wäre sehr dankbar wenn mir jemand zeigen könnte was hinzugefügt werden muss damit ein Tray-Icon beim Start der .exe erzeugt wird.

    TESTApp.cpp

    #include "TESTApp.h"
    
    //(*AppHeaders
    #include "TESTMain.h"
    #include <wx/image.h>
    //*)
    
    IMPLEMENT_APP(TESTApp);
    
    bool TESTApp::OnInit()
    {
        //(*AppInitialize
        bool wxsOK = true;
        wxInitAllImageHandlers();
        if ( wxsOK )
        {
        	TESTFrame* Frame = new TESTFrame(0);
        	Frame->Show();
        	SetTopWindow(Frame);
        }
        //*)
        return wxsOK;
    
    }
    

    TESTMain.cpp

    #include "TESTMain.h"
    #include <wx/msgdlg.h>
    
    //(*InternalHeaders(TESTFrame)
    #include <wx/intl.h>
    #include <wx/string.h>
    //*)
    
    BEGIN_EVENT_TABLE(TESTFrame,wxFrame)
        //(*EventTable(TESTFrame)
        //*)
    END_EVENT_TABLE()
    
    TESTFrame::TESTFrame(wxWindow* parent,wxWindowID id)
    {
        //(*Initialize(TESTFrame)
        Create(parent, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, wxDEFAULT_FRAME_STYLE, _T("wxID_ANY"));
        //*)
    }
    
    TESTFrame::~TESTFrame()
    {
    }
    

    TESTApp.h

    #ifndef TESTAPP_H
    #define TESTAPP_H
    
    #include <wx/app.h>
    
    class TESTApp : public wxApp
    {
        public:
            virtual bool OnInit();
    };
    
    #endif // TESTAPP_H
    

    TESTMain.h

    #ifndef TESTMAIN_H
    #define TESTMAIN_H
    
    //(*Headers(TESTFrame)
    #include <wx/frame.h>
    //*)
    
    class TESTFrame: public wxFrame
    {
        public:
    
            TESTFrame(wxWindow* parent,wxWindowID id = -1);
            virtual ~TESTFrame();
    
        private:
    
            //(*Handlers(TESTFrame)
            //*)
    
            //(*Identifiers(TESTFrame)
            //*)
    
            //(*Declarations(TESTFrame)
            //*)
    
            DECLARE_EVENT_TABLE()
    };
    
    #endif // TESTMAIN_H
    

    resource.rc

    aaaa ICON "wx/msw/std.ico"
    
    #include "wx/msw/wx.rc"
    

    Ich hoffe ich verlange nicht zu viel mit meiner Bitte, aber für einen ganz simplen Einstieg in die Funktionsweise eines Tray-icons wäre ich sehr dankbar.

    Danke schonmal im Voraus,
    Alberich



  • class Frame : public wxFrame
    {
    public:
            Frame() 
                    : wxFrame(NULL, wxID_ANY, "You should never see me")
            {
                    m_tray = new Tray(this);
                    m_tray->SetIcon(wxIcon(wxwin16x16_xpm));
            }
    
            virtual ~Frame()
            {
                    delete m_tray;
            }
    
    private:
            Tray* m_tray;
    };
    
    class Tray : public wxTaskBarIcon
    {
    public:
            Tray(wxWindow* parent)
                    : wxTaskBarIcon(), m_parent(parent))
            {}
    
            virtual ~Tray()
            {
                    if ( IsIconInstalled() )
                    {
                            RemoveIcon();
                    }
            }
    
    };
    

    Das is im Prinzip der ganze code.
    Tray ist vom Typ wxTaskBarIcon abgeleitet.

    Das komplette Programm findest du hier:
    http://code.google.com/p/aomover/source/browse/trunk/main.cpp
    Ist nur diese eine Datei.

    Du brauchst diesen Dummyframe auch wenn das Programm nur aus dem Icon besteht.



  • Vielen Dank für das Beispiel!
    Ich habe die beiden Klassendefinitionen an die TESTMain.h angehängt, bekomme aber noch Fehlermeldungen des Compilers.
    Die Fehler habe ich als Kommentare in die jeweilige Zeile geschrieben.

    TESTMain.h

    #ifndef TESTMAIN_H
    #define TESTMAIN_H
    
    //(*Headers(TESTFrame)
    #include <wx/frame.h>
    //*)
    
    #include "sample.xpm"     //ich benutze das sample.xpm aus den wxWidgets samples
    #include <wx/taskbar.h>   //das muss ja auch noch includiert werden, richtig?
    
    class TESTFrame: public wxFrame
    {
        public:
    
            TESTFrame(wxWindow* parent,wxWindowID id = -1);
            virtual ~TESTFrame();
    
        private:
    
            //(*Handlers(TESTFrame)
            //*)
    
            //(*Identifiers(TESTFrame)
            //*)
    
            //(*Declarations(TESTFrame)
            //*)
    
            DECLARE_EVENT_TABLE()
    };
    
    //der Dummy-Frame
    class Frame : public wxFrame
    {
    public:
            Frame()
                    : wxFrame(NULL, wxID_ANY, "You should never see me")
            {
                    m_tray = new Tray(this);                    //error 3: 'm_tray' was not declared in this scope|
                                                                //error 4: expected type-specifier before 'Tray'|
                                                                //error 5: expected ';' before 'Tray'|
                    m_tray->SetIcon(wxIcon(sample_xpm));
            }
    
            virtual ~Frame()
            {
                    delete m_tray;                              //error 6: 'm_tray' was not declared in this scope|
            }
    
    private:
            Tray* m_tray;                                       //error 1: ISO C++ forbids declaration of 'Tray' with no type|
                                                                //error 2: expected ';' before '*' token|
    };
    
    //
    class Tray : public wxTaskBarIcon
    {
    public:
            Tray(wxWindow* parent)
                    : wxTaskBarIcon(), m_parent(parent)         //hier war ein ")" zuviel denke ich...
                                                                //error 7: class 'Tray' does not have any field named 'm_parent'|
            {}
    
            virtual ~Tray()
            {
                    if ( IsIconInstalled() )
                    {
                            RemoveIcon();
                    }
            }
    
    }; 
    
    #endif // TESTMAIN_H
    


  • Du brauchst den Frame natürlich nicht, wenn du deinen eigenen TESTframe hast. Du brauchst nur ein Fenster das das TrayIcon quasi beherbergt. Und die Fehler bekommst du, weil der Compiler von Tray nix weiss weil es nach der Klasse Frame steht.
    Entweder eine forward declaration einsetzen oder woanders hinkopieren, wie in eine eigene Datei als Beispiel.
    Mir scheint als ob du den Code nicht wirklich verstehst, sondern nur rumkopierst bis es funzt ;).



  • Scorcher24 schrieb:

    Mir scheint als ob du den Code nicht wirklich verstehst, sondern nur rumkopierst bis es funzt ;).

    Richtig, verstünde ich den Code würde ich nicht um Hilfe bitten müssen. 🙂 Ich versuche Anhand von Beispielen nachzuvollziehen wie z.B. die Tray-Icons funktionieren.

    Die TESTMain.h sieht jetzt so aus, der Compiler meldet nur einen Fehler:

    #ifndef TESTMAIN_H
    #define TESTMAIN_H
    
    //(*Headers(TESTFrame)
    #include <wx/frame.h>
    //*)
    
    #include "sample.xpm"
    #include <wx/taskbar.h>
    
    class Tray : public wxTaskBarIcon
    {
    public:
            Tray(wxWindow* parent)
                    : wxTaskBarIcon() , m_parent(parent)   //error: class 'Tray' does not have any field named 'm_parent'
            {}
    
            virtual ~Tray()
            {
                    if ( IsIconInstalled() )
                    {
                            RemoveIcon();
                    }
            }
    };
    
    class TESTFrame: public wxFrame
    {
        public:
    
            TESTFrame(wxWindow* parent,wxWindowID id = -1);
            virtual ~TESTFrame();
    
        private:
    
            //(*Handlers(TESTFrame)
            //*)
    
            //(*Identifiers(TESTFrame)
            //*)
    
            //(*Declarations(TESTFrame)
            //*)
    
            Tray* m_tray;
    
            DECLARE_EVENT_TABLE()
    };
    
    #endif // TESTMAIN_H
    

    TESTMain.cpp

    BEGIN_EVENT_TABLE(TESTFrame,wxFrame)
        //(*EventTable(TESTFrame)
        //*)
    END_EVENT_TABLE()
    
    TESTFrame::TESTFrame(wxWindow* parent,wxWindowID id)
    {
        //(*Initialize(TESTFrame)
        Create(parent, id, wxEmptyString, wxDefaultPosition, wxDefaultSize, wxDEFAULT_FRAME_STYLE, _T("id"));
        //*)
    
        m_tray = new Tray(this);
        m_tray->SetIcon(wxIcon(sample_xpm));
    }
    
    TESTFrame::~TESTFrame()
    {
        delete m_tray;
    }
    


  • Änderung in der TESTMain.h (Zeilen 27, 28, 29) liefert nun die Meldungen:

    undefined reference to \_imp\_\_\_ZN13wxTaskBarIconC2Ev' undefined reference tovtable for Tray'

    Mit dieser Meldung kann ich leider überhaupt nichts anfangen. 😕
    Wo könnte die Ursache diees Fehlers liegen?

    TESTMain.h

    #ifndef TESTMAIN_H
    #define TESTMAIN_H
    
    //(*Headers(TESTFrame)
    #include <wx/frame.h>
    //*)
    
    #include "sample.xpm"
    #include <wx/taskbar.h>
    
    class Tray : public wxTaskBarIcon
    {
    public:
            Tray(wxWindow* parent)
                    : wxTaskBarIcon() , m_parent(parent)   //undefined reference to `_imp___ZN13wxTaskBarIconC2Ev'
                                                           //undefined reference to `vtable for Tray'
            {}
    
            virtual ~Tray()
            {
                    if ( IsIconInstalled() )
                    {
                            RemoveIcon();
                    }
            }
    
    private:
            wxWindow* m_parent;
            DECLARE_EVENT_TABLE()
    
    };
    
    class TESTFrame: public wxFrame
    {
        public:
    
            TESTFrame(wxWindow* parent,wxWindowID id = -1);
            virtual ~TESTFrame();
    
        private:
    
            //(*Handlers(TESTFrame)
            //*)
    
            //(*Identifiers(TESTFrame)
            //*)
    
            //(*Declarations(TESTFrame)
            //*)
    
            Tray* m_tray;
    
            DECLARE_EVENT_TABLE()
    };
    
    #endif // TESTMAIN_H
    

    TESTMain.cpp

    BEGIN_EVENT_TABLE(TESTFrame,wxFrame)
        //(*EventTable(TESTFrame)
        //*)
    END_EVENT_TABLE()
    
    TESTFrame::TESTFrame(wxWindow* parent,wxWindowID id)
    {
        //(*Initialize(TESTFrame)
        Create(parent, id, wxEmptyString, wxDefaultPosition, wxDefaultSize, wxDEFAULT_FRAME_STYLE, _T("id"));
        //*)
    
        m_tray = new Tray(this);
        m_tray->SetIcon(wxIcon(sample_xpm));
    }
    
    TESTFrame::~TESTFrame()
    {
        delete m_tray;
    }
    

Anmelden zum Antworten