C/C++ 如何来自动优雅的涮别银家的贴子

时间:2022-05-05
本文章向大家介绍C/C++ 如何来自动优雅的涮别银家的贴子,主要内容包括其使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。

  被涮屏涮烦了,就分享一下如何用低调的c/c++来涮别人家的屏吧! 此处埋下三颗雷! 这不是啥新知识,也不是什么浅显的代码。下面,来淘淘这份经验,呼呼

我们要了解Web browser 这个控件,因为到目前为止,很少有浏览器能够被调用内核API,而Web browser 提供了IE的内核内容,就是我们可以用Ie提供的内核来自己设计一个简单的浏览器  当然,我们这儿并不是扯这个蛋。 但是为了后面说起来比较合理些 ,就只能翻山越岭的开始介绍了!

首先创建一个dlg,然后点击Acx control ,如果看见了mscro(简称) Web browser ,就双击两下,如果没看见,那就再去看看,很定是可以看得见的! 这些搞定之后,你就会看到下面这个黑乎乎的东西: 

  因为,前面说了这个界面不是分享到重点,所以就轻微的飘过。之后将这个dlg写成下面这般模样!!!

WebMFCDlg.h : 头文件

 1 // WebMFCDlg.h : 头文件
 2 //
 3 
 4 #pragma once
 5 #include "explorer1.h"
 6 
 7 
 8 // CWebMFCDlg 对话框
 9 class CWebMFCDlg : public CDialogEx
10 {
11 // 构造
12     DECLARE_DYNAMIC(CWebMFCDlg)
13 public:
14     CWebMFCDlg(CWnd* pParent = NULL);    // 标准构造函数
15 
16 // 对话框数据
17     enum { IDD = IDD_WEBMFC_DIALOG };
18 
19     protected:
20     virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV 支持
21 
22 
23 // 实现
24 protected:
25     HICON m_hIcon;
26 
27     // 生成的消息映射函数
28     virtual BOOL OnInitDialog();
29     afx_msg void OnSysCommand(UINT nID, LPARAM lParam);
30     afx_msg void OnPaint();
31     afx_msg HCURSOR OnQueryDragIcon();
32     DECLARE_MESSAGE_MAP()
33 public:
34     CExplorer1 m_explo;
35     afx_msg void OnBnClickedOk();
36     DECLARE_EVENTSINK_MAP()
37     void OnNewwindow3Explorer1(LPDISPATCH* ppDisp, BOOL* Cancel, unsigned long dwFlags, LPCTSTR bstrUrlContext, LPCTSTR bstrUrl);
38 
39 };

