유돌이

calendar

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

Notice

2011. 7. 9. 10:55 핫이슈

COM은?
-.컴포넌트 객체 모델 (Component Object Model)의 약자이다. COM은 컴파일과 링크가 되어 있는 바이너리코드로 객체지향 프로그래밍이 가능하게 해주는 윈도우의 기능 중에 하나이다.
-."인터페이스라는 미리 정의된 루틴들을 통해 객체들 사이의 상호작용을 가능하게 해주는 객체기반의 바이너리 표준"라고 MS에서 정의 해 놓았다. 이 말은 객체(Application도 포함)들 사이에 인터페이스가 있는데, 이 인터페이스를 통해 객체간의 공유가 가능하다. 분산환경(Corba, COM) 프로그래밍에는 각각 인터페이스를 정의 하는 표준적인 룰과 그를 응용한 룰(타입 라이브러리 등)이 있다.
-.인터페이스가 상속과 다형성 등의 할 수 있으므로 바이너리 코드기반으로 객체지향 프로그래밍이 가능하다.
-.COM 객체는 위에서 말했듯이 바이너리코드 이다. 이것을 프로세스 단위로 실행 시켜 주어야 한다. 그 프로세스 단위 안에 COM 객체는 1개 이상 있을 수 있다. 또 그 프로세스는 DLL (in-process), EXE (out-of-process) 형태로 만들어질 수 있다.
-.이상 위의 내용을 정리하면 "COM은 인터페이스라는 약속을 정해놓고 특정 프로세스단위 내에 존재하는 클래스를 지금 개발자가 만들고 있는 Application의 인스턴스로 갖다 쓰자." 라고 이해 하자. 추가로 "그 인터페이스를 상속 받아서 다른 COM Class도 만들 수 있다." 라고 이해 하자.
-. 위의 내용을 그림으로 그린 것이 [그림1] 이다.

[그림1] COM의 기본구조.

[그림1] 같이 COM객체는 COM 서버 내에 존재해야 하고, 각각의 COM 객체는 1개 이상의 인터페이스를 통해 Client Application 에게 COM객체 자신의 기능을 노출시킨다. Client Application은 노출된 인터페이스의 GUID (= IID)를 가지고 해당 COM 객체에 접근할 수 있는 것이다. COM 객체 자체가 어떤 일을 하고 그에 따른 함수를 노출하기만 하면(인터페이스를 통해서 ) Client Application 에서는 COM 객체가 어떻게 구현되어있는지 알지 않아도 COM 객체의 기능을 사용할 수 있다. 그렇다면 인터페이스를 이해할 필요가 있을 것이다. 아래에 인터페이스의 기본원리와 어떤 규칙을 따르는지 알아보자.

Interface는?
-.인터페이스는 COM 객체를 외부에서 사용할 수 있도록 하는 매개체 역활을 한다.
-.인터페이스는 함수들의 선언으로만 구성되어있고 COM 객체에서 인터페이스의 함수를 구현해 준다.
-.인터페이스를 서로를 식별하기 위해 GUID 타입의 128bit의 유일한 값을 가진다.
-.인터페이스는 언어 독립적으로 제작가능하고 인터페이스 내의 함수들은 포인터를 통해서 접근할 수 있다.

COM 서버의 형태는?
-. 위에서 COM객체는 COM 서버 내에 존재해야 한다고 설명했는데, COM 서버의 형태에 따란 Client Application에 바인딩이 달리 된다. [그림2]는 이것을 설명하는 그림이다.


[그림2-1 ] In-Process 의 형태


-. [그림2-1]의 In-Process는 COM 서버가 *.DLL로 제작되어있을 경우 이다. DLL로 되어있는 COM 객체에 Client Application이 접근하면 Client Application의 프로세스내에 COM 서버의 인스턴스가 바인딩 된다. 주로 ActiveX 컨트롤이 이런 형태이다. 익스플로어에서 COM서버내의 COM 객체를 호출할 때 익스플로어 프로세스내에 바인딩 되는 것이다. 참고로 ActiveX 컨트롤의 OCX 파일은 구조적으로 DLL과 동일하다.



[그림2-2] Out-Of-Process 의 형태


-. [그림2-2]의 Out-of-process는 COM 서버가 *.EXE로 제작되어있을 경우 이다. EXE로 되어있는 COM 객체에 Client Application이 접근하면 COM 서버는 자체적으로 프로세스를 생성된다. 내부적으로 Client Application에서는 Proxy로 COM서버의 Stub으로 연결된 구조로 In-process 보다 복잡하지만 개발자는 별다른 신경을 쓰지않아도 In-Process와 동일하게 작성하면 된다. 단지 Client Application내에 COM 서버가 인스턴스화 되는지 아니면 다른 프로세스로 생성 되는지 가 중요하다. 그래서 여러 Client Application에서 하나의 COM 객체를 호출할 때 Out-of-Process의 경우에는 호출한 Client Application의 수 만큼 COM 서버 프로세스가 생성되고, In-Process의 경우에는 호출한 Client Application의 수 만큼 COM 서버 인스턴스가 생성되는 것이다.

