|
|
#include "shellprv.h"
#include "ids.h"
#include <oleacc.h>
#ifndef POINTSPERRECT
#define POINTSPERRECT (sizeof(RECT)/sizeof(POINT))
#endif
#define TESTKEYSTATE(vk) ((GetKeyState(vk) & 0x8000)!=0)
#define LINKCOLOR_BKGND COLOR_WINDOW
#define LINKCOLOR_ENABLED GetSysColor(COLOR_HOTLIGHT)
#define LINKCOLOR_DISABLED GetSysColor(COLOR_GRAYTEXT)
#define CF_SETCAPTURE 0x0001
#define CF_SETFOCUS 0x0002
void _InitializeUISTATE(IN HWND hwnd, IN OUT UINT* puFlags); BOOL _HandleWM_UPDATEUISTATE(IN WPARAM wParam, IN LPARAM lParam, IN OUT UINT* puFlags);
// common IAccessible implementation.
class CAccessibleBase : public IAccessible, public IOleWindow { public: CAccessibleBase(const HWND& hwnd) : _cRef(1), _ptiAcc(NULL), _hwnd(hwnd) { DllAddRef(); } virtual ~CAccessibleBase() { DllRelease(); ATOMICRELEASE(_ptiAcc); }
// IUnknown
STDMETHODIMP QueryInterface(REFIID riid, void** ppvObj); STDMETHODIMP_(ULONG) AddRef(); STDMETHODIMP_(ULONG) Release();
// IOleWindow
STDMETHODIMP GetWindow(HWND* phwnd); STDMETHODIMP ContextSensitiveHelp(BOOL fEnterMode) { return E_NOTIMPL; }
// IDispatch
STDMETHODIMP GetTypeInfoCount(UINT * pctinfo); STDMETHODIMP GetTypeInfo(UINT itinfo, LCID lcid, ITypeInfo** pptinfo); STDMETHODIMP GetIDsOfNames(REFIID riid, OLECHAR** rgszNames, UINT cNames, LCID lcid, DISPID * rgdispid); STDMETHODIMP Invoke(DISPID dispidMember, REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS * pdispparams, VARIANT * pvarResult, EXCEPINFO * pexcepinfo, UINT * puArgErr); // IAccessible
STDMETHODIMP get_accParent(IDispatch ** ppdispParent); STDMETHODIMP get_accChildCount(long * pcChildren); STDMETHODIMP get_accChild(VARIANT varChildIndex, IDispatch ** ppdispChild); STDMETHODIMP get_accValue(VARIANT varChild, BSTR* pbstrValue); STDMETHODIMP get_accDescription(VARIANT varChild, BSTR * pbstrDescription); STDMETHODIMP get_accRole(VARIANT varChild, VARIANT *pvarRole); STDMETHODIMP get_accState(VARIANT varChild, VARIANT *pvarState); STDMETHODIMP get_accHelp(VARIANT varChild, BSTR* pbstrHelp); STDMETHODIMP get_accHelpTopic(BSTR* pbstrHelpFile, VARIANT varChild, long* pidTopic); STDMETHODIMP get_accKeyboardShortcut(VARIANT varChild, BSTR* pbstrKeyboardShortcut); STDMETHODIMP get_accFocus(VARIANT FAR * pvarFocusChild); STDMETHODIMP get_accSelection(VARIANT FAR * pvarSelectedChildren); STDMETHODIMP get_accDefaultAction(VARIANT varChild, BSTR* pbstrDefaultAction); STDMETHODIMP accSelect(long flagsSelect, VARIANT varChild); STDMETHODIMP accLocation(long* pxLeft, long* pyTop, long* pcxWidth, long* pcyHeight, VARIANT varChild); STDMETHODIMP accNavigate(long navDir, VARIANT varStart, VARIANT * pvarEndUpAt); STDMETHODIMP accHitTest(long xLeft, long yTop, VARIANT * pvarChildAtPoint); STDMETHODIMP put_accName(VARIANT varChild, BSTR bstrName); STDMETHODIMP put_accValue(VARIANT varChild, BSTR bstrValue);
protected: virtual UINT GetDefaultActionStringID() const = 0; private: LONG _cRef; ITypeInfo* _ptiAcc; const HWND& _hwnd;
#define VALIDATEACCCHILD(varChild, idChild, hrFail) \
if (!(VT_I4 == varChild.vt && idChild == varChild.lVal)) {return hrFail;}
};
#define TEST_CAPTURE(fTest) ((_fCapture & fTest) != 0)
#define MODIFY_CAPTURE(fSet, fRemove) {if (fSet){_fCapture |= fSet;} if (fRemove){_fCapture &= ~fRemove;}}
#define RESET_CAPTURE() {_fCapture=0;}
// this API for compat with old clients of the shell32 link window. that is now
// in comctl32.dll
BOOL WINAPI LinkWindow_RegisterClass() { // get the comctl32 linkwindow, and point the old classname at it
INITCOMMONCONTROLSEX iccs = {sizeof(iccs), ICC_LINK_CLASS}; InitCommonControlsEx(&iccs);
WNDCLASS wc; ULONG_PTR dwCookie = 0; SHActivateContext(&dwCookie);
BOOL bRet = GetClassInfo(NULL, WC_LINK, &wc); SHDeactivateContext(dwCookie); if (bRet) { wc.lpszClassName = TEXT("Link Window"); // old class name for old clients
RegisterClass(&wc); } return bRet; }
BOOL WINAPI LinkWindow_UnregisterClass(HINSTANCE) { return TRUE; }
#define GROUPBTN_BKCOLOR COLOR_WINDOW
#define CAPTION_VPADDING 3
#define CAPTION_HPADDING 2
#define GBM_SENDNOTIFY (GBM_LAST + 1)
// class CGroupBtn
class CGroupBtn : public CAccessibleBase
{ // all members private:
CGroupBtn(HWND hwnd); ~CGroupBtn();
// IAccessible specialization
STDMETHODIMP get_accName(VARIANT varChild, BSTR* pbstrName); STDMETHODIMP accDoDefaultAction(VARIANT varChild);
// CAccessibleBase overrides
UINT GetDefaultActionStringID() const { return IDS_GROUPBTN_DEFAULTACTION; }
// window procedures
static LRESULT WINAPI s_GroupBtnWndProc(HWND, UINT, WPARAM, LPARAM); LRESULT WINAPI WndProc(HWND, UINT, WPARAM, LPARAM);
static LRESULT WINAPI s_BuddyProc(HWND, UINT, WPARAM, LPARAM);
// message handlers
void NcCreate(LPCREATESTRUCT lpcs); LRESULT NcCalcSize(BOOL, LPNCCALCSIZE_PARAMS); void NcPaint(HRGN); LRESULT NcMouseMove(WPARAM, LONG, LONG); LRESULT NcHitTest(LONG, LONG); LRESULT NcButtonDown(UINT nMsg, WPARAM nHittest, const POINTS& pts); LRESULT NcDblClick(UINT nMsg, WPARAM nHittest, LPARAM lParam); LRESULT ButtonUp(UINT nMsg, WPARAM nHittest, const POINTS& pts); void OnCaptureLost(HWND hwndNew) {RESET_CAPTURE();} LRESULT WindowPosChanging(LPWINDOWPOS); LRESULT OnSize(WPARAM, LONG, LONG); BOOL SetPlacement(PGBPLACEMENT); BOOL SetBuddy(HWND, ULONG); void SetText(LPCTSTR); int GetText(LPTSTR, int); int GetTextW(LPWSTR, int); int GetTextLength(); void SetFont(HFONT); HFONT GetFont();
// utility methods
static void _MapWindowRect(HWND hwnd, HWND hwndRelative, OUT LPRECT prcWindow); void _MapWindowRect(HWND hwndRelative, OUT LPRECT prcWindow); HCURSOR GetHandCursor(); void CalcCaptionSize(); BOOL CalcClientRect(IN OPTIONAL LPCRECT prcWindow, OUT LPRECT prcClient); BOOL CalcWindowSizeForClient(IN OPTIONAL LPCRECT prcClient, IN OPTIONAL LPCRECT prcWindow, IN LPCRECT prcNewClient, OUT LPSIZE psizeWindow);
void DoLayout(BOOL bNewBuddy = FALSE);
LONG EnableNotifications(BOOL bEnable); LRESULT SendNotify(int nCode, IN OPTIONAL NMHDR* pnmh = NULL); // instance and static data
HWND _hwnd; HWND _hwndBuddy; WNDPROC _pfnBuddy; ULONG _dwBuddyFlags; SIZE _sizeBuddyMargin; HFONT _hf; static ATOM _atom; LPTSTR _pszCaption; SIZE _sizeCaption; int _yDrop; BOOL _fDropped : 1, _fInLayout : 1; UINT _fCapture; UINT _fKeyboardCues; HCURSOR _hcurHand; LONG _cNotifyLocks;
friend ATOM GroupButton_RegisterClass(); friend HWND CreateGroupBtn(DWORD, LPCTSTR, DWORD, int x, int y, HWND hwndParent, UINT nID); };
ATOM WINAPI GroupButton_RegisterClass() { WNDCLASSEX wc = {0}; wc.cbSize = sizeof(wc); wc.style = CS_GLOBALCLASS; wc.lpfnWndProc = CGroupBtn::s_GroupBtnWndProc; wc.hInstance = HINST_THISDLL; wc.hCursor = LoadCursor(NULL, IDC_ARROW); wc.hbrBackground = (HBRUSH)(GROUPBTN_BKCOLOR+1); wc.lpszClassName = GROUPBUTTON_CLASS; RegisterClassEx(&wc); return (ATOM)TRUE; }
CGroupBtn::CGroupBtn(HWND hwnd) : CAccessibleBase(_hwnd), _hwnd(hwnd), _hwndBuddy(NULL), _pfnBuddy(NULL), _dwBuddyFlags(GBBF_HRESIZE|GBBF_VRESIZE), _fInLayout(FALSE), _hf(NULL), _pszCaption(NULL), _fDropped(TRUE), _fKeyboardCues(0), _yDrop(0), _fCapture(0), _hcurHand(NULL), _cNotifyLocks(0) { _sizeCaption.cx = _sizeCaption.cy = 0; _sizeBuddyMargin.cx = _sizeBuddyMargin.cy = 0; }
ATOM CGroupBtn::_atom = 0;
CGroupBtn::~CGroupBtn() { SetFont(NULL); SetText(NULL); }
// CGroupBtn IAccessible impl
STDMETHODIMP CGroupBtn::get_accName(VARIANT varChild, BSTR* pbstrName) { VALIDATEACCCHILD(varChild, CHILDID_SELF, E_INVALIDARG);
if (NULL == pbstrName) return E_POINTER; *pbstrName = 0;
int cch = GetTextLength(); if ((*pbstrName = SysAllocStringLen(NULL, cch + 1)) != NULL) { GetTextW(*pbstrName, cch + 1); return S_OK; } return E_OUTOFMEMORY; }
STDMETHODIMP CGroupBtn::accDoDefaultAction(VARIANT varChild) { VALIDATEACCCHILD(varChild, CHILDID_SELF, E_INVALIDARG); SendNotify(NM_RETURN); return S_OK; }
// CGroupBtn window impl
// WM_SETTEXT handler
void CGroupBtn::SetText(LPCTSTR pszText) { if (_pszCaption) { if (pszText && 0==lstrcmp(_pszCaption, pszText)) return; delete [] _pszCaption; _pszCaption = NULL; }
if (pszText && *pszText) { if ((_pszCaption = new TCHAR[lstrlen(pszText)+1]) != NULL) lstrcpy(_pszCaption, pszText); } if (IsWindow(_hwnd)) CalcCaptionSize(); }
// WM_GETTEXT handler
int CGroupBtn::GetText(LPTSTR pszText, int cchText) { int cch = 0; if (pszText && cchText > 0) { *pszText = 0; if (_pszCaption && lstrcpyn(pszText, _pszCaption, cchText)) cch = min(lstrlen(_pszCaption), cchText); } return cch; }
int CGroupBtn::GetTextW(LPWSTR pwszText, int cchText) { #ifdef UNICODE
return GetText(pwszText, cchText); #else //UNICODE
int cchRet = 0; LPSTR pszText = new CHAR[cchText]; if (pszText) { cchRet = GetText(pszText, cchText); if (cchRet) { SHAnsiToUnicode(pszText, pwszText, cchText); } delete [] pszText; } return cchRet;
#endif //UNICODE
}
// WM_GETTEXTLENGTH handler
int CGroupBtn::GetTextLength() { return (_pszCaption && *_pszCaption) ? lstrlen(_pszCaption) : 0 ; }
// WM_SETFONT handler
void CGroupBtn::SetFont(HFONT hf) { if (_hf) { DeleteObject(_hf); _hf = NULL; } _hf = hf; }
// WM_GETFONT handler
HFONT CGroupBtn::GetFont() { if (_hf == NULL) { // if we don't have a font, use the parent's font
HFONT hfParent = (HFONT)SendMessage(GetParent(_hwnd), WM_GETFONT, 0, 0); if (hfParent) { LOGFONT lf; if (GetObject(hfParent, sizeof(LOGFONT), &lf) >0) _hf = CreateFontIndirect(&lf); } } return _hf; }
// Hand cursor load
HCURSOR CGroupBtn::GetHandCursor() { if (!_hcurHand) _hcurHand = LoadCursor(NULL, IDC_HAND);
return _hcurHand; }
// Retrieves the window rect in relative coords.
void CGroupBtn::_MapWindowRect(HWND hwnd, HWND hwndRelative, OUT LPRECT prcWindow) { ASSERT(IsWindow(hwnd)); GetWindowRect(hwnd, prcWindow); MapWindowPoints(HWND_DESKTOP, hwndRelative, (LPPOINT)prcWindow, 2); }
// Retrieves the window rect in relative coords.
inline void CGroupBtn::_MapWindowRect(HWND hwndRelative, OUT LPRECT prcWindow) { _MapWindowRect(_hwnd, hwndRelative, prcWindow); }
// Caches the size of the caption 'bar'.
void CGroupBtn::CalcCaptionSize() { SIZE sizeCaption = {0,0}; LPCTSTR pszCaption = (_pszCaption && *_pszCaption) ? _pszCaption : TEXT("|"); HDC hdc;
// compute caption size based on window text:
if ((hdc = GetDC(_hwnd))) { HFONT hf = GetFont(), hfPrev = (HFONT)SelectObject(hdc, hf); if (GetTextExtentPoint32(hdc, pszCaption, lstrlen(pszCaption), &sizeCaption)) sizeCaption.cy += CAPTION_VPADDING; // add some vertical padding
SelectObject(hdc, hfPrev); ReleaseDC(_hwnd, hdc); }
_sizeCaption = sizeCaption; }
// Computes the size and position of the client area
BOOL CGroupBtn::CalcClientRect(IN OPTIONAL LPCRECT prcWindow, OUT LPRECT prcClient) { DWORD dwStyle = GetWindowLong(_hwnd, GWL_STYLE); RECT rcWindow;
if (!prcWindow) { // Get parent-relative coords
_MapWindowRect(GetParent(_hwnd), &rcWindow); prcWindow = &rcWindow; }
*prcClient = *prcWindow;
// compute client rectangle:
// allow for border
if (dwStyle & WS_BORDER) InflateRect(prcClient, -1, -1);
// allow for caption 'bar'
prcClient->top += _sizeCaption.cy;
// Normalize for NULL rect.
if (RECTWIDTH(*prcWindow) <=0) prcClient->left = prcClient->right = prcWindow->left; if (RECTHEIGHT(*prcWindow) <=0) prcClient->bottom = prcClient->top = prcWindow->top;
return TRUE; }
BOOL CGroupBtn::CalcWindowSizeForClient( IN OPTIONAL LPCRECT prcClient, IN OPTIONAL LPCRECT prcWindow, IN LPCRECT prcNewClient, OUT LPSIZE psizeWindow) { if (!(prcNewClient && psizeWindow)) { ASSERT(FALSE); return FALSE; }
RECT rcWindow, rcClient; if (NULL == prcWindow) { GetWindowRect(_hwnd, &rcWindow); prcWindow = &rcWindow; }
if (NULL == prcClient) { GetClientRect(_hwnd, &rcClient); prcClient = &rcClient; }
SIZE sizeDelta; sizeDelta.cx = RECTWIDTH(*prcWindow) - RECTWIDTH(*prcClient); sizeDelta.cy = RECTHEIGHT(*prcWindow) - RECTHEIGHT(*prcClient);
psizeWindow->cx = RECTWIDTH(*prcNewClient) + sizeDelta.cx; psizeWindow->cy = RECTHEIGHT(*prcNewClient) + sizeDelta.cy; return TRUE; }
// WM_WINDOWPOSCHANGING handler
LRESULT CGroupBtn::WindowPosChanging(LPWINDOWPOS pwp) { if (pwp->flags & SWP_NOSIZE) return DefWindowProc(_hwnd, WM_WINDOWPOSCHANGING, 0, (LPARAM)pwp);
// disallow sizing in buddy slave dimension(s).
if (IsWindow(_hwndBuddy) && _dwBuddyFlags & (GBBF_HSLAVE|GBBF_VSLAVE) && !_fInLayout) { RECT rcWindow, rcClient; BOOL fResizeBuddy = FALSE;
GetWindowRect(_hwnd, &rcWindow); GetClientRect(_hwnd, &rcClient);
// Prepare a buddy size data block
GBNQUERYBUDDYSIZE qbs; qbs.cy = pwp->cy - (RECTHEIGHT(rcWindow) - RECTHEIGHT(rcClient)); qbs.cx = pwp->cx - (RECTWIDTH(rcWindow) - RECTWIDTH(rcClient)); if (_dwBuddyFlags & GBBF_HSLAVE) // prevent external horz resizing
{ pwp->cx = RECTWIDTH(rcWindow); // If we're being resized in the vert dir, query for
// optimal buddy width for this height and adjust
if (_dwBuddyFlags & GBBF_VRESIZE && RECTHEIGHT(rcWindow) != pwp->cy) { if (SendNotify(GBN_QUERYBUDDYWIDTH, (NMHDR*)&qbs) && qbs.cx >= 0) { // if the owner wants the buddy width to change, do it now.
LONG cxNew = qbs.cx + (RECTWIDTH(rcWindow) - RECTWIDTH(rcClient)); fResizeBuddy = cxNew != pwp->cx; pwp->cx = cxNew; } } } if (_dwBuddyFlags & GBBF_VSLAVE) // prevent external vert resizing
{ pwp->cy = RECTHEIGHT(rcWindow); // If we're being resized in the horz dir, query for
// optimal buddy height for this horizontal and adjust
if (_dwBuddyFlags & GBBF_HRESIZE && RECTWIDTH(rcWindow) != pwp->cx) { if (SendNotify(GBN_QUERYBUDDYHEIGHT, (NMHDR*)&qbs) && qbs.cy >= 0) { LONG cyNew = qbs.cy + (RECTHEIGHT(rcWindow) - RECTHEIGHT(rcClient)); fResizeBuddy = cyNew != pwp->cy; pwp->cy = cyNew; } } }
if (fResizeBuddy) { _fInLayout = TRUE; SetWindowPos(_hwndBuddy, NULL, 0, 0, qbs.cx, qbs.cy, SWP_NOMOVE|SWP_NOZORDER|SWP_NOACTIVATE); _fInLayout = FALSE; } }
// enforce minimum height:
if (pwp->cy < _sizeCaption.cy) pwp->cy = _sizeCaption.cy;
return 0; }
LRESULT CGroupBtn::OnSize(WPARAM flags, LONG cx, LONG cy) { DoLayout(); return 0; }
void CGroupBtn::DoLayout(BOOL bNewBuddy) { if (!_fInLayout && IsWindow(_hwndBuddy)) { RECT rcWindow, rcThis, rcBuddy; DWORD dwSwpBuddy = SWP_NOACTIVATE, dwSwpThis = SWP_NOMOVE|SWP_NOZORDER|SWP_NOACTIVATE; BOOL fReposThis = FALSE; SIZE sizeNew;
GetClientRect(_hwnd, &rcThis); GetWindowRect(_hwnd, &rcWindow);
// get rectangles in parent coords
MapWindowPoints(_hwnd, GetParent(_hwnd), (LPPOINT)&rcThis, POINTSPERRECT); MapWindowPoints(HWND_DESKTOP, GetParent(_hwnd), (LPPOINT)&rcWindow, POINTSPERRECT); _MapWindowRect(_hwndBuddy, GetParent(_hwnd), &rcBuddy);
// If we need to reposition ourself to the buddy,
// calculate the new size now.
if (_dwBuddyFlags & (GBBF_HSLAVE|GBBF_VSLAVE)) CalcWindowSizeForClient(&rcThis, &rcWindow, &rcBuddy, &sizeNew);
// Resize buddy according to size.
if (_dwBuddyFlags & GBBF_HRESIZE) { rcBuddy.right = rcBuddy.left + RECTWIDTH(rcThis);
if (bNewBuddy && 0 == (_dwBuddyFlags & GBBF_VRESIZE)) { // query height
GBNQUERYBUDDYSIZE qbs; qbs.cx = RECTWIDTH(rcThis); qbs.cy = -1; if (SendNotify(GBN_QUERYBUDDYHEIGHT, (NMHDR*)&qbs) && qbs.cy >= 0) rcBuddy.bottom = rcBuddy.top + qbs.cy; } } else if (_dwBuddyFlags & GBBF_HSLAVE) { rcWindow.right = rcWindow.left + sizeNew.cx; fReposThis = TRUE; } if (_dwBuddyFlags & GBBF_VRESIZE) { rcBuddy.bottom = rcBuddy.top + RECTHEIGHT(rcThis);
if (bNewBuddy && 0 == (_dwBuddyFlags & GBBF_HRESIZE)) { // query width
GBNQUERYBUDDYSIZE qbs; qbs.cx = -1; qbs.cy = RECTHEIGHT(rcThis); if (SendNotify(GBN_QUERYBUDDYWIDTH, (NMHDR*)&qbs) && qbs.cx >= 0) rcBuddy.right = rcBuddy.left + qbs.cx; } } else if (_dwBuddyFlags & GBBF_VSLAVE) { rcWindow.bottom = rcWindow.top + sizeNew.cy; fReposThis = TRUE; } if (_dwBuddyFlags & GBBF_HSCROLL) { /* not implemented */ }
if (_dwBuddyFlags & GBBF_VSCROLL) { /* not implemented */ }
// reposition ourself and update our client rect.
if (fReposThis) { _fInLayout = TRUE; SetWindowPos(_hwnd, NULL, 0, 0, RECTWIDTH(rcWindow), RECTHEIGHT(rcWindow), dwSwpThis); _fInLayout = FALSE; GetClientRect(_hwnd, &rcThis); MapWindowPoints(_hwnd, GetParent(_hwnd), (LPPOINT)&rcThis, POINTSPERRECT); } // slide buddy into client area and reposition
OffsetRect(&rcBuddy, rcThis.left - rcBuddy.left, rcThis.top - rcBuddy.top); _fInLayout = TRUE; SetWindowPos(_hwndBuddy, _hwnd, rcBuddy.left, rcBuddy.top, RECTWIDTH(rcBuddy), RECTHEIGHT(rcBuddy), dwSwpBuddy); _fInLayout = FALSE; } }
// GBM_SETPLACEMENT handler
BOOL CGroupBtn::SetPlacement(PGBPLACEMENT pgbp) { RECT rcWindow, rcClient; SIZE sizeDelta = {0}; DWORD dwFlags = SWP_NOZORDER|SWP_NOACTIVATE;
_MapWindowRect(GetParent(_hwnd), &rcWindow); CalcClientRect(&rcWindow, &rcClient);
// establish whether we need to resize
if ((pgbp->x < 0 || pgbp->x == rcWindow.left) && (pgbp->y < 0 || pgbp->y == rcWindow.top)) dwFlags |= SWP_NOMOVE;
// compute horizontal placement
if (pgbp->x >= 0) // fixed horz origin requested
OffsetRect(&rcWindow, pgbp->x - rcWindow.left, 0);
if (pgbp->cx >= 0) // fixed width requested
rcWindow.right = rcWindow.left + pgbp->cx; else { if (pgbp->cxBuddy >= 0) // client width requested
sizeDelta.cx = pgbp->cxBuddy - RECTWIDTH(rcClient); rcWindow.right += sizeDelta.cx; } // compute vertical placement
if (pgbp->y >= 0) // fixed vert origin requested
OffsetRect(&rcWindow, 0, pgbp->y - rcWindow.top);
if (pgbp->cy >= 0) // fixed height requested
rcWindow.bottom = rcWindow.top + pgbp->cy; else { if (pgbp->cyBuddy >= 0) // client height requested
sizeDelta.cy = pgbp->cyBuddy - RECTHEIGHT(rcClient); rcWindow.bottom += sizeDelta.cy; }
if (pgbp->hdwp && (-1 != (LONG_PTR)pgbp->hdwp)) DeferWindowPos(pgbp->hdwp, _hwnd, NULL, rcWindow.left, rcWindow.top, RECTWIDTH(rcWindow), RECTHEIGHT(rcWindow), dwFlags); else SetWindowPos(_hwnd, NULL, rcWindow.left, rcWindow.top, RECTWIDTH(rcWindow), RECTHEIGHT(rcWindow), dwFlags);
// stuff resulting rects
pgbp->rcWindow = rcWindow; return CalcClientRect(&rcWindow, &pgbp->rcBuddy); }
BOOL CGroupBtn::SetBuddy(HWND hwnd, ULONG dwFlags) { // If we already have a buddy, unhook ourselves
//
if (_hwndBuddy) { if (IsWindow(_hwndBuddy) && _pfnBuddy) { SetWindowLongPtr(_hwndBuddy, GWLP_USERDATA, (LONG_PTR)NULL); SetWindowLongPtr(_hwndBuddy, GWLP_WNDPROC, (LONG_PTR)_pfnBuddy); } _hwndBuddy = NULL; _pfnBuddy = NULL; }
// Handle an invalid window...
if (!IsWindow(hwnd)) hwnd = NULL;
// If we're being buddy'd with a window, hook it
//
if (hwnd) { if (dwFlags & (GBBF_HSLAVE|GBBF_VSLAVE)) { // subclass the buddy
_pfnBuddy = (WNDPROC)SetWindowLongPtr(hwnd, GWLP_WNDPROC, (LONG_PTR)s_BuddyProc); SetWindowLongPtr(hwnd, GWLP_USERDATA, (LONG_PTR)this); }
_hwndBuddy = hwnd; _dwBuddyFlags = dwFlags; DoLayout(TRUE); }
return TRUE; }
// WM_NCCREATE handler
void CGroupBtn::NcCreate(LPCREATESTRUCT lpcs) { // assign user data
SetWindowLongPtr(_hwnd, GWLP_USERDATA, (LONG_PTR)this); // enforce window style bits
lpcs->style |= WS_CLIPCHILDREN|WS_CLIPSIBLINGS; lpcs->dwExStyle |= WS_EX_TRANSPARENT; SetWindowLong(_hwnd, GWL_STYLE, lpcs->style); SetWindowLong(_hwnd, GWL_EXSTYLE, lpcs->dwExStyle);
// enforce min height
SetText(lpcs->lpszName); if (lpcs->cy < _sizeCaption.cy) { lpcs->cy = _sizeCaption.cy; SetWindowPos(_hwnd, NULL, 0,0, lpcs->cx, lpcs->cy, SWP_NOMOVE|SWP_NOZORDER|SWP_NOACTIVATE); } }
// WM_NCCALCSIZE handler
LRESULT CGroupBtn::NcCalcSize(BOOL fCalcValidRects, LPNCCALCSIZE_PARAMS pnccs) { LRESULT lRet = FALSE; RECT rcClient;
if (fCalcValidRects && CalcClientRect(&pnccs->rgrc[0], &rcClient)) { pnccs->rgrc[1] = pnccs->rgrc[2]; pnccs->rgrc[0] = pnccs->rgrc[2] = rcClient; return WVR_VALIDRECTS; } return lRet; }
// WM_NCPAINT handler
void CGroupBtn::NcPaint(HRGN hrgn) { RECT rcWindow; DWORD dwStyle = GetWindowLong(_hwnd, GWL_STYLE); HDC hdc;
GetWindowRect(_hwnd, &rcWindow); OffsetRect(&rcWindow, -rcWindow.left, -rcWindow.top);
if ((hdc = GetWindowDC(_hwnd)) != NULL) { if (dwStyle & WS_BORDER) { HBRUSH hbr = CreateSolidBrush(COLOR_WINDOWFRAME); if (hbr) { FrameRect(hdc, &rcWindow, hbr); DeleteObject(hbr); } }
rcWindow.bottom = rcWindow.top + _sizeCaption.cy;
SetBkColor(hdc, GetSysColor(COLOR_HIGHLIGHT)); SetTextColor(hdc, GetSysColor(COLOR_HIGHLIGHTTEXT));
ExtTextOut(hdc, rcWindow.left, rcWindow.top, ETO_OPAQUE, &rcWindow, NULL, 0, NULL);
InflateRect(&rcWindow, -CAPTION_HPADDING, -(CAPTION_VPADDING/2)); HFONT hfPrev = (HFONT)SelectObject(hdc, GetFont()); ExtTextOut(hdc, rcWindow.left, rcWindow.top, ETO_OPAQUE, &rcWindow, _pszCaption, _pszCaption ? lstrlen(_pszCaption) : 0, NULL); SelectObject(hdc, hfPrev);
if (0 == (_fKeyboardCues & UISF_HIDEFOCUS)) { if (GetFocus() == _hwnd) { rcWindow.right = rcWindow.left + _sizeCaption.cx + 1; InflateRect(&rcWindow, 1, 0); DrawFocusRect(hdc, &rcWindow); } }
ReleaseDC(_hwnd, hdc); } }
// WM_NCMOUSEMOVE handler
LRESULT CGroupBtn::NcMouseMove(WPARAM nHittest, LONG x, LONG y) { if (HTCAPTION == nHittest) { RECT rc; POINT pt; GetWindowRect(_hwnd, &rc); rc.bottom = rc.top + _sizeCaption.cy; rc.right = rc.left + _sizeCaption.cx; InflateRect(&rc, 0, -(CAPTION_VPADDING/2)); pt.x = x; pt.y = y;
if (PtInRect(&rc, pt)) { HCURSOR hc = GetHandCursor(); if (hc != NULL) { SetCursor(hc); return 0; } } } return DefWindowProc(_hwnd, WM_NCMOUSEMOVE, nHittest, MAKELPARAM(x, y)); }
// WM_NCHITTEST handler
LRESULT CGroupBtn::NcHitTest(LONG x, LONG y) { POINT pt; RECT rc, rcClient; DWORD dwStyle = GetWindowLong(_hwnd, GWL_STYLE); pt.x = x; pt.y = y;
GetWindowRect(_hwnd, &rc); CalcClientRect(&rc, &rcClient);
if (PtInRect(&rcClient, pt)) return HTTRANSPARENT;
if (PtInRect(&rc, pt)) { if (dwStyle & WS_BORDER) { if (pt.x == rc.left || pt.x == rc.right || pt.y == rc.bottom) return HTBORDER; } return HTCAPTION; } return HTNOWHERE; }
LRESULT CGroupBtn::NcButtonDown(UINT nMsg, WPARAM nHittest, const POINTS& pts) { LRESULT lRet = 0;
if (HTCAPTION == nHittest) { SetCursor(GetHandCursor()); MODIFY_CAPTURE(CF_SETCAPTURE, 0);
if (GetFocus() != _hwnd) { MODIFY_CAPTURE(CF_SETFOCUS, 0); EnableNotifications(FALSE); // so the host doesn't reposition the link.
SetFocus(_hwnd); EnableNotifications(TRUE); }
SetCapture(_hwnd); } else lRet = DefWindowProc(_hwnd, nMsg, nHittest, MAKELONG(pts.x, pts.y)); return lRet; }
LRESULT CGroupBtn::ButtonUp(UINT nMsg, WPARAM nHittest, const POINTS& pts) { if (TEST_CAPTURE(CF_SETCAPTURE)) { ReleaseCapture(); MODIFY_CAPTURE(0, CF_SETCAPTURE);
POINT ptScrn; ptScrn.x = pts.x; ptScrn.y = pts.y; MapWindowPoints(_hwnd, HWND_DESKTOP, &ptScrn, 1);
LRESULT nHittest = SendMessage(_hwnd, WM_NCHITTEST, 0, MAKELONG(ptScrn.x, ptScrn.y));
if (HTCAPTION == nHittest) { switch (nMsg) { case WM_LBUTTONUP: SendNotify(NM_CLICK); break; case WM_RBUTTONUP: SendNotify(NM_RCLICK); break; } } }
if (TEST_CAPTURE(CF_SETFOCUS)) { MODIFY_CAPTURE(0, CF_SETFOCUS); if (GetFocus() == _hwnd) // if we still have the focus...
SendNotify(NM_SETFOCUS); } return 0; }
// Non-client mouse click/dblclk handler
LRESULT CGroupBtn::NcDblClick(UINT nMsg, WPARAM nHittest, LPARAM lParam) { LRESULT lRet = 0; if (HTCAPTION == nHittest) { SetFocus(_hwnd);
lRet = DefWindowProc(_hwnd, nMsg, HTCLIENT, lParam);
switch (nMsg) { case WM_NCLBUTTONDBLCLK: SendNotify(NM_DBLCLK); break; case WM_NCRBUTTONDBLCLK: SendNotify(NM_RDBLCLK); break; } } else lRet = DefWindowProc(_hwnd, nMsg, nHittest, lParam);
return lRet; }
LONG CGroupBtn::EnableNotifications(BOOL bEnable) { if (bEnable) { if (_cNotifyLocks > 0) _cNotifyLocks--; } else _cNotifyLocks++; return _cNotifyLocks; }
// WM_NOTIFY transmit helper
LRESULT CGroupBtn::SendNotify(int nCode, IN OPTIONAL NMHDR* pnmh) { if (0 == _cNotifyLocks) { NMHDR hdr; if (NULL == pnmh) pnmh = &hdr;
pnmh->hwndFrom = _hwnd; pnmh->idFrom = GetDlgCtrlID(_hwnd); pnmh->code = nCode; return SendMessage(GetParent(_hwnd), WM_NOTIFY, hdr.idFrom, (LPARAM)pnmh); } return 0; }
LRESULT CALLBACK CGroupBtn::s_GroupBtnWndProc(HWND hDlg, UINT wMsg, WPARAM wParam, LPARAM lParam) { CGroupBtn *pThis = (CGroupBtn *)GetWindowLongPtr(hDlg, GWLP_USERDATA);
if (!pThis && (WM_NCCREATE == wMsg)) { pThis = new CGroupBtn(hDlg); SetWindowLongPtr(hDlg, GWLP_USERDATA, (LPARAM)pThis); }
if (pThis) return pThis->WndProc(hDlg, wMsg, wParam, lParam);
return DefWindowProc(hDlg, wMsg, wParam, lParam); }
LRESULT CGroupBtn::WndProc(HWND hwnd, UINT nMsg, WPARAM wParam, LPARAM lParam) { LRESULT lRet = 0; switch (nMsg) { case WM_NCHITTEST: { POINTS pts = MAKEPOINTS(lParam); return NcHitTest(pts.x, pts.y); }
case WM_NCMOUSEMOVE: { POINTS pts = MAKEPOINTS(lParam); return NcMouseMove(wParam, pts.x, pts.y); }
case WM_NCCALCSIZE: return NcCalcSize((BOOL)wParam, (LPNCCALCSIZE_PARAMS)lParam);
case WM_NCPAINT: NcPaint((HRGN)wParam); return 0;
case WM_WINDOWPOSCHANGING: return WindowPosChanging((LPWINDOWPOS)lParam);
case WM_SIZE: { POINTS pts = MAKEPOINTS(lParam); return OnSize(wParam, pts.x, pts.y); }
case WM_DESTROY: if (IsWindow(_hwndBuddy)) DestroyWindow(_hwndBuddy); break;
case WM_ERASEBKGND: return TRUE; // transparent: no erase bkgnd
case WM_NCLBUTTONDOWN: case WM_NCRBUTTONDOWN: { POINTS pts = MAKEPOINTS(lParam); return NcButtonDown(nMsg, wParam, pts); }
case WM_LBUTTONUP: case WM_RBUTTONUP: { POINTS pts = MAKEPOINTS(lParam); return ButtonUp(nMsg, wParam, pts); }
case WM_NCLBUTTONDBLCLK: case WM_NCRBUTTONDBLCLK: return NcDblClick(nMsg, wParam, lParam);
case WM_SHOWWINDOW: if (IsWindow(_hwndBuddy)) ShowWindow(_hwndBuddy, wParam ? SW_SHOW : SW_HIDE); break;
case WM_SETTEXT: SetText((LPCTSTR)lParam); return TRUE;
case WM_GETTEXT: return GetText((LPTSTR)lParam, (int)wParam);
case WM_SETFONT: SetFont((HFONT)wParam); if (lParam /* fRedraw */) InvalidateRect(hwnd, NULL, TRUE); break;
case WM_CAPTURECHANGED: if (lParam /* NULL if we called ReleaseCapture() */) OnCaptureLost((HWND)lParam); break;
case WM_SETFOCUS: NcPaint((HRGN)1); SendNotify(NM_SETFOCUS); break; case WM_KILLFOCUS: NcPaint((HRGN)1); SendNotify(NM_KILLFOCUS); break;
case WM_GETDLGCODE: { MSG* pmsg; lRet = DLGC_BUTTON|DLGC_UNDEFPUSHBUTTON;
if ((pmsg = (MSG*)lParam)) { if ((WM_KEYDOWN == pmsg->message || WM_KEYUP == pmsg->message)) { switch (pmsg->wParam) { case VK_RETURN: case VK_SPACE: lRet |= DLGC_WANTALLKEYS; break; } } else if (WM_CHAR == pmsg->message && VK_RETURN == pmsg->wParam) { // Eat VK_RETURN WM_CHARs; we don't want
// Dialog manager to beep when IsDialogMessage gets it.
return lRet |= DLGC_WANTMESSAGE; } }
return lRet; }
case WM_KEYDOWN: case WM_KEYUP: case WM_CHAR: switch (wParam) { case VK_RETURN: case VK_SPACE: if (WM_KEYDOWN == nMsg) SendNotify(NM_RETURN); return 0; } break;
case WM_UPDATEUISTATE: if (_HandleWM_UPDATEUISTATE(wParam, lParam, &_fKeyboardCues)) SendMessage(hwnd, WM_NCPAINT, 1, 0); break;
case GBM_SETPLACEMENT: if (lParam) return SetPlacement((PGBPLACEMENT)lParam); return 0;
case GBM_SETDROPSTATE: // WPARAM: BOOL fDropped, LPARAM: n/a, return: BOOL
return 0;
case GBM_GETDROPSTATE: // WPARAM: n/a, LPARAM: n/a, return: BOOL fDropped
return 0;
case GBM_SENDNOTIFY: SendNotify((int)wParam); break;
case WM_NCCREATE: NcCreate((LPCREATESTRUCT)lParam); break;
case WM_NCDESTROY: lRet = DefWindowProc(hwnd, nMsg, wParam, lParam); SetWindowPtr(hwnd, GWLP_USERDATA, NULL); _hwnd = NULL; Release(); return lRet;
case WM_CREATE: _InitializeUISTATE(hwnd, &_fKeyboardCues); SetText(((LPCREATESTRUCT)lParam)->lpszName); break;
case GBM_SETBUDDY: // WPARAM: HWND hwndBuddy, LPARAM: MAKELPARAM(cxMargin, cyMargin), return: BOOL
return SetBuddy((HWND)wParam, (ULONG)lParam);
case GBM_GETBUDDY: // WPARAM: n/a, LPARAM: n/a, return: HWND
return (LRESULT)_hwndBuddy;
default: // oleacc defs thunked for WINVER < 0x0500
if ((WM_GETOBJECT == nMsg) && (OBJID_CLIENT == (DWORD)lParam || OBJID_TITLEBAR == (DWORD)lParam)) return LresultFromObject(IID_IAccessible, wParam, SAFECAST(this, IAccessible*));
break; }
return DefWindowProc(hwnd, nMsg, wParam, lParam); }
LRESULT CGroupBtn::s_BuddyProc(HWND hwnd, UINT nMsg, WPARAM wParam, LPARAM lParam) { CGroupBtn *pBtn = (CGroupBtn*)GetWindowLongPtr(hwnd, GWLP_USERDATA);
switch (nMsg) { case WM_SIZE: { LRESULT lRet = CallWindowProc(pBtn->_pfnBuddy, hwnd, nMsg, wParam, lParam); if (!pBtn->_fInLayout) pBtn->DoLayout(); return lRet; }
case WM_DESTROY: { WNDPROC pfn = pBtn->_pfnBuddy; pBtn->SetBuddy(NULL, 0); return CallWindowProc(pfn, hwnd, nMsg, wParam, lParam); } } return pBtn->_pfnBuddy ? CallWindowProc(pBtn->_pfnBuddy, hwnd, nMsg, wParam, lParam) : 0; }
// CAccessibleBase IUnknown impl
STDMETHODIMP CAccessibleBase::QueryInterface(REFIID riid, void** ppvObj) { static const QITAB qit[] = { QITABENT(CAccessibleBase, IDispatch), QITABENT(CAccessibleBase, IAccessible), QITABENT(CAccessibleBase, IOleWindow), { 0 }, }; return QISearch(this, qit, riid, ppvObj); }
STDMETHODIMP_(ULONG) CAccessibleBase::AddRef() { return InterlockedIncrement(&_cRef); }
STDMETHODIMP_(ULONG) CAccessibleBase::Release() { ASSERT( 0 != _cRef ); ULONG cRef = InterlockedDecrement(&_cRef); if ( 0 == cRef ) { delete this; } return cRef; }
// CAccessibleBase IOleWindow impl
STDMETHODIMP CAccessibleBase::GetWindow(HWND* phwnd) { *phwnd = _hwnd; return IsWindow(_hwnd) ? S_OK : S_FALSE; }
// CAccessibleBase IDispatch impl
static HRESULT _accLoadTypeInfo(ITypeInfo** ppti) { ITypeLib* ptl; HRESULT hr = LoadTypeLib(L"oleacc.dll", &ptl);
if (SUCCEEDED(hr)) { hr = ptl->GetTypeInfoOfGuid(IID_IAccessible, ppti); ATOMICRELEASE(ptl); } return hr; }
STDMETHODIMP CAccessibleBase::GetTypeInfoCount(UINT * pctinfo) { *pctinfo = 1; return S_OK; }
STDMETHODIMP CAccessibleBase::GetTypeInfo(UINT itinfo, LCID lcid, ITypeInfo** pptinfo) { HRESULT hr = E_FAIL; if (NULL == _ptiAcc && FAILED((hr = _accLoadTypeInfo(&_ptiAcc)))) return hr;
*pptinfo = _ptiAcc; (*pptinfo)->AddRef(); return S_OK; }
STDMETHODIMP CAccessibleBase::GetIDsOfNames( REFIID riid, OLECHAR** rgszNames, UINT cNames, LCID lcid, DISPID * rgdispid) { HRESULT hr = E_FAIL;
if (IID_NULL != riid && IID_IAccessible != riid) return DISP_E_UNKNOWNINTERFACE;
if (NULL == _ptiAcc && FAILED((hr = _accLoadTypeInfo(&_ptiAcc)))) return hr;
return _ptiAcc->GetIDsOfNames(rgszNames, cNames, rgdispid); }
STDMETHODIMP CAccessibleBase::Invoke( DISPID dispidMember, REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS * pdispparams, VARIANT * pvarResult, EXCEPINFO * pexcepinfo, UINT * puArgErr) { HRESULT hr = E_FAIL; if (IID_NULL != riid && IID_IAccessible != riid) return DISP_E_UNKNOWNINTERFACE;
if (NULL == _ptiAcc && FAILED((hr = _accLoadTypeInfo(&_ptiAcc)))) return hr;
return _ptiAcc->Invoke(this, dispidMember, wFlags, pdispparams, pvarResult, pexcepinfo, puArgErr); }
STDMETHODIMP CAccessibleBase::get_accParent(IDispatch ** ppdispParent) { *ppdispParent = NULL; if (IsWindow(_hwnd)) return AccessibleObjectFromWindow(_hwnd, OBJID_WINDOW, IID_PPV_ARG(IDispatch, ppdispParent)); return S_FALSE; }
STDMETHODIMP CAccessibleBase::get_accChildCount(long * pcChildren) { *pcChildren = 0; return S_OK; }
STDMETHODIMP CAccessibleBase::get_accChild(VARIANT varChildIndex, IDispatch ** ppdispChild) { *ppdispChild = NULL; return S_FALSE; }
STDMETHODIMP CAccessibleBase::get_accValue(VARIANT varChild, BSTR* pbstrValue) { VALIDATEACCCHILD(varChild, CHILDID_SELF, E_INVALIDARG); *pbstrValue = NULL; return S_FALSE; }
STDMETHODIMP CAccessibleBase::get_accDescription(VARIANT varChild, BSTR * pbstrDescription) { VALIDATEACCCHILD(varChild, CHILDID_SELF, E_INVALIDARG); *pbstrDescription = NULL; return S_FALSE; }
STDMETHODIMP CAccessibleBase::get_accRole(VARIANT varChild, VARIANT *pvarRole) { VALIDATEACCCHILD(varChild, CHILDID_SELF, E_INVALIDARG); pvarRole->vt = VT_I4; pvarRole->lVal = ROLE_SYSTEM_LINK; return S_OK; }
STDMETHODIMP CAccessibleBase::get_accState(VARIANT varChild, VARIANT *pvarState) { VALIDATEACCCHILD(varChild, CHILDID_SELF, E_INVALIDARG);
pvarState->vt = VT_I4; pvarState->lVal = STATE_SYSTEM_DEFAULT ;
if (GetFocus() == _hwnd) pvarState->lVal |= STATE_SYSTEM_FOCUSED; else if (IsWindowEnabled(_hwnd)) pvarState->lVal |= STATE_SYSTEM_FOCUSABLE;
if (!IsWindowVisible(_hwnd)) pvarState->lVal |= STATE_SYSTEM_INVISIBLE;
return S_OK; }
STDMETHODIMP CAccessibleBase::get_accHelp(VARIANT varChild, BSTR* pbstrHelp) { VALIDATEACCCHILD(varChild, CHILDID_SELF, E_INVALIDARG); *pbstrHelp = NULL; return S_FALSE; }
STDMETHODIMP CAccessibleBase::get_accHelpTopic(BSTR* pbstrHelpFile, VARIANT varChild, long* pidTopic) { VALIDATEACCCHILD(varChild, CHILDID_SELF, E_INVALIDARG); *pbstrHelpFile = NULL; *pidTopic = -1; return S_FALSE; }
STDMETHODIMP CAccessibleBase::get_accKeyboardShortcut(VARIANT varChild, BSTR* pbstrKeyboardShortcut) { VALIDATEACCCHILD(varChild, CHILDID_SELF, E_INVALIDARG); *pbstrKeyboardShortcut = NULL; return S_FALSE; }
STDMETHODIMP CAccessibleBase::get_accFocus(VARIANT FAR * pvarFocusChild) { HWND hwndFocus; if ((hwndFocus = GetFocus()) == _hwnd || IsChild(_hwnd, hwndFocus)) { pvarFocusChild->vt = VT_I4; pvarFocusChild->lVal = CHILDID_SELF; return S_OK; } return S_FALSE; }
STDMETHODIMP CAccessibleBase::get_accSelection(VARIANT FAR * pvarSelectedChildren) { return get_accFocus(pvarSelectedChildren); // implemented same as focus.
}
STDMETHODIMP CAccessibleBase::get_accDefaultAction(VARIANT varChild, BSTR* pbstrDefaultAction) { VALIDATEACCCHILD(varChild, CHILDID_SELF, E_INVALIDARG);
WCHAR wsz[128]; if (LoadStringW(HINST_THISDLL, GetDefaultActionStringID(), wsz, ARRAYSIZE(wsz))) { if (NULL == (*pbstrDefaultAction = SysAllocString(wsz))) return E_OUTOFMEMORY; return S_OK; } return E_FAIL; }
STDMETHODIMP CAccessibleBase::accSelect(long flagsSelect, VARIANT varChild) { VALIDATEACCCHILD(varChild, CHILDID_SELF, E_INVALIDARG);
if (flagsSelect & SELFLAG_TAKEFOCUS) { SetFocus(_hwnd); return S_OK; } return S_FALSE; }
STDMETHODIMP CAccessibleBase::accLocation(long* pxLeft, long* pyTop, long* pcxWidth, long* pcyHeight, VARIANT varChild) { RECT rc; GetWindowRect(_hwnd, &rc); *pxLeft = rc.left; *pyTop = rc.top; *pcxWidth = RECTWIDTH(rc); *pcyHeight = RECTHEIGHT(rc);
varChild.vt = VT_I4; varChild.lVal = CHILDID_SELF; return S_OK; }
STDMETHODIMP CAccessibleBase::accNavigate(long navDir, VARIANT varStart, VARIANT * pvarEndUpAt) { return S_FALSE; }
STDMETHODIMP CAccessibleBase::accHitTest(long xLeft, long yTop, VARIANT * pvarChildAtPoint) { pvarChildAtPoint->vt = VT_I4; pvarChildAtPoint->lVal = CHILDID_SELF; return S_OK; }
STDMETHODIMP CAccessibleBase::put_accName(VARIANT varChild, BSTR bstrName) { VALIDATEACCCHILD(varChild, CHILDID_SELF, E_INVALIDARG); return S_FALSE; }
STDMETHODIMP CAccessibleBase::put_accValue(VARIANT varChild, BSTR bstrValue) { VALIDATEACCCHILD(varChild, CHILDID_SELF, E_INVALIDARG); return S_FALSE; }
BOOL _HandleWM_UPDATEUISTATE(WPARAM wParam, LPARAM lParam, OUT UINT* puFlags) { UINT uFlags = *puFlags;
switch (LOWORD(wParam)) { case UIS_CLEAR: *puFlags &= ~(HIWORD(wParam)); break;
case UIS_SET: *puFlags |= HIWORD(wParam); break; }
return uFlags != *puFlags; }
void _InitializeUISTATE(IN HWND hwnd, IN OUT UINT* puFlags) { HWND hwndParent = GetParent(hwnd); *puFlags = (UINT)SendMessage(hwndParent, WM_QUERYUISTATE, 0, 0); }
|