WebMFCDlg.cpp: 头文件

  1 // WebMFCDlg.cpp : 实现文件
  2 //
  3 
  4 #include "stdafx.h"
  5 #include "WebMFC.h"
  6 #include "WebMFCDlg.h"
  7 #include "afxdialogex.h"
  8 #include <MsHTML.h>
  9 #ifdef _DEBUG
 10 #define new DEBUG_NEW
 11 #endif
 12 
 13 
 14 // 用于应用程序“关于”菜单项的 CAboutDlg 对话框
 15 
 16 
 17 class CAboutDlg : public CDialogEx
 18 {
 19 public:
 20     CAboutDlg();
 21 
 22 // 对话框数据
 23     enum { IDD = IDD_ABOUTBOX };
 24 
 25     protected:
 26     virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV 支持
 27 
 28 // 实现
 29 protected:
 30     DECLARE_MESSAGE_MAP()
 31 };
 32 
 33 CAboutDlg::CAboutDlg() : CDialogEx(CAboutDlg::IDD)
 34 {
 35 }
 36 
 37 void CAboutDlg::DoDataExchange(CDataExchange* pDX)
 38 {
 39     CDialogEx::DoDataExchange(pDX);
 40 }
 41 
 42 BEGIN_MESSAGE_MAP(CAboutDlg, CDialogEx)
 43 END_MESSAGE_MAP()
 44 
 45 
 46 // CWebMFCDlg 对话框
 47 
 48 IMPLEMENT_DYNAMIC(CWebMFCDlg, CDialogEx)
 49 
 50 CWebMFCDlg::CWebMFCDlg(CWnd* pParent /*=NULL*/)
 51     : CDialogEx(CWebMFCDlg::IDD, pParent)
 52 {
 53     m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
 54 }
 55 
 56 void CWebMFCDlg::DoDataExchange(CDataExchange* pDX)
 57 {
 58     CDialogEx::DoDataExchange(pDX);
 59     DDX_Control(pDX, IDC_EXPLORER1, m_explo);
 60 }
 61 
 62 BEGIN_MESSAGE_MAP(CWebMFCDlg, CDialogEx)
 63     ON_WM_SYSCOMMAND()
 64     ON_WM_PAINT()
 65     ON_WM_QUERYDRAGICON()
 66     ON_BN_CLICKED(IDOK, &CWebMFCDlg::OnBnClickedOk)
 67 END_MESSAGE_MAP()
 68 
 69 
 70 // CWebMFCDlg 消息处理程序
 71 
 72 BOOL CWebMFCDlg::OnInitDialog()
 73 {
 74     CDialogEx::OnInitDialog();
 75 
 76     // 将“关于...”菜单项添加到系统菜单中。
 77 
 78     // IDM_ABOUTBOX 必须在系统命令范围内。
 79     ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
 80     ASSERT(IDM_ABOUTBOX < 0xF000);
 81 
 82     CMenu* pSysMenu = GetSystemMenu(FALSE);
 83     if (pSysMenu != NULL)
 84     {
 85         BOOL bNameValid;
 86         CString strAboutMenu;
 87         bNameValid = strAboutMenu.LoadString(IDS_ABOUTBOX);
 88         ASSERT(bNameValid);
 89         if (!strAboutMenu.IsEmpty())
 90         {
 91             pSysMenu->AppendMenu(MF_SEPARATOR);
 92             pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
 93         }
 94     }
 95 
 96     // 设置此对话框的图标。  当应用程序主窗口不是对话框时,框架将自动
 97     //  执行此操作
 98     SetIcon(m_hIcon, TRUE);            // 设置大图标
 99     SetIcon(m_hIcon, FALSE);        // 设置小图标
100 
101     // TODO:  在此添加额外的初始化代码
102     //com组件的变量
103     
104     CComVariant vtUrl("http://hust.myubbs.com/forum.php?mod=forumdisplay&fid=11");
105     CComVariant vtEmpty;  //NULL
106      m_explo.Navigate2(&vtUrl, &vtEmpty, &vtEmpty, &vtEmpty, &vtEmpty);//打开指定的网页  
107      m_explo.put_Silent(VARIANT_TRUE); //禁止脚本错误提示
108      return TRUE;  // 除非将焦点设置到控件,否则返回 TRUE
109 }
110 
111 void CWebMFCDlg::OnSysCommand(UINT nID, LPARAM lParam)
112 {
113     if ((nID & 0xFFF0) == IDM_ABOUTBOX)
114     {
115         CAboutDlg dlgAbout;
116         dlgAbout.DoModal();
117     }
118     else
119     {
120         CDialogEx::OnSysCommand(nID, lParam);
121     }
122 }
123 
124 // 如果向对话框添加最小化按钮,则需要下面的代码
125 //  来绘制该图标。  对于使用文档/视图模型的 MFC 应用程序,
126 //  这将由框架自动完成。
127 
128 void CWebMFCDlg::OnPaint()
129 {
130     if (IsIconic())
131     {
132         CPaintDC dc(this); // 用于绘制的设备上下文
133 
134         SendMessage(WM_ICONERASEBKGND, reinterpret_cast<WPARAM>(dc.GetSafeHdc()), 0);
135 
136         // 使图标在工作区矩形中居中
137         int cxIcon = GetSystemMetrics(SM_CXICON);
138         int cyIcon = GetSystemMetrics(SM_CYICON);
139         CRect rect;
140         GetClientRect(&rect);
141         int x = (rect.Width() - cxIcon + 1) / 2;
142         int y = (rect.Height() - cyIcon + 1) / 2;
143 
144         // 绘制图标
145         dc.DrawIcon(x, y, m_hIcon);
146     }
147     else
148     {
149         CDialogEx::OnPaint();
150     }
151 }
152 
153 //当用户拖动最小化窗口时系统调用此函数取得光标
154 //显示。
155 HCURSOR CWebMFCDlg::OnQueryDragIcon()
156 {
157     return static_cast<HCURSOR>(m_hIcon);
158 }
159 
160 BEGIN_EVENTSINK_MAP(CWebMFCDlg, CDialogEx)
161     ON_EVENT(CWebMFCDlg, IDC_EXPLORER1, 273, CWebMFCDlg::OnNewwindow3Explorer1, VTS_PDISPATCH VTS_PBOOL VTS_UI4 VTS_BSTR VTS_BSTR)
162 END_EVENTSINK_MAP()
163 
164 //放置调用IE
165 void CWebMFCDlg::OnNewwindow3Explorer1(LPDISPATCH* ppDisp, BOOL* Cancel, unsigned long dwFlags, LPCTSTR bstrUrlContext, LPCTSTR bstrUrl)
166 {
167     // TODO: Add your message handler code here
168     // TODO:  在此处添加消息处理程序代码
169 
170     //  只在一个对话框中操作网页
171     *Cancel = TRUE;
172     CComVariant strUrl;
173     strUrl = bstrUrl;
174     CComVariant vInfo;
175     this->m_explo.Navigate2(&strUrl, &vInfo, &vInfo, &vInfo, &vInfo);
176     this->ShowWindow(SW_SHOW);
177 }
178 void CWebMFCDlg::OnBnClickedOk()
179 {
180     //开始不断的注入数据,哇哈哈哈,好开心!
181     while (1){
182 
183         CComPtr < IDispatch > spDispDoc;  //从com组件中分离
184         spDispDoc = m_explo.get_Document();  //得到文档
185         CComQIPtr< IHTMLDocument2 > spDocument2 = spDispDoc;  //将其转化为document页面 
186         CComQIPtr< IHTMLElementCollection > spElementCollection;  //声明一个页面容器
187         if (SUCCEEDED(spDocument2->get_all(&spElementCollection)))   //如果得到页面容器成功
188         {
189             CComPtr<IDispatch> spDisp1, spDisp2, spDisp;    //com中封住的抽象的对象
190             HRESULT hr1, hr2,hr;
191             //取一个标题
192             hr1 = spElementCollection->item(CComVariant("subject"), CComVariant("0"), &spDisp1);  //将热键获取赋予对象
193             //
194             hr2 = spElementCollection->item(CComVariant("message"), CComVariant("0"), &spDisp2);
195             
196             hr = spElementCollection->item(CComVariant("topicsubmit"), CComVariant("0"), &spDisp);
197             if (SUCCEEDED(hr1) && SUCCEEDED(hr2)){
198                 CComQIPtr<IHTMLInputElement>  spElem1 = spDisp1;  //装换为元素
199                 CComQIPtr<IHTMLInputElement>  spElem2 = spDisp2;
200                 spElem1->put_value(CComBSTR("it's a test!"));  //注入内容
201                 
202                 spElem2->put_value(CComBSTR("这是一份来自电脑的重复输入,测试!it's a test !"));
203                 if (SUCCEEDED(hr)){
204                  CComQIPtr<IHTMLFormElement>  spForm = spDisp;
205                  spForm->submit();
206                 }
207             }
208         }
209         m_explo.GoBack();
210     }
211     // TODO:  在此添加控件通知处理程序代码
212     //CDialogEx::OnOK();
213 }

