c++ win32 add a hyperlink to a dialog
Asked Answered
C

3

11

I would like to add an About dialog to my Win32 application (developed using C++). How can I add a hyperlink to the dialog? I'm loading the dialog from a resource file (.rc). Is it possible to define this functionality from the .rc file?

My .rc file now looks like this:

 IDD_ABOUTBOX DIALOGEX 0, 0, 218, 118
 STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | WS_SYSMENU | DS_CENTER 
 CAPTION "About My App"
 FONT 8, "MS Shell Dlg"
 BEGIN
    ICON            IDI_APP_ICON,IDC_STATIC,13,88,15,15
    LTEXT           "MY url http://www.myurl.com",IDC_STATIC,15,6,194,24,SS_NOPREFIX
    DEFPUSHBUTTON   "OK",IDOK,95,98,50,14,WS_GROUP
 END    
Clywd answered 16/10, 2011 at 14:40 Comment(0)
B
11

You can use a SysLink Control on Windows XP or above.

You can define it from the .rc file like this:

In resource.rc:

 CONTROL         "<a>Link</a>",IDC_SYSLINK1,"SysLink",WS_TABSTOP,7,7,53,12

In resource.h:

#define IDC_SYSLINK1                    1001
Bibliotherapy answered 16/10, 2011 at 15:53 Comment(5)
SYSLink and MFCLink controls both make the entire dialog window blank of any other controls, like it makes all the controls invisible.. no idea why..Plum
@SSpoke: Just curious if the blanked dialogs were created with the CreateDialogIndirect functionBrighton
@LaurieStearn No I used tab1_hwnd = CreateDialog(hDLLModule, MAKEINTRESOURCE(IDD_TAB_1), hDlg, DialogPage); it's hidden by default I enable it by ShowWindow ShowWindow(tab1_hwnd, (Current_Visible_Selected_Tab == 0) ? SW_SHOW : SW_HIDE); Found a good fix for this if anyone needs I could post it.. it requires Subclassing but it's still fairly small and portable. Just changes colors when you put mouse over the label and if you click it does ShellExecute(NULL, "open", "http://blah.com", NULL, NULL, SW_SHOWNORMAL);Plum
@SSpoke: Good to know, Yet to try it here, will get back on that ASAP, thanks. :)Brighton
In order to work I had to add following line: #pragma comment(linker,"/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='x86' publicKeyToken='6595b64144ccf1df' language='*'\"")Tryma
P
3

Best way to do the highlighting without any external libraries, still looks and feels the same way any control would do it, even makes the mouse cursor into a finger pointing icon.

/* Start of HyperLink URL */
#define PROP_ORIGINAL_FONT      TEXT("_Hyperlink_Original_Font_")
#define PROP_ORIGINAL_PROC      TEXT("_Hyperlink_Original_Proc_")
#define PROP_STATIC_HYPERLINK   TEXT("_Hyperlink_From_Static_")
#define PROP_UNDERLINE_FONT     TEXT("_Hyperlink_Underline_Font_")
LRESULT CALLBACK _HyperlinkParentProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam);
LRESULT CALLBACK _HyperlinkProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam);
static void CreateHyperLink(HWND hwndControl);
/* End of HyperLink URL */



static void CreateHyperLink(HWND hwndControl)
{
    // Subclass the parent so we can color the controls as we desire.
    HWND hwndParent = GetParent(hwndControl);
    if (NULL != hwndParent)
    {
        WNDPROC pfnOrigProc = (WNDPROC)GetWindowLong(hwndParent, GWL_WNDPROC);
        if (pfnOrigProc != _HyperlinkParentProc)
        {
            SetProp(hwndParent, PROP_ORIGINAL_PROC, (HANDLE)pfnOrigProc);
            SetWindowLong(hwndParent, GWL_WNDPROC, (LONG)(WNDPROC)_HyperlinkParentProc);
        }
    }

    // Make sure the control will send notifications.
    DWORD dwStyle = GetWindowLong(hwndControl, GWL_STYLE);
    SetWindowLong(hwndControl, GWL_STYLE, dwStyle | SS_NOTIFY);

    // Subclass the existing control.
    WNDPROC pfnOrigProc = (WNDPROC)GetWindowLong(hwndControl, GWL_WNDPROC);
    SetProp(hwndControl, PROP_ORIGINAL_PROC, (HANDLE)pfnOrigProc);
    SetWindowLong(hwndControl, GWL_WNDPROC, (LONG)(WNDPROC)_HyperlinkProc);

    // Create an updated font by adding an underline.
    HFONT hOrigFont = (HFONT)SendMessage(hwndControl, WM_GETFONT, 0, 0);
    SetProp(hwndControl, PROP_ORIGINAL_FONT, (HANDLE)hOrigFont);

    LOGFONT lf;
    GetObject(hOrigFont, sizeof(lf), &lf);
    lf.lfUnderline = TRUE;

    HFONT hFont = CreateFontIndirect(&lf);
    SetProp(hwndControl, PROP_UNDERLINE_FONT, (HANDLE)hFont);

    // Set a flag on the control so we know what color it should be.
    SetProp(hwndControl, PROP_STATIC_HYPERLINK, (HANDLE)1);
}

