레이블이 delphi인 게시물을 표시합니다. 모든 게시물 표시
레이블이 delphi인 게시물을 표시합니다. 모든 게시물 표시

2021년 2월 2일 화요일

JSON 사용해보기 (Parsing)

 JSON의 이론적인 배경이 없이 사용하는데 참고가 될만한 사항만 정리 해봅니다.

동행복권을 REST로 읽어 보면 아래와 같은 구조입니다.

{"totSellamnt":100519459000,"returnValue":"success","drwNoDate":"2021-01-30","firstWinamnt":2188548716,"drwtNo6":41,"drwtNo4":31,"firstPrzwnerCo":11,"drwtNo5":38,"bnusNo":5,"firstAccumamnt":24074035876,"drwNo":948,"drwtNo2":18,"drwtNo3":30,"drwtNo1":13}

{} TJSONObject 
[] TJSONArray

"...." : 10051.. TJSONElement(Array 형태에서)
"...." : 10051   TJSONPair(Element 와 햇갈리죠)

"...." TJSONString
10051 TJSONValue

동행복권의 API는 단순하여 TJSONArray 가 없는 형태이다.

TJSONstring : TJSONValue 가 TJSONPair 가되는데 TJSONValue 자리에 TJSONObject, TJSONArray 가 올 수 있다.

TJASONObject 는 TJSONValue 형태와 TJASONText 형태로 우리가 볼 수 있다.

위의 형태가 TJSONValue 형태이고, 아래 형태가 TJSONText 형태이다.

{
   "totSellamnt":100519459000,
   "returnValue":"success",
   ..............
}


DELPHI의 RESTResponce 에는 이 2가지형태를 전부 제공해줍니다.
Var
  iJsonObject: TJSONObject;
  iJsonValue: TJSONValue;
선언해주고
iJsonObject := TJSONObject(RESTResponse1.JSONValue); 이와 같이 하여 가져옵니다.
Edit1.Text:= iJsonObject.ToJSON; 하면 위와 같은 형식으로 볼 수 있고
Memo1.Lines.Add( iJsonObject.ToString); 하면 2번째 형태로 보여줍니다.

예를 들어 bnusNo 의 값을 읽어오려면
iJsonValue := iJsonObject.Get('bnusNo').JSONValue; 와 같이 하면 되는데
TJsonValue는 TJSONObject가 될 수도 있고, string, number, boolean 이 될 수도 있다.
TJSONObject, , JSONString, TJSONNumber, TJSONPair, TJSONBool, TJSONArray

이렇게 알고 있는 형태로 변환하면서 읽어오면 됩니다.

물론 각각은 .Size 가 있어서 for var idx:= 0 iJsonValue.size -1 형태로 여러개의 Pair를 읽어 올 수도 있습니다.

다음에 기회되면 조금 복잡한 형태의 JSON을 읽어 Parsing 해보겠습니다.

2013년 7월 16일 화요일

홈페이지에 있는 자바 스크립트 호출하기

본 예제는 2가지의 기술이 들어 있습니다.
웹에서의 버튼 조작을 델파이로 갖어와서 델파이에서 처리를 하는데 TWebBrowser 의
StatusTextchange 이벤트를 이용하는 것과
웹에 있는 Javascript function 을 실행하는 것입니다.

홈페이지에는 아래와 같은 스크립트가 들어 있습니다.
<head>
  <script language="javascript">
        function closewin(num){
            window.status='close';
            window.status='';
            window.close();
        }
  </script>
</head>
.......
<from>
   <input id="idtext" name="idtext" type="text" />
   <input 0="" id="idimage" name="idimahe" onclick="closewin()" src="images/images.jpg" style="cursor: hand;" type="image" />
   <input id="idsubmit" name="idsubmit" type="submit" />
</from>
폼에 WebBrowser 와 Editor, button 3개를 올려 놓고
procedure TForm4.Button1Click(Sender: TObject);
var iDoc: IHTMLDocument2;
    iWin: iHTMLwindow2;
    ifunc: string;
begin
  WebBrowser1.Document.QueryInterface(IHTMLDocument2, iDoc);
  WebBrowser1.Document.QueryInterface(IHTMLWindow2, iWin);
  ifunc:= 'closewin()';
  try
    iwin.execScript(ifunc, 'JavaScript');
  finally
  end;
end;

