An improved hyperlink control
Download Source
Code and Demo
Introduction
After having tried some hyperlink controls, I felt the necessity to write my own control that was more flexible and had a more consistent programming interface. My intention was to create an hyperlink that could be used not only with text but also with icons and bitmaps, and that supported dynamic modification of its style and font. Moreover, I wanted that my control had the look and feel of an usual web page hyperlink. Why cannot hyperlinks have the input focus? Why cannot I move the focus from an hyperlink to another using the "tab" key as if they were normal dialog buttons and activate them pressing the spacebar?
Well, here is an hyperlink control that makes all these beautiful things possible. It was realized with the help of some articles written by Paul DiLascia on MSJ and Stuart Patterson on Windows Developer's Journal. It's rightful to tell that I think at my control as an improvement of the homonymous control developed by Chris Maunder, whose work was excellent.
Comparison with existing hyperlinkcontrols
In this section, I summarize the main features that distinguish my control from other similar controls you can find in this site. I hope this will help you to decide which code suits your needs better.
- You can set the hyperlink on any type of static control (bitmaps and icons above all!).
- The hyperlink can get the input focus (a special color is used to show the focus state) and can be activated with the spacebar like normal dialog buttons.
- The hyperlink maintains the correct aspect when you change its style, text or font.
- Control resizing works correctly even if it has a nonclient border.
- Simplified programming interface.
Using the control
To use the hyperlink control, first create a static control with your resource editor (text, icon, or bitmap), then give it a control ID (e.g. IDC_HYPERLINK). If you want your control to be able to get the focus, you have to set the "tabstop" style, since for static controls it is not the default. I advice to set it only with text controls, which can change color when focused. Then, attach it to a member variable of type CHyperLink (ClassWizard makes this very simple). Don't forget to include the "HyperLink.h" file in your dialog class implementation file. The member function SetURL() allows to specify the link URL. However, setting an explicit URL is not obligatory for text controls: if you specify a caption text, this is taken as URL. Vice versa, if you don't specify a caption text, but 'manually' set the URL with SetURL(), then the text is set equal to the URL. For all other types of static controls instead, you have the responsibility to set the URL using SetURL() (usually in the OnInitDialog() member function of your dialog class), or otherwise a debug assertion will occur. The default link colors are blue, dark cyan, purple and red, respectively for normal, focused, visited and "cursor over" states.
Customizing the hyperlink
The hyperlink styles are static class constants. They are shown in the following table
| Style | Meaning | Default |
|---|---|---|
| StyleUnderline | The link is underlined | YES |
| StyleAutoSize | The control resizes itself automatically when text or font changes | YES |
| StyleUseHover | The link use the "hand over" color | NO |
| StyleDownClick | The link is activated when mouse button "goes down" | NO |
| StyleGetFocusOnClick | The link gets the input focus when clicked | NO |
| StyleNoHandCursor | The link doesn't use the default hand cursor | NO |
| StyleNoActiveColor | The link doesn't change color when activated (i.e. when it get the focus) | NO |
- To modify link style call the member function ModifyLinkStyle(dwRemove, dwAdd) where dwRemove is a bitwise OR of the styles you want to remove and dwAdd is a bitwise OR of the styles you want to add (strange but true!).
Setting the StyleAutoSize, the control will automatically resize itself to fit the size of the caption (even while it is visible!). The resizing occurs also if you set a new window caption text or font. Remember that this style applies to text controls only. For icons and bitmaps, auto-resizing is a default characteristic, and StyleAutoSize becomes meaningless. The resizing will honour the SS_CENTERIMAGE, SS_LEFT, SS_RIGHT and SS_CENTER static control flags. If you don't want the style change to be dinamically applied to the control, ModifyLinkStyle() has a third optional boolean parameter: just set it to FALSE (the default is TRUE).
- To mark/unmark a link as visited call the SetVisited() member function.
- To modify link colors, call the SetColors() member function, in the following way:
SetColors(crLinkColor, crActiveColor, crVisitedColor, crHoverColor);
The last parameter is optional: if not specified the system
default highlight color will be used. Alternatively, fill a
HYPERLINKCOLORS structure (a typedef defined in
"HyperLink.h") and pass it to the overloaded version of
SetColors(). This structure is also used by GetColors() to
retrieve the current link colors.
SetColors() is a static member function: the color change has
effect on all instances of CHyperLink and you need to redraw your
control in order that the new colors to be applied.
- To set a mouse cursor different from the default hand, call SetLinkCursor(). This function requires a unique argument: the handle of a new cursor. It is a static function and has effect on all hyperlinks, just like SetColors().
All the "set" functions above have their natural "get" counterparts. See the following section.
Operations for CHyperLink:
Here is an excerpt from the class declaration
// Operations public: static void GetColors(HYPERLINKCOLORS& linkColors); static HCURSOR GetLinkCursor(); static void SetLinkCursor(HCURSOR hCursor); static void SetColors(COLORREF crLinkColor, COLORREF crActiveColor, COLORREF crVisitedColor, COLORREF crHoverColor = -1); static void SetColors(HYPERLINKCOLORS& colors); void SetURL(CString strURL); CString GetURL() const; DWORD GetLinkStyle() const; BOOL ModifyLinkStyle(DWORD dwRemove, DWORD dwAdd, BOOL bApply=TRUE); void SetWindowText(LPCTSTR lpszText); void SetFont(CFont *pFont); BOOL IsVisited() const; void SetVisited(BOOL bVisited = TRUE); // Use this if you want to subclass and also set different URL BOOL SubclassDlgItem(UINT nID, CWnd* pParent, LPCTSTR lpszURL=NULL) { m_strURL = lpszURL; return CStatic::SubclassDlgItem(nID, pParent); }
Implementation details
Some notes about implementation. I used the MFC message reflection to set the text color for the control (see the ON_WM_CTLCOLOR_REFLECT() macro in the message map). Message reflection can be a very complicated argument. Briefly, many controls notifies some event messages to their parent window, so that the latter has a chance to handle them. When the parent window sends back the message to the control we have the so-called message reflection. This mechanism is well implemented in MFC. Reflected messages appear preceded by an equal sign in ClassWizard.
Reading the code, you may be surprised that the control works without the SS_NOTIFY style. Normally, a static control does not get mouse events unless it has the SS_NOTIFY style. However, as Paul DiLascia asserts, handling the WM_NCHITTEST message and making the OnNcHitTest() functions returns the hit-test value HTCLIENT achieves the same effect as SS_NOTIFY, but requires fewer lines of code and is more reliable than turning on SS_NOTIFY in OnCtlColor because Windows doesn't send WM_CTLCOLOR to bitmap static controls.
For dynamic text and font modification I supplied special versions of SetFont() and SetWindowText() functions. These functions perform their operations while the window is kept hidden to maintain the correct link aspect.
Author's note
I'm continuously working to improve this control. I'll be grateful to you if you mail me your comments, advices, or bug apparition reports!.
Latest additions
- Link styles are now static class constants.
- Colors and cursor and their relative get/set functions, are now static class members.
- Many bug fixes in resizing and color management.

