リンクタグを実現しよう
HTMLの醍醐味は、やっぱりハイパーリンクでしょうね。このハイパーリンクを実現すれば、かなりHTMLエディタらしくなってくるでしょうね。今回は、共通関数群を作ろうで作成した"絶対・相対パス変換"のコードが正しく動作するかを確かめるという目的もあります。では頑張って行きましょう。
21.やっぱりリソースをいじるのです
さて、ここでは今回のリンクタグでは、以下の3つのリンクのみをサポートすることにします。詳しいことは書けません(専門ではないし、専門の人にたたかれそうですしね)が、簡単に説明しました。
1. http:(Hypertext Transfer Protocol)
WorldWideWebにおける通常のリンクに使用する。
2. ftp:(File Transfer Protocol)
ファイル転送にしようするサーバーへのリンクへ使用する。
3.mailto:
メールアドレスのリンクに使用する。
ここでやっぱり、ダイアログを作成します。
1.リソースタブをクリック、ダイアログを追加
IDはIDD_DLG_LINKが適当でしょう。ダイアログのタイトルはリンク設定なんかがベストだと思います。
2.こんな感じで編集する(図を参考にしてください)
3.IDC_LINK_RADIO_HTTPを選択・プロパティをオープン
一般タグのグループをチェックしてください。三つのラジオボタンをグループ化します。
4.ダイアログのクラスを作成
※ダイアログをダブルクリックすると、ダイアログのクラスを新規に作成するか、既存のクラスを選択するか聞かれるので新規に作成するを選択してOKを押す。
※クラス名をCDlgSetLinkにしOK(ファイル名は自動補完されるので手を加える必要ないです)
※この操作については、chapter7で詳しく説明したのでもうわかりますよね。
5.コントロールに対応するメンバ変数を作成する
クラスウィザードを開き、メンバ変数タブをクリックします。以下の図のようにメンバ変数を設定してください(前回の説明が分かっていれば簡単ですよね)
ここで大切なのは、ラジオボタンがグループ化されれば、グループをチェックしたIDC_LINK_RADIO_HTTPのみクラスウィザードのメンバ変数の欄で見えるはずです。そうでなければ、ラジオボタンがグループ化されていません。
これで下ごしらえ?は完了です。次はダイアログの動作を決めていきます。
22.メッセージをバインドしていきます
まずはラジオボタンの動作を決めていきます。今回の動作とは、"ラジオボタンを押すことによるエディットボックスへの文字列表示"です。なんだか堅苦しいネーミングですが、要するにhttp:が選択されている状況では、エディットボックスにもhttp:が表示されているようにするわけです。当然mailto:が 選択されていたら、エディットボックスにもmailto:が表示されるように設計します。なぜこのような操作を行うと便利かといいますと、最終的なリンクのタグは
<A HREF = "○○○○○○">〜</A>
で記述され、この○○○○○○の中に
通常のURLであったら
http://www.geocities.co.jp/SiliconValley-PaloAlto/9127/
ftpサーバであったら
ftp://visual.sample.co.jp/ (架空のサイトですよ、もしかして存在したりして^^;)
メールアドレスだったら
mailto:chiaki_f@milk.freemail.ne.jp
が入ります。したがってエディットボックスに書かれる文字そのものを○○○○○○だとすれば、タグ生成コードは非常に単純になるからです。もしこの補完を行わないと、タグを生成する時に、いろいろ面倒くさいことになります。例えば、メールアドレスをリンクするときがもっとも不便です。HTMLをよくご存知の人は、mailto:から書き始めるかも知れませんし、あるいは初心者の人はただ、メールアドレスを書き込むかもしれないので、コーディングで条件判定を・・・なんて面倒くさいことが待っているでしょう。これをなくすためにわざとhttp:やftp:やmailto:の文字列をあらかじめ書き込んでしまおうという魂胆なのです。

"うんちく"を語るのはまた今度にしておいて、早速コーディングの方へ行ってみましょう。
1.クラスウィザードでメッセージをバインドする
IDC_LINK_RADIO_HTTPとIDC_LINK_RADIO_FTPとIDC_LINK_RADIO_MAILに対してBNCLICKEDメッセージをバインドする。これも前章で説明しているのでわかりますよね。この操作だけでも面倒だぁという面倒くさがり屋さんは、このダイアログリソースを開き、ラジオボタンをダブルクリックしても同じことができます。
※3つの関数を追加することになりますが、関数名はディフォルトで結構でしょう。毎回ディフォルトじゃんって言われそうですが、自動的に作られる関数名は、IDから作られた物です。したがってID名をしっかりつけていけば関数名に凝らなくても、自動的に作ってくれるのです。
2.以下のコードをコーディングします。
/////////////////////////////////////////////////////////////////////////////
// CDlgSetLink メッセージ ハンドラ

