Plateforme Level Extreme
Abonnement
Profil corporatif
Produits & Services
Support
Légal
English
Can VFP know if it's idle for a period of time?
Message
 
À
08/08/2001 09:51:53
Allen Hanna
H. A. Hanna Associates
Indianola, Indiana, États-Unis
Information générale
Forum:
Visual FoxPro
Catégorie:
Autre
Divers
Thread ID:
00541244
Message ID:
00541628
Vues:
28
>I have several forms in an app. If there is no user interaction for 30 minutes I'd like to shut VFP6 down. Is there a way to do this without hardcoding a timer in each form that gets reset by control's interactive change, etc.?

I have a solution that uses Windows Hooks and an FLL. It is actually quite simple in design but seems to work very well.

Here is the fll code (it is extracted from a larger file and is untested as is):
// idle.cpp
// IDLE TIME HOOKS -- Copyright 2001 Visual Records, Inc. www.visualrecords.com

#include <pro_ext.h>

// HOOK ROUTINES--
FILETIME ftHookTime;
HHOOK hKeyboardHook, hMouseHook;
POINT ptHook = {0, 0};

LRESULT CALLBACK KeyboardProc(int code, WPARAM wParam, LPARAM lParam)
{
	// RESET TIMER
	GetSystemTimeAsFileTime(&ftHookTime);

	// THUNK TO NEXT HOOK
	return CallNextHookEx(hKeyboardHook, code, wParam, lParam);
}

LRESULT CALLBACK MouseProc(int code, WPARAM wParam, LPARAM lParam)
{
	MOUSEHOOKSTRUCT* pmhs;
	pmhs = reinterpret_cast<MOUSEHOOKSTRUCT*>(lParam);
	if(wParam == WM_MOUSEMOVE)
	{
		if(pmhs->pt.x != ptHook.x || pmhs->pt.y != ptHook.y)
		{
			ptHook = pmhs->pt;
			// RESET TIMER
			GetSystemTimeAsFileTime(&ftHookTime);
		}
	} else
		GetSystemTimeAsFileTime(&ftHookTime);


	// THUNK TO NEXT HOOK
	return CallNextHookEx(hMouseHook, code, wParam, lParam);
}

void InstallHooks(ParamBlk *parm) // bool InstallHooks(lbInstall)
{
	if(p0.val.ev_length)
	{
		// FIRST UNHOOK ANY PRIOR HOOKS
		if(hKeyboardHook) UnhookWindowsHookEx(hKeyboardHook);
		if(hMouseHook) UnhookWindowsHookEx(hMouseHook);

		// INSTALL HOOKS
		hKeyboardHook = SetWindowsHookEx(WH_KEYBOARD, KeyboardProc,
			0, GetCurrentThreadId());
		if(hKeyboardHook == 0)
		{
			_RetLogical(false);
			return;
		}
		
		hMouseHook = SetWindowsHookEx(WH_MOUSE, MouseProc,
			0, GetCurrentThreadId());
		if(hMouseHook == 0)
		{
			// CLEANUP KEYBOARD HOOK
			UnhookWindowsHookEx(hKeyboardHook);
			hKeyboardHook = 0;
			_RetLogical(false);
			return;
		}

		// SET HOOK TIME TO CURRENT TIME
		GetSystemTimeAsFileTime(&ftHookTime);

		// SUCCESS
		_RetLogical(true);
		return;
	} 
	else
	{
		// UNINSTALL HOOKS
		if(hKeyboardHook) {
			UnhookWindowsHookEx(hKeyboardHook);
			hKeyboardHook = 0;
		}
		if(hMouseHook) {
			UnhookWindowsHookEx(hMouseHook);
			hMouseHook = 0;
		}

		// SUCCESS
		_RetLogical(true);
	}
}

void ResetHookTime(ParamBlk *parm) // void ResetHookTime()
{
	// RESET TIMER
	GetSystemTimeAsFileTime(&ftHookTime);

	// SUCCESS
	_RetLogical(true);
	return;
}

void GetHookTime(ParamBlk *parm) // currency GetHookTime()
{
	// PROCESS 64BIT INT
	LARGE_INTEGER time;
	time.LowPart = ftHookTime.dwLowDateTime;
	time.HighPart = ftHookTime.dwHighDateTime;

	// RETURN TIME AS CURRENCY
	_RetCurrency(time, 10);
}

void GetCurrentTime(ParamBlk *parm) // currency GetCurrentTime()
{
	// GET TIME
	FILETIME ft;
	GetSystemTimeAsFileTime(&ft);

	// PROCESS 64BIT INT
	LARGE_INTEGER time;
	time.LowPart = ft.dwLowDateTime;
	time.HighPart = ft.dwHighDateTime;

	// RETURN TIME AS CURRENCY
	_RetCurrency(time, 10);
}

// UNLOAD EVENT
void Unloadlib(ParamBlk *parm)
{
	// UNHOOK ALL HOOKS
	if(hKeyboardHook) UnhookWindowsHookEx(hKeyboardHook);
	if(hMouseHook) UnhookWindowsHookEx(hMouseHook);
	hKeyboardHook = 0;
	hMouseHook = 0;
}

FoxInfo libFoxInfo[] = {
	{"GETCURRENTTIME", (FPFI) GetCurrentTime, 0, ""},
	{"INSTALLHOOKS", (FPFI) InstallHooks, 1, "L"},
	{"RESETHOOKTIME", (FPFI) ResetHookTime, 0, ""},
	{"GETHOOKTIME", (FPFI) GetHookTime, 0, ""},
	{"UNLOADLIB", (FPFI) Unloadlib, CALLONUNLOAD, ""},
};

extern "C" {
    // the FoxTable structure
    FoxTable _FoxTable = {
        (FoxTable  *) 0, sizeof(libFoxInfo)/sizeof(FoxInfo), libFoxInfo
    };
}
--------------------------------------
You will of course have to compile this FLL yourself.

To use, you just install the hooks. To check the current idle time
you substract the "hook time" from the current time. Here is an example:
set library to idle.fll
InstallHooks(.t.)

public g_oIdleTimer
g_oIdleTimer = createobject("CheckIdleTime")

define class CheckIdleTime as timer
	Enabled = .t.
	Interval = 1000 && CHECK EVERY SECOND
	procedure Timer
		activate screen
		? "Current Idle Time in ms: ", GetCurrentTime() - GetHookTime()
	endproc
enddefine
-------------------------------------
In this example the idle time will be reset whenever a key is pressed or the mouse is moved. After thirty minutes you could then quit the application. Note that certain forms of quiting are more reliable than others: CLEAR EVENTS might work in most cases, but what if there is a messagebox open? A more reliable way of closing the application would be to use the API routine ExitProcess() but then of course you have to make sure all your data is saved!

Peter
Peter Stephens
Visual Records, Inc.

Lead Programmer for the general purpose record keeping system Visual Records. Written primarily in VFP 6.0 with a little C++.
Précédent
Suivant
Répondre
Fil
Voir

Click here to load this message in the networking platform