-. 그 외로 다른 컴퓨터의 COM서버의 COM객체를 호출하는 구조의 Remote COM 이 있다. 하지만 이 문서에는 따로 언급을 하지 않겠다.

COM의 확장이란?
-.MS나 그 외 여러 문서를 살펴보면 OLE, ActiveX, COM 등의 정의를 분명하게 하지않아서 혼동의 여지가 있다. 어떤 곳에서는 COM에서 OLE한 면이 없으면 ActiveX 이라고도 하고 OLE3.0에서 부터 COM를 ActiveX라고 부르기도 하지만 모두 틀린 말은 아니다.
-.그래도 계속 혼동스럽 다면 기본 COM에 추가된 기능, 확장된 기능 이라고 생각하자. (단어에 연연하지 말자는 뜻 이다.)
•.Automation Server (독립실행 가능한 Application(EXE)이나 DLL이 프로그래밍을 할수 있도록 객체(COM객체)를 다른 애플리케이션에 제공하는것)
•.Automation Control (위에서 설명한 Automation Sever에서 제공된 COM 객체를 이용하는 Client Application)
•.ActiveX Control(프로그래밍의 언어에 상관 없이 일반 컴포넌트처럼 사용할 수 있고 웹에서도 사용 가능한 객체)
•.Type Library (COM 서버내의 COM객체에 대한 정보를 Client Application에서 사용 가능하도록 하는 바이너리 코드. 표준적인 방식으로 저장되므로, 프로그래밍의 언어와 상관없이 읽을 수 있다. 또 COM 서버파일(DLL)등에 함께 저장될 수 있고 따로 저장해서 링크해서 사용할 수 있다. )
-.그 외 ActiveX Documemt , DCOM, MTS 등은 COM를 기초로 확장된 모습이다.

실습 (간단한 COM서버(DLL=In-Process)와 Client Application 만들기. Delphi5 Ent 기준)

-. COM 서버와 COM 객체 만들기.
1. 모든 프로젝트를 종료하고 File|New 해서 New Items 대화상자에서 --> ActiveX 탭 --> ActiveX Library 를 선택하고 [ OK ]버튼을 클릭한다. 여기서 추가한 ActiveX Library는 일반 DLL과 같은 파일을 생성하지만 COM객체를 레지스트리에 등록하고 해제하고 COM 서버 내의 특정 COM객체를 얻을 수 있는 함수를 Export 한다.

2.File|Save 해서 프로젝트명을 COMSrv.dpr로 저장한다. 다시 File|New --> ActiveX 탭 --> COM Object 를 선택하고 [ OK ]버튼을 클릭한다. CoClassName 을 COMObject로 하고 나머지 옵션은 기본사항으로 하고 [ OK ]버튼을 클릭한다.

옵션 설명
•.Instancing
-. Internal = COM객체를 COM 서버 내부적으로만 사용 가능하게 생성한다.
-. Single Instance = Application 마다 하나의 COM 인터페이스 만을 허용. 다른 인스턴스를 요구하면 COM 서버자체를 또 생성한다.
-. Multiple Instance = 여러 Application에서 서버객체를 연결 하면 인스턴스를 계속 새로 성성 한다. In-Process는 이것만 적용 가능하다.
•. Thread Model
-. Single = COM 서버전체가 하나의 쓰레드에서 생성한다. 쓰레드 사용이 불가능 하다.
-. Apartment = COM 객체는 각각의 쓰레드에서 생성된다. STA 라고 부르고  [그림 3-1]의 모습이다.
-. Free = Client Application은 어떤 시점이나, 어떤 쓰레드 상에서도 COM 객체의 메소드를 호출할 수 있다. MTA 라고 부르고 [그림 3-2]의 모습이다.
-. Both = STA와 MTA 둘 다 사용 가능하다.

[그림 3-1] Single Thread Apartment 모델 [그림 3-2] Mutipul Thread Apartment 모델

그림3-1처럼 STA의 경우에는 COM 객체를 생성한 Thread 만이 해당 COM 객체를 접근할 수 있다. 다른 Thread에서 생성한 COM객체는 접근할 수 없다. 그림3-2 처럼 MTA의 경우에는 COM 객체를 생성한 Thread 말고도 다른 쓰레드 에서도 COM객체에 접근할 수 있다. 개발자가 프로젝트가 쓰레드를 사용하지 않는 다면, STA로 만들고 별로 신경 쓰지 않아도 된다.

3. 타입 라이브러리에서 ICOMObject (COM 객체의 인터페이스)에 팝업메뉴을 띄워서 method를 새로 추가한다.

4. Method 이름을 "callDialog" 로 변경하고 오른쪽 파라메타 탭에서 파라메타를 1개 추가 한다. Name = uName , Type = BSTR

5. Method 를 한 개 더 추가해 이름을 "getNowTime" 로 변경하고 오른쪽 파라메타를 1개 추가한다. Name = nowtime, Type = BSTR* , Modifier = [out, retval] nowTime 파라메타는 호출한 Application으로 리턴할 수 있다.

6. Refresh 버튼을 눌러서 현재 상태를 적용한다.
-. 참고로 기본 리턴값인 HResult 는 COM서버의 내장된 객체의 메소드를 호출이 성공, 실패의 리턴값을 돌려준다.

