_GUIBASE


Quick Data

Header file:gui_base.h
Object name:_GUIBASE
Object index:1 of 1 Object

General Description

The _GUIBASE class contains functions and members that are relevant to most GUI objects, including functions to create, move, resize, and change the properties of a window. If you did not use this class, you would need to copy and paste these functions, which is a little bit of a pain if you learn after creating 25 components that one function doesn't work! Instead, all the common properties are here, but they can be overwritten by a class that inherits these properties if required.

You may wish to use this class to make your own GUI components. There are a few examples at the end on how to make use of this class in your own GUI components. The properties and methods tables are broken up into two categories - those which you'd normally use, and those that are relevant to programmers who are inheriting this class. I would suggest that you use this class as best as you can. It will save you a lot of time and effort in your own GUI classes.


Secondary Options


Name Description Value

There are not many properties available to all components, and those that are available are pretty basic ones. But I will list them here, because you need to know them... PLEASE NOTE - all of these options here are secondary options.
AvWind This style includes both of the following styles and stands for AVerage WINDow style. This style makes the window visible when it is created, and makes the window a child window of the parent window that you specify (which is very useful indeed). If you want to know the in-depth information about the individual styles, read on. WS_VISIBLE | WS_CHILD
WS_VISIBLE This style, when used as a secondary style, makes you window visible when you create it. This style is usually applied, unless you don't want to see the window when you create it. If you use the AvWind style, this style is already included. Hmm...? What could it be? Oh! WS_VISIBLE!
WS_CHILD This style makes the window that you create with this style a child window of the parent that you passed. Exactly why you'd not want to do this is beyond me, but hey, Microsoft seems to think that you might not want to, so they (in their infinite wisdom) made the new industry standard of having to supply this flag. This flag is already included if you combined AvWind anyway. WS_CHILD

Properties - Ordinary properties


Name Description

int Tag; This number is just a number that you can set to identify the component. You can set it to anything that you want - the class will not fiddle with it. I think you'll find this pretty useful when dealing with things like events that have a Sender parameter - for any GUI component, you can return it's Tag by using ((_GUIBASE)Sender)->Tag (With Sender being a parameter passed along with an event - please see the events section for more information on this).
int TabOrder; This member specifies the TAB order of the current window. You can set this number to whatever you want, but I would recomend that you don't set two components to the same thing. If you do, only one window will be focused properly. Only available with the GUI controller.
bool UseTab; This property specifies whether or not this component should use the TAB button when changing focus between controls. Setting this to FALSE makes the TAB controller ignore this control in the TAB order (that means that even if this is next in the TAB order, the TAB controller will forget that this control exists, and simply skip onto the next object in the TAB order). Only available with the GUI controller.
bool RepaintOnResize; This variable specifies whether to repaint a window when you move or resize it using the functions for moving and resizing the window. By default, this should be TRUE. You should keep it at TRUE or otherwise you'll get some funny redrawing errors - but there may be situations where you want to change this. You can change this variable directly or use the SetRepaintFlag() function.
bool DontDestroy; This variable sets whether the class should destroy the window when the object is destroyed or when you call the Destroy() function. By default, this is FALSE. However, if you have taken over control of a button from another place, for example in a system dialog box, then destroying the button when the class is destroyed may not be favourable. So set this to TRUE to stop the class from destroying the window.

Properties - To use if you inherit


Name Description

