ダイアログにハイパーリンクを作成する2(サブクラス使用)

前項目でのハイパーリンク作成方法は比較的簡単にできる反面、色々と拡張する事はできません。
それはリンクに対してのウィンドウメッセージを取得する事が基本的にできない為です。
そこでリンクをサブクラス化すると通常のウィンドウと同様のようにメッセージが取得できるので
かなり自由にカスタマイズする事が出来るようになります。
さらに1つのクラスにする事によって再利用が容易になり
いくつもリンクを張りたい場合、とてもコードが簡略化出来ます。

サブクラスを作成すると言ってもとても簡単。
クラスを新規に作成して、基本クラスにCStaticを持たせるだけでOKです。
これでCStaticをサブクラス化できます。今回はCLinkStaticと名付ける事とします。
すると、新たにLinkStatic.cppとLinkStatic.hファイルが作成されます。

次にこのクラスを使用するにはDDXで普通にスタティックテキストコントロールを配置します。
この時プロパティーでスタイルの通知にチェックを入れておくのを忘れないでください。
そして変数の追加でそのコントロールに変数を割り当てる訳ですが
ここでカテゴリをコントロールにすると変数のタイプにCLinkStaticが追加されているはずです。
これを選択して変数を作成すればサブクラスを使用する事が出来ます。
変数を作成すると「"xxxDlg.h" がクラスCLinkStatic(ファイル "LinkStatic.h")・・・」と出ますが
これはサブクラスを使う為のファイルをインクルードしてあるかを注意させる物です。
当たり前の話ですが新しいクラスの使うにはヘッダファイルをインクルードしなければなりません。
ただしこの場合、.cppファイルの方に#include擬似命令を書いてもコンパイル時にエラーになります
そこで.hファイルに#include擬似命令を記入してやってください。


// xxxDlg.h : ヘッダー ファイル
//

  ・
  ・
  ・

#include "LinkStatic.h"

/////////////////////////////////////////////////////////////////////////////
// CxxxDlg ダイアログ

以上でサブクラス化は完了し使用する準備はできました。
あとはハイパーリンク用にカスタマイズしていきます。

まずは最初にウィンドウ(ハイパーリンク)が表示されたときに指のカーソルの作成と
ハイパーリンク用のフォント(下線を引くのと色をつける)の設定をします。
そこでフォントの設定を保存しておくCFont型のメンバ変数、m_font
色をつけるためのブラシであるCBrush型のメンバ変数m_brush
指のカーソルのハンドルを保存しておくHICON型のメンバ変数、m_hCursorを用意します。
他のクラスから使う訳ではないので全てprivateにしておきましょう。


カーソルの作成とブラシの設定は初期化なのでコンストラクタで行います。
ただしフォントの設定はウィンドウが作成されてからでないと設定できないのでここではしません。
今回、フォントの作成と指のカーソルの作成は前項目とは違う方法で作ります。
こっちの方がよりエレガントかと思います。


CLinkStatic::CLinkStatic()
{
    // 指のカーソル読み込み
    char lpWinDir[MAX_PATH];
    ::GetWindowsDirectory(lpWinDir, MAX_PATH - 13);
    strcat(lpWinDir, _T("\\winhlp32.exe"));
    HINSTANCE hInstHelp = ::LoadLibrary(lpWinDir);
    if(hInstHelp)
    {
        m_hCursor = CopyCursor(::LoadCursor(hInstHelp, MAKEINTRESOURCE(106)));
        ::FreeLibrary(hInstHelp);
    }
    else
        m_hCursor = ::LoadCursor(NULL, IDC_ARROW);

    m_brush.CreateSolidBrush(::GetSysColor(COLOR_3DFACE));
}
 

指のカーソルはwinhlp32.exeからLoadLibrary()で読み込みます。
winhlp32.exeはWindowsに標準に付いているヘルプファイルの事です。
Windowsフォルダに存在しますがNT系の場合、systemフォルダにも存在していて
絶対パスで指定しないとsystemフォルダの方を読み込んでしまい指のカーソルを読み込めません。
その為、GetWindowsDirectory()を使い絶対パスを取得し設定する必要があります。
winhlp32.exeが正常にロードされた場合、LoadCursor()で指のカーソルを読み込み
さらにCopyCursor()でハンドルをコピーします。
そしてコピーしたらFreeLibrary()でインスタンスハンドルを開放してやります。
もしwinhlp32.exeがロードできなかったときは通常の矢印のカーソルを設定してます。
MAKEINTRESOURCE(106)と言うのは指のカーソルの名前だと思ってください。
この方法の利点はカーソルリソースを自前で用意する必要が無い事です。
ただし、カーソルはあの指のカーソル限定になりますが。
あのカーソルが嫌な方はやっぱり自分で作るしかないでしょう。

ブラシの初期化はCreateSolidBrush()で初期化を行います。
ここで設定するブラシの色はダイアログと同じ色にしますが、ダイアログの色の取得方法は
GetSysColor(COLOR_3DFACE)と呼び出すことで取得できます。


次にリンクに下線を引く為、フォントの設定をしますが
これはコントロール(リンク)が一番最初に表示された時に行います
最初に表示された時かどうかを判定するには独自のフラグを作成してもいいのですが
m_fontのオブジェクトが作成されているかどうかで判断できるのでこちらを利用します。
オブジェクトの存在はCFontのメンバ変数、m_hObjectで見分ける事ができます。
それから色をつけるのもコントロールの描写時に色をつけてやります。
コントロール表示時に送られるメッセージはWM_CTLCOLORですが
これはサブクラスなので=WM_CTLCOLORハンドラを追加してください。
するとCtlColor()が追加されるので以下のように記述します。


HBRUSH CLinkStatic::CtlColor(CDC* pDC, UINT nCtlColor) 
{
    // 最初に呼ばれた時だけフォントの設定をする
    if(!m_font.m_hObject)
    {
        // フォントの設定(下線を引く)
        LOGFONT lf;
        GetFont()->GetLogFont(&lf);
        lf.lfUnderline = TRUE;
        m_font.CreateFontIndirect(&lf);
        SetFont(&m_font, FALSE);
        Invalidate();
    }

    // 色を設定
    pDC->SetTextColor(RGB(0, 0, 255));
    pDC->SetBkColor(::GetSysColor(COLOR_3DFACE));
    return m_brush; 
}

フォントの作成はGetFont()で現在のフォントを取得し
GetLogFont()でそのLOGFONT構造体を取得します。
LOGFONT構造体のlfUnderlineメンバをTRUEに設定すると下線が引かれる設定になり
その構造体を使いCreateFontIndirect()で下線が引かれたフォントを作成します。
そしてSetFont()でフォントを設定しなおしてInvalidate()で再描写してやります。
この方法だとユーザーのフォントの設定に下線を引くようになります。
もしダイアログのフォントの設定を標準から変えていてもその設定が反映されたままになるので
多くの環境に対応する事になり、より優れた物となります。
CreateFont()でも良いのですが現在のフォントの設定を取得したりするとなると
こちらの方法でやった方が簡単に出来ると思います。

色の設定ですがSetTextColor()で文字の色を設定します。この場合青色になります。
そしてSetBkColor()で文字の背景色をダイアログの色に設定しています。
もちろん色は好きな色に変えてもらって結構です。
そして最後にこの設定を有効にする為m_brushを返してやります。


以上で初期化は完了です。
後はイベントを追加してやっていきます。
まずはリンク上にカーソルが来たときにカーソルを指のカーソルに変えましょう。
これはカーソルが上に来るとWM_SETCURSORが送られるのでそれを捕らえます。
ハンドラを追加するとOnSetCursor()が追加されるのでそこに記述してください。


BOOL CLinkStatic::OnSetCursor(CWnd* pWnd, UINT nHitTest, UINT message) 
{       
    ::SetCursor(m_hCursor);
    return TRUE;
}

これはリンク上にカーソルが来たらSetCursor()で指のカーソルを設定し
TRUEを返す事でカーソルを変更させています。
リンク上からカーソルが離れると自動的にカーソルは元に戻ります。


それからリンクをクリックしたときに書かれたURLにジャンプをするようにコードを書きます。
左クリック時に送られるメッセージはWM_LBUTTONDOWNですので追加してください。


void CLinkStatic::OnLButtonDown(UINT nFlags, CPoint point) 
{
    CString strJump;
    GetWindowText(strJump);
    ::ShellExecute(NULL, _T("open"), strJump, NULL, NULL, SW_SHOWNORMAL);   

    CStatic::OnLButtonDown(nFlags, point);
}

GetWindowText()でコントロールのキャプションに書かれたURLを取得し
ShellExecute()でブラウザを立ち上げて取得したURLにジャンプします。


以上で基本的なリンクの作成は完了です。
後はリンク上にカーソルが来たときにテキストの色を変えたり
クリックした瞬間ではなくボタンを離した時にジャンプするなど、
色々と機能を拡張してみてください。

ちなみに上記の拡張をしたサンプルを置いておきます。
詳しく説明はしませんがコメントを参考にしてみてください。
プロジェクトにファイルを追加して使うダイアログのヘッダファイルで
インクルードしてやればそのまま使う事も出来ます。

LinkStatic.cpp
LinkStatic.h

< 戻る << HOME ©1999-2001 by Akky, All right reserved.