7. File|SaveAll 해서 Unit1.pas를 ComSrvImpl.pas 로 저장한다. 그리고 다음과 같이 소스코드를 작성한다.

 unit ComSrvImpl;
 interface
 uses
   Windows, ActiveX, Classes, ComObj, COMServer_inpro_TLB, StdVcl;
 type
   TMyCOMObject = class(TTypedComObject, IMyCOMObject)
   protected
     function callDialog(const uName: WideString): HResult; stdcall;
     function getNowTime(out nowTime: WideString): HResult; stdcall;
   end;
 implementation
 uses ComServ, Dialogs, SysUtils;
 function TMyCOMObject.callDialog(const uName: WideString): HResult;
 begin
    ShowMessage('이름: ' + uName  +#13#10 + 'COM 서버에서실행된 대화상자');
 end;
 function TMyCOMObject.getNowTime(out nowTime: WideString): HResult;
 begin
    nowTime := TimeToStr(Now);
 end;
 initialization
   TTypedComObjectFactory.Create(ComServer, TMyCOMObject, Class_MyCOMObject,
     ciMultiInstance, tmApartment); //COM Object Factory 에 인스턴스 등록 
 end.

-. Client Application 만들기


[그림 4] Client Application 폼

1. 그림4 처럼 폼을 디자인 한다. 그리고 아래와 같이 소스코드를 작성한다.

  uses COMSrv_TLB, COMObj;
  {$R *.DFM}
  procedure TForm1.Button1Click(Sender: TObject);
  var
    COMObj: ICOMObject;
    strTime: wideString;
  begin
   COMObj := CoCOMObject.Create;
   oleCheck(COMObj.callDialog(Edit1.Text));
   oleCheck(COMObj.getNowTime(strTime));
   Label2.Caption := '호출된 시간: ' + strTime
  end;
 

2. 테스트.
-. 일반적인 DLL 파일은 실행파일과 같은 디렉토리나 Windows\System\ 디렉토리에 위치하면 되지만 COM 서버 DLL은 위치에 상관없도록 레지스트리에 등록해서 사용한다.
-. 레지스트리에 등록되는 내용은 ClassID (CLASS_), Type Libray ID (LibID_), InterfaceID(IID_) 등에 DLL 파일의 위치와 ProID 등이 저장된다.
-. 등록하는 방법은 COMSrv.dpr프로젝트를 Open 하고 RUN 메뉴에 Register ActiveX Server를 선택하면 된다. Out-Of-Process 경우 RUN만 한다.
-. Client Application을 실행하고 [COM 객체의 함수 호출] 버튼을 클릭한다. 그러면 메시지 창과 함께 현재시간이 Label1에 출력되면 COM 서버를 레지스트리 에서 위치를 얻고 난 후에 해당 인터펭이스를 통해 COM서버를 Client Application 내에 바인딩 한다.

Automation 서버 / Client 만들기

- Automation 서버 만들기 ( Out-Of-Process )

-.델파이에서는 자동화 컨트롤러가 자동화 서버를 호출하는 3가지방법을 제공한다.
1.Virtual Method Table (Vtable) 을 이용하는 방식 - Interface를 이용( 초기 바인딩 )
2.Dispatch Interface 를 이용하는 방식 - Idispatch.invoke()를 이용 ( 후기 바인딩 )
3.Variant를 이용하는 방식( 후기 바인딩 )
참고로 성능 Vtable이 가장 좋고, Dispath Interface가 그 다음이고, Variant는 가장 느리다. 델파이에서는 Vtable을 생성하는 Interface방식으로 Client Application을 만들면 되고, COM 객체는 Dual Interface(Vtable, Dispateh Interface) 형식으로 호환성을 생각해서 작성한다.


[그림 5 ] Automation 서버의 폼

1. 그림5 처럼 File|New Application 해서 폼안에 TShape 컴포넌트를 한 개 추가해서 폼을 디자인한다. File|SaveAll해서 프로젝트이름 AutoSrv.dpr 로 Unit1.pas --> SrvFrm.pas 로 한다.

2. File|New 해서 ActiveX 탭 --> Automation Object 를 선택하고 [ OK ]버튼을 클릭한다. CoClassName을 AutoTest 로 하고 나머지는 기본값으로하고 [ OK ] 버튼을 클릭한다.

3. Type Library 에서 IAutoTest 인터페이스를 클릭하고, setShapeType 메소드를 추가한다. 파라메타 탭에서 paramater name = sType , Type = int 로 파라메타 한개를 추가한다.

5. File Save All 해서 COM 객체 유닛을 AutoImpl.pas로 저장한다.

6. AutoImpl.pas 파일에 선언되어있는 setShapeType 메소드를 구현한다.

  uses ComServ,SrvFrm, extCtrls ;
  procedure TAutoTest.setShapeType(sType: SYSINT);
  begin
    Form1.Shape1.Shape := TShapeType(sType);
  end; 

7. 전체를 다시 저장하고, COM 서버를 레지스트리에 등록한다. Out-Of-Process(.Exe)는 실행만 해도 레지스트리에 자동 등록 된다.

- Automation Control 만들기


[그림6 ] Automation Control의 폼

1. 그림6 처럼 File | New Application 해서 폼안에 TEdit 한개와 TUpDown 1개 Associcate 속성을 Edit1 으로 한다. 그리고 TButton 컴포넌트 4개를 추가하고 위에서부터 vTable호출 (Button1) ~ 연결해제 (Button4) 로 캡션을 입력한다.

2. 소스코드를 아래와 같이 작성한다.

  uses AutoServer_TLB, COMObj;
  {$R *.DFM}
  var
    AutoTest: IAutoTest;  // interface 이용
    AutoTestDisp: IAutoTestDisp; //dispinterface 이용
    vAutoTest: Variant; // variant 이용

  procedure TForm1.Button1Click(Sender: TObject); // Interface(Vtable)을 이용해서 COM 객체 생성
  begin  
     AutoTest := CoAutoTest.Create;
    AutoTest.setShapeType(UpDown1.Position);
  end;

  procedure TForm1.Button2Click(Sender: TObject); // Dispatch Interface를 이용해서 COM 객체 생성
  begin
    AutoTestDisp := CreateComObject(Class_AutoTest) as IAutoTestDisp;
    AutoTestDisp.setShapeType(UpDown1.Position);
  end;
 
  procedure TForm1.Button3Click(Sender: TObject); // Variant 변수에 Program ID 값을 넣고 COM 객체 생성
  begin
    vAutoTest := CreateOleObject('AutoServer.AutoTest');
    vAutoTest.setShapeType(UpDown1.Position);
  end;

  procedure TForm1.Button4Click(Sender: TObject);
  begin
    AutoTest := nil; // Pointer 변수 해제
    AutoTestDisp := nil; 
    vAutoTest := Unassigned; //Variant 변수 해제 
  end;

3. 모두 저장하고 Automation Control (Client Application ) 을 실행한다. UpDown 컴포넌트의 값을 0 ~5 사이에서 변경하면서 테스트 해보자.

Excel 97, 2000 을 Control 하는 Automation Controler 만들기

-. MS사에서 만든 많은 제품들이 COM 객체로써 외부에서 Control 할 수 있도록 만들어져 있다. 이번 실습은 Excel 97, 2000 을 간단히 Control 할 수 있도록 COM Controler 를 만들어 본다.


[그림7 ] Excel Controler 폼

- . 델파이 5 에서 Server 탭에 MS의 Office 제품군을 Control 할 수 있도록 컴포넌트를 만들어 놓았는데, 기본적으로 Interface (VTable) 방식으로 접근할수 있다. 물론 다른 방식도 가능하지만 위에서 설명했듯이 Automation 서버를 Control하는 Client Application 을 델파이에서 만들때에는 Interface 방식의 성능이 가장 우수하다.

1. File|New Application 해서 그림7과 같이 TMemo 컴포넌트 1개와 TButton 3개, Server탭에서 TExcelApplication, TExcelWorkSheet, TExcelWorkBook 1개를 폼안에 추가한다.

2. 아래와 같이 소스코드를 작성한다.

  var
    vExcel: Variant;
 implementation
  uses COMObj;

  procedure TForm1.Button1Click(Sender: TObject);
  Var 
    i: Integer;
  begin
    varExcel := CreateOleObject('Excel.Application');
    varExcel.workbooks.Add;
    for i := 0 to Memo1.Lines.Count-1 do
      varExcel.workbooks[1].worksheets[1].Cells[i+1, 1] := Memo1.Lines[i];
    varExcel.Visible := true;
  end;

  procedure TForm1.Button2Click(Sender: TObject);
  var
    i: Integer;
  begin
    ExcelApplication1.Connect;
    ExcelWorkbook1.ConnectTo(ExcelApplication1.Workbooks.Item[1]);
    ExcelWorkSheet1.ConnectTo(ExcelWorkBook1.Sheets[1] as _WorkSheet);
    with ExcelWorkSheet1 do
      for i := 0 to Memo1.Lines.Count-1 do
        Cells.Item[i+1, 1] := Memo1.Lines[i];
    ExcelApplication1.Visible[0] := True;
  end;

  procedure TForm1.Button4Click(Sender: TObject);
  begin
    if not varIsEmpty(varExcel) then
      varExcel.quit;
    if not varIsEmpty(ExcelApplication1.Application) then
    begin
      ExcelApplication1.Disconnect;
      ExcelApplication1.Quit;
    end;
  end;
 

3. 실행 하고 버튼을 눌러본다. 위의 예제는 PC에 Excel 프로그램이 설치되어 있는 경우에만 제대로 동작 한다.

-이외에도 Delphi에서는Excel의 차트등 거의 모든 객체를 Control 할수 있다. Excel .vbs 파일을 생성해서 실행할수도 있다
아래 소스코드는 Excel 내에 특정 매크로를 생성해서 실행시키는 예제 이다.

  procedure TForm1.Button1Click(Sender: TObject);
  var
    str: String;
    vModule: OleVariant;
  begin
    str := 'Sub Macro()' + #13#10 +
         'Dim X, Y' + #13#10 +
         'Dim X_END, Y_END' + #13#10 +
         'Dim Min, Max' + #13#10 +
         'If Cells(1, 2) = "N" Then'+ #13#10 +
         'X_END = 21'+ #13#10 +
         'Else'+ #13#10 +
         'X_END = 25'+ #13#10 +
         'End If'+ #13#10#13#10+
         'Y_END = Cells(1, 3) + 4'+ #13#10#13#10+
         'For Y = 5 To Y_END'+ #13#10 +
         ' For X = 2 To X_END'+ #13#10 +
         '   Min = Cells(3, X)'+ #13#10 +
         '   Max = Cells(4, X)'+ #13#10 +
         '   Cur = Cells(Y, X)'+ #13#10#13#10+
         '   Cells(Y, X).Font.ColorIndex = 2'+ #13#10 +
         '   Cells(Y, X).Font.FontStyle = "굵게"'+ #13#10#13#10+
         '   If (Min <= Cur) And (Cur <= Max) Then'+ #13#10 +
         '     Cells(Y, X).Interior.ColorIndex = 5'+ #13#10 +
         '   Else'+ #13#10 +
         '     Cells(Y, X).Interior.ColorIndex = 3'+ #13#10 +
         '   End If'+ #13#10 +
         '  Next X' + #13#10 +
         '  Next Y' + #13#10 +
         'End Sub';

    vModule :=  ExcelWorkBook1.VBProject.VBComponents.Add(1);
    vModule.CodeModule.AddFromString(str);
    ExcelApplication1.Run('Macro');
  end; 

'핫이슈' 카테고리의 다른 글

★냉동인간★ 부활시킬 단초 발견!!!  (0) 2011.07.09
고지전 예고편!!  (0) 2011.07.09
나도가수다!! 도플겡어들..ㅋ  (0) 2011.07.08
연금복권 인터넷구매 방법!!!!  (0) 2011.07.08
옵티머스3d 상세스펙  (0) 2011.07.08
posted by 유돌이
2010. 1. 11. 14:37 델파이

프로그램을 띄우거나 파일을 실행할경우 ShellAPI 함수인 ShellExecute() 를 사용합니다.
이 함수는 윈도우즈 탐색기에서 파일을 선택하고 더블클릭하는 기능과 동일한 동작을 합니다.
다음은 ShellExecute() 의 몇가지 사용예입니다.

(1) 파일과 연관(association)된 프로그램으로 파일을 엽니다
    ShellExecute(Handle, 'open', PChar('test.txt'), nil, nil, SW_SHOW);

(2) notepad.exe 에 파라미터로 config.sys 파일을 주어 메모장을 실행합니다
    ShellExecute(Handle, 'open', 'notepad', 'c:\config.sys', nil, SW_SHOW);

(3) PC에 설치된 기본 웝브라우저로 지정한 사이트를 엽니다.
    ShellExecute(Handle, 'open', 'www.howto.pe.kr', nil, nil, SW_SHOW);

(4) 특정 폴더를 시작 폴더로 하는 윈도우즈 탐색기를 엽니다
    ShellExecute(Handle, 'explore', PChar('c:\windows)', nil, nil, SW_SHOW);

(5) readme.doc 파일을 연결된 프로그램으로 인쇄하고 화면을 닫습니다
    ShellExecute(Handle, 'print', 'readme.doc', nil, nil, SW_SHOW);
   
(6) rMyDelphiFile.pas 파일을 wordpad 프로그램으로 인쇄하고 화면을 닫습니다
    ShellExecute(Handle, 'print', 'wordpad.wxe', 'MyDelphiFile.pas', nil, SW_SHOW);

(7) readme.doc 파일을 프린터를 선택하여 연결된 프로그램으로 인쇄하고 화면을 닫습니다
    var
      Device : array[0..255] of char;
      Driver : array[0..255] of char;
      Port   : array[0..255] of char;
      S: String;
      hDeviceMode: THandle;
    begin
      Printer.PrinterIndex := -1;  // 프린터 인덱스를 지정합니다. 여기서는 기본 프린터(-1) 선택
      Printer.GetPrinter(Device, Driver, Port, hDeviceMode);
      S := Format('"%s" "%s" "%s"',[Device, Driver, Port]);
      ShellExecute(Handle, 'printto', 'readme.doc', Pchar(S), nil, SW_HIDE);

(8) 기본 메일 프로그램을 실행합니다.
    ShellExecute(Handle, nil, 'mailto:cozy@howto.pe.kr', nil, nil, SW_SHOW);

(9) DOS 명령어를 실행하고 화면을 닫습니다
    ShellExecute(Handle, 'open', PChar('command.com'), PChar('/c copy file1.txt file2.txt'), nil, SW_SHOW);

(10) DOS 명령어를 실행하고 화면을 닫지 않습니다
     ShellExecute(Handle, 'open', PChar('command.com'), PChar('/k dir'), nil, SW_SHOW);

(11) ShellExecute()의 리턴값은 실행된 프로그램의 핸들이거나 에러코드입니다
     리턴값이 32 이하이면 에러가 발생한것으로 각각은 아래와 같은 의미가 있습니다

  var
    code: Integer;
  begin
    code := ShellExecute(...);
    if code <= 32 then ShowMessage(ShowShellExecuteError(code));
  end;
    
  // ShellExecute()의 리턴코드에 대한 에러 메시지
  function ShowShellExecuteError(i: integer): String;
  begin
    case i of 0: result := 'The operating system is out of memory or resources.';
      ERROR_FILE_NOT_FOUND: result := 'The specified file was not found.';
      ERROR_PATH_NOT_FOUND: result := 'The specified path was not found.';
      ERROR_BAD_FORMAT: result := 'The .EXE file is invalid (non-Win32 .EXE or error in .EXE image).';
      SE_ERR_ACCESSDENIED: result := 'The operating system denied access to the specified file.';
      SE_ERR_ASSOCINCOMPLETE: result := 'The filename association is incomplete or invalid.';
      SE_ERR_DDEBUSY: result := 'The DDE transaction could not be completed because other DDE transactions were being processed.';
      SE_ERR_DDEFAIL: result := 'The DDE transaction failed.';
      SE_ERR_DDETIMEOUT: result := 'The DDE transaction could not be completed because the request timed out.';
      SE_ERR_DLLNOTFOUND: result := 'The specified dynamic-link library was not found.';
      //SE_ERR_FNF          : result:='The specified file was not found.';
      SE_ERR_NOASSOC           : result:='Unbekannter Extender.';
      SE_ERR_OOM: result := 'There was not enough memory to complete the operation.';
      //SE_ERR_PNF          : result:='The specified path was not found.';
      SE_ERR_SHARE: result := 'A sharing violation occurred.';
    end;
  end;

(12) ShellExecuteEX()를 이용하여 notepad.exe 를 실행한 후 종료될때까지 기다립니다
  var
    SEInfo: TShellExecuteInfo;
    ExitCode: DWORD;
    ExecuteFile, ParamString, StartInString: string;
  begin
    ExecuteFile   := 'notepad.exe';   // 실행할 프로그램
    ParamString   := 'c:\winzip.log'; // 프로그램의 명령행 파라미터
    StartInString := 'c:\';           // 시작 위치
    FillChar(SEInfo, SizeOf(SEInfo), 0);
    SEInfo.cbSize := SizeOf(TShellExecuteInfo);

    with SEInfo do
    begin
      fMask        := SEE_MASK_NOCLOSEPROCESS;
      Wnd          := Application.Handle;
      lpFile       := PChar(ExecuteFile);
      lpParameters := PChar(ParamString);
      lpDirectory  := PChar(StartInString);
      nShow        := SW_SHOWNORMAL;
    end;
    if ShellExecuteEX(@SEInfo) then
    begin
      repeat
        Application.ProcessMessages;
        GetExitCodeProcess(SEInfo.hProcess, ExitCode);
      until (ExitCode <> STILL_ACTIVE) or Application.Terminated;
      ShowMessage('프로그램이 종료되었습니다');
    end
    else ShowMessage('프로그램을 실행할 수 없습니다');

 

출처 : http://www.howto.pe.kr 작성자 : 김영대님!


posted by 유돌이
2010. 1. 11. 14:36 델파이

간단한 예제 입니다.

[uses : ShellApi 추가!]

 

function DeleteDirectory(Const DirPath: String): Boolean;
var
  SHFileOpStruct: TSHFileOpStruct;
  DirBuf: array [0..255] of char;
  Directory: string;

begin
  try
    Directory := ExcludeTrailingPathDelimiter(DirPath);
    Fillchar(SHFileOpStruct, sizeof(SHFileOpStruct), 0);
    FillChar(DirBuf, sizeof(DirBuf), 0);
    StrPCopy(DirBuf, Directory);

    with SHFileOpStruct do
    begin
      Wnd := 0;
      pFrom := @DirBuf;
      wFunc := FO_DELETE;
      //fFlags := fFlags or FOF_ALLOWUNDO; // 휴지통에 담기
      fFlags := fFlags or FOF_NOCONFIRMATION;
      fFlags := fFlags or FOF_SILENT;
    end;
    Result := (SHFileOperation(SHFileOpStruct) = 0);
  except
    Result := False;
  end;
end;


posted by 유돌이
2010. 1. 11. 14:35 델파이

function ResponseCodeCheck(URL: String): Boolean;
var
  IdHTTP1: TIdHTTP;

begin
  Result := False;
  IdHTTP1 := TIdHTTP.Create;
  try
    IdHTTP1.Get(URL);

    case IdHTTP1.ResponseCode of
      200:
      begin
        Result := True;
        OutputDebugString('OK');
      end;

     403:OutputDebugString('Forbidden');
     404:OutputDebugString('Not Found');
     500:OutputDebugString('Server Error');

      else begin

        OutputDebugString('The Others ');

      end;
    end;
 finally
    FreeAndNil(IdHTTP1);
  end;


posted by 유돌이
2010. 1. 11. 14:35 델파이
[발생하기 쉬운 HTTP상태코드]

200 : request가 성공적으로 완료되었음.
204 : request가 실행되었으나 클라이언트에게 보낼 데이터가 없음.
300 : 요구된 request가 여러 위치에 존재하는 자원을 필요로 하므로
request는 위에대한 정보를 보낸다. 클라이언트는 가장 적당한
위치를 선택하여야 함.
302 : request가 요구한 데이터를 발견하였으나 실제 다른 url에 존재함.
400 : request의 문법이 잘못되었음.
403 : request는 금지된 자원을 요구하였음.
404 : 서버는 요구된 url을 찾을 수 없음.
500 : 서버에 내부적으로 오류가 발생하여 더 이상을 진행할 수 없음.
501 : 요청된 request는 합법적이나 서버는 요구된 method를 지원하지 않음.
503 : 서버가 바쁘기 때문에 서비스를 할 수 없음. 
posted by 유돌이
2010. 1. 11. 14:34 델파이

간단한 예제로 설명 할게요.

 

아래의 예제는 'F10'키를 HotKey로 등록하여

'F10'키가 눌리면 해당 프로그램이 종료가 되도록 코딩하였습니다.

 

//선언부

 procedure WMHotkey(var msg: TWMHotkey); message WM_HotKey;

 

 

//구현부

procedure TForm1.WMHotkey(var msg: TWMHotkey);
begin
  case msg.HotKey of
    1:
    begin
      OutPutDebugString('Program Exit');
      Form1.Close; // F10
    end;
  end;
end;

 

procedure TForm1.FormCreate(Sender: TObject);
begin
    RegisterHotKey(Handle, 1, 0, VK_F10);
end;

 

이상 간단한 팁이 였습니다. ㅋㅋ

posted by 유돌이
2010. 1. 11. 14:33 델파이

 For Windows 9x/ME/2000/XP }

uses
  Tlhelp32;

function KillTask(ExeFileName: string): Integer;
const
  PROCESS_TERMINATE = $0001;
var
  ContinueLoop: BOOL;
  FSnapshotHandle: THandle;
  FProcessEntry32: TProcessEntry32;
begin
  Result := 0;
  FSnapshotHandle := CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
  FProcessEntry32.dwSize := SizeOf(FProcessEntry32);
  ContinueLoop := Process32First(FSnapshotHandle, FProcessEntry32);

  while Integer(ContinueLoop) <> 0 do
  begin
    if ((UpperCase(ExtractFileName(FProcessEntry32.szExeFile)) =
      UpperCase(ExeFileName)) or (UpperCase(FProcessEntry32.szExeFile) =
      UpperCase(ExeFileName))) then
      Result := Integer(TerminateProcess(
                        OpenProcess(PROCESS_TERMINATE,
                                    BOOL(0),
                                    FProcessEntry32.th32ProcessID),
                                    0));
     ContinueLoop := Process32Next(FSnapshotHandle, FProcessEntry32);
  end;
  CloseHandle(FSnapshotHandle);
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
  KillTask('notepad.exe');
end;

{ For Windows NT/2000/XP }

procedure KillProcess(hWindowHandle: HWND);
var
  hprocessID: INTEGER;
  processHandle: THandle;
  DWResult: DWORD;
begin
  SendMessageTimeout(hWindowHandle, WM_CLOSE, 0, 0,
    SMTO_ABORTIFHUNG or SMTO_NORMAL, 5000, DWResult);

  if isWindow(hWindowHandle) then
  begin
    // PostMessage(hWindowHandle, WM_QUIT, 0, 0);

    { Get the process identifier for the window}
    GetWindowThreadProcessID(hWindowHandle, @hprocessID);
    if hprocessID <> 0 then
    begin
      { Get the process handle }
      processHandle := OpenProcess(PROCESS_TERMINATE or PROCESS_QUERY_INFORMATION,
        False, hprocessID);
      if processHandle <> 0 then
      begin
        { Terminate the process }
        TerminateProcess(processHandle, 0);
        CloseHandle(ProcessHandle);
      end;
    end;
  end;
end;

procedure TForm1.Button2Click(Sender: TObject);
begin
  KillProcess(FindWindow('notepad',nil));
end;

 

 

 

[출처] [delphi]kill!!!|작성자 리우

'델파이' 카테고리의 다른 글

발생하기 쉬운 HTTP상태코드  (0) 2010.01.11
Hot Key 등록하는 방법  (0) 2010.01.11
한영 변환 방법  (0) 2010.01.11
Grid에 CheckBox 넣기  (0) 2010.01.11
중복 실행 방지 (Mutex)  (0) 2009.06.26
posted by 유돌이
2010. 1. 11. 14:33 델파이

{---------------------------}
{      영문입력상태 만들기           }
{---------------------------}
procedure SetEng(Hand: HWnd);
var
  hIMC: integer;
  dwSentence : DWORD;
  dwConversion : DWORD;

begin
   hIMC := ImmGetContext(Hand);
   if ImmGetConversionStatus(hIMC, dwConversion, dwSentence) then begin
     dwConversion := dwConversion and $fffffffe;
     ImmSetConversionStatus(hIMC, dwConversion , dwSentence);
   end;
end;

{---------------------------}
{       한글 입력상태  만들기        }
{---------------------------}
procedure SetHan(Hand: HWnd);
var
  hIMC: integer;
  dwSentence : DWORD;
  dwConversion : DWORD;

begin
   hIMC := ImmGetContext(Hand);
   if ImmGetConversionStatus(hIMC, dwConversion, dwSentence) then
     ImmSetConversionStatus(hIMC, IME_CMODE_NATIVE, dwSentence);
end;

 

 

출처 : 볼랜드포럼  (작성자: 문성운 [moon9424] )


'델파이' 카테고리의 다른 글

Hot Key 등록하는 방법  (0) 2010.01.11
실행프로그램(task,태스크) 죽이기  (0) 2010.01.11
Grid에 CheckBox 넣기  (0) 2010.01.11
중복 실행 방지 (Mutex)  (0) 2009.06.26
Caps Lock 체크 하는 방법  (0) 2009.06.26
posted by 유돌이
2010. 1. 11. 14:32 델파이

간단한 예제로 만들어 봤습니다.

 

참고하세요.

 

unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, Grids, JvExGrids, JvStringGrid;

type
  TForm1 = class(TForm)
    JvStringGrid1: TJvStringGrid;
    Button1: TButton;
    Memo1: TMemo;
    procedure Button1Click(Sender: TObject);
  private
    { Private declarations }
    procedure CheckBoxKeyUp(Sender: TObject; var Key: Word; Shift: TShiftState);
    procedure CheckBoxMouseUp(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: integer);
    procedure OnClickEx(Sender: TObject);
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.Button1Click(Sender: TObject);
var
  r : TRect;
  i, j: integer;

begin
  i := 1;
  for j:=1 to JvStringGrid1.RowCount - 1 do
  begin
    JvStringGrid1.Objects[i, j] := TCheckBox.Create(JvStringGrid1);

    with TCheckBox(JvStringGrid1.Objects[i, j]) do
    begin
      OnKeyUp   := CheckBoxKeyUp;
      OnMouseUp := CheckBoxMouseUp;
      Tag    := j;
      Hint   := IntToStr(i);
      Parent := JvStringGrid1;
      r := JvStringGrid1.CellRect(i, j);
      BoundsRect := r;
      Top := r.Top;
      Width := r.Right - r.Left - 25;
      Left := r.Left + 25;
      Height := r.Bottom - r.Top;
      Checked := False;
      Caption := '';
    end;
  end;
end;

procedure TForm1.CheckBoxMouseUp(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: integer);
begin
  if not TCheckBox(Sender).Checked then
  begin
    JvStringGrid1.Row := TCheckBox(Sender).Tag;
    JvStringGrid1.Col := StrToInt(TCheckBox(Sender).Hint);
    JvStringGrid1.Cells[JvStringGrid1.ColCount -1, JvStringGrid1.Row] := 'False';
  end else begin
    JvStringGrid1.Row := TCheckBox(Sender).Tag;
    JvStringGrid1.Col := StrToInt(TCheckBox(Sender).Hint);
    JvStringGrid1.Cells[JvStringGrid1.ColCount -1, JvStringGrid1.Row] := 'True';
    OnClickEx(JvStringGrid1);
  end;
end;

procedure TForm1.CheckBoxKeyUp(Sender: TObject; var Key: Word; Shift: TShiftState);
begin
  if Key <> VK_SPACE then
  begin
    Exit;
  end else if not TCheckBox(Sender).Checked then
  begin
    Exit;
  end else begin
    JvStringGrid1.Row := TCheckBox(Sender).Tag;
    JvStringGrid1.Col := StrToInt(TCheckBox(Sender).Hint);
    OnClickEx(JvStringGrid1);
  end;
end;

procedure TForm1.OnClickEx(Sender: TObject);
begin
  Memo1.Lines.Add('ROW: ' + IntToStr(JvStringGrid1.Row));
end;

end.


'델파이' 카테고리의 다른 글

실행프로그램(task,태스크) 죽이기  (0) 2010.01.11
한영 변환 방법  (0) 2010.01.11
중복 실행 방지 (Mutex)  (0) 2009.06.26
Caps Lock 체크 하는 방법  (0) 2009.06.26
현재 날짜 구하는 함수  (0) 2009.06.26
posted by 유돌이
2009. 6. 26. 14:03 델파이

프로그램이 이미 실행된 상태에서
동일한 프로그램이 중복 실행되는 것을 방지하려면

프로젝트 소스 파일에서 다음과 같이 코딩합니다.

program Project;

uses
Forms,windows,
Unit1 in 'Unit1.pas' {Form1};

var
Mutex : THandle;

{$R *.RES}

begin
  Mutex := CreateMutex(nil, True, 'noDuplicate');
  if (Mutex <> 0 ) and (GetLastError = 0) then

  begin
    Application.Initialize;
    Application.CreateForm(TForm1, Form1);
    Application.Run;
   

    if Mutex <> 0 then CloseHandle(Mutex);
  end;
end.


'델파이' 카테고리의 다른 글

한영 변환 방법  (0) 2010.01.11
Grid에 CheckBox 넣기  (0) 2010.01.11
Caps Lock 체크 하는 방법  (0) 2009.06.26
현재 날짜 구하는 함수  (0) 2009.06.26
델파이 단축키  (0) 2009.06.26
posted by 유돌이
prev 1 2 3 4 next