I am making a series of applications on physics simulations and until now I've done some of them using purely the handy SFML library. Now I want to add some GUI elements to them. I am just a little bit familiar with wxWidgets framework and wxFrames but have no idea how wxDc works, which seems to be at the core of SFML-wxWidgets integration. I will list my queries one by one.
My shot at the old tutorial provided by SFML dev webpage: The final code, after correcting for the trivial errors looks like this:
#include <SFML/Graphics.hpp>
#include <wx/wx.h>
class wxSFMLCanvas : public wxControl, public sf::RenderWindow
{
public:
wxSFMLCanvas(wxWindow* Parent = NULL, wxWindowID Id = -1, const wxPoint& Position = wxDefaultPosition,
const wxSize& Size = wxDefaultSize, long Style = 0);
virtual ~wxSFMLCanvas();
private:
DECLARE_EVENT_TABLE()
virtual void OnUpdate();
void OnIdle(wxIdleEvent&);
void OnPaint(wxPaintEvent&);
void OnEraseBackground(wxEraseEvent&);
void OnSize(wxSizeEvent&);
};
void wxSFMLCanvas::OnUpdate()
{
}
void wxSFMLCanvas::OnIdle(wxIdleEvent&)
{
// Send a paint message when the control is idle, to ensure maximum framerate
Refresh();
}
void wxSFMLCanvas::OnPaint(wxPaintEvent&)
{
// Prepare the control to be repainted
wxPaintDC Dc(this);
// Let the derived class do its specific stuff
OnUpdate();
// Display on screen
display();
}
void wxSFMLCanvas::OnEraseBackground(wxEraseEvent&)
{
}
void wxSFMLCanvas::OnSize(wxSizeEvent&)
{
}
wxSFMLCanvas::wxSFMLCanvas(wxWindow* Parent, wxWindowID Id, const wxPoint& Position, const wxSize& Size, long Style) :
wxControl(Parent, Id, Position, Size, Style) {
sf::RenderWindow::create(GetHandle());
}
wxSFMLCanvas::~wxSFMLCanvas()
{
}
class MyCanvas : public wxSFMLCanvas
{
sf::CircleShape circ;
public:
MyCanvas(wxWindow* Parent, wxWindowID Id, wxPoint& Position, wxSize& Size, long Style = 0) : wxSFMLCanvas(Parent, Id, Position, Size, Style) {
// specify circle
circ.setRadius(50.0f);
circ.setOrigin(50.0f,50.0f);
circ.setFillColor(sf::Color::Blue);
circ.setPosition(100.0f, 100.0f);
}
private:
virtual void OnUpdate() {
// Clear the view
clear(sf::Color(0, 128, 128));
// Display the circle in the view
draw(circ);
}
};
class MyFrame : public wxFrame
{
public:
MyFrame() : wxFrame(NULL, wxID_ANY, "SFML wxWidgets", wxDefaultPosition, wxSize(800, 600)) {
wxPoint tmp1 = wxPoint(50, 50);
wxSize tmp2 = wxSize(700, 500);
new MyCanvas(this, wxID_ANY, tmp1, tmp2);
}
};
class MyApplication : public wxApp
{
private:
virtual bool OnInit()
{
// Create the main window
MyFrame* MainFrame = new MyFrame;
MainFrame->Show();
return true;
}
};
IMPLEMENT_APP(MyApplication);
This throws a bunch of unresolved externals:
Error LNK2001 unresolved external symbol "protected: virtual struct wxEventTable const * __cdecl wxSFMLCanvas::GetEventTable(void)const " (?GetEventTable#wxSFMLCanvas##MEBAPEBUwxEventTable##XZ) test1 C:\Users\rajat\source\repos\test1\test1.obj 1
Error LNK2001 unresolved external symbol "protected: virtual class wxEventHashTable & __cdecl wxSFMLCanvas::GetEventHashTable(void)const " (?GetEventHashTable#wxSFMLCanvas##MEBAAEAVwxEventHashTable##XZ) test1 C:\Users\rajat\source\repos\test1\test1.obj 1
Error LNK2019 unresolved external symbol main referenced in function "int __cdecl invoke_main(void)" (?invoke_main##YAHXZ) test1 C:\Users\rajat\source\repos\test1\MSVCRTD.lib(exe_main.obj) 1
Furthermore, I don't quite understand how in this example wxWidgets is supposed to draw the contents of a sf::RenderWindow. It will be very helpful if someone can rectify this barebone code so that it works. And also hopefully explain how it works.
Is there an alternative to wxWidgets that would work with SFML, or has a handy tool for fast and simple graphical library? The only requirement is that I should be able to compile it on MSVS for x64 framework and statically link to my application. I considered Qt, but I can't get it to either compile on my own, or even if I do, it's only the 32-bit shared library configuration.
How is the code supposed to work? The sf::RenderWindow is created using sf::RenderWindow::create(GetHandle()). Is it supposed to draw everything on its own? Or do I have to copy the bitmap of the SFML window and draw on the wxControl by myself? It will be really helpful if someone could shed some light on how it's supposed to work.
Your error is due to using DECLARE_EVENT_TABLE but not using any wxBEGIN_EVENT_TABLE/wxEND_EVENT_TABLE, i.e. you never define your event table nor connect any event handlers.
I don't know anything about SFML, so I can't really help you with the rest, but apparently drawing is supposed to be done from your wxEVT_PAINT handler -- once you connect it -- by just calling sf::RenderWindow::Display().
I finally got them to work together. Here's a minimal code that shows a circle on a button click:
#include <SFML/Graphics.hpp>
#include <wx/wx.h>
class wxSFMLCanvas : public wxControl, public sf::RenderWindow
{
public:
wxSFMLCanvas(wxWindow* Parent = NULL, wxWindowID Id = -1, const wxPoint& Position = wxDefaultPosition,
const wxSize& Size = wxDefaultSize, long Style = 0);
virtual ~wxSFMLCanvas();
};
wxSFMLCanvas::wxSFMLCanvas(wxWindow* Parent, wxWindowID Id, const wxPoint& Position, const wxSize& Size, long Style) :
wxControl(Parent, Id, Position, Size, Style) {
sf::RenderWindow::create(GetHandle());
}
wxSFMLCanvas::~wxSFMLCanvas() {
}
class cMain : public wxFrame
{
wxButton* m_btn1 = nullptr;
wxSFMLCanvas* mycanv = nullptr;
wxDECLARE_EVENT_TABLE();
public:
cMain();
void onBtnClicked(wxCommandEvent &evt);
};
wxBEGIN_EVENT_TABLE(cMain,wxFrame)
EVT_BUTTON(10001, onBtnClicked)
wxEND_EVENT_TABLE()
cMain::cMain() : wxFrame(nullptr, wxID_ANY, "Window", wxPoint(30, 30), wxSize(800, 600)) {
mycanv = new wxSFMLCanvas(this, wxID_ANY, wxPoint(50, 50), wxSize(700, 500));
m_btn1 = new wxButton(this, 10001, "button1", wxPoint(10, 10), wxSize(100, 50));
}
void cMain::onBtnClicked(wxCommandEvent& evt) {
sf::CircleShape circ(50.0f);
circ.setOrigin(50.0f, 50.0f);
circ.setFillColor(sf::Color::Blue);
circ.setPosition(350, 250);
mycanv->draw(circ);
mycanv->display();
}
class myApp : public wxApp
{
cMain* m_Frame1 = nullptr;
public:
myApp();
virtual bool OnInit();
};
wxIMPLEMENT_APP(myApp);
myApp::myApp() {
}
bool myApp::OnInit() {
// Create the main window
m_Frame1 = new cMain;
m_Frame1->Show();
return true;
}
The executable of this code(everything statically linked) are ~10MB(debug mode) ~4MB(release mode). I'm leaving this code here in case anyone else finds this useful.
Related
Compiled application
I want to make the Hello World text bigger, but i can't figure out how
I tried using staticText1->SetSize(32), staticText1->SetSize(wxSize(32,32)) and replacing wxDefaultSize with wxSize(32, 32), but nothing works (I am not getting errors, it just doesnt change the text size)
This is my current code:
#include <wx/wx.h>
class Frame : public wxFrame
{
private:
wxStaticText* staticText1 = new wxStaticText(this, wxID_ANY, "Hello, World!", wxDefaultPosition, wxDefaultSize, wxALIGN_CENTER);
public:
Frame() : wxFrame(nullptr, wxID_ANY, "spageta", wxDefaultPosition, wxSize(400, 200)) {
staticText1->SetForegroundColour(wxTheColourDatabase->Find("Black"));
}
};
class App : public wxApp
{
public:
App();
private:
wxFrame* NewFrame = nullptr;
public:
virtual bool OnInit();
};
App::App()
{
}
bool App::OnInit()
{
NewFrame = new Frame();
NewFrame->Show(true);
return true;
}
wxIMPLEMENT_APP(App);
You need to change the font size and not the window size. The best way to do it is to change the size of the same font it already uses, e.g. window->SetFont(window->GetFont().Scale(1.5)), which would make the font 1.5 times bigger. The same approach can be used to make it bold, or italic etc.
This error is with wxWidgets 3.1.5, and SFML 2.5.1
I have the following code:
(main.cpp) :-
#include <SFML/Graphics.hpp>
#include <wx/wx.h>
#include "wxSfmlCanvas.h"
#include "main.h"
TestFrame::TestFrame() :
wxFrame(NULL, wxID_ANY, "SFML 2.5 w/ wxWidgets 3.1", wxDefaultPosition, wxSize(650, 490))
{
mCanvas = new TestSfmlCanvas(this, wxID_ANY, wxPoint(5, 25), wxSize(640, 480));
// Also add a button.
wxButton *button = new wxButton(
this,
wxID_ANY,
wxT("Toggle Size"),
wxPoint(5, 5)
);
button->Bind(wxEVT_BUTTON, [&](wxCommandEvent& arg) -> void {
mCanvas->toggleSize();
});
wxBoxSizer* mainSizer = new wxBoxSizer( wxVERTICAL );
mainSizer->Add(mCanvas, 6, wxALIGN_TOP | wxEXPAND);
mainSizer->Add(button, 0, wxALIGN_RIGHT | wxALIGN_BOTTOM);
SetSizerAndFit(mainSizer);
}
TestSfmlCanvas::TestSfmlCanvas(
wxWindow* Parent,
wxWindowID Id,
wxPoint& Position,
wxSize& Size,
long Style
) : wxSfmlCanvas(Parent, Id, Position, Size, Style),
mLarge(false)
{
// Load a texture and create a sprite.
mTexture.loadFromFile("data/ball.png");
mSprite = std::make_unique<sf::Sprite>(mTexture);
}
void
TestSfmlCanvas::OnUpdate()
{
clear(sf::Color(64, 196, 196));
draw(*mSprite);
}
void
TestSfmlCanvas::toggleSize()
{
if (mLarge) {
mSprite->setScale(sf::Vector2f(1.2f, 1.2f));
}
else {
mSprite->setScale(sf::Vector2f(0.5f, 0.5f));
}
mLarge = !mLarge;
}
IMPLEMENT_APP(TestApplication);
(and main.h) :-
#pragma once
#include <memory>
#include <SFML/Graphics.hpp>
#include <wx/wx.h>
#include <string>
#include "wxSfmlCanvas.h"
// Our overridden class that does some SFML drawing.
class TestSfmlCanvas : public wxSfmlCanvas
{
public:
TestSfmlCanvas(
wxWindow* Parent,
wxWindowID Id,
wxPoint& Position,
wxSize& Size,
long Style = 0
);
void toggleSize();
protected:
void OnUpdate() override;
private:
sf::Texture mTexture;
std::unique_ptr<sf::Sprite> mSprite;
bool mLarge;
};
// wx Frame to contain the main canvas control. Can have extra controls added to it as desired.
class TestFrame : public wxFrame
{
public :
TestFrame();
protected:
TestSfmlCanvas* mCanvas;
};
// Main wx Application instance.
class TestApplication : public wxApp
{
private :
virtual bool OnInit()
{
// Create the main window
TestFrame* MainFrame = new TestFrame;
MainFrame->Show();
return true;
}
};
(wxSFMLCanvas.h) :-
#pragma once
#include <SFML/Graphics.hpp>
#include <wx/wx.h>
#include <string>
class wxSfmlCanvas : public wxControl, public sf::RenderWindow
{
public:
wxSfmlCanvas(wxWindow* Parent = nullptr,
wxWindowID Id = -1,
//const wxPoint& Position = wxDefaultPosition,
const wxSize& Size = wxDefaultSize,
long Style = 0);
virtual ~wxSfmlCanvas();
protected:
virtual void OnUpdate();
void OnIdle(wxIdleEvent&);
void OnPaint(wxPaintEvent&);
void OnEraseBackground(wxEraseEvent&);
void OnSize(wxSizeEvent&);
DECLARE_EVENT_TABLE()
};
(wxSFMLCanvas.cpp) :-
#include "wxSfmlCanvas.h"
#include <wx/wx.h>
#include <string>
BEGIN_EVENT_TABLE(wxSfmlCanvas, wxControl)
EVT_PAINT(wxSfmlCanvas::OnPaint)
EVT_IDLE(wxSfmlCanvas::OnIdle)
EVT_ERASE_BACKGROUND(wxSfmlCanvas::OnEraseBackground)
EVT_SIZE(wxSfmlCanvas::OnSize)
END_EVENT_TABLE()
#ifdef __WXGTK__
#include <string>
#include <gdk/gdkx.h>
#include <gtk/gtk.h>
#include <wx/gtk/win_gtk.h>
#endif
wxSfmlCanvas::wxSfmlCanvas(wxWindow* Parent,
wxWindowID Id,
const wxPoint& Position,
const wxSize& Size,
long Style) :
wxControl(Parent, Id, Position, Size, Style)
{
#ifdef __WXGTK__
#else
sf::RenderWindow::create(GetHandle());
#endif
}
void wxSfmlCanvas::OnIdle(wxIdleEvent&)
{
// Send a paint message when the control is idle, to ensure maximum framerate
Refresh();
}
wxSfmlCanvas::~wxSfmlCanvas()
{
}
void wxSfmlCanvas::OnUpdate()
{
}
void wxSfmlCanvas::OnEraseBackground(wxEraseEvent&)
{
}
void wxSfmlCanvas::OnSize(wxSizeEvent& args)
{
// Set the size of the sfml rendering window
setSize(sf::Vector2u(args.GetSize().x, args.GetSize().y));
// Also adjust the viewport so that a pixel stays 1-to-1.
setView(sf::View(sf::FloatRect(0, 0, args.GetSize().x, args.GetSize().y)));
}
void wxSfmlCanvas::OnPaint(wxPaintEvent&)
{
// Prepare the control to be repainted
wxPaintDC Dc(this);
// Let the derived class do its specific stuff
OnUpdate();
// Display on screen
display();
}
With this code, I get the following compile errors:
Severity Code Description Project File Line Suppression State Error C4996 '_wgetenv': This function or variable may be unsafe. Consider using _wdupenv_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details. ae D:\wxwidg\include\wx\wxcrt.h 1050
And 100 similar others.
Why? what did I do wrong for this?
wxWidgets is properly built, SFML and wx work fine on their own, but when combined, this error takes place for some reason.
The messages you show are not errors at all, they are static analyser warnings and can be safely ignored, the "unsafe" functions are not used in unsafe way inside wxWidgets.
I have made an application using wxWidgets 3.1.5 in C++ and everything is working fine except a test button that I have on my main window.
Here's a pic:
The menubar, menus and their functions work perfectly but the button covers the entire client area.
Here's the code:
main.h
#pragma once
#include <wx\wx.h>
#include "mainFrame.h"
class main : public wxApp
{
private:
mainFrame* frame;
public:
virtual bool OnInit();
};
main.cpp
#include "main.h"
wxIMPLEMENT_APP(main);
bool main::OnInit()
{
frame = new mainFrame("Kill Me", wxPoint(15, 10), wxSize(640, 480));
frame->Show();
return true;
}
mainFrame.h
#pragma once
#include "About.h"
using str = std::string;
class mainFrame : public wxFrame
{
public:
mainFrame(const wxString& title, const wxPoint& pos, const wxSize& size);
~mainFrame();
private:
About* abtF = NULL;
wxButton* hewwo = NULL;
wxMenuBar* mbar = NULL;
wxMenu* sett = NULL;
wxMenu* quitApp = NULL;
wxMenu* abt = NULL;
void onHewwo(wxCommandEvent& evt);
void onSett(wxCommandEvent& evt);
void quit(wxCommandEvent& evt);
void about(wxCommandEvent& evt);
wxDECLARE_EVENT_TABLE();
};
enum {
ID_SETT = 1,
ID_BTN = 2
};
mainFrame.cpp
#include "mainFrame.h"
wxBEGIN_EVENT_TABLE(mainFrame, wxFrame)
EVT_BUTTON(ID_BTN, onHewwo)
EVT_MENU(ID_SETT, onSett)
EVT_MENU(wxID_EXIT, quit)
EVT_MENU(wxID_ABOUT, about)
wxEND_EVENT_TABLE()
mainFrame::mainFrame(const wxString& title, const wxPoint& pos, const wxSize& size)
:
wxFrame(nullptr, wxID_ANY, title, pos, size) {
hewwo = new wxButton(this, ID_BTN, "Hewwo World", wxPoint(15, 15), wxSize(70, 20));
sett = new wxMenu();
sett->AppendSeparator();
sett->Append(ID_SETT, "&Settings");
quitApp = new wxMenu();
quitApp->AppendSeparator();
quitApp->Append(wxID_EXIT, "&Quit this crap");
abt = new wxMenu();
abt->AppendSeparator();
abt->Append(wxID_ABOUT, "&About");
mbar = new wxMenuBar();
mbar->Append(sett, "&Settings");
mbar->Append(abt, "&About");
mbar->Append(quitApp, "&Quit");
SetMenuBar(mbar);
}
void mainFrame::onHewwo(wxCommandEvent& evt) {
wxMessageBox("Hewwo", "Hewwo", wxOK | wxICON_INFORMATION, this);
}
void mainFrame::onSett(wxCommandEvent& evt) {
wxMessageBox("Settings", "Settings", wxOK | wxICON_INFORMATION, this); // Just a test
}
void mainFrame::about(wxCommandEvent& evt) {
abtF = new About(wxPoint(10, 10), wxSize(480, 320));
abtF->Show();
}
void mainFrame::quit(wxCommandEvent& evt) {
Close(true);
}
mainFrame::~mainFrame() {
delete abtF;
}
I'm using Visual Studio 2019.
(I followed OneLoneCoder's (javidx9) youtube video on wxWidgets)
That is how a wxFrame with only one child behaves.
If you don't want that, use a wxSizer to layout your button (position, align, expand etc).
Reference:
if the frame has exactly one child window, not counting the status and toolbar, this child is resized to take the entire frame client area. If two or more windows are present, they should be laid out explicitly either by manually handling wxEVT_SIZE or using sizers
wxFrame docs -> Default event processing -> wxEVT_SIZE
Hi i am trying to create a wxApp that will have not have a titlebar(including the minimize, maximize and close) icons that are by default provided. The code that i have is as follows:
main.h
class MyApp : public wxApp
{
public:
virtual bool OnInit();
};
main.cpp
bool MyApp::OnInit()
{
MyFrame *prop = new MyFrame(wxT("MyFrame"));
prop->Show(true);
return true;
}
myframe.h
class MyFrame : public wxFrame
{
public:
MyFrame(const wxString& title);
void OnClick(wxMouseEvent& event);
};
myframe.cpp
MyFrame::MyFrame(const wxString& title)
: wxFrame(NULL, wxID_ANY, title, wxDefaultPosition, wxSize(250, 130))
{
MyPanel *panel = new MyPanel(this, wxID_ANY);
panel->SetBackgroundColour(wxColour(255,255,255));
MyButton *button = new MyButton(panel, wxID_ANY, wxT("Ok"));
Connect( wxEVT_LEFT_UP,
wxMouseEventHandler(MyFrame::OnClick));
panel->Centre();
}
void MyFrame::OnClick(wxMouseEvent& event)
{
std::cout << "event reached frame class" << std::endl;
}
mypanel.h
class MyPanel : public wxPanel
{
public:
MyPanel(wxFrame *frame, int id);
void OnClick(wxMouseEvent& event);
};
mypanel.cpp
MyPanel::MyPanel(wxFrame *frame, int id)
: wxPanel(frame, id)
{
Connect( wxEVT_LEFT_UP,
wxMouseEventHandler(MyPanel::OnClick));
}
void MyPanel::OnClick(wxMouseEvent& event)
{
std::cout << "event reached panel class" << std::endl;
}
mybutton.h
class MyButton : public wxPanel
{
public:
MyButton(wxPanel *panel, int id, const wxString &label);
void OnClick(wxMouseEvent& event);
};
mybutton.cpp
void MyButton::onClick(wxMouseEvent &event)
{
}
What i want is:
There should be no title bar(including the 3 maximize, minimize & close buttons) at the top.
Now since there is no titlebar at the top of the frame, there is no way to drag or close or maximize or minimize the window. For that i want to create a custom titlebar at the top which should have the three customized maximized,minimized and close button and also i should be able to drag the frame by double clicking and holding and dragging the topmost part of the newly created frame.
Is this possible in wxWidgets? If yes, how can i achieve this?
I am not proposing any new way of dragging. The new frame/window that we will have should also be dragged only by its own customized title bar. It's exactly like dragging the old frame by double clicking and dragging the frame in the native case. I just want to customize the native title bar. Like increase its height, change it's colour, change how to three buttons(minimize, maximize and close) look.
Here's the simplest example I can think of how to create a frame with a pseudo titlebar that can be clicked to drag the frame around. This example shows which mouse events need to be handled to drag the window around and how to do the calculations needed in those event handlers.
Note that moving the frame needs to be done in screen coordinates, but the coordinates received in the event handlers will be in client coordinates for the title bar. This example also shows how to do those coordinate conversions.
#include "wx/wx.h"
class CustomTitleBar:public wxWindow
{
public:
CustomTitleBar(wxWindow* p) : wxWindow(p,wxID_ANY)
{
m_dragging = false;
SetBackgroundColour(*wxGREEN);
Bind(wxEVT_LEFT_DOWN,&CustomTitleBar::OnMouseLeftDown,this);
Bind(wxEVT_MOUSE_CAPTURE_LOST, &CustomTitleBar::OnMouseCaptureLost,
this);
}
wxSize DoGetBestClientSize() const override
{
return wxSize(-1,20);
}
private:
void OnMouseLeftDown(wxMouseEvent& event)
{
if ( !m_dragging )
{
Bind(wxEVT_LEFT_UP,&CustomTitleBar::OnMouseLeftUp,this);
Bind(wxEVT_MOTION,&CustomTitleBar::OnMouseMotion,this);
m_dragging = true;
wxPoint clientStart = event.GetPosition();
m_dragStartMouse = ClientToScreen(clientStart);
m_dragStartWindow = GetParent()->GetPosition();
CaptureMouse();
}
}
void OnMouseLeftUp(wxMouseEvent&)
{
FinishDrag();
}
void OnMouseMotion(wxMouseEvent& event)
{
wxPoint curClientPsn = event.GetPosition();
wxPoint curScreenPsn = ClientToScreen(curClientPsn);
wxPoint movementVector = curScreenPsn - m_dragStartMouse;
GetParent()->SetPosition(m_dragStartWindow + movementVector);
}
void OnMouseCaptureLost(wxMouseCaptureLostEvent&)
{
FinishDrag();
}
void FinishDrag()
{
if ( m_dragging )
{
Unbind(wxEVT_LEFT_UP,&CustomTitleBar::OnMouseLeftUp,this);
Unbind(wxEVT_MOTION,&CustomTitleBar::OnMouseMotion,this);
m_dragging = false;
}
if ( HasCapture() )
{
ReleaseMouse();
}
}
wxPoint m_dragStartMouse;
wxPoint m_dragStartWindow;
bool m_dragging;
};
class Customframe : public wxFrame
{
public:
Customframe(wxWindow* p)
:wxFrame(p, wxID_ANY, wxString(), wxDefaultPosition, wxSize(150,100),
wxBORDER_NONE)
{
CustomTitleBar* t = new CustomTitleBar(this);
SetBackgroundColour(*wxBLUE);
wxBoxSizer* szr = new wxBoxSizer(wxVERTICAL);
szr->Add(t,wxSizerFlags(0).Expand());
SetSizer(szr);
Layout();
}
};
class MyFrame: public wxFrame
{
public:
MyFrame():wxFrame(NULL, wxID_ANY, "Custom frame Demo", wxDefaultPosition,
wxSize(400, 300))
{
wxPanel* bg = new wxPanel(this, wxID_ANY);
wxButton* btn = new wxButton(bg, wxID_ANY, "Custom frame");
wxBoxSizer* szr = new wxBoxSizer(wxVERTICAL);
szr->Add(btn,wxSizerFlags(0).Border(wxALL));
bg->SetSizer(szr);
Layout();
btn->Bind(wxEVT_BUTTON, &MyFrame::OnButton, this);
m_customFrame = NULL;
}
private:
void OnButton(wxCommandEvent&)
{
if ( m_customFrame )
{
m_customFrame->Close();
m_customFrame = NULL;
}
else
{
m_customFrame = new Customframe(this);
m_customFrame->CenterOnParent();
m_customFrame->Show();
}
}
wxFrame* m_customFrame;
};
class MyApp : public wxApp
{
public:
virtual bool OnInit()
{
MyFrame* frame = new MyFrame();
frame->Show();
return true;
}
};
wxIMPLEMENT_APP(MyApp);
On windows, it looks like this.
You should be able to add whatever buttons you want to the custom title bar exactly as you would add buttons to any other window.
"Is this possible in wxWidgets?"
Yes. You need to use a wxWindow instead of a wxFrame and set some style for it. like wxBORDER_NONE. But you will have to implement many things that wxFrame already provides.
And your proposed way of dragging seems wrong/confusing to me. 99.99% of users prefer a UI they are used to it, avoiding to learn a new way of doing simple things they already know.
If you just want to avoid resizing then you have two ways:
a) Catch the size-event and do nothing. Calling event.Skip(false)
(to prevent handling in parent) is not neccessary.
b) Once you have created your window and correctly sized, get its size and set it as max and min.
In both cases the user will see a "resize" mouse pointer when hovering the mouse at any border, but nothing else, no resizing, will be done.
#JasonLiam,
Don't forget to place the application icon in the top left corner of you title bar and handle the right/left mouse clicks appropriately (as in native application) (if you want to go this route and get rid of the native frame window).
Thank you.
I am using wxTreeListCtrl with wxTL_CHECKBOX style, but for some reason I am not able to check checkbox using mouse click, though I can do it by pressing SPACE. Is this normal, or am I missing something ?
My code:
// .h file
#include <wx/wx.h>
#include <wx/treelist.h>
class MyApp: public wxApp
{
public:
virtual bool OnInit();
};
class MyFrame: public wxFrame
{
public:
MyFrame(const wxString& title, const wxPoint& pos, const wxSize& size);
private:
void OnTreeLeftDown (wxMouseEvent& evt);
private:
enum
{
TreeListId = 1
};
wxTreeListCtrl* m_treeList;
wxDECLARE_EVENT_TABLE();
};
// .cpp file
wxBEGIN_EVENT_TABLE (MyFrame, wxFrame)
wxEND_EVENT_TABLE()
wxIMPLEMENT_APP(MyApp);
bool MyApp::OnInit()
{
MyFrame *frame = new MyFrame ("Hello World", wxPoint(50, 50), wxSize(600, 400));
frame->Show (true);
return true;
}
MyFrame::MyFrame (const wxString& title, const wxPoint& pos, const wxSize& size)
: wxFrame (NULL, wxID_ANY, title, pos, size)
{
m_treeList = new wxTreeListCtrl (this, TreeListId, wxPoint (10, 10), wxSize(600, 400), wxTL_CHECKBOX);
m_treeList->AppendColumn (L"Item Name");
m_treeList->AppendItem (m_treeList->GetRootItem(), L"Test");
m_treeList->AppendItem (m_treeList->GetRootItem(), L"Another one");
CenterOnScreen ();
}
As someone pointed out in wxWidgets forum it is a bug in 3.0.0
Here is bug url http://trac.wxwidgets.org/ticket/15731