Comments
You pine on the side of some tomato basil and mozzarella. To indoor from, these slippers are as well-lighted and manueverable as sneakers.
Posted by Soaceddew on 04/20/2013 05:21amHas upright released several different color Democratic Inneva Woven shoes, Nike recently with another direction to bring shoes with different styling to all [url=http://fossilsdirect.co.uk/glossarey.cfm]nike huarache[/url] eyes. This brings special issue Unfastened Inneva Woven is a Fair-skinned Call of works in the series, represents shoes Italian made the assurance. Latest Safe from Inneva Woven clouded and pornographic are available in two color schemes, to hand-knit Woven vamp in extension to infiltrated Italy's [url=http://markwarren.org.uk/property-waet.cfm]nike air max 90[/url] finest crafts, for the moment gives athletes closed to the foot of relieve, the most distinguished affair is the goal of Free 5 configuration, barefoot be aware it pass on allure cannot be ignored. Nike Disburden Inneva Woven SP White Identify Compact on Walk 16 at outlets about the [url=http://northernroofing.co.uk/roofins.cfm]nike free run uk[/url] trade-mark on the shelves, and on in stock in narrow sort, interested friends should produce results fasten attention to Nike announced the news.
ReplyonMouseMove bug
Posted by prakashp5562 on 12/17/2006 05:07pmChange the font of the dialog to Tahoma 8. Now on Mousemove you find that - the text gets disturbed. Resolution: Add ON_WM_ERASEBKGND() in the message map BOOL CHyperLink::OnEraseBkgnd(CDC* pDC) { CRect rect; GetClientRect(rect); pDC->FillSolidRect(rect, ::GetSysColor(COLOR_3DFACE)); return TRUE; }Replyhow to add hyper link in menu item
Posted by Legacy on 06/03/2003 12:00amOriginally posted by: khalil
I want to add hyper link in menu item so plz tell me how i can add hyper link in menu item
ReplyWon't work in About-Dialog.
Posted by Legacy on 09/04/2002 12:00amOriginally posted by: P
Hi
I tried to use this nice control in an aboutdialog - but it won't work !
Any ideas how to do that ?
Thanks
ReplyP
Hyperlink in a textbox?
Posted by Legacy on 06/26/2002 12:00amOriginally posted by: WH
How can i place a hyperlink in a textbox?
ReplyLoad IDC_HAND on Win2k & XP
Posted by Legacy on 01/04/2002 12:00amOriginally posted by: Thomas Baust
ReplyError on a DLL
Posted by Legacy on 08/23/2000 12:00amOriginally posted by: Rod
ReplyI would like to use your control to hold multi line text in multi colors.
Posted by Legacy on 11/03/1999 12:00amOriginally posted by: Phil
Please forgive me for hacking your code. I love your control but I want it to do two more things.
1st display multiple lines of text.
2nd show at least two colors per line.
I'm a pretty good C programmer, but a little new to C++ and Windows, so I included my code change in the hopes of getting your opinion.
Secondly, can the control display more than one color? If so could you give me some hints?
Thanks.
void CHyperLink::AdjustWindow()
{
...
// Get the extent of window text
CString strWndText;
GetWindowText(strWndText);
CDC* pDC = GetDC();
CFont* pOldFont = pDC->SelectObject(&m_Font);
CSize Extent = pDC->GetTextExtent(strWndText);
//Code I added starts here.
//Count the number of line returns
char* pszLineCount = strWndText.GetBuffer(0);
short nLineCount = 1;
while(*pszLineCount != NULL) {
if(*pszLineCount == '\n')
nLineCount++;
pszLineCount++;
}
strWndText.ReleaseBuffer();
//Expand the width by the number of line returns.
Extent = CSize(Extent.cx , Extent.cy * nLineCount);
ReplyHow can we do the same in ATL?
Posted by Legacy on 07/30/1999 12:00amOriginally posted by: Gangadhar Bhat
Hi,
Your hyperlink control looks great!. It works great too!
I am doing GUI using ATL so that I can make it snappable to MMC console. Since it is an executable( not DLL), i can not import any MFC classes. My user interface strictly uses ATL and uses IWebbrowser interface to navigate web pages. However, I have hard time to see the samples for doing hyperlink control using strictly win32 so that i can plug in that code in my ATL code. Could please help to find this out. I am kind of novice to user interface area. I used to be driver guy.
I would greatly appreciate your help.
Thanks..
GD
ReplyHow can we do the same in ATL?
Posted by Legacy on 07/30/1999 12:00amOriginally posted by: Gangadhar Bhat
Hi,
Your hyperlink control looks great!. It works great too!
I am doing GUI using ATL so that I can make it snappable to MMC console. Since it is an executable( not DLL), i can not import any MFC classes. My user interface strictly uses ATL and uses IWebbrowser interface to navigate web pages. However, I have hard time to see the samples for doing hyperlink control using strictly win32 so that i can plug in that code in my ATL code. Could please help to find this out. I am kind of novice to user interface area. I used to be driver guy.
I would greatly appreciate your help.
Thanks..
GD
ReplyLoading, Please Wait ...