⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 pcxmouse.c

📁 c语言实现鼠标图形化
💻 C
字号:
#include <io.h>
#include <bios.h>
#include <conio.h>
#include <stdio.h>
#include <stdlib.h>
#include <dos.h>
#include <bios.h>
#include <fcntl.h>
#include <mem.h>
#include <math.h>
#include <string.h>
#include <malloc.h>
#include <time.h>

#define MOUSE_INT 0x33
#define MOUSE_RESET 0x00
#define MOUSE_SHOW 0x01
#define MOUSE_HIDE 0x02
#define MOUSE_BUTT_POS 0x03
#define MOUSE_SET_SENSITIVITY 0x1A
#define MOUSE_MOTION_REL 0x0B
#define MOUSE_LEFT_BUTTON 0x01
#define MOUSE_RIGHT_BUTTON 0x02
#define MOUSE_CENTER_BUTTON 0x04

#define SPRITE_DEAD 0
#define SPRITE_ALIVE 1
#define SCREEN_WIDTH 320
#define SCREEN_HEIGHT 40
#define SCREEN_WIDTH1 320
#define SCREEN_HEIGHT1 200
#define SCREEN_HEIGHT3 70

#define VGA256 0x13
#define TEXT_MODE 0x03


#define SPRITE_WIDTH 16
#define SPRITE_HEIGHT 16
#define SPRITE1_WIDTH 5
#define SPRITE1_HEIGHT 5

#define MAX_SPRITE_FRAMES 8

#define PALETTE_MASK 0x3c6
#define PALETTE_REGISTER_RD 0x3c7
#define PALETTE_REGISTER_WR 0x3c8
#define PALETTE_DATA 0x3c9
typedef struct RGB_color_typ
{
unsigned char red;
unsigned char green;
unsigned char blue;
}RGB_color,*RGB_color_ptr;


unsigned char far *video_buffer=(char far *)0xA0000000L;

typedef struct{
  int mak[2][16];
  int hor;
  int ver;
  }mscurstype;

mscurstype handcurs={-7681,-7681,-7681,-7681,-7681,-8192,-8192,-8192,
		      0,    0,    0,    0,    0,    0,    0,    0,
		      7680,4608,4608,4608,4608,5119,4681,4681,4681,
		      -28671,-28671,-28671,-22767,-32767,-32767,-1,-1,0};

mscurstype arrow={0x3fff,0x1fff,0x0fff,0x07ff,
 0x03ff,0x01ff,0x00ff,0x007f,
 0x003f,0x00ff,0x01ff,0x10ff,
 0x30ff,0xf87f,0xf87f,0xfc3f,
 0x0000,0x4000,0x6000,0x7000,
 0x7800,0x7c00,0x7e00,0x7f00,
 0x7f80,0x7e00,0x7c00,0x4600,
 0x0600,0x0300,0x0300,0x0180,0,0};

mscurstype lin={0xe3e3,0xe3e3,0xe3e3,0xe3e3,
0x8080, 0x8080,0x8080,0xe3e3,
0xc1c1, 0x8080,0x0000,0x2323,
0xe3e3,0xe3e3,0xe3e3, 0xe3e3,
 0x0000,0x0808,0x0808,0x0808,
 0x0808,0x3e3e,0x0808,0x0808,
 0x1c1c,0x2a2a,0x4848,0x0808,
 0x0808,0x0808,0x0808,0x0000,2,0};

mscurstype arrowcurs={16383,8191,4095,2047,1023,511,225,127,63,
		       31,511,4351,12543,-1921,-1921,-961,0,16348,
		       24576,28672,30720,31744,32256,32512,32640,
		       32704,31744,17920,17920,768,384,192,-1,-1};


void Set_Palette_Register(int index,RGB_color_ptr color)
{
outp(PALETTE_MASK,0xff);
outp(PALETTE_REGISTER_WR,index);
outp(PALETTE_DATA,color->red);
outp(PALETTE_DATA,color->green);
outp(PALETTE_DATA,color->blue);
}


