📄 hlinkmgr.cpp
字号:
/* ***** BEGIN LICENSE BLOCK ***** * Source last modified: $Id: hlinkmgr.cpp,v 1.2.22.1 2004/07/09 01:51:47 hubbe Exp $ * * Portions Copyright (c) 1995-2004 RealNetworks, Inc. All Rights Reserved. * * The contents of this file, and the files included with this file, * are subject to the current version of the RealNetworks Public * Source License (the "RPSL") available at * http://www.helixcommunity.org/content/rpsl unless you have licensed * the file under the current version of the RealNetworks Community * Source License (the "RCSL") available at * http://www.helixcommunity.org/content/rcsl, in which case the RCSL * will apply. You may also obtain the license terms directly from * RealNetworks. You may not use this file except in compliance with * the RPSL or, if you have a valid RCSL with RealNetworks applicable * to this file, the RCSL. Please see the applicable RPSL or RCSL for * the rights, obligations and limitations governing use of the * contents of the file. * * Alternatively, the contents of this file may be used under the * terms of the GNU General Public License Version 2 or later (the * "GPL") in which case the provisions of the GPL are applicable * instead of those above. If you wish to allow use of your version of * this file only under the terms of the GPL, and not to allow others * to use your version of this file under the terms of either the RPSL * or RCSL, indicate your decision by deleting the provisions above * and replace them with the notice and other provisions required by * the GPL. If you do not delete the provisions above, a recipient may * use your version of this file under the terms of any one of the * RPSL, the RCSL or the GPL. * * This file is part of the Helix DNA Technology. RealNetworks is the * developer of the Original Code and owns the copyrights in the * portions it created. * * This file, and the files included with this file, is distributed * and made available on an 'AS IS' basis, WITHOUT WARRANTY OF ANY * KIND, EITHER EXPRESS OR IMPLIED, AND REALNETWORKS HEREBY DISCLAIMS * ALL SUCH WARRANTIES, INCLUDING WITHOUT LIMITATION, ANY WARRANTIES * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, QUIET * ENJOYMENT OR NON-INFRINGEMENT. * * Technology Compatibility Kit Test Suite(s) Location: * http://www.helixcommunity.org/content/tck * * Contributor(s): * * ***** END LICENSE BLOCK ***** */// system#include <string.h>// From include#include "hxtypes.h"#include "hxwintyp.h"#include "hxresult.h"#include "hxcom.h"#include "ihxpckts.h"#include "hxcomm.h"#include "hxwin.h"// From pncont#include "hxslist.h"#include "hxstring.h"// From pnmisc#include "baseobj.h"// From pxrend#include "hlinkmgr.h"// From pndebug#include "hxheap.h"#ifdef _DEBUG#undef HX_THIS_FILE static char HX_THIS_FILE[] = __FILE__;#endifPXHyperlinkManager::PXHyperlinkManager(){ m_lRefCount = 0; m_pCommonClassFactory = NULL; m_ulWidth = 0; m_ulHeight = 0; m_pDefaultLinkStr = NULL; m_bHaveDefault = FALSE; m_pLinkPairList = NULL; m_bSomeLinkHasKeyboardFocus = FALSE; m_bDefaultLinkHasKeyboardFocus = FALSE; m_pKeyboardFocusLink = NULL;}PXHyperlinkManager::~PXHyperlinkManager(){ HX_RELEASE(m_pCommonClassFactory); HX_RELEASE(m_pDefaultLinkStr); ClearLinkPairList(); HX_DELETE(m_pLinkPairList);}STDMETHODIMP PXHyperlinkManager::QueryInterface(REFIID riid, void** ppvObj){ HX_RESULT retVal = HXR_OK; if (ppvObj) { // Set default *ppvObj = NULL; // Check for IID type if (IsEqualIID(riid, IID_IUnknown)) { AddRef(); *ppvObj = (IUnknown*) this; } else { retVal = HXR_NOINTERFACE; } } else { retVal = HXR_FAIL; } return retVal;}STDMETHODIMP_(UINT32) PXHyperlinkManager::AddRef(){ return InterlockedIncrement(&m_lRefCount);}STDMETHODIMP_(UINT32) PXHyperlinkManager::Release(){ if (InterlockedDecrement(&m_lRefCount) > 0) { return m_lRefCount; } delete this; return 0;}HX_RESULT PXHyperlinkManager::Init(IUnknown* pContext, UINT32 ulW, UINT32 ulH){ HX_RESULT retVal = HXR_FAIL; if (pContext && ulW && ulH) { // Assign width and height m_ulWidth = ulW; m_ulHeight = ulH; // Create the link pair list ClearLinkPairList(); HX_DELETE(m_pLinkPairList); m_pLinkPairList = new CHXSimpleList(); if (m_pLinkPairList) { // Get the IHXCommonClassFactory interface HX_RELEASE(m_pCommonClassFactory); retVal = pContext->QueryInterface(IID_IHXCommonClassFactory, (void**) &m_pCommonClassFactory); } } return retVal;}HX_RESULT PXHyperlinkManager::SetDefaultLink(const char *pszDefaultLink){ HX_RESULT retVal = HXR_OK; if (pszDefaultLink && strlen(pszDefaultLink) > 0 && strspn(pszDefaultLink, " \r\n\t") < strlen(pszDefaultLink)) { if (m_pCommonClassFactory) { // Allocate an IHXBuffer HX_RELEASE(m_pDefaultLinkStr); retVal = m_pCommonClassFactory->CreateInstance(CLSID_IHXBuffer, (void**) &m_pDefaultLinkStr); if (SUCCEEDED(retVal)) { // Set the value of the buffer retVal = m_pDefaultLinkStr->Set((const BYTE*) pszDefaultLink, strlen(pszDefaultLink) + 1); if (SUCCEEDED(retVal)) { m_bHaveDefault = TRUE; } } else { retVal = HXR_OUTOFMEMORY; } } else { retVal = HXR_UNEXPECTED; } } else { retVal = HXR_INVALID_PARAMETER; } return retVal;}HX_RESULT PXHyperlinkManager::AddLink(HXxRect cRect, const char* pszLink, UINT32 ulTabIndex, UINT32 ulLexicalOrder){ HX_RESULT retVal = HXR_FAIL; if (m_pLinkPairList) { if (cRect.right <= (INT32) m_ulWidth && cRect.bottom <= (INT32) m_ulHeight && HXxRECT_WIDTH(cRect) > 0 && HXxRECT_HEIGHT(cRect) > 0) { // Check to see if this rect completely obscures a rect which // is already in the list. If so, then remove the smaller, older // rect from the list. Also we want to check whether the // current list includes a link with the same tabindex // and lexical order. BOOL bDupTabLex = FALSE; UINT32 ulMaxLex = 0; LISTPOSITION pos = m_pLinkPairList->GetHeadPosition(); while (pos) { PXHyperlink* pListLink = (PXHyperlink*) m_pLinkPairList->GetAt(pos); if (pListLink) { if (pListLink->m_Rect.left >= cRect.left && pListLink->m_Rect.top >= cRect.top && pListLink->m_Rect.right <= cRect.right && pListLink->m_Rect.bottom <= cRect.bottom) { HX_DELETE(pListLink); pos = m_pLinkPairList->RemoveAt(pos); } else { m_pLinkPairList->GetNext(pos); // Find the max lexical order for this tab index if (ulTabIndex == pListLink->m_ulTabIndex) { if (pListLink->m_ulLexicalOrder > ulMaxLex) { ulMaxLex = pListLink->m_ulLexicalOrder; } } // Check for duplicate tabindex and // lexical order members if (ulTabIndex == pListLink->m_ulTabIndex && ulLexicalOrder == pListLink->m_ulLexicalOrder) { bDupTabLex = TRUE; } } } else { m_pLinkPairList->GetNext(pos); } } // Create a new link PXHyperlink* pLink = new PXHyperlink(); if (pLink) { // Clear the return value retVal = HXR_OK; // Set the rect pLink->m_Rect = cRect; // Set the tabindex pLink->m_ulTabIndex = ulTabIndex; // Set the lexical order. If there is another link // in the list with the same tabindex and // lexical order, then we detected that above. We // also computed the max lexical order for that tabindex. // So set the lexical order to one bigger than that. if (bDupTabLex) { ulLexicalOrder = ulMaxLex + 1; } pLink->m_ulLexicalOrder = ulLexicalOrder; // If there is a link, we need to create an IHXBuffer if (pszLink) { IHXBuffer* pBuffer = NULL; retVal = m_pCommonClassFactory->CreateInstance(CLSID_IHXBuffer, (void**) &pBuffer); if (SUCCEEDED(retVal)) { // Set the value retVal = pBuffer->Set((const BYTE*) pszLink, strlen(pszLink) + 1); if (SUCCEEDED(retVal)) { // Set the string buffer pLink->m_pLinkStr = pBuffer; pLink->m_pLinkStr->AddRef(); } } HX_RELEASE(pBuffer); } if (SUCCEEDED(retVal)) { // Add the link to the list m_pLinkPairList->AddHead((void*) pLink); } } if (FAILED(retVal)) { HX_DELETE(pLink); } } } return retVal;}BOOL PXHyperlinkManager::GetActiveLink(INT16 sX, INT16 sY, INT32 lCurW, INT32 lCurH, REF(IHXBuffer*) rpLinkStr){ BOOL bRet = FALSE; if (m_pLinkPairList) { // Sanity check to make sure x,y is inside our overall window if (sX >= 0 && sX < lCurW && sY >= 0 && sY < lCurH) { // Check if scaling is necessary BOOL bNeedScaling = FALSE; if (lCurW != (INT32) m_ulWidth || lCurH != (INT32) m_ulHeight) { bNeedScaling = TRUE; } // Search the list for the first link which holds this point LISTPOSITION pos = m_pLinkPairList->GetHeadPosition(); while (pos) { PXHyperlink* pLink = (PXHyperlink*) m_pLinkPairList->GetNext(pos); if (pLink) { INT32 lRectX = (INT32) pLink->m_Rect.left; INT32 lRectY = (INT32) pLink->m_Rect.top; INT32 lRectW = (INT32) HXxRECT_WIDTH(pLink->m_Rect); INT32 lRectH = (INT32) HXxRECT_HEIGHT(pLink->m_Rect); if (bNeedScaling) { lRectX = lRectX * lCurW / (INT32) m_ulWidth; lRectY = lRectY * lCurH / (INT32) m_ulHeight; lRectW = lRectW * lCurW / (INT32) m_ulWidth; lRectH = lRectH * lCurH / (INT32) m_ulHeight; } if (sX >= lRectX && sY >= lRectY && sX < lRectX + lRectW && sY < lRectY + lRectH) { // We found the active rect. If it has a link associated // with it, then it's active. If not, we don't have // an active link. Either way, we need to break. if (pLink->m_pLinkStr) { // Set the out param HX_RELEASE(rpLinkStr); rpLinkStr = pLink->m_pLinkStr; rpLinkStr->AddRef(); // Set the return flag bRet = TRUE; } break; } } } // Do we need to assign a default? if (!bRet && m_bHaveDefault) { // We didn't find a link and we DO have a default, // so assign the default as the link // // Set the out param HX_RELEASE(rpLinkStr); rpLinkStr = m_pDefaultLinkStr; rpLinkStr->AddRef(); // Set the return flag bRet = TRUE; } } } return bRet;}void PXHyperlinkManager::NavigateKeyboardFocus(HXFocusContext eFocus){ switch (eFocus) { case HXFirstFocus: { GetFirstLinkWithDefault(); } break; case HXUpFocus: case HXLeftFocus: case HXPrevFocus: { GetPrevLinkWithDefault(); } break;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -