返回
{***************************************************************}
{*** FVision Unit Version1.0 ***}
{*** 蓝蚂蚁工作室 ***}
{***************************************************************}
{*** 事件处理单元 ***}
{***************************************************************}
{$F+,X+,I-,S-}
Unit FEvent;
Interface
Uses
Dos,Crt,FMouse,FTool,FGraph;
{ ******** EVENT MANAGER ******** }
const
{ Safe Memory }
SafeMem=50000;
{ Event codes }
evMouseDown = $0001;
evMouseUp = $0002;
evMouseMove = $0004;
evMouseAuto = $0008;
evKeyDown = $0010;
evCommand = $0100;
evBroadcast = $0200;
{ Event masks }
evNothing = $0000;
evMouse = $000F;
evKeyboard = $0010;
evMessage = $FF00;
{ Extended key codes }
kbSpace = $3920; {57 32}
kbEsc = $011B; kbAltSpace = $0200; kbCtrlIns = $0400;
kbShiftIns = $0500; kbCtrlDel = $0600; kbShiftDel = $0700;
kbBack = $0E08; kbCtrlBack = $0E7F; kbShiftTab = $0F00;
kbTab = $0F09; kbAltQ = $1000; kbAltW = $1100;
kbAltE = $1200; kbAltR = $1300; kbAltT = $1400;
kbAltY = $1500; kbAltU = $1600; kbAltI = $1700;
kbAltO = $1800; kbAltP = $1900; kbCtrlEnter = $1C0A;
kbEnter = $1C0D; kbAltA = $1E00; kbAltS = $1F00;
kbAltD = $2000; kbAltF = $2100; kbAltG = $2200;
kbAltH = $2300; kbAltJ = $2400; kbAltK = $2500;
kbAltL = $2600; kbAltZ = $2C00; kbAltX = $2D00;
kbAltC = $2E00; kbAltV = $2F00; kbAltB = $3000;
kbAltN = $3100; kbAltM = $3200; kbF1 = $3B00;
kbF2 = $3C00; kbF3 = $3D00; kbF4 = $3E00;
kbF5 = $3F00; kbF6 = $4000; kbF7 = $4100;
kbF8 = $4200; kbF9 = $4300; kbF10 = $4400;
kbHome = $4700; kbUp = $4800; kbPgUp = $4900;
kbGrayMinus = $4A2D; kbLeft = $4B00; kbRight = $4D00;
kbGrayPlus = $4E2B; kbEnd = $4F00; kbDown = $5000;
kbPgDn = $5100; kbIns = $5200; kbDel = $5300;
kbShiftF1 = $5400; kbShiftF2 = $5500; kbShiftF3 = $5600;
kbShiftF4 = $5700; kbShiftF5 = $5800; kbShiftF6 = $5900;
kbShiftF7 = $5A00; kbShiftF8 = $5B00; kbShiftF9 = $5C00;
kbShiftF10 = $5D00; kbCtrlF1 = $5E00; kbCtrlF2 = $5F00;
kbCtrlF3 = $6000; kbCtrlF4 = $6100; kbCtrlF5 = $6200;
kbCtrlF6 = $6300; kbCtrlF7 = $6400; kbCtrlF8 = $6500;
kbCtrlF9 = $6600; kbCtrlF10 = $6700; kbAltF1 = $6800;
kbAltF2 = $6900; kbAltF3 = $6A00; kbAltF4 = $6B00;
kbAltF5 = $6C00; kbAltF6 = $6D00; kbAltF7 = $6E00;
kbAltF8 = $6F00; kbAltF9 = $7000; kbAltF10 = $7100;
kbCtrlPrtSc = $7200; kbCtrlLeft = $7300; kbCtrlRight = $7400;
kbCtrlEnd = $7500; kbCtrlPgDn = $7600; kbCtrlHome = $7700;
kbAlt1 = $7800; kbAlt2 = $7900; kbAlt3 = $7A00;
kbAlt4 = $7B00; kbAlt5 = $7C00; kbAlt6 = $7D00;
kbAlt7 = $7E00; kbAlt8 = $7F00; kbAlt9 = $8000;
kbAlt0 = $8100; kbAltMinus = $8200; kbAltEqual = $8300;
kbCtrlPgUp = $8400; kbAltBack = $0800; kbNoKey = $0000;
kbCtrlA = $1E01; kbCtrlB = $3002; kbCtrlC = $2E03;
kbCtrlD = $2004; kbCtrlE = $1205; kbCtrlF = $2106;
kbCtrlG = $2207; kbCtrlH = $2308; kbCtrlI = $1709;
kbCtrlJ = $240A; kbCtrlK = $250B; kbCtrlL = $260C;
kbCtrlM = $320D; kbCtrlN = $310E; kbCtrlO = $180F;
kbCtrlP = $1910; kbCtrlQ = $1011; kbCtrlR = $1312;
kbCtrlS = $1F13; kbCtrlT = $1414; kbCtrlU = $1615;
kbCtrlV = $2F16; kbCtrlW = $1117; kbCtrlX = $2018;
kbCtrlY = $1519; kbCtrlZ = $2C1A;
{ Keyboard state and shift masks }
kbRightShift = $0001;
kbLeftShift = $0002;
kbCtrlShift = $0004;
kbAltShift = $0008;
kbScrollState = $0010;
kbNumState = $0020;
kbCapsState = $0040;
kbInsState = $0080;
kbDoubleShift = $0003;
{ Mouse button state masks }
mbLeftButton = $01;
mbRightButton = $02;
btNormal = $10;
btHelp = $20;
{ Const Command }
cmValid = 0;
cmQuit = 1;
cmError = 2;
cmMenu = 3;
cmClose = 4;
cmZoom = 5;
cmResize = 6;
cmNext = 7;
cmPrev = 8;
cmHelp = 9;
{ TDialog standard commands }
cmOK = 10;
cmCancel = 11;
cmYes = 12;
cmNo = 13;
cmRetry = 14;
cmAbort = 15;
cmIgnore = 16;
cmReset = 17;
cmInsert = 18;
cmDelete = 19;
{ Application command codes }
cmCut = 20;
cmCopy = 21;
cmPaste = 22;
cmUndo = 23;
cmClear = 24;
cmTile = 25;
cmCascade = 26;
cmTimer = 27;
cmInputS = 28;
cmChange = 29;
{ Standard application commands }
cmNew = 30;
cmOpen = 31;
cmSave = 32;
cmSaveAs = 33;
cmSaveAll = 34;
cmChangeDir = 35;
cmDosShell = 36;
cmCloseAll = 37;
cmStop = 38;
cmTest = 39;
{ Edit Code }
cmLeft = 40;
cmRight = 41;
cmUp = 42;
cmDown = 43;
cmInterHor = 44;
cmInterVer = 45;
cmHome = 46;
cmEnd = 47;
cmPgUp = 48;
cmPgDn = 49;
cmCtrlHome = 50;
cmCtrlEnd = 51;
cmCtrlPgUp = 52;
cmCtrlPgDn = 53;
cmInterDouble = 54;
cmInterHit = 55;
cmMove = 56;
cmSearch = 57;
cmReplace = 58;
cmSearchAgain = 59;
{ View Code }
cmCloseWin = 60;
cmOkDown = 61;
cmPrevWin = 62;
cmNextWin = 63;
cmButtonDown = 64;
cmRButtonDown = 65;
cmEditLeft = 66;
cmEditRight = 67;
cmEditUp = 68;
cmEditDown = 69;
{ Dialog Code }
cmOpenFile = 70;
cmMemory = 71;
cmPaintAll = 72;
cmAbout = 73;
cmSaveFile = 74;
cmSelectFile = 75;
cmChkSelect = 76;
cmNewDirectory= 77;
cmDriver = 78;
cmInformation = 79;
{ Menu Code }
cmIndex = 80;
cmTopicSearch = 81;
cmPrevTopic = 82;
cmLeftMenu = 83;
cmRightMenu = 84;
{ Stand Error Code }
cmRunTimeError= 90;
cmOutOfMemory = 91;
cmChangeStatu = 100;
cmChangeIndex = 101;
cmCopyToClip = 110;
cmPasteFromClip = 111;
cmShowClip = 112;
cmSearchStr = 113;
cmSelect = 114;
cmGotoLine = 115;
cmEnterPress = 116;
cmPlay = 120;
cmHead = 121;
cmTail = 122;
Type
String30=string[30];
{ Event record }
TPoint=record
X,Y:Integer;
end;
TRect=object
A,B:TPoint;
end;
PEvent = ^TEvent;
TEvent = record
What: Word;
case Word of
evNothing: ();
evMouse: (
Buttons: Byte;
Double: Boolean;
Where: TPoint);
evKeyDown: (
CMark: Boolean;
case Integer of
0: (KeyCode: Word);
1: (CharCode: Char;
ScanCode: Byte);
2: (HiCode,LoCode:Char));
evMessage: (
Index :Pointer;
Command: Word;
case Word of
0: (InfoPtr : Pointer);
1: (InfoLong : Longint);
2: (InfoWord : Word);
3: (InfoInt : Integer);
4: (InfoByte : Byte);
5: (InfoChar : Char);
6: (InfoReal : Real);
7: (InfoPoint: TPoint));
end;
const
{ Initialized variables }
ButtonCount: Byte = 0;
MouseEvents: Boolean = False;
MouseReverse: Boolean = False;
DoubleDelay: Word = 30;
RepeatDelay: Word = 30;
CtrlBreakHit: Boolean = False;
CritErrorFlag:Boolean = False;
var
{ Uninitialized variables }
MouseIntFlag: Byte;
MouseButtons: Byte;
MouseWhere: TPoint;
Event:TEvent;
{ Event manager routines }
Procedure InitEvent;
Procedure DoneEvent;
Procedure AssignRect(Var R:TRect; X1,Y1,X2,Y2:Integer);
Function IsIn(A:TPoint;P:TRect):Boolean;
Function MouIn(P:TRect):Boolean;
Function IsPosIn(Pos,Pa,Pb:TPoint):Boolean;
Function GetShiftState: Byte;
Function ShiftPush: Boolean;
Procedure GetEvent(var Event:TEvent);
Function GetcLen(S:string):Integer;
{ Keyboard support routines }
function GetAltChar(KeyCode: Word): Char;
function GetAltCode(Ch: Char): Word;
function GetCtrlChar(KeyCode: Word): Char;
function GetCtrlCode(Ch: Char): Word;
Implementation
Uses
FMenu;
var
{ Event manager variables }
LastButtons: Byte;
DownButtons: Byte;
LastDouble: Boolean;
Mx,My:Integer;
LastWhere: TPoint;
DownWhere: TPoint;
DownTicks: Word;
AutoTicks: Word;
AutoDelay: Word;
EventCount: Word;
var
ShiftState: Byte absolute $40:$17;
Ticks: Word absolute $40:$6C;
var
OldCritInt,OldBreakInt:Pointer;
Hourf,Minutef,Secondf,Sec100f:Word;
procedure ResetTime;
begin
GetTime(Hourf,Minutef,Secondf,Sec100f);
end;
function Time:Longint;
var
Hour,Minute,Second,Sec100:Word;
Time_Now:Longint;
begin
GetTime(Hour,Minute,Second,Sec100);
Time_Now:=Longint(Sec100+Second*100+Minute*6000)
-Longint(Sec100f+Secondf*100+Minutef*6000);
while Time_Now<0 do Inc(Time_Now,6000);
Time:=Time_Now;
end;
Procedure AssignRect(Var R:TRect; X1,Y1,X2,Y2:Integer);
Begin
R.A.X:=X1;
R.A.Y:=Y1;
R.B.X:=X2;
R.B.Y:=Y2;
end;
function IsPosIn(Pos,Pa,Pb:TPoint):Boolean;
begin
IsPosIn:=PosIn(Pos.x,Pos.y,Pa.x,Pa.y,Pb.x,Pb.y);
end;
function IsIn(A:TPoint;P:TRect):Boolean;
begin
IsIn:=PosIn(A.x,A.y,P.a.x,P.a.y,P.b.x,P.b.y);
end;
function MouIn(P:TRect):Boolean;
var
T:TRect;
begin
Dec(P.a.x,16);
Dec(P.a.y,16);
MouIn:=IsIn(LastWhere,P);
end;
const
SCriticalError: string[29] = 'Critical disk error on drive ';
SWriteProtected: string[33] = 'Disk is write-protected in drive ';
SDiskNotReady: string[27] = 'Disk is not ready in drive ';
SDataIntegrity: string[30] = 'Data integrity error on drive ';
SSeekError: string[20] = 'Seek error on drive ';
SUnknownMedia: string[28] = 'Unknown media type in drive ';
SSectorNotFound: string[26] = 'Sector not found on drive ';
SOutOfPaper: string[20] = 'Printer out of paper';
SWriteFault: string[21] = 'Write fault on drive ';
SReadFault: string[20] = 'Read fault on drive ';
SGeneralFailure: string[26] = 'Hardware failure on drive ';
SBadImageOfFAT: string[32] = 'Bad memory image of FAT detected';
SDeviceError: string[19] = 'Device access error';
SInsertDisk: string[25] = 'Insert diskette in drive ';
SRetryOrCancel: string[27] = '~Enter~ Retry ~Esc~ Cancel';
{$V-}
function SystemError(ErrorCode: Integer; Drive: Byte): Integer;
var
Ch:Char;
TempStr:string;
begin
case ErrorCode of
0 :TempStr:=SWriteProtected;
1 :TempStr:=SCriticalError;
2 :TempStr:=SDiskNotReady;
3 :TempStr:=SCriticalError;
4 :TempStr:=SDataIntegrity;
5 :TempStr:=SCriticalError;
6 :TempStr:=SSeekError;
7 :TempStr:=SUnknownMedia;
8 :TempStr:=SSectorNotFound;
9 :TempStr:=SOutOfPaper;
10:TempStr:=SWriteFault;
11:TempStr:=SReadFault;
12:TempStr:=SGeneralFailure;
13:TempStr:=SBadImageOfFAT;
14:TempStr:=SDeviceError;
15:TempStr:=SInsertDisk;
else TempStr:='Unknown Error in drive ';
end;
Insert(#1'Critical Error '+IntStr(ErrorCode)+':',TempStr,1);
if ErrorCode in [9,13,14] then
begin
TempStr:=TempStr+#0;
SystemError:=0;
StatusLine^.SwapLine(TempStr);
CritErrorFlag:=True;
Exit;
end;
TempStr:=TempStr+Chr(Ord('A')+Drive)+#0+SRetryOrCancel+#0;
StatusLine^.SwapLine(TempStr);
repeat
Ch:=Readkey;
if Ch=#0 then Ch:=ReadKey;
until (Ch=#13)or(Ch=#27);
if Ch=#13 then
SystemError:=1
else
SystemError:=0;
StatusLine^.SwapLine(TempStr);
end;
{$V+}
procedure NewCritInt(Flags,CS,IP,AX,BX,CX,DX,SI,DI,DS,ES,BP:Word);interrupt;
var
ErrorCode:Byte;
begin
ErrorCode:=Lo(DI);
if (AX and $8000)<>0 then
begin
ErrorCode:=13;
if (Mem[BP:SI+5] and $80)<>0 then Inc(ErrorCode);
end;
AX:=(AX and $FF00)+Lo(SystemError(ErrorCode,Lo(AX)));
if Lo(AX)=0 then Flags:=Flags or 1;
end;
procedure NewBreakInt(Flags,CS,IP,AX,BX,CX,DX,SI,DI,DS,ES,BP:Word);interrupt;
begin
CtrlBreakHit:=True;
end;
procedure InstallNewInt;
begin
GetIntVec($24,OldCritInt);
SetIntVec($24,@NewCritInt);
GetIntVec($1B,OldBreakInt);
SetIntVec($1B,@NewBreakInt);
end;
procedure InitEvent;
begin
LastButtons:=0;
LastDouble:=False;
ResetTime;
ShiftState:=ShiftState or kbInsState;
InstallNewInt;
CtrlBreakHit:=False;
end;
procedure DoneEvent;
begin
SetIntVec($24,OldCritInt);
SetIntVec($1B,OldBreakInt);
end;
procedure GetMouseEvent(var Event: TEvent);
begin
if not MouseGood then Exit;
GetPosition(DownButtons,Mx,My);
DownWhere.x:=Mx;
DownWhere.y:=My;
if (DownButtons<>0) and (LastButtons=0)
and LastDouble and (Time<DoubleDelay) then
begin
Event.What:=evMouseDown;
Event.Buttons:=DownButtons;
Event.Double:=True;
Event.Where:=DownWhere;
LastDouble:=False;
LastButtons:=DownButtons;
LastWhere:=DownWhere;
end else
if (DownButtons=LastButtons) and (DownButtons<>0)
and (LastWhere.x=Mx) and (LastWhere.y=My)
and (Time>RepeatDelay) then
begin
Event.What:=evMouseAuto;
Event.Buttons:=DownButtons;
Event.Double:=False;
Event.Where:=DownWhere;
LastDouble:=False;
LastButtons:=DownButtons;
LastWhere:=DownWhere;
end else
if (LastButtons=0) and(DownButtons<>0) and
(LastWhere.x=Mx) and (LastWhere.y=My) then
begin
Event.What:=evMouseDown;
Event.Buttons:=DownButtons;
Event.Double:=False;
Event.Where:=DownWhere;
LastButtons:=DownButtons;
LastWhere:=DownWhere;
ResetTime;
LastDouble:=False;
end else
if (LastButtons<>0) and (DownButtons=0) then
begin
Event.What:=evMouseUp;
Event.Buttons:=LastButtons;
Event.Double:=False;
Event.Where:=DownWhere;
LastButtons:=DownButtons;
LastWhere:=DownWhere;
if Time<DoubleDelay then
LastDouble:=True
else
LastDouble:=False;
end else
if (LastWhere.x<>Mx) or (LastWhere.y<>My) then
begin
Event.What:=evMouseMove;
Event.Buttons:=DownButtons;
Event.Double:=False;
Event.Where:=DownWhere;
LastButtons:=DownButtons;
LastWhere:=DownWhere;
end;
end;
procedure ConvertEvent(var Event: TEvent);
begin
if (Event.KeyCode=$5200)or(Event.KeyCode=$5300)or
(Event.KeyCode=$52E0)or(Event.KeyCode=$53E0) then
begin
if (ShiftState and $03 <> 0) then
begin
if (Event.KeyCode=$5200)or(Event.KeyCode=$52E0) then
Event.KeyCode:=$0500
else
Event.KeyCode:=$0700;
end;
end else
if (Event.KeyCode=$9200)or(Event.KeyCode=$9300)or
(Event.KeyCode=$92E0)or(Event.KeyCode=$93E0) then
begin
if (ShiftState and $04 <> 0) then
begin
if (Event.KeyCode=$9200)or(Event.KeyCode=$92E0) then
Event.KeyCode:=$0400
else
Event.KeyCode:=$0600;
end;
end;
end;
procedure GetKeyEvent(var Event: TEvent);
var
Regs:Registers;
begin
Regs.AH:=$00;
Intr($16,Regs);
Event.What:=evKeyDown;
Event.CMark:=False;
Event.KeyCode:=Regs.AX;
ConvertEvent(Event);
end;
procedure GetEvent(var Event:TEvent);
begin
if KeyPressed then
GetKeyEvent(Event)
else
GetMouseEvent(Event);
end;
{
function GetKeyEvent:Word;assembler;
asm
mov ah,01h
int 16h
jz @@1
mov ah,00h
int 16h
jmp @@3
@@1:mov ah,11h
int 16h
jz @@2
mov ah,10h
int 16h
jmp @@3
@@2:mov ax,00h
@@3:
end;
procedure GetEvent(var Event:TEvent);
var
Key:Word;
begin
Key:=GetKeyEvent;
if Key<>0 then
begin
Event.What:=evKeyDown;
Event.KeyCode:=Key;
Event.CMark:=False;
ConvertEvent(Event);
end
else
GetMouseEvent(Event);
end;
}
Function GetShiftState: Byte; assembler;
asm
MOV ES,Seg0040
MOV AL,ES:ShiftState
end;
Function ShiftPush: Boolean; assembler;
asm
MOV ES,Seg0040
MOV AL,ES:ShiftState
AND AL,03H
end;
{$V+}
{ ******** UTILITY ROUTINES ******** }
function GetcLen(S:string):Integer;
var
i,j:Integer;
begin
i:=0;
for j:=1 to Length(S) do
if S[j]<>'~' then Inc(i);
GetcLen:=i;
end;
{ Keyboard support routines }
const
AltCodes1: array[$10..$32] of Char =
'QWERTYUIOP'#0#0#0#0'ASDFGHJKL'#0#0#0#0#0'ZXCVBNM';
AltCodes2: array[$78..$83] of Char =
'1234567890-=';
function GetAltChar(KeyCode: Word): Char;
begin
GetAltChar := #0;
if Lo(KeyCode) = 0 then
case Hi(KeyCode) of
$02: GetAltChar := #240;
$10..$32: GetAltChar := AltCodes1[Hi(KeyCode)];
$78..$83: GetAltChar := AltCodes2[Hi(KeyCode)];
end;
end;
function GetAltCode(Ch: Char): Word;
var
I: Word;
begin
GetAltCode := 0;
if Ch = #0 then Exit;
Ch := UpCase(Ch);
if Ch = #240 then
begin
GetAltCode := $0200;
Exit;
end;
for I := $10 to $32 do
if AltCodes1[I] = Ch then
begin
GetAltCode := I shl 8;
Exit;
end;
for I := $78 to $83 do
if AltCodes2[I] = Ch then
begin
GetAltCode := I shl 8;
Exit;
end;
end;
function GetCtrlChar(KeyCode: Word): Char;
begin
GetCtrlChar := #0;
if (Lo(KeyCode) <> 0) and (Lo(KeyCode) <= Byte('Z') - Byte('A') + 1) then
GetCtrlChar := Char(Lo(KeyCode) + Byte('A') - 1);
end;
function GetCtrlCode(Ch: Char): Word;
begin
GetCtrlCode := GetAltCode(Ch) or (Byte(UpCase(Ch)) - Byte('A') + 1);
end;
end.