[BlueLeaf1336]> PROBLEMS> リンクタグ作成 HrefBuilder>
| history | TOP |
2005/05/22:作成
| 2005/05/22 | TOP |
しょうもないツールを作るときでも、たいていインターネットで調べ物をします。このときに参考にさせてもらったURLを、次に使うことが全くないとも言い切れないので、可能な限り参考URLリストとして(勝手に)リンクしています。
ただ、コレが邪魔臭いわけです。本当に次回に役立てようと思うなら、URLとタイトルとそのページの概要と参考にした内容と、そのページのメインのページの概要をまとめておくべきであって、実際にはもっともっと邪魔くさいはずですが、とりあえずURLとタイトルだけでも...と考えただけでも邪魔臭い。
参考にしたページのリストをどうやって作るかにもよるとは思いますが、たいていの場合、Googleで検索して記述されているコードをコピーしてきて動くかどうかだけ確かめて、採用することにした場合は、そのページのURLだけコメントとしてソースコードに貼り付けています。で、恐れ多くもそのソースコードやプログラムを説明しようじゃないかと思い立った場合は、そのURLをもとにして、参考URLリストを作ることになります。その時点で死んじゃってるページなんてのもありますが...。
さて、そうすると、URLだけが入力として使える状態でそのページのタイトルを抜き出すことになります。で、これが邪魔臭い。というのも、WebブラウザにURLを入力してそのページのタイトルを抜き出そうとした場合、たいていはそのページのソースをエディタで開いて、TITLEタグを探してタイトルを得るという流れになるためです。
前置きが長くなりましたが、URLのリストを貼り付けて、それに対応するHTML用のリンクタグを生成するツールを以前に作ったことがあります。
これがかなり使いにくいんですが、多分自分で作ったプログラムの中で一番使用しているような気がします。でも、使いにくい。使いにくい原因は、URLのリストを貼り付けるために、まずそのURLのリストをエディタの新規ページか何かで作る必要がある点だと思います。もちろんそれからもいろいろと問題はあるんですが。
なので、今回、この腐った使い勝手を少しでもコマシにしようと思います。基本方針としては、クリップボードを監視して、URLっぽい文字列が貼り付けられたらバックグラウンドでタイトル文字列を取得して、どんどん貼り付けられたらどんどん取得して、最終的にこのプログラムをアクティブにした時点でネタは取得済み、あとはどうやって使うかだけ、な感じにしたいなぁと。
手始めに次の2点を実現してみます。
| クリップボードを監視すること | TOP |
実はやったことあります。TClipWatcherというクラスにしてあります。使い方はこんな感じです。
//-----------------------------------------------------------------------------
// クリップボード読み取り
procedure TMainForm.GetClip();
begin
// テキストフォーマットなら
if Clipboard.HasFormat(CF_TEXT) then
begin
Form1.ListBox1.Items.Add(Clipboard.AsText);
end;
end;
//-----------------------------------------------------------------------------
// フォーム生成時
procedure TMainForm.FormCreate(Sender: TObject);
begin
// コピー検出クラス
ClipWatcher := TClipWatcher.Create(GetClip);
end;
//-----------------------------------------------------------------------------
// フォーム破棄時
procedure TMainForm.FormDestroy(Sender: TObject);
begin
// コピー検出クラス
ClipWatcher.Free;
end;
| クリップボードを監視すること(本体) | TOP |
//=============================================================================
// クリップボード監視クラス
//-----------------------------------------------------------------------------
// http://www2.big.or.jp/~osamu/Delphi/tips.cgi?index=0210.txt
// http://www2.big.or.jp/~osamu/Delphi/tips.cgi?index=0209.txt
//-----------------------------------------------------------------------------
unit iClip;
interface
uses
Windows, Messages, SysUtils, Classes, ClipBrd;
type
// 変更通知関数
TClipUpdatedNotify = procedure() of object;
// TClipUpdatedNotify = procedure();
// 変更監視クラス
TClipWatcher = class
private
IsFirst : Boolean;
WndHandle : THandle;
HClipNext : HWND;
ClipProc : TClipUpdatedNotify;
procedure ClipboardSetHandle;
procedure ClipboardReleaseHandle;
procedure WndProc(var Msg: TMessage);
public
constructor Create(Proc: TClipUpdatedNotify);
destructor Destroy(); override;
end;
implementation
//-----------------------------------------------------------------------------
// TClipWatcher
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
// コンストラクタ
constructor TClipWatcher.Create(Proc: TClipUpdatedNotify);
begin
inherited Create;
// 初期化未完了
IsFirst := True;
// ウィンドウコントロールのふりをする
WndHandle := AllocateHWnd(WndProc);
// 次のクリップボードビューアのハンドル初期化
HClipNext := INVALID_HANDLE_VALUE;
// 通知関数受け取り
ClipProc := Proc;
// クリップボードビューアとして登録
ClipboardSetHandle;
// 初期化完了
IsFirst := False;
end;
//-----------------------------------------------------------------------------
// デストラクタ
destructor TClipWatcher.Destroy();
begin
// クリップボードビューアとして離脱
ClipboardReleaseHandle;
// ウィンドウのふり中止
DeallocateHWnd(WndHandle);
inherited Destroy;
end;
//-----------------------------------------------------------------------------
// クリップボード監視のための初期化
procedure TClipWatcher.ClipboardSetHandle;
begin
// まだこのこの処理をやってないなら
if HClipNext = INVALID_HANDLE_VALUE then
begin
// クリップボードビューアとして登録してみる
HClipNext := SetClipboardViewer(WndHandle);
// だめなら
if HClipNext = INVALID_HANDLE_VALUE then
// 例外
if GetLastError <> 0 then
raise Exception.Create(SysErrorMessage(GetLastError));
end;
end;
//-----------------------------------------------------------------------------
// クリップボード監視の破棄
procedure TClipWatcher.ClipboardReleaseHandle;
begin
// クリップボードビューアとして登録できているなら
if HClipNext <> INVALID_HANDLE_VALUE then
begin
// 次の奴に「いち抜け」を教えて
ChangeClipboardChain(WndHandle, HClipNext);
// 次の奴のハンドル忘却
HClipNext := INVALID_HANDLE_VALUE;
end;
end;
//-----------------------------------------------------------------------------
// メッセージ受け取り
procedure TClipWatcher.WndProc(var Msg: TMessage);
var
WmDrawClip: TWMDrawClipboard;
WmChangeCB: TWMChangeCBChain;
begin
case Msg.Msg of
// クリップボード更新フック
WM_DRAWCLIPBOARD:
begin
// 構造体のメンバがよくわからないので、キャストしてみる
WmDrawClip := TWMDrawClipboard(Msg);
//通知
if not IsFirst then ClipProc();
//次の人にも教えてやる
if HClipNext <> INVALID_HANDLE_VALUE then
begin
SendMessage(HClipNext, WM_DRAWCLIPBOARD, 0, 0);
end;
end;
// 次にまわす
WM_CHANGECBCHAIN:
begin
// 構造体のメンバがよくわからないので、キャストしてみる
WmChangeCB := TWMChangeCBChain(Msg);
if WmChangeCB.Remove = HClipNext then
begin
HClipNext := WmChangeCB.Next;
end;
if HClipNext <> INVALID_HANDLE_VALUE then
begin
SendMessage(HClipNext, WM_CHANGECBCHAIN, WmChangeCB.Remove, WmChangeCB.Next);
end;
end;
// それ以外のすべて
else
begin
Msg.Result := DefWindowProc(WndHandle, Msg.Msg, Msg.wParam, Msg.lParam);
end;
end;
end;
end.
| 文字列がURLかどうかを判定すること | TOP |
さて、こっちはやったことありません。先のクリップボードの監視の時に、単純にクリップボードの内容がテキスト形式なら処理する、としていましたが、この箇所を、クリップボードの内容がテキスト形式なら「URLっぽいなら」処理する、ように修正したいということです。
s?https?://[-_.!~*'()a-zA-Z0-9;/?:@&=+$,%#]+
そういうことらしいです。つまり、正規表現が使えれば簡単に判断できそうな感じです。また、以前にDelphiで正規表現をするための方法を探したときに、Delphiでマイクロソフト製の正規表現ActiveXコンポを使うというページを見つけました。が!! すでに閉鎖されていました。すごくわかりやすかったんですが...。Internet Archive: Wayback Machineを使っても辿れませんでした。
うーん。どうしよう。前回参考にして書いたソースコードがあるので、それから思い出しながらやればよいのかもしれませんが、ここは別の方法を考えることにします。
別の方法と書いたばかりですが、Delphiで正規表現を使うための別の方法ということです。つまり「文字列がURLかどうかを判定すること」という問題は「Delphiで正規表現を簡単に使うには」という問題に、それとなくずらしてしまうことにします。
| Delphiで正規表現を簡単に使うには | TOP |
日本語で書かれたページだけを対象に検索してみました。リンクに続く説明文は、リンク先のページからだいたいで抜き出したものです。この抜き出しも自動でやってくれるようなのがあればすばらしいんですが、そのぐらいは脳みそ使わないと腐ってしまいそうなので我慢します、じゃなくてそんなのは作れません。
先に見つけた、URIを一撃で表す正規表現がPerl用ですので、Perl互換がよいのではないか、でもDLLかぁというところで、bmonkey's Delphi pageの関数を使用させてもらうことにしようかと思ってダウンロードしてみると、難しそうです。
そうなると、やっぱりBlueLeaf1336-PROBLEMS-2004_0048 > MizuhoGetter > HTMLソースの解析(3)で書いたソースコードを参考にして、ActiveX使ってやることにしようかなぁ。でも使い方がなあ。
ここまで考えてきて、そういえば、今回は「URLかどうか」だけを調べるだけだということを思い出しました。前後にゴミデータがくっついてしまっている場合を考えると、正確には「文字列の中にURLっぽいものが含まれているかどうか」を調べるということになります。大丈夫かも。よって、ActiveXを使うことにします。あぁでも、普通にActiveXの取り込みを実行して作ったTLBファイルでは問題があるとかで、当時は閉鎖されていなかったページからダウンロードできたTLBファイルを使わないと駄目で、それ以前にどのActiveXなのかも特定できなくて、やっぱり、うーん。
| EOF | TOP |