Programming Windows程式开发设计指南 第23章 领略Internet

23. 领略Internet

内容来自dedecms

Internet-全世界电脑透过不同协定交换资讯的大型连结体-近几年重新定义了个人计算的几个领域。虽然拨接资讯服务和电子邮件系统在Internet流行开来之前就已经存在,但它们通常局限於文字模式,并且根本没有连结而是各自分隔的。例如,每一种资讯服务都需要拨不同的电话号码,用不同的使用者ID和密码登录。每一种电子邮件系统仅允许在特定系统的缴款使用者之间发送和接收邮件。

织梦内容管理系统

现在,往往只需要拨单一支电话就可以连结整个Internet,而且可以和有电子邮件位址的人进行全球通信。特别是在World Wide Web上,超文字、图形和多媒体(包括声音、音乐和视讯)的使用已经扩展了线上资讯的范围和功能。 本文来自织梦

如果要提供涵盖Windows中所有与Internet相关程式设计问题的彻底介绍,可能还需要再加上几本书才够。所以,本章实际上主要集中在如何让小型的Microsoft Windows应用程式能够有效地从Internet上取得资讯的两个领域。这两个领域分别是Windows Sockets (Winsock) APIWindows InternetWinInetAPI支援的档案传输协定(FTPFile Transfer Protocol)的部分。 dedecms.com

Windows Sockets
 

copyright dedecms

Socket是由University of CaliforniaBerkeley分校开发的概念,用於在UNIX作业系统上添加网路通讯支援。那里开发的API现在称为「Berkeley socket interface」。 copyright dedecms

SocketsTCP/IP
 

织梦内容管理系统

Socket通常(但不专用於)与主宰Internet通信的传输控制项协定/网际网路协定(TCP/IPTransmission Control Protocol/Internet Protocol)牵连在一起。网际网路协定(IPInternet Protocol),作为TCP/IP的组成部分之一,用来将资料打包成「资料封包(datagram)」,该资料封包包含用於标识资料来源和目的地的表头资讯。而传输控制协定(TCPTransmission Control Protocol)则提供了可靠的传输和检查IP资料封包正确性的方法。

内容来自dedecms

TCP/IP下,通讯端点由IP位址和埠号定义。IP位址包括4个位元组,用於确定Internet上的伺服器。IP位址通常按「由点连结的四个小於255的数字」的格式显示,例如「209.86.105.231」。埠号确定了特定的服务或伺服器提供的服务。其中一些埠号已经标准化,以提供众所周知的服务。 dedecms.com

SocketTCP/IP合用时,Socket就是TCP/IP的通讯端点。因此,Socket指定了IP位址和埠号。

本文来自织梦

网路时间服务
 

织梦好,好织梦

下面给出的范例程式与提供时间协定(Time Protocol)的Internet伺服器相连结。此程式将获得目前准确的日期和时间,并用此资讯设定您的PC时钟。 织梦好,好织梦

在美国,国家标准和技术协会(National Institute of Standards and Technology)(以前称为国家标准局(National Bureau of Standards))负责维护准确时间,该时间与世界各地的机构相联系。准确时间可用於无线电广播、电话号码、电脑拨号电话号码以及Internet,关於这些的所有文件都位於网站 http://www.bldrdoc.gov/timefreq (网域名称「bldrdoc」指的是BoulderColoradoNIST Time的位置和Frequency Division)。 织梦好,好织梦

我们只对NIST Network Time Service感兴趣,其详细的文件位於 http://www.bldrdoc.gov/timefreq/service/nts.htm 。此网页列出了十个提供NIST时间服务的伺服器。例如,第一个名称为time-a.timefreq.bldrdoc.gov,其IP位址为132.163.135.130copyright dedecms

(我曾经编写过一个使用非Internet NIST电脑拨接服务的程式,并发表於《PC Magazine》,您也可以在Ziff-Davis的网站 http://www.zdnet.com/pcmag/pctech/content/16/20/ut1620.001.html 中找到。此程式对於想学习如何使用Windows Telephony API的人很有帮助。) 织梦好,好织梦

Internet上有三个不同的时间服务,每一个都由Request for CommentRFC)描述为Internet标准。日期协定(Daytime Protocol)(RFC-867)提供了一个ASCII字串用於指出准确的日期和时间。该ASCII字串的准确格式并不标准,但人们可以理解其中的含义。时间协定(RFC-868)提供了一个32位元的数字,用来表示从190011日至今的秒数。该时间是UTC(不考虑字母顺序,它表示世界时间座标(Coordinated Universal Time)),它类似於所谓的格林威治标准时间(Greenwich Mean Time)或者GMT-英国格林威治时间。第三个协定称为网路时间协定(Network Time Protocol)(RFC-1305),该协定很复杂。

copyright dedecms

对於我们的目的,即包括分析Socket和不断更新PC时钟,时间协定RFC-868已经够用了。RFC-868只是一个两页的简短文件,主要是说用TCP获得准确时间的程式应该有如下步骤: 织梦好,好织梦

  1. 连结到提供此服务的伺服器埠37
  2. 接收32位元的时间。
  3. 关闭连结。

现在我们已经知道了编写存取时间服务的Socket应用程式的每个细节。

本文来自织梦

NETTIME程式
 

内容来自dedecms

Windows Sockets API,通常也称为WinSock,与Berkeley Sockets API相容,因此,可以想像UNIX Socket程式码可以顺利地拿到Windows上使用。Windows下更进一步的支援由对Berkeley Socket扩充的功能提供,其函式的形式是以WSA(「WinSock API」)为字首。相关的概述和参考位於/Platform SDK/Networking and Distributed Services/Windows Sockets Version 2织梦内容管理系统

NETTIME,如程式23-1所示,展示了使用WinSock API的方法。

本文来自织梦

 程式23-1  NETTIME 

copyright dedecms

NETTIME.C 
copyright dedecms
/*---------------------------------------------------------------------------- 织梦好,好织梦 
        NETTIME.C --   Sets System Clock from Internet Services 织梦内容管理系统 
                                                             (c) Charles Petzold, 1998 dedecms.com 
-----------------------------------------------------------------------------*/ 本文来自织梦 
  织梦好,好织梦 
#include <windows.h> 
本文来自织梦
#include "resource.h" copyright dedecms 
  dedecms.com 
#define        WM_SOCKET_NOTIFY (WM_USER + 1) 本文来自织梦 
#define        ID_TIMER         1 dedecms.com 
  本文来自织梦 
LRESULT        CALLBACK WndProc   (HWND, UINT, WPARAM, LPARAM) ; 

copyright dedecms

BOOL                   CALLBACK MainDlg   (HWND, UINT, WPARAM, LPARAM) ; 内容来自dedecms 
BOOL                   CALLBACK ServerDlg             (HWND, UINT, WPARAM, LPARAM) ; 织梦好,好织梦 
  
本文来自织梦
void    ChangeSystemTime               (HWND hwndEdit, ULONG ulTime) ; 内容来自dedecms 
void    FormatUpdatedTime              (HWND hwndEdit, SYSTEMTIME * pstOld,  织梦内容管理系统 
                                SYSTEMTIME * pstNew) ; dedecms.com 
void EditPrintf (HWND hwndEdit, TCHAR * szFormat, ...) ; 
dedecms.com
HINSTANCE hInst ; 
本文来自织梦
HWND                   hwndModeless ; 
dedecms.com
  

本文来自织梦

int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, 
copyright dedecms
                    PSTR szCmdLine, int iCmdShow) 内容来自dedecms 
{ 织梦好,好织梦 
        static TCHAR   szAppName[] = TEXT ("NetTime") ; 织梦好,好织梦 
        HWND                           hwnd ; dedecms.com 
        MSG                            msg ; copyright dedecms 
        RECT                           rect ; copyright dedecms 
        WNDCLASS                       wndclass ; dedecms.com 
  dedecms.com 
        hInst = hInstance ; 

织梦好,好织梦

        wndclass.style                                = 0 ; 本文来自织梦 
        wndclass.lpfnWndProc                          = WndProc ; 织梦内容管理系统 
        wndclass.cbClsExtra                           = 0 ; 本文来自织梦 
        wndclass.cbWndExtra                           = 0 ; 本文来自织梦 
        wndclass.hInstance                            = hInstance ; 本文来自织梦 
        wndclass.hIcon                                = LoadIcon (NULL, IDI_APPLICATION) ; 
dedecms.com
        wndclass.hCursor                              = NULL ; 

本文来自织梦

        wndclass.hbrBackground                = NULL ; copyright dedecms 
        wndclass.lpszMenuName                 = NULL ; 本文来自织梦 
        wndclass.lpszClassName                = szAppName ; 
copyright dedecms
  织梦好,好织梦 
        if (!RegisterClass (&wndclass)) 本文来自织梦 
        { 本文来自织梦 
         MessageBox (NULL, TEXT ("This program requires Windows NT!"),  copyright dedecms 
                     szAppName, MB_ICONERROR) ; 内容来自dedecms 
                       return 0 ; 

织梦内容管理系统

     } 

织梦内容管理系统

      copyright dedecms 
        hwnd = CreateWindow (szAppName, TEXT ("Set System Clock from Internet"), 内容来自dedecms 
                               WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | 

dedecms.com

                            WS_BORDER | WS_MINIMIZEBOX, 本文来自织梦 
                                              CW_USEDEFAULT, CW_USEDEFAULT, 内容来自dedecms 
                               CW_USEDEFAULT, CW_USEDEFAULT, 本文来自织梦 
                               NULL, NULL, hInstance, NULL) ; copyright dedecms 
  织梦好,好织梦 
               // Create the modeless dialog box to go on top of the window 本文来自织梦 
        hwndModeless = CreateDialog (hInstance, szAppName, hwnd, MainDlg) ; 织梦内容管理系统 
               // Size the main parent window to the size of the dialog box.   

本文来自织梦

               //   Show both windows. 
织梦好,好织梦
  
织梦好,好织梦
        GetWindowRect (hwndModeless, &rect) ; 
织梦好,好织梦
        AdjustWindowRect (&rect, WS_CAPTION | WS_BORDER, FALSE) ; 织梦内容管理系统 
  内容来自dedecms 
        SetWindowPos (hwnd, NULL, 0, 0, rect.right - rect.left, 织梦内容管理系统 
                               rect.bottom - rect.top, SWP_NOMOVE) ; 

dedecms.com

  dedecms.com 
        ShowWindow (hwndModeless, SW_SHOW) ;      copyright dedecms 
        ShowWindow (hwnd, iCmdShow) ; 织梦内容管理系统 
        UpdateWindow (hwnd) ; 

本文来自织梦

  
本文来自织梦
        // Normal message loop when a modeless dialog box is used. 

织梦好,好织梦

        while (GetMessage (&msg, NULL, 0, 0)) 织梦内容管理系统 
        { 本文来自织梦 
                       if (hwndModeless == 0 || !IsDialogMessage (hwndModeless, &msg)) 

织梦好,好织梦

                       { dedecms.com 
                               TranslateMessage (&msg) ; 内容来自dedecms 
                               DispatchMessage (&msg) ; 织梦好,好织梦 
                       } copyright dedecms 
        } 
本文来自织梦
        return msg.wParam ; dedecms.com 
} 

织梦好,好织梦

  

本文来自织梦

LRESULT CALLBACK WndProc (     HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) 本文来自织梦 
{ 

copyright dedecms

        switch (message) 本文来自织梦 
     { 

copyright dedecms

        case    WM_SETFOCUS: dedecms.com 
                               SetFocus (hwndModeless) ; dedecms.com 
                               return 0 ; 
内容来自dedecms
  
copyright dedecms
        case    WM_DESTROY: 

本文来自织梦

                               PostQuitMessage (0) ; 

织梦好,好织梦

                               return 0 ; 

dedecms.com

     } 内容来自dedecms 
        return DefWindowProc (hwnd, message, wParam, lParam) ; 

dedecms.com

} 织梦内容管理系统 
  

本文来自织梦

BOOL CALLBACK MainDlg (        HWND hwnd, UINT message, WPARAM wParam,  dedecms.com 
                                                                     LPARAM lParam) 
织梦内容管理系统
{ 
dedecms.com
        static char            szIPAddr[32] = { "132.163.135.130" } ; 

内容来自dedecms

        static HWND            hwndButton, hwndEdit ; 
织梦好,好织梦
        static SOCKET          sock ; 
织梦好,好织梦
        static struct          sockaddr_in sa ; 

织梦内容管理系统

        static TCHAR           szOKLabel[32] ; 

本文来自织梦

        int                                           iError, iSize ; dedecms.com 
        unsigned long          ulTime ; 
本文来自织梦
        WORD                                          wEvent, wError ; 织梦好,好织梦 
        WSADATA                               WSAData ;      
织梦好,好织梦
  织梦内容管理系统 
        switch (message) 织梦内容管理系统 
        { 织梦好,好织梦 
        case    WM_INITDIALOG: 本文来自织梦 
                               hwndButton = GetDlgItem (hwnd, IDOK) ; 本文来自织梦 
                               hwndEdit = GetDlgItem (hwnd, IDC_TEXTOUT) ; 

内容来自dedecms

                               return TRUE ; 
内容来自dedecms
  
织梦内容管理系统
        case    WM_COMMAND: 织梦好,好织梦 
                               switch (LOWORD (wParam)) 

织梦好,好织梦

                       { dedecms.com 
                               case    IDC_SERVER: 

本文来自织梦

                       DialogBoxParam (hInst, TEXT ("Servers"), hwnd, ServerDlg, (LPARAM) szIPAddr) ; copyright dedecms 
                       return TRUE ; 
copyright dedecms
  
本文来自织梦
                               case    IDOK: 
copyright dedecms
                    // Call "WSAStartup" and display description text 

内容来自dedecms

  织梦好,好织梦 
                       if (iError = WSAStartup (MAKEWORD(2,0), &WSAData)) 

织梦内容管理系统

                       { 内容来自dedecms 
                    EditPrintf (hwndEdit, TEXT ("Startup error #%i.\r\n"), iError) ; dedecms.com 
                    return TRUE ; 本文来自织梦 
                               } 
织梦内容管理系统
                       EditPrintf (hwndEdit, TEXT ("Started up %hs\r\n"),  
dedecms.com
                                WSAData.szDescription); copyright dedecms 
  

copyright dedecms

                    // Call "socket" 

内容来自dedecms

  copyright dedecms 
                                              sock = socket (AF_INET, SOCK_STREAM, IPPROTO_TCP) ; 本文来自织梦 
  

本文来自织梦

                                              if (sock == INVALID_SOCKET) 内容来自dedecms 
                                              { 
copyright dedecms
                    EditPrintf (hwndEdit, TEXT ("Socket creation error #%i.\r\n"), WSAGetLastError ()) ; dedecms.com 
                 WSACleanup () ; 内容来自dedecms 
                 return TRUE ; 内容来自dedecms 
               } 

织梦内容管理系统

               EditPrintf (hwndEdit, TEXT ("Socket %i created.\r\n"), sock) ; 
dedecms.com
  copyright dedecms 
              // Call "WSAAsyncSelect"  
内容来自dedecms
  

内容来自dedecms

              if (SOCKET_ERROR == WSAAsyncSelect (sock, hwnd, WM_SOCKET_NOTIFY, FD_CONNECT | FD_READ)) 内容来自dedecms 
                                              { 
织梦好,好织梦
              EditPrintf (     hwndEdit, TEXT ("WSAAsyncSelect error #%i.\r\n"), WSAGetLastError ()) ; 织梦内容管理系统 
                closesocket (sock) ; copyright dedecms 
                 WSACleanup () ; 内容来自dedecms 
                 return TRUE ; 

织梦好,好织梦

               } 

织梦内容管理系统

  

dedecms.com

                 // Call "connect" with IP address and time-server port 

织梦好,好织梦

  dedecms.com 
               sa.sin_family           = AF_INET ; 内容来自dedecms 
               sa.sin_port             = htons (IPPORT_TIMESERVER) ;  织梦好,好织梦 
               sa.sin_addr.S_un.S_addr = inet_addr (szIPAddr) ; 
内容来自dedecms
  
本文来自织梦
               connect(sock, (SOCKADDR *) &sa, sizeof (sa)) ; 
内容来自dedecms
  内容来自dedecms 
               // "connect" will return SOCKET_ERROR because even if it 
copyright dedecms
               // succeeds, it will require blocking. The following only 织梦好,好织梦 
               // reports unexpected errors. 
dedecms.com
  本文来自织梦 
               if (WSAEWOULDBLOCK != (iError = WSAGetLastError ())) 本文来自织梦 
               { 织梦内容管理系统 
               EditPrintf (hwndEdit, TEXT ("Connect error #%i.\r\n"), iError) ; copyright dedecms 
                               closesocket (sock) ; 
copyright dedecms
                               WSACleanup () ; 
织梦内容管理系统
                               return TRUE ; 织梦内容管理系统 
               } 
织梦好,好织梦
               EditPrintf (hwndEdit, TEXT ("Connecting to %hs..."), szIPAddr) ; 

本文来自织梦

      织梦好,好织梦 
               // The result of the "connect" call will be reported  
内容来自dedecms
               // through the WM_SOCKET_NOTIFY message. 
织梦好,好织梦
               // Set timer and change the button to "Cancel" 内容来自dedecms 
  本文来自织梦 
              SetTimer (hwnd, ID_TIMER, 1000, NULL) ; 
织梦内容管理系统
              GetWindowText (hwndButton, szOKLabel, sizeof (szOKLabel) /sizeof (TCHAR)) ; copyright dedecms 
              SetWindowText (hwndButton, TEXT ("Cancel")) ; 
dedecms.com
              SetWindowLong (hwndButton, GWL_ID, IDCANCEL) ; 本文来自织梦 
             return TRUE ; 

本文来自织梦

  织梦内容管理系统 
                       case    IDCANCEL: 

织梦内容管理系统

                                              closesocket (sock) ; 

内容来自dedecms

                                              sock = 0 ; 
织梦内容管理系统
                                              WSACleanup () ; dedecms.com 
                                              SetWindowText (hwndButton, szOKLabel) ; dedecms.com 
                                              SetWindowLong (hwndButton, GWL_ID, IDOK) ; 

内容来自dedecms

  copyright dedecms 
                                              KillTimer (hwnd, ID_TIMER) ; 
dedecms.com
                                              EditPrintf (hwndEdit, TEXT ("\r\nSocket closed.\r\n")) ; 

本文来自织梦

                                              return TRUE ; 

本文来自织梦

  本文来自织梦 
                               case    IDC_CLOSE: 

copyright dedecms

                                              if (sock) 

本文来自织梦

                               SendMessage (hwnd, WM_COMMAND, IDCANCEL, 0) ; 

本文来自织梦

  
dedecms.com
                                              DestroyWindow (GetParent (hwnd)) ; 
本文来自织梦
                                              return TRUE ; 

内容来自dedecms

                               } 内容来自dedecms 
                               return FALSE ; 

dedecms.com

  dedecms.com 
        case    WM_TIMER: 
本文来自织梦
                               EditPrintf (hwndEdit, TEXT (".")) ; 

内容来自dedecms

                               return TRUE ; 
内容来自dedecms
  
织梦内容管理系统
        case    WM_SOCKET_NOTIFY: 
织梦好,好织梦
                               wEvent = WSAGETSELECTEVENT (lParam) ;   // ie, LOWORD 

内容来自dedecms

                               wError = WSAGETSELECTERROR (lParam) ;   // ie, HIWORD 织梦内容管理系统 
  
本文来自织梦
                                      // Process two events specified in WSAAsyncSelect 内容来自dedecms 
  
织梦好,好织梦
                               switch (wEvent) dedecms.com 
                               { 织梦内容管理系统 
        // This event occurs as a result of the "connect" call 织梦内容管理系统 
  
内容来自dedecms
                               case    FD_CONNECT: 

本文来自织梦

                                              EditPrintf (hwndEdit, TEXT ("\r\n")) ; 本文来自织梦 
  本文来自织梦 
                                              if (wError) 
本文来自织梦
                                              { 本文来自织梦 
       EditPrintf (    hwndEdit, TEXT ("Connect error #%i."), wError) ; 
织梦好,好织梦
       SendMessage (hwnd, WM_COMMAND, IDCANCEL, 0) ; 织梦好,好织梦 
      return TRUE ; 
内容来自dedecms
           } copyright dedecms 
        EditPrintf (hwndEdit, TEXT ("Connected to %hs.\r\n"), szIPAddr) ; 内容来自dedecms 
  本文来自织梦 
         // Try to receive data. The call will generate an error 本文来自织梦 
         // of WSAEWOULDBLOCK and an event of FD_READ 

织梦内容管理系统

  dedecms.com 
         recv (sock, (char *) &ulTime, 4, MSG_PEEK) ; 

dedecms.com

         EditPrintf (hwndEdit, TEXT ("Waiting to receive...")) ; 织梦好,好织梦 
         return TRUE ; 

copyright dedecms

  

织梦内容管理系统

         // This even occurs when the "recv" call can be made 

copyright dedecms

                
copyright dedecms
                       case    FD_READ: 

织梦好,好织梦

                                              KillTimer (hwnd, ID_TIMER) ; 织梦内容管理系统 
                                              EditPrintf (hwndEdit, TEXT ("\r\n")) ; 织梦好,好织梦 
  
织梦好,好织梦
                                              if (wError) 织梦内容管理系统 
                                              { dedecms.com 
        EditPrintf (hwndEdit, TEXT ("FD_READ error #%i."), wError) ; 
copyright dedecms
        SendMessage (hwnd, WM_COMMAND, IDCANCEL, 0) ; copyright dedecms 
        return TRUE ; 织梦好,好织梦 
        } 
织梦内容管理系统
                                                     // Get the time and swap the bytes 
内容来自dedecms
  

织梦好,好织梦

          iSize = recv (sock, (char *) &ulTime, 4, 0) ; 
copyright dedecms
          ulTime = ntohl (ulTime) ; 

dedecms.com

          EditPrintf (hwndEdit,  
织梦好,好织梦
          TEXT ("Received current time of %u seconds ") 

内容来自dedecms

          TEXT ("since Jan. 1 1900.\r\n"), ulTime) ; 
内容来自dedecms
  

织梦好,好织梦

          // Change the system time 

本文来自织梦

      dedecms.com 
                                              ChangeSystemTime (hwndEdit, ulTime) ; copyright dedecms 
                                              SendMessage (hwnd, WM_COMMAND, IDCANCEL, 0) ; 
本文来自织梦
                                              return TRUE ; 

copyright dedecms

                               } 
织梦内容管理系统
                               return FALSE ; 本文来自织梦 
        } copyright dedecms 
        return FALSE ; 
copyright dedecms
} 
织梦好,好织梦
  内容来自dedecms 
BOOL CALLBACK ServerDlg (      HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) 

织梦好,好织梦

{ 织梦好,好织梦 
        static char * szServer ; 

copyright dedecms

        static WORD            wServer = IDC_SERVER1 ; 本文来自织梦 
        char                                          szLabel [64] ; copyright dedecms 
  织梦好,好织梦 
        switch (message) 

dedecms.com

        { 

织梦内容管理系统

        case    WM_INITDIALOG: 织梦好,好织梦 
                               szServer = (char *) lParam ; 织梦好,好织梦 
                               CheckRadioButton (hwnd, IDC_SERVER1, IDC_SERVER10, wServer) ; 内容来自dedecms 
                               return TRUE ; 织梦内容管理系统 
  织梦好,好织梦 
        case    WM_COMMAND: 本文来自织梦 
                               switch (LOWORD (wParam)) 

本文来自织梦

                               { 

dedecms.com

                               case    IDC_SERVER1: dedecms.com 
                               case    IDC_SERVER2: 
内容来自dedecms
                               case    IDC_SERVER3: 
织梦内容管理系统
                               case    IDC_SERVER4: 本文来自织梦 
                               case    IDC_SERVER5: 内容来自dedecms 
                               case    IDC_SERVER6: 

dedecms.com

                               case    IDC_SERVER7: 

织梦内容管理系统

                               case    IDC_SERVER8: dedecms.com 
                               case    IDC_SERVER9: 本文来自织梦 
                               case    IDC_SERVER10: 本文来自织梦 
                                              wServer = LOWORD (wParam) ; 织梦内容管理系统 
                                              return TRUE ; 
copyright dedecms
  copyright dedecms 
                               case    IDOK: 
本文来自织梦
                                              GetDlgItemTextA (hwnd, wServer, szLabel, sizeof (szLabel)) ; 

织梦内容管理系统

                                              strtok (szLabel, "(") ; 织梦好,好织梦 
                                              strcpy (szServer, strtok (NULL, ")")) ; copyright dedecms 
                                              EndDialog (hwnd, TRUE) ; 织梦好,好织梦 
                                              return TRUE ; copyright dedecms 
  本文来自织梦 
                               case    IDCANCEL: 织梦内容管理系统 
                                              EndDialog (hwnd, FALSE) ; 本文来自织梦 
                                              return TRUE ; 织梦内容管理系统 
                               } 

dedecms.com

                               break ; 

织梦内容管理系统

        } 

本文来自织梦

        return FALSE ; 

织梦好,好织梦

} 

内容来自dedecms

  

内容来自dedecms

void ChangeSystemTime (HWND hwndEdit, ULONG ulTime) 

dedecms.com

{ dedecms.com 
        FILETIME                              ftNew ; 

本文来自织梦

        LARGE_INTEGER          li ; 

dedecms.com

        SYSTEMTIME                     stOld, stNew ; 本文来自织梦 
  
织梦内容管理系统
        GetLocalTime (&stOld) ; 织梦好,好织梦 
        stNew.wYear                                                  = 1900 ; 

copyright dedecms

        stNew.wMonth                                          = 1 ; 

dedecms.com

        stNew.wDay                                            = 1 ; 

dedecms.com

        stNew.wHour                                           = 0 ; dedecms.com 
        stNew.wMinute                                         = 0 ; 

本文来自织梦

        stNew.wSecond                                         = 0 ; 
织梦好,好织梦
        stNew.wMilliseconds                   = 0 ; 

dedecms.com

  copyright dedecms 
        SystemTimeToFileTime (&stNew, &ftNew) ; 

织梦好,好织梦

        li = * (LARGE_INTEGER *) &ftNew ; dedecms.com 
        li.QuadPart += (LONGLONG) 10000000 * ulTime ;  

本文来自织梦

        ftNew = * (FILETIME *) &li ; 
织梦内容管理系统
        FileTimeToSystemTime (&ftNew, &stNew) ; 
copyright dedecms
  

dedecms.com

        if (SetSystemTime (&stNew)) 本文来自织梦 
        { 本文来自织梦 
                      GetLocalTime (&stNew) ; 

织梦内容管理系统

                       FormatUpdatedTime (hwndEdit, &stOld, &stNew) ; 

织梦内容管理系统

       } copyright dedecms 
        else dedecms.com 
                       EditPrintf (hwndEdit, TEXT ("Could NOT set new date and time.")) ; 

织梦内容管理系统

} 内容来自dedecms 
  
copyright dedecms
void FormatUpdatedTime (       HWND hwndEdit, SYSTEMTIME * pstOld, SYSTEMTIME * pstNew) 
copyright dedecms
{ 
织梦内容管理系统
        TCHAR szDateOld [64], szTimeOld [64], szDateNew [64], szTimeNew [64] ; 织梦内容管理系统 
        GetDateFormat (LOCALE_USER_DEFAULT, LOCALE_NOUSEROVERRIDE | DATE_SHORTDATE, 本文来自织梦 
                                                             pstOld, NULL, szDateOld, sizeof (szDateOld)) ; 
织梦好,好织梦
        GetTimeFormat (LOCALE_USER_DEFAULT, LOCALE_NOUSEROVERRIDE |  copyright dedecms 
                        TIME_NOTIMEMARKER | TIME_FORCE24HOURFORMAT, 织梦好,好织梦 
                       pstOld, NULL, szTimeOld, sizeof (szTimeOld)) ; copyright dedecms 
  
dedecms.com
        GetDateFormat (LOCALE_USER_DEFAULT, LOCALE_NOUSEROVERRIDE | DATE_SHORTDATE, 
本文来自织梦
                       pstNew, NULL, szDateNew, sizeof (szDateNew)) ; copyright dedecms 
        GetTimeFormat (LOCALE_USER_DEFAULT, LOCALE_NOUSEROVERRIDE |  织梦好,好织梦 
                        TIME_NOTIMEMARKER | TIME_FORCE24HOURFORMAT, copyright dedecms 
                       pstNew, NULL, szTimeNew, sizeof (szTimeNew)) ; 内容来自dedecms 
  
织梦好,好织梦
        EditPrintf (hwndEdit, TEXT ("System date and time successfully changed ") 
本文来自织梦
                                       TEXT ("from\r\n\t%s, %s.%03i to\r\n\t%s, %s.%03i."),  

本文来自织梦

                       szDateOld, szTimeOld, pstOld->wMilliseconds, 

copyright dedecms

                       szDateNew, szTimeNew, pstNew->wMilliseconds) ; 
copyright dedecms
} 织梦好,好织梦 
  
copyright dedecms
void EditPrintf (HWND hwndEdit, TCHAR * szFormat, ...) 内容来自dedecms 
{ copyright dedecms 
        TCHAR          szBuffer [1024] ; 

copyright dedecms

        va_listpArgList ; 
内容来自dedecms
  本文来自织梦 
        va_start (pArgList, szFormat) ; 

本文来自织梦

        wvsprintf (szBuffer, szFormat, pArgList) ; 
织梦内容管理系统
        va_end (pArgList) ; 
copyright dedecms
        SendMessage (hwndEdit, EM_SETSEL, (WPARAM) -1, (LPARAM) -1) ; 
本文来自织梦
        SendMessage (hwndEdit, EM_REPLACESEL, FALSE, (LPARAM) szBuffer) ; 
织梦好,好织梦
        SendMessage (hwn dEdit, EM_SCROLLCARET, 0, 0) ; 

dedecms.com

} 织梦内容管理系统 
 NETTIME.RC (摘录) 内容来自dedecms 
//Microsoft Developer Studio generated resource script. 

dedecms.com

#include "resource.h" 
织梦内容管理系统
#include "afxres.h" 

本文来自织梦

  织梦好,好织梦 
///////////////////////////////////////////////////////////////////////////// 
本文来自织梦
// Dialog 

内容来自dedecms

SERVERS DIALOG DISCARDABLE  20, 20, 274, 202 
dedecms.com
STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU 

copyright dedecms

CAPTION "NIST Time Service Servers" 内容来自dedecms 
FONT 8, "MS Sans Serif" 
本文来自织梦
BEGIN dedecms.com 
        DEFPUSHBUTTON                  "OK",IDOK,73,181,50,14 
织梦内容管理系统
        PUSHBUTTON                            "Cancel",IDCANCEL,150,181,50,14 

织梦好,好织梦

        CONTROL          内容来自dedecms 
                       "time-a.timefreq.bldrdoc.gov (132.163.135.130) NIST, Boulder, Colorado", 内容来自dedecms 
                       IDC_SERVER1,"Button",BS_AUTORADIOBUTTON,9,7,256,16 内容来自dedecms 
        CONTROL          织梦好,好织梦 
               "time-b.timefreq.bldrdoc.gov (132.163.135.131) NIST, Boulder, Colorado", 

dedecms.com

                       IDC_SERVER2,"Button",BS_AUTORADIOBUTTON,9,24,256,16 
内容来自dedecms
        CONTROL          本文来自织梦 
                       "time-c.timefreq.bldrdoc.gov (132.163.135.132) Boulder, Colorado", 本文来自织梦 
                               IDC_SERVER3,"Button",BS_AUTORADIOBUTTON,9,41,256,16 

内容来自dedecms

        CONTROL          
织梦好,好织梦
                       "utcnist.colorado.edu (128.138.140.44) University of Colorado, Boulder", copyright dedecms 
                       IDC_SERVER4,"Button",BS_AUTORADIOBUTTON,9,58,256,16 copyright dedecms 
        CONTROL          织梦好,好织梦 
                               "time.nist.gov (192.43.244.18) NCAR, Boulder, Colorado", copyright dedecms 
                       IDC_SERVER5,"Button",BS_AUTORADIOBUTTON,9,75,256,16 本文来自织梦 
        CONTROL          

copyright dedecms

                               "time-a.nist.gov (129.6.16.35) NIST, Gaithersburg, Maryland", 
dedecms.com
                               IDC_SERVER6,"Button",BS_AUTORADIOBUTTON,9,92,256,16 织梦好,好织梦 
        CONTROL          织梦好,好织梦 
                               "time-b.nist.gov (129.6.16.36) NIST, Gaithersburg, Maryland", 织梦好,好织梦 
                               IDC_SERVER7,"Button",BS_AUTORADIOBUTTON,9,109,256,16 
内容来自dedecms
        CONTROL          织梦内容管理系统 
                       "time-nw.nist.gov (131.107.1.10) Microsoft, Redmond, Washington", 

dedecms.com

                               IDC_SERVER8,"Button",BS_AUTORADIOBUTTON,9,126,256,16 copyright dedecms 
        CONTROL          织梦好,好织梦 
                               "utcnist.reston.mci.net (204.70.131.13) MCI, Reston, Virginia", dedecms.com 
                               IDC_SERVER9,"Button",BS_AUTORADIOBUTTON,9,143,256,16 
织梦内容管理系统
  
织梦好,好织梦
        CONTROL          dedecms.com 
                               "nist1.data.com (209.0.72.7) Datum, San Jose, California", 

织梦内容管理系统

                               IDC_SERVER10,"Button",BS_AUTORADIOBUTTON,9,160,256,16 本文来自织梦 
END 
本文来自织梦
NETTIME DIALOG DISCARDABLE  0, 0, 270, 150 STYLE WS_CHILD FONT 8, "MS Sans Serif" 

织梦好,好织梦

BEGIN dedecms.com 
        DEFPUSHBUTTON                  "Set Correct Time",IDOK,95,129,80,14 织梦好,好织梦 
        PUSHBUTTON                            "Close",IDC_CLOSE,183,129,80,14 dedecms.com 
        PUSHBUTTON                            "Select Server...",IDC_SERVER,7,129,80,14 织梦好,好织梦 
        EDITTEXT                                      IDC_TEXTOUT,7,7,253,110,ES_MULTILINE | ES_AUTOVSCROLL |  
dedecms.com
                                                                     ES_READONLY | WS_VSCROLL | NOT WS_TABSTOP 

织梦好,好织梦

END 

织梦内容管理系统

 RESOURCE.H (摘录) 

copyright dedecms

// Microsoft Developer Studio generated include file. 内容来自dedecms 
// Used by NetTime.rc 织梦好,好织梦 
  dedecms.com 
#define                IDC_TEXTOUT                                                          101 内容来自dedecms 
#define                IDC_SERVER1                                                          1001 
dedecms.com
#define                IDC_SERVER2                                                          1002 dedecms.com 
#define                IDC_SERVER3                                                          1003 织梦内容管理系统 
#define                IDC_SERVER4                                                          1004 
内容来自dedecms
#define                IDC_SERVER5                                                          1005 织梦好,好织梦 
#define                IDC_SERVER6                                                          1006 本文来自织梦 
#define                IDC_SERVER7                                                          1007 织梦内容管理系统 
#define                IDC_SERVER8                                                          1008 
本文来自织梦
#define                IDC_SERVER9                                                          1009 织梦好,好织梦 
#define                IDC_SERVER10                                                         1010 本文来自织梦 
#define                IDC_SERVER                                                           1011 
织梦好,好织梦
#define                IDC_CLOSE                                                                  1012 

织梦内容管理系统

在结构上,NETTIME程式建立了一个依据NETTIME.RC中的NETTIME所建立的非系统模态对话方块。程式重新定义了视窗的尺寸,以便非系统模态对话方块可以覆盖程式的整个视窗显示区域。对话方块包括一个唯读编辑区(程式用於写入文字资讯)、一个「Select Server」按钮、一个「Set Correct Time」按钮和一个「Close」按钮。「Close」按钮用於终止程式。 dedecms.com

MainDlg中的szIPAddr变数用於储存伺服器位址,内定是字串「132.163.135.130」。「Select Server」按钮启动依据NETTIME.RC中的SERVERS模板建立的对话方块。szIPAddr变数作为最後一个参数传递给DialogBoxParam。「Server」对话方块列出了10个伺服器(都是从NIST网站上逐字复制来的),这些伺服器提供了我们感兴趣的服务。当使用者单击一个伺服器时,ServerDlg将分析按钮文字,以获得相应的IP位址。新位址储存在szIPAddr变数中。 织梦内容管理系统

当使用者按下「Set Correct Time」按钮时,按钮将产生一个WM_COMMAND讯息,其中wParam的低字组等於IDOKMainDlg中的IDOK处理是大部分Socket初始行为发生的地方。

dedecms.com

使用Windows Sockets API时,任何Windows程式必须呼叫的第一个函式是:

织梦好,好织梦

iError = WSAStartup (wVersion, &WSAData) ; dedecms.com 

NETTIME将第一个参数设定为0x0200(表示2.0版本)。传回时,WSAData结构包含了Windows Sockets实作的相关资讯,而且NETTIME将显示szDescription字串,并简要提供了一些版本资讯。

织梦内容管理系统

然後,NETTIME如下呼叫socket函式: 本文来自织梦

sock = socket (AF_INET, SOCK_STREAM, IPPROTO_TCP) ; dedecms.com 

第一个参数是一个位址种类,表示此处是某种Internet位址。第二个参数表示资料以资料流的形式传回,而不是以资料封包的形式传回(我们需要的资料只有4个位元组长,而资料封包适用於较大的资料块)。最後一个参数是一个协定,我们指定使用的Internet协定是TCP。它是RFC-868所定义的两个协定之一。socket函式的传回值储存在SOCKET型态的变数中,以便後面的Socket函式的呼叫。

内容来自dedecms

NETTIME下面呼叫的WSAAsynchSelect是另一个Windows特有的Socket函式。此函式用於避免因Internet回应过慢而造成应用程式当住。在WinSock文件中,有些函式与「阻碍性(blocking)」有关。也就是说,它们不能保证立即把控制项权传回给程式。WSAAsyncSelect函式强制阻碍性的函式转为非阻碍性的,即在函式执行完之前把控制项传回给程式。函式的结果以讯息的形式报告给应用程式。WSAAsyncSelect函式让应用程式指定讯息和接收讯息的视窗的数值。通常,函式的语法如下: 织梦内容管理系统

WSAAsyncSelect (sock, hwnd, message, iConditions) ; dedecms.com 

为此任务,NETTIME使用程式定义的一个讯息,该讯息称为WM_SOCKET_NOTIFY。它也用WSAAsyncSelect的最後一个参数来指定讯息发送的条件,特别在连结和接收资料时(FD_CONNECT | FD_READ)。 织梦好,好织梦

NETTIME呼叫的下一个WinSock函式是connect。此函式需要一个指向Socket位址结构的指标,对於不同的协定来说,此Socket位址结构是不同的。NETTIME使用为TCP/IP设计的结构版本:

copyright dedecms

struct sockaddr_in  
织梦好,好织梦
{ 内容来自dedecms 
        short                                         sin_family; 

内容来自dedecms

        u_short                               sin_port; 织梦好,好织梦 
        struct in_addr sin_addr; 
copyright dedecms
        char                                          sin_zero[8]; 

dedecms.com

} ; 内容来自dedecms 

其中in_addr是用於指定Internet位址,它可以用4个位元组,或者2个无正负号短整数,或者1个无正负号长整数来表示。 内容来自dedecms

NETTIMEsin_family栏位设定为AF_INET,用於表示位址种类。将sin_port设定为埠号,这里是时间协定的埠号,RFC-868显示为37。但不要像我最初时那样,将此栏位设为37。当大多数数字通过Internet时,结构的这个埠号栏位必须是「big endian」的,即最高的位元组排第一个。Intel微处理器是little endian。幸运的是,htons(「host-to-network short」)函式使位元组翻转,因此NETTIMEsockaddr_in结构的sin_port栏位设定为:

内容来自dedecms

htons (IPPORT_TIMESERVER) 

织梦好,好织梦

WINSOCK2.H中将常数定义为37NETTIMEinet_addr函式将储存在szIPAddr字串中的伺服器位址转化为无正负号长整数,该整数用於设定结构的sin_addr栏位。

织梦好,好织梦

如果应用程式在Windows 98下呼叫connect,而且目前Windows没有连结到Internet,那么将显示「拨号连线」对话方块。这就是所谓的「自动拨号」。在Windows NT 4.0中没有实作「自动拨号」,因此如果在NT环境下执行,那么在执行NETTIME之前,就必须先连结上Internetcopyright dedecms

connect函式通常已经会阻碍著後面程式的执行,这是因为连结成功以前需要花些时间。然而,由於NETTIME呼叫了WSAAsyncSelect,所以connect不会等待连结,事实上,它会立即传回SOCKET_ERROR的值。这并不是出现了错误,这只是表示现在还没有连线成功而已。NETTIME也不会检查这个传回值,只是呼叫WSAGetLastError而已。如果WSAGetLastError传回WSAEWOULDBLOCK(即函式的执行通常要受阻,但这里并没有受阻),那就一切都还很正常。NETTIME将「Set Correct Time」按钮改成「Cancel」,并设定了一个1秒的计时器。WM_TIMER的处理方式只是在程式视窗中显示句点,以告诉使用者程式仍在执行,系统没有当掉。

内容来自dedecms

连结最终完成时,MainDlgWM_SOCKET_NOTIFY讯息-NETTIMEWSAAsyncSelect函式中指定的程式自订讯息所通知。lParam的低字组等於FD_CONNECT,高字组表示错误。这时的错误可能是程式不能连结到指定的伺服器。NETTIME还列出了其他9个伺服器,供您选择,让您可以试试其他的伺服器。

织梦好,好织梦

如果一切顺利,那么NETTIME将呼叫recv(「receive:接收」)函式来读取资料:

织梦好,好织梦

recv (sock, (char *) &ulTime, 4, MSG_PEEK) ; 本文来自织梦 

这意味著,用4个位元组来储存ulTime变数。最後一个参数表示只是读此资料,并不将其从输入伫列中删除。像connect函式一样,recv传回一个错误代码,以表示函式通常受阻,但这时没有受阻。理论上来说(当然这不大可能),函式至少能传回资料的一部分,然後透过再次呼叫以获得其余的32个位元组值。那就是呼叫recv函式时带有MSG_PEEK选项的原因。 织梦好,好织梦

connect函式类似,recv函式也产生WM_SOCKET_NOTIFY讯息,这时带有FD_READ的事件代码。NETTIME通过再次呼叫recv来对此回应,这时最後的参数是0,用於从伫列中删除资料。我将简要讨论一下程式处理接收到的ulTime的方法。注意,NETTIME通过向自己发送WM_COMMAND讯息来结束处理,该讯息中wParam等於IDCANCEL。对话方块程序通过呼叫closesocketWSACleanup来回应。

本文来自织梦

再次呼叫NETTIME接收的32位元的ulTime值是从199011日开始的0:00 UTC秒数。但最高顺序的位元组是第一个位元组,因此该值必须通过ntohl(「network-to-host long」)函式处理来调整位元组顺序,以便Intel微处理器能够处理。然後,NETTIME呼叫ChangeSystemTime函式。

本文来自织梦

ChangeSystemTime首先取得目前的本地时间-即,使用者所在时区和日光节约时间的目前系统时间。将SYSTEMTIME结构设定为190011日午夜(0时)。并将这个SYSTEMTIME结构传递给SystemTimeToFileTime,将此结构转化为FILETIME结构。FILETIME实际上只是由两个32位元的DWORD一起组成64位元的整数,用来表示从160111日至今间隔为100奈秒(nanosecond)的间隔数。 本文来自织梦

ChangeSystemTime函式将FILETIME结构转化为LARGE_INTEGER。它是一个union,允许64位元的值可以被当成两个32位元的值使用,或者当成一个__int64资料型态的64位元整数使用(__int64资料型态是Microsoft编译器对ANSI C标准的扩充)。因此,此值是160111日到190011日之间间隔为100奈秒的间隔数。这里,添加了190011日至今间隔为100奈秒的间隔数-ulTime10,000,000倍。 织梦好,好织梦

然後通过呼叫FileTimeToSystemTime将作为结果的FILETIME值转换回SYSTEMTIME结构。因为时间协定传回目前的UTC时间,所以NETTIME通过呼叫SetSystemTime来设定时间,SetSystemTime也依据UTC。基於显示的目的,程式呼叫GetLocalTime来获得更新时间。最初的本地时间和新的本地时间一起传递给FormatUpdatedTime,这个函式用GetTimeFormat函式和GetDateFormat函式将时间转化为ASCII字串。 内容来自dedecms

如果程式在Windows NT下执行,并且使用者没有取得设定时间的许可权,那么SetSystemTime函式可能失败。如果SetSystemTime失败,则NETTIME将发出一个新时间未设定成功的讯息来指出问题所在。

本文来自织梦

WININETFTP
  织梦好,好织梦

WinInet(「Windows Internet」)API是一个高阶函式集,帮助程式写作者使用三个常见的Internet协定,这三个协定是:用於World Wide Web全球资讯网的超文字传输协定(HTTPHypertext Transfer Protocol)、档案传输协定(FTPFile Transfer Protocol)和另一个称为Gopher的档案传输协定。WinInet函式的语法与常用的Windows档案函式的语法类似,这使得使用这些协定就像使用本地磁碟机上的档案一样容易。WinInet API的文件位於/Platform SDK/Internet, Intranet, Extranet Services/Internet Tools and Technologies/WinInet API

织梦内容管理系统

下面的范例程式将展示如何使用WinInet APIFTP部分。许多有网站的公司也都有「匿名FTP」伺服器,这样使用者可以在不输入使用者名称和密码的情况下下载档案。例如,如果您在Internet Explorer的位址栏输入 ftp://ftp.microsoft.com ,那么您就可以浏览FTP伺服器上的目录并下载档案。如果进入ftp://ftp.cpetzold.com/cpetzold.com/ProgWin/UpdDemo,那么您将在我的匿名FTP伺服器上发现与待会要提到的范例程式一块使用的档案列表。 本文来自织梦

虽然现今FTP服务对大多数的Web使用者来说并不是那么方便使用,但它仍然相当有用。例如,应用程式能利用FTP从匿名FTP伺服器上取得资料,这些取得资料的运作程序几乎完全在台面下处理,而不需要使用者操心。这就是我们将讨论的UPDDEMO(「update demonstration:更新范例」)程式的构想。 dedecms.com

FTP API概况
 

织梦好,好织梦

使用WinInet的程式必须在所有呼叫WinInet函式的原始档案中包括表头档案WININET.H。程式还必须连结WININET.LIB。在Microsoft Visual C++中,您可以在「Project Settings」对话方块的「Link」页面标签中指定。执行时,程式将和WININET.DLL动态连结程式库连结。 织梦内容管理系统

在下面的论述中,我不会详细讨论函式的语法,因为某些函式有很多选项,这让它变得相当复杂。要掌握WinInet,您可以将UPDDEMO原始码当成食谱来看待。这时最重要的是了解有关的各个步骤以及FTP函式的范围。 织梦内容管理系统

要使用Windows Internet API,首先要呼叫InternetOpen。然後,使用WinInet支援的任何一种协定。InternetOpen给您一个Internet作业代号,并储存到HINTERNET型态的变数中。用完WinInet API以後,应该通过呼叫InternetCloseHandle来关闭代号。

dedecms.com

要使用FTP,您接下来就要呼叫InternetConnect。此函式需要使用由InternetOpen建立Internet作业代号,并且传回FTP作业的代号。您可将此代号作为名称开头为Ftp的所有函式的第一个参数。InternetConnect函式的参数指出要使用的FTP,还提供了伺服器名称,例如,ftp.cpetzold.com。此函式还需要使用者名称和密码。如果存取匿名FTP伺服器,这些参数可以设定为NULL。如果应用程式呼叫InternetConnectPC并没有连结到InternetWindows 98将显示「拨号连线」对话方块。当使用FTP的应用程式结束时,呼叫InternetCloseHandle来关闭代号。 织梦内容管理系统

这时可以开始呼叫有Ftp字首的函式。您将发现这些函式与标准的Windows档案I/O函式很相似。为了避免与其他协定重复,一些以Internet为字首的函式也可以处理FTP

copyright dedecms

下面四个函式用於处理目录: 织梦内容管理系统

fSuccess = FtpCreateDirectory         (hFtpSession,  szDirectory) ; dedecms.com 
fSuccess = FtpRemoveDirectory         (hFtpSession,  szDirectory) ; dedecms.com 
fSuccess = FtpSetCurrentDirectory     (hFtpSession,  szDirectory) ; 本文来自织梦 
fSuccess = FtpGetCurrentDirectory     (hFtpSession,  szDirectory, &dwCharacterCount) ; 
内容来自dedecms

注意,这些函式很像我们所熟悉的Windows提供用於处理本地档案系统的CreateDirectoryRemoveDirectorySetCurrentDirectoryGetCurrentDirectory函式。 织梦内容管理系统

当然,存取匿名FTP的应用程式不能建立或删除目录。而且,程式也不能假定FTP目录具有和Windows档案系统相同的目录结构型态。特别是用相对路径名设定目录的程式,不能假定关於新的目录全名的一切。如果程式需要知道最後所在目录的整个名称,那么呼叫了SetCurrentDirectory之後必须再呼叫GetCurrentDirectoryGetCurrentDirectory的字串参数至少包含MAX_PATH字元,并且最後一个参数应指向包含该值的变数。 dedecms.com

下面两个函式让您删除或者重新命名档案(但不是在匿名FTP伺服器上): 内容来自dedecms

fSuccess = FtpDeleteFile (hFtpSession, szFileName) ; copyright dedecms 
fSuccess = FtpRenameFile (hFtpSession, szOldName, szNewName) ; 
织梦好,好织梦

经由先呼叫FtpFindFirstFile,可以查找档案(或与含有万用字元的档名样式相符的多个档案)。此函式很像FindFirstFile函式,甚至都使用了相同的WIN32_FIND_DATA结构。该档案为列举出来的档案传回了一个代号。您可以将此代号传递给InternetFindNextFile函式以获得额外的档案名称资讯。最後通过呼叫InternetCloseHandle来关闭代号。

本文来自织梦

要打开档案,可以呼叫FtpFileOpen。这个函式传回一个档案代号,此代号可以用於InternetReadFileInternetReadFileExInternetWriteInternetSetFilePointer呼叫。最後可以通过呼叫最常用的InternetCloseHandle函式来关闭代号。 织梦内容管理系统

最後,下面两个高级函式特别有用:FtpGetFile呼叫将档案从FTP伺服器复制到本地记忆体,它合并了FtpFileOpenFileCreateInternetReadFileWriteFileInternetCloseHandleCloseHandle呼叫。FtpGetFile的另一个参数是一个旗标,如果本地已经存在同名档案,那么该旗标将导致函式呼叫失败。FtpPutFile与此函式类似,用於将档案从本地记忆体复制到FTP伺服器。 copyright dedecms

更新展示程式
  本文来自织梦

UPDDEMO,如程式23-2所示,展示了用WinInet FTP函式在第二个执行绪执行期间从匿名FTP伺服器上下载档案的方法。

内容来自dedecms

 程式23-2  UPDDEMO dedecms.com 
UPDDEMO.C dedecms.com 
/*--------------------------------------------------------------------------- 
dedecms.com
        UPDDEMO.C -- Demonstrates Anonymous FTP Access 
内容来自dedecms
                                                             (c) Charles Petzold, 1998 

织梦好,好织梦

----------------------------------------------------------------------------*/ 内容来自dedecms 
  

内容来自dedecms

#include               <windows.h> 本文来自织梦 
#include               <wininet.h> 织梦好,好织梦 
#include               <process.h> 
dedecms.com
#include               "resource.h" 
织梦内容管理系统
  
dedecms.com
               // User-defined messages used in WndProc 内容来自dedecms 
  内容来自dedecms 
#define        WM_USER_CHECKFILES     (WM_USER + 1) copyright dedecms 
#define        WM_USER_GETFILES               (WM_USER + 2) 
内容来自dedecms
  copyright dedecms 
               // Information for FTP download copyright dedecms 
  

织梦好,好织梦

#define        FTPSERVER      TEXT    ("ftp.cpetzold.com") 织梦好,好织梦 
#define        DIRECTORY      TEXT    ("cpetzold.com/ProgWin/UpdDemo") dedecms.com 
#define        TEMPLATE       TEXT    ("UD??????.TXT") dedecms.com 
  
内容来自dedecms
     // Structures used for storing filenames and contents dedecms.com 
typedef struct 本文来自织梦 
{ 

本文来自织梦

        TCHAR * szFilename ; 织梦好,好织梦 
        char  * szContents ; 内容来自dedecms 
} 

织梦内容管理系统

FILEINFO ; 
织梦好,好织梦
typedef struct 
织梦好,好织梦
{ 

内容来自dedecms

        int                            iNum ; 织梦好,好织梦 
        FILEINFO               info[1] ; 织梦内容管理系统 
} 
copyright dedecms
FILELIST ; 织梦好,好织梦 
     // Structure used for second thread 内容来自dedecms 
typedef struct 本文来自织梦 
{ 
本文来自织梦
        BOOL bContinue ; dedecms.com 
        HWND hwnd ; 

织梦好,好织梦

} 内容来自dedecms 
PARAMS ; 织梦内容管理系统 
               // Declarations of all functions in program 
dedecms.com
LRESULT        CALLBACK               WndProc (HWND, UINT, WPARAM, LPARAM) ; copyright dedecms 
BOOL                   CALLBACK               DlgProc (HWND, UINT, WPARAM, LPARAM) ; 
本文来自织梦
VOID                                                         FtpThread (PVOID) ; 织梦好,好织梦 
VOID                                                         ButtonSwitch (HWND, HWND, TCHAR *) ; 
本文来自织梦
FILELIST *                                    GetFileList (VOID) ; 
织梦内容管理系统
int                                                          Compare (const FILEINFO *, const FILEINFO *) ; 织梦好,好织梦 
  

织梦内容管理系统

               // A couple globals 

dedecms.com

  
dedecms.com
HINSTANCE hInst ; copyright dedecms 
TCHAR                          szAppName[] = TEXT ("UpdDemo") ; copyright dedecms 
  内容来自dedecms 
int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, 织梦内容管理系统 
                                                                     PSTR szCmdLine, int iCmdShow) 
copyright dedecms
{ 

dedecms.com

        HWND                                          hwnd ; 织梦好,好织梦 
        MSG                                           msg ; 本文来自织梦 
        WNDCLASS                              wndclass ; 织梦内容管理系统 
  织梦好,好织梦 
        hInst = hInstance ; dedecms.com 
        wndclass.style                                = 0 ; dedecms.com 
        wndclass.lpfnWndProc                          = WndProc ; 内容来自dedecms 
        wndclass.cbClsExtra                           = 0 ; 
织梦内容管理系统
        wndclass.cbWndExtra                           = 0 ; 
本文来自织梦
        wndclass.hInstance                            = hInstance ; dedecms.com 
        wndclass.hIcon                                = LoadIcon (NULL, IDI_APPLICATION) ; 织梦好,好织梦 
        wndclass.hCursor                              = NULL ; 织梦好,好织梦 
        wndclass.hbrBackground                = GetStockObject (WHITE_BRUSH) ; copyright dedecms 
        wndclass.lpszMenuName                 = NULL ; 内容来自dedecms 
        wndclass.lpszClassName                = szAppName ; 织梦好,好织梦 
  

织梦内容管理系统

        if (!RegisterClass (&wndclass)) 

织梦好,好织梦

        { 
织梦好,好织梦
                       MessageBox (   NULL, TEXT ("This program requires Windows NT!"),  
本文来自织梦
                                                                     szAppName, MB_ICONERROR) ; 

dedecms.com

                       return 0 ; 

本文来自织梦

     } 本文来自织梦 
      
copyright dedecms
        hwnd = CreateWindow (  szAppName, TEXT ("Update Demo with Anonymous FTP"), 

dedecms.com

                       WS_OVERLAPPEDWINDOW | WS_VSCROLL, 
内容来自dedecms
                       CW_USEDEFAULT, CW_USEDEFAULT, 本文来自织梦 
                       CW_USEDEFAULT, CW_USEDEFAULT, 
copyright dedecms
                       NULL, NULL, hInstance, NULL) ; 

织梦内容管理系统

  

织梦好,好织梦

        ShowWindow (hwnd, iCmdShow) ; 

织梦好,好织梦

        UpdateWindow (hwnd) ; 

本文来自织梦

  内容来自dedecms 
                       // After window is displayed, check if the latest file exists copyright dedecms 
        SendMessage (hwnd, WM_USER_CHECKFILES, 0, 0) ; 织梦好,好织梦 
        while (GetMessage (&msg, NULL, 0, 0)) 织梦内容管理系统 
        { 
本文来自织梦
                       TranslateMessage (&msg) ; 本文来自织梦 
                       DispatchMessage (&msg) ; 

织梦好,好织梦

        } copyright dedecms 
        return msg.wParam ; dedecms.com 
} 织梦好,好织梦 
  

内容来自dedecms

LRESULT CALLBACK WndProc (     HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) copyright dedecms 
{ dedecms.com 
        static FILELIST *      plist ; 

本文来自织梦

        static int                                    cxClient, cyClient, cxChar, cyChar ; copyright dedecms 
        HDC                                                          hdc ; 织梦内容管理系统 
        int                                                          i ; 

本文来自织梦

        PAINTSTRUCT                                   ps ; 织梦好,好织梦 
        SCROLLINFO                                    si ; 织梦好,好织梦 
        SYSTEMTIME                                    st ; 本文来自织梦 
        TCHAR                                                        szFilename [MAX_PATH] ; 

copyright dedecms

  
dedecms.com
        switch (message) 

织梦好,好织梦

     { 本文来自织梦 
        case    WM_CREATE: 
copyright dedecms
                               cxChar = LOWORD (GetDialogBaseUnits ()) ; 内容来自dedecms 
                               cyChar = HIWORD (GetDialogBaseUnits ()) ; 
内容来自dedecms
                               return 0 ; copyright dedecms 
  

内容来自dedecms

        case    WM_SIZE: 
本文来自织梦
                               cxClient               = LOWORD (lParam) ; 织梦内容管理系统 
                               cyClient               = HIWORD (lParam) ; 织梦内容管理系统 
  本文来自织梦 
                               si.cbSize      = sizeof (SCROLLINFO) ; 本文来自织梦 
                               si.fMask               = SIF_RANGE | SIF_PAGE ; 

本文来自织梦

                               si.nMin                = 0 ; 内容来自dedecms 
                               si.nMax                = plist ? plist->iNum - 1 : 0 ; 
内容来自dedecms
                               si.nPage               = cyClient / cyChar ; 

本文来自织梦

  
织梦内容管理系统
                               SetScrollInfo (hwnd, SB_VERT, &si, TRUE) ; copyright dedecms 
                               return 0 ; 
本文来自织梦
  

dedecms.com

        case    WM_VSCROLL: 
织梦内容管理系统
                               si.cbSize      = sizeof (SCROLLINFO) ; 内容来自dedecms 
                               si.fMask               = SIF_POS | SIF_RANGE | SIF_PAGE ; 内容来自dedecms 
                               GetScrollInfo (hwnd, SB_VERT, &si) ; 

copyright dedecms

  本文来自织梦 
                               switch (LOWORD (wParam)) 

本文来自织梦

                               { 

内容来自dedecms

                               case SB_LINEDOWN: si.nPos += 1 ; break ; 

内容来自dedecms

                               case SB_LINEUP:   si.nPos -= 1 ; break ; 织梦好,好织梦 
                               case SB_PAGEDOWN: si.nPos += si.nPage ; break ; copyright dedecms 
                               case SB_PAGEUP:   si.nPos -= si.nPage ; break ; 

本文来自织梦

                               case SB_THUMBPOSITION: si.nPos = HIWORD (wParam) ;    break ; 

织梦好,好织梦

                               default:                       return 0 ; 内容来自dedecms 
                               } dedecms.com 
                               si.fMask = SIF_POS ; 

dedecms.com

                               SetScrollInfo (hwnd, SB_VERT, &si, TRUE) ; 织梦内容管理系统 
                               InvalidateRect (hwnd, NULL, TRUE) ; 内容来自dedecms 
                               return 0 ; 

dedecms.com

  

dedecms.com

        case    WM_USER_CHECKFILES: copyright dedecms 
                               // Get the system date & form filename from year and month copyright dedecms 
  
内容来自dedecms
                               GetSystemTime (&st) ; 织梦好,好织梦 
                               wsprintf (szFilename, TEXT ("UD%04i%02i.TXT"), st.wYear, st.wMonth) ; 本文来自织梦 
  织梦内容管理系统 
                               // Check if the file exists; if so, read all the files copyright dedecms 
  
本文来自织梦
                               if (GetFileAttributes (szFilename) != (DWORD) -1) 织梦内容管理系统 
                               { 

织梦内容管理系统

                                      SendMessage (hwnd, WM_USER_GETFILES, 0, 0) ; 
本文来自织梦
                                      return 0 ; 

内容来自dedecms

                               } 织梦好,好织梦 
                               // Otherwise, get files from Internet. 

织梦内容管理系统

                               // But first check so we don't try to copy files to a CD-ROM! dedecms.com 
  织梦好,好织梦 
                               if (GetDriveType (NULL) == DRIVE_CDROM) 织梦内容管理系统 
                               { 织梦内容管理系统 
    MessageBox (hwnd, TEXT ("Cannot run this program from CD-ROM!"), 

copyright dedecms

                szAppName, MB_OK | MB_ICONEXCLAMATION) ; 
dedecms.com
                                      return 0 ; 本文来自织梦 
                               } dedecms.com 
                                              // Ask user if an Internet connection is desired 

本文来自织梦

  内容来自dedecms 
                               if (IDYES == MessageBox (hwnd, TEXT ("Update information from Internet?"), 织梦好,好织梦 
                        szAppName, MB_YESNO | MB_ICONQUESTION)) dedecms.com 
  本文来自织梦 
                                              // Invoke dialog box  

copyright dedecms

  dedecms.com 
                       DialogBox (hInst, szAppName, hwnd, DlgProc) ; 
织梦好,好织梦
  

内容来自dedecms

                                              // Update display 

织梦内容管理系统

  

织梦内容管理系统

                               SendMessage (hwnd, WM_USER_GETFILES, 0, 0) ; 本文来自织梦 
                               return 0 ; 
dedecms.com
  

织梦内容管理系统

        case    WM_USER_GETFILES: 内容来自dedecms 
                               SetCursor (LoadCursor (NULL, IDC_WAIT)) ; 

copyright dedecms

                               ShowCursor (TRUE) ; 织梦好,好织梦 
  dedecms.com 
                                              // Read in all the disk files dedecms.com 
  
织梦内容管理系统
                               plist = GetFileList () ; 
织梦好,好织梦
  本文来自织梦 
                               ShowCursor (FALSE) ; 本文来自织梦 
                               SetCursor (LoadCursor (NULL, IDC_ARROW)) ; 

dedecms.com

  dedecms.com 
                                      // Simulate a WM_SIZE message to alter scroll bar & repaint 

dedecms.com

  

织梦好,好织梦

                               SendMessage (hwnd, WM_SIZE, 0, MAKELONG (cxClient, cyClient)) ; 
内容来自dedecms
                               InvalidateRect (hwnd, NULL, TRUE) ; copyright dedecms 
                               return 0 ; 

织梦好,好织梦

  
织梦好,好织梦
        case    WM_PAINT: 内容来自dedecms 
                               hdc = BeginPaint (hwnd, &ps) ; 

本文来自织梦

                               SetTextAlign (hdc, TA_UPDATECP) ; 
dedecms.com
  

copyright dedecms

                               si.cbSize = sizeof (SCROLLINFO) ; 本文来自织梦 
                               si.fMask  = SIF_POS ; 
copyright dedecms
                               GetScrollInfo (hwnd, SB_VERT, &si) ; copyright dedecms 
  内容来自dedecms 
                               if (plist) 
内容来自dedecms
                               { 

织梦好,好织梦

                                      for (i = 0 ; i < plist->iNum ; i++) 本文来自织梦 
                                      { 
内容来自dedecms
                    MoveToEx   (hdc, cxChar, (i - si.nPos) * cyChar, NULL) ; 

本文来自织梦

                    TextOut    (hdc, 0, 0, plist->info[i].szFilename,  

dedecms.com

                    lstrlen (plist->info[i].szFilename)) ; dedecms.com 
                    TextOut  (hdc, 0, 0, TEXT (": "), 2) ; 
织梦内容管理系统
                    TextOutA (hdc, 0, 0, plist->info[i].szContents,  内容来自dedecms 
                    strlen (plist->info[i].szContents)) ; 
内容来自dedecms
                                      } 

织梦好,好织梦

                               } copyright dedecms 
                               EndPaint (hwnd, &ps) ; 

dedecms.com

                               return 0 ; 
本文来自织梦
  

dedecms.com

        case    WM_DESTROY: 

copyright dedecms

                               PostQuitMessage (0) ; 织梦内容管理系统 
                               return 0 ; 

织梦好,好织梦

        } 织梦好,好织梦 
        return DefWindowProc (hwnd, message, wParam, lParam) ; 织梦好,好织梦 
} dedecms.com 
  

