Creating a link within a dialog

This code snippet is originally from the former WinAPI site www.winapi.net

To create a link within a dialog box, you have to add a Text to your dialog, which should be used as link. Assign the Notify-Style to this text control.

We use the Name IDC_URL for this control.

Now we add the following code to your dialog procedure. After clicking the text you will be redirected to the website with the standard browser.

case WM_COMMAND:
    switch(LOWORD(wParam))
    {
        case IDC_URL:
            if(HIWORD(wParam) == STN_CLICKED)
            {
                ShellExecute(hWnd, NULL, TEXT("http://www.pellesc.de/"),
                          NULL, NULL, SW_SHOW);
            }
            return(TRUE);
     }

To get your link underlined, add the following code:

case WM_INITDIALOG:
    {
    LOGFONT lf;
 
    if(NULL == (hFont = (HFONT)SendDlgItemMessage(hWnd, IDC_URL, WM_GETFONT, 0, 0)))
        hFont = (HFONT)GetStockObject(SYSTEM_FONT);
 
    GetObject((HGDIOBJ)hFont, sizeof(lf), &lf);
    lf.lfUnderline = TRUE;
    hFont = CreateFontIndirect(&lf);
    SendDlgItemMessage(hWnd, IDC_URL, WM_SETFONT, (WPARAM)hFont, (LPARAM)TRUE);
    }
    return(TRUE);
 
case WM_NCDESTROY:
    if(hFont)
    {
        DeleteObject((HGDIOBJ)hFont);
     }
    break;

Don't forget to add a HFONT hFont to your dialog procedure!

To change the cursor you have to create at first a gobal variable:

WNDPROC g_wndpStatic;

Add the following code to your dialog procedure:

    g_wndpStatic = (WNDPROC)SetWindowLongPtr(GetDlgItem(hWnd, IDC_URL),
                               GWLP_WNDPROC, (LONG_PTR)UrlProc);

Now we only need the subclass procedure to react on the WM_SETCURSOR message:

LRESULT CALLBACK UrlProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
    switch(uMsg)
    {
        case WM_SETCURSOR:
            SetCursor(LoadCursor(NULL, IDC_HAND));
            return(TRUE);
        default:
            break;
    }
return(CallWindowProc(g_wndpStatic, hWnd, uMsg, wParam, lParam));
}

Mostly, the URL links within a dialog are blue, so we have to change the text color:

case WM_CTLCOLORSTATIC:
   if(GetDlgItem(hWnd, IDC_URL) == (HWND)lParam)
   {
      SetTextColor((HDC)wParam, GetSysColor(COLOR_HIGHLIGHT));
      SetBkMode((HDC)wParam, TRANSPARENT);
      return((BOOL)GetStockObject(NULL_BRUSH));
   }
   break;

That's it. Now you have a link within your dialog like this:

Complete sourcecode

LRESULT CALLBACK UrlProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
    switch(uMsg)
    {
        case WM_SETCURSOR:
            SetCursor(LoadCursor(NULL, IDC_HAND));
            return(TRUE);
        default:
            break;
    }
return(CallWindowProc(g_wndpStatic, hWnd, uMsg, wParam, lParam));
}
 
LRESULT CALLBACK AboutDlgProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
  HFONT hFont;
 
    switch (uMsg)
    {
        case WM_INITDIALOG:
            {
            LOGFONT lf;
 
            if(NULL == (hFont = (HFONT)SendDlgItemMessage(hDlg, IDC_URL, WM_GETFONT, 0, 0)))
                hFont = (HFONT)GetStockObject(SYSTEM_FONT);
 
            GetObject((HGDIOBJ)hFont, sizeof(lf), &lf);
            lf.lfUnderline = TRUE;
            hFont = CreateFontIndirect(&lf);
            SendDlgItemMessage(hDlg, IDC_URL, WM_SETFONT, (WPARAM)hFont, (LPARAM)TRUE);
 
            if(NULL == (hFont = (HFONT)SendDlgItemMessage(hDlg, IDC_APPNAME, WM_GETFONT, 0, 0)))
                hFont = (HFONT)GetStockObject(SYSTEM_FONT);
 
            GetObject((HGDIOBJ)hFont, sizeof(lf), &lf);
            lf.lfHeight = 16;
			lf.lfWeight = FW_BOLD;
            hFont = CreateFontIndirect(&lf);
            SendDlgItemMessage(hDlg, IDC_APPNAME, WM_SETFONT, (WPARAM)hFont, (LPARAM)TRUE);
 
            g_wndpStatic = (WNDPROC)SetWindowLongPtr(GetDlgItem(hDlg, IDC_URL),
                               GWLP_WNDPROC, (LONG_PTR)UrlProc);
            }
            return TRUE;
 
        case WM_COMMAND:
            switch (wParam)
            {
               case IDC_URL:
                  if(HIWORD(wParam) == STN_CLICKED)
                  {
                      ShellExecute(hDlg, NULL, TEXT("http://www.pellesc.de/"),
                                NULL, NULL, SW_SHOW);
                  }
                  return(TRUE);
 
                case IDOK:
                    EndDialog(hDlg, TRUE);
                    return TRUE;
            }
            break;
 
        case WM_CTLCOLORSTATIC:
           if(GetDlgItem(hDlg, IDC_URL) == (HWND)lParam)
           {
              SetTextColor((HDC)wParam, GetSysColor(COLOR_HOTLIGHT));
              SetBkMode((HDC)wParam, TRANSPARENT);
              return((BOOL)GetStockObject(NULL_BRUSH));
           }
           break;
 
        case WM_NCDESTROY:
            if(hFont)
            {
                DeleteObject((HGDIOBJ)hFont);
             }
            break;
 
    }
 
    return FALSE;
}