下面说说如何去涮别人家的屏, 对于要刷别银家的屏,首先你得有个不错的浏览器。怎么才能说不错的浏览器呢?   第一滴: 你得始终不依靠别人家的浏览器。也就是说,无论点击啥网页,你都只能子在自己的浏览器里去跳转,A网站调到B页面,为啥? 因为我们不能让cookie莫名的中断了! 就如你登录再本地浏览器,出去跑了一圈回来,信息难免会损失。 第二点:不要出现脚本错误,你不能访问一个页面,然后就抬出N多这样的脚本错误!

   一般的话都需要加上这句话在你的OnInitDialog()中;

1 m_explo.put_Silent(VARIANT_TRUE); //禁止脚本错误提示

然后要想一直留在自己的浏览器中: 首先得加上一个事件响应函数

在对话框.cpp中,需要实现

1 // CWebMFCDlg 对话框
2 
3 IMPLEMENT_DYNAMIC(CWebMFCDlg, CDialogEx)  //需要补充这句
4 
5 CWebMFCDlg::CWebMFCDlg(CWnd* pParent /*=NULL*/)
6     : CDialogEx(CWebMFCDlg::IDD, pParent)
7 {
8     m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
9 }

并且:

 还需要不上这些

 1 BEGIN_EVENTSINK_MAP(CWebMFCDlg, CDialogEx)
 2     ON_EVENT(CWebMFCDlg, IDC_EXPLORER1, 273, CWebMFCDlg::OnNewwindow3Explorer1, VTS_PDISPATCH VTS_PBOOL VTS_UI4 VTS_BSTR VTS_BSTR)
 3 END_EVENTSINK_MAP()
 4 
 5 //放置调用IE
 6 void CWebMFCDlg::OnNewwindow3Explorer1(LPDISPATCH* ppDisp, BOOL* Cancel, unsigned long dwFlags, LPCTSTR bstrUrlContext, LPCTSTR bstrUrl)
 7 {
 8     // TODO: Add your message handler code here
 9     // TODO:  在此处添加消息处理程序代码
10 
11     //  只在一个对话框中操作网页
12     *Cancel = TRUE;
13     CComVariant strUrl;
14     strUrl = bstrUrl;
15     CComVariant vInfo;
16     this->m_explo.Navigate2(&strUrl, &vInfo, &vInfo, &vInfo, &vInfo);
17     this->ShowWindow(SW_SHOW);
18 }