HWND Handle; This is the object's handle, as given by windows. You can read or write this handle, but it's probably best if you only read it - otherwise this class will forget how to deal with that component. However, if you want to create your window another way and assign this variable that way, then you can.
HWND Parent; This property holds the parent window's handle. This is set when you create a window, and then abandoned. If you call the function to find the window's parent, this variable is not used.
bstring Caption; This variable stores the caption... well, sort of. It is more of a temporary string storage area, and feel free to use it and pass back a pointer to the string data from a function. Hopefully the programmer will copy out the data as soon as a function returns that passes back a pointer to a string.
bstring WindowClass; This is the classname of the window to be created. If you inherit this class into your own, you'll need to set this member in the constructor to the class that you want. Please see the example inheritance at the end to see how to use this properly.
int ItemID; This is the ID of the window that was created. This is set when the window is created, and is either a value that the programmer specified or an automatic number (if you use the AutoID thingy). You can read or write to this number, but it's really only a good idea to read from it. If you write to it after a window has been created, none of the event handlers will work anymore, unless it is restored to it's original value. As a matter of fact, I'd recomend that you only ever read from it.
int ComponentID; This property will only exist with the GUI controller active. It is a number that specifies what type of control it is to the GUI controller. If you write your own class, you might like to add a new ID to the GUI controller's list. Please see the section on inheriting the class below on how to do this.
int PrimaryOptions; This variable stores the Primary Options for this window. They are stored here during the creation of the window, and after that, are left to do nothing much. Occasionally they are used, so don't fiddle with them too much! If you want to change this after you have created the window, please use the Morph() function (which will apply your changes).
int SecondaryOptions; This variable stores the Secondary Options for this window. They are stored here during the creation of the window, and after that, are left to do nothing much. Occasionally they are used, so don't fiddle with them too much! If you want to change this after you have created the window, please use the Morph() function (which will apply your changes).
RECT WinRect;
int pWidth;
int pHeight;
int pLeft;
int pTop;
int pRight;
int pBottom;
These variables are all used for gathering the size and position of the window and setting the size and position of the window. They are automatically overwritten with the correct information each time a move or resize function is called, so you can not just modify these. There are functions that you can use to modify the position and the location of the window. However, if you are writing a function, you are most welcome to use these values.
LRESULT MessageQueueReturn; This variable stores the return value to the message queue for when the PassMessageQueue event (documented below) is called. You would put any return value in this variable and return TRUE from the event to return a value to the message queue.

Methods - Ordinary methods


Prototype Description

