I'm new to macos, I'm trying to figure out how to make an application bundle so my code won't be just an executable file.
I'm working with xcode version 12.5 and writing a test gui application using c++ language and the wxWidgets library.
Now I tried to make a simple gui with just a button and a menu bar (The bar on top of the screen with different menus like File or About ). I encountered 2 issues :
The first and the major one is that the menubar doesn't respond when the executable starts, it only works when focused on another program and then focuses back to the executable, then the menu is clickable and working. I read that this happens because I build the program as an executable and not as an application bundle. Although, couldn't figure out how to do so in xcode, and the internet doesn't quite answers how to do so.
The button doesn't have a click effect when you only touch the mousepad ( you have to click it to make a blue click effect ), you have to click and hold the button to see the button change color.
CODE :
cpp file of the app ( inherits from wxApp )
bool instaStalkApp::OnInit(){
instaFrame = new instaStalkFrame("InstaStalk", wxPoint(50,50), wxSize(P_WIDTH,P_HEIGHT));
instaFrame->Show(true);
SetTopWindow(instaFrame);
mainPanel = new instaStalkPanel(instaFrame, ID_PANEL_MAIN, wxPoint(-1,-1), wxSize(P_WIDTH, P_HEIGHT), wxTAB_TRAVERSAL, "panel");
testButton = new instaButton(mainPanel, ID_TEST_BUTTON_1, "test1" , wxPoint(P_WIDTH / 2 ,P_HEIGHT / 2), wxSize(100,20), "test1but");
return true;
}
Header file of the button class :
#ifndef instaButton_hpp
#define instaButton_hpp
#include <stdio.h>
#include <wx/wx.h>
class instaButton : public wxButton {
private:
public:
instaButton(wxWindow *parent, wxWindowID id, const wxString &label, const wxPoint &pos, const wxSize &size, const wxString &name);
void On_Button1Click(wxCommandEvent &event);
wxDECLARE_EVENT_TABLE();
};
#endif /* instaButton_hpp */
event table of the button :
wxBEGIN_EVENT_TABLE(instaButton, wxButton)
EVT_BUTTON(ID_TEST_BUTTON_1, instaButton::On_Button1Click)
wxEND_EVENT_TABLE()
cpp file of custom button
#include <wx/wx.h>
#include "instaButton.hpp"
instaButton::instaButton(wxWindow *parent, wxWindowID id, const wxString &label, const wxPoint &pos, const wxSize &size, const wxString &name) : wxButton(parent, id, label, pos, size, 0, wxDefaultValidator, name){
}
void instaButton::On_Button1Click(wxCommandEvent &event){
wxLogMessage("hi");
}
cpp file of the frame with the menuBar :
#include <wx/wx.h>
#include "instaStalkFrame.hpp"
#include "instaStalkPanel.hpp"
#include "consts.hpp"
instaStalkFrame::instaStalkFrame(const wxString& title, const wxPoint& pos, const wxSize& size) : wxFrame(NULL, wxID_ANY, title, pos, size){
menuFile = new wxMenu;
menuFile->Append(ID_TEST, "&Hello...\tCtrl-H",
"Help string shown in status bar for this menu item");
menuFile->AppendSeparator();
menuFile->Append(wxID_EXIT);
menuHelp = new wxMenu;
menuHelp->Append(wxID_ABOUT);
menuBar = new wxMenuBar;
menuBar->Append( menuFile, "&File" );
menuBar->Append( menuHelp, "&Help" );
SetMenuBar(menuBar);
}
void instaStalkFrame::OnExit(wxCommandEvent& event){
Close(true);
}
void instaStalkFrame::OnAbout(wxCommandEvent& event){
wxMessageBox( "This is a wxWidgets' Hello world sample",
"About Hello World", wxOK | wxICON_INFORMATION );
}
void instaStalkFrame::OnTest(wxCommandEvent& event){
wxLogMessage("Test!");
}
In order to make an Application Bundle:
You should have been creating an OSX Application project inside Xcode. Check wxWiki (I know it is for older version of Xcode, but it still applies and you can try to match it in the newer version).
If you want to do that later - you can try to build minimal sample from thr wxWidgets distribution, see what it uses in order to create a bundle and replicate that in you test program. But you absolutely should make an Application Bundle project in Xcode to simplify your life.
The menu will start working when you create a Bundle. As you should.
I don't think hovering effect is implemented. You can ask about it on wx-users ML.
Let us know if you need any more guidance.
Related
I made a GUI application in wxWidgets and kept receiving anti virus alerts by various users. I spent a great amount of time commenting out code and re-uploading the EXE to VirusTotal. It turns out, none of this was my code. Using the wxWidgets framework alone will cause plenty of detections. I tried again by compiling a simple hello world application and sure enough, this is the result:
Full source code:
// wxWidgets "Hello world" Program
// For compilers that support precompilation, includes "wx/wx.h".
#include <wx/wxprec.h>
#ifndef WX_PRECOMP
#include <wx/wx.h>
#endif
// Required for static linking
#pragma comment(lib, "comctl32")
#pragma comment(lib, "Rpcrt4")
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 OnHello(wxCommandEvent& event);
void OnExit(wxCommandEvent& event);
void OnAbout(wxCommandEvent& event);
wxDECLARE_EVENT_TABLE();
};
enum
{
ID_Hello = 1
};
wxBEGIN_EVENT_TABLE(MyFrame, wxFrame)
EVT_MENU(ID_Hello, MyFrame::OnHello)
EVT_MENU(wxID_EXIT, MyFrame::OnExit)
EVT_MENU(wxID_ABOUT, MyFrame::OnAbout)
wxEND_EVENT_TABLE()
wxIMPLEMENT_APP(MyApp);
bool MyApp::OnInit()
{
MyFrame* frame = new MyFrame("Hello World", wxPoint(50, 50), wxSize(450, 340));
frame->Show(true);
return true;
}
MyFrame::MyFrame(const wxString& title, const wxPoint& pos, const wxSize& size)
: wxFrame(NULL, wxID_ANY, title, pos, size)
{
wxMenu* menuFile = new wxMenu;
menuFile->Append(ID_Hello, "&Hello...\tCtrl-H",
"Help string shown in status bar for this menu item");
menuFile->AppendSeparator();
menuFile->Append(wxID_EXIT);
wxMenu* menuHelp = new wxMenu;
menuHelp->Append(wxID_ABOUT);
wxMenuBar* menuBar = new wxMenuBar;
menuBar->Append(menuFile, "&File");
menuBar->Append(menuHelp, "&Help");
SetMenuBar(menuBar);
CreateStatusBar();
SetStatusText("Welcome to wxWidgets!");
}
void MyFrame::OnExit(wxCommandEvent& event)
{
Close(true);
}
void MyFrame::OnAbout(wxCommandEvent& event)
{
wxMessageBox("This is a wxWidgets' Hello world sample",
"About Hello World", wxOK | wxICON_INFORMATION);
}
void MyFrame::OnHello(wxCommandEvent& event)
{
wxLogMessage("Hello world from wxWidgets!");
}
How can these be fixed without contacting each AV vendor? Clearly, the code is not malicious and wxWidgets is a popular cross-platform GUI framework which shouldn't cause any AV detections on its own. The static EXE however is quite big and pulls in a lot of Windows API functions so it's hard to even pinpoint anything.
I'm creating a C++ wxWidgets calculator application. I'm implementing trigonometric functions, and to save on space I've reunited all of them in a single button. If you right click on the button then, a popup is created, which contains buttons for all the functions. I'm using a derived wxPopupTransientWindow class for this job, the problem is, the buttons aren't displaying correctly.
This is my code:
expandMenu.h
#include "wx/wx.h"
#include "wx/popupwin.h"
struct expandMenuInfo
{
const wxString& label;
wxWindowID id;
expandMenuInfo(const wxString& l, wxWindowID i)
: label{l}
, id{i}
{}
};
class expandMenu : public wxPopupTransientWindow
{
wxWindow* panel;
wxBoxSizer* sizer;
public:
expandMenu(wxWindow* parent, wxPoint pos, std::vector<expandMenuInfo> buttons);
~expandMenu();
};
expandMenu.cpp
#include "expandMenu.h"
// PANNELLO ESTENSIONE
expandMenu::expandMenu(wxWindow* parent, wxPoint pos, std::vector<expandMenuInfo> buttons)
: wxPopupTransientWindow(parent, wxBORDER_NONE | wxPU_CONTAINS_CONTROLS)
{
this->SetPosition(pos);
this->SetSize(50 * buttons.size(), 50);
this->SetBackgroundColour(wxColour(90, 93, 121));
panel = new wxWindow(this, wxID_ANY);
sizer = new wxBoxSizer(wxHORIZONTAL);
// costruisci struttura
for (unsigned int i = 0; i < buttons.size(); i++)
{
wxButton* btn = new wxButton(this, buttons.at(i).id, buttons.at(i).label);
sizer->Add(btn, 1, wxEXPAND);
}
panel->SetSizer(sizer);
}
expandMenu::~expandMenu()
{
}
And this is the code I use for my custom wxButton's to actually create the popup (it's temporary):
void ikeButton::rightClick(wxMouseEvent& evt) // CREA PANNELLO ESTENSIONE
{
if (flags & EXPANDABLE)
{
std::vector<expandMenuInfo> buttons;
buttons.push_back(expandMenuInfo(L"sin", 3001));
buttons.push_back(expandMenuInfo(L"cos", 3002));
buttons.push_back(expandMenuInfo(L"tan", 3003));
expandMenu* menu = new expandMenu(this, wxGetMousePosition(), buttons);
menu->Popup();
}
}
Thank you in advance for any help, as I'm pretty new to this framework.
To get the buttons to layout in the popup window, in the constuctor for expandMenu I think you just need to change panel->SetSizer(sizer); to
SetSizerAndFit(sizer);
Layout();
From a UI perspective, I think a split button might be a better way to implement the functionality you are describing. wxWidgets doesn't currently have such a control, but this post shows 2 different ways you can create one.
I believe the issue is that you're specifying this for the parent of the buttons, i.e. the popup window. I think you wanted their parent to be the panel instead.
i installed wxwidgets to visual studio 2019 first i install the wxwidgets for visual studio then i open "sln 15" then i buile it in debug,debug dll ,relese dll and relese then i i open project properties and change some properties to include include folder and liberary
and then i copied the "hello world" example on widgets site but when i pressed the debug button to run the code two error messages showed up the first is cant execute because cant find"wxmsw312u_core_vc_custom.dll"
the second cant find"wxbase312u_vc_custom.dll"
the code is :
`
// wxWidgets "Hello World" Program
// For compilers that support precompilation, includes "wx/wx.h".
#include <wx/wxprec.h>
#ifndef WX_PRECOMP
#include <wx/wx.h>
#endif
class MyApp : public wxApp
{
public:
virtual bool OnInit();
};
class MyFrame : public wxFrame
{
public:
MyFrame();
private:
void OnHello(wxCommandEvent& event);
void OnExit(wxCommandEvent& event);
void OnAbout(wxCommandEvent& event);
};
enum
{
ID_Hello = 1
};
wxIMPLEMENT_APP(MyApp);
bool MyApp::OnInit()
{
MyFrame *frame = new MyFrame();
frame->Show(true);
return true;
}
MyFrame::MyFrame()
: wxFrame(NULL, wxID_ANY, "Hello World")
{
wxMenu *menuFile = new wxMenu;
menuFile->Append(ID_Hello, "&Hello...\tCtrl-H",
"Help string shown in status bar for this menu item");
menuFile->AppendSeparator();
menuFile->Append(wxID_EXIT);
wxMenu *menuHelp = new wxMenu;
menuHelp->Append(wxID_ABOUT);
wxMenuBar *menuBar = new wxMenuBar;
menuBar->Append(menuFile, "&File");
menuBar->Append(menuHelp, "&Help");
SetMenuBar( menuBar );
CreateStatusBar();
SetStatusText("Welcome to wxWidgets!");
Bind(wxEVT_MENU, &MyFrame::OnHello, this, ID_Hello);
Bind(wxEVT_MENU, &MyFrame::OnAbout, this, wxID_ABOUT);
Bind(wxEVT_MENU, &MyFrame::OnExit, this, wxID_EXIT);
}
void MyFrame::OnExit(wxCommandEvent& event)
{
Close(true);
}
void MyFrame::OnAbout(wxCommandEvent& event)
{
wxMessageBox("This is a wxWidgets Hello World example",
"About Hello World", wxOK | wxICON_INFORMATION);
}
void MyFrame::OnHello(wxCommandEvent& event)
{
wxLogMessage("Hello world from wxWidgets!");
}`
When you build wxWidgets libraries as DLLs, you need these DLLs to run the applications using them, just as with any other DLL. The DLLs don't need to be in the same directory as the application (although it does work if you do it like this), you may also add the directory containing them to your PATH environment variable.
Alternatively, build wxWidgets as static libraries -- then you won't have any run-time dependencies on them.
What am trying to accomplish is having two Panels , one to draw on , and the other one will hold the tools , so I'm using the default Panel with size of the whole screen for drawing shapes on drawPanel , and a custom Panel on top of it for the tools , so I can add a background to it toolsPanel:
#ifndef WXIMAGEPANEL_H
#define WXIMAGEPANEL_H
#include <wx/wx.h>
#include <wx/custombgwin.h>
#include <wx/dcbuffer.h>
class wxImagePanel : public wxCustomBackgroundWindow<wxPanel>
{
public:
wxImagePanel();
wxImagePanel (wxWindow *parent,
wxWindowID winid = wxID_ANY,
const wxPoint& pos = wxDefaultPosition,
const wxSize& sizee = wxDefaultSize,
long style = wxTAB_TRAVERSAL | wxNO_BORDER,
const wxString& name = wxPanelNameStr);
void SetBackgroundImage(const wxBitmap & background);
virtual ~wxImagePanel();
protected:
private:
const wxBitmap * ptr_backgorund;
void paintEvent(wxPaintEvent & evt);
void OnEraseBackground(wxEraseEvent& event);
DECLARE_EVENT_TABLE()
};
#endif // WXIMAGEPANEL_H
----------------------------------------------------
#include "wxImagePanel.h"
wxImagePanel::wxImagePanel()
{
//ctor
//SetBackgroundStyle(wxBG_STYLE_PAINT);
}
wxImagePanel::wxImagePanel (wxWindow *parent,
wxWindowID winid ,
const wxPoint& pos ,
const wxSize& sizee ,
long style ,
const wxString& name)
{
Create(parent,winid,pos,sizee,style,name);
//SetBackgroundStyle(wxBG_STYLE_PAINT);
}
void wxImagePanel::SetBackgroundImage(const wxBitmap & background)
{
this->ptr_backgorund = &background;
SetBackgroundBitmap(background);
}
wxImagePanel::~wxImagePanel()
{
//dtor
if(ptr_backgorund)
delete ptr_backgorund;
}
BEGIN_EVENT_TABLE(wxImagePanel, wxPanel)
//EVT_PAINT(wxImagePanel::paintEvent)
EVT_ERASE_BACKGROUND(wxImagePanel::OnEraseBackground)
END_EVENT_TABLE()
void wxImagePanel::OnEraseBackground(wxEraseEvent& event)
{
}
void wxImagePanel::paintEvent(wxPaintEvent & evt)
{
wxAutoBufferedPaintDC dc(this);
PrepareDC(dc);
if(ptr_backgorund)
dc.DrawBitmap( *ptr_backgorund, 0, 0);
}
I have tried both ways (drawing the background myself, and using SetBackgroundBitmap method) , both ways are flickering when am calling drawPanel->Refresh() on MouseMove event , so what am missing here , that causing the toolsPanel to flicker?
The flicker is unavoidable if you call Refresh() on the entire window on each mouse move, this simply shouldn't be done. At the very least, you need to refresh just the small area which really needs to be repainted and not the entire window, which would reduce the flicker significantly but might still be not enough. The best solution is to use the (unfortunately still undocumented) wxOverlay class to overlay whatever you're drawing when the mouse moves on top of the window.
try refreshing like this:
window->Refresh(false)
Here's a similar thread containing a very useful piece of advice: on Refresh, "the option eraseBackground = FALSE is very important to avoid flickering"
how to animate picture without making it flicker using wxWidgets in erlang?
The documentation says Refresh repaints "window, and all of its children recursively (except under wxGTK1 where this is not implemented)". Although I don't understand the behaviour, I'm suspecting the recursive nature of Refresh causing the flicker, since I'm usually experiencing it under Windows 7 but not under Linux GTK (with the exact same code).
However, under Windows 10 I don't see any flicker even with eraseBackground = TRUE.
I have this WxWidgets test source code that compiles, and when run, it shows a simple frame:
/*
* hworld.cpp
* Hello world sample by Robert Roebling
*/
#include "wx-2.8/wx/wx.h"
class MyApp: public wxApp
{
virtual bool OnInit();
};
class MyFrame: public wxFrame
{
public:
MyFrame(const wxString& title, const wxPoint& pos, const wxSize& size);
void OnQuit(wxCommandEvent& event);
void OnAbout(wxCommandEvent& event);
DECLARE_EVENT_TABLE()
};
enum
{
ID_Quit = 1,
ID_About,
};
BEGIN_EVENT_TABLE(MyFrame, wxFrame)
EVT_MENU(ID_Quit, MyFrame::OnQuit)
EVT_MENU(ID_About, MyFrame::OnAbout)
END_EVENT_TABLE()
IMPLEMENT_APP(MyApp)
bool MyApp::OnInit()
{
MyFrame *frame = new MyFrame( _T("Hello World"), wxPoint(50,50), wxSize(450,340) );
frame->Show(TRUE);
SetTopWindow(frame);
return TRUE;
}
MyFrame::MyFrame(const wxString& title, const wxPoint& pos, const wxSize& size)
: wxFrame((wxFrame *)NULL, -1, title, pos, size)
{
wxMenu *menuFile = new wxMenu;
menuFile->Append( ID_About, _T("&About...") );
menuFile->AppendSeparator();
menuFile->Append( ID_Quit, _T("E&xit") );
wxMenuBar *menuBar = new wxMenuBar;
menuBar->Append( menuFile, _T("&File") );
SetMenuBar( menuBar );
CreateStatusBar();
SetStatusText( _T("Welcome to wxWindows!") );
}
void MyFrame::OnQuit(wxCommandEvent& WXUNUSED(event))
{
Close(TRUE);
}
void MyFrame::OnAbout(wxCommandEvent& WXUNUSED(event))
{
wxMessageBox(_T("This is a wxWindows Hello world sample"),
_T("About Hello World"), wxOK | wxICON_INFORMATION, this);
}
Created with this simple SCons script:
env = Environment()
env.ParseConfig('wx-config --cxxflags --libs')
env.Program(target='wxTest/wxTest.exe',source=['src/Wxwidgets.cpp'])
The problem: it wont focus when I run it. The only thing I can focus is the red, yellow and green buttons in the upper left corner.
I use Eclipse as my IDE and run scons as an external tool when I build it.
Is there someone out there that know what Im doing wrong? How can I get the frame to focus?
Hope there is someone out the who can help me.
I assume you start the raw executable that is created? This does not work on Mac OS X, see My app can't be brought to the front!
You will have to create an application bundle for your app to work properly on Mac OS X. I don't know anything about SCons, but maybe the wiki does help?