上面2篇文章《Turbo C使用的汇编函数 -- VGA 12H模式图形函数(一)》和《Turbo C使用的汇编函数 -- VGA 12H模式图形函数(一)》给出了图形代码,本篇给出鼠标管理TC函数汇编码文件。该代码很简单,而且对速度没很高的要求,完全可用纯C/C++写,但是在DOS年代,即使速度稍有提高以及代码长度缩短,也愿意用汇编码或插入汇编;鼠标功能使用int 33h,要在程序中使用鼠标,必须安装鼠标驱动程序(指纯DOS环境),鼠标驱动一般有2种形式,一是mouse.sys,必须在DOS下的config.sys文件中安装:device=mouse.sys,另外一种是mouse.com,不必在config.sys中安装,在autoexec.bat或者其它批命令文件或者直接在DOS命令行中运行后,以TSR形式驻留内存。
#ifndef __MOUSE__
#define __MOUSE__
extern int MouseFlag;
#ifdef __cplusplus
extern " C " {
#endif
/* 初始化, 如鼠标存在, MouseFlag = 1, 否则 MouseFlag = 0, 返回该值 */
int Mouse_Init( void );
/* 置鼠标位置到 X, Y */
void Mouse_SetXY( int x, int y);
/* 取鼠标当前位置到 X, Y */
void Mouse_GetXY( int * x, int * y);
/* 打开鼠光标 */
void Mouse_Show( void );
/* 关闭鼠光标 */
void Mouse_Hide( void );
/* 如鼠光标在坐标(x1, y1) - (x2, y2)内返回 1, 否则返回 0 */
int Mouse_InBox( int x1, int y1, int x2, int y2);
/* 取按钮按下信息 b = 0 左按钮, b = 1 右按钮, b = 2 中按钮 */
int Mouse_Press( int b);
/* 取按钮放开信息 b = 0 左按钮, b = 1 右按钮, b = 2 中按钮 */
int Mouse_Rel( int b);
/* 返回当前按钮状态, 有按钮按下返回非 0, 否则返回 0 */
int Mouse_State( void );
/* 设置鼠光标类型, X, Y 为光标热点, Pattern 为光标点阵地址 */
void Mouse_SetCursor( int X, int Y, void far * Pattern);
#ifdef __cplusplus
}
#endif
#endif
include tasm_c.inc
DATASEG
PUBLIC _MouseFlag
_MouseFlag dw 0
MouseCurFlag dw 0
CODESEG
PUBLIC _Mouse_Init
PUBLIC _Mouse_SetXY
PUBLIC _Mouse_GetXY
PUBLIC _Mouse_Show
PUBLIC _Mouse_Hide
PUBLIC _Mouse_State
PUBLIC _Mouse_Press
PUBLIC _Mouse_Rel
PUBLIC _Mouse_InBox
PUBLIC _Mouse_SetCursor
;
; Mouse_Init( void )
;
PROC _Mouse_Init
cmp [word _MouseFlag], 0
jne @@ 1
xor ax, ax
int 33h
cmp ax, 0
je @@ 1
mov [_MouseFlag], bx
xor cx, cx
xor dx, dx
mov ax, 4
int 33h
@@ 1 :
mov ax, [_MouseFlag]
ret
ENDP
;
; void Mouse_SetXY( int x, int y)
;
PROC _Mouse_SetXY
ARG x : word, y : word
mov cx, [x]
mov dx, [y]
mov ax, 3
int 33h
ret
ENDP
;
; void Mouse_GetXY( int * x, int * y)
;
PROC _Mouse_GetXY
ARG x : DPTR_, y : DPTR_
mov ax, 3
int 33h
LES_ bx, [x]
mov [ES_ bx], cx
LES_ bx, [y]
mov [ES_ bx], dx
ret
ENDP
;
; void Mouse_Show( void )
;
PROC _Mouse_Show
cmp [word _MouseFlag], 0
je @@ 1
cmp [word MouseCurFlag], 0
jne @@ 1
mov ax, 1
int 33h
mov [word MouseCurFlag], 1
@@ 1 :
ret
ENDP
;
; void Mouse_Hide( void )
;
PROC _Mouse_Hide
cmp [word _MouseFlag], 0
je @@ 1
cmp [word MouseCurFlag], 0
je @@ 1
mov ax, 2
int 33h
mov [word MouseCurFlag], 0
@@ 1 :
ret
ENDP
;
; void Mouse_SetCursor( int x, int y, void far * prttern)
;
PROC _Mouse_SetCursor
ARG x : word, y : word, prttern : far ptr
mov ax, 9
mov bx, [x]
mov cx, [y]
les dx, [dword prttern]
int 33h
ret
ENDP
;
; int Mouse_State( void )
;
PROC _Mouse_State
mov ax, 3
int 33h
mov ax, bx
ret
ENDP
;
; int Mouse_Press( int b)
;
PROC _Mouse_Press
ARG b : word
mov ax, 5
mov bx, [b]
int 33h
mov ax, bx
ret
ENDP
;
; int Mouse_Rel( int b)
;
PROC _Mouse_Rel
ARG b : word
mov ax, 6
mov bx, [b]
int 33h
mov ax, bx
ret
ENDP
;
; int Mouse_InBox( int x1, int y1, int x2, int y2)
;
PROC _Mouse_InBox
ARG x1 : word, y1 : word, x2 : word, y2 : word
mov ax, [_MouseFlag]
cmp ax, 0
je @@ 3
mov ax, 3
int 33h
xor ax, ax
mov bx, [x1]
cmp bx, [x2]
jle @@ 1
xchg bx, [x2]
@@ 1 :
cmp cx, bx
jl @@ 3
cmp cx, [x2]
jg @@ 3
mov bx, [y1]
cmp bx, [y2]
jle @@ 2
xchg bx, [y2]
@@ 2 :
cmp dx, bx
jl @@ 3
cmp dx, [y2]
jg @@ 3
mov ax, 1
@@ 3 :
ret
ENDP
;
END
上面的文件中使用的插入文件tasm_c.inc和编译文件在《Turbo C使用的汇编函数 -- VGA 12H模式图形函数(一)》中,鼠标函数也可由C++(Trubo C++或者Borland C++)直接调用。如果有人喜欢OO,正好我发现还有个C++的鼠标汇编文件,一并贴在下面供参考,不过其中的函数都是static的:
#ifndef __MOUSE_HPP
#define __MOUSE_HPP
const int
// 定义鼠标按钮状态常量
MO_LEFT_PRESS = - 256 , // 左边按钮按下
MO_RIGHT_PRESS = - 257 , // 右边按钮按下
MO_LEFT_REL = - 258 , // 左边按钮放开
MO_RIGHT_REL = - 259 , // 右边按钮放开
MO_LEFT_DOUBLE = - 260 , // 左边按钮双击
MO_RIGHT_DOUBLE = - 261 , // 右边按钮双击
MO_STATE = - 262 ; // 鼠标拖动
class Mouse
{
public :
// 初始化, 如鼠标存在, 返回 1, 否则返回 0
static int Init( void );
// 置鼠标位置到 X, Y
static void SetXY( int x, int y);
// 返回鼠光标当前的位置
static void GetXY( int & x, int & y );
// 返回鼠标驱动程序安装状态, 1 已安装, 0 未安装
static int DriveFlag();
// 打开鼠光标
static void Show( void );
// 关闭鼠光标
static void Hide( void );
// 如鼠光标在坐标(x1, y1) - (x2, y2)内返回 1, 否则返回 0
static int InBox( int x1, int y1, int x2, int y2);
// 如鼠光标在文本坐标(Row1, Col1) - (Row2, Col2)内返回 1, 否则返回 0
static int InTextBox( int Row1, int Col1, int Row2, int Col2);
// 设置鼠光标类型, X, Y 为光标热点, Pattern 为光标点阵地址
static void SetCursor( int X, int Y, void far * Pattern);
// 返回鼠标按钮状态, 如鼠标不存在或未动作, 返回 0, 否则返回状态值(见状态常量)
static int GetMouse();
};
#endif
下面是鼠标功能C++函数汇编码文件,其中可以看到C++函数名称管理的方式,这个文件没包括在《Turbo C使用的汇编函数 -- VGA 12H模式图形函数(一)》的MAKEFILE中,必须单独编译:
include tasm_c.inc
MO_LEFT_PRESS equ - 256
MO_RIGHT_PRESS equ - 257
MO_LEFT_REL equ - 258
MO_RIGHT_REL equ - 259
MO_LEFT_DOUBLE equ - 260
MO_RIGHT_DOUBLE equ - 261
MO_STATE equ - 262
PUBLIC @Mouse@Init$qv
PUBLIC @Mouse@SetXY$qii
PUBLIC @Mouse@Show$qv
PUBLIC @Mouse@Hide$qv
PUBLIC @Mouse@InBox$qiiii
PUBLIC @Mouse@InTextBox$qiiii
PUBLIC @Mouse@SetCursor$qiinv
PUBLIC @Mouse@GetMouse$qv
PUBLIC @Mouse@DriveFlag$qv
IF LDATA
PUBLIC @Mouse@GetXY$qmit1
ELSE
PUBLIC @Mouse@GetXY$qrit1
ENDIF
DATASEG
MouseFlag dw 0
MouseCurFlag dw 0
MouseTime dd 0
CODESEG
PROC @Mouse@Init$qv
mov ax, [word MouseFlag]
or ax, ax
jnz @@ 1
int 33h
or ax, ax
jz @@ 1
xor cx, cx
xor dx, dx
mov ax, 4
int 33h
mov ax, 1
mov [MouseFlag], ax
@@ 1 :
ret
ENDP
PROC @Mouse@SetXY$qii
ARG x : word, y : word
cmp [word MouseFlag], 0
je @@ 1
mov cx, [x]
mov dx, [y]
mov ax, 4
int 33h
@@ 1 :
ret
ENDP
PROC @Mouse@Show$qv
cmp [word MouseFlag], 0
je @@ 1
cmp [word MouseCurFlag], 0
jne @@ 1
mov ax, 1
int 33h
mov [word MouseCurFlag], 1
@@ 1 :
ret
ENDP
PROC @Mouse@Hide$qv
cmp [word MouseFlag], 0
je @@ 1
cmp [word MouseCurFlag], 0
je @@ 1
mov ax, 2
int 33h
mov [word MouseCurFlag], 0
@@ 1 :
ret
ENDP
PROC @Mouse@SetCursor$qiinv
ARG x : word, y : word, prttern : far ptr
cmp [word MouseFlag], 0
je @@ 1
mov ax, 9
mov bx, [x]
mov cx, [y]
les dx, [dword prttern]
int 33h
@@ 1 :
ret
ENDP
PROC @Mouse@InBox$qiiii
ARG x1 : word, y1 : word, x2 : word, y2 : word
cmp [word MouseFlag], 0
jz @@ 3
mov ax, 3
int 33h
mov ax, [x2]
mov bx, [x1]
cmp bx, ax
jle @@ 1
xchg bx, ax
@@ 1 :
cmp bx, cx
jg @@ 3
cmp ax, cx
jl @@ 3
mov ax, [y2]
mov bx, [y1]
cmp bx, ax
jle @@ 2
xchg bx, ax
@@ 2 :
cmp bx, dx
jg @@ 3
cmp ax, dx
jl @@ 3
mov ax, 1
jmp short @@ 4
@@ 3 :
xor ax, ax
@@ 4 :
ret
ENDP
PROC @Mouse@InTextBox$qiiii
ARG Row1 : word, Col1 : word, Row2 : word, Col2 : word
cmp [MouseFlag], 0
jz @@ 3
mov ax, 3
int 33h
mov bx, cx
mov ax, [Row2]
cmp ax, [Row1]
jge @@ 1
xchg ax, [Row1]
@@ 1 :
mov cl, 3
shl ax, cl
add ax, 7
cmp ax, dx
jl @@ 3
mov ax, [Row1]
shl ax, cl
cmp ax, dx
jg @@ 3
mov ax, [Col2]
cmp ax, [Col1]
jge @@ 2
xchg ax, [Col1]
@@ 2 :
shl ax, cl
add ax, 7
cmp ax, bx
jl @@ 3
mov ax, [Col1]
shl ax, cl
cmp ax, bx
jg @@ 3
mov ax, 1
jmp short @@ 4
@@ 3 :
xor ax, ax
@@ 4 :
ret
ENDP
IF LDATA
PROC @Mouse@GetXY$qmit1
ELSE
PROC @Mouse@GetXY$qrit1
ENDIF
ARG x : DPTR_, y : DPTR_
mov ax, 3
int 33h
LES_ bx, [x]
mov [ES_ bx], cx
LES_ bx, [y]
mov [ES_ bx], dx
ret
ENDP
PROC @Mouse@DriveFlag$qv
mov ax, [MouseFlag]
ret
ENDP
PROC @Mouse@GetMouse$qv
mov ax, [MouseFlag]
or ax, ax
jz @@ 5
xor bx, bx
mov ax, 5
int 33h
mov ax, MO_LEFT_PRESS
or bx, bx
jnz @@ 3
mov bx, 1
mov ax, 5
int 33h
mov ax, MO_RIGHT_PRESS
or bx, bx
jnz @@ 3
xor bx, bx
mov ax, 6
int 33h
or bx, bx
jz @@ 1
mov ax, MO_LEFT_REL
jmp short @@ 5
@@ 1 :
mov bx, 1
mov ax, 6
int 33h
jz @@ 2
mov ax, MO_RIGHT_REL
jmp short @@ 5
@@ 2 :
mov ax, 3
int 33h
xor ax, ax
test bx, 3
jz @@ 5
mov ax, MO_STATE
jmp short @@ 5
@@ 3 :
push ax
mov ah, 2ch
int 21h
pop ax
sub dx, [word MouseTime]
sbb cx, [word MouseTime + 2 ]
or cx, cx
jnz @@ 4
cmp dx, 30
jg @@ 4
sub ax, 4
mov [word MouseTime], cx
mov [word MouseTime + 2 ], cx
jmp short @@ 5
@@ 4 :
add [word MouseTime], dx
adc [word MouseTime + 2 ], cx
@@ 5 :
ret
ENDP
;
END
下一篇给出一个XMS内存管理文件代码。
再次声明,这几篇文章的代码是1995年前的东西,用现在的眼光去看它们,还不知道是不是C函数,只能供初学者们借鉴参考。至于是否有错误,我就不得而知了,不过,我以前使用时,没出过什么问题。有错误或建议,请来信:maozefa@hotmail.com