ホームに戻る 初歩のVC++Programming Tipsに戻る
一般にアプリケーションには「バージョン情報」、あるいはそれと同等のダイアログを表示する機能を実装するのが慣例です。そこにはバージョンはもちろん、著作権情報や著作権者のURL、E-Mailアドレスを表示することになると思います。このURLやE-Mailアドレスをクリックすると自動的にブラウザやメーラーが起動して、目的の場所へ連れていってくれる機能があると、合理的かつ近代的な感じでよいですね。
ShellExecute関数はそんな機能を実現できる便利な関数です。たとえば、ブラウザを起動して
http://www.win32lab.com/
を開くには
ShellExecute(hWnd,NULL,"http://www.win32lab.com/",NULL,NULL,SW_SHOWNORMAL);
の用に記述します。この関数は、他にもe-mailアドレスやファイルの拡張子連動実行にも使えます。詳しい使い方はSDKの文書を見てください。
次に、この関数を実行させるきっかけとなる仕掛けを作ります。この仕掛けは、ダイアログのテキストをクリックするとブラウザが立ち上がるという動作をします。「ホームページを開く」といったボタンなどを設置する場合は以下の手順は必要ありません。
題名のとおりです。これをしないと、ウインドウプロシージャ側でコントロールがクリックされたことを検出できません。リソースの作成で、ダイアログ上のインターネットへのリンクとしたいスタティックテキストのプロパティで、次のように設定します。

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