📄 mouse.cpp
字号:
#include "gl.h"
#include "gengine.h"
#define DEFAULT_MOUSE_CURSOR "mouse.tga"
#define DEFAULT_CURSOR_SIZE 18 //16
int mouseInstalled = false;
int volatile mouseX, mouseY; // used by the external code
DWORD volatile mousePos; // high word for X, low word for Y
int volatile mouseB; // mouse button state
int mouseCursorFroze = false;
static int volatile mousex, mousey; // store the up-to-date mouse position
static DWORD c, currentCursor, currentFrame, frames, types;
static int on = -1;
static Bitmap *bmpWork, *bmpCursor;
static int mouseFocusX = 0, mouseFocusY = 0;
static int mx, my; // internally used for updating mouse cursor
static int timer, speed; // used for animate curosr, 20ms
static int ml, mt, mr, mb; // mouse cursor range;
/* illustrate
double buffer 用来缓冲向screen的输出
save screen 保存将被破坏的屏幕
注意:由于采用了分页动画,当screen切换到backscreen后,原来screen上被破坏的
内容不被恢复 !!
bmpWork: |~~~~~~~~~~~|~~~~~|
| | | <---- save screen
| double |-----|
| buffer | |
|___________|_____|
bmpCursor:
|~~~~|~~~~|~~~~|~
| | | | ... animate cursor type 1
|~~~~|~~~~|~~~~|~
| | | | ... animate cursor type 2
|~~~~|~~~~|~~~~|~
| | | | ... animate cursor type 3 ...
*/
// select current cursor bitmap
void MouseSetCursor( DWORD type )
{
if( type > types )
return;
currentFrame = 0;
currentCursor = type;
if( on < 0 )
return;
// copy to double buffer
bmpWork->Blit( bmpWork, 0, 0, 2 * c, 0, c, c );
// draw mouse cursor in double buffer
bmpCursor->BlitMask( bmpWork, 0, 0, currentFrame * c, currentCursor * c, c, c );
int cl = screen->GetClip( );
screen->SetClip( false );
// copy double buffer to screen
bmpWork->Blit( screen, mx - mouseFocusX, my - mouseFocusY, 0, 0, c, c );
screen->SetClip( cl );
}
void MouseSetRange( int l, int t, int r, int b )
{
l = MIN( l, (int)screenInfo.width );
r = MIN( r, (int)screenInfo.width );
t = MIN( t, (int)screenInfo.height );
b = MIN( b, (int)screenInfo.height );
l = MAX( l, 0 );
r = MAX( r, 0 );
t = MAX( t, 0 );
b = MAX( b, 0 );
ml = MIN( l, r );
mr = MAX( l, r );
mt = MIN( t, b );
mb = MAX( t, b );
MouseSetPos( mx, my ); //adjust mousecursor position
}
void MouseSetSpeed( int xspeed, int yspeed )
{
}
// how far(mickeys) has the mouse moved since the last call to this function
void MouseGetMickeys( int& x, int& y )
{
}
// this function is used by UpdateScfeen()
void MouseBeforeUpdatescreen( void )
{
if( mouseInstalled && on == 0 ){
int cl = backScreen->GetClip();
backScreen->SetClip( false );
// save backscreen
backScreen->Blit( bmpWork, 2 * c, 0, mx - mouseFocusX, my - mouseFocusY, c, c );
// draw mouse cursor on backScreen
bmpCursor->BlitMask( backScreen, mx - mouseFocusX, my - mouseFocusY,
currentFrame * c, currentCursor * c, c, c );
backScreen->SetClip( cl );
}
}
void MouseSetPos( int x, int y )
{
if( x < ml ) x = ml;
else if( x >= mr ) x = mr-1;
if( y < mt ) y = mt;
else if( y >= mb ) y = mb-1;
if( on == 0 ){
MouseOff();
mx = mousex = mouseX = x;
my = mousey = mouseY = y;
mousePos = ( mx << 16 ) | ( my & 0xffff );
MouseOn();
}
}
int MouseLoadCursor( DWORD cl, DWORD ts, DWORD fs, DWORD fps, Bitmap *bmp )
{ // c:边长 ts:光标类型数 fs:帧数 v:帧速 bmp:图片
if( (DWORD)bmp->width < cl * fs || (DWORD)bmp->height < cl * ts || bmp == NULL )
return -1;
Bitmap* bmpW = CreateBitmap( cl*2, cl*2 );
if( bmpWork == NULL )
return -1;
MouseOff();
if( bmpCursor ) delete bmpCursor;
bmpCursor = bmp;
if( bmpWork ) delete bmpWork;
bmpWork = bmpW;
types = ts;
frames = fs;
c = cl;
timer = 0;
speed = 1000 / fps / 20;
MouseOn();
return 0;
}
void MouseSetFocusPos( int x, int y )
{
if( x >= (int)c || y >= (int)c || x < 0 || y < 0 )
return;
MouseOff();
mouseFocusX = x;
mouseFocusY = y;
MouseOn();
}
// turn on mouse cursor, if on == 0, cursor is visible
void MouseOn( void )
{
if( on < 0 ){
on ++;
if( on == 0 && LockScreen() == 0 ){
int cl = screen->GetClip( );
screen->SetClip( false );
// save screen
screen->Blit( bmpWork, 2*c, 0, mx - mouseFocusX, my - mouseFocusY, c, c );
// draw mouse cursor on screen
bmpCursor->BlitMask( screen, mx - mouseFocusX, my - mouseFocusY,
currentFrame * c, currentCursor * c, c, c );
screen->SetClip( cl );
UnlockScreen();
}
}
}
// turn off mouse cursor
void MouseOff( void )
{
if( on == 0 && LockScreen() == 0 ){
int cl = screen->GetClip( );
screen->SetClip( false );
// erase mouse cursor from screen
bmpWork->Blit( screen, mx - mouseFocusX, my - mouseFocusY, 2 * c, 0, c, c );
screen->SetClip( cl );
UnlockScreen();
}
on --;
}
// draw mouse cursor on screen
static void MouseDrawCursor( void )
{
// Are we need to update cursor ?
if( on < 0 ){
return;
}
int mousePos = ::mousePos;
int mouseX = ( mousePos >> 16 ) & 0xffff;
int mouseY = mousePos & 0xffff;
//printf( "mouseDrawCursor: %d, %d, %d\n", ABS( mouseY - mousePrevY ), mouseY );
if( ABS( mouseX - mx ) >= (int)c || ABS( mouseY - my ) >= (int)c ){
MouseOff();
mx = mouseX; my = mouseY;
MouseOn();
}
else{
if( LockScreen() != 0 )
return;
int cl = screen->GetClip( );
screen->SetClip( false );
//hz.TextOut( screen, 100,0, "in mousedrawcursor", 0xff );
int tx, ty;
tx = MIN( mx, mouseX );
ty = MIN( my, mouseY );
// copy screen to double buffer
screen->Blit( bmpWork, 0, 0, tx - mouseFocusX, ty - mouseFocusY, 2*c, 2*c );
// erase mouse cursor in double buffer
bmpWork->Blit( bmpWork, mx - tx, my - ty, 2*c, 0, c, c );
// save screen
bmpWork->Blit( bmpWork, 2*c, 0, mouseX - tx, mouseY - ty, c, c );
//puts( "in mousedrawCursor" );
// draw mouse cursor in double buffer
bmpCursor->BlitMask( bmpWork, mouseX - tx, mouseY - ty,
currentFrame*c, currentCursor*c, c, c );
// copy double buffer to screen
bmpWork->Blit( screen, tx - mouseFocusX, ty - mouseFocusY, 0, 0, 2*c, 2*c );
screen->SetClip( cl );
mx = mouseX; my = mouseY;
UnlockScreen();
}
}
// we update mouse cursor up to 50 times per second
void MouseTimerHandler( void )
{
DIMOUSESTATE mouseState;
EnterCriticalSection( &dDrawCritical );
lpDIMouse->GetDeviceState( sizeof(mouseState), &mouseState );
mousex += mouseState.lX;
mousey += mouseState.lY;
if( mousex < ml ) mousex = ml;
else if( mousex >= mr ) mousex = mr-1;
if( mousey < mt ) mousey = mt;
else if( mousey >= mb ) mousey = mb-1;
if( ! mouseCursorFroze ){
mouseX = mousex;
mouseY = mousey;
mousePos = ( mousex << 16 ) | mousey;
}
//button
if( mouseState.rgbButtons[0] & 0x80 ) mouseB |= MOUSE_L_DOWN;
//else mouseB &= ~MOUSE_L_DOWN;
if( mouseState.rgbButtons[1] & 0x80 ) mouseB |= MOUSE_R_DOWN;
//else mouseB &= ~MOUSE_R_DOWN;
timer ++;
if( speed && timer >= speed ){
timer = 0;
currentFrame = ( currentFrame + 1 ) % frames;
MouseDrawCursor();
return;
}
if( mouseX != mx || mouseY != my ){
MouseDrawCursor();
}
LeaveCriticalSection( &dDrawCritical );
}
int InitMouse( void )
{
if( mouseInstalled )
return -1;
MouseSetRange( 0, 0, screenInfo.width, screenInfo.height );
bmpCursor = LoadPicture( DEFAULT_MOUSE_CURSOR );
bmpWork = CreateBitmap( DEFAULT_CURSOR_SIZE * 3, DEFAULT_CURSOR_SIZE * 2 );
if( bmpWork == NULL || bmpCursor == NULL
|| bmpCursor->width < DEFAULT_CURSOR_SIZE
|| bmpCursor->height < DEFAULT_CURSOR_SIZE ){
delete bmpCursor;
delete bmpWork;
return -1;
}
// set mouse position
mousex = mouseX = mx = screenInfo.width/2;
mousey = mouseY = my = screenInfo.height/2;
c = DEFAULT_CURSOR_SIZE;
currentCursor = 0;currentFrame = 0;
mouseInstalled = true;
timer = speed = 0;
// frames = 10;
// types = 2;
return 0;
}
void MouseExit( void )
{
if( ! mouseInstalled )
return;
MouseOff();
delete bmpWork;
delete bmpCursor;
mouseX = 0;
mouseY = 0;
mouseB = 0;
mousePos = 0;
mouseInstalled = false;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -