home *** CD-ROM | disk | FTP | other *** search
/ PC World Komputer 1996 December / PCWKCD1296.iso / vjplusb / activex / inetsdk / samples / wininet / asyncftp / cdlg.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  1996-06-04  |  47.6 KB  |  1,591 lines

  1.  
  2. #include <windows.h>
  3. #include <tchar.h>
  4. #include <commctrl.h>
  5. #include <wininet.h>
  6. #include "comctlhd.h"
  7. #include "cdlgopt.h"
  8. #include "clist.h"
  9. #include "cdlg.h"
  10. #include "capp.h"
  11. #include "resource.h"
  12.  
  13. extern CApp *lpCApp;
  14.  
  15.  
  16.  
  17. //**********************************************************************
  18. // CDlg::CDlg
  19. //
  20. // Purpose: Constructor for CDlg class
  21. // Parameters: 
  22. //      HANDLE hInst  - Instance handle for this instance from WinMain
  23. //
  24. //********************************************************************
  25.  
  26. CDlg::CDlg(HINSTANCE hInst)
  27. {
  28.     m_hInst = hInst;
  29.     m_hWnd = NULL;
  30.     m_pszUser = m_szUser;
  31.     lstrcpy(m_pszUser, _TEXT("anonymous"));
  32.     m_pszPwd = m_szPwd;
  33.     *m_pszPwd = NULL;
  34.     m_pszProxy = m_szProxy;
  35.     *m_pszProxy = NULL;
  36.     m_dwAccessType = INTERNET_OPEN_TYPE_DIRECT;
  37.     m_anonymous = 1;
  38.     m_hmnu = NULL;
  39.  
  40.     //initialize global handle used to cancel requests
  41.     m_hLastHandleCreated = NULL;
  42.         
  43.     //initialize global session handle
  44.     m_hSession = NULL;
  45.  
  46. }
  47.  
  48.  
  49. //**********************************************************************
  50. // CDlg::~CDlg
  51. //
  52. // Purpose: Destructor for CDlg class
  53. //********************************************************************
  54.  
  55. CDlg::~CDlg()
  56. {
  57.     delete m_pcctrl;
  58.     return;
  59. }
  60.  
  61. //**********************************************************************
  62. // CDlg::Init
  63. //
  64. // Purpose: Create and show modeless dialog
  65. //
  66. // Parameters: 
  67. //    nCmdShow        int from WinMain
  68. //
  69. // Return Value:  
  70. //    BOOL - TRUE if initialization succeeded, FALSE otherwise.
  71. //
  72. //********************************************************************
  73.  
  74. BOOL CDlg::Init(int nCmdShow)
  75. {
  76.     m_hWnd = CreateDialog(m_hInst, MAKEINTRESOURCE(IDD_DIALOG1), NULL, (int (__stdcall *)(void))DialogProc);
  77.  
  78.     // If window could not be created, return "failure"
  79.     if (!m_hWnd) 
  80.         return FALSE;
  81.  
  82.     ShowWindow(m_hWnd, nCmdShow);
  83.     
  84.     return TRUE;
  85. }
  86.  
  87.  
  88. //**********************************************************************
  89. // CDlg::OnGoto
  90. //
  91. // Purpose: Event handler for initiating an Internet connection
  92. //          and enumerating directories after user has entered a URL
  93. //
  94. // Parameters: None
  95. //
  96. // Return Value:  
  97. //    BOOL - TRUE if initialization succeeded, FALSE otherwise.
  98. //
  99. //********************************************************************
  100.  
  101. BOOL CDlg::OnGoto(DWORD dwParam)
  102. {
  103.     TCHAR szURL[80], bufURL[80], szServer[80], msgbuf[80];
  104.     TVNODEINFO tvnodei;
  105.     LPTVNODEINFO lptvnodei;
  106.     TVDATA tvdta;
  107.     HTREEITEM hItem;
  108.     HINTERNET hConnect;
  109.     int RequestType;
  110.     DWORD dwContext;
  111.     BOOL ret;
  112.     
  113.     if (0 == dwParam)
  114.     {
  115.     RequestType = REQUEST_NEW_INTERNET_SITE;
  116.  
  117.     //obtain the URL entered by the user
  118.     ::GetWindowText(GetDlgItem(m_hWnd, IDC_URL), szURL, 80);
  119.     if (0 == lstrlen(szURL))
  120.     {
  121.         MessageBox(m_hWnd, TEXT("Please enter a URL"), TEXT("Error"), MB_ICONEXCLAMATION | MB_OK) ;
  122.         return FALSE;
  123.     }
  124.     if (0 == lstrlen(m_pszUser) || 0 == lstrlen(m_pszPwd))
  125.     {
  126.         MessageBox(m_hWnd, TEXT("Please set user and password under Options"), TEXT("Error"), MB_ICONEXCLAMATION | MB_OK) ;
  127.         return FALSE;
  128.     }
  129.  
  130.     }
  131.     else
  132.     {
  133.         ret = Animate_Play(GetDlgItem(m_hWnd, IDC_ANIMATE1), 0, -1, -1);
  134.         lptvnodei = (LPTVNODEINFO)dwParam;
  135.         lstrcpy(szURL, lptvnodei->pszSite);
  136.         ParseServer(szURL, bufURL, szServer);
  137.         wsprintf(msgbuf, TEXT("Querying %s ..."), bufURL);
  138.         SendMessage(GetDlgItem(m_hWnd,STATUSBAR_CONTROL_ID), SB_SETTEXT, 0, (LPARAM)msgbuf);
  139.  
  140.         lstrcpy(lptvnodei->pszServer, szServer);
  141.         dwContext = (DWORD)lptvnodei;
  142.         InetConnect(lptvnodei->pszServer, &hConnect, dwContext);
  143.         return TRUE;
  144.  
  145.     }
  146.     ret = Animate_Play(GetDlgItem(m_hWnd, IDC_ANIMATE1), 0, -1, -1);
  147.  
  148.     //parse the server name if the URL contains protocol 
  149.     //information (i.e., ftp://).  Also prepend the ftp:// to
  150.     //the URL if not entered for tracking purposes later in 
  151.     //the TreeView control.
  152.     ParseServer(szURL, bufURL, szServer);
  153.  
  154.     wsprintf(msgbuf, TEXT("Opening %s ..."), bufURL);
  155.     ret = SendMessage(GetDlgItem(m_hWnd,STATUSBAR_CONTROL_ID), SB_SETTEXT, 0, (LPARAM)msgbuf);
  156.  
  157.  
  158.     //the TVDATA structure holds information to create and 
  159.     //insert a TreeView item
  160.     //SETTVDATA(tvdta, 1, 1, bufURL, NULL);
  161.     SETTVDATA(tvdta, 1, 1, NULL);
  162.  
  163.     //the TVNODEINFO structure holds key information for 
  164.     //a TreeView item (32-bit lParam value of the TV_ITEM structure)
  165.     SETTVNODEINFO(tvnodei, NULL, FALSE, hConnect, bufURL, 0,0, NULL, TEXT(""));
  166.  
  167.     tvnodei.requestType = RequestType;
  168.  
  169.     hItem = m_pcctrl->TreeViewAdd(bufURL, &tvdta, &tvnodei, &dwContext); 
  170.     lptvnodei = (LPTVNODEINFO)dwContext;
  171.     lptvnodei->hTreeItem = hItem;
  172.     lstrcpy(lptvnodei->pszServer, szServer);
  173.  
  174.     //InternetOpen and InternetConnect
  175.     InetConnect(lptvnodei->pszServer, &hConnect, dwContext);
  176.  
  177.     return TRUE;
  178.  
  179. }
  180.  
  181. void CDlg::InetConnect(LPTSTR lpstrURL, LPHINTERNET phConnect, DWORD dwContext)
  182. {
  183.     INTERNET_STATUS_CALLBACK dwISC;
  184.     DWORD dwError;
  185.     TCHAR buf[80], szEditText[STRMAX];
  186.  
  187.     if (NULL == m_hSession)
  188.     {
  189.     m_hSession  = ::InternetOpen(TEXT("AsyncFtp"),
  190.                                   m_dwAccessType,
  191.                                   m_szProxy,
  192.                                   '\0',
  193.                                   INTERNET_FLAG_ASYNC);
  194.     }
  195.     dwError = GetLastError();
  196.     if (NULL == m_hSession)
  197.     {
  198.         wsprintf(buf, TEXT("InternetOpen failed - error code: %d"), dwError);
  199.         SendMessage(GetDlgItem(m_hWnd,STATUSBAR_CONTROL_ID), SB_SETTEXT, 0, (LPARAM)buf);
  200.         lstrcat(buf, TEXT("\r\n"));
  201.         GetWindowText(GetDlgItem(m_hWnd, IDC_STATUS), szEditText, STRMAX );
  202.         lstrcat(szEditText, buf);
  203.         SetWindowText(GetDlgItem(m_hWnd, IDC_STATUS), szEditText);
  204.  
  205.       return;
  206.     }
  207.  
  208.     dwISC = InternetSetStatusCallback(m_hSession, InternetCallback); 
  209.     if (INTERNET_INVALID_STATUS_CALLBACK == dwISC)
  210.     {
  211.         SendMessage(GetDlgItem(m_hWnd,STATUSBAR_CONTROL_ID), SB_SETTEXT, 0, (LPARAM)"Unexpected Error");
  212.         return;
  213.     }
  214.  
  215.     *phConnect = ::InternetConnect(m_hSession,
  216.                                   lpstrURL,
  217.                                   INTERNET_INVALID_PORT_NUMBER,
  218.                                   m_szUser,
  219.                                   m_szPwd,
  220.                                   INTERNET_SERVICE_FTP,
  221.                                   0,
  222.                                   (DWORD)dwContext); 
  223.  
  224.     dwError = GetLastError();
  225.     return;
  226. }
  227.  
  228. //**********************************************************************
  229. // CDlg::OnCommand
  230. //
  231. // Purpose: Process WM_COMMAND messages for the main dialog procedure
  232. //
  233. //********************************************************************
  234. BOOL CDlg::OnCommand(HWND hWnd, WPARAM wParam, LPARAM lParam)
  235. {
  236.     HTREEITEM htvitem;
  237.     TV_ITEM tvi;
  238.     LPTVNODEINFO lptvnodei;
  239.     UINT state1, state2;
  240.     TCHAR buf[80], msgbuf[80];
  241.     BOOL ret;
  242.     DWORD dwContext, dwError;
  243.     HWND hWndEdit;
  244.     node *pnode;
  245.     POINT pt;
  246.     CDlgOpt *lpCDlgOpt;
  247.     DLGDATA dlgdata;
  248.     
  249.         switch (LOWORD(wParam)) 
  250.         {
  251.             case IDCANCEL:
  252.                 DestroyWindow(hWnd);
  253.                 break;
  254.             case IDGOTO:
  255.                 OnGoto(0);
  256.                 break;
  257.             case IDC_CANCELREQ:  //cancel asynchronous request
  258.                 //an intermediate handle obtained from 
  259.                 //INTERNET_STATUS_HANDLE_CREATED is stored
  260.                 //in a global variable - the value is set
  261.                 //to zero once the request has been complete
  262.                 if (m_hLastHandleCreated)
  263.                 {
  264.                     InternetCloseHandle(m_hLastHandleCreated);
  265.                 }
  266.                 break;
  267.             case IDC_HELPABOUT:
  268.                    DialogBox(
  269.                     m_hInst,
  270.                     MAKEINTRESOURCE(IDD_HELPABOUT),
  271.                     hWnd,
  272.                     (DLGPROC)AboutDlgProc);
  273.  
  274.                 break;
  275.             case IDC_OPTIONS:
  276.                 dlgdata.pszUser = m_pszUser;
  277.                 dlgdata.pszPwd = m_pszPwd;
  278.                 dlgdata.pszProxy = m_pszProxy;
  279.                 dlgdata.dwAccessType = m_dwAccessType;
  280.                 dlgdata.anonymous = m_anonymous;
  281.                 //lpCDlgOpt = new CDlgOpt();
  282.                 //lpCApp->m_pCDlgOpt = lpCDlgOpt;
  283.                 lpCDlgOpt = lpCApp->m_pCDlgOpt;
  284.                 ret = lpCDlgOpt->Init(m_hInst, hWnd, &dlgdata);
  285.                 if (ID_SET == ret )
  286.                 {
  287.                     //store data 
  288.                     m_dwAccessType = lpCDlgOpt->m_dwAccessType;
  289.                     lstrcpy(m_pszProxy, lpCDlgOpt->m_pszProxy);
  290.                     lstrcpy(m_pszUser, lpCDlgOpt->m_pszUser);
  291.                     lstrcpy(m_pszPwd, lpCDlgOpt->m_pszPwd);
  292.                     m_anonymous = lpCDlgOpt->m_anonymous;
  293.  
  294.                 }
  295.                 //delete lpCDlgOpt;
  296.                 return 0;
  297.                 break;
  298.             case IDM_FILEGET:
  299.                 htvitem = TreeView_GetSelection(GetDlgItem(hWnd,TREEVIEW_CONTROL_ID));
  300.                 if (!htvitem)
  301.                     return FALSE;
  302.                 ret = m_pcctrl->TreeViewItem(htvitem, &tvi, TVIF_TEXT | TVIF_PARAM, buf);
  303.                 lptvnodei = (LPTVNODEINFO)(tvi.lParam);
  304.                 lstrcpy(lptvnodei->pszFile,lptvnodei->pszDir); 
  305.                 lstrcat(lptvnodei->pszFile,tvi.pszText); 
  306.                 lstrcpy(lptvnodei->pszFileTarget, tvi.pszText);
  307.  
  308.                 lptvnodei->requestType = REQUEST_FILETRANSFER;
  309.                 dwContext = (DWORD)lptvnodei;
  310.                 pnode = ((m_pcctrl->m_prootlvl[lptvnodei->index])->getfirstnode());
  311.                 wsprintf(msgbuf, TEXT("Downloading file from %s to %s ..."), lptvnodei->pszFile, lptvnodei->pszFileTarget);
  312.                 SendMessage(GetDlgItem(m_hWnd,STATUSBAR_CONTROL_ID), SB_SETTEXT, 0, (LPARAM)msgbuf);
  313.  
  314.                 ret = FtpGetFile(pnode->data.hConnect,
  315.                 lptvnodei->pszFile,lptvnodei->pszFileTarget , 1, FILE_ATTRIBUTE_ARCHIVE, FTP_TRANSFER_TYPE_ASCII, dwContext);
  316.                 dwError = GetLastError();
  317.                 break;
  318.  
  319.             case IDM_FILEOPEN:
  320.                 InetOpen();
  321.                 break;
  322.  
  323.             case IDM_FILEDELETE:
  324.                 htvitem = TreeView_GetSelection(GetDlgItem(hWnd,TREEVIEW_CONTROL_ID));
  325.                 if (!htvitem)
  326.                     return FALSE;
  327.                 ret = m_pcctrl->TreeViewItem(htvitem, &tvi, TVIF_TEXT | TVIF_PARAM | TVIF_HANDLE, buf);
  328.  
  329.                 InetDelete(&tvi);
  330.                 break;
  331.  
  332.             case IDM_DELETEDIR:
  333.                 htvitem = TreeView_GetSelection(GetDlgItem(hWnd,TREEVIEW_CONTROL_ID));
  334.                 if (!htvitem)
  335.                     return FALSE;
  336.                 ret = m_pcctrl->TreeViewItem(htvitem, &tvi, TVIF_TEXT | TVIF_PARAM | TVIF_HANDLE, buf);
  337.  
  338.                 InetDelete(&tvi);
  339.                 break;
  340.  
  341.             case IDM_CLEAR:
  342.                 //clear the editboxes
  343.  
  344.                 //screen coordinates
  345.                 GetCursorPos(&pt);
  346.                 hWndEdit = WindowFromPoint(pt);
  347.                 SetWindowText(hWndEdit, TEXT(""));
  348.                 break;
  349.  
  350.             //triggered when the user selects ENTER from the keyboard
  351.             case IDOK:
  352.                 if (GetFocus() == GetDlgItem(hWnd,IDC_URL))
  353.                 {
  354.                     OnGoto(0);
  355.                     break;
  356.                 }
  357.                 if (GetFocus() == GetDlgItem(hWnd,TREEVIEW_CONTROL_ID))
  358.                 {
  359.                     //if the item is expanded - collapse
  360.                     //if the item is collapsed - expand
  361.                     htvitem = TreeView_GetSelection(GetDlgItem(hWnd,TREEVIEW_CONTROL_ID));
  362.                     if (NULL == htvitem)
  363.                         return FALSE;
  364.                     ret = m_pcctrl->TreeViewItem(htvitem, &tvi, TVIF_STATE, buf);
  365.                     state1 = TVIS_SELECTED | TVIS_EXPANDEDONCE;
  366.                     state2 = TVIS_SELECTED | TVIS_EXPANDEDONCE | TVIS_EXPANDED ;
  367.                     
  368.                     tvi.mask = TVIF_SELECTEDIMAGE;
  369.  
  370.                     if (state1 == tvi.state) {
  371.                         ret = TreeView_Expand(GetDlgItem(hWnd,TREEVIEW_CONTROL_ID), htvitem, TVE_EXPAND);
  372.                         tvi.iSelectedImage = 1; }
  373.                     else if (state2 == tvi.state) {
  374.                         ret= TreeView_Expand(GetDlgItem(hWnd,TREEVIEW_CONTROL_ID), htvitem, TVE_COLLAPSE); 
  375.                         tvi.iSelectedImage = 2; }
  376.  
  377.                     ret = TreeView_SetItem(GetDlgItem(hWnd,TREEVIEW_CONTROL_ID), &tvi);
  378.  
  379.                     break;
  380.                 }
  381.                 break;
  382.             default:
  383.                 return FALSE;
  384.         }
  385.         return TRUE;
  386. }
  387.  
  388.  
  389. //**********************************************************************
  390. // CDlg::DialogProc
  391. //
  392. // Purpose: Main dialog procedure
  393. //
  394. //********************************************************************
  395. BOOL CALLBACK CDlg::DialogProc(HWND hWnd, UINT message,  WPARAM wParam, LPARAM lParam)  
  396. {
  397.     HTREEITEM htvitem;
  398.     LPTVNODEINFO lptvnodei;
  399.     TV_ITEM tvi;
  400.     NM_TREEVIEW *pTvnm;
  401.     TV_KEYDOWN *ptvkd;
  402.     HIMAGELIST himage;
  403.     LPTSTR lpstrSite = NULL;
  404.     DWORD dwError;
  405.  
  406.     HMENU hmenu;
  407.     RECT rect;
  408.     WORD wMenu;
  409.     POINT pt, pt1;
  410.     CDlg *lpCDlg = lpCApp->m_pCDlg;
  411.     CCommonCtrl *lpCmctrl = lpCDlg->m_pcctrl;
  412.  
  413.     TCHAR buf[80];
  414.     HWND hWndTV, hWndSB; 
  415.     BOOL ret, boolChangeImage;
  416.     static HBITMAP hbitmap;
  417.  
  418.     switch (message) 
  419.     {
  420.     case WM_INITDIALOG:
  421.  
  422.         //ensure that common controls DLL is loaded
  423.         InitCommonControls();
  424.  
  425.         //create a new class to take care of common controls manipulation
  426.         lpCDlg->m_pcctrl = new CCommonCtrl(lpCApp->m_hInst, hWnd);
  427.  
  428.         //initialize imagelist
  429.         if (!lpCDlg->m_pcctrl->ImageListInit())
  430.             break;
  431.  
  432.         //create a treeview and set its imagelist
  433.         lpCDlg->m_pcctrl->m_hWndTV = CreateWindowEx(WS_EX_LEFT,WC_TREEVIEW,TEXT(""),
  434.             TVS_HASLINES | TVS_LINESATROOT | TVS_HASBUTTONS | WS_VISIBLE | WS_CHILD,25,76,240,178,hWnd, 
  435.             (HMENU)TREEVIEW_CONTROL_ID, lpCApp->m_hInst, NULL);
  436.         hWndTV = lpCDlg->m_pcctrl->m_hWndTV;
  437.         himage = TreeView_SetImageList(hWndTV, lpCDlg->m_pcctrl->m_himg, TVSIL_NORMAL);
  438.         
  439.         //create a status bar
  440.         hWndSB = CreateWindowEx(0L, STATUSCLASSNAME, TEXT(""), WS_CHILD |
  441.             WS_BORDER | WS_VISIBLE , 150, 179, 600, 30, hWnd, (HMENU)STATUSBAR_CONTROL_ID,
  442.             lpCApp->m_hInst, NULL);
  443.  
  444.         //initialize the animation control
  445.         ret = Animate_Open(GetDlgItem(hWnd, IDC_ANIMATE1), MAKEINTRESOURCE(IDR_AVI1));
  446.  
  447.         dwError = GetLastError();
  448.  
  449.         //semaphore to use for FtpOpenFile/InternetReadFile - see comments
  450.         //under CDlg::InetOpen for details
  451.         lpCDlg->m_hFileDownload = CreateSemaphore(NULL, 1, 1, NULL);
  452.         
  453.         //bring up our logon dialog
  454.         PostMessage(hWnd, WM_COMMAND, (WPARAM)(MAKELONG(IDC_OPTIONS,BN_CLICKED)), (LPARAM)(GetDlgItem(hWnd,IDC_OPTIONS))); 
  455.         
  456.         //set focus to a particular control - so return FALSE
  457.         SetFocus(GetDlgItem(hWnd, IDC_URL));
  458.         return FALSE;
  459.  
  460.     case WM_SYSCOMMAND:
  461.         switch (wParam)
  462.         {
  463.             case SC_CLOSE:
  464.                 DestroyWindow(hWnd);
  465.                 break;
  466.             default:
  467.                 return FALSE;
  468.         }
  469.         break;
  470.  
  471.     //user define message passed back from Internet callback function
  472.     //indicating we need to open and enumerate a directory
  473.     case WM_INTERNETENUMERATE : 
  474.         lptvnodei = (LPTVNODEINFO)lParam;
  475.         lpCDlg->InetEnumerate(lParam, lptvnodei->hTreeItem);
  476.         break;
  477.  
  478.     //user define message passed back from Internet callback function
  479.     //indicating we need to open a file for read
  480.     case WM_INTERNETOPENFILE:
  481.         lpCDlg->InetOpen();
  482.         break;
  483.  
  484.     //user define message passed back from Internet callback function
  485.     //indicating we need to make a new Internet connection 
  486.     case WM_INTERNETCONNECT:
  487.         lptvnodei = (LPTVNODEINFO)lParam;
  488.         lptvnodei->requestType = REQUEST_INTERNET_CONNECT;
  489.         lpCDlg->OnGoto((DWORD)lParam);
  490.         break;
  491.     
  492.     //user define message passed back from Internet callback function
  493.     //indicating we need to make a new Internet connection and open
  494.     //and enumerate a directory
  495.     case WM_INTERNETENUMCONNECT:
  496.         lptvnodei = (LPTVNODEINFO)lParam;
  497.         ret = lpCDlg->m_pcctrl->TreeViewItem(lptvnodei->hTreeItem, &tvi, 
  498.                   TVIF_CHILDREN, buf);
  499.  
  500.         //enumflag reserved for future use for optimization
  501.         if (FILE_ATTRIBUTE_DIRECTORY == lptvnodei->dwAttributes &&
  502.                     !tvi.cChildren) //&& !lptvnodei->enumflag)
  503.         {
  504.         //set the enumflag and use TreeView_SetItem to replace the data
  505.         lptvnodei->requestType = REQUEST_INTERNET_CONNECT;
  506.         lpCDlg->OnGoto((DWORD)lParam);
  507.         }
  508.         break;
  509.  
  510.     //user define message passed back from Internet callback function
  511.     //indicating a file has been opened and it needs to be read
  512.     case WM_INTERNETFILEOPENED:
  513.             lpCDlg->InetRead(lParam);
  514.         break;
  515.  
  516.     //user define message passed back from Internet callback function
  517.     //indicating a FtpFindFirstFile was successful - try findnext again
  518.     case WM_INTERNETFILEFOUND:
  519.         ret = lpCDlg->InetEnumNext(lParam);
  520.         break;
  521.  
  522.     //user define message passed back from Internet callback function
  523.     //indicating a file transfer completed
  524.     //case WM_INTERNETFILETRANSFERRED:
  525.     //    SendMessage(GetDlgItem(lpCDlg->m_hWnd,STATUSBAR_CONTROL_ID), SB_SETTEXT, 0, (LPARAM)"File Transfer Completed");
  526.     //    break;
  527.     
  528.     //track cursor for right mouse clicks to display our menu
  529.     case WM_SETCURSOR:
  530.         //wParam has hwnd of window
  531.         if ((HWND)wParam == GetDlgItem(hWnd,IDC_EDIT1) || 
  532.             (HWND)wParam == GetDlgItem(hWnd,IDC_STATUS))
  533.         {
  534.         switch (HIWORD(lParam))
  535.         {
  536.             case WM_RBUTTONDOWN:
  537.                     if (NULL != lpCDlg->m_hmnu)
  538.                     {
  539.                         DestroyMenu(lpCDlg->m_hmnu);
  540.                         lpCDlg->m_hmnu = NULL;
  541.                     }
  542.                     //screen coordinates
  543.                     GetCursorPos(&pt);
  544.                     lpCDlg->m_hmnu = LoadMenu(lpCDlg->m_hInst,MAKEINTRESOURCE(IDM_EDITBOX));
  545.                     hmenu = GetSubMenu( lpCDlg->m_hmnu, 0 );
  546.  
  547.                     ret = TrackPopupMenu(hmenu, TPM_LEFTBUTTON | TPM_LEFTALIGN ,
  548.                     pt.x + 15, pt.y , 0, hWnd, NULL);
  549.  
  550.                 break;
  551.         }
  552.         break;
  553.         }
  554.  
  555.         break;
  556.  
  557.     //process the TreeView messages via WM_NOTIFY
  558.     case WM_NOTIFY:
  559.         pTvnm = (NM_TREEVIEW *)lParam;
  560.         hWndTV = lpCDlg->m_pcctrl->m_hWndTV;
  561.         switch (pTvnm->hdr.code)
  562.         {
  563.             case TVN_ITEMEXPANDING:
  564.  
  565.                 //get treeview item specifics
  566.                 ret = lpCDlg->m_pcctrl->TreeViewItem(pTvnm->itemNew.hItem, &tvi, 
  567.                       TVIF_TEXT | TVIF_PARAM, buf);
  568.  
  569.                 boolChangeImage = FALSE;
  570.                 //if a directory or a root level node change the selected image
  571.                 if (!_tcsstr(tvi.pszText,TEXT("ftp://"))) 
  572.                 {
  573.                     lptvnodei = (LPTVNODEINFO)(tvi.lParam);
  574.                     if (FILE_ATTRIBUTE_DIRECTORY == lptvnodei->dwAttributes)
  575.                         boolChangeImage = TRUE;
  576.                 }
  577.                 else
  578.                 {
  579.                     boolChangeImage = TRUE;
  580.                 }
  581.  
  582.                 //change selected image type
  583.                 if (boolChangeImage)
  584.                 {
  585.                     tvi.mask = TVIF_SELECTEDIMAGE;
  586.                     switch (pTvnm->action)
  587.                     {
  588.                     case TVE_EXPAND:
  589.                         tvi.iSelectedImage = 1;
  590.                         break;
  591.                     case TVE_COLLAPSE:
  592.                         tvi.iSelectedImage = 2;
  593.                         break;
  594.                     }
  595.                     ret = TreeView_SetItem(hWndTV, &tvi);
  596.  
  597.                 }
  598.                 break;
  599.  
  600.             //process delete key
  601.             case TVN_KEYDOWN:
  602.                 ptvkd = (TV_KEYDOWN *)lParam;
  603.                 switch (ptvkd->wVKey)
  604.                 {
  605.                 case VK_DELETE:
  606.                 htvitem = TreeView_GetSelection(GetDlgItem(hWnd,TREEVIEW_CONTROL_ID));
  607.                 if (!htvitem)
  608.                     return FALSE;
  609.                 ret = lpCDlg->m_pcctrl->TreeViewItem(htvitem, &tvi, TVIF_TEXT | TVIF_PARAM | TVIF_HANDLE, buf);
  610.  
  611.                     return lpCDlg->InetDelete(&tvi);
  612.  
  613.                     break;
  614.  
  615.                 default:
  616.                     return FALSE;
  617.                 }
  618.                 break;
  619.  
  620.             //selection changed triggers the call to enumerate a directory
  621.             //if it has not yet been enumerated
  622.             case TVN_SELCHANGED:
  623.  
  624.                 ret = lpCDlg->m_pcctrl->TreeViewItem(pTvnm->itemNew.hItem, &tvi, 
  625.                       TVIF_TEXT | TVIF_CHILDREN | TVIF_PARAM | TVIF_HANDLE, buf);
  626.  
  627.                 lptvnodei = (LPTVNODEINFO)(tvi.lParam);
  628.                 if (FILE_ATTRIBUTE_DIRECTORY == lptvnodei->dwAttributes)
  629.                 {
  630.                     
  631.  
  632.                     lptvnodei->requestType = REQUEST_INTERNET_ENUM_CONNECT;
  633.                     lptvnodei->hTreeItem = tvi.hItem;
  634.  
  635.                     //if the node represents a directory, it has no
  636.                     //child items, and it has not been enumerate,
  637.                     //enumerate the directory now
  638.                     if (FILE_ATTRIBUTE_DIRECTORY == lptvnodei->dwAttributes &&
  639.                         !tvi.cChildren)
  640.                     {
  641.                         lpCDlg->OnGoto((DWORD)lptvnodei);
  642.  
  643.                     }
  644.  
  645.                 }
  646.  
  647.                 break;
  648.             case NM_DBLCLK:
  649.                 //open a file
  650.                 lpCDlg->InetOpen();
  651.                 break;
  652.  
  653.             case NM_RCLICK:
  654.                     //screen coordinates
  655.                     GetCursorPos(&pt);
  656.                     //relative coordinates
  657.                     GetClientRect(hWndTV, &rect);
  658.                     pt1 = pt;
  659.                     ScreenToClient(hWndTV, &pt1);
  660.  
  661.                     if (!PtInRect(&rect, pt1))
  662.                         return FALSE;
  663.  
  664.                     htvitem = TreeView_GetSelection(hWndTV);
  665.                     if (!htvitem)
  666.                         return FALSE;
  667.                     ret = lpCDlg->m_pcctrl->TreeViewItem(htvitem, &tvi, TVIF_PARAM, buf);
  668.                     lptvnodei = (LPTVNODEINFO)(tvi.lParam);
  669.  
  670.                     //is this a directory or a FTP site node
  671.                     if (FILE_ATTRIBUTE_DIRECTORY == lptvnodei->dwAttributes || 
  672.                         0 == lptvnodei->dwAttributes)
  673.                     {
  674.                         wMenu = IDM_DIR;
  675.                     }
  676.                     else
  677.                     //this is a file node
  678.                     {
  679.                         wMenu = IDM_FILE;
  680.                     }
  681.     
  682.                     if (NULL != lpCDlg->m_hmnu)
  683.                     {
  684.                         DestroyMenu(lpCDlg->m_hmnu);
  685.                         lpCDlg->m_hmnu = NULL;
  686.                     }
  687.  
  688.  
  689.                     lpCDlg->m_hmnu = LoadMenu(lpCDlg->m_hInst,MAKEINTRESOURCE(wMenu));
  690.                     hmenu = GetSubMenu( lpCDlg->m_hmnu, 0 );
  691.  
  692.                     pt1.x = rect.right;
  693.                     pt1.y = rect.bottom;
  694.                     ClientToScreen(hWndTV, &pt1);
  695.                     ret = TrackPopupMenu(hmenu, TPM_LEFTBUTTON | TPM_LEFTALIGN ,
  696.                     pt.x + 15, pt.y , 0, hWnd, NULL);
  697.  
  698.                     break;
  699.  
  700.             default:
  701.                 return FALSE;
  702.         }
  703.  
  704.         break;
  705.  
  706.     case WM_NCLBUTTONDOWN:
  707.         switch (wParam)
  708.         {
  709.         case HTCLOSE:
  710.             DestroyWindow(hWnd);
  711.             break;
  712.         default:
  713.             return FALSE;
  714.         }
  715.         break;
  716.       
  717.     case WM_COMMAND:  // message: command from application menu
  718.         return lpCDlg->OnCommand(hWnd, wParam, lParam);
  719.  
  720.         break;
  721.  
  722.         case WM_DESTROY:  // message: window being destroyed
  723.             if (NULL != lpCDlg->m_hmnu)
  724.                 DestroyMenu(lpCDlg->m_hmnu);
  725.  
  726.             //close InternetSession handle
  727.             if (NULL != lpCDlg->m_hSession)
  728.                 InternetCloseHandle(lpCDlg->m_hSession);
  729.             PostQuitMessage(0);
  730.             return 0;
  731.  
  732.         default:
  733.             return FALSE;
  734.     }
  735.     return TRUE;
  736. }
  737.  
  738.  
  739. //**********************************************************************
  740. // CDlg::InternetCallback
  741. //
  742. // Purpose: Internet callback function used during asynchronous calls
  743. //          to Wininet
  744. // Parameters:
  745. //    HINTERNET hInternet - Upon first entry into the callback (during
  746. //    the INTERNET_STATUS_HANDLE_CREATED status this value contains the
  747. //    handle passed in on the original call to the asynchronous Wininet
  748. //    API.  Upon INTERNET_STATUS_HANDLE_CREATED this value contains 
  749. //    the return value of the asynchronous Wininet API
  750. //
  751. //    DWORD dwContext - an application defined value to associated with
  752. //    the callback.  For this application this is a pointer to a 
  753. //    TVNODEINFO structure
  754. //
  755. //    DWORD dwInternetStatus - status value (INTERNET_STATUS_*)
  756. //
  757. //    LPVOID lpvStatusInformation - value returned by callback function
  758. //    specific to the STATUS type
  759. //
  760. //    DWORD dwStatusInformationLength
  761. //********************************************************************
  762. void CALLBACK CDlg::InternetCallback (HINTERNET hInternet, DWORD dwContext, DWORD dwInternetStatus, LPVOID lpvStatusInformation, DWORD dwStatusInformationLength)
  763. {
  764.     TCHAR strError[80], NewTitle[80], buf[80], szDisplay[STRRDMAX + 1];
  765.     BOOL ret;
  766.     DWORD dwExtErrorLen, dwExtError;
  767.     LONG dwPreviousCount;
  768.     LPTVNODEINFO ptvnodei;
  769.     LPWIN32_FIND_DATA lpw32;
  770.     CDlg *lpCDlg = lpCApp->m_pCDlg;
  771.     HWND hWnd = lpCApp->m_pCDlg->m_hWnd;
  772.     TCHAR szEditText[STRMAX];
  773.     LPINTERNET_ASYNC_RESULT piar;
  774.  
  775.     switch(dwInternetStatus)
  776.     {
  777.     case INTERNET_STATUS_RESOLVING_NAME:
  778.         lstrcpy(NewTitle, TEXT("Resolving "));
  779.         wsprintf(buf, TEXT("Resolving %s ..."), (LPTSTR)lpvStatusInformation);
  780.         SendMessage(GetDlgItem(hWnd,STATUSBAR_CONTROL_ID), SB_SETTEXT, 0, (LPARAM)buf);
  781.  
  782.         break;
  783.  
  784.     case INTERNET_STATUS_NAME_RESOLVED:
  785.         lstrcpy(NewTitle, TEXT("Resolved "));
  786.         wsprintf(buf, TEXT("Resolved %s ..."), (LPTSTR)lpvStatusInformation);
  787.         SendMessage(GetDlgItem(hWnd,STATUSBAR_CONTROL_ID), SB_SETTEXT, 0, (LPARAM)buf);
  788.  
  789.         break;
  790.  
  791.     case INTERNET_STATUS_CONNECTING_TO_SERVER:
  792.         lstrcpy(NewTitle, TEXT("Connecting to "));
  793.         break;
  794.  
  795.     case INTERNET_STATUS_CONNECTED_TO_SERVER:
  796.         wsprintf(buf, TEXT("Connected to %s ..."), (LPTSTR)lpvStatusInformation);
  797.         SendMessage(GetDlgItem(hWnd,STATUSBAR_CONTROL_ID), SB_SETTEXT, 0, (LPARAM)buf);
  798.  
  799.         lstrcpy(NewTitle, TEXT("Connected to "));
  800.         break;
  801.  
  802.     case INTERNET_STATUS_SENDING_REQUEST:
  803.         lstrcpy(NewTitle, TEXT("Sending request "));
  804.         break;
  805.  
  806.     case INTERNET_STATUS_REQUEST_SENT:
  807.         lstrcpy(NewTitle, TEXT("Sent Request "));
  808.         break;
  809.  
  810.     case INTERNET_STATUS_RECEIVING_RESPONSE:
  811.         lstrcpy(NewTitle, TEXT("Receiving response "));
  812.         break;
  813.  
  814.     case INTERNET_STATUS_RESPONSE_RECEIVED:
  815.         lstrcpy(NewTitle, TEXT("Received response "));
  816.         break;
  817.  
  818.     case INTERNET_STATUS_CLOSING_CONNECTION:
  819.         lstrcpy(NewTitle, TEXT("Closing connection "));
  820.         break;
  821.  
  822.     case INTERNET_STATUS_CONNECTION_CLOSED:
  823.         lstrcpy(NewTitle, TEXT("Closed connection "));
  824.  
  825.         break;
  826.  
  827.     case INTERNET_STATUS_HANDLE_CREATED:
  828.         lstrcpy(NewTitle, TEXT("Handle created "));
  829.         ret = Animate_Stop(GetDlgItem(hWnd, IDC_ANIMATE1));
  830.  
  831.         //set global flags used for cancelling intermediate requests
  832.         lpCDlg->m_hLastHandleCreated = (HINTERNET)lpvStatusInformation;
  833.  
  834.         
  835.         ptvnodei = (LPTVNODEINFO)dwContext;
  836.         wsprintf(buf, TEXT("Handle Created %d, %d"), (long)hInternet, (long)lpvStatusInformation);
  837. #ifdef _DEBUG
  838.         ::OutputDebugString(buf);
  839.         ::OutputDebugString(TEXT("\n"));
  840. #endif 
  841.         lstrcat(buf, TEXT("\r\n"));
  842.         GetWindowText(GetDlgItem(hWnd, IDC_STATUS), szEditText, STRMAX );
  843.         lstrcat(szEditText, buf);
  844.         SetWindowText(GetDlgItem(hWnd, IDC_STATUS), szEditText);
  845.  
  846.         break;
  847.  
  848.     case INTERNET_STATUS_HANDLE_CLOSING:
  849.         lstrcpy(NewTitle, TEXT("Handle Closing "));
  850.         lpCDlg->m_hLastHandleCreated  = NULL; 
  851.             break;
  852.  
  853.     case INTERNET_STATUS_REQUEST_COMPLETE:
  854.         //stop the animation
  855.         ret = Animate_Stop(GetDlgItem(hWnd, IDC_ANIMATE1));
  856.  
  857.         //get the TVNODEINFO structure originally passed in from
  858.         //an API call
  859.         ptvnodei = (LPTVNODEINFO)dwContext;
  860.  
  861.         //check the INTERNET_ASYNC_RESULT structure for error information
  862.         piar = (LPINTERNET_ASYNC_RESULT)(lpvStatusInformation);
  863.  
  864.         //set global flag used for cancelling intermediate requests
  865.         //back to NULL since the request is finished anyway
  866.         lpCDlg->m_hLastHandleCreated = NULL;
  867.         if (!(piar->dwResult))
  868.         {
  869.             wsprintf(NewTitle, TEXT("Internet Request Completed - Status Code: %d"), piar->dwError);
  870.             //SendMessage(GetDlgItem(hWnd,STATUSBAR_CONTROL_ID), SB_SETTEXT, 0, (LPARAM)buf);
  871.  
  872.             lstrcat(NewTitle, TEXT("\r\n"));
  873. #ifdef _DEBUG
  874.             ::OutputDebugString(NewTitle);
  875. #endif
  876.             GetWindowText(GetDlgItem(hWnd, IDC_STATUS), szEditText, STRMAX );
  877.             lstrcat(szEditText, NewTitle);
  878.             SetWindowText(GetDlgItem(hWnd, IDC_STATUS), szEditText);
  879.  
  880.             switch (piar->dwError)
  881.             {
  882.                 //standard error returned from FtpFindFirstFile 
  883.                 //and InternetFindNextFile
  884.                 case ERROR_NO_MORE_FILES:
  885.                     //set the request value which will be processed
  886.                     //next time in the callback function
  887.                     ptvnodei->requestType = REQUEST_FILENOTFOUND;
  888.  
  889.                     //get handle values we used and close them
  890.                     lpw32 = (LPWIN32_FIND_DATA)(ptvnodei->prequestResult);
  891.  
  892.                     ret = InternetCloseHandle(ptvnodei->hFile);
  893.                     ret = InternetCloseHandle(ptvnodei->hEnum);
  894. #ifdef _DEBUG
  895.                     wsprintf(buf, TEXT("InternetCloseHandle: %d, %d \n"), ptvnodei->hFile,ptvnodei->hEnum);
  896.                     ::OutputDebugString(buf);
  897. #endif
  898.                     //SendMessage(GetDlgItem(hWnd,STATUSBAR_CONTROL_ID), SB_SETTEXT, 0, (LPARAM)"Ready");
  899.  
  900.                     break;
  901.  
  902.                 case ERROR_INTERNET_EXTENDED_ERROR:
  903.                     //error triggered when the server can pass back
  904.                     //more information on what went wrong.
  905.                     dwExtErrorLen = 80;
  906.                     ret = InternetGetLastResponseInfo(&dwExtError, strError, &dwExtErrorLen);
  907.                     lstrcat(strError, TEXT("\r\n"));
  908. #ifdef _DEBUG
  909.                     ::OutputDebugString(strError);
  910. #endif 
  911.                     GetWindowText(GetDlgItem(hWnd, IDC_STATUS), szEditText, STRMAX );
  912.                     lstrcat(szEditText, strError);
  913.  
  914.                     SetWindowText(GetDlgItem(hWnd, IDC_STATUS), szEditText);
  915.  
  916.                     break;
  917.                 case 1:
  918.                     //no problem - this would be a boolean return value
  919.                     //representing success
  920.                     break;
  921.                 default:
  922.                     //this would be a good place to check for all the
  923.                     //INTERNET_ERROR_* messages (for example, 
  924.                     //INTERNET_ERROR_NAME_NOT_RESOLVED) to give more
  925.                     //descriptive output to the user
  926.  
  927.                     return;
  928.             }
  929.         }
  930.         else
  931.         {
  932.             wsprintf(NewTitle, TEXT("Internet Request Completed - Status Code: %d\n"), piar->dwResult);
  933. #ifdef _DEBUG
  934.             ::OutputDebugString(NewTitle);
  935. #endif 
  936.             lstrcat(NewTitle, TEXT("\r\n"));
  937.             GetWindowText(GetDlgItem(hWnd, IDC_STATUS), szEditText, STRMAX );
  938.             lstrcat(szEditText, NewTitle);
  939.             SetWindowText(GetDlgItem(hWnd, IDC_STATUS), szEditText);
  940.         }
  941.             switch (ptvnodei->requestType)
  942.             {
  943.             case REQUEST_NEW_INTERNET_SITE:
  944.                 //we'll use this handle to enumerate directories
  945.                 ptvnodei->hEnum = hInternet;
  946.                 //now make another connection to cache to use for other operations (FtpDeleteFile, etc)
  947.                 //operations which won't require a new handle everytime
  948.                 ::PostMessage(lpCDlg->m_hWnd,WM_INTERNETCONNECT, NULL, (LPARAM)(dwContext)) ;
  949.                 break;
  950.  
  951.             case REQUEST_INTERNET_CONNECT:
  952.                 //cache this handle for general use (FtpOpenFile, InternetReadFile, etc.)
  953.                 ptvnodei->hConnect = hInternet;
  954.                 ::PostMessage(lpCDlg->m_hWnd,WM_INTERNETENUMERATE, NULL, (LPARAM)(dwContext)) ;
  955.                 break;
  956.  
  957.             case REQUEST_INTERNET_ENUM_CONNECT:
  958.                 ptvnodei->hEnum = hInternet;
  959.                 ::PostMessage(lpCDlg->m_hWnd,WM_INTERNETENUMERATE, NULL, (LPARAM)(dwContext)) ;
  960.                 break;
  961.  
  962.             case REQUEST_INTERNET_OPEN_CONNECT:
  963.                 ptvnodei->hConnect = hInternet;
  964.                 ::PostMessage(lpCDlg->m_hWnd,WM_INTERNETOPENFILE, NULL, (LPARAM)(dwContext)) ;
  965.                 break;
  966.  
  967.             case REQUEST_INTERNET_OPENFILE:
  968.                 ptvnodei->hFile = hInternet;
  969.                 dwContext = (DWORD)ptvnodei;
  970.                 ::PostMessage(lpCDlg->m_hWnd,WM_INTERNETFILEOPENED, NULL, (LPARAM)(dwContext)) ;
  971.                 break;
  972.  
  973.             case REQUEST_FIRSTFILEFOUND:
  974.                 ptvnodei->hFile = hInternet;
  975.                 ::PostMessage(lpCDlg->m_hWnd,WM_INTERNETFILEFOUND, NULL, (LPARAM)(dwContext)) ;
  976.                 break;
  977.  
  978.             case REQUEST_FILETRANSFER:
  979.                 SendMessage(GetDlgItem(lpCDlg->m_hWnd,STATUSBAR_CONTROL_ID), SB_SETTEXT, 0, (LPARAM)"File Transfer Completed");
  980.                 //::PostMessage(lpCDlg->m_hWnd,WM_INTERNETFILETRANSFERRED, NULL, (LPARAM)(dwContext)) ;
  981.                 break;
  982.  
  983.             case REQUEST_INTERNETFILEREAD:
  984.                 ret = ReleaseSemaphore(lpCDlg->m_hFileDownload, 1, &dwPreviousCount);
  985.                 InternetCloseHandle(ptvnodei->hFile);
  986.                 ptvnodei->hFile = NULL;
  987.                 lstrcpyn(szDisplay, lpCDlg->m_filebuf, (int)(lpCDlg->m_dwBytesRead + 1));
  988.                 SetWindowText(GetDlgItem(hWnd, IDC_EDIT1), szDisplay);
  989.                 SendMessage(GetDlgItem(hWnd,STATUSBAR_CONTROL_ID), SB_SETTEXT, 0, (LPARAM)"File Transfer Complete");
  990.  
  991.                 break;
  992.             case REQUEST_INTERNETDELETEFILE:
  993.                 SendMessage(GetDlgItem(lpCDlg->m_hWnd,STATUSBAR_CONTROL_ID), SB_SETTEXT, 0, (LPARAM)"File Deleted");
  994.                 break;
  995.  
  996.             }
  997.         break;
  998.     }
  999.     if (INTERNET_STATUS_REQUEST_COMPLETE != dwInternetStatus)
  1000.     {
  1001.         if (dwStatusInformationLength && lpvStatusInformation && 
  1002.         1 != lstrlen((LPTSTR)lpvStatusInformation)) {
  1003.         if (INTERNET_STATUS_HANDLE_CREATED == dwInternetStatus)
  1004.         {
  1005.         wsprintf(buf, TEXT(" %d, %d"), (long)hInternet, (long)lpvStatusInformation);
  1006.         lstrcat(NewTitle, buf);
  1007.         }
  1008.         else {
  1009.         lstrcat(NewTitle, (LPTSTR) lpvStatusInformation); }
  1010.         //SendMessage(GetDlgItem(hWnd,STATUSBAR_CONTROL_ID), SB_SETTEXT, 0, (LPARAM)NewTitle);
  1011.  
  1012.         }
  1013.  
  1014.     lstrcat(NewTitle, TEXT("\r\n"));
  1015. #ifdef _DEBUG
  1016.     ::OutputDebugString(NewTitle);
  1017. #endif 
  1018.     GetWindowText(GetDlgItem(hWnd, IDC_STATUS), szEditText, STRMAX);
  1019.     lstrcat(szEditText, NewTitle);
  1020.  
  1021.     SetWindowText(GetDlgItem(hWnd, IDC_STATUS), szEditText);
  1022.  
  1023.     }
  1024. return;
  1025. }
  1026.  
  1027.  
  1028. //**********************************************************************
  1029. // CDlg::AddItem
  1030. //
  1031. // Purpose: Add new TreeView item
  1032. // Parameters: 
  1033. //    LPARAM lParam - context value representing a TVNODEINFO structure
  1034. // Return Value:  
  1035. //    BOOL - TRUE if initialization succeeded, FALSE otherwise.
  1036. //
  1037. //********************************************************************
  1038.  
  1039. BOOL CDlg::AddItem(LPARAM lParam)
  1040. {
  1041.     LPTVNODEINFO lptvnodei;
  1042.     LPWIN32_FIND_DATA lptvFindData;
  1043.     HTREEITEM htvi, hItem;
  1044.     TVDATA tvdta;
  1045.     TVNODEINFO tvnodei;
  1046.     TV_ITEM tvi;
  1047.     DWORD dwContext;
  1048.     TCHAR buf[80], dir[80];
  1049.     LPTSTR pdir = dir;
  1050.     BOOL ret;
  1051.  
  1052.     lptvnodei = (LPTVNODEINFO)lParam;
  1053.     htvi = lptvnodei->hTreeItem;
  1054.  
  1055.     //set pointer to WIN32_FIND_DATA structure - this will be 
  1056.     //passed (and returned) via dwContext parameter of FtpFindFirstFile
  1057.     //and InternetFindNextFile functions
  1058.     lptvFindData = (LPWIN32_FIND_DATA)(lptvnodei->prequestResult);
  1059.  
  1060.     //for directories image selected and nonselected will initially
  1061.     //be a folder
  1062.     if (FILE_ATTRIBUTE_DIRECTORY == lptvFindData->dwFileAttributes) {
  1063.         SETTVDATA(tvdta, 2, 2, htvi); }
  1064.     else {
  1065.         //file image 
  1066.         SETTVDATA(tvdta, 0, 0,  htvi);  }
  1067.  
  1068.     lstrcpy(dir, lptvnodei->pszDir);
  1069.     //parent directory
  1070.     if (lstrcmp(pdir,TEXT("")))
  1071.     {
  1072.     //parent text
  1073.     ret = m_pcctrl->TreeViewItem(htvi, &tvi, 
  1074.                TVIF_TEXT , buf);
  1075.     lstrcat(dir, buf);
  1076.     lstrcat(dir, TEXT("/"));
  1077.     }
  1078.     else
  1079.         lstrcat(dir, TEXT("/"));
  1080.  
  1081.     //initialize TVNODEINFO structure and add a treeview item where
  1082.     //the structure will be stored in the TV_ITEM.lParam
  1083.     SETTVNODEINFO(tvnodei, lptvFindData->dwFileAttributes, FALSE, lptvnodei->hConnect, 
  1084.     lptvnodei->pszSite, 0,0, NULL, dir);
  1085.     hItem = m_pcctrl->TreeViewAdd(lptvFindData->cFileName, &tvdta, &tvnodei, &dwContext);//tvnodei);
  1086.  
  1087.     return TRUE;
  1088. }
  1089.  
  1090. //**********************************************************************
  1091. // CDlg::ParseServer
  1092. //
  1093. // Purpose: Parse user input into server name and protocol (like ftp://)
  1094. // Parameters: 
  1095. //    LPTSTR pszInput - IN value, user defined URL 
  1096. //    LPTSTR pszURL - OUT value, full URL
  1097. //    LPTSTR pszServer - OUT value, server name
  1098. // Return Value: None 
  1099. //
  1100. //********************************************************************
  1101. void CDlg::ParseServer(LPTSTR pszInput, LPTSTR pszURL, LPTSTR pszServer)
  1102. {
  1103.     LPTSTR pstr;
  1104.     pstr = NULL;
  1105.     pstr = _tcsstr(pszInput, TEXT("ftp://"));
  1106.     if (NULL == pstr)
  1107.     {
  1108.         lstrcpy(pszURL, TEXT("ftp://"));
  1109.         lstrcat(pszURL, pszInput);
  1110.         lstrcpy(pszServer, pszInput);
  1111.     }
  1112.     else
  1113.     {
  1114.         lstrcpy(pszURL, pszInput);
  1115.         lstrcpy(pszServer, pstr + 6);
  1116.     }
  1117.     return;
  1118.  
  1119. }
  1120.  
  1121. //**********************************************************************
  1122. // CDlg::InetEnumerate
  1123. //
  1124. // Purpose: Wrapper function for the FtpFindFirstFile API
  1125. // Parameters: 
  1126. //    LPARAM lParam - context value representing a TVNODEINFO structure
  1127. //    HTREEITEM htitem - handle of TreeView item representing the 
  1128. //                       directory to enumerate
  1129. // Return Value: None 
  1130. //
  1131. //********************************************************************
  1132. void CDlg::InetEnumerate(LPARAM lParam, HTREEITEM htitem)
  1133. {
  1134.     LPTVNODEINFO lptvnodei;
  1135.     TV_ITEM tvi;
  1136.     HINTERNET hFtp;
  1137.     CDlg *lpCDlg = lpCApp->m_pCDlg;
  1138.     CCommonCtrl *lpCmctrl = lpCDlg->m_pcctrl;
  1139.     DWORD dwContext, dwError;
  1140.     TCHAR buf[80], strSearch[80], msgbuf[80];
  1141.     BOOL ret;
  1142.     LPWIN32_FIND_DATA lpwf;
  1143.  
  1144.     //show the user we are busy
  1145.     ret = Animate_Play(GetDlgItem(m_hWnd, IDC_ANIMATE1), 0, -1, -1);
  1146.  
  1147.     //get a pointer to the TVNODEINFO structure which was originally passed
  1148.     //to the Internet callback function via the dwContext parameter and 
  1149.     //which was returned to the dialog procedure via the lParam parameter
  1150.     //of the PostMessage API
  1151.     lptvnodei = (LPTVNODEINFO)lParam;
  1152.  
  1153.     //get text associated with treeview item
  1154.     m_pcctrl->TreeViewItem(htitem, &tvi, TVIF_TEXT, buf );
  1155.     //if this is a root level ftp site node use "/*" as the search criteria
  1156.     if (_tcsstr(tvi.pszText, TEXT("ftp://")))
  1157.         lstrcpy(strSearch , TEXT("/*"));
  1158.     else
  1159.     {
  1160.         //this is a directory node - use a fullpath/* as the search criteria
  1161.         lstrcpy(strSearch, lptvnodei->pszDir);
  1162.         lstrcat(strSearch, tvi.pszText);
  1163.         lstrcat(strSearch, TEXT("/*"));
  1164.     }
  1165.  
  1166.     //application defined REQUEST type to send to Internet callback
  1167.     lptvnodei->requestType = REQUEST_FIRSTFILEFOUND;
  1168.  
  1169.     lpwf = &(lpCDlg->m_pcctrl->m_FindData);
  1170.     lptvnodei->prequestResult = (LPVOID)lpwf;
  1171.     lstrcpy(lptvnodei->pszFile, strSearch);
  1172.  
  1173.     //package up our TVNODEINFO structure into a context value (dwContext) to
  1174.     //pass to the Internet callback function via an asynchronous call.
  1175.     //This packet of data will be our method of passing and receiving 
  1176.     //data with the callback function.
  1177.     dwContext = (DWORD)(lptvnodei);
  1178.  
  1179.     //set a pointer to the WIN32_FIND_DATA structure we want returned
  1180.     LPVOID pvx = ((LPTVNODEINFO)lptvnodei)->prequestResult;
  1181.  
  1182. #ifdef _DEBUG
  1183.     {
  1184.     TCHAR szDebugbuf[80];
  1185.     wsprintf(szDebugbuf, TEXT("Before FtpFindFirst %d\n"), (long)(lptvnodei->hEnum));
  1186.     ::OutputDebugString(szDebugbuf);
  1187.     ::OutputDebugString(strSearch);
  1188.     }
  1189. #endif
  1190.  
  1191.     //set the text in the status bar
  1192.     wsprintf(msgbuf, TEXT("Opening folder ... %s"), tvi.pszText);
  1193.     SendMessage(GetDlgItem(m_hWnd,STATUSBAR_CONTROL_ID), SB_SETTEXT, 0, (LPARAM)msgbuf);
  1194.  
  1195.     //Use the hEnum to enumerate - this value was set when the user
  1196.     //first connected to the site.  Note the lptvnodei->pszFile value passed
  1197.     //into the API.  This parameter will have a lifetime longer than the 
  1198.     //API's execution.  Currently, arguments passed into an asynchronous
  1199.     //call must be managed by the user and ensured to not go out of scope
  1200.     //before the function terminates
  1201.     hFtp = ::FtpFindFirstFile(lptvnodei->hEnum, lptvnodei->pszFile, (LPWIN32_FIND_DATA)pvx, 0, dwContext);
  1202.         
  1203.     dwError = GetLastError();
  1204.     //the handle return value will be set in either the callback function
  1205.     //or here (or both)
  1206.     lptvnodei->hFile = hFtp;
  1207.  
  1208. #ifdef _DEBUG
  1209.     {
  1210.     TCHAR szDebugbuf[80];
  1211.     wsprintf(szDebugbuf, TEXT("After FtpFindFirst %d, %d\n"), (long)hFtp, dwError);
  1212.     ::OutputDebugString(szDebugbuf);
  1213.     }
  1214. #endif 
  1215.  
  1216.  
  1217.     //just in case the function call will not return a
  1218.     //GetLastError() value of ERROR_IO_PENDING and will return the 
  1219.     //function handle immediately continue and explicitly
  1220.     //call the InternetFindNextFile API which is wrapped by
  1221.     //CDlg::InetEnumNext
  1222.     dwContext = (LPARAM)lptvnodei;
  1223.     if (ERROR_IO_PENDING != dwError && NULL != hFtp)
  1224.     {
  1225.         //also to late to cancel an intermediate request - reset
  1226.         m_hLastHandleCreated = NULL;
  1227.         ret = InetEnumNext(dwContext);
  1228.     }
  1229.  
  1230. }
  1231.  
  1232.  
  1233. //**********************************************************************
  1234. // CDlg::InetEnumNext 
  1235. // Purpose: Wrapper function for the InternetFindNextFile API
  1236. // Parameters: 
  1237. //    LPARAM lParam - context value representing a TVNODEINFO structure
  1238. // Return Value: 
  1239. //    BOOL - TRUE if initialization succeeded, FALSE otherwise. 
  1240. //
  1241. //********************************************************************
  1242.  
  1243. BOOL CDlg::InetEnumNext(LPARAM lParam)
  1244. {
  1245.     LPTVNODEINFO lptvnodei;
  1246.     BOOL ret;
  1247.     DWORD dwError;
  1248.  
  1249.     //show the user we are busy
  1250.     ret = Animate_Play(GetDlgItem(m_hWnd, IDC_ANIMATE1), 0, -1, -1);
  1251.  
  1252.     //get a pointer to the TVNODEINFO structure which was originally passed
  1253.     //to the Internet callback function via the dwContext parameter and 
  1254.     //which was returned to the dialog procedure via the lParam parameter
  1255.     //of the PostMessage API
  1256.     lptvnodei = (LPTVNODEINFO)lParam;
  1257.  
  1258.     //if the status has been returned from the callback function
  1259.     //that no more files were found leave the function
  1260.     if (REQUEST_FILENOTFOUND == lptvnodei->requestType)
  1261.         return FALSE;
  1262.  
  1263.     //FtpFindFirstFile/InternetFindNextFile were successful, create a new
  1264.     //treeview node representing the file or directory
  1265.     ret = AddItem(lParam);
  1266.  
  1267.     //set a pointer to a WIN32_FIND_DATA structure which will
  1268.     //be populated by a call to InternetFindNextFile
  1269.     lptvnodei->prequestResult = &(m_pcctrl->m_FindData);
  1270. #ifdef _DEBUG
  1271.     {
  1272.     TCHAR buf[80];
  1273.     wsprintf(buf, TEXT("Before InternetFindNext  %d\n"), (long)(lptvnodei->hFile));
  1274.     ::OutputDebugString(buf);
  1275.     }
  1276. #endif 
  1277.  
  1278.     //find next file - note that the WIN32_FIND_DATA structure will 
  1279.     //not go out of scope even if we leave this function
  1280.     ret = ::InternetFindNextFile(lptvnodei->hFile, lptvnodei->prequestResult);
  1281.  
  1282.     dwError = GetLastError(); //for debug - should return an ERROR_IO_PENDING
  1283.     return TRUE;
  1284. }
  1285.  
  1286.  
  1287. //**********************************************************************
  1288. // CDlg::InetOpen
  1289. // Purpose: Wrapper function for the FtpOpenFile API
  1290. // Parameters: None
  1291. // Return Value: None
  1292. //
  1293. //********************************************************************
  1294.  
  1295. void CDlg::InetOpen()
  1296. {
  1297.     LPTVNODEINFO lptvnodei;
  1298.     DWORD dwContext, dwError, dwWait;
  1299.     TV_ITEM tvi;
  1300.     HINTERNET hFile;
  1301.     TCHAR buf[80], msgbuf[80];
  1302.     BOOL ret;
  1303.     HWND hWndTV = m_pcctrl->m_hWndTV;
  1304.     node *pnode;
  1305.     HTREEITEM hItem;
  1306.     hItem = TreeView_GetSelection(hWndTV);
  1307.     if (NULL == hItem)
  1308.         return;
  1309.  
  1310.     //get lParam from TreeView item structure (TV_ITEM) it holds
  1311.     //a pointer to our TVNODEINFO structure returned from the callback
  1312.     //function
  1313.     ret = m_pcctrl->TreeViewItem(hItem, &tvi, TVIF_TEXT | TVIF_PARAM, buf);
  1314.     lptvnodei = (LPTVNODEINFO)(tvi.lParam);
  1315.  
  1316.     //make sure this is a file not a directory
  1317.     if (FILE_ATTRIBUTE_DIRECTORY == lptvnodei->dwAttributes ||
  1318.         0 == lptvnodei->dwAttributes)
  1319.         return;
  1320.  
  1321.     //show the user we are busy
  1322.     ret = Animate_Play(GetDlgItem(m_hWnd, IDC_ANIMATE1), 0, -1, -1);
  1323.  
  1324.     //build full path names
  1325.     lstrcpy(lptvnodei->pszFile, lptvnodei->pszDir);
  1326.     lstrcat(lptvnodei->pszFile, tvi.pszText);
  1327.  
  1328.     //set REQUEST type to pass to callback function
  1329.     lptvnodei->requestType = REQUEST_INTERNET_OPENFILE;
  1330.     dwContext = (DWORD)lptvnodei;
  1331.  
  1332.     //since we are going to use the cached connection it is held 
  1333.     //in the node representing the root level site.  get the root
  1334.     //level node
  1335.     pnode = ((m_pcctrl->m_prootlvl[lptvnodei->index])->getfirstnode());
  1336.  
  1337. #ifdef _DEBUG
  1338.     wsprintf(msgbuf, TEXT("Before FtpOpenFile %d\n"), pnode->data.hConnect);
  1339.     ::OutputDebugString(msgbuf);
  1340.     wsprintf(msgbuf, TEXT("Full Path: %s\n"), lptvnodei->pszFile);
  1341.     ::OutputDebugString(msgbuf);
  1342. #endif
  1343.     if (!(pnode->data.hConnect))
  1344.         return;
  1345.  
  1346.     //Why use Semaphore and WaitForSingleObject?
  1347.     // 1) we only have one editbox for viewing files so this is a 
  1348.     //    resource limitation
  1349.     // 2) InternetReadFile passes streams back sequentially anyway
  1350.     //    so going asynchronous will not buy us anything
  1351.  
  1352.     //Wait for file handle resource to be available
  1353.     dwWait = WaitForSingleObject(m_hFileDownload, INFINITE);
  1354.  
  1355.     wsprintf(msgbuf, TEXT("Opening file %s ..."), lptvnodei->pszFile);
  1356.  
  1357.     //set status bar text
  1358.     SendMessage(GetDlgItem(m_hWnd,STATUSBAR_CONTROL_ID), SB_SETTEXT, 0, (LPARAM)msgbuf);
  1359.  
  1360.     //open file for read in ascii mode
  1361.     hFile = FtpOpenFile(pnode->data.hConnect, lptvnodei->pszFile, GENERIC_READ,FTP_TRANSFER_TYPE_ASCII,dwContext);
  1362.  
  1363.     dwError = GetLastError();
  1364. #ifdef _DEBUG
  1365.     wsprintf(msgbuf, TEXT("After FtpOpenFile %d, %d\n"), hFile, dwError);
  1366.     ::OutputDebugString(msgbuf);
  1367. #endif
  1368.  
  1369.     //just in case the function call will not return a
  1370.     //GetLastError() value of ERROR_IO_PENDING and will return the 
  1371.     //function handle immediately continue and PostMessage
  1372.     //to explicitly call the InternetReadFile API which is wrapped
  1373.     //by CDlg::InetRead()
  1374.  
  1375.     if (ERROR_IO_PENDING != dwError && NULL != hFile)
  1376.     {
  1377.         //also to late to cancel an intermediate request - reset
  1378.         m_hLastHandleCreated = NULL;
  1379.  
  1380.         lptvnodei->hFile = hFile;
  1381.         InetRead((LPARAM)lptvnodei);
  1382.  
  1383.     }
  1384.  
  1385. }
  1386.  
  1387. //**********************************************************************
  1388. // CDlg::InetRead
  1389. // Purpose: Wrapper function for the InternetReadFile API
  1390. // Parameters: 
  1391. //    LPARAM lParam - context value representing a TVNODEINFO structure
  1392. // Return Value: None
  1393. //
  1394. //********************************************************************
  1395. void CDlg::InetRead(LPARAM lParam)
  1396. {
  1397.     DWORD dwError, dwBytesToRead;
  1398.     LPTVNODEINFO lptvnodei;
  1399.     BOOL ret;
  1400.     TCHAR buf[80], szDisplay[STRRDMAX + 1];
  1401.  
  1402.     //show the user we are busy
  1403.     ret = Animate_Play(GetDlgItem(m_hWnd, IDC_ANIMATE1), 0, -1, -1);
  1404.  
  1405.     //get our TVNODEINFO structure returned from the callback function
  1406.     lptvnodei = (LPTVNODEINFO)lParam;
  1407.  
  1408.     //set the request type to pass to the callback function
  1409.     lptvnodei->requestType = REQUEST_INTERNETFILEREAD;
  1410.  
  1411.  
  1412.     dwBytesToRead = STRRDMAX;
  1413.     wsprintf(buf, TEXT("Before InternetReadFile %d\n"), lptvnodei->hFile);
  1414.     wsprintf(buf, TEXT("Reading file %s ..."), lptvnodei->pszFile);
  1415.     SendMessage(GetDlgItem(m_hWnd,STATUSBAR_CONTROL_ID), SB_SETTEXT, 0, (LPARAM)buf);
  1416.  
  1417.     //Readfile - use global variables to return buffer and number of 
  1418.     //bytes read.  Since we are not allowing asynchronous reads using
  1419.     //a semaphore there is no danger of overwriting 
  1420.     ret = InternetReadFile(lptvnodei->hFile, m_filebuf,dwBytesToRead, &m_dwBytesRead );
  1421.     dwError = GetLastError();
  1422.  
  1423. #ifdef _DEBUG
  1424.     wsprintf(buf, TEXT("After InternetRead %d, %d, %d\n"), dwError, ret, m_dwBytesRead);
  1425.     ::OutputDebugString(buf);
  1426. #endif
  1427.  
  1428.     if (ERROR_IO_PENDING != dwError)
  1429.     {
  1430.     //update the user interface
  1431.     lstrcpyn(szDisplay, m_filebuf, (int)(m_dwBytesRead + 1));
  1432.  
  1433.     SetWindowText(GetDlgItem(m_hWnd, IDC_EDIT1), m_filebuf);
  1434.     Animate_Stop(GetDlgItem(m_hWnd, IDC_ANIMATE1));
  1435.     SendMessage(GetDlgItem(m_hWnd,STATUSBAR_CONTROL_ID), SB_SETTEXT, 0, (LPARAM)"File Transfer Complete");
  1436.     if (NULL != lptvnodei->hFile)
  1437.         InternetCloseHandle(lptvnodei->hFile);
  1438.  
  1439.     }
  1440.  
  1441. }
  1442.  
  1443. //**********************************************************************
  1444. // CDlg::InetDelete
  1445. // Purpose: Process delete requests
  1446. // Parameters: None
  1447. //    BOOL - TRUE if initialization succeeded, FALSE otherwise. 
  1448. //
  1449. //********************************************************************
  1450. BOOL CDlg::InetDelete(TV_ITEM *ptvi)
  1451. {
  1452.     HWND hWndTV = m_pcctrl->m_hWndTV;
  1453.     node *pnode;
  1454.     HTREEITEM htvitem, hParent;
  1455.     TCHAR buf[80], msgbuf[80];
  1456.     BOOL ret;
  1457.     LPTVNODEINFO lptvnodei;
  1458.     int i;
  1459.     Clist *pClist;
  1460.     DWORD dwError;
  1461.     lptvnodei = (LPTVNODEINFO)(ptvi->lParam);
  1462.  
  1463.     htvitem = TreeView_GetSelection(hWndTV);
  1464.     if (NULL == htvitem)
  1465.         return FALSE;
  1466.     hParent = TreeView_GetParent(hWndTV, htvitem);
  1467.  
  1468.     //if the node has a parent use FtpDeleteFile or 
  1469.     if (hParent)
  1470.     {
  1471.         if (FILE_ATTRIBUTE_DIRECTORY == lptvnodei->dwAttributes) {
  1472.                     
  1473.             //use our cached connection
  1474.             //for our case allow file deletes only
  1475.             lstrcpy(msgbuf, TEXT("Confirm delete for: "));
  1476.             MessageBox(NULL, msgbuf,TEXT("Directory Delete not allowed"), MB_OK | MB_ICONSTOP);
  1477.             return TRUE;
  1478.             //ret = FtpRemoveDirectory(pnode->data.hConnect, lptvnodei->pszFile)
  1479.         }
  1480.         else {
  1481.             //confirm delete before proceeding
  1482.             lstrcpy(msgbuf, TEXT("Confirm delete for: "));
  1483.             lstrcat(msgbuf, ptvi->pszText);
  1484.             if (IDNO == MessageBox(NULL, msgbuf,TEXT("Confirm Delete"), MB_YESNO))
  1485.                 return TRUE;
  1486.             
  1487.             //get the node where our cached connection is stored
  1488.             pnode = ((m_pcctrl->m_prootlvl[lptvnodei->index])->getfirstnode());
  1489.             //generate full path rather than using relative and worry
  1490.             //about changing current directory
  1491.             lstrcpy(lptvnodei->pszFile, lptvnodei->pszDir);
  1492.             lstrcat(lptvnodei->pszFile, ptvi->pszText);
  1493.             //remove data from linked list
  1494.             (m_pcctrl->m_prootlvl[lptvnodei->index])->remove(lptvnodei->key);
  1495.             //remove TreeView node
  1496.             TreeView_DeleteItem(hWndTV, htvitem);
  1497.             //set request type
  1498.             lptvnodei->requestType = REQUEST_INTERNETDELETEFILE;
  1499.             //use our cached connection
  1500.             wsprintf(buf, TEXT("Deleting file %s ..."), lptvnodei->pszFile);
  1501.             SendMessage(GetDlgItem(m_hWnd,STATUSBAR_CONTROL_ID), SB_SETTEXT, 0, (LPARAM)buf);
  1502.  
  1503.             ret = FtpDeleteFile(pnode->data.hConnect, lptvnodei->pszFile);
  1504.             dwError = GetLastError();
  1505.  
  1506.             //the user probably doesn't have access to delete a file
  1507.             //- this will return an error message "access denied"
  1508.             if (ERROR_INTERNET_EXTENDED_ERROR == dwError)
  1509.             {
  1510.                 TCHAR buf[80], szEditText[STRMAX];
  1511.                 DWORD dwbuf = 80;
  1512.                 InternetGetLastResponseInfo(&dwError, buf, &dwbuf);
  1513.                 GetWindowText(GetDlgItem(m_hWnd, IDC_STATUS), szEditText, STRMAX );
  1514.                 lstrcat(szEditText, buf);
  1515.                 SetWindowText(GetDlgItem(m_hWnd, IDC_STATUS), szEditText);
  1516.  
  1517.             }
  1518. #ifdef _DEBUG
  1519.             wsprintf(msgbuf, TEXT("Delete File %s with handle %d - return code: %d\n"), lptvnodei->pszFile, pnode->data.hConnect, dwError);
  1520.             ::OutputDebugString(msgbuf);
  1521. #endif
  1522.             return TRUE;
  1523.         }
  1524.  
  1525.  
  1526.         }
  1527.         else
  1528.         {
  1529.             //root level node 
  1530.             //confirm delete before proceeding
  1531.             lstrcpy(msgbuf, TEXT("Confirm delete for: "));
  1532.             lstrcat(msgbuf, ptvi->pszText);
  1533.             if (IDNO == MessageBox(NULL, msgbuf,TEXT("Confirm Delete"), MB_YESNO))
  1534.                 return FALSE;
  1535.     
  1536.             // delete branch and close connection
  1537.                         pClist = (Clist *)(ptvi->lParam);
  1538.                         i = lptvnodei->index;
  1539.                         //close cached connection
  1540.                         InternetCloseHandle(lptvnodei->hConnect);
  1541.                         m_pcctrl->m_prootlvl[lptvnodei->index]->remove();
  1542.                         ret = TreeView_DeleteItem(hWndTV, ptvi->hItem);
  1543.                         delete m_pcctrl->m_prootlvl[i];
  1544.                         m_pcctrl->m_prootlvl[i] = NULL;
  1545.                         
  1546.  
  1547.         }
  1548.         return TRUE;
  1549. }
  1550.  
  1551.  
  1552. /* AboutDlgProc
  1553.  * ------------
  1554.  *
  1555.  *      Dialog procedure for the About function
  1556.  */
  1557. BOOL CALLBACK AboutDlgProc(HWND hDlg, UINT Message, WPARAM wParam, LPARAM lParam)
  1558. {
  1559.  
  1560.    switch(Message) {
  1561.  
  1562.       case WM_INITDIALOG:
  1563.           return TRUE;
  1564.          break;
  1565.  
  1566.      case WM_NCLBUTTONDOWN:
  1567.         switch (wParam)
  1568.         {
  1569.         case HTCLOSE:
  1570.             EndDialog(hDlg,0);
  1571.         default:
  1572.             return FALSE;
  1573.         }
  1574.         break;
  1575.  
  1576.  
  1577.       case WM_COMMAND :
  1578.          switch(wParam) {
  1579.             case IDOK:
  1580.                EndDialog(hDlg,0);
  1581.                break;
  1582.          }
  1583.          break;
  1584.  
  1585.       default :
  1586.          return FALSE;
  1587.  
  1588.    }
  1589.    return TRUE;
  1590. }
  1591.