. 다운로드 대화상자

원격지의 파일을 다운로드하거나 업로드하는 것은 굉장히 느리다. 네트워크 속도가 아무리 빠르다 하더라도 물리적인 여러 계층을 통과해야 하며 에러 발생 가능성도 높기 때문에 로컬 파일보다는 느리고 불확실할 수밖에 없다. 이런 느린 동작을 할 때는 사용자를 마냥 기다리게 할 수 없으며 지금 어디쯤 전송하고 있고 남은 시간은 얼마인지 보여주어야 한다. 시간이 오래 걸리는 것은 사용자들도 이해하기 때문에 별 문제가 되지 않는다.

또한 전송 중간에 취소가 가능해야 한다. 열고자 하는 파일이 아닌 다른 파일을 실수로 선택할 수도 있고 너무 속도가 느려 더 기다릴 수가 없을 때는 언제든지 전송을 취소할 수 있도록 해야 한다. 당근은 전송 과정을 보여주고 취소 명령을 입력받기 위해 다운로드 대화상자를 사용하며 리소스에 다음과 같이 작성되어 있다.

전송 과정을 백분율로 보여주는 프로그래스 컨트롤과 취소 명령을 입력받기 위한 버튼이 있고 그림에 보이지는 않지만 위쪽에 두 개의 스태틱 컨트롤이 배치되어 있다. 위쪽 스태틱에는 전송중인 파일의 이름을 보여주고 아래쪽 스태틱에는 전송된 바이트 수를 보여줄 것이다. 다음 전역변수는 전송 계속 여부를 통제한다.

 

BOOL bContDown;

 

FindInFiles 함수에서 사용했던 bContFIF 변수와 거의 의미가 같다. 네트워크 전송 함수들은 이 변수가 TRUE인 동안 계속 다운로드받으며 이 변수가 FALSE가 되면 전송을 중지하고 즉시 리턴한다. 다운로드 대화상자는 사용자가 취소 버튼을 클릭했을 때 이 변수를 FALSE로 바꾸어 전송 취소를 명령하게 된다. 대화상자 프로시저는 다음과 같이 작성한다.

 

BOOL CALLBACK DGDownProc(HWND hDlg,UINT iMessage,WPARAM wParam,LPARAM lParam)

{

     TCHAR Mes[128];

    

     switch(iMessage)

     {

     case WM_INITDIALOG:

          MoveToParentCenter(hDlg);

          SendDlgItemMessage(hDlg, IDC_PRODOWN, PBM_SETRANGE, 0, MAKELPARAM(0,100));

          SendDlgItemMessage(hDlg, IDC_PRODOWN, PBM_SETPOS, 0, 0);

          return TRUE;

     case WM_USER+1:

          if (lParam==-1) {

              wsprintf(Mes,"%d 바이트 다운로드 중(전체 크기는 알수 없음)",wParam);

          } else {

              wsprintf(Mes,"%d 바이트 중 %d 바이트 전송 중(%d%%)",

                   lParam,wParam,wParam*100/lParam);

              SendDlgItemMessage(hDlg, IDC_PRODOWN, PBM_SETPOS, wParam*100/lParam, 0);

          }

          SetDlgItemText(hDlg,IDC_STDOWN2,Mes);

          return TRUE;

     case WM_COMMAND:

          switch (LOWORD(wParam))

          {

          case IDCANCEL:

              if (MessageBox(hDlg,"전송을 취소하시겠습니까? 업로드중에 취소하시면 파일의 "

                   "일부만 수정되므로 위험합니다.","질문",MB_YESNO)==IDYES) {

                   bContDown=FALSE;

                   EndDialog(hDlg,IDCANCEL);

              }

              return TRUE;

          }

          return FALSE;

     }

     return FALSE;

}

 

WM_INITDIALOG에서 프로그래스 컨트롤의 범위를 0~100으로 설정했으며 IDCANCEL 버튼을 클릭하면 bContDown FALSE로 변경한다. DgHttpDown 함수에서 이 대화상자를 어떻게 사용하는지 코드를 보자. 먼저 bContDown TRUE로 설정하여 다운로드 루프가 계속 진행하도록 초기화하며 다운로드 대화상자를 모델리스로 생성한다. 이 대화상자가 열려 있는 동안 다른 작업을 할 수는 없으므로 메인 윈도우는 사용 금지된다.

위쪽 스태틱 컨트롤에 접속중... 메시지를 출력하고 접속된 후에는 다운로드받을 파일의 경로를 출력하였다. 다운로드 루프에서는 bContDown을 계속 점검하여 이 값이 TRUE인 동안만 다운로드를 계속하며 이 값이 FALSE가 되는 즉시 루프를 탈출한다. 다운로드가 진행될 때마다 대화상자로 WM_USER+1 메시지를 전달하는데 이때 lParam에는 총 바이트 수, wParam에는 전송된 바이트 수가 전달된다. 다운로드 대화상자는 WM_USER+1 메시지를 받았을 때 아래쪽 스태틱에 전송된 바이트 수를 보여주고 프로그래스 바의 위치를 갱신한다.

, HTTP 프로토콜은 원격지의 파일 크기를 미리 알 수 없기 때문에 이 경우 lParam으로는 -1이 전달되며 이때는 단순히 받은 바이트 수만 출력하도록 했다. 이 루프가 실행중인 동안에 사용자가 취소 버튼을 클릭할 수 있어야 하므로 메시지 펌핑을 해야 한다. 다운로드가 완료되면 메인 윈도우를 활성화시키고 다운로드 대화상자는 파괴한다. 이후 FTP 다운로드, FTP 업로드 함수에 대해서도 이 대화상자는 동일한 방식으로 사용된다.