在对话框.h中:

1 // CWebMFCDlg 对话框
2 class CWebMFCDlg : public CDialogEx
3 {
4 // 构造
5     DECLARE_DYNAMIC(CWebMFCDlg)   //需要添加上这句
6 public:
7     CWebMFCDlg(CWnd* pParent = NULL);    // 标准构造函数

并且:

1 public:
2     CExplorer1 m_explo;
3     afx_msg void OnBnClickedOk();
4     DECLARE_EVENTSINK_MAP()  //补充这句
5     void OnNewwindow3Explorer1(LPDISPATCH* ppDisp, BOOL* Cancel, unsigned long dwFlags, LPCTSTR bstrUrlContext, LPCTSTR bstrUrl); //和这句

实现了这些,然后只需要在对话框初始化函数中 添加如下:

1 CComVariant vtUrl("http://tieba.baidu.com/f?kw=%BA%FE%B1%B1%B9%A4%D2%B5%B4%F3%D1%A7&fr=ala0&tpl=5");
2     CComVariant vtEmpty;  //NULL
3      m_explo.Navigate2(&vtUrl, &vtEmpty, &vtEmpty, &vtEmpty, &vtEmpty);//打开指定的网页 

然后运行就可以去看到这个了:

当然扯了这么多,并没什么鸟用。不过铺垫讲完了,到重点了? 如何才能将我们事先写好的数据,输入到html页面去呢?   而且还是用c++

恩! 这个问题,首先分析,用主流的五大浏览器,是很定搞不定的! 因为我们并不能去调用tm的API,所以我们只能想前面鲁的一大串一样! 去自己写一个浏览器

然后来实现这些调用IE公用的内核API!!!!

   那么如何调用呢? 我们再来看看这图片:

这是浏览器原理里面的一部分内容! 偷偷的盗了一张好图,这里道声谢!

我们要将Ccomvarite 转化为document,然后在转化出HTMLHtmlElement元素即可!!!

首先我们需要引入: 头文件 #include<MsHTML.h>

 1         CComPtr < IDispatch > sDDc;  //从com组件中分离
 2         sDDc = m_explo.get_Document();  //得到文档
 3         CComQIPtr< IHTMLDocument2 > sDoc= sDDc;  //将其转化为document页面 
 4         CComQIPtr< IHTMLElementCollection > spECn;  //声明一个页面容器
 5         if (SUCCEEDED(sDoc->get_all(&spECn)))   //如果得到页面容器成功
 6         {
 7             CComPtr<IDispatch> spD1, spD2, spD;    //com中封住的抽象的对象
 8             HRESULT hr1, hr2,hr;
 9             //取一个标题
10             hr1 = spECn->item(CComVariant("subject"), CComVariant("0"), &spD1);  //将热键获取赋予对象
11             //
12             hr2 = spECn->item(CComVariant("message"), CComVariant("0"), &spD2);
13             
14             hr = spECn->item(CComVariant("topicsubmit"), CComVariant("0"), &spD);
15             if (SUCCEEDED(hr1) && SUCCEEDED(hr2)){
16                 CComQIPtr<IHTMLInputElement>  spElem1 = spD1;  //装换为元素
17                 CComQIPtr<IHTMLInputElement>  spElem2 = spD2;
18                 spElem1->put_value(CComBSTR("it's a test!"));  //注入内容
19                 
20                 spElem2->put_value(CComBSTR("这是一份来自电脑的重复输入,测试!it's a test !"));
21                 if (SUCCEEDED(hr)){
22                  CComQIPtr<IHTMLFormElement>  spForm = spD;
23                  spForm->submit();
24                 }
25             }
26         }

对于上面的这部分代码: 包含了数据的填写和提交,请结合上面的这张图,来理解!!!!

  效果:

然后拉倒华科的考研论坛区测试了下:

第一个框中自动填充成功,但是第二,由于对方用js,写了预防注入的程序代码,就是必须输入前鼠标点击一下,不然输入不进去。所以这样单纯的填充,对于这种设置还是比较棘手!!! 当然如果c++,这边调用js来搞的话! 也许也未可知!

以后有时间再来做这方面的 探讨吧!!   希望这些分享,能带给大家一点点的帮助!!

 ---------------------------------------分割线-----------------------------

这篇文章过去太久了,久得连MFC已经没落的不成样子,隔了这么久,贴一下剩余的几个功能代码.

 补充: 如何使用MFC调用JS来模拟鼠标点击网页

这里只是针对C++,ATL编写客户端时,调用微软API时常用的问题的解决方案:

1. 使用com组件调用js来模内点击网页按钮,避免使用复杂的dom树:

比如有这么一段html页面:

<input type="submit" id="su" value="百度一下" class="bg s_btn">

也就是百度首页:

首先在截图:

在console中输入:

document.getElementById("su").click()

会看到这:截图:

这说明这个js是生效的,然后我们再使用com组件调用这条js代码即可:

 1 std::string strScript ="document.getElementById("su").click()";
 2     // 获取 IHTMLDocument2 接口
 3     IHTMLDocument2 *spDoc = NULL;
 4     if (!webclient.get_Busy() && webclient.get_Document() != NULL)
 5         webclient.get_Document()->QueryInterface(
 6         ::IID_IHTMLDocument2, reinterpret_cast<void **>(&spDoc));
 7     else
 8     {
 9         ::MessageBox(this->GetSafeHwnd(),L"IHTMLDocument2 接口获取失败",
10             L"Error", MB_OK | MB_ICONERROR);
11         return;
12     }
13 
14     bool bSucceed(false);
15     if (spDoc)
16     {
17         // 获取 IHTMLWindow2 接口
18         IHTMLWindow2 *spWin;
19         VARIANT vRet;
20         HRESULT hr=spDoc->get_parentWindow(&spWin);
21         if (spWin)
22         {
23             CComBSTR bstrjs = (strScript.c_str());  
24             CComBSTR bstrlan = SysAllocString(L"javascript");  
25             long lRet = spWin->execScript(bstrjs, bstrlan, &vRet);
26             bSucceed = lRet == 0;
27             spWin->Release();
28         }
29         spDoc->Release();
30     }

第二个问题,那就是发帖子需要登陆,然后你还要获取到网站cookie才可以,所以下面我又补上获取cookie的代码.

2. 如何得到webbrower中的cookie值:

 1 HRESULT hr;  
 2     IDispatch* lpDispatch;  
 3     lpDispatch = webclient.GetDocument();  
 4     IHTMLDocument2* lpDocument2;  
 5     hr = lpDispatch->QueryInterface(IID_IHTMLDocument2, (PVOID*)&lpDocument2);  
 6     if ( hr == S_OK )  
 7     {  
 8         BSTR bstrCookie;
 9         hr = lpDocument2->get_cookie(&bstrCookie);  
10         if ( hr == S_OK )  
11         {  
12             webCookie(bstrCookie); 
13         }  
14         lpDocument2->put_cookie(NULL);  
15         pBody->Release();  
16         lpDocument2->Release();  
17     }  
18     lpDispatch->Release();  

  至此,你就可以大胆的去制作刷广告机啦~~