ホームに戻る 初歩のVC++Programming Tipsに戻る

初歩のVC++Programming Tips Win32SDK篇

アプリケーションからインターネットへのリンクの作り方


一般にアプリケーションには「バージョン情報」、あるいはそれと同等のダイアログを表示する機能を実装するのが慣例です。そこにはバージョンはもちろん、著作権情報や著作権者のURLE-Mailアドレスを表示することになると思います。このURLやE-Mailアドレスをクリックすると自動的にブラウザやメーラーが起動して、目的の場所へ連れていってくれる機能があると、合理的かつ近代的な感じでよいですね。

ShellExecute関数

ShellExecute関数はそんな機能を実現できる便利な関数です。たとえば、ブラウザを起動して
http://www.win32lab.com/ を開くには

ShellExecute(hWnd,NULL,"http://www.win32lab.com/",NULL,NULL,SW_SHOWNORMAL);

の用に記述します。この関数は、他にもe-mailアドレスやファイルの拡張子連動実行にも使えます。詳しい使い方はSDKの文書を見てください。

次に、この関数を実行させるきっかけとなる仕掛けを作ります。この仕掛けは、ダイアログのテキストをクリックするとブラウザが立ち上がるという動作をします。「ホームページを開く」といったボタンなどを設置する場合は以下の手順は必要ありません。

コントロールからのマウスメッセージを親ウインドウに通知させる

題名のとおりです。これをしないと、ウインドウプロシージャ側でコントロールがクリックされたことを検出できません。リソースの作成で、ダイアログ上のインターネットへのリンクとしたいスタティックテキストのプロパティで、次のように設定します。

リンクにはアンダーライン

リンクになっていることを、ユーザーに認知させるために、テキストにはアンダーラインを引きます。これを実現するために、サブクラス化というテクニックを使います。サブクラス化とは、おおざっぱに言うと独自に作成したウインドウ関数を、ウインドウに登録することを言います。つまり、そのウインドウへのメッセージを乗っ取ることが出来るわけです。今回は WM_PAINT を処理するコードを作成し、それ以外のメッセージはデフォルトのウインドウ関数に渡します。
 今回は見送りましたが、マウスポインタがリンク上にあるときにはマウスポインタを「手」に変わるようにしたり、一度訪れた後にはリンクを赤く設定するなどの機能をつけると面白いかもしれません。

リンクの上では「手」マウスカーソル[1998/9/16 加筆]

MSJの記事に刺激されたってわけじゃありませんが、リンクの上にカーソルを合わせたら「手」の形のポインタにしないと、ユーザーがリンクになっていることを見落とす可能性があります。この「手」のポインタはストックオブジェクトにはありませんので自分で作る必要があります。リソースエディタで作ってください。

実行コードでは、LoadCursor関数で作ったカーソルリソースを読み込んで、サブクラスハンドラ内でWM_SETCURSORを受け取ったときにSetCursor関数で『手」のポインタにセットします。

実行してみたらこんな感じ

以下、使用例です。「ダイアログベースアプリの作り方」のソースを元に作りました。

resource.h

//{{NO_DEPENDENCIES}}
// Microsoft Developer Studio generated include file.
// Used by Script1.rc
//
#define IDD_DIALOG1                     101
#define IDC_WWW                         1000

// Next default values for new objects
// 
#ifdef APSTUDIO_INVOKED
#ifndef APSTUDIO_READONLY_SYMBOLS
#define _APS_NO_MFC                     1
#define _APS_NEXT_RESOURCE_VALUE        102
#define _APS_NEXT_COMMAND_VALUE         40001
#define _APS_NEXT_CONTROL_VALUE         1001
#define _APS_NEXT_SYMED_VALUE           101
#endif
#endif

tips12.c

/******************************************************************************
title    : tips12 - ダイアログにURLへのリンクを付ける     for win95/NT4.0
compiler : VC++ 5.0
******************************************************************************/
#include<windows.h>
#include<shlobj.h>
#include"resource.h"

/* グローバル変数 */
const char  szClassName[]="Tips12Class";
const char  szAppName[]="Tips12";
const char  szAppVer[]="1.0";
HFONT       hFontLink;          //リンクラベルフォント
WNDPROC     oldLinkProc=NULL;
HCURSOR     hCurHand;

