[API] Drag&Drop

simpled 2013.06.23 16:05 조회 수 : 6545

Drag&Drop은 매우 흔한 개념의 이벤트이며 메시지이다.
하지만 막상 구현할려고 하면 막연한데,
1. 파일의 경로를 받아야 하고
2. 파일의 이름을 받아야 하고
3. 파일의 확장자를 받아야 하며
4. 파일의 내용을 긁어 올 수 있는 함수나 클래스가 준비되어 있어야 하고
5. 그 데이타를 저장 or 임시보관하여 조작 할 수 있어야 하기 때문이다.

일단 다이얼로그안에서 아무 리소스나 붙여 넣어서 에디터 속성 창의 Accept file 속성에서 true값을 설정해 주면 된다.
하지만 FPS 게임이 아닌 이상, 편이성을 고려해야 하기 때문에, 필자는 다이얼로그 자체의 Accept file 속성을 true로 설정해 주었다.

005.png

<그림 1 :: 다이얼 로그의 Accept file속성 true>


그리고 인터넷 검색 결과, Accept file->true의 윈도우에서 파일이 드랍되면 다음과 같은 메시지가 떨어진다고 한다.
이것도 상당히 힘들게 검색했다.

WM_DROPFILES
 
그런데 이것에 문제점이 있다.
바로 파일의 경로를 불러오고 쓰는 함수들이 ERROR C1189에 걸린다는 점이다.

에러코드를 검색해보면 쉬웠는데, 나는 함수를 헤더파일 선언으로만 해결하려 해서 시간을 많이 잡아먹었다.
결국 에러코드를 설명해주는 사이트를 찾았다. : http://asas0653.blog.me/120114250706

001.png
<그림 2 :: 일단 프로젝트를 우클릭 하여 속성으로 간다.>

002.png
 <그림 3 :: MFC사용에서 공유 DLL을 선택한다. 이때 DEBUG 뿐만 아니라 Release 모드에서도 똑같이 적용시켜야 한다.>

그럼 또 에러가 나오는데, MFC에서는 windows.h 헤더파일을 사용하지 않는다는 개소리다.]
003.png

 <그림 4 :: 윈도우 헤더파일을 주석처리 한 모습.>



004.png
 <그림 5 :: MFC함수인 DragQueryFile이 오류없이 빌드된 모습>

마지막으로 다이얼로그 함수를 다음과 같이 변경해 주면 일사천리다.

아이디는 그림 6을 참고하도록 !



005 (1).png
 <그림 6 :: 다이얼로그의 ID값 설정>

 

INT_PTR CALLBACK Open(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)

{

        int wmId, wmEvent;

        UNREFERENCED_PARAMETER(lParam);

       

        LPTSTR pFileName;

        DWORD dwNumDrop;

        DWORD dwBufSize;

        CString strFileName;

        TCHAR tcFileName[128];

       

        switch (message)

        {

               case WM_INITDIALOG:

                       return (INT_PTR)TRUE;

                      

               case WM_DROPFILES:

                       // dwNumDropFile의개수를입력받는다.

                       dwNumDrop = DragQueryFile((HDROP)wParam, 0xFFFFFFFF, NULL ,0);

 

                       // dwNumDrop만큼for문을돈다

                       for(DWORD i=0L; i<dwNumDrop; i++)

                       {

                              // i번째에해당하는파일의버퍼사이즈를불러온다.

                              dwBufSize = DragQueryFile((HDROP)wParam, i, NULL ,0L) + 1;

 

                              // 버퍼사이즈만큼TCHARLPTSTR 형식으로동적할당취한다.

                              pFileName=(LPTSTR)new TCHAR [dwBufSize];

                             

                              // 난 DragQueryFile 함수가뭐하는녀석인지잘모른다.

                              // 하지만 주석 처리 하면 프로그램 에러가 난다는 것은 잘 알고있다.

                              DragQueryFile((HDROP)wParam, i, pFileName, dwBufSize);

 

                              // 클래스변수(strFileName)에포인터변수의내용(pFileName)을초기화시킨다.

                              strFileName=pFileName;

                             

                              // 포인터변수를동적해제시킨다.

                              delete []pFileName;

       

                              // 클래스변수를ID_DLG_FILE_PATH 에출력시킨다.

                              SetDlgItemText(hDlg, ID_DLG_FILE_PATH, strFileName);

                             

                              // 클래스변수를TCHAR 변수에초기화시킨다.

                              wsprintf(tcFileName, strFileName);

 

                              // TCHAR 변수에있는File의경로(Path)를지워준다.

                              PathStripPath(tcFileName);

 

                              // file명과확장자만존재하는TCHAR 변수를ID_DLG_FILE_NAME에출력한다.

                              SetDlgItemText(hDlg, ID_DLG_FILE_NAME, tcFileName);

                       }

                       break;

 

               case WM_COMMAND:

                       wmId    = LOWORD(wParam);

                       wmEvent = HIWORD(wParam);

                       if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL)

                       {

                              EndDialog(hDlg, LOWORD(wParam));

                              return (INT_PTR)TRUE;

                       }

                       switch (wmId)

                       {

                              case ID_DLG_FILE_PATH:

                                      break;

 

                              case ID_DLG_FILE_NAME:

                                      break;

 

                              case ID_DLG_FILE_DRAG:

                                      break;

 

                              case ID_DLG_FILE_OK:

                                     

                                      SendMessage(hDlg, WM_COMMAND, IDOK, IDCANCEL);

                                      break;

                       }

                       break;

        }

        return (INT_PTR)FALSE;

}