How to Trap CTRL+C and CTRL+BREAK KeystrokesLast reviewed: July 17, 1997Article ID: Q86558 |
5.10 6.00 6.00a 6.00ax 7.00 | 1.00 1.50
MS-DOS | WINDOWSkbprg The information in this article applies to:
SUMMARYThe program below demonstrates how to revector interrupts to your own service routine. Also, it shows how to stop the ^C character from appearing on the screen when CTRL+C is pressed.
MORE INFORMATIONThe sample program shows how to trap the CTRL+C and CTRL+BREAK key combinations. The program waits for a keystroke. When a key is pressed, the program checks to see if the keystroke is a CTRL+C or CTRL+BREAK key combination. If the keystroke is CTRL+BREAK, nothing happens. If the keystroke is CTRL+C, a message is displayed and the keyboard buffer is dumped to the screen in hexadecimal values. If the keystroke is neither CTRL+C nor CTRL+BREAK, just the keyboard buffer is dumped to the screen.
Sample Code
/* Compile options needed: None */ #include <stdio.h> #include <dos.h> #include <conio.h> #define HIBYTE(x) ((unsigned char) (((unsigned) x >> 8) & 0x00FF)) #define HIWORD(x) \ ((unsigned) (((unsigned long) x >> 16) & 0x0000FFFF) #define LOBYTE(x) ((unsigned char) ((unsigned) x & 0x00FF)) #define LOWORD(x) ((unsigned) ((unsigned long) x & 0x0000FFFF)) #define BITSET(x, n) ( (((unsigned) x >> n) & 0x0001) == 1 ? 1 : 0) #define AND(a, b) ( a &= b ) /* a = a AND b */ #define OR(a, b) ( a |= b ) /* a = a OR b */ #define XOR(a, b) ( a ^= b ) /* a = a XOR b */ #define SEMINIT(s) ( XOR(s, s) ) #define SEMSET(s) ( s ? 1 : 0 ) #define INT09 0x0009 /* Keyboard interrupt number */ #define INT1B 0x001B /* CTRL+C interrupt number */ #define INT23 0x0023 /* CTRL+BREAK interrupt number */ #define ESC 0x1B /* ASCII escape code */ #define SPACE 0x20 /* ASCII space code */ #define cScan 0x2E /* Scan code for the "C" key */ #define CtrlOff 0xFB /* CTRL+C bit mask */ #define CtrlOn 0x04 /* CTRL+C bit mask */ #define Value 0x001F /* Replace ^C with this value */ #define KBDMEM 0x0000041C /* Keyboard buffer tail pointer address */ #define KBDBUF 0x0000041E /* Keyboard buffer address */ #define KBDFLAG 0x00000417 /* Keyboard flag byte address */ #define KB_DATA 0x0060 /* Keyboard port address */ #define ADDRESS unsigned far * /*========================================================*/ /* Functions pointers */ void (interrupt far *KbdPtr)(void); /* Points to keybrd routine */ void (interrupt far *BrkPtr)(void); /* Points to break routine */ void (interrupt far *OldInt09)(void); /* Save old kbd handler */ void (interrupt far *OldInt1B)(void); /* Save old ^C handler */ void (interrupt far *OldInt23)(void); /* Save old brk handler */ /*========================================================*/ ADDRESS KbdBuf; ADDRESS KbdCtrl; ADDRESS KbdTail; void main (void); void KbdHexDump( ADDRESS str ); /*=========================================================*/ /* Interrupt service routines */ void interrupt far Int09(); void interrupt far Int1B(); void interrupt far Int23(); /*=========================================================*/ unsigned sem; /* ^C was pressed then sem=1, else sem=0 */ unsigned ch; unsigned cell; /* Data from kbd port 60h */ void main (void) { unsigned i; OldInt09 = _dos_getvect( INT09 ); OldInt1B = _dos_getvect( INT1B ); OldInt23 = _dos_getvect( INT23 ); KbdPtr = Int09; _dos_setvect( INT09, KbdPtr ); BrkPtr = Int1B; _dos_setvect( INT1B, BrkPtr); BrkPtr = Int23; _dos_setvect( INT23, BrkPtr ); KbdTail = (ADDRESS) KBDMEM; KbdBuf = (ADDRESS) KBDBUF; KbdCtrl = (ADDRESS) KBDFLAG; for(i = 0; i < 16; i++) KbdBuf[i] = (unsigned) (0x3900 | SPACE); SEMINIT(sem); /* Clear semaphore */ XOR(ch, ch); /* ch=0 */ while( LOBYTE(ch) != ESC ) { ch = getch(); if ( SEMSET(sem) ) printf("\nCtrl-C key was pressed!\n"); KbdHexDump( KbdBuf ); } _dos_setvect( INT09, OldInt09 ); _dos_setvect( INT1B, OldInt1B ); _dos_setvect( INT23, OldInt23 ); } void KbdHexDump( ADDRESS str ) { unsigned j; printf("\n"); for( j=0; j < 16; j++ ) { if ( LOBYTE(str[j]) < 15 ) printf("0"); if ( str[j] == Value ) printf("03 "); else printf("%x ", LOBYTE(str[j])); } printf(" "); for( j=0; j < 16; j++ ) { if ( LOBYTE(str[j]) < SPACE ) printf("%c", '.'); else printf("%c", LOBYTE(str[j])); } printf("\n"); } /*========================================================*/ /* Interrupt service routines */ void interrupt far Int09( void ) { unsigned indx; _disable(); cell = inp( KB_DATA ); if ( BITSET(*KbdCtrl, 2) && LOBYTE(cell) == cScan ) { sem = 1; indx = ( *KbdTail - LOBYTE(LOWORD(KbdBuf)) ) / 2; AND( *KbdCtrl, CtrlOff ); } else XOR(sem, sem); OldInt09(); if ( SEMSET(sem) ) { OR( *KbdCtrl, CtrlOn ); KbdBuf[indx] = Value; } } void interrupt far Int1B(void) { /* New home for CTRL+C */ } void interrupt far Int23(void) { /* New Home for CTRL+BREAK */ } |
Additional reference words: kbinf 5.10 6.00 6.00a 6.00ax 7.00 1.00 1.50
© 1998 Microsoft Corporation. All rights reserved. Terms of Use. |