|
|
/*--------------------------------------------------------------------------*
* * Microsoft Windows * Copyright (C) Microsoft Corporation, 1992 - 00 * * File: kbdnav.cpp * * Contents: Implementation of CKeyboardNavDelayTimer * * History: 4-May-2000 jeffro Created * *--------------------------------------------------------------------------*/
#include "stdafx.h"
#include "kbdnav.h"
#ifdef DBG
CTraceTag tagKeyboardNavDelay (_T("Keyboard Navigation"), _T("Keyboard Navigation Delay")); #endif
/*+-------------------------------------------------------------------------*
* CKeyboardNavDelayTimer::CKeyboardNavDelayTimer * * Constructs a CKeyboardNavDelayTimer object. *--------------------------------------------------------------------------*/
CKeyboardNavDelayTimer::CKeyboardNavDelayTimer () : m_nTimerID (0) { }
/*+-------------------------------------------------------------------------*
* CKeyboardNavDelayTimer::~CKeyboardNavDelayTimer * * Destroys a CKeyboardNavDelayTimer object. *--------------------------------------------------------------------------*/
CKeyboardNavDelayTimer::~CKeyboardNavDelayTimer () { ScStopTimer(); }
/*+-------------------------------------------------------------------------*
* CKeyboardNavDelayTimer::TimerProc * * Callback function called when a timer started by this class fires. *--------------------------------------------------------------------------*/
VOID CALLBACK CKeyboardNavDelayTimer::TimerProc ( HWND hwnd, UINT uMsg, UINT_PTR idEvent, DWORD dwTime) { CTimerMap& TimerMap = GetTimerMap();
/*
* locate the CKeyboardNavDelayTimer object corresponding to this timer event */ CTimerMap::iterator itTimer = TimerMap.find (idEvent);
// ASSERT(itTimer != TimerMap.end());
// The above assertion is not valid because: (From the SDK docs):
// The KillTimer function does not remove WM_TIMER messages already posted to the message queue.
if (itTimer != TimerMap.end()) { CKeyboardNavDelayTimer *pNavDelay = itTimer->second;
if (pNavDelay != NULL) { Trace (tagKeyboardNavDelay, _T ("Timer fired: id=%d"), pNavDelay->m_nTimerID); pNavDelay->OnTimer(); } } }
/*+-------------------------------------------------------------------------*
* CKeyboardNavDelayTimer::ScStartTimer * * *--------------------------------------------------------------------------*/
SC CKeyboardNavDelayTimer::ScStartTimer() { DECLARE_SC (sc, _T("CKeyboardNavDelayTimer::ScStartTimer"));
/*
* shouldn't start a timer if it's started already */ ASSERT (m_nTimerID == 0);
/*
* Get the menu popout delay and use that for the delay before * changing the result pane. If the system doesn't support * SPI_GETMENUSHOWDELAY (i.e. Win95, NT4), use a value slightly * longer than the longer of keyboard repeat delay and keyboard * repeat rate. */ DWORD dwDelay;
if (!SystemParametersInfo (SPI_GETMENUSHOWDELAY, 0, &dwDelay, false)) { /*
* Get the keyboard delay and convert to milliseconds. The ordinal * range is from 0 (approximately 250 ms dealy) to 3 (approximately * 1 sec delay). The equation to convert from ordinal to approximate * milliseconds is: * * msec = (ordinal + 1) * 250; */ DWORD dwKeyboardDelayOrdinal; SystemParametersInfo (SPI_GETKEYBOARDDELAY, 0, &dwKeyboardDelayOrdinal, false); DWORD dwKeyboardDelay = (dwKeyboardDelayOrdinal + 1) * 250;
/*
* Get the keyboard speed and convert to milliseconds. The ordinal * range is from 0 (approximately 2.5 reps per second, or 400 msec * interval) to 31 (approximately 30 reps per second, or 33 msec * interval). (The documentation has this reversed.) The equation * to convert from ordinal to approximate milliseconds is: * * msec = (ordinal * -12) + 400; */ DWORD dwKeyboardRateOrdinal; SystemParametersInfo (SPI_GETKEYBOARDSPEED, 0, &dwKeyboardRateOrdinal, false); DWORD dwKeyboardRate = (dwKeyboardRateOrdinal * -12) + 400;
dwDelay = std::_MAX (dwKeyboardDelay, dwKeyboardRate) + 50; }
m_nTimerID = SetTimer(NULL, 0, dwDelay, TimerProc); if (m_nTimerID == 0) return (sc.FromLastError());
GetTimerMap()[m_nTimerID] = this; // set up the timer map.
Trace (tagKeyboardNavDelay, _T("Started new timer: id=%d, delay=%d milliseconds"), m_nTimerID, dwDelay);
return (sc); }
/*+-------------------------------------------------------------------------*
* CKeyboardNavDelayTimer::ScStopTimer * * Stops the timer running for this CKeyboardNavDelayTimer, if it is running *--------------------------------------------------------------------------*/
SC CKeyboardNavDelayTimer::ScStopTimer() { DECLARE_SC (sc, _T("CKeyboardNavDelayTimer::ScStopTimer"));
if (m_nTimerID != 0) { CTimerMap& TimerMap = GetTimerMap(); CTimerMap::iterator itTimer = TimerMap.find (m_nTimerID); ASSERT (itTimer != TimerMap.end());
TimerMap.erase (itTimer); Trace (tagKeyboardNavDelay, _T("Stopped timer: id=%d"), m_nTimerID); UINT_PTR nTimerID = m_nTimerID; m_nTimerID = 0;
if (!KillTimer (NULL, nTimerID)) return (sc.FromLastError()); }
return (sc); }
/*+-------------------------------------------------------------------------*
* CKeyboardNavDelayTimer::GetTimerMap * * Returns a reference to the data structure that maps timer IDs to * CKeyboardNavDelayTimer objects. *--------------------------------------------------------------------------*/
CKeyboardNavDelayTimer::CTimerMap& CKeyboardNavDelayTimer::GetTimerMap() { static CTimerMap map; return (map); }
|