procedure TForm4.Button2Click(Sender: TObject);
begin
  WebBrowser1.Navigate(http://localhost/test.html');
end;

procedure TForm4.Button3Click(Sender: TObject);
var Obj,Doc : OleVariant;
begin
  Obj:= 0;
  // 필요하면 IDispatch(TTTestCode.Create); 방법으로 Dispatch인터페이스로 형변환한다...
  // HTML Script는 Dispatch인터페이스만 지원한다.
  // Script 인터페이스를 얻고...
  Doc:=IHTMLDocument2(WebBrowser1.Document).Script;
  // Script의 SetObject함수를 호출한다...(이함수는 HTML의 JavaScript함수이다)
  Doc.closewin(obj);
end;

procedure TForm4.WebBrowser1StatusTextChange(ASender: TObject; const Text: WideString);
var iStr: string;
begin
  iStr:= Text;
  if istr= 'close' then begin
    close;
  end;
end;
웹에서 이미지를 크릭하면 프로그램이 종료합니다.
프로그램에서 버튼3를 크릭하면 웹에 있는 스크립트를 실행하고, 즉 이미지를 크릭한 것과 같은 현상, 그 결과로서 프로그램을 종료 합니다.
다른 스크립트를 실행 시킬 수 있고, 다른 동작을 할수 있겠지요.
예를 들어 특정 버튼의 결과에 특정 디비에서 자료를 읽어와 Html을 만들고 그웹을 뿌려줄 수 있겠지요.

한영변환(펌)

public에 밑에 함수 추가
const   English = 0; Korean = 1;
uses InputUnit, ViewUnit, Imm;
{$R *.DFM}
//////////// 한/영상태 검사 루틴///////////////
function TMainForm.IsHanState(paForm: TForm): boolean;
var
   fFlag, imeMode: DWORD;
   hIMC: THandle;
begin
   hIMC:= ImmGetContext(paForm.Handle);
   ImmGetConversionStatus(hIMC, fFlag, imeMode);
   ImmReleaseContext(paForm.Handle, hIMC);
   Result:= (fFlag = 1);
end;
//////////// 한/영상태 변화 루틴///////////////
procedure TMainForm.SetIMEMode(const Language: Integer);
var
   dwConversion, dwSentence: DWORD;
   hIMC: THandle;
begin
   hIMC:= ImmGetContext(Application.Handle);
   ImmGetConversionStatus(hIMC, dwConversion, dwSentence);
   Case Language Of
      English: ImmSetConversionStatus(hIMC, IME_CMODE_ALPHANUMERIC, dwSentence);
      Korean : ImmSetConversionStatus(hIMC, IME_CMODE_NATIVE, dwSentence);
   end; {Case Value Of}
   ImmReleaseContext(Application.Handle, hIMC);
end;

procedure TMainForm.AppMessage(var Msg: TMsg; var Handled: Boolean);
begin
   If IsHanState(Self) Then StatusBar1.Panels[1].Text:= ' 한글 '
   Else StatusBar1.Panels[1].Text:= ' 영문 ';
end;
procedure TMainForm.FormCreate(Sender: TObject);
begin
   InputFormActive:= False;
   ViewFormActive:= False;
   InputClose:= True;
   Application.OnHint:= ShowHint;
   Application.OnMessage:= AppMessage;
   SetIMEMode(Korean);
   Left:= 1;
   Top:= 1;
end;
* 자료출처 : http://blog.daum.net/ryang000/118

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함수를 이용해서도 호출을 할수 있습니다...
단지 이방법은 문자열로 함수를 호출하기 때문에 인수의 타입에 제한이 있죠.,..

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

2012년 11월 23일 금요일

델파이 레코드에서 함수 사용가능하기에 2

델파이 레코드에서 함수 사용가능하기에 1 에서 C++로 구현 한것을 델파이로 구현해 보았습니다. 이제 까진 Unit를 클래스에서나 사용해 왔는데.. 조금 나아가 생각하면 자신만의 라이브러리를 record로 구현 해 놓고 불러서 사용하면 좋을 것 같습니다.
unit Unit1;
interface
type
  변동금리형식 = record
    신용등급: integer;
    function 결정할증(): real;
  end;
type
  은행형식 = record
    원금, 이율, 기간: real;
    변동금리: 변동금리형식;
    function 원리합계: real;
  end;
implementation
{ 변동금리형식 }
function 변동금리형식.결정할증: real;
var 임시할증: real;
begin
  임시할증 := 1.0;
  case 신용등급 of
    1: 임시할증 := 1.1;
    2: 임시할증 := 1.2;
  else writeln('신용등급 입력 에러');
  end;
  Result := 임시할증;
end;
{ 은행형식 }
function 은행형식.원리합계: real;
begin
  Result := 원금 * 이율 * 기간 * 변동금리.결정할증;
end;
end.
program Project1;
{$APPTYPE CONSOLE}
uses
  System.SysUtils,
  Unit1 in 'Unit1.pas';  // 이게 C++에서 Namespace ?
var 은행: 은행형식;
begin
  with 은행 do begin  // 이게 C++ 에서 Using
    원금:= 10000.0;
    이율:= 0.035;
    기간:= 3; //년
    Write('신용등급?(1,2 으로 구분하여 입력) ');
    Readln (변동금리.신용등급);
    Writeln ('당신의 원리합계는 = ', 원리합계():10:3);
    Readln;
  end;
end.

델파이 레코드에서 함수 사용가능하기에 1

C++을 공부하면서 느낀 것인데 델파이에서 레코드에 함수를 사용 할 수 있게 함으로 인하여 C++의 네임스페이스를 거의 완벽하게 구현이 가능하다는 것을 느꼈습니다.
아래 예를 보면
Unit1.cpp

#include 
#include 
namespace 은행 {
 double 원금, 이율, 기간;
 double 원리합계();
 namespace 변동금리 {
  int 신용등급;
  double 결정할증();
 }
}
double 은행::원리합계() {
   return 원금 * 이율 * 기간 * 변동금리::결정할증();
}
double 은행::변동금리::결정할증() {
   double 임시할증;
   임시할증 = 1.0;
   switch (신용등급) {
  case 1 :
    임시할증 = 이율 * 1.1;
    break;
  case 2 :
    임시할증 = 이율 * 1.2;
    break;
   default:
  cout << "신용긍급 입력 에러!";
   }
   return 임시할증;
}
File1.cpp
#include 
#include 
#pragma hdrstop
#pragma argsused
#include "Unit1.cpp"
int main(int argc, char* argv[]) {
 using namespace 은행;
 원금 = 10000.0;
 이율 = 0.035;
 기간 = 3; // 년
 cout << "시용등급?(1,2 으로 구분하여 입력): ";
 cin >> 변동금리::신용등급;
 cout << "\n당신의 원리합계는 = " << 은행::원리합계() << "\n\n";
 return 0;
}

2012년 11월 6일 화요일

델파이 환경 설정

1. Build All 할때 외부 추가 컴포넌트가 컴파일 되어 생성 되는 것을 못하게 하려면 Project 탭에서 Build Configarations 팝업 메뉴에서 [Delphi Compiler > Targer:= All configurations - All platform] Unit Output directory 의 .\$(Platform)\$(Config) 를 지워 주면 됩니다.






2020년 수정





2012년 11월 2일 금요일

퀀텀그리드 01

TMS 그리드를 사용하다가 퀀텀그리드를 접하게 되어 퀀텀 그리드를 익히고 있습니다.
이곳에서는 일반 그리드에 대한 개념을 갖고 계신 분이 퀀텀 그리드에 접근하는데,
도움이 될 수 있는 것을 메모 할려고 합니다.
컨텀 그리드 좋은 강좌는 :김성원블로그 이 잘되어 있습니다.
1. 델파이적인 기본 접근
 - [File > New > VCL Forms Application] 하면 기본 품이 만들어 집니다.
 - TClientDataSet,  TDataSource,  TDBNavigator 그리고 TCXGRid 를 올려 놓고 그림과 같이 배치합니다.
계속하여
- ClientDataSet1
  FileName := C:\Users\Public\Documents\RAD Studio 9.0 Samples\Data\animals.xml
- Active:= True;
- DataSource1. DataSet:= ClientDataSet1
- DBNavigator1.DataSet:= ClientDataSet1

한다음 cxGrid1 바탕에서 마우스 오른쪽 버튼을 크릭하여 나타나는 팝업메뉴에서
LIne To DataSource1을 선택합니다.
또는, cxGrid 공간에서 더블크릭하여 나오는 제어 화면에서
cxGrid1DBTableView1.DataController.DataSource:= DataSource
cxGrid PopUp Menu 에서
Create All Columns (적색 표시 버튼)를 선택합니다.

제어 화면에서
cxGrid1DBTableView1BMP 를 선택하고
Properties:= Image
에서 (즉, cxGrid1DBTableView1BMP.roperties:= Image) 을 선택합니다.

소스를 보면
cxGrid1DBTableView1NAME: TcxGridDBColumn;
    cxGrid1DBTableView1SIZE: TcxGridDBColumn;
cxGrid1DBTableView1WEIGHT: TcxGridDBColumn;
    cxGrid1DBTableView1AREA: TcxGridDBColumn;
    cxGrid1DBTableView1BMP: TcxGridDBColumn;
부분이 추가 되었씀을 참고 하십시요.
또한, 일반 그리드와는 달리 cxGrid의 그리드(테이블)의 셀 형식은 Varient 형식입니다.

델파이의 부활(Antigravity와의 만남)?

 델파이 프로그램을 사용하여 개인적으로 필요한 프로그램을 생성해 왔는데, 얼마전부터 파이썬으로 옮겨갔다.  그런데 Google 의 Antigravity를 만나고 나서 델파이에 대한 미련을 버리지 못해  제미나이가 Delphi이에 대한 학습도 엄청 했을...