第149章 本文中からURLを検出する


今回は、試しにRich Edit 2.0を使ってみます。 新しく出てくる構造体などはまだプレリミナリーなものなので 近い将来仕様が変更になる可能性があります。したがって ここで,詳しく解説してもあまり意味がないかもしれません。 それで、第147章で少し書いた URLの検出をRich Editの本文中で行う方法のみを解説します。 当然Rich Edit 2.0をサポートする環境でプログラムを作る必要が あります。


まず、Rich Edit 2.0の作り方ですが,

1.LoadLibrary("RICHED20.DLL");でDLLをロードする 2.CreateWindowExのウィンドウクラスをRICHEDIT_CLASSにする

これだけで大丈夫です。
本文中からURLを検出するにはコントロールにEM_AUTOURLDETECTを 送ります。

EM_AUTOURLDETECT wParam = (WPARAM) bEnable; // TRUE , FALSE lParam = 0 ; //使いません

また、URL検出部分にマウスが来たり、マウスがクリックされた ことを親に通知させるには、イベントマスクにENM_LINKを加えます。

例によって親のプロシージャでWM_NOTIFYメッセージを処理します。

EN_LINK idEditCtrl = (int) LOWORD(wParam); //エディットコントロールのID pEnlink = (ENLINK *) lParam; // ENLINK 構造体へのポインタ

ENLINK構造体は次のように定義されています。

typedef struct _enlink { NMHDR nmhdr; UINT msg; _WPAD _wPad1; WPARAM wParam; _WPAD _wPad2; LPARAM lParam; CHARRANGE chrg; } ENLINK;

32ビット版では_wPadXは無視して下さい。 これは、解説はあんまり必要ないですね。

あと,構造体としてCHARFORMAT2とか PARAFORMAT2とかが出てきますがこれも仕様が変更になる 可能性がありますので、ここでは解説しません。 今回のサンプルでは単純にCHARFORMATをCHARFORMAT2に、 PARAFORMATをPARAFORMAT2に書き換えただけです。 (新しい構造体ではメンバがかなり増えて細かな設定ができる ようになりました)

URLとかmailto:などをみつけるとその部分の色が変わり下線が 引かれます。また,この部分をマウスが通過するとカーソルが 指型(?)に変わります。また、この部分をクリックすると指定の URLを呼び出したり、メールを出したりすることができます。 Rich Edit2.0では1.0の時はは,かなりめんどうだったことが比較的簡単に実現 できます。


では、プログラムを見てみましょう。リソース・スクリプトに変更はありません。

// rich20.cpp #ifndef STRICT #define STRICT #endif ...省略... #define SZMYVERSION "猫でもわかるRTF#猫でもわかるRTF Ver0.20" ...省略... char szClassName[] = "rich20"; //ウィンドウクラス ...省略... DWORD dwMyMask; //CHARFORMAT2で使うマスク値 ...省略...

VC++6.0ではSTRICTは自動的に付加されるので#ifndefにしました。

WinMain, InitApp, InitInstance

の各関数に変更はありません。

//ウィンドウプロシージャ LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wp, LPARAM lp) { ...省略... ENLINK *penlk; char szURL[256]; ...省略... switch (msg) { case WM_CREATE: ...省略... hRtLib = LoadLibrary("RICHED20.DLL"); hEdit = CreateWindowEx(WS_EX_CLIENTEDGE, RICHEDIT_CLASS, "", WS_CHILD | WS_VISIBLE | WS_BORDER | ES_MULTILINE | WS_HSCROLL | WS_VSCROLL | ES_AUTOVSCROLL | ES_AUTOHSCROLL | ES_NOHIDESEL, 0, 0, 0, 0, //とりあえず幅、高さ0のウィンドウを作る hWnd, (HMENU)ID_RICH, hInst, NULL); //リッチエディットコントロールの最大文字数のセット SendMessage(hEdit, EM_EXLIMITTEXT, 0, (LPARAM)(1024*1024)); //親ウィンドウへデータ(hEdit)のアタッチ SetWindowLong(hWnd, GWL_USERDATA, (LONG)hEdit); DragAcceptFiles(hEdit, TRUE); //URL検出機能を組み込む SendMessage(hEdit, EM_AUTOURLDETECT, (WPARAM)TRUE, 0); ...省略... dwEvent |= ENM_MOUSEEVENTS | ENM_SELCHANGE | ENM_LINK; ...省略... case WM_NOTIFY: ...省略... if (wp == (WPARAM)ID_RICH) { lpN = (LPNMHDR)lp; switch (lpN->code ) { case EN_LINK: penlk = (ENLINK *)lp; if (penlk->msg == WM_LBUTTONDOWN) { SendMessage(hEdit, EM_EXSETSEL, 0, (LPARAM)(&(penlk->chrg))); SendMessage(hEdit, EM_GETSELTEXT, 0, (LPARAM)szURL); ShellExecute(hEdit, NULL, szURL, NULL, NULL, SW_SHOWNORMAL); } break; ...省略... }

たったこれだけの改造で本文中からURLとかメールアドレスを検出して クリックすることにより実行することができるようになります。

BOOL SetInitialFont(HWND hEdit)//最初のフォントの設定 { CHARFORMAT2 cfm; memset(&cfm, 0, sizeof(CHARFORMAT2)); cfm.cbSize = sizeof(CHARFORMAT2); cfm.dwMask = CFM_BOLD | CFM_CHARSET | CFM_COLOR | CFM_FACE | CFM_ITALIC | CFM_SIZE | CFM_STRIKEOUT | CFM_UNDERLINE; dwMyMask = cfm.dwMask;//以後dwMyMaskの値を使う cfm.bCharSet = DEFAULT_CHARSET; cfm.yHeight = 14*20; strcpy(cfm.szFaceName, "System"); if (SendMessage(hEdit, EM_SETCHARFORMAT, SCF_SELECTION, (LPARAM)&cfm) == 0) { MessageBox(hEdit, "EM_SETCHARFORMAT2失敗です", "Error", MB_OK); return FALSE; } return TRUE; }

初期状態のフォントをSystemにしました。この時フォントの高さも指定しておいて下さい。 そうしないとステータスバーに表示されるポイントが0になってしまいます。 この辺が1.0とはちょっと違うようです。

BOOL SetMyFont(HWND hEdit) { CHARFORMAT2 cfm; ...省略... cfm.cbSize = sizeof(CHARFORMAT2); ...省略... //フォント選択ダイアログを出して新しい設定を取得する if (ChooseFont(&cf)) { cfm.cbSize = sizeof(CHARFORMAT2); ...省略... }

単純にCHARFORMATをCHARFORMAT2に変えただけです。

BOOL SetCenter(HWND hEdit) { PARAFORMAT2 pf; memset(&pf, 0, sizeof(PARAFORMAT2)); pf.cbSize = sizeof(PARAFORMAT2); SendMessage(hEdit, EM_GETPARAFORMAT, 0, (LPARAM)&pf); pf.dwMask |= PFM_ALIGNMENT; pf.wAlignment = PFA_CENTER; SendMessage(hEdit, EM_SETPARAFORMAT, 0, (LPARAM)&pf); SetFocus(hEdit); return TRUE; }

これも構造体をPARAFORMAT2にしただけです。

BOOL SetLeft(HWND hEdit) { PARAFORMAT2 pf; memset(&pf, 0, sizeof(PARAFORMAT2)); pf.cbSize = sizeof(PARAFORMAT2); ...省略... } BOOL SetRight(HWND hEdit) { PARAFORMAT2 pf; memset(&pf, 0, sizeof(PARAFORMAT2)); pf.cbSize = sizeof(PARAFORMAT2); ...省略... }

これもPARAFORMAT2にしただけです。

ClearCheck, RTF_Save, RTF_SaveAs, MySaveProc, RTF_Open, MyReadProc

の各関数に変更はありません。

void RTF_CheckMenu(HWND hEdit, HMENU hMenu) { CHARRANGE cr; PARAFORMAT2 pf; ...省略... memset(&pf, 0, sizeof(PARAFORMAT2)); pf.cbSize = sizeof(PARAFORMAT2); ...省略... }

ここもPARAFORMAT2になっただけです。

RTF_Print, PrinterSet, GetPrintInfo, RTF_All, RTF_AddPageNo, RTF_SetWYSIWYG, RTF_New, RTF_Vertical, RTF_Horizontal, RTF_BackColor, MakeMyToolbar, InsertSep, MakeMyStatusbar

の各関数に変更はありません。

void SetStatusFontInfo(HWND hStatus, HWND hEdit) { CHARFORMAT2 cf; ...省略... memset(&cf, 0, sizeof(CHARFORMAT2)); cf.cbSize = sizeof(CHARFORMAT2); SendMessage(hEdit, EM_GETCHARFORMAT, (WPARAM)TRUE, (LPARAM)&cf); ...省略... }

ここも単純な置き換えです。

IsEditButtonAvailable, IsPasteButtonAvailable, SetStatusClock

の各関数に変更はありません。

// タブの設定 void RTF_SetTab(HWND hEdit, int unit) { PARAFORMAT2 pf; int i; memset(&pf, 0, sizeof(PARAFORMAT2)); pf.cbSize = sizeof(PARAFORMAT2); ...省略... } // 現在の段落の配置法(center, right, left)を調べてボタンに反映 void SetAlignmentButton(HWND hEdit, HWND hTool) { PARAFORMAT2 pf; memset(&pf, 0, sizeof(PARAFORMAT2)); pf.cbSize = sizeof(PARAFORMAT2); ...省略... }

ここも単純な置き換えです。

SetButtonHV, MyToolProc

の各関数に変更はありません。

void RTF_Num(HWND hEdit) { PARAFORMAT2 pf; memset(&pf, 0, sizeof(PARAFORMAT2)); pf.cbSize = sizeof(PARAFORMAT2); ...省略... }

置き換えです。

MakeMyRuler

この関数に変更はありません。

LRESULT CALLBACK MyStaticProc(HWND hStatic, UINT msg, WPARAM wp, LPARAM lp) { ...省略... PARAFORMAT2 pf; ...省略... Rectangle(hdc, 2, 6, w-2, 24); memset(&pf, 0, sizeof(PARAFORMAT2)); pf.cbSize = sizeof(PARAFORMAT2); SendMessage(hEdit, EM_GETPARAFORMAT,0, (LPARAM)&pf); if (pf.rgxTabs[0] > 0 && pf.cTabCount > 0) { ...省略... }

置きかえる場所は結構あちこちにあります。

MyEditProc, MyAboutProc, MyAboutStaticProc

の各関数に変更はありません。

さて、今回のプログラムで一番問題なのは縦書きが実現できない という点です。これは、どうしたらよいのでしょうか。


[SDK第2部 Index] [総合Index] [Previous Chapter] [Next Chapter]

Update 15/Oct/1998 By Y.Kumei
当ホーム・ページの一部または全部を無断で複写、複製、 転載あるいはコンピュータ等のファイルに保存することを禁じます。