mgsLib  1.3
Mermaja's Graphic Screen. A simple C library to build Windows graphic applications from console programs.
mgsLib fundamentals

Introduction to mgsLib

mgsLib (Mermaja's Graphic Screen Library) is a simple graphic library developed by Germán Fabregat to teach C programming to Industrial Engineering students at the University Jaume I of Castellón, SPAIN.

mgsLib allows the programmer to generate graphic output in one or several graphic windows from a Windows console application. Whit this simple library the programmer can plot functions, display images, use text of different sizes and colors, draw geometric figures and play around with many other 2D graphic objects without having to worry about the way Windows graphic applications work. The library does also provide keyboard and mouse input functions, basic sound playing and moreover, timed frame synchronization to allow the programmer to build simple animations, games or simulations.

This current version of mgsLib incorporates several widgets that can be used on any animated application (see the animation section) to provide high level input including buttons, text boxes, lists... Next page, Widgets for mgsLib, describes these widgets and their usage.

mgsLib does not require any other library to be installed on the system but the standard Windows libraries that are present in any C development environment for Windows. The mgsLib library itself has been developed and tested using the MinGW C complier and the MinGW Developer Studio IDE.

NOTE: Both mgsLib itself and this documentation are currently under development. Please feel free to contact the author to contribute with doubts, suggestions, discovered bugs or mistakes, incorrect use of the english language or any other comment you may consider will help to improve them. They will be very welcome.


Creating and using graphic screens

An application creates a graphic screen to draw on by using the mgsCreateScreen() function, that returns the handle to the screen, an integer value. The call creates a new window on the desktop with the given width and height in pixels on its client area (the part of the window inside its borders), and filled either with an image or a solid color, according to its creation parameters. As we can see on the image, the screen adapts to the usual Windows system of coordinates, being (0, 0) the top left corner, and (width - 1, height - 1) the bottom right one.

screen.png
Created with mgsCreateScreen(800, 600, "800 x 600 Screen", 0x204020, NULL)

Once the application has created the screen, it can use its handler to draw lines, figures and images on it using funcions from the groups presented in the next sections. The result of these drawing functions though will not directly reflect on screen, but affect an associated memory buffer that is copied to the actual window by means of the mgsUpdateScreen() function. With this approach refreshing the screen is under control of the application, which allows it to perform timed updates and animations.

The library also provides the mgsClearScreen() function that resets the memory buffer (not the visible screen, so a later update is required if we want to clear the visible contents of the window) to display its background, either color or image. The application can use at any moment the mgsSetBackground() call to freeze the current contents of the memory buffer and use this image as background, thus having the posibility to change the background at any moment. When an application has finished using a screen, it can be deleted and removed from the system using mgsDeleteScreen().

This current version adds the possibility to create one (and obviously only one) full screen, borderless window using mgsFullScreen() to create it. It has also added the posibility to move a window on screen using mgsMoveScreen() and to set the focus on it with mgsActivateScreen(). Finally, the function mgsGetScreenInfoAdvanced() is provided to obtain size and position information for the screens and the desktop and to get the standard Windows handle of the screen window to use any other Windows function on it.

All these basic screen handling functions are further described following this link.


Drawing on the screen

Once an application has created a screen it can start drawing on it to place points and lines or to display geometric figures or images from files in many formats. Note that previous versions of mgsLib handled only windows bitmap files, but this has been solved on this current version. The contents of the screen window, as it has been said before, will be updated as required by the application to show the results of the set of drawing functions used.

Apart from the images, whose colors are those of the file, any 24 bits RGB color can be used on the item to be placed on screen, so we describe now the color format used by mgsLib. Following subsections will discusse in detail the families of functions available to place things on screen.

Color format

All the fuctions of the library (at least up to the current version) represent colors as 32 bits integers. Colors are solid, so no alpha channel is used and the 8 msb are not used and should be 0. The order of the remaining bytes (8 bit groups) on the 32 bit integer adapt to the Windows COLORREF structure so the second most significative byte represents the blue component, the second least significative the green and the least significative the red. We can depict a color in hexadecimal as 0x00BBGGRR where the place of each color component inside the integer is represented by its initial letter.

mgsLib includes the mgsRGBColor() macro to create a color given its RGB components as bytes. Predefined constants for the most usual colors are also included in the header file.

Basic drawing

The basic drawing functions are used to draw points and straight and elliptic lines. mgsPoint() plots a pixel anywhere on the screen and mgsLine() draws a straight line of the given width between two points. mgsEArc() and mgsRotatedEArc() draw elliptic arcs. We have also included in this category the mgsGetColor() function that returns the color of the pixel at the given coordinates. The image below shows the result of using points to plot x*sin(x) and sin(x) and lines to draw the axis.

fnpoints.png
Plot of two well-known functions

The example file functions.c shows the code used to generate this image and the previous one, as well as a plot of the same functions using lines instead of points.

Figures

More diverse is the set of functions available to draw geometric figures. It includes outlined and filled figures, and straight and rotated versions of each. These figures include ploygons, ellipses, stars, elliptic segments and sectors, etc. The following links list the whole set of outlined straight and rotated figures and solid straight and rotated versions of rectangles, ellipses, polygons, regular polygons, stars, etc. The solid figures have a border of selectable width and color, but macros exist to draw non bordered solid figures.

figures.png
Some bordered and non bordered solid figures

The example file figures.c shows the code used to generate this image and to animate it using rotated figures.

Handling and drawing images

In addition to use images as background for the screens, mgsLib can load many types of image files and display them on screen. As images will be often reused (and maybe given other uses in future versions of mgsLib) they are treated as a special type of element. An image is loaded using the mgsLoadImage() function that returns an integer to reference it. This integer will be later used by the functions mgsDisplayImage() and mgsDisplayRotatedImage() whenever the application wants to display the image. Images can be also created from a rectangular region of the drawing buffer using the mgsMakeImage() function. The size of the image can be retrieved using mgsImageWidth() and mgsImageHeight(). Here you can find the complete list of image handling functions.

As it has been said when discussing colors, mgsLib does not currently support alpha channel, but images can be displayed in solid or transparent mode. When an image is created from a file format that does not support transparency, the system considers the color on its left upper corner as the transparent color. When the transparent mode is used to display the image, every pixel on it having that color will not be printed on the background, thus allowing for an all or nothing kind of transparency. This has to be taken into account when using antialiased images. As pixels tend to degradate its color towards that of the background, those that are similar will not be treated as transparent, possibly causing artifacts or deforming the image. On the other hand, when the image is imported from a file format that supports transparency, transparent pixels have to be converted to a color in order to use this color as transparent. The function mgsSetImportTColor() can be used to set this color.

As images consume some system resources when loaded, it is convenient to use mgsDeleteImage() to release them when they are no longer needed.

images.png
Seagulls and crabs on the seaside using images

The example file images.c shows the code used to generate the screen with a seaside background and to load and display seagull and crab images on it. The example magnifier.c shows the use of mgsMakeImage() to copy a region of a screen as a new image and show them magnified in another window. The image below displays the results of this example.

magnifier.png
Grabbing a rectangle of a screen to magnify it in another. A simple color picker is also added for free

Printing text on screen

mgsLib provides several functions to handle texts and display them on screen, with different sizes and colors. Previous versions of mgsLib only provided mgsSetFont() to set the character height (in Windows logical units), its foreground and background color from a fixed system font. This current version adds mgsSetFontType() to give the flexibility to select font type, size, style, etc. and mgsSetFontColor() to set its foreground and background colors.

Once the font has been set, all subsequent calls to mgsPuts() will use it to print a string at the given position. Unless the transparent color is used for the background, text will be displayed on a box of that color. This box and the text will be clipped out of the screen if they exceed its dimensions. This current version of mgsLib includes mgsPutsAligned() to draw a text string aligned on the given rectangle and mgsTextSize() to obtain the width and height of a given string with the current font and adjust it on screen as desired.


User input

Applications can react to user interaction monitoring mouse and keyboard activity. These interactions are to be thought of as events the user sends to the application, no as text data input. Applications can always ask for user data using the console and the standard glibc functions.

Mouse input

mgsLib tracks mouse activity in a screen-wise fashion. Mouse (or pointer) activity is tracked by each screen if the cursor is over it, so any function inquiring mouse state should include a screen handler. The set of basic mouse functions include mgsMouseX() and mgsMouseY() to read cursor position, mgsMouseButtons() to detect pressing and releasing of mouse buttons and mgsMouseWheel() to track rotation of the mouse wheel over the screen. This current version of mgsLib adds two mouse functions, mgsMouseIn() to detect if the cursor is on a given screen and mgsMouseGlobal() to obtain the position of the cursor on the desktop.

mouse.png
Reacting to mouse clicks on the colored rectangles

The example file mouse.c shows how to use the mouse input functions as shown on the image. The complete set of mouse functions of this second version of mgsLib include the advanced functions mgsMouseClicked(), mgsMousePressed() and mgsMouseOver() that get track of mouse activity related to selected rectangular regions of the screen. These functions are typically used in a timed loop, and require a single call to mgsHandleMouse(), usually at the begining of the loop. The example file lines.c shows hoy to use these advanced functions to perform a simple user interface, as well as serving as example of a nice animation. The image below shows what will appear rotating and beating on screen after the configuration.

lines.png
Use the advanced mouse functions to configure the rotating lined polygon

Keyboard input

Keyboard input, on the other hand, is system-wise and much simpler. Only the mgsKeyPressed() function is provided to monitor the state, pressed or released, of the given key. It should be taken into account that the function monitors the state of the given key be the focus on the application or on any other window, so it will detect the given key pressed equally when the user is interacting with the application or typing on his favourite word processor.

To perform normal text input this current version of mgsLib includes two on screen keyobard types and text boxes associated with them. See Widgets for mgsLib to know more about these advanced text input facilities.


Playing sounds

A basic mean to play sound has been included providing the mgsPlaySoundFile() function. It loads form disk and plays a .wav sound file. No mixing is handled, so a second call to this function to play a sound will stop the currently playing one, if any. To stop any sound without playing another, mgsStopSound() is provided.


Timing the screen updates: animation

On the first tests when considering the develompent of mgsLib it became evident that it was not adequate to draw directly on the displayed window but on a memory buffer, as it has been said previously. Then the mean to actually transfer the drawn objects to the screen was the mgsUpdateScreen() function. Provided this way to control the instants when the screen is updated, it suffices to time them adequately to perform animations. So mgsLib offers mgsWaitFrame() to stop the program and wait until the next frame time arrives, and mgsSetFrameTime() to control the frame rate. Obviously if the lapse between two consecutive calls to mgsWaitFrame() is greater than the fixed frame time, no delay will occur and frames will not be synchronized (at least under mgsLib control).

As it has been implicitly stated, frames can synchronize by calling mgsWaitFrame() repeatedly, so the natural way to display animations is in an (almost) infinte loop. To have a fluent animation the loop code should be ordered according to the following list (really this is a recomendation from the author, who is not an expert in computer animation...)

while(any_almost_infinite_condition) {

  1. Carry out all the application logic, calculations, input check, or whatsoever your application has to do to calculate new objects and new positions.
  2. mgsClearScreen(); // Yes, clear the screen.
  3. Draw all the objects on its new positions. Take into account that the z order (orthogonal to the screen plane) depends on the drawing order, so draw first the lower image elements and let the upper be the last.
  4. mgsWaitFrame(); // Time your animation.
  5. mgsUpdateScreen(); // Show the new screen.

}

To have an idea of the time consumed by step one of the list and maybe adjust the frame rate accordingly, mgsPerformanceMeasure() can be used.

Very different examples of animation can be found on the files figures.c , where a set of objects is put to rotate on screen, and mouse.c where animation is used to change the screen objects interacting with the user.


System and error information.

Many of the functions of mgsLib are susceptible to fail, either by system reasons (a file not found, for instance) or misuse (wrong screen handler, trying to draw a one sided polygon) so the function mgsShowError() is included to display error and application provided information either on the console or opening a Windows message box. To complete the information functions, mgsVersionData() will return a set of system parameters with useful version and run time information.