Hyperlinks+in+text+boxes

//by Richard Russell, January 2007//


 * The code in this article is not applicable to Windows 9x, Windows Me or Windows NT4.**

On occasion you may want to incorporate clickable //hyperlinks// in some text displayed in a dialogue box or elsewhere. For example you may want to incorporate a web or email address in a page of help text. One way of doing that would be to write the text in HTML and display it using your browser (for example in an ATL container control) but a simpler method is described in this article. This method also gives you control over the action to be taken when the link is clicked.

You must initially prepare the text to be displayed, where the hyperlinks are delimited using **** and **** tags as in the following example:

code format="bb4w" linktext$ = "For details of the full version of BBC BASIC for Windows email "+ \ \      "info@rtrussell.co.uk or visit http://www.bbcbasic.co.uk/" code Here two hyperlinks are included in the text string, but there can be as many as you like. You can also incorporate **line breaks** using the usual CRLF sequence (****).

You can display the text either in a dialogue box or on your main output window. The method used differs slightly between these options, and will be described separately.

Dialogue box
Firstly some initialisation:

code format="bb4w" INSTALL @lib$+"WINLIB2B" DIM _NMHDR{hwndFrom%, idFrom%, code%} DIM _LITEM{mask%, iLink%, state%, stateMask%, szID&(95), szUrl&(4165)} SYS "LoadLibrary", "SHELL32.DLL" TO shell32% SYS "GetProcAddress", shell32%, 258 TO LinkWindow_RegisterClass% SYS LinkWindow_RegisterClass% code Note that in this application you must use **WINLIB2B** (rather than WINLIB2 or WINLIB2A) so that the **WM_NOTIFY** messages are forwarded and can be intercepted using **ON SYS**.

The next step is to create the dialogue box. In this example it contains only the link window, but you can of course incorporate any of the normal dialogue box controls:

code format="bb4w" lwid% = 101 dlg% = FN_newdialog("Hyperlink control", 200, 20, 150, 140, 8, 1000) WS_CHILD = &40000000 WS_VISIBLE = &10000000 PROC_dlgctrl(dlg%, "", lwid%, 20, 20, 96, 40, WS_CHILD + WS_VISIBLE, "Link Window") code Note that the link window has been allocated the ID number **101**. Refer to the documentation for [|PROC_dlgitem] for the meaning of the other parameters.

Now you can display the dialogue box and load the required link text:

code format="bb4w" PROC_showdialog(dlg%) SYS "SetDlgItemText", !dlg%, lwid%, linktext$ code Note the use of the control's ID number **lwid%**.

Finally you need to be able to detect when one of the links is clicked, so that you can take the appropriate action. You do that in a similar way to responding to menu and button clicks, using **ON SYS**:

code format="bb4w" *SYS 1 WM_NOTIFY = &4E ON SYS PROCsys(@msg%, @wparam%, @lparam%) : RETURN code The **PROCsys** routine is listed at the end of the article.

Main output window
Firstly some initialisation:

code format="bb4w" INSTALL @lib$+"WINLIB5" DIM _NMHDR{hwndFrom%, idFrom%, code%} DIM _LITEM{mask%, iLink%, state%, stateMask%, szID&(95), szUrl&(4165)} SYS "LoadLibrary", "SHELL32.DLL" TO shell32% SYS "GetProcAddress", shell32%, 258 TO LinkWindow_RegisterClass% SYS LinkWindow_RegisterClass% code You can alternatively use the **WINLIB5A** library, in which case remember to pass the window handle **@hwnd%** as the first parameter of **FNcreatewindow**.

The link window is created, with the required text, as follows:

code format="bb4w" lwid% = 101 WS_BORDER = &800000 hlink% = FN_createwindow("Link Window", linktext$, 50, 100, 400, 80, \      \                        lwid%, WS_BORDER, 0) code Refer to the documentation for [|FN_createwindow] for the meaning of the parameters.

Finally you need to be able to detect when one of the links is clicked, so that you can take the appropriate action. You do that in a similar way to responding to menu and button clicks, using **ON SYS**:

code format="bb4w" *SYS 1 WM_NOTIFY = &4E ON SYS PROCsys(@msg%, @wparam%, @lparam%) : RETURN code The **PROCsys** routine is listed below.

PROCsys
The //interrupt service routine// listed below responds the **WM_NOTIFY** messages received from the link window when one of the hyperlinks is clicked:

code format="bb4w" DEF PROCsys(M%, W%, L%) CASE M% OF       WHEN WM_NOTIFY: LOCAL nmlink{} DIM nmlink{hdr{}=_NMHDR{}, item{}=_LITEM{}} !(^nmlink{}+4) = L%         IF nmlink.hdr.idFrom% = lwid% AND nmlink.hdr.code% = -2 THEN PRINT "Clicked link ";nmlink.item.iLink% ENDIF ENDCASE ENDPROC code If there is more than one hyperlink in the text you can determine which was clicked from the **nmlink.item.iLink%** value (0 corresponds to the first hyperlink, 1 to the second etc.). For the purposes of demonstration the value is printed to the screen; in a real application you will want to take a different action.

Note that the usual [|precautions] related to interrupt service routines apply, and you may wish to set a global flag which is tested elsewhere rather than process the action within **PROCsys**.

If, as is likely, your program needs to respond to other **ON SYS** events, such as menu selections and button presses, you will need to extend the **PROCsys** routine by adding a **WHEN** clause to intercept the **WM_COMMAND** (&111) messages.