425 lines
10 KiB
C++
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);
|
||
|
}
|