Click here to Skip to main content
Click here to Skip to main content
Add your own
alternative version

CButtonST v3.9 (MFC Flat buttons)

, 28 Mar 2003
A fully featured owner-draw button class - it's got the lot!
cbuttonst-beta.zip
cbuttonst26_demo.zip
CButtonST_demo.clw
CButtonST_demo.dsp
CButtonST_demo.dsw
FILE_ID.DIZ
res
32x32x16_About.ico
32x32x16_Cancel.ico
32x32x16_CancelBor.ico
32x32x16_Exit.ico
32x32x16_Explore.ico
32x32x16_Info.ico
32x32x16_Left.ico
32x32x16_Ok.ico
32x32x16_OkBor.ico
32x32x16_Question.ico
32x32x16_Right.ico
32x32x16_Screw.ico
32x32x16_Text.ico
32x32x16_View.ico
32x32x256_Baloon.ico
32x32x256_Cancel.ico
32x32x256_CDGold.ico
32x32x256_Hand.ico
32x32x256_Lamp.ico
32x32x256_Ok.ico
32x32x256_Zip.ico
32x32x256_ZipSmall.ico
32x32x2_CancelBor.ico
32x32x2_Lamp.ico
32x32x2_OkBor.ico
CButtonST_demo.ico
hand.cur
Release
TransparentCButtonST_demo.exe
CButtonST_demo.exe
cbuttonst26_src.zip
cbuttonst31_demo.zip
CButtonST_Demo.aps
CButtonST_Demo.clw
CButtonST_Demo.dsp
CButtonST_Demo.dsw
CButtonST_Demo.ncb
CButtonST_Demo.opt
CButtonST_Demo.exe
About.ico
Baloon.ico
BmpBack.bmp
Cancel1_32x32x16.ico
Cancel4_32x32x2.ico
Cannibal.bmp
CButtonST_Demo.ico
CDRom.ico
Eagle.bmp
EOapp.ico
Explorer.ico
Face.bmp
Halloween1.ico
Halloween2.ico
Hand.cur
Help.ico
JPEG Image.ico
Key manager.ico
Lamp1.ico
Lamp2.ico
LedOff.ico
LedOn.ico
Left2_32x32x16.ico
LogOff.ico
Ok1_32x32x16.ico
Ok4_32x32x2.ico
Open.ico
Palette.bmp
Right2_32x32x16.ico
Run.ico
Search1.ico
Search2.ico
Sky.bmp
Sound.ico
STLogo_Small.bmp
Tools4.ico
Web2.ico
Winzip1.ico
Winzip2.ico
Workgroup.ico
cbuttonst31_src.zip
CButtonST31_src
cbuttonst32_demo.zip
CButtonST_Demo.aps
CButtonST_Demo.clw
CButtonST_Demo.dsp
CButtonST_Demo.dsw
CButtonST_Demo.opt
CButtonST_Demo.exe
About.ico
Baloon.ico
BmpBack.bmp
Cancel1_32x32x16.ico
Cancel3_32x32x256.ico
Cancel4_32x32x2.ico
Cannibal.bmp
CButtonST_Demo.ico
CDRom.ico
Eagle.bmp
EOapp.ico
Explorer.ico
Face.bmp
Halloween1.ico
Halloween2.ico
Hand.cur
Help.ico
Help2_32x32x256.ico
IEDocument_48x48x256.ico
JPEG Image.ico
Key manager.ico
Lamp1.ico
Lamp2.ico
LedOff.ico
LedOn.ico
Left2_32x32x16.ico
LogOff.ico
Ok1_32x32x16.ico
Ok3_32x32x256.ico
Ok4_32x32x2.ico
Open.ico
Palette.bmp
Razor_32x32x256.ico
Right2_32x32x16.ico
Run.ico
Search1.ico
Search2.ico
Sky.bmp
Sound.ico
STLogo_Small.bmp
Tools4.ico
Web2.ico
Winzip1.ico
Winzip2.ico
Workgroup.ico
cbuttonst32_src.zip
cbuttonst_demo.zip
CButtonST_Demo.clw
CButtonST_Demo.dsp
CButtonST_Demo.dsw
CButtonST_Demo.opt
CButtonST_Demo.exe
About.ico
Baloon.ico
BmpBack.bmp
Butterfly.ico
Button.bmp
Cancel1_32x32x16.ico
Cancel3_32x32x256.ico
Cancel4_32x32x2.ico
Cannibal.bmp
CButtonST_Demo.ico
CDRom.ico
Classes1_32x32x16.ico
EOapp.ico
Explorer.ico
Face.bmp
Halloween1.ico
Halloween2.ico
Hand.cur
Help.ico
Help2_32x32x256.ico
Hover.wav
IEDocument_48x48x256.ico
JPEG Image.ico
Key manager.ico
Lamp1.ico
LedOff.ico
LedOn.ico
Left6_32x32x256.ico
LogOff.ico
No3_32x32x256.ico
Ok3_32x32x256.ico
Open.ico
Razor_32x32x256.ico
Right6_32x32x256.ico
Run.ico
Search1.ico
Sky.bmp
Sound.ico
Start.wav
STLogo_Small.bmp
toolbar.bmp
Tools4.ico
Web2.ico
Winzip1.ico
Workgroup.ico
cbuttonst_src.zip
// HyperLink.cpp : implementation file
//
// HyperLink static control. Will open the default browser with the given URL
// when the user clicks on the link.
//
// Copyright Chris Maunder, 1997
// Feel free to use and distribute.
//
// Thanks to P�l K. T�nder for auto-size and window caption changes.
//
// "GotoURL" function by Stuart Patterson
// As seen in the August, 1997 Windows Developer's Journal.
// Copyright 1997 by Miller Freeman, Inc.
// All rights reserved.
// Modified by Chris Maunder to use TCHARs instead of chars.

