C++ 파일 존재 여부 체크하는 함수 (isExistFile) 함수

2018.01.08 10:42

C#에서는 FILE 핸들러로 바로 확인이 가능한데 C++는 한줄에 쓰기 번거러워 따로 함수를 만들어서 사용한다.


유니코드가 아닌 프로젝트도 있어 분기처리 해준다.



bool isExistFile(CString _strFile) { #ifdef _UNICODE return(_waccess_s(_strFile, 0) != -1); #else return (_access_s(_strFile, 0) != -1); #endif }




[MFC] ComboBox(콤보박스) ReadOnly로 설정하기

2017.04.25 17:18

MFC에서 ComboBox(콤보박스) 사용시 사용자가 임의적으로 항목을 수정할 수 있다.


물론 수정된 값을 받는 경우도 있지만, 해당 선택된 항목의 index값을 가져와서 쓰는경우 매개변수가 잘못되었다는 등의 오류가 발생 할 수 있다.


사용자가 수정할 항목이 아닌 경우라면 이를 ReadOnly로 바꿔줄 필요가 있다.


ReadOnly 설정은 따로 코드를 수정하는 경우도 있지만, 간단하게 해당 리소스 속성항목에서 


Type를 "Drop List"로 바꿔주면 된다.


아래는 Reference에 나와있는 Style Type별 상태

StyleWhen is list box visibleStatic or edit control
SimpleAlwaysEdit
Drop-downWhen dropped downEdit
Drop-down listWhen dropped downStatic



킬로,메가,기가,테라,베타,엑사, 나노,피코,펨토,아토,젭토 욕토 [SI 단위] [출처] 킬로,메가,기가,테라,베타,엑사, 나노,피코,펨토,아토,젭토 욕토

2017.04.07 11:06

SI 기본 단위의 정의



SI 접두어



CFileDialog 정리

2017.03.24 13:36

CFileDialog 클래스는 흔히 사용되는 파일열기, 폴더 열기 등 FileOpen 다이얼로그를 생성하는 클래스이다.

자세한 내용은 레퍼런스를 참고하자.(https://msdn.microsoft.com/ko-kr/library/dk77e5e7.aspx#cfiledialog__cfiledialog)


아래는 레퍼런스에 나와있는 CFileDialog 생성자이다.

CfileDialog는 객체 생성시에 추가로 인자값을 넣어주어야 한다.


explicit CFileDialog(
	BOOL bOpenFileDialog,  //TRUE : 파일 열기, FALSE : 다른 이름으로 저장 대화 상자
	LPCTSTR lpszDefExt = NULL,  //기본 파일 이름 확장자
	LPCTSTR lpszFileName = NULL,  //초기 파일 이름, 파일명 지정하는 edit컨트롤 기본 내용
	DWORD dwFlags = OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT,  //대화상자 

	/*

	- OFN_EXPLOPER     윈도우 탐색기 스타일
	- OFN_ARROWMULTISELECT       파일을 한번에 여러개 선택 가능
	- OFN_CREATEPROMPT         존재하지 않는 파일명을 입력했을 경우 새로 생성하겠냐는 메시지 박스 출력
	- OFN_FILEMUSTEXIST     존재하지 않는 파일명을 입력할 수 없도록 함
	- OFN_HIDEREADONLY      읽기 전용 파일은 출력하지 않음
	- OFN_LONGNAMES          긴 파일 이름 포맷 지원
	- OFN_OVERWRITEPROMPT  존재하는 파일명을 입력했을 경우 덮어쓰겠냐는 메시지 박스 출력
	- OFN_PATHMUSTEXIST      이미 존재하는 디렉터리명만을 입력


	//2개 이상의 플래그를 이용하고자 하는 경우 '|' 기호로 구분하여 사용한다.
	*/
	LPCTSTR lpszFilter = NULL,  //확장자 필터
	CWnd* pParentWnd = NULL,
	DWORD dwSize = 0,
	BOOL bVistaStyle = TRUE);


****************** CFileDialog 클래스의 멤버 함수
CString GetPathName       선택된 파일의 절대 경로
CString GetFileName        선택된 파일의 이름과 확장자
CString GetFileExt            선택된 파일의 확장자
CString GetFileTitle           선택된 파일의 파일명
BOOL GetReadOnlyPref     읽기 전용 여부

POSITION GetStartPosition           다중 선택의 경우
CString GetNextPathName



******************CFileDialog 클래스의 인스턴스를 선언하고 DoModal 함수 호출

** 한개의 파일만 선택할 경우
char szFilter[] = "Image (*.BMP, *.GIF, *.JPG) | *.BMP;*.GIF;*.JPG | All Files(*.*)|*.*||";
CFileDialog dlg(TRUE, NULL, NULL, OFN_HIDEREADONLY, szFilter);
if(IDOK == dlg.DoModal())
{
        CString strPathName = dlg.GetPathName();
}


** 여러개의 파일을 복수 선택할 경우

char szFilter[] = "All Files(*.*) | *.* ||";
CFileDialog dlg(TRUE, NULL, NULL, OFN_ALLOWMULTISELECT, szFiilter);

if(IDOK == dlg.DoModal())
      for(POSITION pos=dlg.GetStartPosition(); pos != NULL;)
               m_ctrlListBox.AddString(dlg.GetNextPathName(pos));



Get으로 멤버함수를 찾으면 될듯 하다..


Mil 기초적 파악사항 - 2

2017.02.20 10:32

Mil과  Mil Lite,     Active Mil 과의 차이점.??


Mil - Lite의 경우는  Matrox Frame Grabber 설치를 위한 Driver를 제공하며 기본적인 Frame Grabber기능 즉 영상획득
디스플레이 , 영상 로드, 저장이 가능한 모듈들로 구성되어 있습니다.

주로 영상을 획득하여 이미지 확인 및 이에 대한 저장을 위해 많이 사용되며, 이미지 데이타를 직접 접근하여
독자적인 프로세싱처리 및 알고리즘을 적용할 수 있습니다.

MIL의 경우에는 MIL-lite에서 제공하는 기능을 포함하며 영상처리를 위해 사용되는 알고리즘이 쉽게 사용할 수 있는 함수로
구현되어 있습니다.

즉 이미지 프로세싱  패턴 매칭   OCR  blob  Measurement등의 기능을 함수로써 제공하므로 누구나 쉽게 사용하실 수
있도록 구성.

Mil은 우리가 Visual C++ 환경에서  c언어를 사용하여 프로그래밍 할 수 있도록 라이브러리가 구성되어 있습니다.

Active Mil은 Active X 사용하는 것으로써 Visual basic과 visual c++환경에서 개발이 가능하며 mil에서 사요하는
모듈들로 컨트롤이 구성되어 있습니다.

즉 MIL에서는 사용하기 위한 모듈들에 대한 선언 및 초기화 작업에 대한 작업을 config을 통해 설정을 해 주는 반면에
active mil의 경우는 active x control로 모든 모듈들이 구성되어 있어 컨트롤을 form 및 리소스에서 원하는 컨트롤을 선택하고 여기에 대한 초기화를 속성창을 통해 설정을 합니다.

지원하는 기능은 동일하며 다만 사용하는 함수의 표현방식이 개발환경에 따라 다릅니다. 




■ Mil workspace 생성을 위한 세팅하는 방법


MIL을 이용한 프로그램을 실행하기 위해서는

1. Tool / option 에서  Directories tab에서  라이브러리,  인클루드 파일에 매트록스에 폴더를 넣어준다.

2. 그런후 컴파일을 하면  workspace 가 생성되면서,  에러가 발생한다.

이 에러경우는 각 모듈에 대한 라이브러리가 링크되지 않아서 발생하는 에러이므로 다음과 같은 설정을 한다.

 -  project / setting tab의  link의 프로그램에서 사용되는 library modules을 삽입해 주시면 됩니다.  
  - 예를들면 mblob.c 를 사용할 경우 기본적으로  mil.lib, milblob.lib,  millimlib 의 라이브러리 첨가해주시면 됩니다.

3. 그리고 다시 컴파일을 한다.




■ MIL 기본 소스구조.

Mil은 매트록스에서 나오는 프레임 Grabber를 사용하기 위해서 필요한 일종의 라이브러리.

Mil 과 Mil-Lite의 두 종류로 나뉘어 있으며, Mil은 Mil-Lite에 들어있지 않은 Image-Processing관련 함수들이
포함되어 있습니다.

Mil 처음하시는 분들을 위해서 간단한  Grab예제로 설명



/*  Mil함수들이 정의되어 있는 함수로써 include해야 됩니다. */

#include< mil.h >
#include< stdio.h >

void main(void)
{
    /*  Mil에서 각 개체들을 다루는 data type으로서 아래와 같은 항목들을 지정합니다. */
 
    MIL_ID MilApplication;   // 응용프로그램 ID
    MIL_ID MilSystem;       //  Frame Grabber의 ID
    MIL_ID Mildisplay;        //  디스플레이를 위한 ID
    MIL_ID MilDigitizer;       //  digitizer를 위한 ID
    MIL_ID MilImage;          // Image buffer를 위한 ID


    /*  응용프로그램에서 각각 ID들을 기본적인 설정으로 할당합니다. */

    MappAllocDefault( M_SETUP, &MilApplication, & MilSystem, &MilDisplay, &MilDigitizer, &MilImage );

    /*  모니터에 MilImage의 내용을 디스플레이 하기 위한 설정을 한다.  */
    MdispSelect(MilDigitizer, MilImage);

     /*  카메라에서  Grb하여 MilImage에 저장합니다. */
    MdigGrab( MilDigitizer, MilImage );


     printf("An Image has been Grabbed\n");
 
     getchar();

    /*  처음에 할당한 ID들을 해제 합니다. */

    MappFreeDefault( MilApplication,  MilSystem, MilDisplay, MilDigitizer, MilImage );


}



위에서 각 ID들을 할당하고 해제시켜주는 것은 모든 응용프로그램에서 동일하다.

다만 각 경우에 따라 각 ID들을 따로 할당시키고 각각해제할 수 있습니다.

각각의 MIL_ID를 할당 및 해제하는 함수는 다음과 같다.

MilApplication - MappAlloc , MappFree

MilSystem - MsysAlloc,  MsysFree

MilDisplay - MdispAlloc,  MdispFree

MilDigitizer - MdigAlloc,  MdigFree

MilImage -    MbufAlloc2d , MbufAllocColor, MbufFree,  etc....



여기서 주의 할 점은 할당 해제시 순서이다.

할당시에는  
  MappAlloc  -> MsysAlloc  -> MdigAlloc  -> MdispAlloc - > MbufAlloc 


해제시에는  
 MbuffFree  ->  MdispFree  -> MdigFree ->  MsysFree  -> MappFree




■ MilImage를 파일로 저장하거나 불러오는 방법

MIL에서 기본으로 사용하는 Image Format은  *.mim형태의 tiff형식의 파일입니다.

따라서  MbufLoad와  MbufSave를 다음과 같이 사용하시면  mim파일로 저장 또는 불러오기가 가능.

MbufLoad( "load.mim", MilImageLoaded );
MbufSave("save.mim"  MilImagfeSaved);

그러나 일반적으로 사용하는 포맺인 jpeg나 tiff, raw등의 이미지 파일 포맺은 다음의 함수를 사용하여 저장 불러오기가능.

MbufImport( "sample.jpg", M_JPEG_LOSY, M_RESTORE, MilSystem, &MilImage);
MbufExport( "sample.tif",  M_TIFF, MilImage );

그리고 Image의 sequence를 avi파일로도 저장이 가능한다. 이때는 
MbufImprtSequence,  MbufExportSequence 함수를 이용하면 된다.




■ MIL을 이용한 프로세싱 시간 측정.

프로그램을 직접 작성하다 보면 각 부분들은 성능을 측정하고, 디버깅을 위해 Timer가 필요한 경우가 많다.
이럴경우 Mil에서 제공하는 MappTimer를 사용하면 된다.,

  /* Return되는 시간값의 단위는 sec(초) 이고 따라서 보통 Time * 1000(ms)로 사용합니다. */


double Time;
MappTimer(M_TIMER_RESET, M_NULL);

/*이곳에 시간측정 대상이 되는 프로세스가 들어간다.*/

MappTimer(M_TIMER_READ, &Time);


Mil 기초적 파악사항 - 1

2017.02.20 10:32

Mil을 이용한 프로그래밍을 위해서는 라이브러리에 대한 기본적인 구조를 알아야한다.

카메라로부터 영상을 획득해 디스플레이 하거나, 처리를 해주기 위해서는 다음과 같은 5가지 요소가 필요합니다.

먼저 이 5가지 요소에 대한 선언을 해주고 프로그램 초기화부분에 Allocate해줍니다. 마지막으로

프로그램이 종료할때 Free를 해주면 됩니다. 



■ 선언

MIL_ID Application;
MIL_ID System;
MIL_ID Digitizer;
MIL_ID Display;
MIL_ID Buffer;

■ Allocate

 MappAlloc() // Application 할당
 MsysAlloc() // 프레임그래버 할당
 MdigAlloc() //  카메라 할당.
 MdispAlloc() // 디스플레이 할당
 MbuffAlloc2d() // Buffer할당 


■ Free

마지막으로 프로그램 종료되기 전 Free를 해주면 됩니다. 여기에서 Free는 할당의 역순으로 하면된다.

MbuffFree();
MdispFree();
MdigFree();
MsysFree();
MappFree();


이상이 가장 기본적인 구조입니다. 더 자세한 사항은 다음을 참고하기시길 바랍니다.
CD안에 들어있는 User guide Manual의 28페이지를 참고.

영상을 획득하기 위한 함수로는 MdigGrabContinuous()와  MdigGrab()이 쓰입니다.



■  MdigGrabContinuous( DigId,  DestImageBufId );

MdigGrabContinuous() 함수는 하나의 버퍼공간에 계속 데이터를 덮어쓰면서 연속적인 Grab를 합니다.

영상처리를 위한 버퍼로는 거의 쓰이지 않습니다. 영상처리를 위해서라면 아래에 설명되는
MdigGrab() 함수를 쓰기 바랍니다.

MdigGrabContinuous() 함수를 종료하기 위해서는  MdigHalt() 명령어를 써서 종료하여야 한다.



■  MdigGrab( DigId, DestImageBufId )

MdigGrab() 함수는 하나의 Buffer또는 여러개의 Buffer에 영상데이터를 저장시킵니다.

거의 모든 Application에서는 MdigGrab()를 이용합니다.

MdigGrab()을 한번 수행하면 단지 한장의 영상데이터만을 가져오므로, 연속적인 저장을 위해서는 
for문이나 while문 Do문 ,  HookFunction();  Thread를 이용해서 계속적인 호출을 발생
시켜야 합니다.




여기서는 카메라로부터 받아들인 데이터를 화면상에 디스플레이 해주는 방법에 대해서 알아보겠습니다.


MdispAlloc();  // 을 이용해서 디스플레이를 할당시켜줍니다.



그리고 가장 중요한 것은 디스플레이 시켜줄곳에 대한 Select를 해주어야 합니다.

1. MdispSelect() // MIL이 제공하는 Tool에 디스플레이
2. MdispSelectWindow();  // user가 원하는 곳에 디스플레이



위의 두가지 중에 하나를 쓰면 되는데, 첫번째것은 Mil에서 제공되는 Display Box에 디스플레이를 해주며,
두번째 것은 User가 원하는 곳에 디스플레이를 해줍니다.


MdispSelectWindow(  DisplayId,  ImageBufId,  ClientWindowHandle  );

- 첫번째 인자는 디스플레이 ID, 두번째 인자는 Buffer ID,  세번째는 윈도우 핸들러로 m_hWnd를 쓰면
현재 ClientWindowHandle에 디스플레이 해주며, 유저가 원하는 디스플레이를 원하면 핸들러를 만들어서 그곳의 핸들러를
입력시켜주면 됩니다.


물론, ImageBufId값에  MdigGrab()  or  MdigGrabContinuous()를 이용하여 넣어주어야  디스플레이가 됩니다.

Mil에서 영상데이터에 접급하는 방법은 2가지 방법, 사용자가 택일해서 사용해야한다




■ MbufGet()  

 - MbufGet() 명령어는 버퍼를 유저가 지정한 Array에 입력시킬수 있습니다. 유저 Array로 가져온 데이터는 유저가 
 원하는대로 조작 ( 이진화, Edge추출등..  ) 할 수가 있습니다.

그럼 직접 영상데이터를 Access해 보겠습니다.





BYTE Buffer[480][640];
MdigGrab(DigitizerID, MilImage);
MbufGet2d( MilImage, 0, 0, 640, 480, &Buffer );

이렇게 해주면, MilImage의 버퍼를 Buffer라는 유저Array로 가져올수 있습니다.
그러면, Buffer를 조작할 수 있스빈다. 가령 이진화를 한다면....


for(int i=0; i<480; i++)
{
    for(int j=0; j<640; j++)
    {

       if( Buffer[i][j] > 128 )

Buffer[i][j] =  255;
       

       else 
            Buffer[i][j] = 0;


     }
}


위와같이 해주면 되겠져.
그러나 이렇게만 해준다면 다 끝난게 아닙니다. 변경된 데이터값을 다시 원래 Buffer에 넣어주어야합니다.
그 명령어는 MbufPut() 이라는 명령어입니다.  다음과 같습니다.

MbufPut2d( MilImage, 0, 0, 640, 480, &Buffer );


이렇게만 해주면 완벽한 이진화를 할 수 있습니다. 하지만 단점은 매 영상을 MbufGet를 이용해 얻어와서
처리를 한 다음 다시 MbufPut()를 이용해서 넣어줘야 하므로, 프로세싱 타임이 길어지
게된다.
하지만 가장 쉽게 접근할 수 있는 장점도 있다.



■ MbufInquire()    

이 명령어는 위의 경우와는 다르게 한번만 적어놓으면, 연결시켜둔 버퍼의 내용이 변경되더라도 자동적으로
갱신되게 됩니다.( 왜냐하면 주소에 직접연결되기 때문 ), 그렇기 때문에 프로세싱 을 하는 시간은 훨씬 효율적
.
쓰이는 방법은 다음과 같습니다. 역시 이진화를 예로 들겠습니다.


BYTE *  BufferAddress;               
MbufAlloc2d( ....., &MilImage);                                           // 주소값을 받아온다.
MbufInquire(MilImage, M_HOST_ADDRESS, &BufferAddress);


이렇게 선언을 해 놓습니다. 그러면 MilImage의 내용이 변경되더라도 자동적으로 
BufferAddress는 갱신되게 됩니다.


for(int i=0; i<480; i++)
{
    for(int j=0; j<640; j++)
    {

        if(BufferAddress[ i * 640 + j ]  > 128  )
            BufferAddress[ i * 640 + j ]  = 255;

        else
            BufferAddress[ i * 640 + j ]  = 0;
  
    }
}


이렇게 해주면 이진화는 완벽하게 구현.
그러면 자동적으로 MilImage의 버퍼도 이진화가 되어있을 것입니다. 하지만 그냥 보이는것은 이진화가 되지 않은
영상일 것입니다. 이 부분은 변경되어진 것을 갱신
시켜주어야 하는데 그럴때 다음의 명령어를 추가


MbufControl( MilImage,  M_MODIFIED, M_DEFAULT );





■ 오버레이 ( Overlay )

버레이란 원영상에는 영향을 미치지 않고 ( non-destructively ) 윈도우 화면이나 외부화면에 디스플레이 해줄수 있는
일종의 버퍼를 말합니다. 간단하게 설명하면, 원래의 버퍼위에 투명버퍼를 씌운
다고 생각하면 쉬울 것.


■ 프로그래밍

1. 먼저 오버레이를 쓸 수 있게끔 해줍니다.
MdispControl( DisplayID, M_WINDOW_OVR_WRITE, M_ENABLE );

2. 디스플레이 하기 위한 버퍼를 선택합니다.
MdispSelect( DisplayID, ImageBufID  ,   MdispSelectWindow();

3. Display할 버퍼와 연결시킬 오버레이 버퍼 인자를 적습니다.
MdispInquire( DisplayID, M_WINDOW_OVR_BUF_ID, &OverlayBufferID );


이렇게 선언을 하고, OverlayBuferID값에 글씨나 그림을 넣어줄 수 있습니다. 그런데, 이 오버레이 버퍼를 
clear하려고 하면 ????

검정색이나 흰색으로 clear를 한다면 우리가 보는 영상은 까맣거나, 하얗게 됩니다.
즉 원 영상과 같은 그림으로 clear를 해주어야 하는 것입니다. 

이렇게 하기 위해서는 다음과 같이 key칼라를 얻어와서 그것을 이용해 clear를 해준다.

4. MdispInquire( DisplayID, M_KEY_COLOR, &TransparentColor );
5. MbufClear( OverlayBufferID, TransparentColor );
이상입니다.



■ RGB버퍼는 packed나 planer 중에 하나의 방식으로 저장되게 됩니다.



▶ packed : packed는 RGB버퍼의 성분이 다음과 같이 구성되어 있습니다.

즉  BGRBGRBGRBGRB... 이런식으로  같은 속성을 가진 버퍼를 아래와 같은 형식으로
R,G,B를 분리해 낼수 있습니다.




BYTE * GrabAddress;
MbufInquire ( BufferID, M_HOST_ADDRESS, &GrabAddress );


for(int i=0; )
{
     for(int j=0; )
    {

GrbAddress[ i * ( SizeX ) * 3    +   k*3+0   ]     // Blue
GrbAddress[ i * ( SizeX ) * 3    +   k*3+1   ]     // Green
GrbAddress[ i * ( SizeX ) * 3    +   k*3+2   ]     // Red
     }
}





▶ Planner : Planner 는 RGB버퍼의 성분중에 모든 R성분들이 연속적으로 저장되어져 있고, 그 다음에 B성분들이
... 마지막으로 G성분들이 연속적으로 저장되어 있습니다.  아래와 같이 R, G, B를 분리 해 낼 수 있습니다.
즉 다음과 같습니다.   
   RRRRRRRRRRRRRRRR....BBBBBBBBBBBBBBBB....GGGGGGGGG....



BYTE * GrabAddress;
MbufInquire( BufferID, M_HOST_ADDRESS, &GrabAddress );

for(int i=0; i<480; i++)
{
    for(int j=0;  j<640; j++)
    {
         GrabAddress[ i*640 + j + (640* 480 * 0 ) ];  // Blue 성분
         GrabAddress[ i*640 + j + (640* 480 * 1 ) ];  // green 성분
         GrabAddress[ i*640 + j + (640* 480 * 2 ) ];  // Red 성분
    }
}




실시간 영상처리를 위한 하나의 방법으로  Hook-Function을 쓰게 됩니다. 그럼 Hook-Function에 대해서 ...



■ Hook-Function이란?
   Hook-Function이란 말 그대로 Digitizer( Frame Grabber ) 로 부터 발생된 Event를 가로채는 함수를 말합니다.
Event로 부터 가로챈 함수는 별개의 Thread로 실행합니다.  이것은 Hook Function이 비동기적으로 실행되게 합니다.


- Hook Function의 발생.  Hook Function의 이벤트는 다음과 같은 여러 종류의 이벤트에 따라 적용시킬수 있습니다.

M_GRAB_START ( hook to the start of each grab )
M_GRAB_END( hook to the end of the each grab )
M_GRAB_FRAME_START( hook to the start of grabbed frames ) 
M_GRAB_FRAME_END( hook tothe end of grabbed frames )
M_GRAB_FIELD_END( hook to the end of grabbed fields)
M_GRAB_FIELD_END_ODD( hook to the end of grabbed odd fields )
M_GRAB_FIELD_END_EVEN ( hook to the end of grabbed even fields )

즉 위와 같은 상황에서 hook event를 얻어올 수 있는 것입니다.

예를들어 M_GRAB_START의 이벤트를 가져오려면 다음과 같이 사용하면 된다.
 

MdigHookFunction( DigID, M_GRAB_START, HookHandlerPtr, UserDataPtr );

여기서 HookHandlerPtr은 다음과 같은 형식으로 정의하시면 됩니다.
long MFTYPE HookHandler( HookType, EventId, UserDataPtr );

long HookType;  // Type of event hooked
MIL_ID EventId;  //  Event Identifier  ( Currently set to null )
void MPTYPE * UserDataPtr; // user Data Pointer


■ 연속적인 Hook Function의 실행.

실시간 처리를 위해서는 Grab를 지속적으로 해주어서.. 여기에서 나오는 Event를 가지고 프로세싱을 해주면 됩니다.
 

즉, 먼저 MdigGrab() 명령어를 실행시켜서 정의한 이벤트가 발생되면 Hook Function으로 들어가게 됩니다 그리고 Hook Function안에서
 

처리를 해주고 마지막에 MdigGrab 명령어를 다시 넣어주면 또 다시 MdigGrab의 이벤트를 받아서 처리를 해주게 됩니다.
이런식으로 계속적인 Grab과 프로세싱이 가능합니다.

■ Hook Fucntion의 종료

 Hook Fucntion의 종료할때에는 위해서 얻어온 이벤트와 같은 Hook Event +  M_UNHOOK 라고 쓰면 됩니다.

MdigHookFuction( DigId, M_GRAB_START+M_UNHOOK, HookHandlerPtr, UserDataPtr );