LRESULT CALLBACK _HyperlinkParentProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    WNDPROC pfnOrigProc = (WNDPROC)GetProp(hwnd, PROP_ORIGINAL_PROC);

    switch (message)
    {
    case WM_CTLCOLORSTATIC:
    {
        HDC hdc = (HDC)wParam;
        HWND hwndCtl = (HWND)lParam;

        BOOL fHyperlink = (NULL != GetProp(hwndCtl, PROP_STATIC_HYPERLINK));
        if (fHyperlink)
        {
            LRESULT lr = CallWindowProc(pfnOrigProc, hwnd, message, wParam, lParam);
            SetTextColor(hdc, RGB(0, 0, 192));
            return lr;
        }

        break;
    }
    case WM_DESTROY:
    {
        SetWindowLong(hwnd, GWL_WNDPROC, (LONG)pfnOrigProc);
        RemoveProp(hwnd, PROP_ORIGINAL_PROC);
        break;
    }
    }
    return CallWindowProc(pfnOrigProc, hwnd, message, wParam, lParam);
}

LRESULT CALLBACK _HyperlinkProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    WNDPROC pfnOrigProc = (WNDPROC)GetProp(hwnd, PROP_ORIGINAL_PROC);

    switch (message)
    {
    case WM_DESTROY:
    {
        SetWindowLong(hwnd, GWL_WNDPROC, (LONG)pfnOrigProc);
        RemoveProp(hwnd, PROP_ORIGINAL_PROC);

        HFONT hOrigFont = (HFONT)GetProp(hwnd, PROP_ORIGINAL_FONT);
        SendMessage(hwnd, WM_SETFONT, (WPARAM)hOrigFont, 0);
        RemoveProp(hwnd, PROP_ORIGINAL_FONT);

        HFONT hFont = (HFONT)GetProp(hwnd, PROP_UNDERLINE_FONT);
        DeleteObject(hFont);
        RemoveProp(hwnd, PROP_UNDERLINE_FONT);

        RemoveProp(hwnd, PROP_STATIC_HYPERLINK);

        break;
    }
    case WM_MOUSEMOVE:
    {
        if (GetCapture() != hwnd)
        {
            HFONT hFont = (HFONT)GetProp(hwnd, PROP_UNDERLINE_FONT);
            SendMessage(hwnd, WM_SETFONT, (WPARAM)hFont, FALSE);
            InvalidateRect(hwnd, NULL, FALSE);
            SetCapture(hwnd);
        }
        else
        {
            RECT rect;
            GetWindowRect(hwnd, &rect);

            POINT pt = { LOWORD(lParam), HIWORD(lParam) };
            ClientToScreen(hwnd, &pt);

            if (!PtInRect(&rect, pt))
            {
                HFONT hFont = (HFONT)GetProp(hwnd, PROP_ORIGINAL_FONT);
                SendMessage(hwnd, WM_SETFONT, (WPARAM)hFont, FALSE);
                InvalidateRect(hwnd, NULL, FALSE);
                ReleaseCapture();
            }
        }
        break;
    }
    case WM_SETCURSOR:
    {
        // Since IDC_HAND is not available on all operating systems,
        // we will load the arrow cursor if IDC_HAND is not present.
        HCURSOR hCursor = LoadCursor(NULL, IDC_HAND);
        if (NULL == hCursor)
            hCursor = LoadCursor(NULL, IDC_ARROW);
        SetCursor(hCursor);
        return TRUE;
    }
    }

    return CallWindowProc(pfnOrigProc, hwnd, message, wParam, lParam);
}

Here is how to use it:

CreateHyperLink(GetDlgItem(Dialog_HWND_GOES_HERE, STATIC_TEXT_IDENIFIER_GOES_HERE));

Where the static label can get clicked in the main dialogs subclass do something like this..

        if (HIWORD(wParam) == BN_CLICKED) { //Buttons, checkboxs, labels, static labels clicked
            switch (LOWORD(wParam))
            {
                case STATIC_TEXT_IDENIFIER_GOES_HERE:
                    ShellExecute(NULL, "open", "http://www.google.com", NULL, NULL, SW_SHOWNORMAL);
                    break;
            }
        }
Plum answered 29/2, 2016 at 23:41 Comment(1)
Beautiful! (winhlp32.exe here). There's another good explanation here, and the error codes from this beef it up a bit.Brighton
W
0

I know this question is old, but hopefully this answer helps anyone aiming to define the hyperlink directly inside an .rc file. Since .rc files do not support certain escape sequences like \", you have to use "" (double quotes) instead. Like this:

CONTROL "<a href=""<LINK>"">Click Here</a>", IDC_SYSLINK, "SysLink", WS_TABSTOP, 10, 10, 40, 40
Wimple answered 1/4 at 0:10 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.