思いつきなのですが、
・InternetExplolerでローカルのhtmlファイルを表示し、
・そのhtml上のリンクとかボタンをクリックして、
・Delphiでクリックイベントにうまくリンクさせて動作させる
つまり、Formの設計をIEで代替するような事はできないでしょうか?
※そんなん簡単やろ!などと言わず道筋をお教え願えませんでしょうか。
よろしくお願いします。
何をやらせたいのかによって、CGIなのか、ActiveXコントロールなのか、別の手段が必要(たとえばプロトコルの実装)なのかが違います。
いずれにしても、HTMLブラウザのクリックなどでDelphiプログラムが(クライアント上で)動く、としたら、セキュリティに関しても考慮すべきです。
>Delphiでクリックイベントにうまくリンクさせて動作させる
こういうことでしょうか?↓
{
参考:
TEventDelegator
http://www.effie.co.il/default.asp?sec=printview&topic=delphiasp&lang=he
Bubble Power: Internet Explorer 4.0 におけるイベント処理
http://www.microsoft.com/japan/msdn/web/ie/ie40/ie4event.asp
Handling Events in Visual Basic Applications
http://msdn.microsoft.com/workshop/browser/webbrowser/tutorials/forward.asp
TieAutomationコンポーネント
http://www33.ocn.ne.jp/~takoyakusi/delphi/InternetProg.html
}
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, ieAutomation, SHDocVw_TLB, MSHTML_TLB;
//-----------------------------------------------------------------------------
type
TCallbackMethod = procedure of object;
TEventDelegator = class(TInterfacedObject, IDispatch)
private
FOwner : TObject;
FCallback: TCallbackMethod;
protected
{ IDispatch }
function GetTypeInfoCount(out Count: Integer): HRESULT; stdcall;
function GetTypeInfo(Index, LocaleID: Integer; out TypeInfo): HRESULT; stdcall;
function GetIDsOfNames(const IID: TGUID; Names: Pointer; NameCount, LocaleID: Integer; DispIDs: Pointer): HRESULT; stdcall;
function Invoke(DispID: Integer; const IID: TGUID; LocaleID: Integer;
Flags: Word; var Params; VarResult, ExcepInfo,
ArgErr: Pointer): HRESULT; stdcall;
public
constructor Create(AOwner:TObject; Callback :TCallbackMethod);
end;
//-----------------------------------------------------------------------------
type
TForm1 = class(TForm)
ieAuto: TieAutomation;
Button1: TButton;
procedure Button1Click(Sender: TObject);
procedure ieAutoDocumentComplete(Sender: TObject; const pDisp: IDispatch; var URL: OleVariant);
procedure FormCreate(Sender: TObject);
procedure FormDestroy(Sender: TObject);
procedure ieAutoQuit(Sender: TObject);
private
{ Private 宣言 }
procedure IE_AttachEvevt;
procedure Some_Procedure1;
procedure Some_Procedure2;
procedure Some_Procedure3;
public
{ Public 宣言 }
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
//-----------------------------------------------------------------------------
constructor TEventDelegator.Create(AOwner:TObject; Callback:TCallbackMethod);
begin
inherited Create;
FOwner := AOwner;
FCallback := Callback;
end;
function TEventDelegator.GetTypeInfoCount(out Count: Integer): HRESULT;
begin
// Skeleton implementation
Count := 0;
Result := S_OK;
end;
function TEventDelegator.GetTypeInfo(Index, LocaleID: Integer; out TypeInfo): HRESULT;
begin
// Skeleton implementation
Result := E_NOTIMPL;
end;
function TEventDelegator.GetIDsOfNames(const IID: TGUID; Names: Pointer;
NameCount, LocaleID: Integer; DispIDs: Pointer): HRESULT;
begin
// Skeleton implementation
Result := E_NOTIMPL;
end;
function TEventDelegator.Invoke(DispID: Integer; const IID: TGUID; LocaleID: Integer;
Flags: Word; var Params; VarResult, ExcepInfo, ArgErr: Pointer): HRESULT;
begin
try
FCallback;
except
end;
Result := S_OK;
end;
//-----------------------------------------------------------------------------
procedure TForm1.Some_Procedure1;
var
oDoc2: IHTMLDocument2;
oWindow: IHTMLWindow2;
oEle: IHTMLElement;
begin
Windows.Beep(3000, 100);
Button1.Caption := 'Some_Procedure1 was called.';
oDoc2 := ieAuto.ieObject.Document as IHTMLDocument2;
oWindow := oDoc2.parentWindow;
oEle := oWindow.event.srcElement;
oEle.innerText := 'Some_Procedure1 was called.';
end;
procedure TForm1.Some_Procedure2;
var
oDoc: IHTMLDocument2;
oWindow: IHTMLWindow2;
oEle: IHTMLElement;
begin
oDoc := ieAuto.ieObject.Document as IHTMLDocument2;
oWindow := oDoc.parentWindow;
oEle := oWindow.event.srcElement;
oEle.style.backgroundColor := 'Gray';
end;
procedure TForm1.Some_Procedure3;
var
oDoc: IHTMLDocument2;
oWindow: IHTMLWindow2;
oEle: IHTMLElement;
begin
oDoc := ieAuto.ieObject.Document as IHTMLDocument2;
oWindow := oDoc.parentWindow;
oEle := oWindow.event.srcElement;
oEle.style.backgroundColor := '';
end;
//-----------------------------------------------------------------------------
// ブラウザオープン
procedure TForm1.Button1Click(Sender: TObject);
begin
ieAuto.IeOpen;
end;
procedure TForm1.ieAutoDocumentComplete(Sender: TObject;
const pDisp: IDispatch; var URL: OleVariant);
var
oDoc: IHTMLDocument2;
sHTML: WideString;
begin
// 適当なHTML
// ID,Name などで識別できるようにしておく
sHTML := '<P>This is some text.</P>';
sHTML := sHTML + '<P>And here is a button.</P>';
sHTML := sHTML + '<BUTTON ID="btnMyButton">Click this Button.</BUTTON>';
oDoc := ieAuto.ieObject.Document as IHTMLDocument2;
oDoc.body.innerHTML := sHTML;
IE_AttachEvevt;
end;
// イベント実装
procedure TForm1.IE_AttachEvevt;
var
oDoc: IHTMLDocument3;
oEle: IHTMLElement2;
oEvent: IDispatch;
begin
if not Assigned(ieAuto.ieObject) then Exit;
oDoc := ieAuto.ieObject.Document as IHTMLDocument3;
// ID で識別
oEle := oDoc.getElementById('btnMyButton') as IHTMLElement2;
oEvent := TEventDelegator.Create(Form1, Some_Procedure1);
oEle.attachEvent('onclick', oEvent);
// Document すべてに(イベント バブリング)
oEvent := TEventDelegator.Create(Form1, Some_Procedure2);
oDoc.attachEvent('onmouseover', oEvent);
oEvent := TEventDelegator.Create(Form1, Some_Procedure3);
oDoc.attachEvent('onmouseout', oEvent);
{onclick, ondblclick,
onmousedown, onmouseup,
onmouseover, onmouseout,
onmousemove,
onkeydown, onkeyup,
onkeypress
...などなど}
end;
procedure TForm1.FormCreate(Sender: TObject);
begin
// フォームを表示しない
Application.ShowMainForm := False;
Button1Click(Sender);
end;
// ブラウザとフォームの終了を連動
procedure TForm1.FormDestroy(Sender: TObject);
begin
ieAuto.IeClose;
end;
procedure TForm1.ieAutoQuit(Sender: TObject);
begin
Application.Terminate;
end;
end.
早速の返答ありがとうございます。にしのさん、もちKiri さん
目的はFormの設計の簡略化です。CGIなどは私の手には余ると思います。
ところで、上記のサンプルコードを試そうとTieAutomationコンポーネントをインストールしようと四苦八苦しています。
(Microsoft Internet ControlsとMicrosoft HTML Object Libraryは取り込みました)
コンパイルの時点でunassignedが未定義の識別子 と言って怒られます。
何が悪いのでしょうか・・・すみませんがもう少し教えてください。よろしくお願いします。
uses節にVariantsを追加したらインストールできました。
Helpは見るものです・・・・
それではこれから試したいと思います。
惨敗です。
ieAuto.IeOpen でIEが立ち上がりません。
というか立ち上がると思っているのが間違いなのでしょうか・・
私のやりたい事にすごく近い気がするのですが・・・・
> 目的はFormの設計の簡略化です。
Delphi より簡単に Form を設計するって、あり得ないと思うんですが。
簡単そうに見えるのは、Delphi.NETでWeb.NETを使うというものでしょうか?(実はすごく。。。。。。)
>Delphi より簡単に Form を設計するって、あり得ないと思うんですが。
「用意されたコンポーネントを配置してそれなりのものを作る」場合には、簡便さはDelphiの統合開発環境が勝ります。
しかし、見栄えのよいウインドウを作る という命題の前にはどうでしょうか?
勿論Delphi は総合プログラミング環境ですから、凡そ欲することのほとんどの事が可能(なはず)ですが、用意されたコンポーネント以上のことをしようとすると、極端に難易度があがりませんか?(え?そうでもない?)
今現在、HTMLは参考ソースが最も多く、しかも「見栄え」に拘ったものが何百万も存在しますし、保守性もよいです。
それを流用できないかなぁと思っているのですが。
(いまだにTieAutomation使えていません。エラソーなことを語るには素人です。すみません)
スレ汚しすみません。
上記サンプル、やっと動かせました!!!
ieAutoDocumentCompleteイベントをアタッチできておりませんでした。
あと、visibleプロパティもtrueにしないといけません。
ありがとうございます。いろいろ試行してみます。
HTMLは見栄えはよいですが、UIとして考えるとやはり足りない部分がでてきます。
HTMLの中で使えるコンポーネントと、Delphiのコンポーネントを比べても、Delphiのほうが豊富で、カスタマイズも出来ます。
Webシステムなどを作ってみると、いかにHTMLで出来ることが少ないか(実現することが難しいか)がわかるかと思います。
例えば、
Web)ウィンドウの形を変えられない
Delphi)リージョンを使用してウィンドウの形を任意に変えられる
Web)フローティングレイヤーの下にSELECTタグがあるとSELECTタグのほうが上に表示されてしまう。また、フローティングレイヤーはウィンドウの外に出られない。
Delphi)フローティングウィンドウは、全てのコンポーネントの上に表示できるし、ウィンドウの外に出ることもできる。
リージョンを使用する場面は少ないと思いますが、入力系でコンボボックスがあり、その上にレイヤーを表示することなどは多々あるかと思います。
# 例えば、
発送希望日[INPUT TYPE="text"][Button]<-ボタンを押してカレンダー(レイヤー)表示
宛先:都道府県[北海道▼]<-ここはコンボボックス
宛先:住所[INPUT TYPE="text]
こんな感じの入力系で、カレンダーを表示するとレイヤーの上に[北海道▼]が重なって表示されます。
ツイート | ![]() |