上面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形式驻留内存。
/*
mouse.h
*/
#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
; mouse.asm
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的:
//
mouse.hpp
#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中,必须单独编译:
; mouse.asm
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函数,只能供初学者们借鉴参考。至于是否有错误,我就不得而知了,不过,我以前使用时,没出过什么问题。有错误或建议,请来信:[email protected]