function TfmBackUp.FindFile(FolderName: String): Integer;
var
 RowIndex : Integer;
 SR : TSearchRec;
begin
 if (findFirst(FolderName+'\*.*',faAnyFile,Sr)) = 0 then
   repeat
     if (Sr.Name <> '.') and (Sr.Name <> '..') then
     begin
       if (SR.Attr and faDirectory) = faDirectory then
       begin
         FindFile(FolderName + '\'+SR.Name);
       end
       else
         ListBox1.Items.Add(Sr.Name);
     end;
   until FindNext(Sr) <> 0;
 FindClose(Sr);
end;

신고
Posted by 나비 나비:D

윈도를 재 설치하고 델파이를 다시 세팅하면서 진작 이런걸 만들어 뒀으면

좀더 쉽게 세팅했을 텐데.. 하는 생각이 들어서 또 델파이를 배우시는 분들에게

도움이 될까 적어 둡니다.


<컴포넌트>

Another Socket 3.0 (http://www.eternallines.com/fundamentals)

CoolTray 4.3.1 (http://www3.brinkster.com/troels/delphi.asp)

Design Experience 2.0.1 (델마당, 델코, 한델 중 한곳에서 받았음 ㅡ_ㅡ)

Embeded WebBrower 1.16b (http://www.euromind.com/iedelphi)

Flat Style 2001.6.27일자 (http://www.delphifreestuff.com)

Graphics32 1.5.1 (http://g32.org)

HttpDown 1.94 (http://www.utilmind.com)

MSN Popup (http://people.zeelandnet.nl/famboek/delphi)

Ole-Drag (델마당[양병규] http://www.delmadang.com)

PSEdit 0.1 (델마당[밥벌래 ricebug@hitel.net] http://www.delmadang.com)

ScanImg 1998.3.2일자 (델마당[민성기] http://www.delmadang.com)

TMS (http://www.tmssoftware.com)

WinGod (델마당, 델코, 한델 중 한곳에서 받았음 ㅡ_ㅡ)

XPMenu 1.02 (http://www.shagrouni.com)


- 직접제작

SizeBar

Title

VScrImage

TPipeMessage

TDXImageHp

TDragOutOf


<클래스 & 넌비주얼 컴포넌트>

CAB Compress 1.08 (http://aravilsoft.tripod.com)

GIF Image (http://www.hasc.com)

GraphicEX (http://www.lischke-online.de)

DX9 1.1 (JEDI http://www.delphi-jedi.org)

JanFX Original Release 2000.7.2

TProEffectImage 1.0  (http://raveland.netfirms.com)

BMPRGN (델마당 http://www.delmadang.com)

MMX_Move (델마당 http://www.delmadang.com)


[직접만듦]

ASCII_CODE

BitmapList

Calculate

FileList

GlobalMatrix

MJBitmap

MJList

MyProcess

Option

SurfaceLayer

Tray

WowPluginManager

FileStuff

신고
Posted by 나비 나비:D
 글이 상당히 좋은 글임에도 불구하고 보시는 분마다 스트레스(?)를 받는것은 그냥... 좀 어려운내용이 길~게 있으니깐 그럴것입니다.
해서리.. 제가 초간단으로 요점을 간추려서 제 스타일로 다시 설명을 해보겠습니다...
쩝....(이런건 또 첨해보넹.. --;)



API후킹이란?...


1. API는 DLL파일안에 들어있습니다.
  API함수를 사용한다는것은 윈도우가 제공하는 DLL안에 들어있는 함수를 사용하는겁니다.
  그러므로 API후킹을 한다는것은 다른 프로그램이 DLL의 함수를 사용하는것을 내가 가로채는것을 말합니다.


API 후킹의 목적...


2. 가로채서? 그 다음은 그 함수의 기능을 사용하지 못하게 할수도 있고 어떻게 사용하는지 감시만 할 수도 있고 전혀 다른 내용으로 바뀌게끔 할 수도 있습니다. 그러므로 이것을 이용해서 할 수 있는 일을 두가지 정도로만 야그해보면...

3. 다른 프로그램을 디버깅하거나 리버스엔지니어링들을 위해서 사용할 수 있습니다. API함수만 알아가지고 뭘 알수 있겠냐라고 생각할 수도 있겠지만.. 사실 우리가 사용하는 모든 델파이 문법과 라이브러리는 결국 API함수를 사용하기위한 과정에 불과합니다. 윈도우는 디바이스에 내용을 출력하고 키보드 마우스로 입력받고, 다른 장비와 통신하고하는 모든 과정을 API, 메세지, ActiveX 이 세가지로 다 합니다.

4. API후킹을.. 디버깅하는데만 사용하지는 않고 어떤 특별한 기능을 구현할때도 사용합니다. 가장 좋은 예로 노클릭 영한사전이 있습니다. 글씨에 커서를 가져가면 번역을 보여주는.. 그런것을 할때도 API후킹이 필요합니다. 그때는 Text에 관련된 함수들을 후킹하겠지요..

5. DLL의 구조를 좀 알아야합니다. 여기서 DLL의 구조를 안다는것을 PE포맷을 알아야 한다는것과 유사한데 그렇다고 핵사에디터로 DLL을 열어서 바이너리를 들여다 보라는 야그가 아니라 적어도 DLL의 도스헤더, NT헤더(PE헤더) 그리고 임포트테이블 정도까지는 아..그런게 있구나 하는 정도는 알아야한다는겁니다. 물론 그것들을 위한 스트럭쳐(레코드)가 있으므로 그것을 우선 확보해서 사용방법을 알면 되겠습니다.


두 가지 기술...


6. 남의 역역으로 쳐들어가기.. API후킹을 할려면 다른 프로그램의 메모리 영역으로 내가 만든 코드를 침투시켜야합니다. 왜냐하면 NT의 버쳘메모리메니져가 기본적으로 남의 영역을 침범하지 못하게 만들어 놨기 때문입니다. 물론 그것은 9x계열도 마찬가집니다. 그래서.... API 후킹을 하는데 있어서 남의 영역으로 쳐들어 가는 방법은 상당히 중요한 부분입니다.

7. 함수 가로채기.. 일단 쳐들어가면 그 다음에는 함수를 가로채야합니다. 목적이 그것이니깐여... 함수를 가로채는데도 여러가지 방법이 있습니다.


남의 영역으로 쳐들어가기


8. 메세지훅을 이용하는 방법... 메세지 후킹을 시스템 전역으로 설치하면 다른 프로그램이 내가 만든 DLL을 로드하게 됩니다.
  그것을 이용해서 남의 프로그램의 영역에 침투시키는데 이 방법이 가장 일반적입니다.
  그래서 메세지 후킹도 알아야 하는데 잘 할 필요는 없습니다. 그냥 남이 만든거 배껴서 고쳐서 쓸수 있는 정도면 되겠습니다.
  본문에서는 메세지훅을 윈도우즈후크라고 표현했습니다.

  메세지훅을 이용했을때의 장점은 모든 윈도우에서 동일한 방법으로 지원한다.
  미래의 윈도우즈에서도 계속 지원이 유지될것이다.
  훅의 시작과 해제를 자유롭게 제어할수있다..라고 본문에서 설명하고 있는데..
  양병규가 좀더 덧붙이자면 메세지훅은 윈도우가 지원하는 표준적인 방법이라는것이 가장 큰 매력인것같고요...
  본문는 미래에도 이 방법은 바뀌지 않을것같다라고 했는데 제 생각은 좀 다릅니다.
  그렇게 생각하는 가장 큰 이유는 이 방법이 문서화 되어있는 표준적인 개발 방법이기때문에 호환성을 위해서라도 없앨수 없다라고 라고 생각하는데..
  그것은 맞는 말이지만.... 메세지 훅을 통해서 로드된 DLL이 프로그램의 모든 버쳘메모리 영역에 침투할 수 있다..라는 사실은 MSDN어디에도 명시되어있지 않습니다.
  그것이 그렇게 되어있는 이유는 현재의 윈도우 버쳘메모리 메니져가 그렇게 만들어져 있기때문이고 앞으로 MS가 그것이 문제가 심각하다라고 판단하면 언제든지 변경을 할 수 있는 내용입니다.

  메세지훅을 이용하는 방법의 단점은... 시스템의 성능을 확연하게 저하시킵니다. 메세지의 체계에 하나가 더 끼어들기때문에 어쩔수 없이 그렇게 됩니다.
  하지만... 제 생각은 조금 다릅니다. 시스템 성능이 저하는 되지만 확연하게..는 아닙니다... 현저하게 저하되는 경우는 훅프로시져에서 많은 일을 할수록 시스템성능이 더 많이 저하됩니다.
  그런데 API훅의 침투용으로 사용하는 훅프로시져는 대부분 아무일도 안합니다.
  그리고 메세지 훅도 훅 나름입니다. WB_GETMESSAGE훅의 경우 메세지가 발생하는 대부분의 윈도우에 걸립니다. 그러므로 한 프로그램에 윈도가 100개면 그만큼 훅프로시도 많이 동작하게 됩니다.
  WB_CBT훅의 경우는 시스템메뉴메세지가 동작할때 발생하므로 윈도가100개라도 그중에 가장 parent에 있는 윈도만 그 훅을 받아들이고 발생도 자주 안합니다.
  고로...메세지훅의 종류와 사용법에 따라 많이 달라집니다. 암튼.. 그러므로 메세지훅을 잘 이용하면 성능저하가 피부로 느끼지 못하게 할수도 있습니다.
  본문에서 "어떤 특별한 상황(버그 발생)에서는 복구하기 위해 시스템을 리부팅해야만 한다"고 했는데...
  메세지훅이 걸린 상태에서 에러가 발생하는등 훅을 건 프로그램이 정상기능을 수행하지 못하게 되버리면 훅을 해제할 수도 없고 훅용DLL이 사용중이니 재 컴파일 할수 없으므로 재부팅을 해야한다는 말입니다.
  제가 생각하는 메세지훅의 또 다른 단점은 윈도우가 없는 어플리케이션에는 침투할 수 없다는 단점이 있습니다.
  좌우지간 메세지훅을 이용하는 방법은 까다로운면도 많고 장점도 많고... 단점도 있고.... 머 그렇습니다.

9. USER32.DLL의 초기화 부분을 이용하는 방법 USER32.DLL은.. 초기화 부분이 실행될때 레지스트리에 등록된 USER32초기화 DLL목록을 읽어와서 거기에 등록되어진 DLL을 로드하게 되어있습니다.
  흠... 그렇게 만든 이유는 아마도 USER32는 윈도우에서 사용하는 대부분의 객체가 구현되어져 있기때문에 그것과 관련이 있지 않나 싶습니다.
  본문에서 소개하고 있는 레지스트리 경로에 DLL파일을 추가하면됩니다.
  이 방법의 장점은 비교적 손쉽다라는 장점이 있습니다.. 더 이상 다른 장점은 없습니다. ^^;
  단점은 USER32.DLL을 안쓰는 프로그램에는 효과가 없고 NT계열만 되고.. 설치후 재부팅을 해야하고...훅의 시작와 해제를 맘대로 제어할 수 없습니다.
  고로 이방법은 일반 어플리케이션에 적용하기에는 좀 그렇고 거의 디버깅용으로 밖에 쓸 수 없습니다.

10. CreateRemoteThread를 이용하는 방법을 본문의 저자가 젤루 선호한다고 했는데....
   CreateRemoteThread함수를 이용할때 콜백함수를 지정하게 되는데 그 콜백함수의 구조가 LoadLibrary함수의 구조와 동일합니다.
   그래서 콜백함수로 LoadLibrary를 지정해서 로드하게 만든다... 머 그런겁니다.
   이 방법의 단점은 시스템 전역으로 사용하기에는 무리가 있고 주로 디버깅용으로 많이 사용합니다. 글구 NT계열에서만 됩니다.

11. 본문에서 그 외 소개하는 방법은 익스플로러나 오프스등의 플러그인 기능을 이용한다는 방법인데...
   요즘 이걸 이용한 바이러스들이 아주 지랄입니다. 이 넘이 하나 깔리면 V3로 치료를 해도 또 살아나고 그럽니다.
   그래서 바탕화면까지 몽땅 죽여놓은 상태에서 백신을 돌려야 치료가 되곤합니다.
   사실 저도 예전에 민성기님과 이런 저런 야그를 하면서 폴더카피훅을 이용해서 쳐들어가곤 했는데.... 암튼 이방법은 아주 허접합니다. ^^;;
   단점은 걸리면 무쟈게 욕을 먹고 요즘엔 이런것만 잡고 다니는 프로그램도 많습니다.


함수 가로채기...


12. 본문에서는 커널레벨훅과 서브클래싱을 소개하고 있는데 그것은 API후킹이 아닙니다... --;

13. DLL바꿔치기... 본문에서는 Proxy DLL (Trojan DLL)(대리자 DLL)라고 소개하고 있는데...
   API함수를 가지고 있는 DLL을 똑같이 새로 만드는 방법입니다.
   그 DLL에는 원래 DLL이 가지고 있는 API함수를 똑같은 구조로 만들어서 그 함수들은 원래의 DLL함수의 똑같은 함수를 호출합니다.
   아~~주 단순무식한 방법인데 수 년전에 내가 하영재씨와 민성기씨에게 이 방법을 소개했드만 낄낄대고 웃더라... ^^;
   하지만 기술적으로 아주 쉬운방법이긴합니다 ^^;; 물론 실용성은 없슴다 --;

14. Code overwriting(코드 덮어쓰기)
   이 방법은... 메모리상에있는 함수들을 싸그리 뒤져서 CALL명령($E9)을 찾아다가 그 바로 뒤 네바이트(포인터값)을 봐서 그 값이 API함수의 어드레스면 그것을 내가 만든 함수의 어드레스로 바꿔치고 내가 만든 함수에다가 하고싶은 일을 다하고 다시 원래 API함수를 호출하는 .. 머 그런 방법인데...
   잘 만들면 괜찮은 방법인데 이 방법을 써서 제대로 돌아가는 프로그램을 못봤슴다. 1분안에 에러가 안나면 기적이다.. ^^;;

15. Spying by a debugger(디버거를 이용한 스파이)
   이 방법은 아무리 생각해봐도...... API후킹이라고 말하기에는 좀 그렇슴다....
   본문을 쓴 원작자는...  API후킹을 주로 크랙이나 리버스엔지니어링으로 많이 사용하는 경향이 있는것같슴다... 쩝....

16. 임포트테이블 바꾸기
   이 부분은 상당히 길게 설명하고 있는데... 많이 보편화 되어있습니다.... 실제로 피씨방에서 감시용 프로그램등에 많이 사용되고 있지여..
   EXE에는 DLL함수를 연결하는 함수 임포트테이블이란걸 가지고 있습니다. (DLL에도 있따)
   실행이 되면 윈도우가 DLL에 있는 함수의 주소를 그 테이블에 써줍니다. 그래서 그 주소로 점프하게 되는데...
   그 주소를 바꿔치기하는 방법입니다.
   장점은 9x, NT모두 사용할수 있고 비교적 쉽습니다.
   제가 덧붙이면.. 단점이 하나있는데 UPX, ASPack등으로 압축된 실행파일은 임포트테이블을 제거하고 LoadLibrary로 대치하는등 임포트테이블을 망가뜨려버리기때문에 이 방법이 안통합니다.


그 외....


17. 나머지 설명들은 API후킹을 이용하는 프로그램의 구성등에 대해 설명하고 있슴다....
   그러므로 뒷부분은 일단 API후킹을 성공한 후부터 보면될것 같습니다.


그리고 본문에서 소개하는 방법외에도 몇가지를 더 소개하면....


18. 심플코드오버라이팅이라는 방법이 있는데 제가 젤루 선호하는 ^^ 방법입니다.
   원래의 API함수 자체를 수정하는 방법인데 내가 만든 함수로 점프하게하는 코드를 써넣습니다.

19. 익스포트테이블을 수정하는 방법도 있는데 임포트테이블을 수정하는 방법하고 유사합니다.
   다른 점은 임포트테이블을 수정하는 방법은 EXE에 있는 테이블을 수정하는것이고 이 방법은 API함수가 있는 DLL에서 익스포트테이블을 고치는 방법인데(물론 모두 메모리에서 벌어지는 일입니다. 실제 파일을 수정하는게 아닙니다.)
   EXE의 경우 UPX등으로 압축할 수 있지만 API함수가 있는 DLL을 UPX로 압축해서 쓰는 사람은 없으므로 위에서 말한 단점을 보완할수 있다는 장점이 있습니다.


제가 생각하기에는...


20. API후킹을 이용해서 프로젝트를 할 때는 반드시 그것이 통하는 범위를 제한해야합니다.
   예컨데 노클릭영한 사전을 만들면서 한글로된 모든 텍스트를 다 후킹할수 있따...라고 호언장담하지말고..
   캡쳐방지를 만들면서 모든 캡쳐프로그램을 다 막을수 있습니다....라고 장담하지 말라는 야급니다.


쩝...

- 끝 -

헥헥~ @@;
신고
Posted by 나비 나비:D
11월 세미나 소스 리팩토링 예제

[일러두기]
이글은 11월에 개최할 세미나 예제 중 하나이며, 다소 광고성 성격이 강함을 미리 일러두겠습니다. 11월경의 세미나때문에  최근 저의 강좌들이 다소 세미나 홍보성글인데 대해서 고개 숙여 양해를 구합니다. 남의 코딩 방식을 자주 보면 도움이 되는 경우가 많은데, 이 강좌를 저의 코딩 방식을 엿보는 기회로 삼으시기 바랍니다.
[일러두기 끝]

이글에 첨부한 프라젝트는, 아주 간단한 MDI 방식의 실행 파일로서 다음과 같은 기능을 가지고 있다(참고로 리팩토링이 안된 상태의 프라젝트 소스이다)

1. 프로그램을 종료할 때 Fading효과(조금씩 사라지는 효과)를 보여준다.
2. MDI 메인폼에 배경 그림을 표시한다.
3. 메인메뉴에 세개의 작업폼(MDI Child 폼)을 보이도록 하는 메뉴가 있다.
4. 동일 클래스의 작업폼을 2개 이상 만들지 못하도록 처리되어 있다.

한번 실행해 보면 모든 기능을 알 수 있는 아주 간단한 프로그램이다.

다음은 이 프라젝트의 메인폼 소스 파일 내용이다.

// FmMain.pas.. 리팩토링 이전의 상태

unit fmMain;

interface

uses
 Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
 Dialogs, Menus;

type
 TMainFrm = class(TForm)
 {..중략..}
 private
   procedure OpenForm(AFormClass:TFormClass);    
 public
 end;

var
 MainFrm: TMainFrm;

implementation

{$R *.dfm}

uses fmSub1, fmSub2, fmSub3;

var
 // For Form Painting
 BitMap : TBitMap;

procedure TMainFrm.FormCreate(Sender: TObject);
begin
 // Begin Form Fading Effect Code
 AlphaBlend := True;
 AlphaBlendValue := 255;
 // End Fading Effect Code

 // Begin Form Painting
 Bitmap := TBitmap.Create;
 Bitmap.LoadFromFile('깃털.BMP');
 // End Form Painting
end;

procedure TMainFrm.FormClose(Sender: TObject; var Action: TCloseAction);
begin
 // Begin Form Fading Effect Code
 while AlphaBlendValue > 1 do
 begin
   AlphaBlendValue := AlphaBlendValue - 1;
   Sleep(10);// Change the sleep time to manage fading speed
 end;
 // End Fading Effect Code
end;

procedure TMainFrm.FormPaint(Sender: TObject);
var
 // Form Painting Vars
 X, Y, W, H: LongInt;
begin
 // Begin Form Painting
 with Bitmap do
 begin
   W := Width;
   H := Height;
 end;
 Y := 0;
 while Y < Height do
 begin
   X := 0;
   while X < Width do
   begin
     Canvas.Draw(X, Y, Bitmap);
     Inc(X, W);
   end;
   Inc(Y, H);
 end;
 // End Form Painting
end;

procedure TMainFrm.FormDestroy(Sender: TObject);
begin
 Bitmap.Free;
end;

// 동일 클래스의 폼을 2개 만들지 못하도록 처리
procedure TMainFrm.OpenForm(AFormClass:TFormClass);
var
 i: Integer;
begin
 for i := 0 to MdiChildCount - 1 do begin
   if MdiChildren[i].ClassType = AFormClass then
   begin
     MdiChildren[i].BringToFront;
     Exit;
   end;
 end;

 AFormClass.Create(Self);
end;

procedure TMainFrm.Sub11Click(Sender: TObject);
begin
 OpenForm(TSub1Frm); // 작업폼1 열기
end;

procedure TMainFrm.Sub21Click(Sender: TObject);
begin
 OpenForm(TSub2Frm); // 작업폼2 열기
end;

procedure TMainFrm.Sub31Click(Sender: TObject);
begin
 OpenForm(TSub3Frm); // 작업폼3 열기
end;

end.

아마도, 대부분의 델파이 개발자들은 이런식으로 메인폼 소스 파일을 작성할 것이다. 다시 말해서 전형적인 델파이 방식 메인 폼 소스 파일일 것이다.

이 소스를 주위 델파이 개발자들에게 보여주고, 잘못된 점을 찾아보라고 했다. 대부분 별다른 문제점을 찾아 내지 못했다.사실 너무 간단하기도 하지만, 얼핏 봐서는 잘못된 점이 보이지 않을 수도 있다. 코드 중복도 거의 없으며, 상당히 깔끔하게 작성된 메인 폼 소스처럼 보일 것이다.

그러나, 이 전형적인 메인 폼 소스 파일에는, 후일 유지보수와 디버깅에 치명적인 장애물이 될 수 있는 함정들이 여러 군데에 걸쳐 있다. 이 치명적 장애물이 무엇인지, 어떻게 실제로 리팩토링을 해야 하는지는 이번 세미나에서 굉장히 중요한 주제 중의 하나이므로, 지금 이글에서 여러분들에게 알려주지 못함을 양해해 주시라.

이 강좌에서는 이 메인폼 소스 파일을 리팩토링한, 결과 소스만 보이고자 한다.

// fmMain.pas ...리팩토링한 후의 메인 폼 소스

unit fmMain;

interface

uses
 Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
 Dialogs, Menus, EtcUtil;

type
 TMainFrm = class(TForm)
  {.. 중략...}
 private
   { Private declarations }
 public
   { Public declarations }
 end;

var
 MainFrm: TMainFrm;

implementation

{$R *.dfm}

uses fmSub1, fmSub2, fmSub3;

procedure TMainFrm.FormCreate(Sender: TObject);
begin
 // Fading 효과 설정
 TFadingEffect.Create(Self).Init();
 // 배경 그림 설정
 TBackGround.Create(Self).Init('깃털.bmp');

 // 작업 메뉴 초기화
 mnuJobForm.Add( TMenuItem.Create(Self).Init('Sub1 폼 보이기', TSub1Frm) );
 mnuJobForm.Add( TMenuItem.Create(Self).Init('Sub2 폼 보이기', TSub2Frm) );
 mnuJobForm.Add( TMenuItem.Create(Self).Init('Sub3 폼 보이기', TSub3Frm) );
end;

end.

리팩토링한 소스 파일은 매우 간략해져서, 프로그램 흐름이 한 눈에 들어오는 구조로 변했다. 특히 리팩토링이 안된 버전에 비해서 이벤트 메서드 수가 현저히 작다. 보시다 시피 Form의 OnCreate 이벤트 고작 하나 뿐이다.

리팩토링한 결과 소스를 본 사람 중에는, 왜 Free 호출이 없는가 궁금해 하는 사람도 있을 것 이다. 이런식으로 코딩하면 객체가 파괴되지 않아서 메모리 누수 현상이 발생하지 않는가 의아해할 수도 있다. 그러나, 이것이 바로 자동 파괴 개념이다. 파괴를 안하는 것이 아니라 파괴자 호출을 자동화하는 것이다.

객체지향과 델파이에 매우 능한 개발자라면, 내가 어떻게 리팩토링했는지, 이 소스를 보고 상당 부분 이미 짐작했을 수도 있다.

사실 리팩토링은 끝이 없다. 매우 간략해 보이는 두번째 메인 폼 소스조차도, 리팩토링을 또 할 수 있는 여지는 많기 때문이다. 지나친 리팩토링은 개발기간을 가중시키므로, 바람직하지 않지만, 적절한 리팩토링은 개발 효율을 높일 수 있다는 사실을 이 강좌의 결론으로 두고자 한다.

업무 변경 사항이 잦아서 소스가 꼬이기 시작한다면 리팩토링을 고려할 시기가 된 것이다.

http://cafe.daum.net/delphinegong
신고
Posted by 나비 나비:D

작성자 : 주정섭  (jjsverylong)

원문 : http://delphi.borlandforum.com/impboard/impboard.dll?action=read&db=del_tutorial&no=98


____________________________________________________________________________________________
원래 이 글은 예전에 작성한 것이지만, 볼랜드 포럼의 델파이 강좌란이 너무 심심(?)한 것 같아서 재편집해 올립니다. 개발자 게시판이란 좋은 강좌와 팁이 많아야 하는데, 최근의 여러 델파이 관련 사이트를 보면, 대부분 자유게시판과 질답 게시판에만 글이 올라 오고,  다른 게시판은 거의 죽어 있는 것같아 무지 안타깝습니다.

좋은 강좌와 팁이 델파이 관련 사이트에 넘치기를 바라면서....
___________________________________________________________________________________________

다음 코드는 어떤 버튼의 클릭이벤트이다. 클릭할 때마다 버튼의 Caption 속성을 '하하'와 '호호'로 토글하는 코드다. 이 버튼의 Name 속성을 Button1이라고 하자.

[원본 클릭 이벤트]

procedure TForm1.Button1Click(Sender: TObject);
begin
  if Button1.Caption = '하하' then
    Button1.Caption := '호호'
  else
    Button1.Caption := '하하'
end;

코드는 매우 간단하므로 이해하는데 별로 어려움이 없을 것이다. 이 정도의 간단한 코드에 무슨 리팩토링이 필요할 것인가라고 생각할지 모르나, 사실은 그렇지 않다. 여기서 논하는 리팩토링은 마틴 파울러의 리팩토링 책 내용과는 다소 다른 내용이다. 이 리팩토링은 델파이라는 특수한 개발 환경에 의존적이기 때문이다. 어쨋든 여러분은 이 간단한 코드에도 리팩토링이 가능함을 알 수 있을 것이다. 문제는 이 간단한 리팩토링 마저도 상당수의 델파이 개발자들이 하지 않는다는 것이다.

[리팩토링 1단계]

가급적 상수(constant)들은 코드내에서 들어내서 별도로 두라.

procedure TForm1.Button1Click(Sender: TObject);
const
  s1 = '하하';
  s2 = '호호';
begin
  if Button1.Caption = s1 then
    Button1.Caption := s2
  else
    Button1.Caption := s1;
end;

[리팩토링 2단계]

이벤트 메서드 내에서 가급적이면 콤포넌트 Name을 직접 참조하지 말라. 콤포넌트명을 직접 참조하면 후일 그 콤포넌트 Name 속성을 바꿨을 때, 그 콤퍼넌트를 참조하는 코드도 같이 수정해야만 하기 때문이다.

procedure TForm1.Button1Click(Sender: TObject);
const
  s1 = '하하';
  s2 = '호호';
begin
  if TButton(Sender).Caption = s1 then
    TButton(Sender).Caption := s2
  else
    TButton(Sender).Caption := s1;
end;

[리팩토링 3단계]

방어적인 운전이 있듯이 방어적인 코딩도 있다. 에러에 미리 대처하는 코딩을 말한다. 이 이벤트가 실수로 버튼이 아닌 다른 콤포넌트의 클릭 이벤트에 연결되면 참으로 큰일 날 것이다. 다음은 이에 대한 대처 방법이다.

procedure TForm1.Button1Click(Sender: TObject);
const
  s1 = '하하';
  s2 = '호호';
begin
  Assert(Sender is TButton, '버튼에만 연결할 수 있는 이벤트다. 조졌다 니는 잘못 연결했다.');

  if TButton(Sender).Caption = s1 then
    TButton(Sender).Caption := s2
  else
    TButton(Sender).Caption := s1;
end;

신고
Posted by 나비 나비:D

[함수 원형]

WINSHELLAPI  int  WINAPI  SHFileOperation( LPSHFILEOPSTRUCT lpFileOp );



[SHFILEOPSTRUCT 구조체]

typedef struct _SHFILEOPSTRUCT{
    HWND         hwnd;
    UINT         wFunc;
    LPCSTR       pFrom;
    LPCSTR       pTo;
    FILEOP_FLAGS fFlags;
    BOOL         fAnyOperationsAborted;
    LPVOID       hNameMappings;
    LPCSTR       lpszProgressTitle;
} SHFILEOPSTRUCT, FAR *LPSHFILEOPSTRUCT;



[파라미터]

hwnd  파일 동작 상태에 대하여 정보를 출력하기 위한 대화 상자의 윈도우 핸들

wFunc 수행할 동작. 이 멤버는 다음 값 중 하나가 될 수 있다.

    FO_COPY : pFrom 멤버에 정의된 폴더 또는 파일로부터 pTo 멤버에 정의된 폴더 또는 파일로 복사를 수행한다.

    FO_DELETE : pFrom 멤버에 정의된 폴더 또는 파일을 삭제한다. (pTo는 무시된다.)

    FO_MOVE : pFrom 멤버에 정의된 폴더 또는 파일로부터 pTo 멤버에 정의된 폴더 또는 파일을 이동시킨다.

    FO_RENAME : pFrom에 정의된 폴더 또는 파일의 이름을 변경한다.

pFrom 하나 또는 그 이상의 소스 파일로 채워진 버퍼의 주소. 다중 파일 이름은 널로 구분되어야 한다.그리고 파일 이름의 끝은 더블 널로 종결되어야 한다. ex) a.txt\0b.txt\0c.txt\0\0 (파일명 사이에는 NULL, 파일의 끝은 더블 NULL)

pTo 목적지 파일 또는 디렉터리의 이름을 포함하는 버퍼의 주소. 버퍼는 fFlags가 FOF_MULTIDESTFILES일 때 다중 목적지가 될 수 있다. 다중 이름은 pFrom과 같이 NULL로 구분되어야하며 더블 NULL로 끝나야 한다.
fFlags 파일 동작을 제어하는 플래그들. 이 멤버는 다음 플래그의 조합이 될 수 있다.
    FOF_ALLOWUNDO : Ctrl + Z 등에 의한 Undo 기능을 지원한다.
    FOF_CONFIRMMOUSE : 아직 지원되지 않는다.
    FOF_FILESONLY : *.*이 파일로 지정되었을 때, 파일만 사용하도록 한다.
    FOF_MULTIDESTFILES : pTo 멤버에 다중 목적지를 허용하도록 한다.
    FOF_NOCONFIRMATION : 표시되는 모든 대화 상자의 물음에 대하여 자동으로 Yes를 선택하도록 한다. 그러므로 이 플래그가
                                         사용되면 사용자가 누를 필요가 없다.
    FOF_NOCONFIRMMKDIR : 폴더를 생성해야 할 때 물어보지 않고 폴더를 생성한다.
    FOF_NOCOPYSECURITYATTRIBS : 보안 속성.
    FOF_NOERRORUI : 에러 발생 시 사용자에게 표시하지 않는다.
    FOF_RENAMEONCOLLISION  : 파일 복사, 이동, 변경 시 이미 해당 폴더에 이름이 존재할 때 새 이름으로 동작되도록 한다.
    FOF_SILENT : 프로그래스 대화 상자를 표시하지 않는다.
    FOF_SIMPLEPROGRESS : 파일 이름을 제외한 프로그래스바만 표시한다.
    FOF_WANTMAPPINGHANDLE : FOF_RENAMEONCOLLISION 플래그 사용 시 hNameMappings를 이름 변경될 정보를 채우도록
                                                한다.
fAnyOperationsAborted 파일 동작이 완료되기 전에 사용자가 취소한 경우 이 값은 TRUE를 갖는다. 그 밖에는 FALSE가 된다.
hNameMappings ^**^ 즐~
Handle to a file name mapping object that contains an array of SHNAMEMAPPING structures. Each structure contains the old and new path names for each file that was moved, copied, or renamed. This member is used only if the fFlags member includes the FOF_WANTMAPPINGHANDLE flag. The handle must be freed by using the SHFreeNameMappings function.
lpszProgressTitle 프로그래스 대화 상자에 타이틀로 사용될 문자열의 주소를 표시한다. 이 멤버는 fFlags의
                             FOF_SIMPLEPROGRESS 플래그를 사용해야 유효하다.

만일 pFrom 또는 pTo 멤버들이 전체 경로를 포함하지 않는다면, 현재 경로는 GetCurrentDirectory() 함수에 의해 얻어지는 경로가 유효한 경로가 된다.

신고
Posted by 나비 나비:D

 함수 레퍼런스 정리...(A) 
 Abs
   문 법 function Abs(X);
    X 의 절대값을 구하는 함수이다.
절대값이란 값은 같으며 부호가 양수인 수를 말한다.
X 는 정수 또는 실수값이다.
   예 제 Abs(-3.14); {결과는 3.14}
Abs(3.14); {결과는 3.14} 
 Addr
   문 법 function Addr(X):Pointer;
    X 의 번지를 구할 때 쓴 함수이다.
X 는 변수나 함수의 명칭이며 결과는 X의 메모리 번지를 나타내는 포인터 값이며, Pointer형이다. Addr 함수의 리턴값이 Pointer형이므로 Pointer형의 변수에 곧바고 대입될 수 있지만 이 함수의 리턴값으로 메모리를 직접 참조할 수는 없다.
메모리를 참조하기 위해서는 타입 캐스트를 해 주어야 한다.
   예 제 Var i : Interger;
begin
    P := Addr(i); {i의 번지를 구한다.}
end; 
 Append
   문 법 procedure Append(Var f:Text);
    파일을 추가 기록용으로 오픈할 때 쓰는 함수이다.
파일 변수 F 는 Assign으로 외부 파일과 연결되어 있어야 한다.
외부 파일이 없으면 에러가 발생하며 이미 열려 있는 경우는 파일을 닫은 후 다시 연다.
파일을 오픈한 후 에디터라인은 파일의 끝(EOF)에 위치시키므로 추가적인 데이터를 파일 끝에 추가할 수가 있다.
다음 예는 루트 디렉토리의 Autoexec.Bat 파일 끝에 Prompt 문을 추가시키는 예제이다.
   예 제 Var F : Textfile;
begin
    AssignFile(F,'c:/autoexec.bat');
    Append(F); {파일 오픈}
    Writeln(F,'Prompt $p$g');
    CloseFile(F); {파일 닫음}
end; 
 AppendStr
   문 법 procedure AppendStr(Var Dest: String; Const S: String);
    두 개의 문자열을 결합하는 함수이다.
Dest 문자열 뒷부분에 Src 문자열이 추가되는 것으로, Dest := Dest + S 와 문법적으로 동일한 기능을 수행한다.
   예 제 Src := 'Apple';
Dest := 'Orange';
AppendStr(Dest, Src);

즉, Dest 문자열은 OrrangeApple 이 된다.
 AssignFile
   문 법 procedure AssignFile(Var f, String);
    텍스트 파일 변수와 외부 파일을 연결시키는 함수이다.
파일 핸들에 파일을 할당하는 것으로 일단 파일과 핸들이 연결되면 핸들에 대한 모든 조작은 파일로 입출력이 된다.
이 프로시져로 핸들에 파일을 할당한 후 Reset이나 Rewrite등을 사용하여 파일을 오픈하며, Writeln이나 Readln으로 파일 입출력을 수행한다.
파일 이름은 문자열 형태로 전달하되 필요한 경우 드라이브명과 디렉토리명을 사용할 수 있다. 주의할 것은 이미 열려져 있는 파일핸들을 재할당해서는 안된다는 점이다.
다음 예는 text.txt파일에서 첫 줄을 읽어 에디트 박스로 출력하는 예이다.
   예 제 Var F: TextFile; S: String;
begin
    AssignFile(F, 'text.txt');
    Reset(F);
    Readln(F,S);
    Edit1.Text := S;
    CloseFile(F);
end; 
       
 
 함수 레퍼런스 정리...(C) 
 ChangeFileExt
   문 법 function ChangeFileExt(Const FileName, ExTension:string):string;
    첫번째 인수 FileName으로 주어진 파일의 이름 중 파일의 확장자만 두번째 인수 Extension 으로 변경하는 함수이다.
다음 예는 인수로 주어진 파일의 확장자를 무조건 INI파일로 변경하는 예이다.
   예 제 ChangeFileExt(ParamStr(0),'.INI'); 
 Chdir
   문 법 procedure chdir(S:string);
    인수 S가 지정하는 경로로 현재 디렉토리를 변경하는 함수이다.
만약 S가 드라이브 문자를 포함하고 있을 경우 현재 드라이브도 변경된다.
 Chr
   문 법 function Chr(X:Byte):Char;
    서수값 X가 지정하는 무자를 구하는 함수이다.
아스키 코드값을 X로 전달하면 해당하는 문자를 얻을 수 있는데 Chr(65)는 알파벳 문자로 A를 뜻한다. 이 함수를 사용하면 키보드로 직접 입력할 수 없는 문자를 입력할 수 있는 쓰임새가 많은 함수이다.
 CloseFile
   문 법 procedure CloseFile(Var F);
    파일 핸들과 외부 파일과의 연결을 끊고 파일 핸들을 닫는 함수이다.
파일 변수 F는 Reset, Rewrite, Append 등에 의하여 오픈된 파일 핸들이며 파일 핸들은 사용 후에 반드시 닫아주어야 하는 함수이다.
   예 제 Var F: TextFile; S: String;
begin
    AssignFile(F, 'text.txt');
    Reset(F);
    Readln(F,S);
    Edit1.Text := S;
    CloseFile(F); // 파일을 반드시 닫아줘야 한다.
end; 
 CompareStr
   문 법 function CompareStr(Const Si, S2: string):Integer;
    두개의 문자열 S1 과 S2 를 비교하되 대소문자를 구분하여 비교하는 함수이다.

S1 과 S2 문자열이 같으면 0 값을 리턴한다.
S1 < S2 이면 음수의 값을 리턴하며, S1 > S2 이면 양수를 리턴한다.

문자열끼리의 비교는 문자열을 이루는 각 문자의 문자 코드를 비교하여 수행되며, 현재 설치된 언어 드라이버에는 영향을 받지 않는다.
 CompareText
    문 법 function CompareText(Const S1, S2 : String):Integer;
      두개의 문자열 S1 과 S2를 비교하되 대소문자를 구분하지 않고 비교하는 함수이다.

S1 과 S2 문자열이 같으면 0을 리턴하며 S1 < S2 이면 음수의 값을 리턴한다.
S1 > S2 이면 양수를 리턴한다.

문자열끼리의 비교는 문자열을 이루는 각 문자의 문자 코드를 비교하여 수행된다.
"Apple" 과 "APPLE" 을 CompareText 함수로 비교하면 결과는 0 이다.
두 문자열이 같은 것으로 비교되지만 CompareStr 함수로 비교하면 결과는 두 문자열이 서로 다른 것으로 비교된다.
 Concat
    문 법 function Concat(S1 [, S2, ... , Sn]:String):String;
      두개 이상의 문자열들을 결합하여 새로운 긴 문자열을 만드는 함수이다.
만약 문자열을 연결한 결과가 255문자 이상일 경우 255번째 이후의 문자는 잘려나간다.
이 함수 대신 + 연산자를 사용하여 문자열을 결합해도 결과는 동일하다.
Concat('Korea','China') 의 경우는 'Korea'+'China'는 같은 결과의 예이다.
다음 예는 Edit1에 입력된 문자열과 Edit2에 입력된 문자열을 한해 Edit3에 대입한다.
    예 제 Edit3.Text := ConCat(Edit1.Text, Edit2.Text);
 Continue
    문 법 procedure Continue;
      For, While, Repeat 등의 반복문에서 사용되며 다음 반복 부분으로 흐름을 옮기도록 하는 함수이다.
루프의 남은 뒷부분은 무시되며 루프의 조건 점검부로 점프한다.
만약 반복 루프 외부에서 이 프로시저가 사용되면 에러가 발생한다.
다음 예는 i가 1~100 까지 증가하며 모종의 처리를 하되 i 가 10인 경우만 특별히 처리가 생략되는 예이다.
    예 제 For i := 1 to 100 do
begin
    If i = 10 then continue;
    ...
end; 
 Copy
    문 법 procedure Copy(S:String; Index, Count:Integer):String;
     한 문자열의 부분 문자열을 추출해 내는 함수이다.
S 문자열의 Index 위치에서부터 Count 문자분의 부분 문자열이 추출된다.
Index 가 문자열의 전체 길이보다 길 경우 빈 문자열을 리턴하며 Count가 문자열의 남은 부분보다 클 경우 문자열의 끝까지 추출해 낸다.
Dest 문자열이 'Orange'일 경우 Copy(Dest, 2, 3)은 Dest문자열의 두번째 문자에서부터 3문자분의 부분 문자열인 'ran'을 추출해 낸다.
       
 
 함수 레퍼런스 정리...(D) 
 Date
   문 법 function Date(Date:TDateTime);
    시스템의 시계를 참조하여 오늘 날짜를 구하는 함수이다.
날짜는 TDateTime형이므로 곧바로 문자열로 출력할 수 없으며, DateToStr 함수를 사용하여 문자열로 바꾸어 주어야만 한다.
다음 예는 Label1에 오늘 날짜가 출력되는 예제이다.
   예 제 Label1.Caption := DateToStr(Date); 
 DateTimeToFileDate
   문 법 function DateTimeToFileDate(DateTime: TDateTime):Longint;
    TDateTime형의 날짜,시간 값을 DOS형식의 날짜,시간형식으로 바꾸는 함수이다.
도스 형식의 날짜는 4바이트의 정수형이며 각 비트에 날짜,시간 요소를 포함하고 있다.
다음 예는 도스형식의 날짜, 시간 형식을 레이블로 출력하는 예제이다.
    예 제 Label1.Caption := IntToStr(DateTimeToFileDate(Now));
 DateTimeToStr
   문 법 function DateTimeToStr(DateTime: TDateTime):String;
    날짜와 시간을 담은 TDateTime형의 변수를 문자열로 바꾸는 함수이다.
만약 DateTime 인수가 날짜를 포함하지 않으면 날짜는 00/00/00 이 되며, 시간을 포함하지 않으면 00:00:00 AM이 된다.
다음 예는 현재 시간과 날짜를 레이블로 출력하는 예이다.
    예 제 Label1.Caption := DateTimeToStr(Now);
 DateToStr
   문 법 function DateToStr(Date: TDateTime):String;
    날짜를 담는 TDateTime형의 변수에서 날짜를 문자열로 바꾸는 함수이다.
다음 예는 오늘 날짜를 레이블로 출력하는 예이다.
   예 제 Label1.Caption := DateToStr(Date);
 DayOfWeek
   문 법 function DayOfWeek(Date: TDateTime):Integer;
    특정 날짜의 요일을 계산하는 함수이다. 리턴되는 값은 1~7까지의 정수이며, 1이 일요일, 7일 토요일이다. 리턴되는 값이 정수형이므로 월, 화, 수 , 목, 금, 토, 일 로 실제요일 이름으로 바꾸어 주어야 한다.
다음예는 요일이름을 레이블로 출력한다.
오늘이 무슨 요일인지 조사해서 요일 이름을 레이블로 출력하는 예이다. 
    예 제 Var
  Yo : String;
  ONUL: TDateTime;
begin
    ONUL := Now;
    Case DayOfWeek(ONUL) of
        1 : Yo := '일';
        2 : Yo := '월';
        3 : Yo := '화';
        4 : Yo := '수';
        5 : Yo := '목';
        6 : Yo := '금';
        7 : Yo := '토';
      end;
    Label1.Caption := '오늘은 ' + YO + '요일입니다.';
end;
 DecodeDate
    문 법 procedure DecodeDate(Date : TDateTime; Var Year, Month, Day: Word);
      날짜를 담는 TDatetime형의 변수에서 년,월,일의 값을 분리시키는 함수이다.
분리된 값들은 각각 Year, Month, Day 등의 정수형 변수에 대입된다.
날짜값은 DateToStr 함수로, 문자열로 바꾼 후 한꺼번에 출력할 수 있지만 개별적인 요소를 가공할 후 한꺼번에 출력할 수 있지만, 개별적인 요소를 가공한 후 출력하고자 할 경우는 이 함수를 사용한다. 이 함수의 반대 함수는 EncodeDate 함수이다.
다음예는 오늘 날ㅉ와 현재 시간을 조사한 후 문자열 조립을 통해 말로 시간과 날짜를 알려준다.
    예 제 Var
  Present: TDateTime;
  Year, Month, Day, Hour, Min, Sec, MSec: Word;
begin
    Present := Now;
    DecodeDate(Present, Year, Month, Day);
    Label1.Caption := '오늘은'+IntToStr(Year)+'년'+IntToStr(Month)+'월'
            +IntToStr(Day)+'일입니다.';
    DecodeTime(Present, Hour, Min, Sec, MSec);
    Label2.Caption := '지금은'+IntToStr(Hour)+'시'+IntToStr(Min)+'분'
            +IntToStr(Sec)+'초입니다.';
end; 
 DecodeTime
    문 법 fun;
      시간을 담는 TDateTime형의 변수에서 시, 분, 초의 값을 분리시키는 함수이다.
분리된 값들은 각각 Hour, Min, Sec, MSec 등의 정수형변수에 대입된다.
시간값은 TimeToStr 함수로 문자열로 바꾼후 한꺼번에 출력할 수 있지만 개별적인 요소를 가공한 후 출력하고자 할 경우는 이 함수를 사용한다.
이 함수의 반대 함수는 EncodeTime 함수이다.
DecodeTime 함수의 예제를 참조하기 바란다. 
 Delete
    문 법 procedure Delete(var S:String; Index, Count: Integer);
      한 문자열에서 부분 문자열을 삭제하는 함수이다.
S 문자열의 Index위치에서부터 Count 문자분의 부분 문자열이 삭제된다.
Index 가 문자열의 전체 길이보다 길 경우 삭제는 이루어지지 않으며, Count가 문자열의 남은 부분보다 클 경우 문자열이 끝까지 삭제된다.
Dest 문자열이 'Orange'일 경우 Delete(Dest, 2, 3)은 Dest 문자열의 두번째 문자에서부터 3분자분의 부분 문자열인 'ran'을 삭제하며 Dest 문자열은 'Oge'가 된다.
 DeleteFile
    문 법 function DeleteFile(const FileName: String): Boolean;
     디스크 상의 파일을 지우는 함수이다.
파일이 없거나 읽기 전용 속성을 가질 경우 False를 리턴하며 파일은 지워지지 않는다.
그러나 파일을 지울 수 없는 경우라도 예외는 발 생하지 않는다.
파일은 경로를 포함할 수 있으며, 다음 예는 C 드라이브의 루트에 있는 Command.com 파일을 지우는 예이다.
물론, 이 명령을 실행한 후부터 부팅이 되지 않으니 다른 파일로 실험하세요. 
    예 제 DeleteFile('C:/Command.Com');
 DirectoryExists
   문 법 function DirectoryExists(Name: string): Boolean;
    인수로 전달된 디렉토리가 존재하는지 검사하며 존재할 경우 True값을 리턴하고 존재하지 않을 경우 False값을 리턴한다.
       
 
 함수 레퍼런스 정리...(E) 
 EncodeDate
   문 법 function EncodeDate(Year, Month, Day: Word): TDateTime;
    정수형으로 주어진 년, 월, 일의 값을 사용하여 날짜를 담은 TDateTime 형의 변수 하나를 만들어 주는 함수이다.
Year 는 1~9999까지의 값을 가지며 Month는 1~12, Day는 1~31까지 가능하다.
단, Day값의 범위는 Month 값의 영향을 받으며 Year는 윤년인 경우의 영향도 받는다.
만약 날짜값이 무효일 경우, 예를 들어 2월30일 등의 값이 주어지면 EConvertError예외가 발생하다.
년,월,일을 개별적으로 입력받아 하나의 날짜값을 만들고자 할 때 이 함수를 사용한다.
이 함수의 반대는 DecodeDate 이다. 
 EncodeTime
   문 법 function EncodeTime(Hour, Min, Sec, MSec: Word): TDateTime;
    정수형으로 주어진 시, 분, 초의 값을 사용하여 시간을 담은 TDatetime형의 변수 하나를 만든다.
Hour 는 0~12까지 가능하며, 만약 Time24Hour가 True일 경우 0~23까지의 24시간을 표현할 수 있다.
Min, Sec은 0~59까지 가능하며 MSec은 0~999까지 가능하다.
시간값이 무효일 경우, 예를 들어 8시 86분 등의 값이 주어지면 EConvertError 예외가 발생한다.
시,분,초를 개별적으로 입력받아 하나의 시간값을 만들고자 할 때 이 함수를 사용한다.
이 함수의 반대는 DecodeTime 이다. 
 Eof
   문 법 function Eof[(Var F: Text)]: Boolean;
    입력한 값들에 대한 끝인가를 점검하는 함수로서 Eof는 End Of File을 의미한다.
DB 작업을 할때, While문을 많이 쓰게 되는데 이경우 필드의 끝이 아닐때까지 계속 루프를 돌리는 작업때 많이 쓰이게 된다. 
 ExpandFileName
   문 법 function ExpandFileName(const FileName: string): String;
    파일 이름에 드라이브명과 디렉토리명을 붙여 완전 경로(Full Path)를 만들어내는 함수이다. 덧붙여지는 경로는 현재 드라이브와 현재 디렉토리이다. 
 ExtractFileExt
   문 법 function ExtractFileExt(const FileName: string): string;
    완전 경로에서 파일의 확장자만 분리시키는 함수이다.
특정 파일의 확장자를 알고자 할 때 이 함수를 사용하여 확장자만 분리한 후 문자열 비교를 수행하면 된다.
 ExtractFileName
    문 법 function ExtractFileName(const FileName: String): String;
      완전 경로에서 파일 이름만 분리해 내는 함수이다.
파일의 확장자도 같이 분리된다.
즉, 완전 경로에서 드라이브명과 디렉토리명이 제외된다. 
 ExtractFilePath
    문 법 function ExtractFilePath(const FileName: String): String;
      완전 경로에서 파일 이름을 제외하고 드라이브명과 디렉토리명만 분리해 내는 함수이다.
다음 예는 완전 경로를 가진 FileName 으로부터 경로만 분리해낸 후 파일이 있는 디렉토리로 이동한다.
    예 제 Chdir(ExtractFilePath(FileName));
       
 
 함수 레퍼런스 정리...(F) 
 FileExists
    문 법 function FileExists(const FileName: String): Boolean;
      파일이 디스크상에 존재하는지를 조사하는 함수로서, 파일이 없을 경우 False를 리턴한다. 존재하지 않는 파일을 사용하고자 할 경우 예외가 발생하므로 먼저 이 함수를 사용하여 파일이 있는지를 먼저 확인해 보아야 한다.
다음 예는 파일의 존재 여부를 점검해 본 후 파일을 삭제하는 예이다. 
   예 제 If FileExists(FileName) Then DeleteFile(FileName);
 FileOpen
    문 법 function FileOpen(const FileName: String; Mode: Word): Integer;
      델파이가 사용하는 내부적인 함수로서 사용자가 직접 사용하는 경우는 드문 함수이다. 파일을 오픈할 때는 델파이가 제공하는 Reset, Rewrite, Append등의 프로시저를 사용한다. 
 FileSearch
    문 법 function FileSearch(const Name, DirList: String): String;
      DirList에 주어진 디렉토리의 경로에 Name파일이 있는지를 조사해주는 함수로서, DirList는 도스의 Path문에서와 같이 여러개의 디렉토리명을 세미콜론으로 끊어 기입한다. 파일을 찾을 경우 파일의 완전경로를 리턴하며 파일을 찾지 못할 경우 널스트리을 리턴한다. 
 FindClose
    문 법 procedure FindClose(var SearchRec: TSearchRec);
      FindFirst, FindNext 함수를 사용한 파일검색을 종료하는 함수로서, 굳이 파일 검색 작업을 종료해 주어야 할 필요는 없으며, 실제로 16비트 버젼의 윈도우에서 이 함수는 아무런 일도 하지 않지만, 32비트 버젼의 윈도우에서는 반드시 검색 종료를 해 주어야 하므로 호환성을 위해 검색 후 종료해 주는 것이 좋다. 
 FindFirst
   문 법 function FindFirst(const Path: String; Attr: Word; Var F: TSearchRec): Integer;
    주어진 검색조건과 파일의 속성을 사용하여 첫 번째 일치하는 파일을 검색해 내는 함수로서, Path는 검색하고자 하는 디렉토리와 파일의 조건이며 와일드 카드식으로 표현이 된다.
예를 들어 'c:/windows/*.exe'는 windows 디렉토리의 확장자가 EXE 인 첫번째 파일을 검색한다. Attr인수는 검색대상이 되는 파일의 속성을 지정하며 아래와 같은 속성 상수를 사용한다.
여러가지 속성을 사용할 경우에는 'Or' 연산자로 속성을 연결하면 된다. 예를 들어 읽기전용이면서 숨은 파일을 검색하고 싶다면(faReadOnly + faHidden)과 같이 Attr인수를 설정하면 되는 것이다. 
      상 수 값 의 미
faReadOnly $01 읽기 전용
faHidden $02 숨은 파일
faSysFile $04 시스템 파일
faVolumeID $08 디스크 볼륨
faDirectory $10 디렉토리
faArchive $20 기록 속성
faAnyFile $3F 모든 속성
 
 FindNext
    문 법 function FindNext(var F:TSearchRec): Integer;
      FindFirst에 이어 계속 검색을 수행하는 함수이다. FIndFirst가 첫번째 검색한 결과를 저장한 F를 다시 인수로 넘겨주면 계속해서 일치하는 조건을 가진 파일을 검색해 내며, 검색한 결과는 역시 F로 저장된다.
검색이 계속 이루어지고 있다면 0을 기턴하며 검색중 에러가 발생했거나 더 이상 조건이 일치하는 파일이 없으면 음수의 에러코드를 리턴한다.
FindFirst와 FindNext는 조건에 맞는 모든 파일을 검색해 낼 때 사용한다. 
 Format
    문 법 function Format(const Format: String; const Args: Array of const): String;
      서식 문자열과 뒤따라오는 변수에 의해 문자열을 포맷하는 함수이다. 계산식이나 회계분야에서는 가끔씩 써먹는 함수로서, 이러한 포맷도 지원하는구나하는 정도로 가볍게 받아두고 필요시 다시 살펴보는 방법이 가장 좋은 방법인것 같다.

C의 pintf함수와 사용방법이 유사하며 문자열 내부에 변수값을 삽입할 수 있는 아주 편리한 방법을 제공한다.
서식 문자열에는 일반 문자열과 서식이 삽입되며 일반 문자열은 그대로 출력되지만 서식은 대응되는 인수값으로 채워진다.

서식은 % 기호와 변수의 타입으로 이루어지며 % 와 타입 사이에 인덱스, 좌측 정렬 지정, 폭, 정밀도 지정이 삽입된다.

%[인덱스:][-][폭][.정밀도]타입 일단 Format함수를 사용하는 예를 들어보자...

Var A : Integer; S,
    St : String;
Begin
    A := 29;
    B := 'Lyon, Kim';
    St := Format('My age is %d, My Name is %s', [A,S]);
End;

서식 문자열에 포함된 %d 자리에는 정수형 변수인 A의 값인 29 가 삽입되며, %s 의 자리에는 문자열 변수인 S의 값 Lyon, Kim 이 삽입되는 방식이다.
그럼, 당연히 St 의 문자열은 My age is 29, My Name is Lyon, Kim 이 되는 것이다.

서식 문자열 내의 서식은 인수 리스트의 변수들과 순서대로 대응되며 서식의 개수와 인수의 개수가 일치해야 할뿐만 아니라 대응되는 서식과 변수의 타입도 일치해야만 한다.

만약 개수나 타입이 일치하지 않을 경우 컴파일은 가능하지만 실행중에 에러가 발생하게 된다. 폭 지정이란 변수값이 문자열 내부에서 차지하는 자리수를 지정하며 생략시는 변수값의 길이만큼만 자리를 차지한다. 강제로 자리를 늘리고자 할 경우 서식과 타입사이에 폭을 정수로 지정한다. 예를 들어 %5d 라고 하면 이 서식에 대입되는 정수가 5자리가 안되더라도 5자리를 강제로 차지한다.

단, 여기서 지정하는 폭 지정은 최소한의 폭을 의미할 뿐이며 폭값이 실제값보다도 작더라고 강제로 폭에 맞추지는 않는다. 예를 들어 I가 12345라는 다섯자리 값을 가지는데 %2d와 대응될 경우 폭지정 2를 지키기 위해 45만 출력하지 않으며 이경우는 폭 지정이 무시된다. 즉, I의 12만이 대응된다고 볼 수 있다.

정밀도 지정이란 실수에 사용되며 소수점 이하 몇 자리까지를 문자열로 바꿀 것인가를 지정한다. %10.5f 서식은 10자리를 차지하며 소수점 이하 5자리까지 문자열로 출력한다. 좌측 정력 지정은 폭이 변수값보다 길 경우 공백을 우측에 배치하도록 하며 폭 지정 앞에 '-' 기호를 붙여 표현한다.
%5d 에 대응되는 정수값이 만약 12일 경우 출력은 'bbb12' 가 되지만, 서식을 %-5d 로 변경하면 '12bbb'가 된다. 여기서 b 표시는 공백을 의미한다.

인덱스 지정자는 인수 리스트의 몇 번째 인수를 사용할 것인가를 지정하며 정수 하나와 ':' 을 사용한다. 인덱스 지정자가 없으면 인수 리스트에 나타나는 순서대로 서식과 대응되지만 인덱스를 밝힘으로써 중복되는 인수 리스트를 재사용할 수 있다.

예를 들어 '%d%d%d,1,2,3'은 앞쪽 서식부터 순서대로 정수 1,2,3로 대응되지만 '%d%d%0:d'는 앞쪽 둘은 순서대로 1,2에 대응되고 세번째 서식은 인덱스 지정에 의해 첫 번째 인수 1에 대응된다.

타입 문자는 아래와 같으며 대문자와 소문자를 구분하지는 않는다. 
      문 자 의 미
d 정수값 하나에 대응된다.
대응되는 변수는 반드시 정수이어야 한다.
e 실수값을 공학적 표기법, 즉 부동 소수점 형식으로 변환된다.
f 실수값을 부동 소수점 형식으로 변환한다.
g 실수값과 대응하되 고정 소수점 형식과 부동 소수점 형식 중 길이가 짧은쪽으로 변환한다.
n 실수값에 대응하며, 천단위로 콤마를 삽입해 준다.
p 포인터 값에 대응된다.
출력되는 문자열은 SSSS:0000 형태의 세그먼트, 오프셋 형태를 띄며 이때, 세그먼트, 오프셋은 모두 네 자리의 16진수를 사용한다.
m 실수값에 대응되며, 화폐 형태의 문자열로 변환한다.
s 문자열 변수, 문자 변수에 대응된다.
x 정수에 대응되며, 16진수 형태의 문자열로 변환된다.
 
 FormatDateTime
    문 법 function FormatDateTime(const Format: String; DateTime: TDateTime): String;
      TDateTime형의 변수에 저장된 시간과 날짜 정보를 특정한 형태의 문자열 포맷으로 변환하는 함수이다.
이 함수는 시스템의 날짜와 시간을 받아 사용하므로 Y2K 문제를 해결해 나갈 수 있는 아주 유용한 함수임을 알았으면 한다.

문자열로 출력되는 형식은 다음과 같은 지정자에 의해 결정되며 각 지정자는 한 칸 이상의 공백으로 구분되어야 한다. 포맷을 지정하는 Format 인수에는 지정자와 일반 문자열들이 올 수 있으며 일반 문자열들은 겹 따옴표로 싸 주어야 한다.
지정자의 대소문자는 구분하지 않는다.

아래는 FormatDateTime함수내에서 사용하는 문자들이다.
      지 정 자 의 미
c 전역변수 ShortDateFormat, LongTimeFormat이 지정하는 형식대로 출력되며 지정자가 생략될 경우의 디폴트 지정자이다. 
d 날짜값을 출력하되 선행 제로를 생략한다. (1~31)
dd 날짜값을 출력하되 선행 제로를 출력한다. (01~31)
ddd 요일을 생략형으로 출력한다. Sun, Mon, Sat 등과 같이 출력된다.
이 생략형 요일 이름은 ShortDayNames 변수에 의해 지정된다.
dddd 요일이름은 완전한 형식으로 출력한다.
Sunday, Monday 등과 같이 출력된다. 완전한 요일 이름은 LongDayNames변수에 의해 지정된다.
ddddd ShortDateFormat 전역 변수가 지정하는 형식으로 날짜가 출력된다.
dddddd LongDateFormat 전역 변수가 지정하는 형식으로 날짜가 출력된다.
m 월을 출력하되 선행 제로를 생략한다. (1~12)
mm 월을 출력하되 선행 제로를 출력한다. (01~12)
mmm 월 이름을 생략형으로 출력한다. Jan, Dec 등과 같이 출력한다.
이 생략형 월 이름은 ShortMonthName 변수에 의해 지정된다.
mmmm 월 이름은 완전한 형식으로 출력한다.
January, December 등과 같이 출력된다.
완전한 월 이름은 LongMonthName 변수에 의해 지정된다.
yy 년도를 두자리 숫자로 출력한다. (00~99)
yyyy 년도를 네자리 숫자로 출력한다. (0000~9999)
h 시간을 출력하되 선행 제로를 생략한다. (1~12)
hh 시간을 출력하되 선행 제로를 출력한다. (01~12)
n 분을 출력하되 선행 제로를 생략한다. (1~59)
nn 분을 출력하되 선행 제로를 출력한다. (01~59)
s 초를 출력하되 선행 제로를 생략한다. (1~59)
ss 초를 출력하되 선행 제로를 출력한다. (01~59)
t 시간값을 ShortTimeFormat 전역 변수가 지정하는 형식으로 출력한다.
tt 시간값을 LongtimeFormat 전역 변수가 지정하는 형식으로 출력한다.
am/pm 오전과 오후를 출력하며 h 나 hh 지정자의 시간을 12간제로 출력한다.
오전이면 am 이 출력되며 오후면 pm 이 출력된다.
대문자 소문자 모두 쓸 수 있으며, 혼합해서 쓸 수도 있다.
출력되는 결과는 이 지정자의 대소문자 구성을 따른다.
즉, Am/Pm 지정자를 쓰면 Am 이나 Pm 이 출력되며,
AM/PM 지정자를 쓰면 AM 이나 PM 이 출력된다. 
a/p 오전과 오후를 출력하며 h 나 hh 지정자의 시간을 12시간제로 출력한다.
오전이면 a 가 출력되며 오후면 p 가 출력된다.
대문자 소문자 모두 쓸 수 있으며 혼합해서 쓸 수도 있다.
출력되는 결과는 이 지정자의 대소문자 구성을 따른다.
ampm 12시간제로 시간을 출력하며 오전일 경우 전역 변수 TimeAmString에 저장된 문자열을 출력하며 오후일 경우 TimePmString에 저장된 문자열을 출력한다.
/ DataSeparator 지정자가 지정하는 날짜 구분 기호를 출력한다.
: TimeSeparator 지정자가 지정하는 시간 구분 기호를 출력한다.
 
    예 제 FormatDateTime('dddd mmmm d yyyy hh:mm AM/PM', Now);
FirDay December 24 1999 12:25 PM

FormatDateTime(' "지금시간은" ddd mmm d yyyy hh:mm AM/PM', Now);
지금시간은 Fri Dec 24 1999 12:26 PM
      
  



 


--------------------------------------------------------------------------------

 함수 레퍼런스 정리...(G) 
 GetDir
   문 법 procedure GetDir(D: Byte; Var S: String);
    지정한 드라이브의 현재 드렉토리를 조사하는 함수이다.

D로 드라이브의 번호를 지정하면 현재 디렉토리가 문자열 S 에 대입되며, 드라이브 번호 D 는 0 일 경우, 디폴트 드라이브 1일 경우 A, 2일 경우 B등과 같이 지정한다.
이 프로시져는 일체의 에러 체크를 하지 않는다.
만약 드라이브 번호로 주어진 D 가 존재하지 않을 경우 조사되는 디렉토리는 'X:/' 가 된다.

다음 예는 현재 드라이브의 디렉토리를 조사하여 레이블에 출력하는 예이다. 
   예 제 Var
    dir: String;
begin
    GetDir(0, dir);
    Label1.Caption := Dir;
end; 
 GetMem
   문 법 procedure GetMem(Var P: Pointer; Size: Word);
    동적으로 메모리를 할당하며 할당된 번지를 포인터형의 변수 P 에 대입하는 함수이다. Size 는 동적으로 할당할 메모리의 크기를 바이트 수로 나타내며, 할당된 메모리의 변수는 P^ 로 읽거나 쓸 수 있다. 
      

  
 함수 레퍼런스 정리...(H) 
 Halt
   문 법 procedure Halt[ (ExitCode: Word)];
    프로그램을 강제로 종료하고 운영체제로 제어권을 넘기는 함수이다.
Exitcode 는 프로그램의 탈출코드이다. 
 High
   문 법 function High(X);
    인수로 주어진 X 의 값 중 가장 큰값을 찾는다.
X 가 integer형이라면 결과는 32767이 되며 LongInt형이라면 결과는 2147483647이 된다. 결과값은 인수로 주어진 X와 동일한 형태이다.
다음 예는 열거형 중 가장 큰 값을 찾아내는 예제이다.
레이블로 출력되는 값은 6이다. 
    예 제 type
    Day = (sun, mon, tue, wed, thu, fri, sat);
Var
    i : Integer;
begin
    i := integer(High(Day));
    label1.Caption := IntToStr(i);
end;
      

  
 함수 레퍼런스 정리...(I) 
 Inc
   문 법 procedure Inc(Var X[N: Longint];
    변수의 값을 1 증가시키는 함수이다. Inc(X)는 X := X + 1 과 동일한 동작을 한다.
두 번째 인수를 사용하면 1 이상의 값을 증가시킬 수도 있다.
Inc(X, 5)는 X := X + 5 와 동일한 동작을 한다.
첫 번재 인수는 서수형의 변수이며 확장 문법이 적용될 경우 PChar형도 가능하다.
N 은 정수형의 상수 또는 변수여야 한다.
Inc 함수는 가장 최적화된 코드를 생성해 내므로 루프 내부에서 사용하기에 적합하다.
 Include
   문 법 procedure include(Var S: Set of T; I: T);
    집합형 S 에 요소 I 를 추가하는 함수이다.
Include(S, I) 는 S := S + (1) 와 동일한 동작을 하지만 좀 더 효율적인 코드를 생성해 낸다. 
 InputBox
    문 법 function InputBox(Const ACaption, APrompt, ADefault: String): String;
      문자열을 입력할 수 있는 대화상자를 보여주고 사용자에게 문자열을 입력받아 리턴한다. 인수의 의미는 인수의 이름을 참조하기 바란다.
아래의 예제는 사용자가 문자열을 입력후 Cancle 버튼을 누르면 디폴트 문자열이 리턴되며 OK 버튼을 누르면 에디트 박스에 입력된 문자열이 입력된다. 
    예 제 Var
    Str : String;
begin
    Str := InputBox('함수레퍼런스정리[I]','잘되죠?','Oh ! Yes');
end; 
    그 림 
 InputQuery
    문 법 function InputQuery(const ACaption, APrompt: String; Var Value: String): Boolean;
     문자열을 입력할 수 있는 대화상자를 보여주고 사용자에게 문자열을 입력받아 리턴한다. 대화상자가 열리면 아무것도 입력되어 있지 않은 빈 에디트를 보여주며 이 에디트에 사용자가 문자열을 입력한다.
입력된 결과는 리턴값으로 전달되며는 것이 아니라 참조호출로 전달된 Value로 전달되며 리턴값은 사용자가 누른 버튼의 종류이다.
아래의 예제는 사용자가 대화상자에서 어떤 버튼을 눌렀는가를 꼭 알아야 할 경우는 InputQuery 를 사용하며 단순히 문자열만 입력받고자 할 경우는 InputBox 를 사용하면 된다. 
    예 제 Var
    Str : String;
    Ans : Boolean;
begin
    Ans := InputQuery('함수레퍼런스정리[I]','이것도 잘되죠?',Str);
end; 
    그 림 
 Insert
   문 법 procedure Insert(Source: String; Var S: String; Index: Integer);
    한 문자열의 중간에 다른 문자열을 삽입하는 함수이다.
삽입되는 위치는 Index 인수가 지정하는 위치이다.
문자열을 삽입한 후의 문자열 길이가 255 자를 넘을 경우 255 문자 이후의 문자는 잘려진다.
Dest 문자열이 'Orange' 이고, Src 문자열이 'Apple' 인 경우 Insert(Src, Dest, 3); 는 Dest 문자열의 3번째 문자인 a 위치에 Src 문자열을 삽입하며 Dest 문자열은 'OrAppleange' 가 된다.
아래 예제는 레이블로 abcdhotdogefghijkl 문자열이 출력된다. 
   예 제 Var
    S : String;
begin
    S := 'abcdefghijkl'; Insert('hotdog', S , 5);
    label1.Caption := S;
end;
 Int
   문 법 function Int(X: Real): Real;
    실수 X의 정수부를 구하는 함수이다.
소수부는 반올림되지 않으며 버려진다.
Int(3.14) 는 3 의 값을 반납한다.
주의할 것은 Int 함수의 리턴값은 정수값을 담지만 데이터형은 여전히 실수형이라는 점이다.
 IntToHex
   문 법 function IntToHex(Value: Longint; Digits: Integer): String; 
    10 진 정수값을 16진수 형태의 문자열로 바꾸어 문자열을 리턴하는 함수이다.
예를 들어 IntToHex(100, 2) 명령에 의해 십진수 100을 16진수로 바꾼 문자열 '64'가 리턴된다. Digits 인수는 만들어질 16진수의 자리수를 지정한다.
그러나 이 값은 최소한의 자리수를 지정할 뿐이며 자리수보다 16진수의 크기가 더 많을 경우는 이 인수값은 무시된다.
즉, IntToHex(100, 3)에 의해 최소한 세 자리를 할당하여 '064'가 리턴되지만 IntToHex(100, 1)로 한다고 하면 두 자리의 16진수를 강제로 한 자리 숫자로 만들지는 않는다는 것이다.
 IntToStr
   문 법 function IntToStr(Value: LongInt): String;
    정수를 문자열로 바꾸어 리턴하는 함수이다.
정수값을 레이블이나 에디트박스에 출력하고자 할 경우 직접 그 값을 출력할 수는 없다.
왜냐하면 레이블의 Caption 속성이나 에디트의 Text 속성은 문자열형이므로 정수형 값을 대입받을 수 없기 때문이다.
정수값을 문자열로 바꾸고자 할 경우에는 이 함수를 사용한다. 
 IOResult
   문 법 function IOResult: Integer;
    마지막 입출력 동작에서 발생한 상태값을 조사한다.
이 함수를 사용하여 입출력 에러를 검사하려면 {$I-} 옵션을 반드시 꺼 주어야 한다.
IOResult 함수를 호출하면 내부적인 에러값은 리셋된다.
이 함수가 리턴하는 값이 0 이면 에러가 없다는 것이다.

  
 함수 레퍼런스 정리...(K) 
 KeyPressed
   문 법 function KeyPressed: Boolean;
    키보드에서 키가 눌러지면 True 를 리턴하며, 키가 눌러져 있지 않으면 False 를 리턴하는 함수이다.
ReadKey 함수로 키 값을 읽기 전에 키가 눌러져 있는지 점검해 볼 때 사용한다.
     

  
 함수 레퍼런스 정리...(L) 
 Length
   문 법 function Length(S: String): Integer;
    주어진 문자열의 길이를 구하는 함수이다.
Length('Korea') 는 5의 값을 리턴한다. 
 LowerCase
   문 법 function LowerCase(Const S: String): String;
    문자열 내부의 대문자를 모두 소문자로 바꾸어주는 함수이다.
문자 변환은 7비트의 아스키 코드 내에서 이루어지며 문자 'A' ~ 'Z' 까지가 변환의 영향을 받는다.
나머지 기호나 숫자, 한글은 변환되지 않는다. 
     
  





--------------------------------------------------------------------------------


 함수 레퍼런스 정리...(M) 
 MessageDlg
   문 법 function MessageDlg(Const msg: String; AType: TMsgDlgType;
         AButtons: TMsgDlgButtons; HelpCtx: LongInt): Word;
    Message를 전달하는 대화상자를 보여주며 사용자로부터 응답을 받아들여 리턴하는 함수이다.
Msg 문자열이 Message의 내요이며 AType에 의해 Message 상자의 형태와 캡션에 출력된 문자열이 결정된다. 
      값 형 태
mtWarning 노란색 느낌표 비트맵이 나타난다. [그림참조]
mtError 빨간색의 엑스 비트맵이 나타난다. [그림참조]
mtInformation 파란색의 i 자 비트맵이 나타난다. [그림참조]
mtConfirmation 물음표 비트맵이 나타난다. [그림참조]
mtCustom 비트맵을 사용하지 않는다. [그림참조]
 
      
      
      ABotton 인수는 Message 상자에 나타날 버튼의 종류를 지정하며 여러개의 버튼을 집합형으로 전달한다.
리턴값은 사용자가 대화상자에 나타난 버튼 중 어떤 버튼을 눌렀는가를 나타내는 값이다. 
      버튼 기턴 값
mbYes mrYes
mbNo mrNo
mbOK mrOK
mbCancel mrCancel
mbHelp 
mbAbort mrAbort
mbRetry mrRetry
mbIgnore mrIgnore
mbAll mrAll
 
      버튼 이름을 일일이 지정해 주는 것이 번거로우면 미리 정의 되어 있는 다음과 같은 집합명을 사용해도 무방하다.
       
      mbYesNoCancel 은 Yes, No, Cancle 버튼을 한꺼번에 보여주고,
mbOkCancel 은 Ok, Cancle 버튼을 한꺼번에 보여준다.
mbAbortRetryIgnore 는 Abort, Retry, Ignore 버튼을 한꺼번에 보여준다.

이 집합명은 그 자체가 집합형이므로 [] 괄호를 쓰지 않아도 된다. 
       
    예 제 If MessageDlg(('Ok 누르면 실행합니다.'), MtInformation, mbOkCancel, 0) = mrOk Then
    label1.caption := 'Ok 를 눌렀군요...'
else
    label1.caption := 'Cancel 을 눌렸군요...';

위의 예제는 MessageDlg를 사용하는 방법에 대해 간단히 알아볼 수가 있다.
만약, ABotton인수에 현재는 mbOkCancel 을 넣었지만, 여러개의 버튼을 넣는다면,
[mbOk, mbCancel] 을 입력해도 똑같은 결과를 나타낸다.
여러개를 한꺼번에 쓸 때는 '[ ]' 안에 넣어야만 하고 집합형일 경우는 그냥 쓰면 된다는 아주 간단한 예제이다.
아래 그림은 실행한 화면의 MessageDlg 예제였다.
    그 림 
 MessageDlgPos
    문 법 function MessageDlgPos(Const Msg: String; AType: TMsgDlgType; AButtons:
         TMsgDlgButtons; HelpCtx: LongInt; X, Y: Integer): Word;
      MessageDlg 함수와 동일한 동작을 하는 함수이다.
단 MessageDlg는 대화상자를 무조건 화면 중앙에 열어주지만 이 함수는 X, Y 인수를 사용하여 대화상자가 출력된 화면 좌표를 지정할 수 있다. 
 MkDir
    문 법 procedure MkDir(S: String);
      새로운 서브 디렉토리를 생성한다.
문자열 S에 생성하고자 하는 서브 디렉토리의 경로를 준다.
디렉토리를 생성하는 규칙은 도스에서와 동일하다.
즉, 같은 이름의 디렉토리나 화일이 있어서는 안된다. 
     
 
 함수 레퍼런스 정리...(N) 
 Now
   문 법 function Now: TDateTime;
    현재 날짜와 시간을 한꺼번에 구하는 함수이다.
날짜와 시간은 TDateTime형이므로 곧바로 문자열로 출력할 수 없으며 DateTimeToStr함수를 사용하여 문자열로 바꾸어 주어야 한다.
Label1.Caption := DateTimeToStr(Now); 명령에 의해 Label1에 오늘 날짜와 시간이 출력된다. StrToDate 문자열을 날짜 형태로 바꾸어 TDateTime형의 변수에 저장해 준다.
문자열에 저장된 날짜는 반드시 유효한 날짜 정보를 가지고 있어야 하며 만약 날짜가 무효할 경우 EConverError 예외를 발생시킨다.
문자열은 년, 월, 일을 나타내는 두 개 또는 세 개의 숫자를 담고 있어야 하며 각 요소는 DataSeparator 변수가 지정하는 구분문자(보통 슬래시 기호)에 의해 구분되어 있어야 한다. 년, 월, 일의 순서는 ShortDateTime 변수에 따라 달라지며 mm/dd/yy 또는 dd/mm/yy 또는 yy/mm/dd 중 하나가 된다.
만약 문자열에 두 개의 숫자만 있으면 이는 각각 월, 일의 정보로 인식되며 년은 올해의 년도가 된다. 
     
  
 함수 레퍼런스 정리...(O) 
 Odd
   문 법 function Odd(X: LongInt): Boolean;
    인수로 주어진 정수가 홀수인지를 검사하는 함수이다.
만약, 홀수이면 True값을 리턴하며, 짝수이면 False값을 리턴한다.
다음예는 인수로 주어진 정수값 I 가 홀수인지 짝수인지를 검사하여 레이블로 출력하는 예제로서 I에 3을 대입하면 '홀수입니다.'라는 메세지를 레이블로 출력하는 예제이다. 
    예 제 Var
    I : Integer;
begin
    I := 3;
    If Odd(I) Then
        Label1.Caption := '홀수입니다.'
    Else
        Label1.Caption := '홀수가 아닙니다.';
end; 
 Ord
   문 법 function Ord(X): LongInt;
    순서형값의 순서값을 조사하는 함수로서, 다음예제는 열거형의 열거요소중 Soo가 몇번째 값인지를 조사하는 예제이다. 여기서의 순서값은 2가 출력된다. 
    예 제 Type
    Yoil = (Wol,Hwa,Soo,Mok,Gum,TTo,Il);
begin
    Label1.Caption := 'Soo Member Is ' + IntToStr(Ord(Soo));
end; 
     
 
 함수 레퍼런스 정리...(P) 
 Pi
   문 법 function Pi: Real;
    원주율을 구하는 함수이다.
원주율은 3.1415926535897932385...로 정의되어 있으며 이값은 부동 소수점 연산 보조 프로세서가 있는지 없는지에 따라 정확도가 달라질 수 있다. 
 Pos
   문 법 function Pos(SubStr: String; S: String): Byte;
    문자열내의 부분 문자열을 검색하는 함수이다.
부분 문자열이 검색된 위치를 리턴해 주며, 만약 부분 문자열이 발견되지 않으면 리턴값은 0 이다. 이 함수는 문자열 검색에서 탁월한 성능을 발휘한다.
자세한 사항은 도움말을 참고하기 바란다. 
     
 
 함수 레퍼런스 정리...(R) 
 ReadKey
   문 법 function ReadKey(Buffer: PChar; Count: Word): Word;
    키보드로부터 문자값을 읽는 함수이다.
단, 이 함수는 표준 ASCII 코드만을 읽을뿐 기능키나 커서 이동키 등의 확장키 코드는 읽지 못한다. 
 Readln
   문 법 procedure Readln([Var F; Text;] V1[V2,...,Vn]);
    파일로부터 문장 한 줄을 읽어 변수 V1이하에 대입하며 다음 문장으로 이동하는 함수이다. Readln(F)와 같이 읽어들일 변수를 지정하지 않으면 다음 줄로 이동하기만 한다.
파일 변수가 생략될 경우는 표준 입력 장치인 키보드로부터 문자열을 입력받아 V1이하의 변수에 대입한다.
인수없이 Readln만 사용되면 Enter키가 입력될 때까지 대기한다.
다음 예는 키보드로부터 문장을 입력받아 다시 레이블로 출력하는 예제이다. 
   예 제 Var
    S : String;
begin
    Write('문장을 입력하세요');
    Readln(S);
    Label1.Caption := S;
end; 
 Rename
   문 법 procedure Rename(Var F: Newname);
    파일의 이름을 변경하는 함수이다.
변경하고자 하는 이름을 문자열로 전달해 주면 된다.
파일명을 변경하려면 AssignFile 함수로 파일 핸들에 외부 파일명을 할당해 주고 이 함수를 호출하면 되는데, 파일을 오픈할 필요까지는 없다. 
 ReWrite
   문 법 procedure ReWrite(Var F; File [;Recsize: Word]);
    파일을 쓰기 전용으로 오픈하는 함수이다.
F는 AssignFile함수로 외부파일과 연결된 파일 핸들이며 RecSize는 F가 untyped 파일일 경우 한번에 출력할 레코드의 크기를 지정한다.
RecSize가 생략될 경우 이 값은 128바이트로 간주된다.
파일이 없을 경우에는 파일을 생성하고 파일이 이미 열려져 있으면 파일을 닫은 후에 다시 생성하며 파일 위치는 파일의 선두에 맞추어 진다.
이 함수로 파일을 오픈할 후에 Writeln등의 함수로 데이터를 파일로 출력하게 된다.
다음 예는 Test.txt라는 간단한 파일을 만든후 문자열 하나를 출력하는 예제이다.
파일 입출력이 끝난 후에 파일 핸들은 반드시 Closefile 프로시져로 닫아 주어야 한다. 
   예 제 Var
    F : TextFile;
begin
    AssignFile(F, 'Test.txt');
    ReWrite(F);
    Writeln(F, '출력할 내용을 쓴다.');
    CloseFile(F);
end; 
 RmDir
   문 법 procedure RmDir(S : String);
    서브 디렉토리를 삭제하는 함수이다.
삭제할 디렉토리명을 문자열로 넘겨주는데, 도스의 RM 명령과 거의 동일한 규칙을 사용하며 디렉토리가 비어 있지않을 경우, 현재 디렉토리인 경우, 루트 디렉토리인 경우는 디렉토리를 삭제할 수 없다. 
 Round
   문 법 function Round(X : Real): LongInt;
    실수값 X 를 정수값으로 만들어주는 함수이다.
즉, 실수의 소수부분을 버리고 정수 부분만 결과로 취한다.
이때 소수부 첫째 자리에서 반올림이 일어나며 반올림의 결과는 부호와 상관없이 일어난다. 반올림의 결과와 LongInt형의 범위를 벗어날 경우는 실행시 에러가 발생한다.
다음 예제는 실수 3.1415 를 반올림하여 정수로 만드는 예제로서 레이블의 출력결과는 소수부가 잘려나간 3이되며, 만약 실수의 값이 3.6415일 경우는 반올림에 의해 4가 출력된다. 
   예 제 Var
    F : Double;
begin
    F := 3.1415;
    Label1.Caption := IntToStr(Round(F));
end; 
 RunError
   문 법 procedure RunError[(ErrorCode: Byte)];
    실행시 에러를 발생시키고 프로그램을 종료하는 함수이다.
치명적인 에러가 발생했을 경우 이 함수를 이용한다. 
     
   





--------------------------------------------------------------------------------


 함수 레퍼런스 정리...(S) 
 Seek
   문 법 procedure Seek(Var F; N: LongInt);
    파일의 현재 위치(FP)를 N위치로 옮긴다.
Untyped 파일일 경우 N의 의미는 파일 선두에서의 바이트 단위 거리이지만 Typed파일일 경우 N은 N번째 요소의 위치를 의미한다.
예를 들어 레코드형 파일일 경우 N이 5이면 여섯 번재의 레코드의 위치로 이동한다. 첫번째 레코드의 번호가 0번이다.
Seek(F,FileSize(F))는 파일의 끝으로 현재위치를 이동시킨다. 
 SeekEof
   문 법 function SeekEof[(Var F: Text)]: Boolean;
    파일의 현재위치가 끝(EOF)인지 점검한다.
 SeekEoln
   문 법 function SeekEoln[(Var F: Text)]: Boolean;
    파일의 현재위치가 줄의 끝(EOL)인지 점검한다.
 SelectDirectory
   문 법 function SelectDirectory(Var Directory: String; Options: TSelectDirOpts; HelpCtx:
LongInt): Boolean;
    디렉토리 선택 대화상자를 보여주고 사용자로 하여금 디렉토리를 선택하도록 한다.
드라이브 콤보박스와 디렉토리 리스트 박스를 사용하여 디렉토리를 선택하며 파일 리스트 박스는 어떤 파일이 있는지만 보여준다.
디렉토리를 선택하는 것뿐만 아니라 에디트박스에 디렉토리명을 입력하여 없는 디렉토리를 직접 생성할 수도 있다.
인수로 주어지는 Directory문자열은 대화상자가 처음 열릴때 선택될 디렉토리이며 사용자가 대화상자에서 선택한 디렉토리명이 인수로 리턴된다.
사용자가 OK버튼을 누르면 True를 리턴하고 Cancle버튼을 누르면 False를 리턴한다.
두번째 인수 Options는 대화상자의 모양과 기능을 정의하는 옵션이며 다음과 같은 값의 집합형이다. 
  옵 션 의 미
  [] 사용자는 존재하는 디렉토리를 선택할 수 있을 뿐이며 없는 디렉토리를 만들 수 없다.
  sdAllowCreate 에디트 박스에 사용자가 직접 존재하지 않는 디렉토리를 입력하는 것을 허용한다.
그러나 이 옵션을 사용한다고 해서 디렉토리를 생성해 주는 것은 아니며 사용자가 직접 Directory 인수를 참조하여 생성해 주어야 한다.
  sdPerformCreate 이 옵션을 sdAllowCreate 옵션과 함께 사용할 경우 존재하지 않는 디렉토리가 입력되면 직접 디렉토리를 만들어 준다.
  sdPrompt 디렉토리를 새로 만들기 전에 사용자로부터 디렉토리를 정말로 만들 것인가를 물어본다.
   예 제 Uses 절에 FileCtrl 를 추가해야만 한다.

Var
    Dir: String;
begin
    Dir := 'C:/DELPHI';
    If SelectDirectory(Dir, [sdAllowCreate, sdPerformCreate, sdPrompt], 0) then
        Label1.Caption := Dir;
end;

디렉토리 선택 대화상자의 모습은 아래와 같다. 
    그 림 
 SizeOf
   문 법 function SizeOf(X): Word;
    X의 크기를 바이트 단위로 리턴하는 함수이다. X는 변수이거나 데이터 타입이다. SizeOf(Integer)는 2이며, SizeOf(Double)은 8 이다.
주로 레코드나 오브젝트 등 크기가 큰 데이터의 크기를 계산할 때 사용한다. 가상 메소드 테이블을 가진 오브젝트의 인스턴스크기를 조사하면 VMT에 저장된 크기가 리턴된다. 
 Sqr
   문 법 function Sqr(X: Real): Read;
    X의 제곱값을 구하는 함수이다. Sqr(X)는 X*X와 동일한 결과를 계산해 낸다. 
 Sqrt
   문 법 function Sqrt(X: Real): Real;
    X의 제곱근을 구하는 함수이다. Sqrt(2)는 1.414213이다.
이때 계산되는 제곱근은 양의 제곱근이다. 
 Str
   문 법 procedure Str(X[: Width [: Decimals]]; Var S);
    숫자값 X를 문자열 S로 출력하는 함수이다. 이때 출력되는 값의 폭은 Width 인수가 지정하는 폭을 사용하며 Decimals인수가 지정하는 정밀도를 사용한다. 숫자값 X는 정수형이거나 실수형 모두 가능하다. 다음예는 3.1415를 폭 5, 정밀도 3으로 문자열로 변환하는 예제이다. 이때, 레이블로 출력되는 문자열은 3.142이다. 
   예 제 Var
    F : Double;
    S : String;
begin
    F := 3.1415;
    Str(F:5:3, S);
    Label1.Caption := S;
end; 
 StrCat
   문 법 function StrCat(Dest, Source: PChar): PChar;
    두개의 문자열을 연결하는 함수이다.
Source문자열을 Dest문자열에 추가하며 연결된 문자열을 리턴한다.
문자열의 길이 점검은 하지 않으므로 Dest문자열이 Source의 문자열을 충분히 수용할만한 크기를 가지도록 해야한다. 다음 예제는 두개의 문자열을 결합하는 예제로서 레이블로 출력되는 결과는 Made In Korea 이다. 
   예 제 Var
    S1 : Arrary[0..128] of Char;
    S2 : Arrary[0..128] of Char;
begin
    StrCopy(S1,'Made In ');
    StrCopy(S2.'Korea');
    trCat(S1,S2);
    Label1.Caption := StrPas(S1);
end; 
 StrComp
   문 법 function StrComp(Str1, Str2: PChar): Integer;
    두개의 문자열을 비교하는 함수이다.
S1과 S2문자열이 같으면 0을 리턴하며, S1S2이면 양수를 리턴한다.
문자열끼리의 비교는 문자열을 이루는 각 문자의 문자코드를 비교하여 수행한다. 
 StrCopy
   문 법 function StrCopy(Dest, Source: PChar): PChar;
    널 종료 문자열을 복사하는 함수이다.
Source문자열을 Dest문자열에 복사하며 Dest문자열을 리턴한다.
이 함수는 문자열의 길이점검을 하지 않으므로 Dest문자열의 길이가 Source문자열의 길이보다 짧지 않도록 주의해야 한다. 만약 Dest문자열의 길이가 Source문자열을 충분히 수용하지 못할 경우 Dest 뒷부분의 다른 변수값이 파괴된다.
널 종료 문자열끼리는 := 연산자에 의해 직접 대입할 수 없으므로 이 함수를 사용하여 문자열끼리 복사해 주어야 한다.
예를 들어 Source가 'Korea'이고 이 값을 Dest문자열로 대입하고 싶다고 해서
Dest := Source와 같은 문장을 쓸수는 없다.
이때는 StrCopy(Dest, Source)와 같이 StrCopy함수를 사용하여야 한다. 
 ShowMessage
   문 법 procedure ShowMessage(Const Msg: String);
    대화상자를 열어 Msg 문자열을 보여주기만 하며 OK버튼을 누르면 대화상자를 닫는다.
캡션에는 이 대화상자를 호출한 프로그램의 실행파일이름을 출력한다. 간단한 메세지만을 전달하고 사용자의 입력을 받아야 할 필요가 없을 때 이 함수를 자주 사용한다. 
   예 제 ShowMessage('ShowMessage 함수의 실행화면입니다.');
   그 림 
 ShowMessagePos
   문 법 procedure ShowMessagePos(Const Msg: String; X, Y: Integer);
    ShowMessage프로시져와 동일한 동작을 하는 함수이다.
하지만 ShowMessage는 대화상자를 무조건 화면 중앙에 열어주지만 이 ShowMessagePos함수는 X, Y인수를 사용하여 대화상자를 출력될 화면좌표를 지정할 수 있다. 
 StrLower
   문 법 function StrLower(Str: PChar): PChar;
    주어진 문자열을 소문자로 바꾼다.
 StrToDate
   문 법 function StrToDate(Const S: String): TDateTime;
    문자열을 날짜 형식으로 바꿔어주는 함수이다.
문자열은 날짜 형식으로 되어 있어야 한다. 즉, 문자열 안에는 날짜를 이루는 세가지 요소가 순서에 맞게 배치되어 있어야 하며 각 요소는 날짜 구분 문자(/)로 분리되어 있어야 한다.
문자열에 날짜로 변경할 수 없는 문자가 있을 경우 EConvertError 예외가 발생한다. 
 StrToDateTime
   문 법 function StrToDateTime(Const S: String): TDateTime;
    문자열은 날짜와 시간을 담는 TDateTime형의 변수로 바꿔어주는 함수이다. 문자열에는 MM/DD/YY HH:MM:SS 형태로 날짜와 시간이 담겨 있어야 하며 시간값은 24시간제로 표현하거나 AM, PM을 추가로 뒤에 붙여주어야 한다. 
 StrToFloat
   문 법 function StrToFloat(Const S: String): Extended;
    문자열을 실수값으로 변환하는 함수이다. 문자열에는 부호를 나타내는 +/- 와 숫자, 그리고 소수점만 있어야 하며 지수를 나타내는 E가 올 수 있다.
그 외의 문자가 있을 경우는 EConvertError예외가 발생한다. 
 StrToInt
   문 법 function StrToInt(Const S: String): LongInt;
    문자열을 정수값으로 변환하는 함수이다. 이때 문자열에는 숫자로 바꿀 수 없는 문자가 있어서는 안되며, 만약 무효한 문자가 있을 경우 EConvertError예외를 발생시킨다.
에디트박스에 사용자가 입력한 값을 정수형 변수에 대입하고자 할 때 에디트 박스의 Text속성과 정수형 변수의 데이터형이 일치하지 않아 대입이 불가능하다.
문자열에 입력된 정수를 정수형 값으로 바꾸어 주어야 정수형 변수에 대입할 수 있다. 
 StrToTime
   문 법 function StrToTime(Const S: String): TDateTime;
    문자열을 시간 형태로 바꾸어 TDateTime형의 변수에 저장해 두는 함수이다. 문자열에는 HH:MM:SS 형태로 시, 분, 초가 담겨 있어야 하며, AM,PM은 있어도 되고 없어도 된다.
시간은 반드시 24시간 형태로 표시해 주어야 한다.
예를 들어 오후 8:30 은 20:30으로 표현하는데, 만약 문자열에 무효한 시간값이 들어있을 경우에는 EConvertError예외를 발생한다. 
 StrUpper
   문 법 function StrUpper(Str: PChar): PChar;
    주어진 문자열을 대문자로 바꿔주는 함수이다.
       
 
 함수 레퍼런스 정리...(T) 
 Time
   문 법 function Time: TDateTime;
    시스템의 시계를 참조하여 현재 시간을 구하는 함수이다.
시간은 TDateTime형이므로 곧바로 문자열로 출력할 수 없으며 TimeToStr함수를 사용하여 문자열로 바꾸어 주여야 한다. Label1.Caption := TimeToStr(Time) 명령에 의해 Label1에 현재시간이 출력된다. 
 TimeToStr
    문 법 function TimeToStr(Time: TDateTime): String;
      시간을 나타내는 Time을 문자열 형태로 변경하는 함수이다.
시간값을 곧바로 레이블이나 에디트등으로 출력할 수 없기 때문에 이 함수를 사용하여 문자열로 변경해 주어야 한다. 
 Trunc
   문 법 function Trunc(X: Real): LongInt;
    실수의 소수점 이하를 버리고 정수부만 취하는 함수이다. Round함수는 소수점 첫째자리에서 반올림을 하지만 이 Trunc함수는 반올림없이 무조건 소수점을 버린다.
다음 예는 3.6415를 정수부분만을 취하여 레이블에 3을 출력하는 예제이다. 
   예 제 Var
    F : Double;
begin
    F := 3.6415;
    Label1.Caption := IntToStr(Trunc(F));
end;
       
 
 함수 레퍼런스 정리...(U) 
 UpCase
   문 법 function UpCase(Ch: Char): Char;
    문자 Ch를 대문자로 바꿔주는 함수이다.
소문자 a 에서 대문자 Z 까지의 문자가 대문자 A ~ Z 로 변경되며 그 외 나머지 문자일 경우는 전혀 영향을 받지 않는다. 
 UpperCase
   문 법 function UpperCase(const S: string): string;
    문자열 내부의 소무낮를 모두 대문자로 바꾸어 주는 함수이다.
문자 변환은 7 비트의 아스키코드내에서 이루어지며 문자 'A' ~ 'Z' 까지가 변환의 영향을 받는다. 나머지 기호나 숫자, 한글은 변환되지 않는다. 
     
 
 함수 레퍼런스 정리...(V) 
 Val
   문 법 procedure Val(S; var V; var Code: Integer);
    문자열 변수 S 를 숫자형 변수로 바꾸어 주는 함수이다.
문자열 변수 S 에는 숫자가 담겨 있어야 한다.
문자열을 바꾼 결과를 받기위한 인수 V는 정수형이거나 실수형 변수 모두 가능하다.
S에 숫자로 바꿀 수 없는 무효 문자가 없다면 Code 값은 0 가 된다.
널 종료 문자열의 경우 Code에 리턴되는 에러 위치는 실제문자의 위치보다 하나가 더 많은 값이 된다. 
       
 
 함수 레퍼런스 정리...(W) 
 Write
   문 법 procedure Write([Var F: Text;] P1[,P2,...,Pn]);
    변수값을 파일로 출력하는 함수이다.
F 는 출력용으로 오픈된 텍스트파일이어야 하며 파일이 생략될 경우 표준 출력 장치인 화면으로 출력된다.
파일 변수 다음의 이수 P1 이하는 파일로 실제 출력될 값들이며, 이 값에 필드 폭, 정밀도를 지정할 수 있다.
출력할 수 있는 타입은 문자형, 정수형, 실수형, 문자열, 진위형 등이 있다.
타입도 파일일 경우 출력되는 변수 V1 이하는 파일의 요소와 같은 형이어야 한다.
즉, 레코드형 파일이라면 출력되는 값도 같은 형의 레코드이여야 한다. 파일의 현재 위치가 파일의 끝이라면 파일의 크기는 출력된 데이터의 길이만큼 늘어난다. 
 Writeln
    문 법 procedure Writeln([Var F: Text;] P1[,P2,...,Pn]);
      write 함수의 기능을 확장한 함수이다.
Write 를 호출하여 변수를 파일로 출력하되 변수 값 다음에 EOL (End Of Line)을 출력하여 자동으로 개행되도록 한다.

신고
Posted by 나비 나비:D

델파이6 기준으로 TexcelApplication,
TExcelWorkbook, TExcelWorksheet, TexcelChart 올려놓고 실행하면 됩니다.

uses절에 Activex 추가하시고 다음과 같이 코딩하면 됩니다.

unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, excel2000, OleServer, Activex;

type
  TForm1 = class(TForm)
    Button1: TButton;
    ExcelApplication1: TexcelApplication;
    ExcelWorkbook1: TexcelWorkbook;
    ExcelWorksheet1: TexcelWorksheet;
    ExcelChart1: TexcelChart;
    procedure Button1Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.Button1Click(Sender: TObject);
var
  LCID,i : Integer;
  Sheet, Selection : Variant;
  Format : OleVariant;
  //차트용
  ChObj: ChartObject;
  SheetType: OleVariant;
  Rnge, ChType: OleVariant;
  Ax: Axis;
begin
  excelApplication1.Connect; //엑셀을 가동한다.(InVisible 상태)
  ExcelWorkbook1.connectto(excelApplication1.workbooks.add(TOleEnum(xlWBATWorksheet), LCID));
  ExcelWorksheet1.connectto(excelWorkbook1.worksheets.item['Sheet1'] as _worksheet );

  //워크시트 이름 변경
  excelWorksheet1.Name := '날 죽여라';
  excelApplication1.DisplayAlerts[LCID] := False;
  excelApplication1.Visible[LCID] := true;
  Sheet := ExcelApplication1.WorkBooks[ExcelApplication1.Workbooks.Count].WorkSheets[excelWorkbook1.Worksheets.Count];
  Sheet.Cells[1,1] := '엑셀서식';
  excelApplication1.Range['A1','A1'].borders.lineStyle := 1;
  excelApplication1.Range['A1','A1'].borders.Color := clNavy;
  excelApplication1.Range['A1','A1'].Interior.Color := clYellow;


  //폰트변경
  excelApplication1.Range[Sheet.Cells[1,1],Sheet.Cells[1,1]].font.bold := true;
  excelApplication1.Range[Sheet.Cells[1,1],Sheet.Cells[1,1]].font.Size := 20;
  excelApplication1.Range[Sheet.Cells[1,1],Sheet.Cells[1,1]].font.Name := '±A¼­';

  //우측정렬(가로정렬)
  excelApplication1.Range[Sheet.Cells[1,1],Sheet.Cells[1,1]].HorizontalAlignment := xlHAlignRight;


  //가운데정렬(세로정렬)
  excelApplication1.Range['B1','B1'].VerticalAlignment := xlHAlignCenter;

  //범위로 찍을 경우
  excelApplication1.Range['B1','C2'].Value := '123456789';

  //숫자형 포맷
  Format := '_-* #,##0.0_-;-* #,##0.0_-;_-* "-"???_-;_-@_-';

  '@'; //  테스트형식

  #,##0.0 // 숫자형식
  excelApplication1.Range['B1','B1'].NumberFormatLocal := Format;

  Sheet.Range['B2', 'C2'].Interior.Color := RGB(223, 123, 123);
  excelApplication1.Range['B4', 'C4'].Interior.Color := clSilver;

  //날짜 찍기
  Sheet.Cells[5,1] := '2002/5/6';
  Sheet.Cells[5,2] := '2002/5/6';

  //숫자형
  Sheet.Cells[5,3] := '12345';
  Sheet.Cells[5,4] := '12345';

  //날짜포맷
  Format := 'yyyy-mm-dd';
  excelWorksheet1.Range[Sheet.Cells[5,1], Sheet.Cells[5,1]].NumberFormat := Format;

  Format := 'mmmm d, yyyy';
  excelWorksheet1.Range[Sheet.Cells[5,2], Sheet.Cells[5,2]].NumberFormat := Format;

  // 스트링형으로 변경
  Format := '@';
  excelWorksheet1.Range[Sheet.Cells[5,3], Sheet.Cells[5,3]].NumberFormat := Format;

  excelWorksheet1.Range['B11','B11'].VerticalAlignment := xlHAlignCenter;
  excelWorksheet1.Range['B11','B11'].HorizontalAlignment := xlHAlignRight;
  excelWorksheet1.Range['B11','B11'].Value := '셀병합후 가운데(세로) 정렬';
  excelWorksheet1.Range['B11','B13'].MergeCells := true;
  excelWorksheet1.Range['B11','B13'].borders.LineStyle := 2;

  excelWorksheet1.Range['B15','B15'].borders.lineStyle := 0;
  excelWorksheet1.Range['B15','B15'].HorizontalAlignment := xlHAlignRight;
  excelWorksheet1.Range['B15','B15'].Value := '셀병합후 우측(가로) 정렬';
  excelWorksheet1.Range['B15','D15'].MergeCells := true;
  excelWorksheet1.Range['B15','D15'].borders.LineStyle := 1;

  excelWorksheet1.Range['F15','G20'].MergeCells := true;
  excelWorksheet1.Range['F15','F15'].Value := '다중셀병합';
  excelWorksheet1.Range['F15','G20'].MergeCells := true;
  excelWorksheet1.Range['F15','F15'].HorizontalAlignment := xlHAlignCenter;
  excelWorksheet1.Range['F15','F15'].VerticalAlignment   := xlHAlignCenter;
  excelWorksheet1.Range['F15','G20'].borders.Weight := 4;

  //라인 스타일
  for i := 0 to 13 do
  begin
    excelWorksheet1.Range['B'+inttostr((2*i)+16),'B'+inttostr((2*i)+16)].borders.lineStyle := i;
    excelWorksheet1.Range['B'+inttostr((2*i)+16),'B'+inttostr((2*i)+16)].Value := 'borders.lineStyle := '+inttostr(i);
  end;

  //border Weight
  for i := 1 to 4 do
  begin
    excelWorksheet1.Range['B'+inttostr((2*i)+42),'B'+inttostr((2*i)+42)].borders.lineStyle := 1;
    excelWorksheet1.Range['B'+inttostr((2*i)+42),'B'+inttostr((2*i)+42)].borders.Weight := 1;
    excelWorksheet1.Range['B'+inttostr((2*i)+42),'B'+inttostr((2*i)+42)].Value := 'borders.Weight := '+inttostr(i);
  end;

  //라인 위치
  excelWorksheet1.Range['D18','D18'].borders.Item[1].LineStyle := 1;
  excelWorksheet1.Range['D18','D18'].Value := 'borders.Item[1].LineStyle := 1';
  excelWorksheet1.Range['D20','D20'].borders.Item[2].LineStyle := 1;
  excelWorksheet1.Range['D20','D20'].Value := 'borders.Item[2].LineStyle := 1';
  excelWorksheet1.Range['D22','D22'].borders.Item[3].LineStyle := 1;
  excelWorksheet1.Range['D22','D22'].Value := 'borders.Item[3].LineStyle := 1';
  excelWorksheet1.Range['D24','D24'].borders.Item[4].LineStyle := 1;
  excelWorksheet1.Range['D24','D24'].Value := 'borders.Item[4].LineStyle := 1';

  //패턴 변경
  for i := 1 to 18 do
  begin
    excelWorksheet1.Range['D'+inttostr(i+24),'D'+inttostr(i+24)].Interior.Pattern := i;
    excelWorksheet1.Range['E'+inttostr(i+24),'E'+inttostr(i+24)].Value := 'Interior.Pattern := '+inttostr(i);
  end;

{ 이미지를 삽입할 경우 실제파일을 기록해야 되기 때문에 주석처리
  실제 파일과 경로명 기록하고 주석푸시고 싱행해보세요
  //백그라운드 이미지
  //excelWorksheet1.SetBackgroundPicture('C:\My Documents\My Pictures\couplevssolo(6).jpg');


  //이미지 입력
  Selection := Sheet.Pictures.Insert('C:\My Documents\My Pictures\302492_2.jpg');


  //이미지 위치 조절
  Selection.ShapeRange.IncrementLeft(243);
  Selection.ShapeRange.IncrementTop(605);
}

  //수식 입력
  Format := '#,##0.00_ ;-#,##0.00;_-* "-"???_-;_-@_-';
  excelApplication1.Range['F3','H8'].NumberFormatLocal := Format;

  excelWorksheet1.Range['F3', 'H8'].Formula := '=RAND()*10';
  excelWorksheet1.Range['F9', 'F9'].Formula := '=SUM(F3:F8)';
  excelWorksheet1.Range['G9', 'G9'].Formula := '=SUM(G3:G8)';
  excelWorksheet1.Range['H9', 'H9'].Formula := '=SUM(H3:H8)';
  excelWorksheet1.Range['I9', 'I9'].Formula := '=SUM(F9:H9)';


  excelWorksheet1.Range['F2', 'F2'].Value := '1학년';
  excelWorksheet1.Range['G2', 'G2'].Value := '2학년';
  excelWorksheet1.Range['H2', 'H2'].Value := '3학년';

  excelWorksheet1.Range['E3', 'E3'].Value := '1년';
  excelWorksheet1.Range['E4', 'E4'].Value := '2년';
  excelWorksheet1.Range['E5', 'E5'].Value := '3년';
  excelWorksheet1.Range['E6', 'E6'].Value := '4년';
  excelWorksheet1.Range['E7', 'E7'].Value := '5년';
  excelWorksheet1.Range['E8', 'E8'].Value := '6년';
  excelWorksheet1.Range['E3', 'E8'].HorizontalAlignment := xlHAlignRight;

  //차트용 오브젝트 생성
  ChObj := (excelWorksheet1.ChartObjects(EmptyParam, lcid) as ChartObjects).Add(600, 10, 400, 250);
  excelChart1.ConnectTo(ChObj.Chart as _Chart);


  //데이터 범위(데이터뿐만 아니라 가로축 세로축에 찍힐 주석값까지 포함)
  Rnge := excelWorksheet1.Range['E2','H8']; // the data range, including titles


  //차트타입
  ChType := TOleEnum(xl3DColumn);
  excelChart1.ChartWizard(Rnge, ChType, EmptyParam, xlColumns, 1, 1, True,
                          excelWorksheet1.Range['A1', 'A1'].Text, // The chart title
                          '번호', '점수', EmptyParam, lcid);
  Ax := excelChart1.Axes(xlValue, xlPrimary, lcid) as Axis;
  Ax.AxisTitle.Font.FontStyle := '굴림체';

  //자동 컬럼 폭 맞춤
excelWorksheet1.Range[ XL.Cells[1, 1], XL.Cells[ir, 9]].Select;

excelWorksheet1.Columns.AutoFit;
end;

end

신고
Posted by 나비 나비:D

엑셀자료 불러오기를 하다가 제일 막혔던 부분이 바로 엑셀의 Record(Row)수를 구하는 거였습니다.
자료가 많은경우 ProgressBar를 이용하면 보기 좋겠죠.
이 자료는 대부분 참조한 거구요. Count수 구하는것은 아래처럼 하시면 될것 같습니다.
허접하니까 여기저기 살붙여서 사용하세요

procedure TActiveFormX.BitBtn1Click(Sender: TObject);
var
  ExcelApp, ExcelBook, ExcelSheet : Variant;
  I, J : Integer; // 순환변수  
begin
  //엑셀이 설치되었있을 경우만 가능
  try
    //엑셀을 실행
    ExcelApp := CreateOLEObject('Excel.Application');
  except
    ShowMessage('Excel이 설치되어 있지 않습니다!!!');
    Exit;
  end;

  Try
    ExcelApp.Visible := False;
    ExcelApp.DisplayAlerts := False;
    //엑셀 통합문서 열기
    if OpenDialog1.Execute then
    begin
      ExcelBook := ExcelApp.WorkBooks.Open(OpenDialog1.FileName);
      ExcelBook := ExcelApp.WorkBooks.item[1]; //워크 쉬트 설정
      //일단 개별문서는 sheet1으로 고정
      ExcelSheet := ExcelBook.Worksheets.Item[1];

      //StringGrid 초기화 (Title은 고려하지 않았습니다.)

      StringGrid1.RowCount := ExcelSheet.UsedRange.Rows.count;
      StringGrid1.ColCount := ExcelSheet.UsedRange.Columns.count;

      For I := 1 to ExcelSheet.UsedRange.Rows.count do
        For J := 1 to ExcelSheet.UsedRange.Columns.count do
           StringGrid1.Cells[J,I] := vartostr(ExcelSheet.Cells[I,J]);  //스트링그리드에 뿌리기
      ExcelApp.WorkBooks.Close;
      ExcelApp.quit;
      ExcelApp := unassigned;
    end;
  Except
    on err:exception do
    begin
      ExcelApp.WorkBooks.Close;
      ExcelApp.quit;
      ExcelApp := unassigned;
      ShowMessage('작업이 취소되었습니다. Data확인요망-'+err.message);
    end;
  end;
  ShowMessage(IntToStr(ExcelSheet.UsedRange.Rows.count) + '건의 자료를 변환하였습니다');
end;

신고
Posted by 나비 나비:D

1. 필요 unit


엑셀로 인한 추가 unit 2개 : ComObj, OleCtrls


2. 변수 선언


var

     XL : variant ;

begin

    XL := CreateOLEObject('Excel.Application');     // OLE컨트롤 생성
    XL.DisplayAlerts := False;          //경고창 숨기기

    XL.WorkBooks.Add;                   //새화일 열기

    XL.SaveAs('C:\test.xls');         //다른이름 저장

    XL.quit;            //엑셀 언로드 ---> exception 구간에서 사용하기 ! 안사용하면 메모리누수


3. 생각해야 될것 기타 값 입력 모양 변경 등등은


엑셀에 보면 도구 - 메크로 - 메크로 기록이라는 항목이 있는데


거기서 기록 을 누른 후 행동을 하고 ㅁ 버튼을 눌러 메크로 기록을 중지하면


기록된 메크로를 볼 수 있는데 (alt + F11)  여기서 만들어진 메크로를 적용 시키면 된다.



3번이 가장 중요 ! 즉 메크로 기록을 한후 역추적을 통해 코딩 ㄱㄱ



===================================================================================

이하 코드를 통하여 참조하여 주시기 바랍니다. ㄳ

===================================================================================

unit Unit1;

interface

uses
//    엑셀로 인한 추가 unit 2개 : ComObj, OleCtrls
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, ComObj, OleCtrls, Grids, StdCtrls;
type
  TForm1 = class(TForm)
    Button1: TButton;
    procedure Button1Click(Sender: TObject);
  Function  ReadExcelFile(sFileName:String):integer;
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

{ TForm1 }

procedure TForm1.Button1Click(Sender: TObject);
begin
    ReadExcelFile('12.xls');
end;

function TForm1.ReadExcelFile(sFileName: String): integer;
var
  XL, XArr, XTitle : Variant;
  sheetNumer,x,y : Integer;
  temp : String;
begin
  sheetNumer:=1;
  temp := 'a1:a1';
  try
    XL := CreateOLEObject('Excel.Application');
    XL.DisplayAlerts := False;          //경고창 보이기
    XL.workbooks.add;                   //새화일 열기
    XL.ActiveCell.FormulaR1C1 := '=3*3';
    XL.ActiveCell.CurrentRegion.Select;
    XL.selection.style:='Currency';
    XL.Cells[1,3].value := '3';

    XL.Range['D22'].Select;
    XL.ActiveCell.FormulaR1C1 := 'wonsama';
    XL.Selection.Font.ColorIndex := 3;


//   참조항목
//    XL.workbooks.Add('C:\test.xls');    //특정 이름의 화일 열기
//    XL.workbooks.Open('C:\'+sFileName); //특정 이름의 화일 열기
//    XL.ActiveWorkbook.saveas('C:\123.xls'); //활성화된 엑셀 다른 이름으로 저장
//    XL.ActiveCell.FormulaR1C1 := '=3*3';    //값입력
//    XL.ActiveCell.Font.Bold := True      //글자 환경 변경
//    XL.ActiveCell.CurrentRegion.Select;   //활성화 된 셀의 영역을 선택
//    XL.selection.style:='Currency';       //선택영역 통화 형태로

  except
    result:= 0;
    MessageDlg('Excel이 설치되어 있지 않습니다.'+#13+'이 기능을 이용하시려면 반드시 MS오피스 엑셀이 설치되어 있어야 합니다.- ' , MtWarning, [mbok], 0);
    XL.quit;            //엑셀 언로드
    Exit;
  end;
  XL.Visible := true;
  XL:= Unassigned;
 end;
end.

신고
Posted by 나비 나비:D

BLOG main image
by 나비:D

공지사항

카테고리

분류 전체보기 (278)
Programming? (0)
----------------------------- (0)
나비의삽질 (5)
Application (177)
SQL (51)
Web (27)
etc. (14)
Omnia (0)
---------------------------.. (0)

글 보관함

달력

«   2017/08   »
    1 2 3 4 5
6 7 8 9 10 11 12
13 14 15 16 17 18 19
20 21 22 23 24 25 26
27 28 29 30 31    
Total : 870,708
Today : 10 Yesterday : 157