#include "stdafx.h"
#include "HyperLink.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

#define TOOLTIP_ID 1

/////////////////////////////////////////////////////////////////////////////
// CHyperLink

CHyperLink::CHyperLink()
{
	m_crLinkColour      = RGB(0, 0, 238);     // Blue
	m_crVisitedColour   = RGB(85, 26, 139);   // Purple
	m_bVisited          = FALSE;              // Hasn't been visited yet.
	m_bUnderline        = TRUE;               // Underline the link?
	m_bAdjustToFit      = TRUE;               // Resize the window to fit the text?
	m_strURL.Empty();
}

CHyperLink::~CHyperLink()
{
	if ((HFONT)m_Font)
		m_Font.DeleteObject();
}


BEGIN_MESSAGE_MAP(CHyperLink, CStatic)
	//{{AFX_MSG_MAP(CHyperLink)
	ON_CONTROL_REFLECT(STN_CLICKED, OnClicked)
	ON_WM_CTLCOLOR_REFLECT()
	ON_WM_SETCURSOR()
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CHyperLink message handlers

BOOL CHyperLink::PreTranslateMessage(MSG* pMsg) 
{
	m_ToolTip.RelayEvent(pMsg);
	return CStatic::PreTranslateMessage(pMsg);
}

HBRUSH CHyperLink::CtlColor(CDC* pDC, UINT nCtlColor) 
{
	ASSERT(nCtlColor == CTLCOLOR_STATIC);

	// Set the approriate colour
	if (m_bVisited)
		pDC->SetTextColor(m_crVisitedColour);
	else
		pDC->SetTextColor(m_crLinkColour);

	// Set underline font if required
	if (m_bUnderline) {

		if (!(HFONT)m_Font) {			// Create font only once.
			LOGFONT lf;
			GetFont()->GetLogFont(&lf);
			lf.lfUnderline = TRUE;
			m_Font.CreateFontIndirect(&lf);
		}

		pDC->SelectObject(&m_Font);
	}

	// transparent text.
	pDC->SetBkMode(TRANSPARENT);
	return (HBRUSH)GetStockObject(NULL_BRUSH);
}

BOOL CHyperLink::OnSetCursor(CWnd* /*pWnd*/, UINT /*nHitTest*/, UINT /*message*/) 
{
	::SetCursor(m_hLinkCursor);
	return TRUE;
}

void CHyperLink::PreSubclassWindow() 
{
	// We want to get mouse clicks via STN_CLICKED
	DWORD dwStyle = GetStyle();
	::SetWindowLong(m_hWnd, GWL_STYLE, dwStyle | SS_NOTIFY);
	
	// Set the URL as the window text
	if (m_strURL.IsEmpty())
		GetWindowText(m_strURL);

	// Check that the window text isn't empty. If it is, set it as the URL.
	CString strWndText;
	GetWindowText(strWndText);
	if (strWndText.IsEmpty()) {
		ASSERT(!m_strURL.IsEmpty());	// Window and URL both empty. DUH!
		SetWindowText(m_strURL);
	}

	// Adjust size of window to fit URL if necessary
	PositionWindow();		

	// Load up the (standard) hyperlink cursor
	m_hLinkCursor = AfxGetApp()->LoadStandardCursor(IDC_ARROW);

	// Create the tooltip
	CRect rect; 
	GetClientRect(rect);
	m_ToolTip.Create(this);
	m_ToolTip.AddTool(this, m_strURL, rect, TOOLTIP_ID);

	CStatic::PreSubclassWindow();
}

/////////////////////////////////////////////////////////////////////////////
// CHyperLink operations

void CHyperLink::SetURL(CString strURL)
{
	m_strURL = strURL;
	PositionWindow();
	m_ToolTip.UpdateTipText(strURL, this, TOOLTIP_ID);
}

void CHyperLink::SetColours(COLORREF crLinkColour, COLORREF crVisitedColour) 
{ 
	m_crLinkColour    = crLinkColour; 
	m_crVisitedColour = crVisitedColour; 
	Invalidate(); 
}

