Implementing a "window" system and "no deletion of self" rule - c++

I've been trying to program in C++ a sort of simple "window" system for use in a game, which draws windows that can have buttons, etc. in them in the game area (internal to the game's own graphics, i.e. not the OS's GUI windows). The window objects (call it "class Window" for here) have some methods for events like key press, and the ability to hook on a handler to be called upon receipt of that event.
Windows are (or will be) collected in a "window manager", and the window object will have "close()" member that would call the parent window manager's window-deletion routine to delete itself. An event handler hooked to, say, a button on the window might invoke this routine to close the window (think an "OK" box).
The trouble is this sounds like a "delete *this;" statement, which I've heard is a no-no. True, it doesn't do that directly, but the effect is the same: an object has a member function that brings about its own destruction (e.g. the "close()" function, or the event function that triggers the handler leading to the "close()" function being called.). If this is bad, then what is a better way to design this?

There is nothing wrong with an object deleting itself. You must simply tell the window manager to remove the window from it's collection and then delete. If you have the window manager delete the window object, that's even better.
If you really want to avoid this behavior, you can add a bool dead; to each window that initializes to false. When the window is to be closed, set this->dead = true;. Every frame, have the window manager iterate through it's windows and delete the ones that are dead.
Note that this solution still does not fix errors that arise from external systems that have a reference to the deleted window, but it does have the advantage of centralizing the deletion of windows.
I have designed many games' window systems, and in my experience, allowing windows to delete themselves is a very elegant solution, even if it is more error-prone.
A minimal example:
class Window
{
public:
void keyPressCallback(int c)
{
if (c == KEY_ESC)
{
manager.destroy(this);
return;
}
}
WindowManager& manager;
};
class WindowManager
{
public:
void destroy(Window* target)
{
delete target;
windows.erase(std::find(windows.begin(), windows.end(), target));
}
std::vector<Window*> windows;
};
As long as there are no remaining pointers to that window, this method is perfectly safe and semantically sane. When the window receives a signal to close, it closes itself.
The same example with the dead flag:
class Window
{
public:
Window() : dead(false) {}
void keyPressCallback(int c)
{
if (c == KEY_ESC)
{
dead = true;
return;
}
}
bool dead;
};
class WindowManager
{
public:
void cleanup()
{
for (auto iter = windows.begin(); iter != windows.end(); ++iter)
{
if (iter->dead) windows.erase(iter);
}
}
std::vector<Window*> windows;
};

Related

Why a Widget class uses pointers as data members?

I'm working through "Programming Principles and Practice", and I don't understand why this Widget class uses pointers as data members.
The book's explanations is this:
Note that our Widget keeps track of its FLTK widget and the Window with which it is associated. Note that we need pointers for that because a Widget can be associated with different Windows during its life. A reference or a named object wouldn’t suffice. (Why not?)
So, I still don't understand why the Widget can't have a named object Window win as a data member, which can take a different value when it's associated with a different Window. Could someone explain this a bit?
class Widget {
// Widget is a handle to a Fl_widget — it is *not* a Fl_widget
// we try to keep our interface classes at arm’s length from FLTK
public:
Widget(Point xy, int w, int h, const string& s, Callback cb)
:loc(xy), width(w), height(h), label(s), do_it(cb) { }
virtual ~Widget() { } // destructor
virtual void move(int dx,int dy)
{ hide(); pw–>position(loc.x+=dx, loc.y+=dy); show(); }
virtual void hide() { pw–>hide(); }
virtual void show() { pw–>show(); }
virtual void attach(Window&) = 0; // each Widget defines at least one action for a window
Point loc;
int width;
int height;
string label;
Callback do_it;
protected:
Window* own; // every Widget belongs to a Window
Fl_Widget* pw; // a Widget “knows” its Fl_Widget
};
Window own;
This will copy the whole Window object. If the real window changes, this widget will have an old and useless copy.
Window & own;
A reference. We meet two issues:
A) We can not know if the window has been deleted outside the widget code
B) The window must exists before this widget
Window * own;
A pointer can be NULL, as opposed to a reference. This avoids reference issues.
The book seems a bit old, just because it uses raw-pointers.
EDIT due to comments
It is absolutely true that issue "A)" is the same for references and pointers. But it can be easier handled with a pointer.
What I wanted to point to is that when a window is deleted, the widget must be informed about it, so as to not use the "own" object.
With a pointer, it can be resetted to NULL, so any further attemp to use "own" can be easily catched. But with a reference you need, at least, an extra bool in your code just to store if "own" is valid or not.
First, we need to work out the logical and implementation details. On the logical side, a window contains widgets: just like a mother has children. This is a one to many relationship. Each widget has an implementation entity, in this case an Fl_widget. It could equally be a MS windows Window, a QtWidget or and X-Windows Widget. It is one of those implementation dependent things
___________
|window |
| _______ | _________
| |widget-|-|--->|Fl_widget|
| _______ | _________
| |widget-|-|--->|Fl_widget|
|___________|
Within window itself, there will also be an implementation detail like another Fl_Widget or Fl_window.
The reason why we cannot have Window win instead of Window win* is because the window owns the widget and not the other way round. If we had Window win then whenever any window property changed, you'd have to modify all the widgets containing the same window. Taking, the mother child relationship, if the mother had a haircut, the mother member for all the children of the same mother would have to have a haircut. You'd have to have a method to keep track of and update all the mothers of all the children. This would just be a maintenance nightmare.
If we just hold a pointer to the window then we know that if the window is modified, all sibling widgets will be able to query the change in the parent window and get the same answer without a lot of effort.
The second part of your question about moving widgets between windows - I've never seen anyone do that. In all the implementations I have ever used, this is impossible. The parent window owns the widget for life. To "move it", you'd normally have to reincarnate it i.e. destroy it from the current window and re-create it in the new window.