/*-----------------------------------------------------------------------------
  メインダイアログ サブクラス ハンドラ
-----------------------------------------------------------------------------*/
LRESULT CALLBACK linkProc(HWND hWnd,UINT uMessage,WPARAM wParam,LPARAM lParam)
{
    switch(uMessage){
        
        //マウスポインタの変更
        case WM_SETCURSOR:
            SetCursor(hCurHand);
            return 0;
        
        case WM_PAINT:
        {
            PAINTSTRUCT ps;
            HDC         hdc;
            char        szTextTmp[100];
            
            GetWindowText(hWnd,szTextTmp,100);
            hdc=BeginPaint(hWnd,&ps);
            SelectObject(hdc,hFontLink);
            SetTextColor(hdc,RGB(0,0,255));//青
            SetBkColor(hdc,GetSysColor(COLOR_BTNFACE));
            SetBkMode(hdc,OPAQUE);
            TextOut(hdc,0,0,szTextTmp,lstrlen(szTextTmp));
            EndPaint(hWnd,&ps);
            return 0;
        }
    }
    return CallWindowProc(oldLinkProc,hWnd,uMessage,wParam,lParam);
}


/*-----------------------------------------------------------------------------
  メインダイアログプロシージャ
-----------------------------------------------------------------------------*/
LRESULT CALLBACK mainDlgProc(HWND hWnd,UINT uMessage,WPARAM wParam,LPARAM lParam)
{

    switch(uMessage){
        
        //ウインドウ作成時の処理
        case WM_INITDIALOG:
        {
            LOGFONT logfont;
        
            //フォントの設定(アンダーライン)
            hFontLink=(HFONT)SendMessage(GetDlgItem(hWnd,IDC_WWW),WM_GETFONT,0,0);
            GetObject(hFontLink,sizeof(logfont),&logfont);
            logfont.lfUnderline=1;
            hFontLink=CreateFontIndirect(&logfont);
            SendDlgItemMessage(hWnd,IDC_WWW,WM_SETFONT,(WPARAM)hFontLink,0);
            //サブクラスハンドラの登録
            oldLinkProc=(WNDPROC)GetWindowLong(GetDlgItem(hWnd,IDC_WWW),GWL_WNDPROC);
            SetWindowLong(GetDlgItem(hWnd,IDC_WWW),GWL_WNDPROC,(LONG)linkProc);
            break;
        }
        
        //ユーザーメッセージ処理
        case WM_COMMAND:
            switch(LOWORD(wParam)){
                //終了
                case IDCANCEL:
                    DestroyWindow(hWnd);
                    break;
                
                //WWWブラウザの起動
                case IDC_WWW:
                    if(HIWORD(wParam) == STN_CLICKED)
                    {
                        char szTextTmp[100];
                        
                        GetDlgItemText(hWnd,LOWORD(wParam),szTextTmp,100);
                        ShellExecute(hWnd,NULL,szTextTmp,NULL,NULL,SW_SHOWNORMAL);
                    }
                    break;
                
                default:
                    return DefWindowProc(hWnd,uMessage,wParam,lParam);
            }
            break;
        
        //[X]ボタン
        case WM_CLOSE:
            PostMessage(hWnd,WM_COMMAND,IDCANCEL,0);
            break;
        
        //プログラム終了時のウインドウ破棄
        case WM_DESTROY:
            DeleteObject(hFontLink)
            PostQuitMessage(0);
            break;

        default:
            return DefWindowProc(hWnd,uMessage,wParam,lParam);
    }//switch end
    
    return 0;
}


