You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
188 lines
5.9 KiB
188 lines
5.9 KiB
/*--------------------------------------------------------------------------*
|
|
*
|
|
* 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);
|
|
}
|