void CDlgSetLink::OnLnkRadioHttp() 
{
	m_strUrl = "http:";
	UpdateData(false);
}

void CDlgSetLink::OnLnkRadioMail() 
{
	m_strUrl = "mailto:";
	UpdateData(false);
}

void CDlgSetLink::OnLnkRadioFtp() 
{
	m_strUrl = "ftp:";
	UpdateData(false);	
}
ただエディットボックスに文字を反映させるだけですが、一旦メンバ変数に文字列を代入し、UpdateData(false);でメンバからエディットボックスにデータを反映させています。この操作で、メンバ変数m_strUrlの値と表示されている文字列は一致します。(が、当然のことながらユーザがエディットボックスにデータを書きこむと、エディットボックスとメンバ変数のデータは異なってきます。)
3.メニューリソースを編集する
では、ラジオボタンが動作するかを確認するために、リンクダイアログを表示させましょう。リソースのメニューを開き、[挿入]に以下の[リンク]メニューを追加する。
クラスウィザードで、ID_INS_LINKにCOMMANDメッセージをバインドするのですが、ここではCMyHtmlViewクラスのCOMMANDにバインドしましょう。関数名はディフォルト(OnInsLink)です。したがって[リンク]を押すとビューのOnInsLink関数が駆動するようになります。この関数に以下のコードを記述します。
// リンク
void CMyHtmlView::OnInsLink() 
{
	CString strSel;
 	CDlgSetLink cDlg;
 	if(cDlg.DoModal()!=IDOK){return;}
}
さて実行してみましょう。ラジオボタンを押すとエディットボックスに文字列が書き込まれますよね。しかし初めてダイアログを起動した時に、ラジオボタンの選択がされていないことに気がつきましたか?(気づかなかった人は確認しておきましょう)。一般的にラジオボタンは、複数の選択肢のうちどれか1つを選択するためのボタンですから、初期選択されていなければなりません。そこで・・・
4.メッセージWM_INITDIALOGハンドラを追加
具体的には、下の図のような操作です。
BOOL CDlgSetLink::OnInitDialog() という関数が自動的に挿入されます。WM_INITDIALOGはダイアログが表示される前にダイアログに送られるメッセージで、このメッセージが出たらOnInitDialog() を実行すると定義したことになります。ここで
BOOL CDlgSetLink::OnInitDialog() 
{
	CDialog::OnInitDialog();
	
	m_strUrl = "http:";
	m_btnCheck.SetCheck(1);
	UpdateData(false);

	return TRUE;  // コントロールにフォーカスを設定しないとき、戻り値は TRUE となります
	              // 例外: OCX プロパティ ページの戻り値は FALSE となります
}
※SetCheck関数とは、ラジオボタンでグループのチェックを入れたもの(リーダー)を選択状態にする関数です。

最後に残ったのは、参照ボタンです。これはホームページを作成する時など、ローカル(PC内の)ファイルをリンクするのに使用するものです。まずはメッセージバインドからいつものように行っていきます。
1.クラスウィザードでIDC_LINK_BTN_URLに関して、メッセージBN_CLICKEDを選択し、関数の追加
これがよく言うメッセージバインドです。関数名はディフォルト(OnLnkBtnUrl)で結構ですよ。
2.コードを書き込む (今回はちょっと複雑です)
void CDlgSetLink::OnLnkBtnUrl() 
{
	// Documentのポインタ
	CMyHtmlDoc* pDoc = GetMyDocument();

	CString strBasePath;	// 基準(現在開いているドキュメント)フルパス
	CString strFilePath;	// リンクターゲットのフルパス

	// ファイルを開くダイアログ(コモンダイアログ)
	CString strFilter = "htmlファイル(*.html;*.htm)|*.html; *.htm|全てのファイル(*.*)|*.*||";
	CFileDialog cDlg(true,NULL,NULL,OFN_HIDEREADONLY|OFN_OVERWRITEPROMPT,strFilter,NULL);
	if(cDlg.DoModal()!=IDOK){return;}
	// リンクターゲットのフルパス取得
	strFilePath = cDlg.GetPathName();

	// ドキュメントフルパスを取得
	strBasePath = pDoc->GetPathName();

	// 未保存のためドキュメントフルパスが取得できない場合
	if(strBasePath.IsEmpty()){AfxMessageBox("ドキュメントを一度保存してください");return;}

	// 相対パスの計算
	m_strUrl = GetRelativePath(strBasePath,strFilePath);
	UpdateData(false);	
}
ここでいつものようにコードを追っていきましょう。
CMyHtmlDoc* pDoc = GetMyDocument();
ドキュメントへのポインタを取得します。現在操作しているドキュメントのパスを取得するために使用します。#include "myhtmldoc.h"のインクルードも忘れずに。これは共通関数群で作成したマクロでしたね。したがって#include "myhtmlcom.h"のインクルードも忘れてはいけませんよ!
CString strFilter = "htmlファイル(*.html;*.htm)|*.html; *.htm|全てのファイル(*.*)|*.*||";
CFileDialog cDlg(true,NULL,NULL,OFN_HIDEREADONLY|OFN_OVERWRITEPROMPT,strFilter,NULL);
if(cDlg.DoModal()!=IDOK){return;}
ファイルを開くダイアログ(コモンダイアログ)を開きます。ここでは詳しい説明はしませんが(さほど重要でもないので)、strFilterは、どのファイルを開くかの特定を行っています。またCFileDialogの第一引数がtrueの時は、ファイルを開く、falseの時はファイルに保存のコマンドになります。今回は別にファイルを開きたいわけではないのです。ただリンク先のファイル名のフルパスを取得するために過ぎません。
strFilePath = cDlg.GetPathName();
先ほどのダイアログのメンバ関数GetPathName()から、リンクターゲットファイルのフルパスを取得します。
strBasePath = pDoc->GetPathName();
CDocumentのメンバ関数GetPathName()から、現在操作中のドキュメントのフルパスを取得します。
if(strBasePath.IsEmpty()){AfxMessageBox("ドキュメントを一度保存してください");return;}
ドキュメントが未保存であると相対リンクは作れないので、フルパスが空だったらドキュメントを保存するように促す。
m_strUrl = GetRelativePath(strBasePath,strFilePath);
現在のドキュメントを基準にしたリンクターゲットの相対パスを求め、メンバ変数に格納します。
UpdateData(false);
メンバ変数のあたいをすぐさま反映する関数です。
では実行してみましょう。2つのHTMLファイルを使って相対パスが正しく作られているか確認してみてくださいね。同じファルダにあるファイルをリンクしようとするとエディットボックスの文字列は、ファイル名そのものになっているはずです。
23.タグ生成コードを作成しよう
最後は、リンクタグを作成するコードです。でも前回のフォントタグと比べたら非常に簡単だと思います。まずは、リンクタグを作成するメンバ関数とそれに必要なメンバ変数を追加していきます。
1.DlgSetFont.hを開き、以下を追加
class CDlgSetLink : public CDialog
{
// コンストラクション
public:
	void MakeTag(CString strIns);	// ここを追加
	CString strTag;		// ここを追加
	CDlgSetLink(CWnd* pParent = NULL);   // 標準のコンストラクタ

// ダイアログ データ
2.DlgSetFont.cppを開き、ファイルの末尾に以下を挿入
// タグの生成
void CDlgSetLink::MakeTag(CString strIns)
{
	CString strTagA,strTagB;
	strTagA = "<A HREF=\"";
	strTagA += m_strUrl;
	strTagA += "\">";
	strTagB = "</A>";
	strTag = strTagA + strIns + strTagB;
}
言うまでもありませんが、タグを生成するコードです。簡単なので説明は割愛させていただきます。ちょっと言い忘れてましたが、文字列の中に「"」ダブルクォーテーションを入れたい場合は、文字列を識別するダブルクォーテーションと区別するために、\を直前につける必要があります。
strTagA += "\">";
つまるところ、上の赤い"が文字列を識別するダブルクォーテーションで、緑色の"は「"」そのものということになります。
3.最後にCMyHtmlView::OnInsLink()関数を編集
// リンク
void CMyHtmlView::OnInsLink() 
{
	CString strSel;
 	CDlgSetLink cDlg;
 	if(cDlg.DoModal()!=IDOK){return;}

	CEdit& cEdt = GetEditCtrl();
	cEdt.Copy();
	strSel = GetClipBoard();
	
	cDlg.MakeTag(strSel);
	PasteString(cDlg.strTag);
	SetFocus();
}
実はフォントタグの時とあんまり変わってないですが^^;、実行してみましょう。うまくリンクでタグが挿入できましたか?
さて、あとまだ実現できていない代表的なタグといえば・・・そうIMGタグですね。これに関しては、民さんに全部実装してほしいと思います。
プログラミングの基本は、
1.まず人の書いたプログラムをコピー
C言語だったら、printf("Hello C World\n");なんてコードを書いた覚えありますよね。
2.少しずつ書き換えたりして、どんな働きになるか調べてみる
変数を変えてみたり,printfの書式を変えたりしていろいろ試したはずですよね。
3.自分で書いてみる
そして自分でプログラムを1から書いてみます。
だと思います。そこで本サイトではイメージタグの挿入に関しては解説しません。各自ご自由に作成してください。ちょっとヒントに私が作ったイメージタグ挿入のダイアログをお見せして、この章は終わりにしておきますね。では!
※もう少しヒントですが、ファイルのリンクと画像のリンクも相対パスを使用する点は全く同じですよ!

[Next]
[Previous]
[Home]