WindowsXP-SP1/windows/oleacc/oleacc/alttab.cpp
2020-09-30 16:53:49 +02:00

425 lines
10 KiB
C++

// Copyright (c) 1996-1999 Microsoft Corporation
// --------------------------------------------------------------------------
//
// ALTTAB.CPP
//
// Switch window handler
//
// --------------------------------------------------------------------------
#include "oleacc_p.h"
#include "default.h"
#include "client.h"
#include "alttab.h"
// --------------------------------------------------------------------------
//
// CreateSwitchClient()
//
// --------------------------------------------------------------------------
HRESULT CreateSwitchClient(HWND hwnd, long idChild, REFIID riid, void** ppvSwitch)
{
CAltTab* palttab;
HRESULT hr;
InitPv(ppvSwitch);
palttab = new CAltTab(hwnd, idChild);
if (!palttab)
return(E_OUTOFMEMORY);
hr = palttab->QueryInterface(riid, ppvSwitch);
if (!SUCCEEDED(hr))
delete palttab;
return(hr);
}
// --------------------------------------------------------------------------
//
// CAltTab::CAltTab()
//
// NOTE: We initialize with the # of items at the start, not every time
// someone makes a call. People should never hang on to a pointer to one
// of these babies. On NT, the switch window is created and destroyed
// repeatedly.
//
// --------------------------------------------------------------------------
CAltTab::CAltTab(HWND hwnd, long idChildCur)
: CClient( CLASS_SwitchClient )
{
ALTTABINFO ati;
Initialize(hwnd, idChildCur);
if (MyGetAltTabInfo(hwnd, -1, &ati, NULL, 0))
{
m_cChildren = ati.cItems;
m_cColumns = ati.cColumns;
m_cRows = ati.cRows;
}
}
// --------------------------------------------------------------------------
//
// CAltTab::get_accName()
//
// --------------------------------------------------------------------------
STDMETHODIMP CAltTab::get_accName(VARIANT varChild, BSTR* pszName)
{
InitPv(pszName);
//
// Validate
//
if (!ValidateChild(&varChild))
return(E_INVALIDARG);
if (!varChild.lVal)
return(HrCreateString(STR_ALTTAB_NAME, pszName));
else
{
ALTTABINFO ati;
TCHAR szItem[80];
if (!MyGetAltTabInfo(m_hwnd, varChild.lVal-1, &ati, szItem,
ARRAYSIZE(szItem)))
return(S_FALSE);
*pszName = TCharSysAllocString(szItem);
if (! *pszName)
return(E_OUTOFMEMORY);
}
return(S_OK);
}
// --------------------------------------------------------------------------
//
// CAltTab::get_accRole()
//
// --------------------------------------------------------------------------
STDMETHODIMP CAltTab::get_accRole(VARIANT varChild, VARIANT* pvarRole)
{
InitPvar(pvarRole);
//
// Validate
//
if (!ValidateChild(&varChild))
return(E_INVALIDARG);
pvarRole->vt = VT_I4;
if (varChild.lVal)
pvarRole->lVal = ROLE_SYSTEM_LISTITEM;
else
pvarRole->lVal = ROLE_SYSTEM_LIST;
return(S_OK);
}
// --------------------------------------------------------------------------
//
// CAltTab::get_accState()
//
// --------------------------------------------------------------------------
STDMETHODIMP CAltTab::get_accState(VARIANT varChild, VARIANT* pvarState)
{
ALTTABINFO ati;
InitPvar(pvarState);
if (! ValidateChild(&varChild))
return(E_INVALIDARG);
if (! varChild.lVal)
return(CClient::get_accState(varChild, pvarState));
// Get the item, is this the one with the focus?
pvarState->vt = VT_I4;
varChild.lVal--;
if (! MyGetAltTabInfo(m_hwnd, varChild.lVal, &ati, NULL, 0))
pvarState->lVal = STATE_SYSTEM_INVISIBLE;
else
{
pvarState->lVal = 0;
// If this item is off the end, pretend that it's 'clipped'.
if( varChild.lVal >= ati.cColumns * ati.cRows )
pvarState->lVal |= STATE_SYSTEM_INVISIBLE | STATE_SYSTEM_OFFSCREEN;
if (((varChild.lVal % ati.cColumns) == ati.iColFocus) &&
((varChild.lVal / ati.cColumns) == ati.iRowFocus))
pvarState->lVal |= STATE_SYSTEM_FOCUSED;
pvarState->lVal |= STATE_SYSTEM_FOCUSABLE;
}
return(S_OK);
}
// --------------------------------------------------------------------------
//
// CAltTab::get_accFocus()
//
// --------------------------------------------------------------------------
STDMETHODIMP CAltTab::get_accFocus(VARIANT * pvarFocus)
{
ALTTABINFO ati;
InitPvar(pvarFocus);
//
// Get the alt-tab info
//
if (!MyGetAltTabInfo(m_hwnd, -1, &ati, NULL, 0))
return(S_FALSE);
pvarFocus->vt = VT_I4;
pvarFocus->lVal = (ati.iRowFocus * m_cColumns) + ati.iColFocus + 1;
return(S_OK);
}
// --------------------------------------------------------------------------
//
// CAltTab::get_accDefaultAction()
//
// The default action of a tasklist item is to switch to its window
//
// --------------------------------------------------------------------------
STDMETHODIMP CAltTab::get_accDefaultAction(VARIANT varChild, BSTR* pszDefA)
{
InitPv(pszDefA);
if (!ValidateChild(&varChild))
return(E_INVALIDARG);
if (!varChild.lVal)
return(CClient::get_accDefaultAction(varChild, pszDefA));
return(HrCreateString(STR_TAB_SWITCH, pszDefA));
}
// --------------------------------------------------------------------------
//
// CAltTab::accSelect()
//
// --------------------------------------------------------------------------
STDMETHODIMP CAltTab::accSelect(long lSelFlags, VARIANT varChild)
{
if (! ValidateChild(&varChild) ||
! ValidateSelFlags(lSelFlags))
return(E_INVALIDARG);
//
// Bogus! Manually change the focus in the alt-tab window.
//
return(E_NOTIMPL);
}
// --------------------------------------------------------------------------
//
// CAltTab::accLocation()
//
// --------------------------------------------------------------------------
STDMETHODIMP CAltTab::accLocation(long* pxLeft, long* pyTop, long* pcxWidth,
long* pcyHeight, VARIANT varChild)
{
ALTTABINFO ati;
InitAccLocation(pxLeft, pyTop, pcxWidth, pcyHeight);
//
// Validate
//
if (!ValidateChild(&varChild))
return(E_INVALIDARG);
if (!varChild.lVal)
return(CClient::accLocation(pxLeft, pyTop, pcxWidth, pcyHeight, varChild));
--varChild.lVal;
//
// Figure out where the item is.
//
if (! MyGetAltTabInfo(m_hwnd, varChild.lVal, &ati, NULL, 0))
return(S_FALSE);
ClientToScreen(m_hwnd, &ati.ptStart);
*pxLeft = ati.ptStart.x + ((varChild.lVal % m_cColumns)*ati.cxItem);
*pyTop = ati.ptStart.y + ((varChild.lVal / m_cColumns)*ati.cyItem);
*pcxWidth = ati.cxItem;
*pcyHeight = ati.cyItem;
return(S_OK);
}
// --------------------------------------------------------------------------
//
// CAltTab::accNavigate()
//
// --------------------------------------------------------------------------
STDMETHODIMP CAltTab::accNavigate(long dwNavDir, VARIANT varStart, VARIANT* pvarEnd)
{
int iItem;
int delta;
InitPvar(pvarEnd);
//
// Validate
//
if (!ValidateChild(&varStart) ||
!ValidateNavDir(dwNavDir, varStart.lVal))
return(E_INVALIDARG);
iItem = 0;
if (dwNavDir == NAVDIR_FIRSTCHILD)
iItem = 1;
else if (dwNavDir == NAVDIR_LASTCHILD)
iItem = m_cChildren;
else if (!varStart.lVal)
return(CClient::accNavigate(dwNavDir, varStart, pvarEnd));
else
{
switch (dwNavDir)
{
case NAVDIR_NEXT:
iItem = varStart.lVal+1;
if (iItem > m_cChildren)
iItem = 0;
break;
case NAVDIR_PREVIOUS:
iItem = varStart.lVal - 1;
break;
case NAVDIR_LEFT:
delta = -1;
goto MultiColumnMove;
case NAVDIR_RIGHT:
delta = 1;
goto MultiColumnMove;
case NAVDIR_UP:
delta = -m_cColumns;
goto MultiColumnMove;
case NAVDIR_DOWN:
delta = m_cColumns;
MultiColumnMove:
iItem = varStart.lVal + delta;
if ((iItem < 1) || (iItem > m_cChildren))
iItem = 0;
break;
}
}
if (iItem)
{
pvarEnd->vt = VT_I4;
pvarEnd->lVal = iItem;
}
return(iItem ? S_OK : S_FALSE);
}
// --------------------------------------------------------------------------
//
// CAltTab::accHitTest()
//
// --------------------------------------------------------------------------
STDMETHODIMP CAltTab::accHitTest(long x, long y, VARIANT* pvarHit)
{
ALTTABINFO ati;
RECT rc;
POINT pt;
int iColHit, iRowHit;
InitPvar(pvarHit);
if (!MyGetAltTabInfo(m_hwnd, -1, &ati, NULL, 0))
return(S_FALSE);
//
// Is the point in our client at all?
//
MyGetRect(m_hwnd, &rc, FALSE);
pt.x = x;
pt.y = y;
ScreenToClient(m_hwnd, &pt);
if (!PtInRect(&rc, pt) ||
(pt.x < ati.ptStart.x) ||
(pt.y < ati.ptStart.y))
return(S_FALSE);
//
// Does this lie in an item?
//
iColHit = (pt.x - ati.ptStart.x) / ati.cxItem;
iRowHit = (pt.y - ati.ptStart.y) / ati.cyItem;
if ((iColHit >= m_cColumns) ||
(iRowHit >= m_cRows))
return(S_FALSE);
//
// Phew. Return it.
//
pvarHit->vt = VT_I4;
pvarHit->lVal = (iRowHit * m_cColumns) + iColHit + 1;
return(S_OK);
}
// --------------------------------------------------------------------------
//
// CAltTab::accDoDefaultAction()
//
// --------------------------------------------------------------------------
STDMETHODIMP CAltTab::accDoDefaultAction(VARIANT varChild)
{
if (!ValidateChild(&varChild))
return(E_INVALIDARG);
if (!varChild.lVal)
return(CClient::accDoDefaultAction(varChild));
return(E_NOTIMPL);
}