/*=============================================================================
  WinMain
=============================================================================*/
int APIENTRY WinMain(HINSTANCE hInstCurrent, HINSTANCE hinstPrevious, LPSTR lpszCmdLine, int nCmdShow)
{
    HWND        hDlg;           //メインダイアログハンドル
    MSG         msg;
    WNDCLASS    wndclass;
    
    //メインウインドウクラスの登録
    wndclass.style         = 0;
    wndclass.lpfnWndProc   = mainDlgProc;
    wndclass.cbClsExtra    = 0;
    wndclass.cbWndExtra    = DLGWINDOWEXTRA;
    wndclass.hInstance     = hInstCurrent;
    wndclass.hIcon         = LoadIcon(NULL,IDI_APPLICATION);
    wndclass.hCursor       = LoadCursor(NULL,IDC_ARROW);
    wndclass.hbrBackground = (HBRUSH)(COLOR_BTNFACE+1);
    wndclass.lpszMenuName  = NULL;
    wndclass.lpszClassName = szClassName;
    if(RegisterClass(&wndclass) == 0)
    {
        MessageBox(NULL,"ウインドウクラスを登録できませんでした",
                szAppName,MB_APPLMODAL | MB_ICONSTOP);
        return FALSE;
    }
    
    //カーソルリソースの読み込み
    hCurHand=LoadCursor(hInstCurrent,MAKEINTRESOURCE(IDC_HAND));

    //メインウインドウの生成
    if((hDlg=CreateDialog(hInstCurrent,MAKEINTRESOURCE(IDD_DIALOG1),0,mainDlgProc)) == NULL)
    {
        MessageBox(NULL,"メインウインドウを作成できませんでした",
                szAppName,MB_APPLMODAL | MB_ICONSTOP);
        return FALSE;
    }
    
    //メインウインドウの表示
    ShowWindow(hDlg, nCmdShow);
    UpdateWindow(hDlg);

    //メッセージループ
    while(GetMessage(&msg, NULL, 0, 0))
    {
        if(IsDialogMessage(hDlg,&msg) == FALSE)
        {
            TranslateMessage(&msg);
            DispatchMessage(&msg);
        }
    }

    return msg.wParam;
}

Script1.rc

//Microsoft Developer Studio generated resource script.
//
#include "resource.h"

#define APSTUDIO_READONLY_SYMBOLS
/////////////////////////////////////////////////////////////////////////////
//
// Generated from the TEXTINCLUDE 2 resource.
//
#include "afxres.h"

/////////////////////////////////////////////////////////////////////////////
#undef APSTUDIO_READONLY_SYMBOLS

/////////////////////////////////////////////////////////////////////////////
// 日本語 resources

#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_JPN)
#ifdef _WIN32
LANGUAGE LANG_JAPANESE, SUBLANG_DEFAULT
#pragma code_page(932)
#endif //_WIN32

/////////////////////////////////////////////////////////////////////////////
//
// Dialog
//

IDD_DIALOG1 DIALOG DISCARDABLE  0, 0, 163, 105
STYLE WS_MINIMIZEBOX | WS_POPUP | WS_CAPTION | WS_SYSMENU
CAPTION "Tips12"
CLASS "Tips12Class"
FONT 9, "MS Pゴシック"
BEGIN
    PUSHBUTTON      "OK",IDCANCEL,57,84,50,14
    LTEXT           "http://member.nifty.ne.jp/t-matsuo/",IDC_WWW,28,21,106,
                    8,SS_NOTIFY
END


/////////////////////////////////////////////////////////////////////////////
//
// DESIGNINFO
//

#ifdef APSTUDIO_INVOKED
GUIDELINES DESIGNINFO DISCARDABLE 
BEGIN
    IDD_DIALOG1, DIALOG
    BEGIN
        LEFTMARGIN, 7
        RIGHTMARGIN, 156
        TOPMARGIN, 7
        BOTTOMMARGIN, 98
    END
END
#endif    // APSTUDIO_INVOKED


#ifdef APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// TEXTINCLUDE
//

1 TEXTINCLUDE DISCARDABLE 
BEGIN
    "resource.h\0"
END

2 TEXTINCLUDE DISCARDABLE 
BEGIN
    "#include ""afxres.h""\r\n"
    "\0"
END

3 TEXTINCLUDE DISCARDABLE 
BEGIN
    "\r\n"
    "\0"
END

#endif    // APSTUDIO_INVOKED


/////////////////////////////////////////////////////////////////////////////
//
// Cursor
//

IDC_HAND                CURSOR  DISCARDABLE     "hand.cur"
#endif    // 日本語 resources
/////////////////////////////////////////////////////////////////////////////



#ifndef APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// Generated from the TEXTINCLUDE 3 resource.
//


/////////////////////////////////////////////////////////////////////////////
#endif    // not APSTUDIO_INVOKED

copyright (c) 1998-2000 by T-Matsuo
ホームに戻る 初歩のVC++Programming Tipsに戻る