Posted: 23rd Feb 2004 19:26
The following used to be my SendKey plug-in. Unfortunately it was too unreliable to be much use (wierd thing like blocking keys). Anyway, its here for those who want to know how it could be done :

+ Code Snippet
// SendInput.cpp : Defines the entry point for the DLL application.
//
#define _WIN32_WINNT 0x0501

#include "stdafx.h"
#include "SendInput.h"
#include "windows.h"
#include "winuser.h"
#include "stdio.h"
#include "math.h"

BOOL APIENTRY DllMain( HANDLE hModule, 
                       DWORD  ul_reason_for_call, 
                       LPVOID lpReserved
					 )
{
    switch (ul_reason_for_call)
	{
		case DLL_PROCESS_ATTACH:
		case DLL_THREAD_ATTACH:
		case DLL_THREAD_DETACH:
		case DLL_PROCESS_DETACH:
			break;
    }
    return TRUE;
}

void __sendMouseCode(int x,int y,int button,bool up)
{
INPUT	input;

	ZeroMemory(&input,sizeof(input));
	input.type=INPUT_MOUSE;
	switch (button) {
		case	VK_LBUTTON	:	// Left button
								input.mi.dwFlags=(up ? MOUSEEVENTF_LEFTUP : MOUSEEVENTF_LEFTDOWN);
								break;
		case	VK_MBUTTON	:	// Middle button
								input.mi.dwFlags=(up ? MOUSEEVENTF_MIDDLEUP : MOUSEEVENTF_MIDDLEDOWN);
								break;
		case	VK_RBUTTON	:	// Right button								
								input.mi.dwFlags=(up ? MOUSEEVENTF_RIGHTUP : MOUSEEVENTF_RIGHTDOWN);
								break;
		case	VK_MMOVE	:	// Mouse movement
								input.mi.dx=x;
								input.mi.dy=y;
								input.mi.dwFlags=MOUSEEVENTF_ABSOLUTE | MOUSEEVENTF_MOVE;
								break;
		};										

	SendInput(1,(INPUT *) &input,sizeof(input));
}	

void __sendKeyboardCode(int code,bool keyUp,bool extended)
{
INPUT	input;

	if (code==VK_SLEEP)
	{
		return;
	}

	ZeroMemory(&input,sizeof(input));
	input.type=INPUT_KEYBOARD;
	input.ki.wVk=code;
	input.ki.wScan=MapVirtualKey(code,0);
	input.ki.dwFlags=(keyUp ? KEYEVENTF_KEYUP : 0);
	input.ki.dwFlags|=(extended ? KEYEVENTF_EXTENDEDKEY : 0);
	SendInput(1,(INPUT *) &input,sizeof(input));
}

DWORD SendInputText(LPSTR text)
{
	if ((text) && (strlen(text)>0))
	{
	register int loop;

		for (loop=0; loop<(int) strlen(text); loop++)
		{
		char one;

			one=(char) *(text+loop);
			if (one>=(char) 'a' && one<=(char) 'z')
			{
				SendCapsLock((DWORD) false);
				__sendKeyboardCode(toupper(one),false,false);
				SendCapsLock((DWORD) false);				
			}
			else
			if (one>=(char) 'A' && one<=(char) 'Z')
			{
				SendCapsLock((DWORD) true);
				__sendKeyboardCode(one,false,false);
				SendCapsLock((DWORD) true);
			}
			else
			{
				__sendKeyboardCode(one,false,false);
			}
		}

		return ((DWORD) true);
	}

	return ((DWORD) false);
}

// First key is ALT+code, the other is a normal code
DWORD SendAltKey(LPSTR text)
{
	if ((text) && (strlen(text)>0))
	{
		__sendKeyboardCode(VK_LMENU,false,false);
		__sendKeyboardCode(*(text),false,false);
		__sendKeyboardCode(VK_LMENU,true,false);
		return (SendInputText((LPSTR) (text+1)));
	}

	return ((DWORD) false);
}

DWORD SendFunctionKey(DWORD functionKey)
{
	if (functionKey>=1 && functionKey<=24)
	{
		__sendKeyboardCode(VK_F1+(functionKey-1),false,false);
		__sendKeyboardCode(VK_F1+(functionKey-1),true,false);
		return ((DWORD) true);
	}

	return ((DWORD) false);
}

