Monday, September 19, 2011

Analog Clock source code using c++ and winBGI graphics

The is the sample example of a WinBGIm graphics library implementation. The program will create an Analog clock using WinBGIm library. WinBGIm library does not come by default in Codeblocks IDE. You have to setup WinBGIm library before using the below code. If you haven't done it yet then please follow my earlier article How to Setup WinBGIm graphics in Codeblocks.

If you encounter any errors please leave comments.

#include <graphics.h>
#include <winbgim.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <conio.h>
#include <math.h>
#include <dos.h>
#include <string.h>
#include <iostream>
#include <ctime>

#define S_N_L (radius-10)        // Second Needle Length
#define S_N_C RED                   // Second needle Color
#define M_N_L (radius-20)           // Minute Needle Length
#define M_N_C LIGHTRED              // Minute Needle Color
#define H_N_L (radius-(radius/2))       // Hour Needle Length
#define H_N_C CYAN                     // Hour Needle Color

float cx,cy;
float radius=100;

void draw_face(float radius);
void get_time(int &h,int &m,int &s);
void second_needle(int s);
void minute_needle(int m,int s);
void hour_needle(int h,int m,int s);

int main(void)
{
    /* request auto detection */
    int gdriver = DETECT, gmode, errorcode;
    initgraph(&gdriver,&gmode,"");
    /***********************************/
    cx=getmaxx()/2.0; // cx is center x value.
    cy=getmaxy()/2.0; // cy is center y value.
    /** Now the point (cx,cy) is the center of your screen. **/

    float x,y;
    int hour,minute,second;
    draw_face(radius);
    while(!kbhit())
    {
        get_time(hour,minute,second);
        second_needle(second);
        minute_needle(minute,second);
        hour_needle(hour,minute,second);
        circle(cx,cy,2);
        delay(100);
    }
    getch();
    closegraph();
    return 0;
}
//*************** FUNCTIONS DEFINITIONS *****************//

void draw_face(float radius)
{
    int theta=0; // theta is the angle variable.
    float x,y;
    /** Draw Clock Border. **/
    circle(cx,cy,radius+24);
    circle(cx,cy,radius+23);
    /** Draw GREEN material border. **/
    setcolor(BROWN);    // I like a wooden frame!
    /** Paint the border. **/
    for(int i=0;i<9;i++)
    circle(cx,cy,radius+13+i);
    /** Set the color white. **/
    setcolor(WHITE);
    /** Draw outer-inner border. **/
    circle(cx,cy,radius+12);
    circle(cx,cy,radius+10);
    /** Draw center dot. **/
    circle(cx,cy,2);
    int i=0;
    /** DRAW NUMERIC POINTS **/
    do{
        /** Getting (x,y) for numeric points **/
        x=cx+radius*cos(theta*M_PI/180);
        y=cy+radius*sin(theta*M_PI/180);
        /** Draw Numeric Points **/
        circle(x,y,2);
        /* Draw Dots around each numeric points **/
        circle(x+5,y,0);
        circle(x-5,y,0);
        circle(x,y+5,0);
        circle(x,y-5,0);
        /** Increase angle by 30 degrees, 
        which is the circular distance between each numeric points. **/
        theta+=30;
        /** Increase i by 1. **/
        i++;

    } while(i!=12); //LIMIT NUMERIC POINTS UPTO =12= Numbers.
    i=0;
    /** DRAW DOTS BETWEEN NUMERIC POINTS. **/
    do{
        putpixel(cx+radius*cos(i*M_PI/180)
        ,cy+radius*sin(i*M_PI/180),DARKGRAY);
        i+=6;
    }while(i!=360);

    /** FACE COMPLETELY DRAWN. **/
}
//================
/** Function to get the current time. **/
void get_time(int &h,int &m,int &s)
{
    time_t rawtime;
    struct tm *t;
    time(&rawtime);
    t = gmtime(&rawtime);
    h=t->tm_hour;
    m=t->tm_min;
    s=t->tm_sec;
}
//=================
/** Function to draw Second needle. **/
void second_needle(int s)
{
    float angle=-90;
    float sx,sy;
    setcolor(0);
    sx=cx+S_N_L*cos((angle+s*6-6)*M_PI/180);
    sy=cy+S_N_L*sin((angle+s*6-6)*M_PI/180);
    line(cx,cy,sx,sy);
    setcolor(S_N_C);
    sx=cx+S_N_L*cos((angle+s*6)*M_PI/180);
    sy=cy+S_N_L*sin((angle+s*6)*M_PI/180);
    line(cx,cy,sx,sy);
}
/** Function to draw Minute needle. **/
void minute_needle(int m,int s)
{
    float angle=-90;
    float sx,sy;
    setcolor(0);
    sx=cx+M_N_L*cos((angle+m*6-6)*M_PI/180);
    sy=cy+M_N_L*sin((angle+m*6-6)*M_PI/180);
    line(cx,cy,sx,sy);
    setcolor(M_N_C);
    sx=cx+M_N_L*cos((angle+m*6/*+(s*6/60)*/)*M_PI/180);
    sy=cy+M_N_L*sin((angle+m*6/*+(s*6/60)*/)*M_PI/180);
    line(cx,cy,sx,sy);
}
/** Function to draw Hour needle. **/
void hour_needle(int h,int m,int s)
{
    float angle=-90;
    float sx,sy;
    setcolor(0);
    sx=cx+H_N_L*cos((angle+h*30-(m*30/60))*M_PI/180);
    sy=cy+H_N_L*sin((angle+h*30-(m*30/60))*M_PI/180);
    line(cx,cy,sx,sy);
    setcolor(H_N_C);
    sx=cx+H_N_L*cos((angle+h*30+(m*30/60))*M_PI/180);
    sy=cy+H_N_L*sin((angle+h*30+(m*30/60))*M_PI/180);
    line(cx,cy,sx,sy);
}