Drawing a Graph in C++ MFC App

I am writing a C++ MFC application to control a machine in a manufacturing setting. This app also needs to analyze a lot of information in a very short cycle time.
For testing purposes and long term maintenance, I need to be able to graph data coming from a sensor on the console. I may have totally overlooked an option (feel free to propose other options) but my research has taken me to using a picture control.
I am successfully drawing in this control by use of OnPaint(). My issue is that I need to redraw a new image every few seconds and I cannot call OnPaint() repetitively or pass data to it.
How can I create a new function that can be used to draw on the picture control repetitively? Also, this is my first foray into an MFC app so please explain on an appropriate level. Thanks!
class CPicture : public CStatic
{
DECLARE_MESSAGE_MAP()
public:
afx_msg void OnPaint();
};
BEGIN_MESSAGE_MAP(CPicture, CStatic)
ON_WM_PAINT()
END_MESSAGE_MAP()
void CPicture::OnPaint()
{
CPaintDC dc(this); // device context for painting
dc.SelectStockObject(BLACK_BRUSH);
dc.Rectangle(5, 50, 1000, 51);
}
I guess the question is how and where to access this
//Picture
class CPicture : public CStatic
{
DECLARE_MESSAGE_MAP()
public:
afx_msg void OnPaint();
vector<Coordinates> GraphData;
};
void CPicture::OnPaint()
{
// device context for painting
CPaintDC dc(this);
// save current brush
CBrush *pOldBrush = (CBrush*)dc.SelectStockObject(BLACK_BRUSH);
int NumPoints = GraphData.size() - 1;
for (int N = 0; N <= NumPoints; N++) {
dc.Rectangle(GraphData[N].x, GraphData[N].y, GraphData[N].x, GraphData[N].y);
}
// select original brush into device contect
dc.SelectObject(pOldBrush);
}
You can call Invalidate() on your control when new data arrives, or use RedrawWindow() to force an immediate redraw:
CPicture myPicture;
myPicture.Invalidate();
or
myPicture.RedrawWindow();
I cannot call OnPaint() repetitively or pass data to it.
To pass data, a structure containg the data can be declared inside your CPicture class (or some place else in your program), and that data can then be accessed from within OnPaint():
struct myData {
int value1;
int value2; // or an array, or some other data structure
}
class CPicture : public CStatic
{
DECLARE_MESSAGE_MAP()
public:
myData m_data;
afx_msg void OnPaint();
};
In OnPaint() (you should also select the original brush back into the device context to avoid resource leaks):
void CPicture::OnPaint()
{
CPaintDC dc(this); // device context for painting
// save current brush
CBrush *pOldBrush = (CBrush*)dc.SelectStockObject(BLACK_BRUSH);
// check pOldBrush - could be NULL
// dc.Rectangle(5, 50, 1000, 51);
// access m_data here, for example
dc.Rectangle(m_data.value1, m_data.value2, 1000, 51);
// select original brush into device contect
dc.SelectObject(pOldBrush);
}
Update (working with threads):
Assuming the following (from the comments):
for the main thread you have a dialog CLongbowDlg.
for the graph, you have a PicControl derived from CStatic, and that control is placed on the dialog.
from the main thread, a worker thread is started to read the data.
PicControl and CLongbowDlg are defined in the same header, but are
independent of each other. I need to be able to call Invalidate() or
RedrawWindow() from inside CLongbowDlg's functions because they
represent the primary thread.
I'll try to give a short description of one of the possibilities here, because this should actually be a seperate question.
Firstly, an object of PicControl has to be a member of CLongbowDlg, which I assume is the case (let's call it m_PicControl) - So, in class CLongbowDlg:
PicControl m_PicControl;
For the data (I'll be using the above myData as example data): in your main thread (the Dialog), create a variable of type myData: m_data (for larger data you could allocate space on the heap, or use CArray or some other container):
myData m_data;
In PicControl create a member variable of type myData* and set it to NULL in the PicControl constructor.
myData *m_pData;
In OnInitDialog() (main dialog), provide m_picControl with a pointer to the data (or better create a function to do that in PicControl):
m_picControl.m_pData = &m_data;
When starting the worker thread, also provide it a pointer to m_data and/or a pointer to the dialog itself (this).
Make sure to protect the data with a critical section.
When data comes in, the worker thread can write to it via the provided pointer.
In PicControl::OnPaint(), the same data can be accessed through m_pData.
To initiate a redraw, there are several ways:
use a timer inside PicControl or in the main dialog, and call Invalidate() every time the timer fires.
to control the redrawing from the worker thread (when a certain amount of new data has arrived for example) a message can be posted, using PostMessage(), to the main dialog (using the pointer that was provided when starting the thread - the this pointer).
To receive the message you'll have to create a message handler in the main dialog, and from there call Invalidate() on m_picControl (you could also post a message directly to PicControl, but I prefer to do it via the main window).

gtkmm and Gtk::Builder: Lifetime of objects after calling get_widget

I think I must be "doing something wrong" here. I have a program using gtkmm. The main window for the program is a subclass of Gtk::Window and I have the bare bones of the application drawn out in Glade.
Here's an edited version of the main window's constructor:
template<class T>
static T*
get_widget (Glib::RefPtr<Gtk::Builder> builder, const Glib::ustring& name)
{
T* widget;
builder->get_widget (name, widget);
if (! widget) no_such_widget (name);
return widget;
}
app_window::app_window ()
{
Glib::RefPtr<Gtk::Builder> builder;
try {
builder = Gtk::Builder::create_from_file (installed_ui_name);
}
catch (const Glib::FileError& err) {
g_error ("Couldn't open UI definition file at %s",
installed_ui_name);
throw;
}
// main_box is a std::unique_ptr<Gtk::Widget>, a field of app_window.
//
// This works fine: the Gtk::Box gets added as the main child of this
// app_window and survives until the app_window is destroyed.
main_box.reset (get_widget <Gtk::Box> (builder, "main-box"));
add (* main_box);
auto accel_group = get_accel_group ();
// This doesn't work so well
//
// menu_quit is a Gtk::MenuItem*. The object seems to be actually
// constructed for the call to builder->get_widget, because its existence
// stops the menu item from being finalized at the end of the application.
auto menu_quit (get_widget<Gtk::MenuItem> (builder, "menu-quit"));
menu_quit->add_accelerator ("activate", accel_group,
GDK_KEY_q, Gdk::CONTROL_MASK, Gtk::ACCEL_VISIBLE);
using std::bind;
menu_quit->signal_activate ().connect (bind (& app_window::on_close, this));
show ();
}
When setting up the window, I want to register various signal handlers for menu items etc. (the menu_quit widget in the example is just one of them). To do so, I think I need to use builder->get_widget() to get hold of an object to talk about.
The problem is that I've now got an instance of (a subclass of) Gtk::Widget and I don't know what to do with it. If I call delete on the pointer, the widget doesn't appear in the application, but no other problems happen. That's a bit confusing: I would expect either no effect or a segmentation fault (depending on whether something else thought it owned the object or not).
If, on the other hand, I leak the pointer, assuming that object will be owned by the container into which main_box has been added, I get a memory leak. In particular, menu_quit's underlying gtk_image_menu_item doesn't get finalised because the reference count is one too high. (I can check easily enough that with GDB)
A "solution" is to store a pointer to each object that I get with builder->get_widget as a field in the app_window and then delete it in the destructor (automated with std::auto_ptr or std::unique_ptr). But that's really horrible: I don't want to have to write out a field for every single menu item! Avoiding that sort of nonsense was the whole point of using GtkBuilder in the first place!
Assuming that this isn't a bug (gtkmm 3.12.0, if that's relevant), I assume I'm just doing it wrong. How is an application supposed to do this?

form properties not called during resize

I have a .NET form with a boolean property called _isResized, which is set to true when the SizeChanged event is called and is set to false when the bool isResized() function is called.
ref class net_window : public System::Windows::Forms::Form
{
private:
bool _isResized;
public:
net_window(void)
: _isResized(false){
InitializeComponent();
}
void InitializeComponent(void){
this->SizeChanged += gcnew EventHandler(this, &net_window::eventResized);
}
bool isResized(void){
bool temp = _isResized;
_isResized = false;
return temp;
}
Void eventResized(Object^ sender, EventArgs^ e){
_isResized = true;
}
};
I also have an native C++ class called window which acts as a layer around the .NET form. This class is updated every frame of the main loop and uses the bool isResized() function of the form to see if the size has changed.
class Window
{
private:
void* _net_window_handle;
Window(){
_net_window_handle = new gcroot<net_window^>;
(*(gcroot<net_window^>*)_net_window_handle) = gcnew net_window;
}
~Window(){
delete _net_window_handle;
}
void update(void)//Called every frame.
{
if( (*(gcroot<net_window^>*)_element)->isResized() )
//Do stuff.
}
};
The delegate added to SizeChanged is called whenever the form is being resized, so _isResized is set to true as soon as the form size changes, but for some reason the thread of the main loop freezes whenever the window class uses the bool isResized() function, until the user has released the edge of the form and thus the resizing has finished.
Is it not possible to access .NET form values as long as it is being resized. Is there an alternative?
Thanks
EDIT
I use a main loop which calls System::Windows::Forms::Application::DoEvents() every frame. When the thread of the loop enters this function and the main window is resizing, it freezes. Is there a way to avoid this problem.
DoEvents strikes again. Windows pumps a modal message loop when the user starts dragging a window edge. Which means that your DoEvents loop isn't running anymore. Use a timer instead, SetTimer with a 15 or 31 msec interval is about right. Having your code respond to the Resize event directly of course highly preferred.
Thanks Hans Passant

C++ - WINAPI - Object-oriented approach to closing a window

While trying to create a nice wrapper around Win32 specific GUI components, I eventually ran into a problem. The problem is that I'm unable to close the application after the windows I created no longer exist.
My API works like this:
/// ----------------------------
/// #author God
/// #project Helixirr Widgets
/// ----------------------------
#include <helixirrwidgets/HelixirrWidgets.hpp>
int main(void){
HelixirrWidgets::Window __windows[2] = {HelixirrWidgets::Window("Big Window"), HelixirrWidgets::Window()};
__windows[0].position(200, 200);
__windows[0].size(800, 600);
__windows[0].visible(true);
__windows[0].save_changes();
__windows[1].name("Tiny Window");
__windows[1].position(10, 100);
__windows[1].size(400, 200);
__windows[1].visible(true);
__windows[1].save_changes();
while(__windows[0].active() || __windows[1].active()){
if(__windows[0].visible()){
__windows[0].show();
}
if(__windows[1].visible()){
__windows[1].show();
}
}
return 0;
}
In method of HelixirrWidgets::Window called "active", which is declared like this
inline bool active(void) const noexcept;
I can check, whether my window is active or not.
This method basically return a const reference to a boolean member variable of an instance. This member variable is modified in "show"-method of the same class. Here's the definition:
void Window::show(void){
if(GetMessage(&_m_opHelper->message, _m_opHelper->handle_window, 0, 0)){
if(_m_opHelper->message.message == WM_CLOSE){
_m_bActive = false;
return;
}
TranslateMessage(&_m_opHelper->message);
DispatchMessage(&_m_opHelper->message);
ShowWindow(_m_opHelper->handle_window, SW_SHOWDEFAULT);
UpdateWindow(_m_opHelper->handle_window);
_m_bActive = true;
return;
}
_m_bActive = false;
}
Do note I use pimpl-idiom to hide platform-specific structures ("_m_opHelper" is pointer to implementation).
It may look like it works, but it doesn't and I can't understand why. It all comes down to a simple question: how can I close my window implemented using WINAPI specific functions and structures to be closed appropriately by a user of my application?
I guess the cause of the issue is related to the fact WM_CLOSE simply is not last message HWND gets. Messages like WM_DESTROY, WM_NCDESTROY and possibly more (depending on the particlar window and its state) will come after WM_CLOSE, leading to the assignment _m_bActive = TRUE.
I.e. the window becomes inactive for very short time, and (likely) they will never be inactive at the same time, causing an endless loop in main().