xhtmlstatic.cpp

来自「管理项目进度工具的原代码」· C++ 代码 · 共 1,326 行 · 第 1/3 页

CPP
1,326
字号

	if (pRect->top >= (pRect->bottom-1))
		return 0;

	// set initial size
	TCHAR * szTest = _T("abcdefgABCDEFG");
	GetTextExtentPoint32(hdc, szTest, _tcslen(szTest), &size);

	// prepare for next line - clear out the error term
	SetTextJustification(hdc, 0, 0);

	CString strOut = _T("");

	BOOL bReturnSeen = FALSE;

	TEXTMETRIC tm;
	::GetTextMetrics(hdc, &tm);

	do									// for each text line
	{
		nWord = 0;						// initialize number of spaces in line

		// skip to first non-space in line
		while (/**pText != _T('\0') && */*pText == _T(' '))
		{
			if (xNext)
				strOut += *pText;
			pText++;
		}

		for(;;)							// process each word
		{
			CString strWord;
			TCHAR *saved_pText = pText;
			strWord = GetNextWord(&pText, &bReturnSeen);

			CString strTrial;
			strTrial = strOut + strWord;

			// after each word, calculate extents
			nWord++;
			GetTextExtentPoint32(hdc, strTrial, strTrial.GetLength(), &size);

			BOOL bOverflow = (size.cx >= (pRect->right - xNext - 2));	
											// don't get too close to margin,
											// in case of italic text

			if (bOverflow)
			{
				if (strOut.IsEmpty())
				{
					bOverflow = FALSE;
					strOut = strWord;
				}
			}
			else
			{
				strOut += strWord;
			}

			if (bReturnSeen || bOverflow || (*pText == _T('\0')))
			{
				if (strOut.IsEmpty())
					break;

				if (bOverflow)
					pText = saved_pText;
				nWord--;               // discount last space at end of line

				// if end of text and no space characters, set pEnd to end

				GetTextExtentPoint32(hdc, strOut, strOut.GetLength(), &size);

				xStart = pRect->left;
				xStart += xNext;
				xNext = 0;
				xLast = xStart + size.cx;

				// display the text

				if ((m_yStart <= (pRect->bottom-size.cy)))// && (!IsBlank(strOut)))
				{
					TextOut(hdc, xStart, m_yStart, strOut, strOut.GetLength());
					if (*pText || bReturnSeen)
					m_yStart += size.cy;
				}

				// prepare for next line - clear out the error term
				SetTextJustification(hdc, 0, 0);

				strOut.Empty();
			}
			else	// new word will fit
			{

			}
		}

		nWord--;               // discount last space at end of line

		// if end of text and no space characters, set pEnd to end

		// prepare for next line - clear out the error term
		SetTextJustification(hdc, 0, 0);

		strOut.Empty();

	} while (*pText && (m_yStart < pRect->bottom));

	if (m_yStart > (pRect->bottom-size.cy))
		pRect->top = pRect->bottom;
	else
		pRect->top = m_yStart;

	return xLast;
}

///////////////////////////////////////////////////////////////////////////////
// GetNextWord
CString CXHTMLStatic::GetNextWord(TCHAR **ppText, BOOL * pbReturnSeen)
{
	CString strWord;
	strWord = _T("");
	TCHAR *pText = *ppText;

	*pbReturnSeen = FALSE;

	// skip to next word

	for(;;)
	{
		if (*pText == _T('\0'))
			break;

		// skip \r
		if (*pText == _T('\r'))
			pText++;

		// \n = new line
		if (*pText == _T('\n'))
		{
			strWord += _T(' ');
			pText++;
			*pbReturnSeen = TRUE;
			break;
		}

		TCHAR c = *pText;

		// process character entities
		if (c == _T('\001'))
		{
			c = *++pText;

			c = GetCharEntity(c);
		}

		strWord += c;

		if (*pText++ == _T(' '))
			break;
	}

	*ppText = pText;

	return strWord;
}

///////////////////////////////////////////////////////////////////////////////
// PreSubclassWindow
void CXHTMLStatic::PreSubclassWindow() 
{
    // We want to get mouse clicks via STN_CLICKED
    DWORD dwStyle = GetStyle();
    ::SetWindowLong(GetSafeHwnd(), GWL_STYLE, dwStyle | SS_NOTIFY);

	CStatic::PreSubclassWindow();

	CFont* cf = GetFont();
	LOGFONT lf;

	if (cf != NULL)
	{
		cf->GetObject(sizeof(lf), &lf);
	}
	else
	{
		GetObject(GetStockObject(SYSTEM_FONT), sizeof(lf), &lf);
	}

	m_font.DeleteObject();
	VERIFY(m_font.CreateFontIndirect(&lf));
}

///////////////////////////////////////////////////////////////////////////////
// OnTimer
void CXHTMLStatic::OnTimer(UINT nIDEvent) 
{
	int n = m_AnchorRectPtrs.GetSize();

	if (n == 0)
		return;

	CPoint point;
	::GetCursorPos(&point);

	m_bOnHyperlink = FALSE;

	for (int i = 0; i < n; i++)
	{
		CRect *pRect = (CRect *) m_AnchorRectPtrs[i];
		CRect rect = *pRect;
		ClientToScreen(&rect);

		if (rect.PtInRect(point))		 // Cursor is currently over control
		{
			if (m_hLinkCursor)
			{
				HCURSOR hPrevCursor = ::SetCursor(m_hLinkCursor);
				if (m_hPrevCursor == NULL)
					m_hPrevCursor = hPrevCursor;
				m_bOnHyperlink = TRUE;
				break;
			}
		}
	}

	if (!m_bOnHyperlink && m_hPrevCursor)
	{
		::SetCursor(m_hPrevCursor);
		m_hPrevCursor = NULL;
		RedrawWindow();
	}

	CStatic::OnTimer(nIDEvent);
}

///////////////////////////////////////////////////////////////////////////////
// OnSetCursor
BOOL CXHTMLStatic::OnSetCursor(CWnd* pWnd, UINT nHitTest, UINT message) 
{
	if (!m_bOnHyperlink)	
		return CStatic::OnSetCursor(pWnd, nHitTest, message);
	else
		return FALSE;
}

///////////////////////////////////////////////////////////////////////////////
// OnClicked
void CXHTMLStatic::OnClicked()
{
	CPoint point;
	::GetCursorPos(&point);

	BOOL bOnHyperlink = FALSE;

	int n = m_AnchorRectPtrs.GetSize();

	if (n == 0)
		return;

	int i = 0;
	for (i = 0; i < n; i++)
	{
		CRect *pRect = (CRect *) m_AnchorRectPtrs[i];
		CRect rect = *pRect;
		ClientToScreen(&rect);

		if (rect.PtInRect(point))		 // Cursor is currently over control
		{
			bOnHyperlink = TRUE;
			break;
		}
	}

	if (bOnHyperlink)
		GotoURL(m_AnchorUrls[i], SW_SHOW);
}