织梦好,好织梦

BOOL CALLBACK DlgProc (        HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) copyright dedecms 
{ dedecms.com 
        static PARAMS params ; 本文来自织梦 
        switch (message) 
本文来自织梦
        { 

织梦内容管理系统

        case    WM_INITDIALOG: 本文来自织梦 
                               params.bContinue = TRUE ; 
copyright dedecms
                               params.hwnd = hwnd ; 
dedecms.com
  本文来自织梦 
                               _beginthread (FtpThread, 0, ¶ms) ; copyright dedecms 
                               return TRUE ; 
dedecms.com
  dedecms.com 
        case    WM_COMMAND: dedecms.com 
                               switch (LOWORD (wParam)) 

本文来自织梦

                               { 本文来自织梦 
                               case    IDCANCEL:   // button for user to abort download 

本文来自织梦

                                      params.bContinue = FALSE ; 
dedecms.com
                                      return TRUE ; 
织梦内容管理系统
  织梦内容管理系统 
                               case    IDOK:      // button to make dialog box go away 

本文来自织梦

                                      EndDialog (hwnd, 0) ; 
内容来自dedecms
                                      return TRUE ; 本文来自织梦 
                               } 本文来自织梦 
        } 
本文来自织梦
        return FALSE ; 内容来自dedecms 
} 
内容来自dedecms
  织梦内容管理系统 
/*--------------------------------------------------------------------------- 
dedecms.com
        FtpThread: Reads files from FTP server and copies them to local disk 
dedecms.com
-----------------------------------------------------------------------------*/ 
copyright dedecms
  dedecms.com 
void FtpThread (PVOID parg) 

织梦好,好织梦

{ 织梦好,好织梦 
        BOOL                                                         bSuccess ; 本文来自织梦 
        HINTERNET                                     hIntSession, hFtpSession, hFind ; 内容来自dedecms 
        HWND                                                         hwndStatus, hwndButton ; copyright dedecms 
        PARAMS                                *       pparams ; 
织梦内容管理系统
        TCHAR                                                        szBuffer [64] ; 
织梦内容管理系统
        WIN32_FIND_DATA                finddata ; 织梦好,好织梦 
  
织梦好,好织梦
        pparams                = parg ; 织梦内容管理系统 
        hwndStatus     = GetDlgItem (pparams->hwnd, IDC_STATUS) ; 本文来自织梦 
        hwndButton     = GetDlgItem (pparams->hwnd, IDCANCEL) ; dedecms.com 
  
织梦内容管理系统
                               // Open an internet session dedecms.com 
      dedecms.com 
        hIntSession = InternetOpen (szAppName, INTERNET_OPEN_TYPE_PRECONFIG, 

dedecms.com

                                      NULL, NULL, INTERNET_FLAG_ASYNC) ; dedecms.com 
        if (hIntSession == NULL) 

本文来自织梦

        { 内容来自dedecms 
        wsprintf (szBuffer, TEXT ("InternetOpen error %i"), GetLastError ()) ; 内容来自dedecms 
                       ButtonSwitch (hwndStatus, hwndButton, szBuffer) ; dedecms.com 
                       _endthread () ; 本文来自织梦 
        } 
织梦好,好织梦
  

copyright dedecms

        SetWindowText (hwndStatus, TEXT ("Internet session opened...")) ; 
本文来自织梦
                               // Check if user has pressed Cancel 
dedecms.com
        if (!pparams->bContinue) 

织梦好,好织梦

        { 内容来自dedecms 
                       InternetCloseHandle (hIntSession) ; 
织梦内容管理系统
                       ButtonSwitch (hwndStatus, hwndButton, NULL) ; 织梦好,好织梦 
                       _endthread () ; 内容来自dedecms 
        } copyright dedecms 
  

内容来自dedecms

                       // Open an FTP session. 

dedecms.com

hFtpSession = InternetConnect (hIntSession, FTPSERVER, INTERNET_DEFAULT_FTP_PORT, copyright dedecms 
                              NULL, NULL, INTERNET_SERVICE_FTP, 0, 0) ; 

织梦内容管理系统

        if (hFtpSession == NULL) 内容来自dedecms 
        { 

织梦好,好织梦

                       InternetCloseHandle (hIntSession) ; 

织梦内容管理系统

                       wsprintf (szBuffer, TEXT ("InternetConnect error %i"),  

本文来自织梦

                                                                     GetLastError ()) ; 
copyright dedecms
               ButtonSwitch (hwndStatus, hwndButton, szBuffer) ; dedecms.com 
               _endthread () ; 

织梦好,好织梦

     } copyright dedecms 
  dedecms.com 
        SetWindowText (hwndStatus, TEXT ("FTP Session opened...")) ; 织梦内容管理系统 
                               // Check if user has pressed Cancel 

copyright dedecms

        if (!pparams->bContinue) 
织梦内容管理系统
        { 

dedecms.com

                       InternetCloseHandle (hFtpSession) ; copyright dedecms 
                       InternetCloseHandle (hIntSession) ; dedecms.com 
                       ButtonSwitch (hwndStatus, hwndButton, NULL) ; 
织梦好,好织梦
                       _endthread () ; dedecms.com 
        } 

织梦好,好织梦

  copyright dedecms 
                               // Set the directory 织梦内容管理系统 
        bSuccess = FtpSetCurrentDirectory (hFtpSession, DIRECTORY) ; 

织梦内容管理系统

        if (!bSuccess) 织梦内容管理系统 
        { 

copyright dedecms

                       InternetCloseHandle (hFtpSession) ; 
织梦好,好织梦
                       InternetCloseHandle (hIntSession) ; 

dedecms.com

                       wsprintf (     szBuffer, TEXT ("Cannot set directory to %s"), 
copyright dedecms
                                                                     DIRECTORY) ; 织梦内容管理系统 
                       ButtonSwitch (hwndStatus, hwndButton, szBuffer) ; 
内容来自dedecms
                       _endthread () ; 织梦好,好织梦 
        } 织梦内容管理系统 
  

织梦好,好织梦

        SetWindowText (hwndStatus, TEXT ("Directory found...")) ; 内容来自dedecms 
                       // Check if user has pressed Cancel 织梦好,好织梦 
        if (!pparams->bContinue) 
copyright dedecms
        { 
内容来自dedecms
                       InternetCloseHandle (hFtpSession) ; 

织梦内容管理系统

                       InternetCloseHandle (hIntSession) ; 
内容来自dedecms
                       ButtonSwitch (hwndStatus, hwndButton, NULL) ; 内容来自dedecms 
                      _endthread () ; 
织梦好,好织梦
        } 

copyright dedecms

  

内容来自dedecms

                               // Get the first file fitting the template 

本文来自织梦

        hFind = FtpFindFirstFile (hFtpSession, TEMPLATE, &finddata, 0, 0) ; 本文来自织梦 
        if (hFind == NULL) copyright dedecms 
        { 
内容来自dedecms
                       InternetCloseHandle (hFtpSession) ; 织梦内容管理系统 
                       InternetCloseHandle (hIntSession) ; copyright dedecms 
                       ButtonSwitch (hwndStatus, hwndButton, TEXT ("Cannot find files")) ; 
织梦好,好织梦
                       _endthread () ; 织梦好,好织梦 
        } dedecms.com 
  

dedecms.com

        do  本文来自织梦 
        { 
dedecms.com
                               // Check if user has pressed Cancel 

dedecms.com

               if (!pparams->bContinue) 
织梦好,好织梦
                       { 

copyright dedecms

                               InternetCloseHandle (hFind) ; 内容来自dedecms 
                               InternetCloseHandle (hFtpSession) ; 
本文来自织梦
                               InternetCloseHandle (hIntSession) ; 

织梦好,好织梦

                               ButtonSwitch (hwndStatus, hwndButton, NULL) ; 

织梦内容管理系统

                               _endthread () ; 本文来自织梦 
                       } 本文来自织梦 
                               // Copy file from internet to local hard disk, but fail 

内容来自dedecms

                               // if the file already exists locally dedecms.com 
  
织梦好,好织梦
                       wsprintf (szBuffer, TEXT ("Reading file %s..."), finddata.cFileName) ; 织梦内容管理系统 
                       SetWindowText (hwndStatus, szBuffer) ; 
dedecms.com
  织梦好,好织梦 
                       FtpGetFile (   hFtpSession,  织梦内容管理系统 
                finddata.cFileName, finddata.cFileName, TRUE,  

织梦好,好织梦

                FILE_ATTRIBUTE_NORMAL, FTP_TRANSFER_TYPE_BINARY, 0) ; 
copyright dedecms
        } copyright dedecms 
        while (InternetFindNextFile (hFind, &finddata)) ; 
织梦内容管理系统
        InternetCloseHandle (hFind) ; 

织梦内容管理系统

        InternetCloseHandle (hFtpSession) ; 本文来自织梦 
        InternetCloseHandle (hIntSession) ; 

内容来自dedecms

  

内容来自dedecms

        ButtonSwitch (hwndStatus, hwndButton, TEXT ("Internet Download Complete")); 

本文来自织梦

} 

