本文共 4447 字,大约阅读时间需要 14 分钟。
此处主要记录关于爬取百度图片模块与MFC界面融合时所遇到的问题,以及当中涉及的一些知识点做一下总结。
在mfc中,将CHttp类导入后,还需要引入头文件,一般头文件的引入要在stdafx.h中的最下方引入,否则有些文件会出现未定义标识符等错误。
#include "CHttp.h"#include#include using namespace std;
CString转string示例如下:
//使用CString类型接收搜索内容并转换成string类型 CString strText; m_text.GetWindowTextW(strText); string text = CW2A(strText.GetString());
CString转化为int类型示例如下:
//使用CString 接收编辑框内容 CString strFistPage; m_fistPage.GetWindowTextW(strFistPage);//将CString转化为int类型 int fistPage = _wtoi(strFistPage);
在主窗口类中的头文件中声明变量接收内容
//需要线程中使用的变量 string text; //转换后的文本 int fistPage; //转换后的首页 int lastPage; //转换后的尾页 string savePath; //转换后的路径 CWinThread *pThread; //定义线程句柄 //用于接收编辑框的变量 CString strText, strFistPage, strLastPage, strSavaPath, strThreads;
此处将所接受的保存路径中的字符"\“替换为”/",是为了后续函数URLDownloadToFile中的保存路径格式正确,否则下载时路径会出现问题
//接收保存路径并将其转换成string类型 m_savaPath.GetWindowTextW(strSavaPath); strSavaPath.Replace(_T("\\"), _T("/"));
在此处创建线程是为了防止在下载图片时主线程堵塞,导致界面卡顿无法移动等现象。创建一个线程就比较好。
而在mfc中创建线程调用窗口类函数的过程中遇到了很多问题,开始使用的createthread函数,一直无法实现,此函数主要用于控制台应用程序。如果要在mfc中创建线程,一般应使用AfxBeginThread函数创建。 参考链接:https://blog.csdn.net/u014568921/article/details/44262645 https://www.cnblogs.com/renyuan/p/3430894.html http://www.360doc.com/content/14/0507/09/8236462_375415995.shtml线程函数的类型是规定好的不能是类函数
具体示例如下:pThread = AfxBeginThread(ThreadProc,this); //参数1线程函数名,参数2this表示此窗口指针(通过此指针可以控制控件变量)
而pThread 则是此线程的句柄,在主窗口类的头文件中定义(为了在其他按钮控件中也能使用此句柄来控制线程,故在主窗口类的头文件中定义此线程句柄)
CWinThread *pThread; //定义线程句柄
而线程函数ThreadProc实现如下
int code = 0; //用来接收线程状态值//定义爬取线程UINT __cdecl ThreadProc(LPVOID lpParameter){ code = 1;//将先程状态值设为1,表明线程正在进行 CspiderBaiDuImgDlg *pThisGlg = (CspiderBaiDuImgDlg*)lpParameter; pThisGlg->StartCatchBaiDu(pThisGlg->text, pThisGlg->savePath, pThisGlg->fistPage, pThisGlg->lastPage); //通过指针调用主窗口类中的成员函数及成员变量 code = 0; //线程结束时再变为0 return 0;}
此处使用code作为线程状态值,为了后面的暂停、恢复、停止等功能实现时显示当前状态。
在初始化函数中创建判断线程
创建一个判断线程,判断执行线程是否还在执行 m_status.SetWindowTextW(_T("当前无任务进行")); CWinThread *pJudge = AfxBeginThread(ThreadJudge, this);
判断线程函数如下:
//定义判断爬取线程是否工作的线程(未能成功实现)UINT __cdecl ThreadJudge(LPVOID lpParameter){ CspiderBaiDuImgDlg *pThisGlg = (CspiderBaiDuImgDlg*)lpParameter; while(1){ //获取线程pThread的执行状态,如果 //若为真表明线程正在执行 if (code == 1){ pThisGlg->m_status.SetWindowTextW(_T("正在下载,请等候. . .")); } else if (code == 2){ pThisGlg->m_status.SetWindowTextW(_T("下载已暂停")); } else{ pThisGlg->m_status.SetWindowTextW(_T("当前无任务进行")); } Sleep(1000*1); //隔1秒进行一次判断 } return 0;}
参考链接:https://blog.csdn.net/plum2003/article/details/8651726
https://blog.csdn.net/visualeleven/article/details/6214725 示例代码如下:int iLen = m_result.GetWindowTextLength(); //获取输出结果编辑框中文本的长度 m_result.SetSel(iLen, iLen, TRUE); //设置光标位置为编辑框的文本的最后一位m_result.ReplaceSel(_T("获取html页面失败\r\n"), FALSE); //添加所要输出的字符串
参考链接:https://www.cnblogs.com/dzqdzq/archive/2013/04/09/3010665.html
使用此函数时,需要注意的是参数的格式
//下载文件stringToLPCWSTRHRESULT hr = URLDownloadToFile(NULL, buffer, imgsavepath, 0, NULL);
在downLoadImage函数中,是使用string类型来接收url地址及保存地址的。所以此处要将string类型的变量变为LPCWSTR类型的变量。方式如下所示:
string savepath = savepathM + "/" + name + to_string(fistPage) + "-" + to_string(i+1) + ".jpg"; //此处使用数字对其重命名 size_t len1 = savepath.length(); wchar_t* imgsavepath = new wchar_t[len1]; int nmlen1 = MultiByteToWideChar(CP_ACP, 0, savepath.c_str(), len1 + 1, imgsavepath, len1);
参考链接:https://blog.csdn.net/zanda_/article/details/90544856
示例如下:FILE* fp = fopen(savepath.c_str(), "r"); //savepath是string类型的,即保存路径如"G:/爬取图片/img/1.jpg"fseek(fp, 0, SEEK_END);size_t size = ftell(fp);fclose(fp);CString sizeImg;sizeImg.Format(_T("下载完成 [%4dKB] | "), (size/1000)); //此处将size 转为CString类型的方便显示在编辑框内
参考链接:https://blog.csdn.net/u011555996/article/details/90717837
https://www.cnblogs.com/tianxiafeiyu/p/9129849.html https://blog.csdn.net/langb2014/article/details/50644792IDR_MAINFRAME ICON "res\\spider.ico"