Bootstrap

VC++中使用使用winnet类获取网页内容

 

  • 微软提供的Winnet类是一个应用层的网络通信组件,

    它可以使你的应用程序很容易的实现http、ftp、gopher等协议而不需要

    你去深入的了解协议本身的规范。而之前,如果要想做类似的应用,我们

    必须了解socket编程并且要对协议本身非常熟悉,哪怕是一个非常非常

    简单的程序。



    下面是codeguru上的一个使用wininet类的例子,它能够从给定的url地址中

    获取该文件。



    这个例子实现了两个方法:

    cstring getwebpage(const cstring& url);

    void seterrormessage(cstring s);


    getwebpage是主要的方法,后面跟的url地址必须是一个完整的url地址,

    比如http://blog.csdn.net/cqq。

    seterrormessage方法, 能够处理程序中发生的错误。




    下面来看代码:

    /*
    //------------------------------------------------------------------------------------------------------------------
    // webworld.h: interface for the cwebworld class.
    //一个封装的类cwebworld,webworld.h是该类的头文件
    //------------------------------------------------------------------------------------------------------------------
    */

    #include "wininet.h" //包含wininet.h ,在mfc中也可以是afxinet.h

    class cwebworld
    {
    public:
    void seterrormessage(cstring s); //声明seterrormessage方法
    cstring getwebpage(const cstring& url); //声明getwebpage方法
    cwebworld(); //构造函数
    virtual ~cwebworld();

    private:
    cstring m_errormessage;
    hinternet m_session; //声明一个http连接的句柄
    };



    /*
    //------------------------------------------------------------------------------------------------------------------
    // webworld.cpp: implementation of the cwebworld class.
    // cwebworld类的具体实现
    //------------------------------------------------------------------------------------------------------------------
    */

    #include "stdafx.h"
    #include "webthief.h"


    #ifdef _debug
    #undef this_file
    static char this_file[]=__file__;
    #define new debug_new
    #endif

    #define agent_name "codegurubrowser1.0"

    //
    // construction/destruction
    //

    cwebworld::cwebworld()
    {
    dword dwerror;

    // initialize the win32 internet functions
    // 构造函数中初始化网络连接
    m_session = ::internetopen(agent_name,
    internet_open_type_preconfig, // use registry settings.
    null, // proxy name. null indicates use default.
    null, // list of local servers. null indicates default.
    0) ;

    dwerror = getlasterror();
    }

    cwebworld::~cwebworld()
    {
    // closing the session
    //虚构函数中释放连接
    ::internetclosehandle(m_session);
    }

    cstring cwebworld::getwebpage(const cstring& url)
    {
    hinternet hhttpfile;
    char szsizebuffer[32];
    dword dwlengthsizebuffer = sizeof(szsizebuffer);
    dword dwfilesize;
    dword dwbytesread;
    bool bsuccessful;
    cstring contents;

    // setting default error message
    contents = m_errormessage;

    // opening the url and getting a handle for http file
    hhttpfile = internetopenurl(m_session, (const char *) url, null, 0, 0, 0);

    if (hhttpfile)
    {
    // getting the size of http files
    bool bquery = ::httpqueryinfo(hhttpfile,http_query_content_length, szsizebuffer, &dwlengthsizebuffer, null) ;

    if(bquery==true)
    {
    // allocating the memory space for http file contents
    dwfilesize=atol(szsizebuffer);
    lpstr szcontents = contents.getbuffer(dwfilesize);

    // read the http file
    bool bread = ::internetreadfile(hhttpfile, szcontents, dwfilesize, &dwbytesread);

    if (bread)
    bsuccessful = true;

    ::internetclosehandle(hhttpfile); // close the connection.
    }

    }
    else
    {
    // connection failed.
    bsuccessful = false;
    }
    return contents;
    }

    void cwebworld::seterrormessage(cstring s)
    {
    m_errormessage = s;
    }


    下面是关于上面的类的使用方法:

    cwebworld a;
    cstring pagecontent;

  • 作者:经乾


    一、Windows的控制面板应用程序
    ---- 在Windows的系统目录下可以找到控制面板应用程序,它们是一些扩展名
    为cpl的dll,通常用来提供配置服务,如配置网络硬件和软件用的ncpa.cpl,配
    置桌面用的desk.cpl等,它们的父窗口都是桌面。运行这类程序的方法很多:双
    击控制面板中的图标,双击系统目录下的cpl文件,或者使用如下DOS命令:
    rundll32 shell32.dll,Control_RunDLL
    < cpl文件> [@n]或者
    control < cpl文件> [@n]

    ---- 其中@n用于指定运行运行哪一个小程序(一个cpl文件中可包含多个小程
    序),若不带此参数则相当于@0,即运行第一个小程序。例如:
    ---- Rundll32 shell32.dll,Control_RunDLL main.cpl @n

    ---- 若不带@n参数,则运行鼠标设置;@1则运行键盘设置;@2则运行打印机设
    置;@3则显示系统字体。

    ---- Control_RunDLL是shell32.dll中定义的一个函数,大小写敏感,用于启动
    控制面板。

    ---- 通过控制面板应用程序来提供配置服务是一种很好的方法,那么如何设计
    这种应用程序呢?下面以Visual C++6.0为例进行介绍。

    二、开发控制面板应用程序
    ---- 若希望一个文件传输程序启动后自动连接到某一个站点,就需要为其提供
    一些缺省值,如:服务器名、用户名、口令等。下面就开发一个控制面板应用
    程序来提供这些缺省值,具体步骤为:
    ---- 1.创建一个"MFC AppWizard (dll)"类型的项目,命名为:MyCplApp,选
    择"Regular DLL With MFC statically linked",使它的运行不依赖于其它任何DLL。

    ---- 2.选择Project菜单下的Settings项或按Alt+F7,在Link页中将输出文件
    名改为:

    ---- < WindowsDir >/< SystemDir >/Mycplapp.cpl,在Debug页中将
    "Executable for debug session"改为:< WindowsDir >/< SystemDir >/Control.exe,
    以便直接用控制面板运行。对于Win9x,< SystemDir >为System,对于WinNT,
    < SystemDir >为System32。

    ---- 3.从MSDN Library Visual Studio 6.0光盘的Smples目录中找到
    Ctrlpan.cpp 和Ctrlpan.h 文件,并把它们加到项目中。

    ---- 4.创建如图所示对话框,代号为:IDD_MYDIALOG,用Class Wizard创建
    一个CMyDialog类。为每个控件创建成员变量,如"FTP服务器"对应的成员变
    量定义为:CString m_strServer。



    ---- 5.引入或新建一个ICON,代号为:IDI_MYICON,用于控制面板中显示。

    ---- 6.从CControlPanel类(在Ctrlpan.h中定义)继承一个新类CMyPanel,修改
    MyPanel.h文件:

    #include "Ctrlpan.h"
    class CMyPanel : public CControlPanel
    { public:
    virtual LONG OnInquire(UINT uAppNum, NEWCPLINFO* pInfo);
    virtual LONG OnDblclk(HWND hwndCPl,
    UINT uAppNum, LONG lData);
    };//两个虚拟函数由读者加入

    ---- 7.在MyPanel.cpp中实现MyPanel.h中定义的两个虚拟函数:
    LONG CMyPanel::OnInquire(UINT uAppNum,
    NEWCPLINFO* pInfo)
    { //此函数在控制面板打开时被调用,
    用于获取资源信息,即填充pInfo结构
    pInfo- >dwSize = sizeof(NEWCPLINFO);//指定结构长度
    pInfo- >dwFlags = 0;//此成员忽略
    pInfo- >dwHelpContext = 0; //此成员忽略
    pInfo- >lData = 0;//小程序传递给应用程序的LONG类型的值
    pInfo- >hIcon= ::LoadIcon(AfxGetResourceHandle(),
    MAKEINTRESOURCE(IDI_MYICON));//加载图标
    strcpy(pInfo- >szName, "FTP设置");//设置名称
    strcpy(pInfo- >szInfo, "设置FTP缺省信息");//设置描述
    strcpy(pInfo- >szHelpFile, "");//此成员忽略
    return 0; //不发送CPL_INQUIRE消息
    }
    LONG CMyPanel::OnDblclk(HWND hwndCPl,
    UINT uAppNum, LONG lData)
    { //双击控制面板中的图标时,此函数被调用,
    用于读取或保存设置信息。
    CMyDialog dlg(CWnd::FromHandle(hwndCPl));
    //用父窗口句柄初始化对话框
    HKEY hcpl;//主键,用于读写注册表
    if (RegOpenKeyEx(HKEY_CURRENT_USER,
    "Control Panel//FTPSet",0,
    KEY_QUERY_VALUE, &hcpl) == ERROR_SUCCESS)
    { DWORD dwType = 1;//字符串类型REG_SZ
    DWORD dwSize;//字符串长度
    RegQueryValueEx(hcpl,"FTPServer",NULL,&dwType,
    (BYTE*)(LPCTSTR)dlg.m_strServer,&dwSize);
    RegCloseKey(hcpl);
    }//查询注册表,读取以前的设置信息,上面仅以m_strServer为例。
    RegCloseKey(hcpl);
    if(dlg.DoModal()!=IDOK) return 0;//执行对话框,
    若用户点击"取消"则返回
    DWORD dwDisp;//用于接收创建主键的返回值
    if (RegCreateKeyEx(HKEY_CURRENT_USER,
    "Control Panel//FTPSet",0,"",
    REG_OPTION_NON_VOLATILE, KEY_WRITE, NULL,
    &hcpl, &dwDisp) == ERROR_SUCCESS)
    { RegSetValueEx(hcpl,"FTPServer",0,REG_SZ,
    (BYTE*)(LPCTSTR)dlg.m_strServer,
    dlg.m_strServer.GetLength());
    RegCloseKey(hcpl);//将对话框中设置保存到注册表
    }return 0;
    }

    ---- 8.修
  • VC5开发工具提供了现成的窗口、控制与工具条的制作手段,大大简化了界面的开发
    过程,并且使得开发出的界面具有组态软件风格,使用起来方便、灵活、简单易学。

    本文以一实例介绍如何实现三个独立的分离窗口:监视窗口,控制窗口和动画窗口,
    并以图1中的进水和温度值传递为例,介绍如何实现控制功能和不同窗口间的数据共享,
    并介绍实现无闪烁动画的方法。
    (图略)

    如图1,将工作台分离成为三个窗口,动画窗口用于模拟锅炉的进、出水、升温的画
    面显示,其中的画面与系统采集的数据相对应。控制窗口用于实现预设温度值,调节水位、
    控制加热、暂停等功能。监视窗口用来实时跟踪采样的温度值,作出温度--时间曲线。

    一、创立分离窗口

    要实现多窗口显示,必须使用CSplitterWnd类,将窗口分成三个子窗口,然后将各个
    功能类与窗口联系起来。在创建应用程序时,在第一步中选择Single Document Interface, 并
    选用中文字库,在第4步中按下Advanced,选择Use Split Window选项。设定应用程序名
    为Animation。目前我们只有一个视类CAnimationView,它将与动画窗口对应,此外我们
    还要生成具有对话功能的监视窗口(对应CShowView类)和控制窗口(对应 CControlView
    类)。在Resource View中调出上下文菜单并选择Insert,选择属性为IDD_FORMVIEW,创
    建监视对话框IDD_SHOWVIEW和控制对话框IDD_CONTROLVIEW,并单击鼠标右键在
    Properties选择项中选择中文字库。然后编辑IDD_CONTROLVIEW:利用VC5提供的控件
    生成器生成ID名为IDC_SETTEMPERATURE的文字编辑域,并生成Caption为“设置温
    度初始值”。再利用button生成器,生成控件IDC_WATERIN,IDC_CONFIRM,Caption
    分别为“进水”和“确认”。再利用ClassWizard,创建基于CFormView类的新类,分别为
    CShowView和CControlView类,并将它们与刚创建的两个对话框联系。

    在CMainFrame类中,重载OnCreateClient()函数创建三个静态分离窗口,先在
    MainFrame.h中声明所需变量:

    protected:
    CSplitterWnd m_wndSplitter2;
    转入MainFrame.cpp程序,在开头处包含头文件“ShowView.h”,向下找到函数
    OnCreateClient(),添加如下代码,生成两个窗口,三个视图:
    BOOL CMainFrame::OnCreateClient(LPCREATESTRUCT/*lpcs*/,CCreateContext* pContext)
    {
    //先分裂成两个窗口,一行两列
    if(!m_wndSplitter.CreateStatic(this,1,2))
    {
    TRACE0("Failed to CreateStaticSplitter/n");
    return FALSE;
    }

    // 加上动画窗口,将其放在左边
    if(!m_wndSplitter.CreateView(0,0,pContext->m_pNewViewClass,CSize(425,50),pContext))
    {
    TRACE0("Failed to create first pane/n");
    return FALSE;
    }

    //将第二个窗口再一分为二
    if(!m_wndSplitter2.CreateStatic(
    &m_wndSplitter, //原来的m_wndSplitter是父指针,m_wndSplitter2是子指针
    2,1, //窗口分为两行,一列
    WS_CHILD|WS_VISIBLE|WS_BORDER,m_wndSplitter.IdFromRowCol(0,1)))
    {
    TRACE0("Failed to create nested splitter/n");
    return FALSE;
    }

    //增加两个视图,并调整视图大小
    if(!m_wndSplitter2.CreateView(0,0,
    RUNTIME_CLASS(CShowView),CSize(0,175),pContext))
    {
    TRACE0("Failed to create second pane/n");
    return FALSE;
    }

    if(!m_wndSplitter2.CreateView(1,0,RUNTIME_CLASS(CControlView),
    CSize(0,0),pContext))
    {
    TRACE0("Failed to create third pane/n");
    return FALSE;
    }
    return TRUE;
    }

    再转入Animation.cpp中,修改InitInstance()函数,将其中的m_pMainWnd->ShowWindow
    (SW_SHOW),改为m_pMainWnd->ShowWindow(SW_SHOWMAXIMIZED);至此,我们
    可以生成图1的界面框架。

    二、动画显示窗口的实现

    动画是通过调用一幅幅的图片来实现的,因此先将所需的画面载入资源BITMAP中,
    并按顺序编辑它们的ID号,然后在定时器中,每隔一定的时间调用一次动画函数。第一
    步先生成定时器,用ClassWizard给CAnimationView添加消息处理程序:OnCreate()函数
    对应于消息WM_CREATE,OnTimer()函数对应于消息WM_TIMER。编辑函数OnCreate(),
    生成每隔0.1秒的时钟。

    int CAnimationView::OnCreate(LPCREATESTRUCT lpCreateStruct)
    {
    if(CView::OnCreate(lpCreateStruct)= = -1)
    return -1;
    SetTimer(2,100,NULL); //产生每隔0.1秒的时钟
    return 0;
    }
    在函数OnTimer()中,调用动画服务函数ServicedAnimation(),该函数根据系统情况作出
    无闪烁动画,并可以根据不同的功能,选择画面。
    void CAnimationView::OnTimer(UINT nIDEvent)
    {
    CClientDC ClientDC(this);
    ServicedAnimation(&ClientDC); //调用动画服务函数
    CView::OnTimer(nIDEvent);
    }
    ServicedAnimation()用于检查系统的时钟,并能计算从发生最后一个动画事件开始计算
    起所经过的时间,然后这个函数检查本帧动画的延迟时间,并决定是否到达了另一次更新
    的时间,
  • ---- 读 了 贵 报9 月7 日《 学 习 与 编 程》 版 刊 登 的 宋 立 波 先
    生 的 文 章, 本 文 介 绍 另 一 种 方 法 来 制 作 封 面, 此 方 法 对
    于 单 文 档、 多 文 档 及 对 话 框 窗 体 均 适 用, 且 弥 补 了 宋 立
    波 先 生 文 章 中 所 述 封 面 关 闭 后 应 用 程 序 窗 体 才 能 显 示
    的 不 足 之 处。 方 法 如 下:
    ---- 1. 用App Wizard 生 成 一 工 程, 然 后 打 开 资 源 编 辑 器,
    Import 一 个BMP 图 形 文 件( 注: 由 于VC 的Bitmap 资 源 只 能 使
    用256 色 图 形, 所 以 需 用 画 板 或 其 他 图 形 工 具 转 换 成256
    色 图 形), 打 开 属 性 对 话 框, 将ID 号 改 为IDB_BITMAP -SPLASH。

    ---- 2. 新 建 一 个 对 话 框 资 源, 打 开 属 性 对 话 框, 选 择
    General; 将 新 对 话 框 资 源 的ID 号 改 为IDD_DIALOG_SPLASH, 选
    择Styles, 将Title bar 选 择 框 置 空, 改 变Border 属 性; 选 择
    None, 则 封 面 为 平 面 图 形; 选 择Dialog Frame, 则 封 面 为 立
    体 三 维 图 形。 在 对 话 框 资 源 上 添 加Picture 控 件, 打 开 属
    性 对 话 框 选 择General, 将Picture 控 件 的Type 改 为Bitmap、 Image
    改 为IDB -BITMAP -SPLASH; 将 对 话 框 资 源 的 大 小 改 为 与
    Picture 控 件 大 小 相 同。

    ---- 3. 选 对 话 框 资 源IDD_DIALOG_SPLASH, 打 开Class Wizard 添 加
    一 个 新 类, 类 名 定 义 为CSplash。

    ---- 4. 在MainFrame.h 的 类 定 义 中 添 加 一 指 针 成 员 变 量
    *sphash, 类 型 为CSplash; 在MainFrame.cpp 文 件 中 添 加 头 文 件,
    引 用 #include“splash.h”。 打 开Class Wizard, 选 择Message Maps,
    在Class name 中 选 择CMainFrame, 在Messages 中 选 择WM_TIMER 添 加
    OnTimer 函 数。

    ---- 5. 在CMainFrame 类 的OnCreate 函 数 中 添 加SetTimer 函 数, 并
    添 加 显 示splash 对 话 框 的 程 序 段:

    int CMainFrame::OnCreate
    (LPCREATESTRUCT 1pCreateStruct)
    {
    SetTime(1,50,NULL);

    ---- ∥ 添 加ID 号 为1 的WM_TIMER 事 件, 响 应 频 率 由 用 户 自 定 义, 但 不 宜 过 大

    splash=new CSplash();
    ∥ 添 加 播 放WAV 声 音 的 程 序 段
    ∥ 例 如:sndPlaySound(“sound.way,”SND_ASYNC);
    splash ->Create(IDD_DIALOG1);
    splash ->ShowWindo(SW_SHOW);
    splash ->UpdateWindow();
    … … ∥ 此 处 是OnCreate 函 数 中 原 有 的 程 序 段
    CenterWindow();
    ∥ 应 用 程 序 窗 体 居 中 显 示
    return 0;
    }

    ---- 6. 在CMainFrame 类 的OnTimer 函 数 中 添 加 响 应WM_TIMER 事 件
    的 程 序 段: Void CMainFrame::OnTimer(UINT nIDEvent)

    {
    ∥TODO:Add your message handler code here and/or call default
    if (nIDEvent==1)
    {
    if(splash ->Is WindowVisibl())
    {
    splash ->SetActiveWindow();
    ∥ 封 面 置 为 当 前 活 动 窗 体
    splash ->UpdateWindow();
    Sleep(2000); ∥ 封 面 显 示 停 留 时 间 由 用 户 自 己 改 变
    splash ->SendMessa(WM_CLOSE);
    }
    else
    {
    SetActiveWindow();
    ∥ 应 用 程 序 窗 体 置 为 当 前 活 动 窗 体
    KillTimer(1);
    ∥ 清 除WM_TIMER 事 件
    }
    }
    }

    ---- 到 此, 封 面 制 作 成 功, 如 果 要 添 加 声 音, 只 需 按 宋
    立 波 先 生 文 章 中 所 述 方 法, 添 加 在CMainFrame 类 的OnCreate
    函 数 中 注 释 段 内 即 可。 此 法 制 作 简 单, 容 易 实 现, 唯 一
    的 缺 点 是 此 封 面 显 示 的 图 形 色 彩 不 够 丰 富。( 贾 暾)
  • 很 多 大 型 应 用 程 序 都 有 启 动 封 面, 如Word 等 办 公 系 列 软
    件 和VC + + 等编 程 软 件。 通 过 启 动 封 面, 除 了 显 示 应 用 程
    序 名 称 和 版 权 等 提 示 画 面,还 可 避 免 由 于 应 用 程 序 启 动
    前 进 行 大 量 数 据 初 始 化 时, 用 户 较 长 时 间 的等 待, 给 应
    用 程 序 增 添 了 许 多 动 态 特 性 和 专 业 规 范。 鉴 于VC + + 开
    发 工 具 应 用 较 广, 这 里 以VC5 为 例 阐 述 启 动 封 面 的 一 般
    实 现 步 骤。

    ---- 1. 制 作 封 面 位 图

    ---- 制 作 应 用 程 序 启 动 封 面 真 彩 位 图, 记 录 位 图 的 高 度
    和 宽 度, 建 立 所 需要 的 其 他 声 音 等 文 件。

    ---- 2. 建 立 应 用 程 序

    ---- 利 用FILE
  • 随着Microsoft凭借Windows在操作系统上取得的巨大成绩,Windows用户界面也
    日益成为业界标准。统一的界面给广大用户对应用软件的学习与使用带来了很大
    方便。但每天都面对同一副面孔,日久天长难免会产生一些厌倦,开发一些"离
    经叛道",一改Windows应用程序千篇一律的"标准"界面,一定会给你带来一种清
    新的感觉。
    ---- 标准Windows应用程序窗口一般为带有标题栏的浅灰色矩形外观,因而"异
    形"对话框/窗口也主要是颜色与外形上动手脚。

    ---- 1.改变背景颜色

    ---- 改变对话框(窗口)的背景颜色是最简单的改变Windows应用程序外观的
    方法,根据Windows创建与管理机理,一般有两种方法。一种是处理WM_CTLCOLOR
    消息,首先创建所选背景颜色的刷子,然后调用SetBkColor()或
    SetDialogBkColor()以所创建的刷子来绘制窗口或对话框的背景。需要重画窗
    口或对话(或对话的子控件)时,Windows向对话发送消息WM_CTLCOLOR,应用程
    序处理WM_CTLCOLOR消息并返回一个用来绘画对话背景的刷子句柄。另外一种是
    响应Windows的WM_ERASEBKGND消息,Windows向窗口发送一个WM_ERASEBKGND消息
    通知该窗口擦除背景,可以使用VC++的ClassWizard重载该消息的缺省处理程序
    来擦除背景(实际是用刷子画),并返回TRUE以防止Windows擦除窗口。

    ---- 2.改变窗口外形
;