AutoJim

Jim is one of my bosses. He’s been giving a co-worker a hard time by opening a program like notepad and leaving messages for him whenever he finds that my co-worker’s computer has been left unlocked and unattended. The problem is, Jim is a busy guy and can’t always be on the lookout for unlocked computers.

I’ve spent the last two nights writing this program to help him out. I took some sample code for writing a program to put an icon in the taskbar, modified it so that every 5 minutes it checks to see if the mouse cursor has been moved. If the cursor hasn’t been moved then it opens a text file for write, leaves a random message in the text file, and then has notepad open the text file so that the user can see it.

You can compile this in gcc under cygwin like so:

gcc -mwindows -mno-cygwin autojim.c -o autojim.exe

#include <windows.h>
#include <stdio.h>

#define CLASS "Auto Jim v.1.0"
#define TITLE "Auto Jim"

static BOOL g_bModalState  = FALSE;
static BOOL g_bActiveState = FALSE; // Whether or not we've already activated.
static POINT ptOld;                 // previous cursor location
static UINT uResult;                // SetTimer's return value

enum {
ID_TRAYICON         = 1,
IDT_MOUSETRAP       = 1,
APPWM_TRAYICON      = WM_APP,
APPWM_NOP           = WM_APP + 1,
ID_ABOUT            = 2000,
ID_EXIT
};

void AddTrayIcon( HWND hWnd, UINT uID, UINT uCallbackMsg, UINT uIcon, LPSTR pszToolTip );
void RemoveTrayIcon( HWND hWnd, UINT uID);
void ModifyTrayIcon( HWND hWnd, UINT uID, UINT uIcon, LPSTR pszToolTip );
HICON LoadSmallIcon( HINSTANCE hInstance, UINT uID );
BOOL ShowPopupMenu( HWND hWnd, POINT *curpos, int wDefaultItem );
void OnInitMenuPopup( HWND hWnd, HMENU hMenu, UINT uID );
BOOL OnCommand( HWND hWnd, WORD wID, HWND hCtl );
void OnTrayIconMouseMove( HWND hWnd );
void OnTrayIconRBtnUp( HWND hWnd );
void OnTrayIconLBtnDblClick( HWND hWnd );
void OnClose( HWND hWnd );
void RegisterMainWndClass( HINSTANCE hInstance );
void UnregisterMainWndClass( HINSTANCE hInstance );

int WINAPI WinMain( HINSTANCE hInst, HINSTANCE prev, LPSTR cmdline, int show ) {
HMENU   hSysMenu    = NULL;
HWND    hWnd        = NULL;
HWND    hPrev       = NULL;
MSG     msg;

//  Do not allow multiple copies of the same program.
if ( hPrev = FindWindow( CLASS, TITLE ) ) {
return 0;
}

RegisterMainWndClass( hInst );

hWnd = CreateWindow( CLASS, TITLE, 0, 0, 0, 100, 100, NULL, NULL, hInst, NULL );

if ( ! hWnd ) {
MessageBox( NULL, "Ack! I can't create the window!", TITLE, MB_ICONERROR | MB_OK | MB_TOPMOST );
return 1;
}

// Record the initial cursor position of the mouse, set the timer. 
GetCursorPos( &ptOld );
uResult = SetTimer( hWnd, IDT_MOUSETRAP, 300000, ( TIMERPROC ) NULL );

if ( uResult == 0 ) {
MessageBox( NULL, "Couldn't create a timer.", TITLE, MB_ICONERROR | MB_OK | MB_TOPMOST );
}

while ( GetMessage( &msg, NULL, 0, 0 ) ) {
TranslateMessage( &msg );
DispatchMessage( &msg );
}

UnregisterMainWndClass( hInst );

return msg.wParam;
}

void AddTrayIcon( HWND hWnd, UINT uID, UINT uCallbackMsg, UINT uIcon, LPSTR pszToolTip ) {
char    szIconFile[512];
NOTIFYICONDATA  nid;

memset( &nid, 0, sizeof( nid ) );

nid.cbSize              = sizeof( nid );
nid.hWnd                = hWnd;
nid.uID                 = uID;
nid.uFlags              = NIF_ICON | NIF_MESSAGE | NIF_TIP;
nid.uCallbackMessage    = uCallbackMsg;

GetSystemDirectory( szIconFile, sizeof( szIconFile ));

if ( szIconFile[ strlen( szIconFile ) - 1 ] != '\' ) {
strcat( szIconFile, "\" );
}

strcat( szIconFile, "shell32.dll" );
ExtractIconEx( szIconFile, 23, NULL, &( nid.hIcon ), 1 );

strcpy( nid.szTip, pszToolTip );

Shell_NotifyIcon( NIM_ADD, &nid );
}

void ModifyTrayIcon( HWND hWnd, UINT uID, UINT uIcon, LPSTR pszToolTip ) {
NOTIFYICONDATA  nid;

memset( &nid, 0, sizeof( nid ) );

nid.cbSize  = sizeof( nid );
nid.hWnd    = hWnd;
nid.uID     = uID;

if ( uIcon != (UINT)-1 ) {
nid.hIcon   = LoadSmallIcon( GetModuleHandle( NULL ), uIcon );
nid.uFlags  |= NIF_ICON;
}

if ( pszToolTip ) {
strcpy( nid.szTip, pszToolTip );
nid.uFlags  |= NIF_TIP;
}

if ( uIcon != (UINT)-1 || pszToolTip ) {
Shell_NotifyIcon( NIM_MODIFY, &nid );
}
}

void RemoveTrayIcon( HWND hWnd, UINT uID ) {
NOTIFYICONDATA  nid;

memset( &nid, 0, sizeof( nid ) );

nid.cbSize  = sizeof( nid );
nid.hWnd    = hWnd;
nid.uID     = uID;

Shell_NotifyIcon( NIM_DELETE, &nid );
}

static LRESULT CALLBACK WindowProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam ) {
POINT pt;       // current cursor location 
FILE *fp;
char msgs[10][40] = {
//23456789012345678901234567890123456789
"Who's been using your computer?",
"Maybe I saved a bookmark this time.",
"Could be anyone. Check all your files.",
"You can't even walk away for a moment.",
"I could have done anything.",
"Try locking your computer.",
"Are you always this careless?",
"How does this keep happening?",
"Not locked this time either."
};

switch ( uMsg ) {
case WM_CREATE:
AddTrayIcon( hWnd, ID_TRAYICON, APPWM_TRAYICON, 0, TITLE );
return 0;

case APPWM_NOP:
//  There's a long comment in OnTrayIconRBtnUp() which explains 
//  what we're doing here.
return 0;

//  This is the message which brings tidings of mouse events involving 
//  our tray icon.  We defined it ourselves.  See AddTrayIcon() for 
//  details of how we told Windows about it.
case APPWM_TRAYICON:
SetForegroundWindow( hWnd );

switch ( lParam ) {
case WM_MOUSEMOVE:
OnTrayIconMouseMove( hWnd );
return 0;

case WM_RBUTTONUP:
//  There's a long comment in OnTrayIconRBtnUp() which 
//  explains what we're doing here.
OnTrayIconRBtnUp( hWnd );
return 0;

case WM_LBUTTONDBLCLK:
OnTrayIconLBtnDblClick( hWnd );
return 0;
}
return 0;

case WM_COMMAND:
return OnCommand( hWnd, LOWORD(wParam), (HWND)lParam );

case WM_INITMENUPOPUP:
OnInitMenuPopup( hWnd, (HMENU)wParam, lParam );
return 0;

case WM_CLOSE:
OnClose( hWnd );
return DefWindowProc( hWnd, uMsg, wParam, lParam );

case WM_TIMER:
// If the window is minimized, compare the current 
// cursor position with the one from 10 seconds 
// earlier. If the cursor position has not changed, 
// move the cursor to the icon. 
GetCursorPos(&pt);

if (( pt.x == ptOld.x ) && ( pt.y == ptOld.y ) && ( g_bActiveState == FALSE )) {
g_bActiveState = TRUE;
fp = fopen( "c:\CaughtYa.txt", "w" );
fprintf( fp, "%s", msgs[(( int ) rand() % 9 )] );
fclose( fp );
ShellExecute( hWnd,"open","notepad.exe", "c:\CaughtYa.txt","",SW_SHOW );
} else if (( pt.x != ptOld.x ) || ( pt.y != ptOld.y )) {
g_bActiveState = FALSE;
ptOld.x = pt.x;
ptOld.y = pt.y;
}

return 0;

default:
return DefWindowProc( hWnd, uMsg, wParam, lParam );
}
}