///////////////////////////////////////////////////////////////////////////////
// GoToURL
BOOL CXHTMLStatic::GotoURL(LPCTSTR url, int showcmd)
{
	BOOL bRet = FALSE;

	ASSERT(url);
	ASSERT(url[0] != _T('\0'));

	TCHAR key[MAX_PATH * 2];

	// check if this is "app:" protocol	
	int nAppSize = 0;
	if (_tcsnicmp(url, _T("APP:"), 4) == 0)
		nAppSize = 4;
	else if (_tcsnicmp(url, _T("\"APP:"), 5) == 0)
		nAppSize = 5;
	if (nAppSize)
	{
		bRet = ProcessAppCommand(&url[nAppSize]);
	}
	else
	{
		// not "app" - assume http: or mailto:

		// First try ShellExecute()
		HINSTANCE result = ::ShellExecute(NULL, _T("open"), url, NULL,NULL, showcmd);

		// If it failed, get the .htm regkey and lookup the program
		if ((UINT)result <= HINSTANCE_ERROR) 
		{
			if (GetRegKey(HKEY_CLASSES_ROOT, _T(".htm"), key) == ERROR_SUCCESS) 
			{
//fabio_2005
#if _MSC_VER >= 1400
				_tcscat_s(key, _T("\\shell\\open\\command"));
#else
				_tcscat(key, _T("\\shell\\open\\command"));
#endif

				if (GetRegKey(HKEY_CLASSES_ROOT,key,key) == ERROR_SUCCESS) 
				{
					TCHAR *pos;
					pos = _tcsstr(key, _T("\"%1\""));
					if (pos == NULL) {					   // No quotes found
						pos = _tcsstr(key, _T("%1"));	   // Check for %1, without quotes 
						if (pos == NULL)				   // No parameter at all...
							pos = key+lstrlen(key)-1;
						else
							*pos = _T('\0');			   // Remove the parameter
					}
					else
						*pos = _T('\0');				   // Remove the parameter

//fabio_2005
#if _MSC_VER >= 1400
					_tcscat_s(pos,1, _T(" "));
					_tcscat_s(pos,lstrlen( url), url);
#else
					_tcscat(pos, _T(" "));
					_tcscat(pos, url);
#endif
					result = (HINSTANCE) WinExec((LPSTR)key,showcmd);
				}
			}
		}

		bRet = result > (HINSTANCE) HINSTANCE_ERROR;
	}

	return bRet;
}

///////////////////////////////////////////////////////////////////////////////
// ProcessAppCommand
BOOL CXHTMLStatic::ProcessAppCommand(LPCTSTR lpszCommand)
{
	TRACE(_T("in CXHTMLStatic::ProcessAppCommand:  %s\n"), lpszCommand);

	BOOL bRet = FALSE;

	CString strCommand(lpszCommand);
	if (strCommand[0] == _T('"'))
		strCommand = strCommand.Mid(1);
	if (strCommand[strCommand.GetLength()-1] == _T('"'))
		strCommand = strCommand.Left(strCommand.GetLength()-1);

	if ((m_nAppCommands > 0) && (m_paAppCommands != NULL))
	{
		for (int i = 0; i < m_nAppCommands; i++)
		{
			if (_tcsicmp(m_paAppCommands[i].pszCommand, strCommand) == 0)
			{
				TRACE(_T("found app command %s\n"), strCommand);
				if (m_paAppCommands[i].hWnd &&
					::IsWindow(m_paAppCommands[i].hWnd))
				{
					::SendMessage(m_paAppCommands[i].hWnd, 
								  m_paAppCommands[i].uMessage, 
								  m_paAppCommands[i].wParam,
								  0);
					bRet = TRUE;
					break;
				}
			}
		}
	}

	return bRet;
}

///////////////////////////////////////////////////////////////////////////////
// GetRegKey
LONG CXHTMLStatic::GetRegKey(HKEY key, LPCTSTR subkey, LPTSTR retdata)
{
	HKEY hkey;
	LONG retval = RegOpenKeyEx(key, subkey, 0, KEY_QUERY_VALUE, &hkey);
	
	*retdata = 0;

	if (retval == ERROR_SUCCESS) 
	{
		long datasize = MAX_PATH;
		TCHAR data[MAX_PATH];
		retval = RegQueryValue(hkey, NULL, data, &datasize);
		if (retval == ERROR_SUCCESS) 
		{
			lstrcpy(retdata, data);
			RegCloseKey(hkey);
		}
	}
	
	return retval;
}

///////////////////////////////////////////////////////////////////////////////
// OnDestroy
void CXHTMLStatic::OnDestroy() 
{
	if (m_bHyperlinkTimer)
		KillTimer(1);
	m_bHyperlinkTimer = FALSE;

	CStatic::OnDestroy();
}

///////////////////////////////////////////////////////////////////////////////
// SetWindowText
void CXHTMLStatic::SetWindowText(LPCTSTR lpszString)
{
	Init();
	CStatic::SetWindowText(lpszString);
	RedrawWindow();
}

LRESULT CXHTMLStatic::OnShowAccelerators(WPARAM /*wp*/, LPARAM /*lp*/)
{
	LRESULT lr = Default();
	RedrawWindow();

	return lr;
}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?