void CHyperLink::SetVisited(BOOL bVisited /* = TRUE */) 
{ 
	m_bVisited = bVisited; 
	Invalidate(); 
}

void CHyperLink::SetUnderline(BOOL bUnderline /* = TRUE */)
{
	m_bUnderline = bUnderline; 
	Invalidate(); 
}

void CHyperLink::SetAutoSize(BOOL bAutoSize /* = TRUE */)
{
	m_bAdjustToFit = bAutoSize;
	PositionWindow();
}


// Move and resize the window so that the window is the same size
// as the hyperlink text. This stops the hyperlink cursor being active
// when it is not directly over the text. If the text is left justified
// then the window is merely shrunk, but if it is centred or right
// justified then the window will have to be moved as well.
//
// Suggested by P�l K. T�nder 

void CHyperLink::PositionWindow()
{
	if (!m_bAdjustToFit) return;

	// Get the current window position
	CRect rect;
	GetWindowRect(rect);

	CWnd* pParent = GetParent();
	if (pParent)
		pParent->ScreenToClient(rect);

	// Get the size of the window text
	CString strWndText;
	GetWindowText(strWndText);

	CDC* pDC = GetDC();
	CSize Extent = pDC->GetTextExtent(strWndText);
	ReleaseDC(pDC);

	// Get the text justification via the window style
	DWORD dwStyle = GetStyle();

	// Recalc the window size and position based on the text justification
	if (dwStyle & SS_CENTERIMAGE)
		rect.DeflateRect(0, (rect.Height() - Extent.cy)/2);
	else
		rect.bottom = rect.top + Extent.cy;

	if (dwStyle & SS_CENTER)   
		rect.DeflateRect((rect.Width() - Extent.cx)/2, 0);
	else if (dwStyle & SS_RIGHT) 
		rect.left  = rect.right - Extent.cx;
	else // SS_LEFT = 0, so we can't test for it explicitly 
		rect.right = rect.left + Extent.cx;

	// Move the window
	SetWindowPos(NULL, rect.left, rect.top, rect.Width(), rect.Height(), SWP_NOZORDER);
}

/////////////////////////////////////////////////////////////////////////////
// CHyperLink implementation

void CHyperLink::OnClicked()
{
	int result = (int)GotoURL(m_strURL, SW_SHOW);
	m_bVisited = (result > HINSTANCE_ERROR);
	if (!m_bVisited) {
		MessageBeep(MB_ICONEXCLAMATION);	// Unable to follow link
		ReportError(result);
	} else 
		SetVisited();						// Repaint to show visited colour
}

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

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

    return retval;
}

void CHyperLink::ReportError(int nError)
{
	CString str;
	switch (nError) {
		case 0:                       str = "The operating system is out\nof memory or resources."; break;
		case SE_ERR_PNF:              str = "The specified path was not found."; break;
		case SE_ERR_FNF:              str = "The specified file was not found."; break;
		case ERROR_BAD_FORMAT:        str = "The .EXE file is invalid\n(non-Win32 .EXE or error in .EXE image)."; break;
		case SE_ERR_ACCESSDENIED:     str = "The operating system denied\naccess to the specified file."; break;
		case SE_ERR_ASSOCINCOMPLETE:  str = "The filename association is\nincomplete or invalid."; break;
		case SE_ERR_DDEBUSY:          str = "The DDE transaction could not\nbe completed because other DDE transactions\nwere being processed."; break;
		case SE_ERR_DDEFAIL:          str = "The DDE transaction failed."; break;
		case SE_ERR_DDETIMEOUT:       str = "The DDE transaction could not\nbe completed because the request timed out."; break;
		case SE_ERR_DLLNOTFOUND:      str = "The specified dynamic-link library was not found."; break;
		case SE_ERR_NOASSOC:          str = "There is no application associated\nwith the given filename extension."; break;
		case SE_ERR_OOM:              str = "There was not enough memory to complete the operation."; break;
		case SE_ERR_SHARE:            str = "A sharing violation occurred. ";
		default:                      str.Format("Unknown Error (%d) occurred.", nError); break;
	}
	str = "Unable to open hyperlink:\n\n" + str;
	AfxMessageBox(str, MB_ICONEXCLAMATION | MB_OK);
}

HINSTANCE CHyperLink::GotoURL(LPCTSTR url, int showcmd)
{
	TCHAR key[MAX_PATH + MAX_PATH];

	// 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) {
			lstrcat(key, _T("\\shell\\open\\command"));

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

				lstrcat(pos, _T(" "));
				lstrcat(pos, url);
				result = (HINSTANCE) WinExec(key,showcmd);
			}
		}
	}

	return result;
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here

Share

About the Author

Davide Calabro
Web Developer
Italy Italy
No Biography provided

| Advertise | Privacy | Terms of Use | Mobile
Web04 | 2.8.1411023.1 | Last Updated 29 Mar 2003
Article Copyright 1999 by Davide Calabro
Everything else Copyright © CodeProject, 1999-2014
Layout: fixed | fluid