home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
OS/2 Professional
/
OS2PRO194.ISO
/
os2
/
prgramer
/
cenvi
/
keypush.lib
< prev
next >
Wrap
Text File
|
1994-03-08
|
16KB
|
431 lines
// KeyPush.lib - PM routines to control, or mimic, the pushing of
// ver.1 keys on the keyboard. This is one method of controlling
// windows applications. The functions in this library work
// by sending keyboard messages to the focus window as if
// the key messages were actually being sent by Windows.
//
//**** KeyPushFocusID(): Select focus window specification for this library
// SYNTAX: int KeyPushFocusID(NULL) // this is the default
// int KeyPushFocusID(string TopLevelTitle[,TempMakeActive])
// int KeyPushFocusID(int TopLevelHandle[,TempMakeActive])
// int KeyPushFocusID(int FocusWindowHandle)
// WHERE: NULL: if NULL or 0 then will always send to the currently active focus window
// TopLevelTitle: ascii string - will send to focus window of this top-level window
// TopLevelHandle: handle for top-level window - will send to focus window of this top-level window
// FocusWindowHandle: will send directly to this window handle
// TempMakeActive: This window (or top-level window) for this application
// must be the active window while the keystrokes are
// sent, and will temporarily be made active. The default
// is TRUE for TopLevelTitle and TopLevelHandle methods, else
// this doesn't apply and does not switch active window.
// RETURN: Return window that would get focus NOW according to this setting, which
// may be NULL if this setting wouldn't work
// NOTE: For TopLevelTitle and TopLevelHandle methods, these library routines
// may need to temporarily alter the activation of different windows if
// you don't specify TempMakeActive=False, which will look messy if the
// window you're sending to is not currently the active window. In these
// situations, or if you're sending lots of KeyPushxxx messages, you may
// want to make the application active first or get the FocusWindowHandle
// if the window won't change. For top level windows where this is not
// TempMakeActive is not given or is True, then will not make the application
// active but will only send to sub-window that last had active focus.
//
//
//**** KeyStroke(): Press and release a key or combination of keys
// SYNTAX: int KeyStroke([Holdkey1,HoldKey2,HoldKey3...,]byte Character)
// int KeyStroke([Holdkey1,HoldKey2,HoldKey3...,]int VirtualKeyCode)
// int KeyStroke([Holdkey1,HoldKey2,HoldKey3...,]string KeyString)
// WHERE: Holdkey...: mimic that these keys are pressed before KeyCode or KeyString, and then
// will press and release KeyCode or KeyString, and then will release
// HoldKeys in reverse order.
// Character: ascii character to send
// VirtualKeyCode: one of the VK_ key codes (see below)
// KeyString: Ascii string to send
// RETURN: Return handle keys were sent to; 0 if no handle found
// EXAMPLES: To press the 'S' key: KeyStroke('S');
// To type a sentence: KeyStroke("On top of Old Smokey!\n");
// To type Alt-F1: KeyStroke("VK_ALT,VK_F1);
// To simulate Ctl-Alt-R: KeyStroke(VK_CONTROL,VK_ALT,'R');
//
//
//**** SpeedKeys(): Send character messages
// SYNTAX: int SpeedKeys(string AsciiString[,DelayBetweenKeys])
// int SpeedKeys(byte Character[,DelayBetweenKeys])
// WHERE: AsciiString: string of characters to send
// Character: single character to send
// DelayBetweenKeys: Approximate time, in milliseconds, to wait after
// sending each key message
// NOTE: Speed keys sends only WM_CHAR messages to an application and is much
// faster than KeyStroke(), but should only be used for regular ascii
// strings passed to applications that don't need to for each specific
// keystroke. So, if KeyStroke() is too slow and you're entering a
// stretch of plain text, then use this function.
//
//
//**** VKeyDown(): Press down a key (no release yet)
// SYNTAX: int VKeyDown(int KeyCode)
// WHERE: KeyCode: Virtual VK_ key or character key
// RETURN: Return handle keys were sent to; 0 if no handle found
//
//
//**** VKeyUP(): Release a key (that has been pressed down)
// SYNTAX: int VKeyUP(int KeyCode)
// WHERE: KeyCode: Virtual VK_ key or character key
// RETURN: Return handle keys were sent to; 0 if no handle found
//
//
#include <WinMsg.lib>
#include <GiveMem.lib>
#include <WinTools.lib>
/*** Virtual key values *************************************************/
#define VK_BUTTON1 0x01
#define VK_BUTTON2 0x02
#define VK_BUTTON3 0x03
#define VK_BREAK 0x04
#define VK_BACKSPACE 0x05
#define VK_TAB 0x06
#define VK_BACKTAB 0x07
#define VK_NEWLINE 0x08
#define VK_SHIFT 0x09
#define VK_CTRL 0x0A
#define VK_ALT 0x0B
#define VK_ALTGRAF 0x0C
#define VK_PAUSE 0x0D
#define VK_CAPSLOCK 0x0E
#define VK_ESC 0x0F
#define VK_SPACE 0x10
#define VK_PAGEUP 0x11
#define VK_PAGEDOWN 0x12
#define VK_END 0x13
#define VK_HOME 0x14
#define VK_LEFT 0x15
#define VK_UP 0x16
#define VK_RIGHT 0x17
#define VK_DOWN 0x18
#define VK_PRINTSCRN 0x19
#define VK_INSERT 0x1A
#define VK_DELETE 0x1B
#define VK_SCRLLOCK 0x1C
#define VK_NUMLOCK 0x1D
#define VK_ENTER 0x1E
#define VK_SYSRQ 0x1F
#define VK_F1 0x20
#define VK_F2 0x21
#define VK_F3 0x22
#define VK_F4 0x23
#define VK_F5 0x24
#define VK_F6 0x25
#define VK_F7 0x26
#define VK_F8 0x27
#define VK_F9 0x28
#define VK_F10 0x29
#define VK_F11 0x2A
#define VK_F12 0x2B
#define VK_F13 0x2C
#define VK_F14 0x2D
#define VK_F15 0x2E
#define VK_F16 0x2F
#define VK_F17 0x30
#define VK_F18 0x31
#define VK_F19 0x32
#define VK_F20 0x33
#define VK_F21 0x34
#define VK_F22 0x35
#define VK_F23 0x36
#define VK_F24 0x37
#define VK_ENDDRAG 0x38
#define VK_MENU VK_F10
KeyPushFocusID(pFocusID,pTempMakeActive)
{
gFocusIDIsTopLevel = False;
if ( !pFocusID ) {
gFocusID = 0;
gKPTempMakeActive = False;
} else if ( 0 != DataDimension(pFocusID) ) {
// find window based on string
if ( !(gFocusID = GetWindowHandle(pFocusID)) )
return 0;
gFocusIDIsTopLevel = True;
} else {
// determine if this is one of the top level windows
lEnum = WinBeginEnumWindows(HWND_DESKTOP);
while ( lChild = WinGetNextWindow(lEnum) ) {
if ( pFocusID == lChild ) {
gFocusIDIsTopLevel = True;
break;
}
}
WinEndEnumWindows(lEnum);
gFocusID = pFocusID;
}
gKPTempMakeActive = ( va_arg() < 2 ) ? True : pTempMakeActive ;
// gFocusID parameter is set. Return window handle as regular KeyPush calls would
KeyPushInitialize();
KeyPushTerminate();
return gKPFocusWindow;
}
KeyStroke(pKey1,pKey2,pKey3/*etc...*/)
{
if ( KeyPushInitialize() ) {
lArgCount = va_arg();
// if more than one parameter, then hold down all but the last one
for ( lKeyC = 1; lKeyC < lArgCount; lKeyC++ )
KeyDown(va_arg(lKeyC-1));
lKey = va_arg(lArgCount-1);
// Treat differently depending on whether Virtual Key Code, char, or string
if ( CMM_BYTE == DataType(lKey) ) {
if ( 1 == DataDimension(lKey) ) {
// send entire string one character at a time
for ( lIdx = 0; lKey[lIdx]; lIdx++ ) {
KeyDown(lKey[lIdx]);
KeyUp(lKey[lIdx]);
}
} else {
// send a single character out the port
KeyDown(lKey);
KeyUp(lKey);
}
} else {
// simply a virtual key code
KeyDown(lKey);
KeyUp(lKey);
}
// if more than one parameter, then reverse release all but the last one
for ( lKeyC = 1; lKeyC < lArgCount; lKeyC++ )
KeyUp(va_arg(lArgCount-lKeyC-1));
}
KeyPushTerminate();
return gKPFocusWindow;
}
#define WM_CHAR 0x007a
#define WM_TRANSLATEACCEL 0x004b
/* WM_CHAR fs field bits */
#define KC_CHAR 0x0001
#define KC_VIRTUALKEY 0x0002
#define KC_SCANCODE 0x0004
#define KC_SHIFT 0x0008
#define KC_CTRL 0x0010
#define KC_ALT 0x0020
#define KC_KEYUP 0x0040
#define KC_PREVDOWN 0x0080
#define KC_LONEKEY 0x0100
#define KC_DEADKEY 0x0200
#define KC_COMPOSITE 0x0400
#define KC_INVALIDCOMP 0x0800
#define KC_TOGGLE 0x1000
#define KC_INVALIDCHAR 0x2000
#define KC_DBCSRSRVD1 0x4000
#define KC_DBCSRSRVD2 0x8000
gKPLatestKeyDown = FALSE; // True on call to key down, false on KeyUp
KeyDown(pKey)
{
if ( KeyPushInitialize() ) {
// Save the current state of the 256-byte keyboard buffer
lKeyTable = GetKeyboardTable();
gKPLatestKeyDown = TRUE;
if ( CMM_BYTE == DataType(pKey) ) {
// pushing just a character
lfsflags = KC_CHAR;
lusch = pKey;
lusvk = 0;
} else {
// pushing a virtual key
lfsflags = KC_VIRTUALKEY;
lusch = 0;
lusvk = pKey;
if ((lKeyTable[pKey] = (lKeyTable[pKey] | 0x80) ^ 1) & 0x01)
lfsflags |= KC_TOGGLE;
SetKeyboardTable(lKeyTable);
}
if ( lKeyTable[VK_SHIFT] & 0x80 )
lfsflags |= KC_SHIFT;
if ( lKeyTable[VK_ALT] & 0x80 )
lfsflags |= KC_ALT;
if ( lKeyTable[VK_CTRL] & 0x80 )
lfsflags |= KC_CTRL;
SendMessageAndAccelTable(lfsflags | (1 << 16),lusch | (lusvk << 16));
}
KeyPushTerminate();
return gKPFocusWindow;
}
KeyUp(pKey)
{
if ( KeyPushInitialize() ) {
// Save the current state of the 256-byte keyboard buffer
lKeyTable = GetKeyboardTable();
// set some fsflags based on keys currently pressed
lfsflags = KC_KEYUP /*| KC_PREVDOWN*/;
if ( CMM_BYTE == DataType(pKey) ) {
// pushing just a character
lfsflags |= KC_CHAR;
if ( (lKeyTable[VK_CTRL] & 0x80) && isalpha(pKey) )
// convert to control character
lusch = toupper(pKey) - 'A' + 1;
else
lusch = pKey;
lusvk = 0;
} else {
// pushing a virtual key
lfsflags |= KC_VIRTUALKEY;
lusch = 0;
lusvk = pKey;
if ((lKeyTable[pKey] &= 0x7F) & 0x01);
lfsflags |= KC_TOGGLE;
SetKeyboardTable(lKeyTable);
}
if ( lKeyTable[VK_SHIFT] & 0x80 )
lfsflags |= KC_SHIFT;
if ( lKeyTable[VK_ALT] & 0x80 )
lfsflags |= KC_ALT;
if ( lKeyTable[VK_CTRL] & 0x80 )
lfsflags |= KC_CTRL;
if ( gKPLatestKeyDown )
lfsflags |= KC_LONEKEY;
gKPLatestKeyDown = FALSE;
// send message to window that this key is being pressed
SendMessageAndAccelTable(lfsflags | (1 << 16),lusch | (lusvk << 16));
}
KeyPushTerminate();
return gKPFocusWindow;
}
SpeedKeys(pAsciiString,pDelayBetweenCharacters)
{
if ( KeyPushInitialize() ) {
if ( 1 == DataDimension(pAsciiString) ) { lChar = pAsciiString; }
else { lChar[1] = '\0'; lChar[0] = pAsciiString; }
for ( ; lChar[0]; lChar++ ) {
lParam1 = ((KC_CHAR | KC_LONEKEY)) | (1 << 16);
WinSendMsg(gKPFocusWindow,WM_CHAR,lParam1,lChar[0]);
if ( 1 < va_arg() )
suspend(pDelayBetweenCharacters);
}
}
KeyPushTerminate();
return gKPFocusWindow;
}
/***********************************************************
*** PRIVATE UTILITIES USED BY THE ABOVE PUBLIC ROUTINES ***
***********************************************************/
gFocusID = 0;
gFocusIDIsTopLevel = False; // set true if using Focus ID that is top-level window
gKeyPushInitializeDepth = 0; // keep track how many times recursively called
gKPFocusWindow; // KeyPushInitialize sets to window
gKPSaveActiveWindow = 0;
gKPTempMakeActive = True;
KeyPushInitialize()
{
// keep track of how many times called. get actual ID to send to on first
// level, on recursive calls revert to first return. If need to activate
// window then do so. Return FALSE for failure, else non-false is TRUE
if ( 0 == gKeyPushInitializeDepth++ ) {
gKPSaveActiveWindow = 0; // assume don't need to change focus
if ( !gFocusID ) {
// take whatever is the focus window
gKPFocusWindow = GetFocus();
} else if ( !IsWindow(gFocusID) ) {
gKPFocusWindow = 0; // gFocusID is not valid
} else if ( !gFocusIDIsTopLevel ) {
gKPFocusWindow = gFocusID; // this isn't top level, so is actual window to send to
} else {
// this is a top level window, if KeyPushFocusID() set up to make active
// when sending keystrokes then do so, else send to the child that was
// the focus when this window was active
if ( gFocusID == (lActive=GetActiveWindow()) ) {
gKPFocusWindow = GetFocus();
} else {
if ( gKPTempMakeActive ) {
gKPSaveActiveWindow = lActive;
SetActiveWindow(gFocusID);
gKPFocusWindow = GetFocus();
} else {
gKPFocusWindow = GetFocusChild(gFocusID);
}
}
}
}
return gKPFocusWindow;
}
KeyPushTerminate()
{
// undo what KeyPushInitialize did. restore active window if KeyPushInitialize()
// activated it. Must call same number of times as KeyPushInitialize.
if ( 0 == --gKeyPushInitializeDepth ) {
if ( gKPSaveActiveWindow ) {
SetActiveWindow(gKPSaveActiveWindow);
}
}
}
#define HWND_DESKTOP 1
#define ORD_WIN32SETKEYBOARDSTATETABLE 921
GetKeyboardTable() // return 256 byte buffer for current keyboard state
{
lTable[255] = '\0'; // initialize 256-byte key table
DynamicLink("PMWIN",ORD_WIN32SETKEYBOARDSTATETABLE,BIT32,CDECL,
HWND_DESKTOP,lTable,FALSE);
return(lTable);
}
SetKeyboardTable(pKeyBuf) // set the 256 byte buffer for current keyboard state
{
DynamicLink("PMWIN",ORD_WIN32SETKEYBOARDSTATETABLE,BIT32,CDECL,
HWND_DESKTOP,pKeyBuf,TRUE);
}
/***********************************/
/*** SEND KEY MESSAGES TO WINDOW ***/
SendMessageAndAccelTable(pParam1,pParam2)
// Send this message and send an accelerator table message
{
// see that the current window has been given access to the shared
// memory table memory
lSharedMemory = GiveMemoryToWindow(gKPFocusWindow);
// copy the message to the globally allocated and shared memory
// build blob message to give to accelerator table
poke( lSharedMemory, gKPFocusWindow, UWORD32 );
poke( lSharedMemory+4, WM_CHAR, UWORD32 );
poke( lSharedMemory+8, pParam1, UWORD32 );
poke( lSharedMemory+12, pParam2, UWORD32 );
// send message to window accelerator in case it wants to translate
WinSendMsg(gKPFocusWindow,WM_TRANSLATEACCEL,lSharedMemory,0);
// send translated message to the window
WinSendMsg(peek(lSharedMemory,UWORD32),peek(lSharedMemory+4,UWORD32),
peek(lSharedMemory+8,UWORD32),peek(lSharedMemory+12,UWORD32));
}