How to Setup WinBGIm library in Codeblocks IDE

BGI (Borland Graphics Interface) is a very old graphics library available in Borland C++ and Turbo C++ IDE. Borland c++ and Turbo C++ both were discontinued. BGI graphics library was very popular, and still, students in our schools and colleges want to use it in their projects. Codeblocks IDE with MinGW compiler is widely used as C/C++ especially to develop cross-platform open-source software but BGI is not available in Codeblocks. Thanks to Michael Main, who created WinBGIm at the University of Colorado to use the BGI graphics library in windows with other compilers. There are many alternatives to winBGIm, But BGI is good for beginners because you don’t have to worry about whole new fancy functions, classes, etc.

However, the latest version of WinBGIm was released in Nov 2005 which is very old and no longer supported in a newer version of the MinGW compiler. We have to compile source code to make it run in the latest Codeblocks. In this article, I will provide instructions to compile source code and configure the library in Codeblocks IDE. I have also created a video about it. You can watch below:


If you don’t want to compile source code and fix errors by yourself then copy project files from my github https://github.com/smokindinesh/WinBGIm and go to configure library section.

Lets get started: Create Static Library Project
  1. First download WinBGIm Source Code from http://winbgim.codecutter.org/
  2. Extract it. (Note: Make sure you have download source code)
  3. Open Codeblocks and create a new project. (File -> New -> Project)
  4. From the Project template window select "Static Library" and fillup all necessary information to finish the project creation wizard.
  5. Go to project properties and select "Build targets" option and rename output filename with libbgi.a for both debug and release targets.
  6. Copy all source files that you have extracted in the earlier step and paste them to the project directory.
  7. Remove "main.c" file from the project.
  8. Add source files in the project (Select project in Workspace -> Right Click -> Add Files recursively). Select both Build and Release options in the Target window which pops-up after adding files.
  9. Now, a project is ready to build but there are errors in the source code. Please follow the instructions provided below to fix errors.

Instruction to fix errors:
  • Source file "bgiout.cxx" 
    • Line 1: Replace '#include <stringstream>' with '#include <sstream>'
    • Line 2: Remove ': virtual std::basic_ostringstream'
  • Source file "winbgim.h"
    • Line 302: Replace "right=0" with "top=0"
  • Source file "graphics.h"
    • Line 302: Replace "right=0" with "top=0"
  • Source file "misc.cxx"
    • Line 595 to 599: Remove "~". e.g Replace ~0xE0 with 0xE0.
  • Source file "winthread.cxx"
    • Line 103: Replace "SetWindowLong( hWindow, GWL_USERDATA, (LONG)pWndData )" with "SetWindowLongPtr( hWindow, GWLP_USERDATA, (LONG_PTR)pWndData )"
  • Source file "drawing.cxx"
    • Line 66: Replace "return (WindowData*)GetWindowLong( hWnd, GWL_USERDATA )" with "return (WindowData*)GetWindowLongPtr( hWnd, GWLP_USERDATA );"
  • Note: In above steps 5 and 6, if GWLP_USERDATA didnot work then try with GWL_USERDATA
  • Finally, compile project in Release target. I hope you will not encounter any other errors.

Configure winbgim library in Codeblocks.
  1. Create a folder in any directory and give the name "WinBGIm" and create include and lib folder inside it. (eg. c:\WinBGIm\include and c:\WinBGIm\lib).
  2. From the project created above, copy "graphics.h" and "winbgim.h" header files and paste it inside include directory, and "libbgi.a" file from bin/release project folder and paste it inside lib directory that you have created in step 2. (eg. c:\WinBGIm\include and c:\WinBGIm\lib). 
  3. Open the code::blocks and go to File -> New -> Project or click create a new project link from the start page.
  4. From the project wizard select "empty project" and click "Go" button and provide all necessary information. Also, do not forget to  add main.cpp file.
  5. Go to menu bar and select project-> Project properties. A dialogue box will appear and click "Project's build options". Another dialogue box will appear and click the "Search directories" tab. Under "Compiler" tab provide the path of WinBGIm include folder (e.g. c:\WinBGIm\include) and under "Linker" tab provide the path of WinBGIm lib folder (e.g. c:\WinBGIm\lib).
  6. Select "Linker Setting" tab and add "libbgi.a" file e.g path c:\WinBGIm\lib\libbgi.a. In "Other linker options" text box add linkers -lbgi -lgdi32 -lcomdlg32 -luuid -loleaut32 -lole32
  7. Now click ok.

Finally, you can now compile source code using "graphics.h". To test configuration please copy source code from the sample winBGIm graphics program from here. I hope, you found this guide helpful, and in case you need my help just leave a message.

Thursday, September 15, 2011

College project Contacts Management in C with source code

In this article, we will create a contact management system in C and store data in the file. You will learn CRUD (Create, Read, Update, and Delete) operation in C files, and various modes of opening files. The main objective of this article is to give you an idea of file handling in C programming. 

At the end of this article, you will learn the following items:
  • Break down the application into separate individual modules.
  • Create an application flow chart.
  • Convert the flow chart processes into C functions.
  • Learn techniques to switch between processes based on the user input.
  • Master the CRUD (Create, Read, Update, and Delete) operation in file handling.
You can download the final version of the application from GitHub Download from GitHub.

For a detailed explanation follow the articles below.

Chapter 1 -> Flow chart and Functions: In this article, you will learn to create a flow chart, breakdown the application into C functions, and create a Main Menu function to display options and get user input.
Chapter 2 -> File handling in C: In this article, you will learn to add, read, update, and delete data from the file

I have also created a video about this project on YouTube.