int Squeeze_Mouse(int command,int *x,int *y,int *buttons)
{
union REGS inregs,outregs;

switch(command)
{
case MOUSE_RESET:
{
inregs.x.ax=0x00;
int86(MOUSE_INT,&inregs,&outregs);
*buttons=outregs.x.bx;
return(outregs.x.ax);
}break;



case MOUSE_SHOW:
{
inregs.x.ax=0x01;
int86(MOUSE_INT,&inregs,&outregs);
return(1);
}break;


case MOUSE_HIDE:
{
inregs.x.ax=0x02;
int86(MOUSE_INT,&inregs,&outregs);
return(1);
}break;


case MOUSE_BUTT_POS:
{
inregs.x.ax=0x03;
int86(MOUSE_INT,&inregs,&outregs);
*x=outregs.x.cx;
*y=outregs.x.dx;
*buttons=outregs.x.bx;
return(1);
}break;


case MOUSE_MOTION_REL:
{
inregs.x.ax=0x03;
int86(MOUSE_INT,&inregs,&outregs);
*x=outregs.x.cx;
*y=outregs.x.dx;
return(1);
}break;

case MOUSE_SET_SENSITIVITY:
{
inregs.x.ax=0x04;

inregs.x.bx=*buttons;
inregs.x.cx=*x;
inregs.x.dx=*y;

int86(MOUSE_INT,&inregs,&outregs);
return(1);
}break;


default:break;
}
}

void setcurshape(mscurstype mask)
{
  union REGS r;
  struct SREGS s;
  r.x.ax=9;
  r.x.bx=mask.hor;
  r.x.cx=mask.ver;
  r.x.dx=FP_OFF(&mask);
  s.es=FP_SEG(&mask);
  int86x(0x33,&r,&r,&s);
}

void mscurson(mscurstype shape)
{
int msvisible;
 union REGS r;
 struct SREGS s;
 setcurshape(shape);
 r.x.ax=1;
 msvisible=1;
 int86x(0x33,&r,&r,&s);
 }


 typedef struct pcx_header_typ
	{
	char manufacturer;
	char version;
	char encoding;
	char bits_per_pixel;
	int x,y;
	int width,height;
	int horz_res;
	int vert_res;
	char ega_palette[48];
	char reserved;
	char num_color_planes;
	int bytes_per_line;
	int palette_type;
	char padding[58];

	} pcx_header, *pcx_header_ptr;


typedef struct pcx_picture_typ
	{
	pcx_header header;
	RGB_color palette[256];
	char far *buffer;

	} pcx_picture, *pcx_picture_ptr;



void Set_Video_Mode(int mode)
{
	union REGS inregs,outregs;
	inregs.h.ah=0;
	inregs.h.al=(unsigned char)mode;
	int86(0x10,&inregs,&outregs);
}

void PCX_Load_Screen(char *filename, pcx_picture_ptr image,int enable_palette)
{
// this function loads a pcx file into a picture structure, the actual image
// data for the pcx file is decompressed and expanded into a secondary buffer
// within the picture structure, the separate images can be grabbed from this
// buffer later.  also the header and palette are loaded

FILE *fp;
int num_bytes,index;
unsigned int count;
unsigned char data;
char far *temp_buffer;

// open the file

fp = fopen(filename,"rb");

// load the header

temp_buffer = (char far *)image;

for (index=0; index<128; index++)
    {
    temp_buffer[index] = getc(fp);
    } // end for index

// load the data and decompress into buffer
count=0;


while(count<=(unsigned int)SCREEN_WIDTH1 * SCREEN_HEIGHT1)
	 {
	 // get the first piece of data

	 data = getc(fp);

	 // is this a rle?

     if (data>=192 && data<=255)
	{
	// how many bytes in run?

        num_bytes = data-192;

	// get the actual data for the run

	data  = getc(fp);

		// replicate data in buffer num_bytes times

        while(num_bytes-->0)
             {
//             image->buffer[count++] = data;
  video_buffer[count++]=data;
	     } // end while

	} // end if rle
     else
	{
	// actual data, just copy it into buffer at next location

	//image->buffer[count++] = data;
	  video_buffer[count++]=data;
	} // end else not rle

     } // end while

// move to end of file then back up 768 bytes i.e. to begining of palette

fseek(fp,-768L,SEEK_END);

// load the pallete into the palette

for (index=0; index<256; index++)
    {
    // get the red component

    image->palette[index].red   = (getc(fp) >> 2);

    // get the green component

    image->palette[index].green = (getc(fp) >> 2);

    // get the blue component

    image->palette[index].blue  = (getc(fp) >> 2);

    } // end for index

fclose(fp);

// change the palette to newly loaded palette if commanded to do so

if (enable_palette)
   {

   for (index=0; index<256; index++)
       {

       Set_Palette_Register(index,(RGB_color_ptr)&image->palette[index]);

       } // end for index

   } // end if change palette

} // end PCX_Load