virtual void CreateWin(fFORM* Parent, char* Caption, int PrimaryOptions, int SecondaryOptions);
virtual void CreateWin(fFORM* Parent, char* Caption, int ID, int PrimaryOptions, int SecondaryOptions);
virtual void CreateWin(HWND Parent, char* Caption, int PrimaryOptions, int SecondaryOptions);
virtual void CreateWin(HWND Parent, char* Caption, int ID, int PrimaryOptions, int SecondaryOptions);
All of these functions acheive the same thing, but all with different parameters. All of these functions create a window with all the parameteres that you specify.
First we start with the Parent parameter. If you have included the fFORM object, then you can pass along a pointer to a fFORM object to specifiy that as the parent. Otherwise, you can just pass a handle to a window as the parent. Next, we have the caption. This is the window's caption. After that is the component's ID number. Please note that the ID is not mentioned in some of the prototypes listed here. If you #define F_AUTOID before the inclusion of the GUI components, ID numbers will automatically be assigned, and thus you will not need to specify them. Next comes the PrimaryOptions. These are the primary options for the window that you are creating, and what they are will depend on what component uses this interface. Finally we have SecondaryOptions, which is the secondary options for this component. These will depend on what type of window you created. All of these functions can be replaced by you class if you inherit this class.
virtual void Destroy(); This function destroys the window. Simple, and final.
void AddGUIController(void);
void RemoveGUIController(void);
This function adds or removes this component from the GUI controller. This might be useful if you manually create a window, in which case the component will not add itself to the GUI controller. However, once you have added a control, it will remove itself automatically when the window is destroyed (whether you call Destroy() or the component intercepts the WM_DESTROY message via it's message queue), or otherwise you can force it to remove itself.
HWND GetHandle(void); This function returns the handle of the window. It is advised that you use this function to retrieve the handle.
void GetID(void); This function retrieves the ID of the component. Please note that this is not the ID that is stored in the variable ItemID - the proper ID is retrieved from the window first, and then returned.
void SetFoc(void); This function makes this component have the keyboard focus.
void Morph(int PrimaryOptions, int SecondaryOptions); This function changes the primary and secondary options for this window. Please note that not all of the changes may come into effect automatically due to some funny thing about Windows.
void SetID(int ID); This function sets the ID of the control. You can change this after the control is created. If you like, you can change this if you otherwise specified that you wanted to use the AutoID thingy.
HWND GetParentWindow(void);
void SetParentWindow(HWND Parent);
These functions either set or get the parent window of this control. You can call these functions after the control has been created.
void Assimiliate(HWND Handle, int ID); This function makes this component take over control of an already created control. All you need to do is specify the handle and the ID of the control. If you are using the AutoID thingy, then you don't need to provide the ID of the control to take over. The ID and the Handle will be saved and used. You can change the ID of the control afterwards if you so wish. This function could be useful for taking over controls that are on dialog boxes, or system controls, or other such things. After you have taken over control, you will then be able to use the functions provided by this component to deal with the control that you took over. If you do not want the class to destroy this window when it is destroyed, then set the don't destroy flag - as documented by the next function.
void SetDontDestroyFlag(bool Set);
bool GetDontDestroyFlag(void);
These functions set or get the flag which specifies whether or not to destroy the component when the object is destroyed. This may be useful for situations when you have taken over control of a control that is part of a system dialog, in which case destroying the object may be rather detrimental. Pass TRUE to make the flag say, "DO NOT DESTROY THE OBJECT", or pass FALSE to make the flag say, "DESTROY THE OBJECT."
void Left(int Left);
int Left(void);
void Top(int Top);
int Top(void);
int Right(void);
int Bottom(void);
These functions either set or get a co-ordinate relating to the position of the component. Those functions returning void and taking an int set the respective property, and those returning an int are used to get a respective property. Please note that you can only retrieve the Right and Bottom co-ordinates, not set them. The co-ordinates returned will be relative to the parent window's client area. By this, it means that the numbers will start at (0,0) from the bottom left hand edge of the title bar and the inside of the border. If your window has a menu, then (0,0) is shifted down to be below this menu.
void Width(int Width);
int Width(void);
void Height(int Height);
int Height(void);
These functions set the width and height of the component. Those functions returning void and taking an int set the respective property, and those functions returning an int and not taking any parameters return the respective property.
void SetPos(int Left, int Top);
void SetSize(int Width, int Height);
void SetAll(int Left, int Top, int Width, int Height);
These functions set the location or the size of the component, but set several of these values at once. I'm fairly sure that all of the parameters are self-explanatory. I would recommend using SetAll(), as it seems to be the most reliable of the size and setting functions.
void SetRepaintFlag(bool Set); This function sets the flag that tells the class whether or not to repaint the window when it is sized or moved by the internal functions. You can set this to TRUE to make the window be repainted when moved or resized, or FALSE to prevent this. By default, it is TRUE, and unless you have a good reason not to, I'd keep it at TRUE. Putting it at FALSE can make the component look a little wierd.
void SetCaption(char* Caption);
char* GetCaption(void);
These functions get or set the window's caption. This can be a rather useful thing - and it is the way to get the text contained in an edit control.
void SetFont(HFONT Font);
void SetFont(fFONT* Font);
These functions set the font of the component. There are two ways that you can specify the font; either by a HFONT handle or by a fFONT object. Whichever way you do it is up to you and how you are writing your program.
void Enabled(bool Set);
bool Enabled(void);
These functions set whether the window is enabled or not. If the window is not enabled, then the window does not receive any keyboard input or mouse clicks, and depending on what component this is, it may grey out the component. Passing TRUE will make the component enabled, and passing FALSE will make the component un-enabled (if that makes sense).
void Visible(bool Set);
bool Visible(void);
These functions either get or set whether the window is visible or not. It the window is not visible, you can not see it (obviously). Pass TRUE to be able to see the window, or FALSE to hide the window.
LRESULT SendMsg(UINT Message, WPARAM wParam, LPARAM lParam); This function sends a message to the window that this class looks after. The only thing that this function has over manually using the SendMessage() function is that you don't need to specify the Handle of the window. Anyway, this function is here if you should wish to use it, and it will not return until the message has been processed. The result of the processing will be returned.
void PostMsg(UINT Message, WPARAM wParam, LPARAM lParam); This function "Posts" a message to the window. This function is just like the PostMessage() function except for the fact that you do not need to pass a handle to the window. This function will send the message and return immediately, not waiting for a return value.

Methods - To use if you inherit


Prototype Description

void Internal_CreateWindow(void); This function creates the window, internally, with all the data that you have placed into the variables that were mentioned above in the properties table. The variables that you might like to set before calling this function are as follows: PrimaryOptions, WindowClass, Caption, SecondaryOptions, pLeft, pTop, pWidth, pHeight, Parent, and ItemID. This function also adds the control to the GUI controller, ready for it to send out events. You might like to set ComponentID first, but please see the final section on inheriting this class to see how to use that. You should not overwrite this function, but call it when you are ready to create your window.
void Internal_DestroyWindow(void); This function destroys the window. The control will also be removed from the GUI controller if it was part of the GUI controller.
void Internal_GUIInit(void); This function goes through and resets all of the event pointers to NULL. Call this function from your constructor, but please note that you can only call this if the GUI controller is active. Please do not replace this function.
void Internal_SetPos(void); This function takes the variables pLeft, pTop, pWidth, and pHeight and sets where the window is and how wide the window is. Set the aformentioned variables before you call this function, please. Also, do not overwrite this function.
void Internal_CalcPos(void); This function checks where the window is, and sets the variables pLeft, pTop, pWidth, pHeight, pRight, and pBottom to where the window is. You might like to call this to find the current window's location before you set where the window is, otherwise you might not have all of the correct information. Please do not replace this function.
~_GUIBASE() De-Constructor. By default, this just destroys the window when the object is destroyed. You are most welcome to replace this if you so wish, but please make sure that you call the Internal_DestroyWindow() function from inside your deconstructor. You may like to replace this for things where you need to unload extra loaded DLL's for the window (for example, the RichEdit control).
virtual void Internal_InitBefore(void);
virtual void Internal_InitAfter(void);
These functions can be replaced if need be. The first function is called before the window is created, and the second is called after the window is created. You may like to do some initialisation in these functions.

Events

Please see the chapter on event handling for information on how to use these correctly.

Important Note: along with each event, there is a parameter void* Sender. This is a pointer to the object that sent the event. You can access all the _GUIBASE properties for this object by acessing it with this code: ((_GUIBASE)Sender)->FunctionName(); What you might like to do is retrieve the Tag property. If you know what the component is, you can cast the pointer to that type of component. For example, if you know that the component that sent the event was a button, then you can use the button's properties by casting with the following code: ((fBUTTON*)Sender)->FunctionName();

If you really want, you can return the type of component that was sent. The ((_GUIBASE)Sender)->ComponentID property will be one of the following values, representing certain components.

Additional values may be available if more GUI components are added to your distribution. They will most likely be listed here when they are available. However, if you want to check the list or add more values to the list (in case you write your own component), it can be found at the top of gui_controller_start.h.


Prototype Description Sent under

void (*OnLMouseDown)(void* Sender, int Keys, int X, int Y);
void (*OnLMouseUp)(void* Sender, int Keys, int X, int Y);
void (*OnLDBLClick)(void* Sender, int Keys, int X, int Y);
void (*OnRMouseDown)(void* Sender, int Keys, int X, int Y);
void (*OnRMouseUp)(void* Sender, int Keys, int X, int Y);
void (*OnRDBLClick)(void* Sender, int Keys, int X, int Y);
void (*OnMMouseDown)(void* Sender, int Keys, int X, int Y);
void (*OnMMouseUp)(void* Sender, int Keys, int X, int Y);
void (*OnMDBLClick)(void* Sender, int Keys, int X, int Y);
These events occur when somebody either pushes a mouse button down, or releases a mouse button, or double clicks a mouse button. Keys can be one (or a combination) of the following: (taken from the Win32 SDK Reference Manual)
  • MK_CONTROL - Set if the CTRL key is down.
  • MK_LBUTTON - Set if the left mouse button is down.
  • MK_MBUTTON - Set if the middle mouse button is down.
  • MK_RBUTTON - Set if the right mouse button is down.
  • MK_SHIFT - Set if the SHIFT key is down.
X and Y are the location at which the event occured.
WM_LBUTTONDOWN,
WM_LBUTTONUP,
WM_LBUTTONDBLCLK,
WM_RBUTTONDOWN,
WM_RBUTTONUP,
WM_RBUTTONDBLCLK,
WM_MBUTTONDOWN,
WM_MBUTTONUP,
WM_MBUTTONDBLCLK
void (*OnMouseMove)(void* Sender, int Keys, int X, int Y); This event occurs repeatedly when the user moves the mouse around in this window. Keys are one (or a combination) of the following: (taken from the Win32 SDK Reference Manual)
  • MK_CONTROL - Set if the CTRL key is down.
  • MK_LBUTTON - Set if the left mouse button is down.
  • MK_MBUTTON - Set if the middle mouse button is down.
  • MK_RBUTTON - Set if the right mouse button is down.
  • MK_SHIFT - Set if the SHIFT key is down.
X and Y are the location at which the mouse cursor now is.
WM_MOUSEMOVE
void (*OnKeyPress)(void* Sender, int Key, LPARAM lParam);
void (*OnKeyDown)(void* Sender, int Key, LPARAM lParam);
void (*OnKeyUp)(void* Sender, int Key, LPARAM lParam);
These events occur when the user either presses a key, or holds a key down, or lets a key go. Key can be any one of the virtual key codes. lParam is a funny thing, and it contains a lot of extra information. According to the Win32 SDK Reference Manual, this is what lParam means:
"Value of lParam. Specifies the repeat count, scan code, extended-key flag, context code, previous key-state flag, and transition-state flag, as shown in the following table:
Value - Description
0-15 - Specifies the repeat count. The value is the number of times the keystroke is repeated as a result of the user holding down the key.
16-23 - Specifies the scan code. The value depends on the original equipment manufacturer (OEM).
24 - Specifies whether the key is an extended key, such as the right-hand ALT and CTRL keys that appear on an enhanced 101- or 102-key keyboard. The value is 1 if it is an extended key; otherwise, it is 0.
25-28 - Reserved; do not use.
29 - Specifies the context code. The value is always 0 for a WM_KEYDOWN message.
30 - Specifies the previous key state. The value is 1 if the key is down before the message is sent, or it is 0 if the key is up.
31 - Specifies the transition state. The value is always 0 for a WM_KEYDOWN message."
Now I would be guessing that each of the numbers are bits inside the lParam number, which you can extract with the bit shift operators (<< and >>) and an '&' bitmask. Bits 0-15 would be the first half of the number. If you can understand this and find this useful, then that's great.
WM_CHAR, WM_KEYDOWN, WM_KEYUP
void (*OnPaint)(void* Sender, HDC SuggestedHDC); This event occurs when the window needs to be repainted. So repaint it! Actually, you might only want to repaint it if you are using an ownerdrawn window. The HDC that is passed along can be used to draw with if you so wish (which is reccommended), otherwise you can just get your own HDC to draw with. WM_PAINT
bool (*OnEraseBack)(void* Sender, HDC SuggestedHDC); This event occurs when Windows wants a control to erase it's background, ready to paint again. I would advise you to use the HDC that is passed along. Return TRUE if you erased the background, or FALSE if you didn't, or FALSE if you want Windows not to think that you have erased the background. Why you wouldn't want Windows to know... I don't know. Who knows? WM_ERASEBKGND
void (*OnGainFocus)(void* Sender, HWND HandleLostIt);
void (*OnLoseFocus)(void* Sender, HWND HandleGetIt);
These events occur when the window either gains or loses the focus. The Handle that is passed along is either the handle of the window that just lost the focus or the handle of the window that is about to get the focus. WM_SETFOCUS, WM_KILLFOCUS
void (*OnCreate)(void* Sender); This event is called when the window is created. Please note that it is called from within this class, not from the window's message queue like would be normal. The reason for this is that it is impossible to catch the WM_CREATE message with the way that the class works. This is just as good, though. WM_CREATE?
void (*OnDestroy)(void* Sender); This event occurs when the window is destroyed, either by Windows, a pesky user, or the application (whilst it is closing, or something smart like that). WM_DESTROY
bool (*PassMessageQueue)(void* Sender, HWND Handle, UINT Message, WPARAM wParam, LPARAM lParam); This event is called whenever a message gets sent to the window. You can filter out and use any messages from this. Return TRUE if you are going to return a value, and store the value in (_GUIBASE*)Sender->MessageQueueReturn (type LRESULT) and this will be returned. If you don't wish to return anything to the message queue, return FALSE. All Messages

Sample Code

The following snippet gives a basic idea of how to use this component.


//Create your component, whatever it might be - in this example,
//it's just a button.
//You should not create an instance of a _GUIBASE object!
fBUTTON Button;

//All these functions are inherited...
Button.CreateWin(&Window, "Click me!!", BUTTON_ID, bsNormal, bsUsual);
Button.SetAll(10,10,75,25);
... = Button.Width();

Button.SendMsg(WM_NULL, 0, 0); //Just any message...

Button.Morph(bsNormal, bsCheckBox); //Change it...

//Please don't try this unless you know what you are doing
//(this code will not work directly).
Button.Assimilate(HandleToStartButton, ID_START_BUTTON);

Sample Inhertiance code

This sample code shows how to build an object that inherits the _GUIBASE properties and works properly.

In this example is the code for the fPROGRESS component, plus a few new explanatory comments.


class fPROGRESS : public _GUIBASE { //Inherit the _GUIBASE class.
      private:
//No private properties needed in this class.

      public:
             fPROGRESS()
                  {
                  //Initialise all the stuff...
                  //You will need to do this in your class too...
                  //Set the window class.
                  WindowClass     = PROGRESS_CLASS;
                  //Set up other options...
                  RepaintOnResize = TRUE;
                  Handle          = 0;
                  pLeft           = 0;
                  pTop            = 0;
                  pRight          = 0;
                  pBottom         = 0;
                  pWidth          = 0;
                  pHeight         = 0;
                  DontDestroy     = FALSE;
                  #ifdef F_USEFUICONTROLLER
                  //Change this to TRUE if you want to use
                  //the TAB key to change the focus.
                  UseTab          = FALSE;
                  ComponentID     = CT_BUTTON;
                  Internal_GUIInit();
                  #endif
                  };

//Add your extra properties here. If you have a basic component, you can
//just add some extra properties to make it go.
             void SetBarColour(COLORREF Colour)
                  {
                  if (Handle) SendMessage(Handle, WM_USER+9, 0, (LPARAM) Colour);
                  };
 ...
             void Step(void)
                  {
                  if (Handle) SendMessage(Handle, PBM_STEPIT, 0, 0);
                  };
};

Of course, there is more to the inheritance than this. Firstly, there is the CreateWin() function thingy. Mostly you can use the default ones, but sometimes you may like to replace them with functions that take more or less parameters. An example of this is the listbox, which has it's own CreateWin() functions altered to leave out the caption parameter. If you wish to replace these, copy the CreateWin() functions from gui_base.h and then paste them into your class. Then you can change them to suit your needs.

However, if you just want to do some initialisation before you create the window, or initialisation afterwards, then you can replace the functions void Internal_InitBefore(void); and void Internal_InitAfter(void); These might be useful in situations where you need to load a DLL before you can create the window, or if you need to set some properties related to the window you just created - an example of this is the RichEdit control. Please note that the two aforementioned functions are called internally from CreateWin().


...
//So in your class, if need be, use these functions...
void Internal_InitBefore(void)
     {
     //Do some stuff before the window is created.
     };

void Internal_InitAfter(void)
     {
     //Do some stuff after the window is created.
     };

The last item not mentioned yet is the use of the ComponentID member. Go and have a look at the source of gui_controller_start.h - in particular, lines 31 to 48. The lines 31 through 48 specify numbers for each type of component. The numbers from 1 to 49 are reserved for components based on the _GUIBASE object. The other variables are special objects that require the GUI controller, but are not based on _GUIBASE. If you wish to create a new component, you may like to add a new constant to this list. Please note that I may change this if you submit the code to me; the reason for this is to make sure that all the components fit together nicely - but if you use the constants, there should be no problems.

Any more questions? If you are having trouble, go and look at the other components which make use of this - any of the GUI components (except fFORM) makes use of this class. One class that may be worth a look is the fRICHEDIT class (in richeditor.h), as it has to use both the Internal_InitBefore() and the Internal_InitAfter() functions to load the appropriate DLL's and then unload them when the window is destroyed.

If you make a new GUI object, share it with me and I'll share it around! I'll document it as best I can, and you will definitely get the credit. Please see how to contact me on the main page for where to send your class.


Back to indexThe FreeFoote Foundation Classes Documentation