织梦好,好织梦

  

织梦内容管理系统

/*---------------------------------------------------------------------------- dedecms.com 
        ButtonSwitch:  Displays final status message and changes Cancel to OK 
内容来自dedecms
  -------------------------------------------------------------------------*/ 
copyright dedecms
VOID ButtonSwitch (HWND hwndStatus, HWND hwndButton, TCHAR * szText)  
内容来自dedecms
{ 织梦好,好织梦 
        if (szText) 织梦好,好织梦 
                               SetWindowText (hwndStatus, szText) ; 织梦好,好织梦 
        else 

本文来自织梦

                               SetWindowText (hwndStatus, TEXT ("Internet Session Cancelled")) ; 

织梦内容管理系统

        SetWindowText (hwndButton, TEXT ("OK")) ; 本文来自织梦 
        SetWindowLong (hwndButton, GWL_ID, IDOK) ; 

织梦好,好织梦

} 
dedecms.com
  

织梦内容管理系统

/*--------------------------------------------------------------------------- 织梦好,好织梦 
        GetFileList: Reads files from disk and saves their names and contents 

本文来自织梦

-----------------------------------------------------------------------------*/ 
织梦好,好织梦
  

copyright dedecms

FILELIST * GetFileList (void) 

dedecms.com

{ 织梦好,好织梦 
        DWORD                                                        dwRead ; 织梦内容管理系统 
        FILELIST                              *       plist ; 织梦内容管理系统 
        HANDLE                                                hFile, hFind ; copyright dedecms 
        int                                                          iSize, iNum  ; 织梦内容管理系统 
        WIN32_FIND_DATA                finddata ; 内容来自dedecms 
  
内容来自dedecms
        hFind = FindFirstFile (TEMPLATE, &finddata) ; 
织梦好,好织梦
        if (hFind == INVALID_HANDLE_VALUE) 内容来自dedecms 
                               return NULL ; 织梦内容管理系统 
        plist          = NULL ; 织梦内容管理系统 
        iNum           = 0 ; 内容来自dedecms 
  织梦内容管理系统 
        do 

内容来自dedecms

        { 

内容来自dedecms

                                      // Open the file and get the size 

copyright dedecms

                       hFile = CreateFile (finddata.cFileName, GENERIC_READ, FILE_SHARE_READ, 织梦内容管理系统 
                        NULL, OPEN_EXISTING, 0, NULL) ; 内容来自dedecms 
  dedecms.com 
                       if (hFile == INVALID_HANDLE_VALUE) 织梦好,好织梦 
                                      continue ; 

本文来自织梦

      
织梦内容管理系统
                       iSize = GetFileSize (hFile, NULL) ; 

织梦内容管理系统

  内容来自dedecms 
                       if (iSize == (DWORD) -1) 

dedecms.com

               { 

dedecms.com

                                      CloseHandle (hFile) ; 

织梦好,好织梦

                                      continue ; copyright dedecms 
               } 
copyright dedecms
                                      // Realloc the FILELIST structure for a new entry  

copyright dedecms

  本文来自织梦 
                       plist = realloc (plist, sizeof (FILELIST) + iNum * sizeof (FILEINFO)); 本文来自织梦 
  

织梦好,好织梦

                                      // Allocate space and save the filename  dedecms.com 
  内容来自dedecms 
                       plist->info[iNum].szFilename = malloc (lstrlen (finddata.cFileName) +sizeof (TCHAR)) ; 

本文来自织梦

                       lstrcpy (plist->info[iNum].szFilename, finddata.cFileName) ; 

本文来自织梦

  

本文来自织梦

                                      // Allocate space and save the contents 本文来自织梦 
  内容来自dedecms 
                       plist->info[iNum].szContents = malloc (iSize + 1) ; 
本文来自织梦
                       ReadFile (hFile, plist->info[iNum].szContents, iSize, &dwRead, NULL); 内容来自dedecms 
                       plist->info[iNum].szContents[iSize] = 0 ; 内容来自dedecms 
  

dedecms.com

                       CloseHandle (hFile) ; 

copyright dedecms

                       iNum ++ ; 
dedecms.com
        } 本文来自织梦 
        while (FindNextFile (hFind, &finddata)) ; copyright dedecms 
        FindClose (hFind) ; copyright dedecms 
                                      // Sort the files by filename 织梦内容管理系统 
        qsort (plist->info, iNum, sizeof (FILEINFO), Compare) ; 

dedecms.com

        plist->iNum = iNum ; copyright dedecms 
        return plist ; dedecms.com 
} 本文来自织梦 
  

织梦好,好织梦

/*--------------------------------------------------------------------------- dedecms.com 
        Compare function for qsort 
织梦内容管理系统
----------------------------------------------------------------------------*/ 

copyright dedecms

  
dedecms.com
int Compare (const FILEINFO * pinfo1, const FILEINFO * pinfo2) 织梦内容管理系统 
{ 
内容来自dedecms
        return lstrcmp (pinfo2->szFilename, pinfo1->szFilename) ; 
dedecms.com
} 本文来自织梦 
 UPDDEMO.RC (摘录) 
织梦好,好织梦
//Microsoft Developer Studio generated resource script. 
本文来自织梦
#include "resource.h" 

内容来自dedecms

#include "afxres.h" 织梦内容管理系统 
  本文来自织梦 
///////////////////////////////////////////////////////////////////////////// copyright dedecms 
// Dialog 织梦内容管理系统 
UPDDEMO DIALOG DISCARDABLE  20, 20, 186, 95 织梦好,好织梦 
STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU 

copyright dedecms

CAPTION "Internet Download" 织梦内容管理系统 
FONT 8, "MS Sans Serif" 
本文来自织梦
BEGIN 
dedecms.com
        PUSHBUTTON             Cancel",IDCANCEL,69,74,50,14 织梦好,好织梦 
        CTEXT                                         "",IDC_STATUS,7,29,172,21 织梦内容管理系统 
END 内容来自dedecms 
 RESOURCE.H (摘录) 
织梦好,好织梦
// Microsoft Developer Studio generated include file. 
本文来自织梦
// Used by UpdDemo.rc 织梦内容管理系统 
  

织梦好,好织梦

#define IDC_STATUS     40001 
本文来自织梦

UPDDEMO使用的档案名称是UDyyyymm.TXT,其中yyyy4位阿拉伯数字的年数(当然适用於2000),mm2位阿拉伯数字的月数。这里假定程式可以享有每个月都有更新档案的好处。这些档案可能是整个月刊,而由於阅读效率上的考虑,让程式将其下载到本地储存媒体上。

dedecms.com

因此,WinMain在呼叫ShowWindowUpdateWindow来显示UPDDEMO主视窗以後,向WndProc发送程式定义的WM_USER_CHECKFILES讯息。WndProc通过获得目前的年、月并检查该年月UDyyyymm.TXT档案所在的内定目录来处理此讯息。这种档案的存在意义在於UPDDEMO会被完全更新(当然,事实并非如此。一些过时的档案将漏掉。如果要做得更完整,程式得进行更广泛的检测)。在这种情况下,UPDDEMO向自己发送一个WM_USER_GETFILES讯息,它通过呼叫GetFileList函式来处理。这是UPDDEMO.C中稍长的一个函式,但它并不是特别有用,它所做的全部工作就是将所有的UDyyyymm.TXT档案读到动态配置的FILELIST型态结构中,该结构是在程式顶部定义的,然後让程式在其显示区域显示这些档案的内容。

织梦内容管理系统

如果UPDDEMO没有最新的档案,那么它必须透过Internet进行更新。程式首先询问使用者这样做是否「OK」。如果是,程式将显示一个简单的对话方块,其中只有一个「Cancel」按钮和一个IDIDC_STATUS的静态文字区。下载时,此静态文字区向使用者提供状态报告,并且允许使用者取消过於缓慢的更新作业。此对话程序的名称是DlgProc本文来自织梦

DlgProc很短,它建立了一个包括自身视窗代号的PARAMS型态的结构以及一个名称为bContinueBOOL变数,然後呼叫_ beginthread来执行第二个执行绪。

dedecms.com

FtpThread函式透过使用下面的呼叫来完成实际的传输:InternetOpenInternetConnectFtpSetCurrentDirectoryFtpFindFirstFileInternetFindNextFileFtpGetFileInternetCloseHandle(三次)。如同大多数程式码,该执行绪函式如果略过错误检查、让使用者了解下一步的操作情况以及允许使用者随意取消整个显示的那些步骤,那么它将变得简洁许多。FtpThread函式透过用hwndStatus代号呼叫SetWindowText来让使用者知道进展情况,这里指的是对话方块中间的静态文字区。

copyright dedecms

执行绪可以依照下面的三种方式之一来终止:

dedecms.com

第一种,FtpThread可能遇到从WinInet函式传回的错误。如果是这样,它将清除并编排错误字串的格式,然後将此字串(连同对话方块文字区代号和「Cancel」按钮的代号一起)传递给ButtonSwitchButtonSwitch是一个小函式,它显示了文字字串,并将「Cancel」按钮转换成「OK」按钮-不只是按钮上的文字字串的转换,还包括控制项ID的转换。这样就允许使用者按下「OK」按钮来结束对话方块。 织梦好,好织梦

第二种方式,FtpThread能在没有任何错误的情况下完成任务,其处理方法和遇到错误时的方法一样,只不过对话方块中显示的字串为「Internet Download Complete」。 织梦内容管理系统

第三种方式,使用者可以在程序中选择取消下载。这时,DlgProcPARAMS结构的bContinue栏位设定为FALSEFtpThread频繁地检查该值,如果bContinue等於FALSE,那么函式将做好应该进行的收拾工作,并以NULL文字参数呼叫ButtonSwitch,此参数表示显示了字串「Internet Session Cancelled」。同样,使用者必须按下「OK」按钮来关闭对话方块。 织梦内容管理系统

虽然UPDDEMO取得的每个档案只能显示一行,但我(本书的作者)可以用这个程式来告诉您(本书的读者)本书的更新内容以及其他资讯,您也可以在网站上发现更详细的资讯。因此,UPDDEMO成为我向您传送资讯的方法,并且可以让本书的内容延续到最後一页之後。 dedecms.com