typedef struct sprite_type
{
int x,y;
int x_old,y_old;
int width,height;
int anim_clock;
int anim_speed;
int motion_clock;
int motion_speed;
char far *frames[MAX_SPRITE_FRAMES];
int curr_frame;
int num_frames;
int state;
char far *background;
void far *extra_data;
}sprite,*sprite_ptr;





void Sprite_Init_Size(sprite_ptr sprite,int x,int y,int ac,int as,int mc,int ms,int height,int width,int frame)
{
// this function initializes a sprite with the sent data

int index;

sprite->x            = x;
sprite->y            = y;
sprite->x_old        = x;
sprite->y_old        = y;
sprite->width        = width;
sprite->height       = height;
sprite->anim_clock   = ac;
sprite->anim_speed   = as;
sprite->motion_clock = mc;
sprite->motion_speed = ms;
sprite->curr_frame   = 0;
sprite->state        = SPRITE_DEAD;
sprite->num_frames   = 0;
sprite->background   = (char far *)malloc(width * height+1);

// set all bitmap pointers to null

for (index=0; index<frame; index++)
    sprite->frames[index] = NULL;

} // end Sprite_Init


void PCX_Grab_Bitmap_Size_Screen(pcx_picture_ptr image,
		    sprite_ptr sprite,
		    int sprite_frame,
		    int grab_x, int grab_y,int height,int width)

{
// this function will grap a bitmap from the pcx frame buffer. it uses the
// convention that the 320x200 pixel matrix is sub divided into a smaller
// matrix of 12x8 adjacent squares each being a 24x24 pixel bitmap
// the caller sends the pcx picture along with the sprite to save the image
// into and the frame of the sprite.  finally, the position of the bitmap
// that should be grabbed is sent

int x_off,y_off, x,y, index;
char far *sprite_data;

// first allocate the memory for the sprite in the sprite structure

sprite->frames[sprite_frame] = (char far *)malloc(width * height);

// create an alias to the sprite frame for ease of access

sprite_data = sprite->frames[sprite_frame];

// now load the sprite data into the sprite frame array from the pcx picture

// we need to find which bitmap to scan, remember the pcx picture is really a
// 12x8 matrix of bitmaps where each bitmap is 24x24 pixels. note:0,0 is upper
// left bitmap and 11,7 is the lower right bitmap.

x_off = (width) * grab_x;
y_off = (height) * grab_y ;

// compute starting y address

y_off = y_off * 320;

for (y=0; y<height; y++)
    {

    for (x=0; x<width; x++)
	{

	// get the next byte of current row and place into next position in
	// sprite frame data buffer

	sprite_data[y*width + x] = video_buffer[y_off + x_off + x+1];

	} // end for x

	// move to next line of picture buffer

	y_off+=320;

    } // end for y

// increment number of frames

sprite->num_frames++;

// done!, let's bail!

} // end PCX_Grap_Bitmap

//////////////////////////////////////////////////////////////////////////////



void Fill_Screen(int value)
{
_fmemset(video_buffer,(char)value,SCREEN_WIDTH*SCREEN_HEIGHT1+1);
}

void Fill_Screen_Size(int value,int x0,int y0,int x1,int y1)
{
int x,y;
long i=0,height,width;
height=y1-y0+1;
width=x1-x0+1;
x=x0;
while(i<height*width)
{
	y=y0+i/width;
	i=i+width;
	_fmemset(video_buffer+x+y*SCREEN_WIDTH,(char)value,width);
}
}
void Behind_Sprite_Size(sprite_ptr sprite,int height,int width)
{

// this function scans the background behind a sprite so that when the sprite
// is draw, the background isnn'y obliterated

char far *work_back;
int work_offset=0,offset,y;

// alias a pointer to sprite background for ease of access

work_back = sprite->background;

// compute offset of background in video buffer

offset = (sprite->y << 8) + (sprite->y << 6) + sprite->x;

for (y=0; y<height; y++)
    {
    // copy the next row out off screen buffer into sprite background buffer

    _fmemmove((void far *)&work_back[work_offset],
	     (void far *)&video_buffer[offset],
	     width);

    // move to next line in video buffer and in sprite background buffer

    offset      += SCREEN_WIDTH;
    work_offset += width;

    } // end for y

} // end Behind_Sprite