void OnClose( HWND hWnd ) {
//  Remove icon from system tray.
RemoveTrayIcon( hWnd, ID_TRAYICON );

// Destroy the timer. 
KillTimer( hWnd, IDT_MOUSETRAP );

PostQuitMessage( 0 );
}

BOOL ShowPopupMenu( HWND hWnd, POINT *curpos, int wDefaultItem ) {
HMENU   hPop        = NULL;
int     i           = 0;
WORD    cmd;
POINT   pt;

if ( g_bModalState ) {
return FALSE;
}

hPop = CreatePopupMenu();

if ( ! curpos ) {
GetCursorPos( &pt );
curpos = &pt;
}

InsertMenu( hPop, i++, MF_BYPOSITION | MF_STRING, ID_ABOUT, "About..." );
InsertMenu( hPop, i++, MF_BYPOSITION | MF_STRING, ID_EXIT, "Exit" );

SetMenuDefaultItem( hPop, ID_ABOUT, FALSE );

SetFocus( hWnd );

SendMessage( hWnd, WM_INITMENUPOPUP, (WPARAM)hPop, 0 );

cmd = TrackPopupMenu( hPop, TPM_LEFTALIGN | TPM_RIGHTBUTTON | TPM_RETURNCMD | TPM_NONOTIFY, curpos->x, curpos->y, 0, hWnd, NULL );

SendMessage( hWnd, WM_COMMAND, cmd, 0 );

DestroyMenu( hPop );

return cmd;
}

BOOL OnCommand( HWND hWnd, WORD wID, HWND hCtl ) {
if ( g_bModalState ) {
return 1;
}

//  Have a look at the command and act accordingly
switch ( wID ) {
case ID_ABOUT:
g_bModalState = TRUE;
MessageBox( hWnd, CLASS, TITLE, MB_ICONINFORMATION | MB_OK );
g_bModalState = FALSE;
return 0;

case ID_EXIT:
PostMessage( hWnd, WM_CLOSE, 0, 0 );
return 0;
}
}

//-----------------------------------------------------------------------------
//  When the mouse pointer drifts over the tray icon, a "tooltip" will be 
//  displayed.  Before that happens, we get notified about the movement, so we 
//  get a chance to set the "tooltip" text to be something useful.  
void OnTrayIconMouseMove( HWND hWnd ) {
//  stub
}

void OnTrayIconRBtnUp( HWND hWnd ) {
SetForegroundWindow( hWnd );

ShowPopupMenu( hWnd, NULL, -1 );

PostMessage( hWnd, APPWM_NOP, 0, 0 );
}

void OnTrayIconLBtnDblClick( HWND hWnd ) {
SendMessage( hWnd, WM_COMMAND, ID_ABOUT, 0 );
}

void OnInitMenuPopup( HWND hWnd, HMENU hPop, UINT uID ) {
//  stub
}

void RegisterMainWndClass( HINSTANCE hInstance ) {
WNDCLASSEX wclx;
memset( &wclx, 0, sizeof( wclx ) );

wclx.cbSize         = sizeof( wclx );
wclx.style          = 0;
wclx.lpfnWndProc    = &WindowProc;
wclx.cbClsExtra     = 0;
wclx.cbWndExtra     = 0;
wclx.hInstance      = hInstance;
wclx.hCursor        = LoadCursor( NULL, IDC_ARROW );
wclx.hbrBackground  = (HBRUSH)( COLOR_BTNFACE + 1 );
wclx.lpszMenuName   = NULL;
wclx.lpszClassName  = CLASS;

RegisterClassEx( &wclx );
}

void UnregisterMainWndClass( HINSTANCE hInstance ) {
UnregisterClass( CLASS, hInstance );
}

HICON LoadSmallIcon( HINSTANCE hInstance, UINT uID ) {
return LoadImage( hInstance, MAKEINTRESOURCE( uID ), IMAGE_ICON, 16, 16, 0 );
}

Leave a Reply

You must be logged in to post a comment.