When should I destroy a window ?
Usually, the destruction of a window is due to a GEM event message, for example the user clicks on the closer widget, then the screen manager of the AES reacts by sending a message to the application a WM_CLOSED message. Of course WindCreate() attributes to the WinDom a standard (i.e. a predefined) function handling this message. So you don't need to close and destroy explicitly a window (with the functions WindClose() and WindDelete()), because the standard functions perform this task for you.
The only case when you should destroy explicitly a window is when your window has no closer function and no destroy function or when your application exits.
The standard closer function:
This function (all standard functions of WinDom are located in the file SRC/STDCODE.C of the WinDom package, the standard closer function is std_cls()) just sends an another message to the application window, a WM_DESTROY message. This predefined WinDom message, means that the window should be deleted.
When should I write a new closer function ?
As soon as you want a window to keep its attributes until it is opened again. Such a window has to just disapear from the screen stay in memory when it is closed. Many GEM programs provide this feature: a window is closed but its data is kept. Closed windows are accessible from the application menu or by an icon on the application desktop. Then the new closer function is something like that:
void new_std_cls( WINDOW *win) { /* Keep information somewhere ... */ insert_in_menu( win->data); /* ... and close the window */ WindClose( win); }Redefining this closer function, the window will never be deleted. That's why you'll need to destroy it explicitly before the end of the application. This results a code similar to the following:
int main( void) { WINDOW *win; ApplInit(); /* Create windows ... */ win = WindCreate(...); /* Attribute the new function */ EvntAttach( win, WM_CLOSED, new_std_cls); ... /* Delete all windows */ while( wglb.first) { #if GOODWAY ApplWrite( wglb.first, WM_DESTROY); EvntWindom( MU_MESAG); #else /* Very bad way */ WindDelete( wglb.first); #endif } /* then quit ... */ ApplExit(); return(0); }As you can see, we delete all windows using the WinDom global variable wglb.first. The best way is to send a destroy message then execute all GEM event with EvntWindom() rather than deleting the window with WindDelete(). Indeed, some AES present the following problem: if you create/delete too many windows in same time, the system may crash.
Remarks: In a old version of WinDom, the documentation shows this example using the message WM_CLOSED instead the message WM_DESTROY. This method had two inconvenient:
Close Window ^UWhen you type the key shortcut, the window is closed but as the control key is pressed, WinDom interprets it as an iconification request.
This function is called by EvntWindom() when it gets an WM_DESTROY message. This function destroys explicitly the window by calling both WindClose() and WindDelete(). Of course, in the previous example, the destroy window should be rewritten by something like that:
void new_std_dty( WINDOW *win) { /* Get my data */ void *mydata = DataSearch( win, 'DATA'); /* Save data if needed */ if( needed) save_my_data( win->data); /* free memory ... */ free_my_data( mydata); DataDelete( win, 'DATA'); /* ... and delete the window */ WindDelete( win); }This example is very special because we have changed the standard closer function. Usually, we don't change this function, and the destroy function should be:
void new_std_dty( WINDOW *win) { /* Get my data */ void *mydata = DataSearch( win, 'DATA'); /* Save data if needed */ if( needed) save_my_data( win->data); /* free memory ... */ free_my_data( mydata); DataDelete( win, 'DATA'); /* ... close the window ... */ WindClose( win); /* ... and delete the window */ WindDelete( win); }If needed, it is a good idea to save data inside the destroy function before freeing it.
Tip: WindDelete() closes the window with WindClose() if it is not already closed. Thus, calling WindClose() before WindDelete() is optional.