Sunday, May 21, 2017

C Program to restrict mouse pointer in a window

Graphics in C – Restrict Mouse Pointer in a Window


In the previous post I have explained the features which are essential to know for mouse programming using C computer language. Now, here is a simple program, by which you will understand these concepts better. Please type this program in your editor. 

#include<graphics.h>
#include<dos.h>

union REGS in, out;
int mousestart();
void showpointer();
void boundpointer(int x1, int y1, int x2, int y2);

void main()
{
      int gd = DETECT, gm, maxx, maxy, x, y;
      initgraph(&gd, &gm, "c:\\tc\\bgi");
      maxx = getmaxx();
      maxy = getmaxy();
      rectangle(0, 20, maxx, maxy-20);
      setviewport(1, 21, maxx-1, maxy-21, 1);
      if(mousestart() == 0)
      {
            closegraph();
            restorecrtmode();
            printf("\nMouse driver not loaded");
            exit(1);
      }
      boundpointer(1, 21, maxx-1, maxy-21);
      showpointer();
      getch();
      closegraph();
      restorecrtmode();
}

int mousestart()
{
      in.x.ax = 0;
      int86(0x33, &in, &out);
      return(out.x.ax);
}

void showpointer()
{
      in.x.ax = 1;
      int86(0x33, &in, &out);
}

void boundpointer(int x1, int y1, int x2, int y2)
{
      in.x.ax = 7;
      in.x.cx = x1;
      in.x.dx = x2;
      int86(0x33, &in, &out);

      in.x.ax = 8;
      in.x.cx = y1;
      in.x.dx = y2;
      int86(0x33, &in, &out);
}

Compile and execute this program. Output will be a rectangle or window, in which mouse pointer shows up. Move the mouse pointer. You will see that mouse pointer moves within this rectangular boundary or box and does not cross the boundaries.

In this program, I have declared three functions. The task of first function is to check whether mouse driver is loaded or not. Second function does the task of showing mouse pointer in a user-defined window. Third function restricts the movement of mouse pointer in this window. These functions are defined after the function main().

int mousestart();
void showpointer();
void boundpointer(int x1, int y1, int x2, int y2);

In the start, I have declared two variables ‘in’ and ‘out’ of type union REGS. I have told you about union REGS in my previous post. Here is a quick revision.

struct BYTEREGS {
      unsigned char al, ah, bl, bh;
      unsigned char cl, ch, dl, dh;
};

struct WORDREGS {
      unsigned int ax, bx, cx, dx;
      unsigned int si, di, cflag, flags;
};

union REGS {
        struct WORDREGS x;
        struct BYTEREGS h;
};

Thus, union REGS is a user-defined data type, which contains two struct WORDREGS and BYTEREGS variables ‘x’ and ‘h’. What is the use of these union variables, you will see later. These structures and union are defined in dos.h file.

In the function main(), I have obtained maximum screen coordinates and stored these in  variables ‘maxx’ and ‘maxy’.

maxx = getmaxx();
maxy = getmaxy();

I have drawn a rectangle, in which mouse pointer will move.

rectangle(0, 20, maxx, maxy-20);

Then, I have defined the user-defined view-port.

setviewport(1, 21, maxx-1, maxy-21, 1);

Function setviewport() establishes a new view-port for graphics output.

Declaration:

void far setviewport(int left, int top, int right, int bottom, int clip);

Where (left, top) is the upper-left corner, and (right, bottom) is the bottom-right corner of the view-port. The ‘clip’ argument determines whether drawings are clipped or truncated at the current view-port boundaries. If ‘clip’ is non-zero, all drawings will be truncated to the current view-port. The current position (C.P.) moves to (0, 0) in the new window.

Syntax for calling this function is given below-

setviewport(left, top, right, bottom, clip);

Therefore, whatever you draw beyond these boundaries, will not be drawn on the screen, because value of ‘clip’ has been given 1.

Now, an ‘if’ construct checks whether mouse driver has been installed or not. If installed, take further actions, otherwise exit. To check the availability of mouse driver, a function mousestart() has been called.

int mousestart()
{
      in.x.ax = 0;
      int86(0x33, &in, &out);
      return(out.x.ax);
}

To understand this function, please recall from the previous post.

Interrupt : 33h
Service : 0
Call with AX = 0
Returns
AX = 0000 (if mouse driver is not installed)
AX = FFFFh (if mouse driver is installed)

Thus, in the function mousestart(), I have given the value 0 (service number = 0) to the element  ‘ax’ of structure WORDREGS, now ‘x’ is the element of type struct WORDREGS in the union REGS, and ‘in’ is the variable of type union REGS. To refer ‘ax’, I have given the full notation like this- in.x.ax.

in.x.ax = 0;

Then, I have called the function int86() and passed the interrupt number 33h, and addresses of variables ‘in’ & ‘out’. After execution, this function returns the value of register ‘ax’ in the variable ‘out’. If it is 0, it means driver not loaded. If value of out.x.ax is FFFFh, it means driver is loaded.

return (out.x.ax);

Now, control returns to function main().  I assume that mouse driver is loaded. In the function main(), function boundpointer() is called. 

void boundpointer(int x1, int y1, int x2, int y2)
{
      in.x.ax = 7;
      in.x.cx = x1;
      in.x.dx = x2;
      int86(0x33, &in, &out);

      in.x.ax = 8;
      in.x.cx = y1;
      in.x.dx = y2;
      int86(0x33, &in, &out);
}

To understand this function, please recall the services from the previous post. These are given below-

Service : 7
Sets horizontal limits for pointer
Call with AX = 7
CX = minimum x coordinate
DX = maximum x coordinate
Returns nothing
à Restricts mouse horizontal movement to window
à If min value is greater than max value they are swapped

Service : 8
Sets vertical limit for pointer
Call with AX = 8
CX = minimum y coordinate
DX = maximum y coordinate
Returns nothing
à Restricts mouse vertical movement to window
à If min value is greater than max value they are swapped

Therefore, to restrict the horizontal movement, we call service 7 under interrupt 33h.

in.x.ax = 7;

To give the horizontal bounds, we have given the values to ‘cx’ and ‘dx’ variables as given below-

in.x.cx = x1; // minimum horizontal bound
in.x.dx = x2; // maximum horizontal bound

Then, we have called the function int86(). This function takes the action.

int86(0x33, &in, &out);

The same way, to give the vertical bounds, we have given the instructions given below-

in.x.ax = 8; // for vertical bounds give service 8
in.x.cx = y1; //minimum vertical bound
in.x.dx = y2; // maximum vertical bound
int86(0x33, &in, &out); // execute the service

Now, for showing the pointer, function showpointer() has been called.

void showpointer()
{
      in.x.ax = 1;
      int86(0x33, &in, &out);
}

This time, service 1 is executed available under interrupt 33h. Please recall from previous post.

Service : 1
Shows mouse pointer
Call with AX = 1
Returns nothing

Therefore, this way mouse pointer is displayed and restricted in the given boundaries. To understand this program better, please refer my previous post.

OUTPUT:








No comments:

Post a Comment

Please give your comment