void Draw_Sprite_Size(sprite_ptr sprite,int height,int width)
{

// this function draws a sprite on the screen row by row very quickly
// note the use of shifting to implement multplication

char far *work_sprite;
int work_offset=0,offset,x,y;
//unsigned char data;

// alias a pointer to sprite for ease of access

work_sprite = sprite->frames[sprite->curr_frame];

// compute offset of sprite in video buffer

offset = ((sprite->y) << 8) + ((sprite->y) << 6) + sprite->x;

for (y=0; y<height; y++)
    {
    // copy the next row into the screen buffer using memcpy for speed

    for (x=0; x<width; x++)
	{

	// test for transparent pixel i.e. 0, if not transparent then draw
      if(work_sprite[work_offset+x])

	 //data==(unsigned char)work_sprite[work_offset+x];
// if(data)
//	     video_buffer[offset+x] =data;
     video_buffer[offset+x]=work_sprite[work_offset+x];
	} // end for x

    // move to next line in video buffer and in sprite bitmap buffer

    offset      += SCREEN_WIDTH;
    work_offset += width;

    } // end for y
} // end Draw_Sprite

void Erase_Sprite_Size(sprite_ptr sprite,int height,int width)
{
// replace the background that was behind the sprite

// this function replaces the background that was saved from where a sprite
// was going to be placed

char far *work_back;
int work_offset=0,offset,y;

// alias a pointer to sprite background for ease of access

work_back = sprite->background;

// compute offset of background in video buffer

offset = (sprite->y << 8) + (sprite->y << 6) + sprite->x;

for (y=0; y<height; y++)
    {
    // copy the next row out off screen buffer into sprite background buffer

    _fmemmove((void far *)&video_buffer[offset],
	     (void far *)&work_back[work_offset],
	     width);

    // move to next line in video buffer and in sprite background buffer

    offset      += SCREEN_WIDTH;
    work_offset += width;

    } // end for y


} // end Erase_Sprite


void Sprite_Delete_Size(sprite_ptr sprite,int frame)
{
// this function deletes all the memory associated with a sprire

int index;

farfree(sprite->background);

// now de-allocate all the animation frames

for (index=0; index<frame; index++)
    farfree(sprite->frames[index]);

} // end Sprite_Delete


void main(void)
{
int xmouse=0,ymouse=0,btnmouse=0,xmouse_old=0,ymouse_old=0;
sprite small;
pcx_picture background_pcx,objects_pcx;
Set_Video_Mode(VGA256);
PCX_Load_Screen("flowersc.pcx",(pcx_picture_ptr)&objects_pcx,1);//调用图片文件
Sprite_Init_Size((sprite_ptr)&small,0,0,0,0,0,0,65,55,1);//初始化小图片
PCX_Grab_Bitmap_Size_Screen((pcx_picture_ptr)&objects_pcx,(sprite_ptr)&small,0,0,0,65,55);//将屏幕内容复制给小图片
Fill_Screen(0);
PCX_Load_Screen("poem.pcx",(pcx_picture_ptr)&objects_pcx,1);//背景
Behind_Sprite_Size((sprite_ptr)&small,65,55);//取图片后内容
Squeeze_Mouse(MOUSE_RESET,0,0,0);//初始化鼠标
mscurson(lin);//设置鼠标形状
Squeeze_Mouse(MOUSE_HIDE,0,0,0);//隐藏鼠标
while(!kbhit())
{
	Squeeze_Mouse(MOUSE_BUTT_POS,&xmouse,&ymouse,&btnmouse);//取鼠标位置
	if(xmouse!=xmouse_old||ymouse!=ymouse_old)//判断是否移动过鼠标
	{
		Erase_Sprite_Size((sprite_ptr)&small,65,55);//显示小图片后背景内容
		small.x=xmouse/2;
		small.y=ymouse;
		Behind_Sprite_Size((sprite_ptr)&small,65,55);//保存小图片后背景内容
		Draw_Sprite_Size((sprite_ptr)&small,65,55);//显示小图片于鼠标位置
		xmouse_old=xmouse;
		ymouse_old=ymouse;
	}
}
getch();

Sprite_Delete_Size((sprite_ptr)&small,1);
Set_Video_Mode(TEXT_MODE);

}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -