2013년 7월 12일 금요일

ActiveX폼에서 JavaScript의 함수 호출

델마당의 강용희님 글 델마당에는 소스가 첨부되어 있습니다.
우선...
ActiveX폼이라는 놈을 이용해 프로그램을 만들면 꼭 한번씩 JavaScript의 함수를 호출할때가 필요합니다. 여기저기 알아봐도 답이 없고 해서 직접 분석해서 알아 냈습니다... 원리는 간단한데... 예상외로 알고 있는 사람이 없더군요... 제가 원래 말솜씨가 없서서 강좌가 좀 부실할검니다... ^^;; 넓은 아량으로 봐주세요!!

우선 JavaScript에서 지원하는 Object는 Automation Object입니다... 이 Object는 COM이기는 COM인데, 이름으로 호출 하는것을 지원하는 놈이죠... 델파이의 경우는 C나 C++처럼 포인터를 이용해서 함수를 호출하는 방식하고 JavaScript나 VB에서 지원하는 이름으로 함수를 호출하는 방식 모두를 지원합니다... 
COM Object만드는 방식은 여기 강좌에 보시면 많이 있으므로 생략하고...
Automation Object는 델파이의 File->New->Other->ActiveX->Automation Object를 선택하면 만들수 있습니다. 만일 ActiveX Form에서 사용한다고 하면 ActiveX Form자체가 Automation Object이므로 따로 Object를 만들 필요가 없고, ActiveX Form에서 Typelib 편집기에서 함수를 만들면 JavaScript에서 바로 함수를 호출할수가 있습니다.^^;;
아래는 Automation Object의 예입니다... 

unit Unit2;
{$WARN SYMBOL_PLATFORM OFF}
interface
uses
   ComObj, ActiveX, Project1_TLB, StdVcl, Dialogs;
type // Automation(Dispatch)오브젝트...
  // HTML(JavaScript)에서 호출을 할려면 VB처럼 Dispatch방식을 지원해야 된다...
TTTestCode = class(TAutoObject, ITTestCode)
protected
procedure TestCall(const Param1: WideString); safecall;
end;
implementation
uses ComServ;
procedure TTTestCode.TestCall(const Param1: WideString);
begin // ShowMessage로 전달받은 문자열을 출력한다...
  ShowMessage('난 델파이의 객체야!!'+#13+Param1);
end;
initialization
TAutoObjectFactory.Create(ComServer, TTTestCode, Class_TTestCode,
ciMultiInstance, tmApartment);
end.

멤버함수로 TestCall이라는 함수가 있는데... 이함수는 전달받은 인수를 델파이의 ShowMessage를 이용해서 출력합니다.
그러면 TestCall은 누가 호출을 하느냐 하면...
아래의 HTML에서 "요기를 눌러보세요"를 누르면 호출을 합니다.. ^^;; 

요기를 눌러보세요... 

그럼 위의 두문장으로 실행이 될까요. 당연히 않되겠죠. object는 선언만 되었지... 실제로 객체가 할당이 되지 않았으니까요. 그럼 Object를 할당하는 JavaScript함수를 만들었습니다...
함수는 SetObject이구요...
이제 이함수를 메인 폼에서 호출해주면 되겠죠!!
그럼 이제 메인 소스를 볼까요!!

unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,Dialogs, ComObj, StdCtrls, OleCtrls, SHDocVw, MSHTML;
type
TForm1 = class(TForm)
WebBrowser1: TWebBrowser;
Button1: TButton;
Button2: TButton;
Button3: TButton;
Button4: TButton;
procedure Button1Click(Sender: TObject);
procedure Button2Click(Sender: TObject);
procedure Button3Click(Sender: TObject);
procedure Button4Click(Sender: TObject);
end;
var
Form1: TForm1;
implementation
uses Unit2;
{$R *.dfm}
procedure TForm1.Button1Click(Sender: TObject);
begin // HTML을 읽어 들인다...
  WebBrowser1.Navigate(ExtractFilePath(Application.ExeName)+'test.htm');
end;
procedure TForm1.Button2Click(Sender: TObject);
var
  Obj,Doc : OleVariant;
begin
  Obj:=IDispatch(TTTestCode.Create); // Dispatch인터페이스로 형변환한다...
  // HTML Script는 Dispatch인터페이스만 지원한다.
  Doc:=IHTMLDocument2(WebBrowser1.Document).Script; // Script 인터페이스를 얻고...
  Doc.SetObject(Obj); // Script의 SetObject함수를 호출한다...(이함수는 HTML의 JavaScript함수이다)
end;

procedure TForm1.Button3Click(Sender: TObject);
var
  Obj,Doc : OleVariant;
begin
  Obj:=Unassigned;
  Doc:=IHTMLDocument2(WebBrowser1.Document).Script;
  Doc.SetObject(obj); // HTML의 Object를 Null로 초기화 한다...
end;

procedure TForm1.Button4Click(Sender: TObject);
var Win : IHTMLWindow2;
begin // 아래는 다른 방법으로 스크립트를 호출한다...
  // 이방법의 단점은... 오직 문자열로만 표현되는 인수만 전달할수 있다.
  // 즉 문자나 숫자는 전달할수 있지만,
  // Object등은 전달할수가 없다...
  Win:=IHTMLWindow2(IHTMLDocument2(WebBrowser1.Document).frames); // HTML의 Window객체를 얻는다...
  Win.execScript('SimpleCall("다른 방법으로 스크립트 호출")','');
end;
end.

위의 소스를 보면 Button2를 누르면 Automation Object를 만들어서 HTML SetObject를 호출해 객체를 설정하는것을 알수 있습니다... ^^;;
이렇게 객체를 설정한후에 링크를 누르면 제대로 동작하느것을 볼수 있을것입니다.
원리는 간단하죠!!
근데 아무리 강좌를 뒤비봐도 없더라구요...

휴... 
위에서 보듯이 HTML의 JavaScript함수를 호출하는 방법은 2가지가 있는데...
첫번째는 Script라는 Dispatch인터페이스를 이용해서 호출하는 방법입니다...
이방법이 가장 좋은 방법이구요...

아니면 IHTMLWindow2의 execScript함수를 이용해서도 호출을 할수 있습니다...
단지 이방법은 문자열로 함수를 호출하기 때문에 인수의 타입에 제한이 있죠.,..

그럼 수고하시구요...
즐프하세요;;

tensorflow gpu 사용하기에서

 tensorflow 설치시 주의해야 한다. # Anything above 2.10 is not supported on the GPU on Windows Native python - m pip install "tensorflow<2.11...