DWORD SendControlKey(LPSTR text)
{
	if ((text) && (strlen(text)>0))
	{
		__sendKeyboardCode(VK_LCONTROL,false,false);
		__sendKeyboardCode(*(text),false,false);
		__sendKeyboardCode(VK_LCONTROL,true,false);
		return (SendInputText((LPSTR) (text+1)));
	}

	return ((DWORD) false);
}

DWORD SendNumLock(DWORD on)
{
BYTE keyState[256];

	GetKeyboardState((LPBYTE)&keyState);
	if ((on && !(keyState[VK_NUMLOCK] & 1)) ||
	   (!on && (keyState[VK_NUMLOCK] & 1)))
	{
		__sendKeyboardCode(VK_NUMLOCK,false,true);
		__sendKeyboardCode(VK_NUMLOCK,true,true);
	}
	return ((DWORD) true);
}

DWORD SendScrollLock(DWORD on)
{
BYTE keyState[256];

	GetKeyboardState((LPBYTE)&keyState);
	if ((on && !(keyState[VK_SCROLL] & 1)) ||
	   (!on && (keyState[VK_SCROLL] & 1)))
	{
		__sendKeyboardCode(VK_SCROLL,false,true);
		__sendKeyboardCode(VK_SCROLL,true,true);
	}
	return ((DWORD) true);
}

DWORD SendCapsLock(DWORD on)
{
BYTE keyState[256];

	GetKeyboardState((LPBYTE)&keyState);
	if ((on && !(keyState[VK_CAPITAL] & 1)) ||
	   (!on && (keyState[VK_CAPITAL] & 1)))
	{
		__sendKeyboardCode(VK_CAPITAL,false,true);
		__sendKeyboardCode(VK_CAPITAL,true,true);
	}
	return ((DWORD) true);

}

DWORD SendPrintScreen(void)
{
	__sendKeyboardCode(VK_SNAPSHOT,false,false);
	__sendKeyboardCode(VK_SNAPSHOT,true,false);
	return ((DWORD) true);
}

DWORD SendWindowsKey(void)
{
	__sendKeyboardCode(VK_MENU,false,false);
	__sendKeyboardCode(VK_MENU,true,false);
	return ((DWORD) true);
}

DWORD SendLeftMButton(void)
{
	__sendMouseCode(0,0,VK_LBUTTON,false);
	__sendMouseCode(0,0,VK_LBUTTON,true);
	return ((DWORD) true);
}

DWORD SendMiddleMButton(void)
{
	__sendMouseCode(0,0,VK_MBUTTON,false);
	__sendMouseCode(0,0,VK_MBUTTON,true);
	return ((DWORD) true);
}

DWORD SendRightMButton(void)
{
	__sendMouseCode(0,0,VK_RBUTTON,false);
	__sendMouseCode(0,0,VK_RBUTTON,true);
	return ((DWORD) true);
}

void ScreenToNACStep(int *x,int *y)
{
WINDOWINFO winInfo;

	GetWindowInfo(GetDesktopWindow(),&winInfo);
	*(x)=(int) (65535/(int) (winInfo.rcWindow.right-winInfo.rcWindow.left))+1;
	*(y)=(int) (65535/(int) (winInfo.rcWindow.bottom-winInfo.rcWindow.top))+1;
}

int XPixelToXNAC(int xPos)
{
int x,y;

	ScreenToNACStep(&x,&y);
	return (abs(xPos*x));
}

int YPixelToYNAC(int yPos)
{
int x,y;

	ScreenToNACStep(&x,&y);
	return (abs(yPos*y));
}

DWORD SendMouseMovement(DWORD x,DWORD y)
{
HWND hWnd;
RECT rect;
POINT cToS;
int xStep,yStep;

	ScreenToNACStep(&xStep,&yStep);
	if ((hWnd=GetForegroundWindow())!=NULL) 
	{
	int xP,yP;
	
		GetClientRect(hWnd,&rect);
		cToS.x=rect.left;
		cToS.y=rect.top;
		ClientToScreen(hWnd,&cToS);
		xP=(x*xStep)+(cToS.x*xStep);
		yP=(y*yStep)+(cToS.y*yStep);
		__sendMouseCode(xP,yP,VK_MMOVE,false);
		return ((DWORD) true);
	}
		
	return ((DWORD) false);
}

DWORD SendMouseAbs(DWORD x,DWORD y)
{
	__sendMouseCode(x,y,VK_MMOVE,false);
	return ((DWORD) true);
}