Path: utzoo!utgpu!news-server.csri.toronto.edu!cs.utexas.edu!uwm.edu!ux1.cso.uiuc.edu!uxh.cso.uiuc.edu!mead From: mead@uxh.cso.uiuc.edu (Alan David Mead) Newsgroups: comp.lang.pascal Subject: mouse routines and a problem Keywords: rodnetia Message-ID: <1990Nov3.002032.22360@ux1.cso.uiuc.edu> Date: 3 Nov 90 00:20:32 GMT Sender: news@ux1.cso.uiuc.edu (News) Organization: University of Illinois at Urbana Lines: 372 Here are some routines from Turbo Technix (May/June 1988). If they have been posted previously, I missed them. They simplify programming the mouse. You should get a copy of the article (p52-64?) or a discussion of the results of the mouse functions. Only Microsoft and (really) 100% compatibles are (garrunteed to be) supported except that there are 2 extra Logitech functions. After MOUSE, there is my modified version of the event handler demo that was included in the article. The program is set up for a color monitor (of any type)--change the offset parameter in the MemW array in the procedure handler to $B000 for a monochrome. The code draws a screen and then continuously displays the coordinates of the cursor, clicking every time the cursor moves. Hitting the right button exits the demo. I have been having several problems, here are two: 1) the mouse cursor is specified by character AND attribute, so when you move it from the blue background onto the cyan it doesn't look so hot--to compensate, I thought I'd just a) read the color attribute with mem, b) clear the low bits, and c) redefine the cursor with the new attribute. But on my IBM PS2 55SX, the blue background returns a 7? Also, I fear that I'm over-burdening the event handler (which should be quick, right?). Does anyone know of a better way? 2) Perhaps related to the above (although I don't think so), the cursor sometimes forgets to erase itself as it moves. This results in green or black (or whatever) blocks messing up the display. Is this a timing problem? It is most acute when the cursor is being moved moderately quickly. Any help would be greatly appreciated. One user recommended a book by Microsoft (title similar to _Programming a Mouse_)--has anyone used the book? Is it any good? Thanks in advance. -alan mead : mead@uxh.cso.uiuc ==========[ begin ]=============== unit mouse; Interface (*{$U \tp}*) uses dos; const MDD = $33; type ResetRec = record exists : boolean; { true if mouse installed } nButtons : integer; { number buttons on mouse } end; LocRec = record buttonStatus, { initialized by functions 3 5 & 6 } opCount, { bits 0-2 on if L,R,M button is down } column, row : integer; end; moveRec = record { initialized by function 11 } hCount, { net horizontal movement } vCount : integer; { net vertical movement } end; var reg : registers; { Microsoft mouse functions } procedure mReset( var Mouse:ResetRec ); { function 0 } procedure mShow; { function 1 } procedure mHide; { function 2 } procedure mPos( var Mouse:LocRec ); { function 3 } procedure mMoveTo( col,row:integer ); { function 4 } procedure mPressed( button:integer; var mouse:LocRec ); { function 5 } procedure mReleased( button:integer; var mouse:LocRec ); { function 6 } procedure mColRange( min,max:integer ); { function 7 } procedure mRowRange( min,max:integer ); { function 8 } procedure mGraphCursor( hHot,vHot:integer; { function 9 } MaskSeg,MaskOfs:word ); procedure mTextCursor( cType,p1,p2:word ); { function 10 } procedure mMotion( var moved:moveRec ); { function 11 } procedure mInstTask( mask,TaskSeg,TaskOfs:word ); { function 12 } procedure mLpenOn; { function 13 } procedure mLpenOff; { function 14 } procedure mRatio( horiz,vert:integer ); { function 15 } implementation function Lower( n1,n2:integer ):integer; { local to unit } begin if n1 < n2 then lower := n1 else lower := n2; end; function Upper( n1,n2:integer ):integer; begin if n1 > n2 then Upper := n1 else Upper := n2; end; procedure mReset; begin reg.AX := 0; intr( MDD,reg ); { mouse.exists := ( reg.AX = 0 ); } if reg.AX <> 0 then mouse.exists := TRUE else mouse.exists := FALSE; mouse.nButtons := reg.BX; end; procedure mShow; begin reg.AX := 1; intr( MDD,reg ); end; { mShow } procedure mHide; begin reg.AX := 2; intr( MDD,reg ); end; { mHide } procedure mPos; begin reg.AX := 3; intr( MDD,reg ); mouse.ButtonStatus := reg.BX; mouse.Column := reg.CX; mouse.Row := reg.DX; end; { mPos } procedure mMoveTo; begin reg.AX := 4; reg.CX := col; reg.DX := row; intr( MDD,reg ); end; { mMoveTo } procedure mPressed; begin reg.AX := 5; reg.BX := button; intr( MDD,reg ); mouse.ButtonStatus := reg.AX; mouse.OpCount := reg.BX; mouse.column := reg.CX; mouse.row := reg.DX; end; { mPressed } procedure mReleased; begin reg.AX := 6; reg.BX := button; intr( MDD,reg ); mouse.ButtonStatus := reg.AX; mouse.OpCount := reg.BX; mouse.column := reg.CX; mouse.row := reg.DX; end; {mReleased } procedure mColRange; begin reg.AX := 7; reg.CX := lower( min,max ); reg.DX := upper( min,max ); intr( MDD,reg ); end; { mColRange } procedure mRowRange; begin reg.AX := 8; reg.CX := lower( min,max ); reg.DX := upper( min,max ); intr( MDD,reg ); end; { mRowRange } procedure mGraphCursor; begin reg.AX := 9; reg.BX := hHot; reg.CX := vHot; reg.DX := maskOfs; reg.ES := maskSeg; intr( MDD,reg ); end; { mGraphCursor } procedure mTextCursor; { NOTES: Type 0 is the software cursor. When unspecified, p1 and p2 are the screen and cursor masks. Type 1 is the hardware cursor. When specified, p1 and p2 are the start and stop scan lines, ie the cursor shape. } begin reg.AX := 10; reg.BX := ctype; reg.CX := p1; reg.DX := p2; intr( MDD,reg ); end; { mTextCursor } procedure mMotion; { Net movement since last call } begin { Expressed in mickeys (1/100") } reg.AX := 11; intr( MDD,reg ); moved.hCount := reg.CX; moved.vCount := reg.DX; end; { mMotion } procedure mInstTask; { Install user-defined task } begin reg.AX := 12; reg.CX := mask; reg.DX := taskOfs; reg.ES := taskSeg; intr( MDD,reg ); end; { mInstTask } procedure mLpenOn; { Begin emulation of light pen } begin reg.AX := 14; intr( MDD,reg ); end; { mLpenOn } procedure mLpenOff; { Stop emulating light pen } begin reg.AX := 15; intr( MDD,reg ); end; { mLpenOff } procedure mRatio; { set mickey to pixel ratio } { NOTES: Ratios are R/8. Default is 16 for vertical, 8 for horizontal } begin reg.AX := 15; reg.CX := horiz; reg.DX := vert; intr( MDD,reg ); end; { mRatio } end. ==============[ cut here ]================ program mousevnt; uses dos,crt,mouse; type mEvent = record event , btnStatus, horiz, vert : word; end; var mous : mEvent; t : LocRec; m : resetRec; x,y : byte; procedure handler( Flags,CS,IP,AX,BX,CX,DX,SI,DI,DS,ES,BP : word ); { For speed, I've used inc() to add and SHR | SHL to divide | multiply by powers of two. } interrupt; var attribute:word; AtOffset:word; begin mous.event := AX; mous.btnStatus := BX; mous.horiz := CX; mous.vert := DX; AtOffset := (( 5*mous.vert ) SHL 5 )+( mous.horiz * 2 ) ; attribute := MemW[ $B800:AtOffset ]; attribute := ( attribute SHR 8 ); attribute := ( attribute SHL 8 ); mTextCursor( 0,0,$0040+ attribute ); mous.horiz := mous.horiz SHR 3; { divide by 8. Mouse goes by (graphic) } mous.vert := mous.vert SHR 3; { pixels instead of rows & columns } inc( mous.horiz ); { So that the upper left is 1,1--not 0,0 } inc( mous.vert ); inline( { exit processing and far return from the driver } $8B/$E5/ $5D/ $07/ $1F/ $5F/ $5E/ $5A/ $59/ $5B/ $58/ $CB ); end; begin window( 1,1,80,1 ); textcolor( white ); textBackground( Cyan ); ClrScr; GotoXY( 2,1 ); write( 'MOUSE EVENT-HANDLING DEMO' ); window( 1,25,80,25 ); ClrScr; GotoXY( 17,1 ); write( 'Press right button to quit' ); window( 1,2,80,24 ); TextColor( White ); TextBackground( Blue ); ClrScr; window( 1,1,80,25 ); textbackground( cyan ); { set up rodent } mReset( m ); if m.exists then begin mInstTask( 25,seg( handler ),ofs( Handler )); mous.event := 0; mous.horiz := 0; mous.vert := 0; mShow; mTextCursor( 0,0,$1f40); { white on blue at-symbol } x := 0; y := 0; { Loop to perform demo } repeat mPressed( 4,t ); if ( mous.horiz <> x ) OR ( mous.vert <> y ) then begin x := mous.horiz; y := mous.vert; mHide; Gotoxy( 50,1 ); writeln( 'X= ',mous.horiz:5,', Y= ',mous.vert:5 ); sound( 2000 ); delay( 5 ); nosound; mShow; end; until t.ButtonStatus = 2 ; GotoXY( 50,1 ); writeln( 'Good bye ! ' ); { Clean up and quit } mHide; mReset( m ); end; { ClrScr; } end. ======================[ end ]======================== -- Alan Mead : mead@uxh.cso.uiuc.edu