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

时间:2023-03-10 01:17:51
C/C++ 如何来自动优雅的涮别银家的贴子

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

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

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

C/C++ 如何来自动优雅的涮别银家的贴子  因为,前面说了这个界面不是分享到重点,所以就轻微的飘过。之后将这个dlg写成下面这般模样!!!

WebMFCDlg.h : 头文件

 // WebMFCDlg.h : 头文件
// #pragma once
#include "explorer1.h" // CWebMFCDlg 对话框
class CWebMFCDlg : public CDialogEx
{
// 构造
DECLARE_DYNAMIC(CWebMFCDlg)
public:
CWebMFCDlg(CWnd* pParent = NULL); // 标准构造函数 // 对话框数据
enum { IDD = IDD_WEBMFC_DIALOG }; protected:
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV 支持 // 实现
protected:
HICON m_hIcon; // 生成的消息映射函数
virtual BOOL OnInitDialog();
afx_msg void OnSysCommand(UINT nID, LPARAM lParam);
afx_msg void OnPaint();
afx_msg HCURSOR OnQueryDragIcon();
DECLARE_MESSAGE_MAP()
public:
CExplorer1 m_explo;
afx_msg void OnBnClickedOk();
DECLARE_EVENTSINK_MAP()
void OnNewwindow3Explorer1(LPDISPATCH* ppDisp, BOOL* Cancel, unsigned long dwFlags, LPCTSTR bstrUrlContext, LPCTSTR bstrUrl); };

WebMFCDlg.cpp: 头文件

 // WebMFCDlg.cpp : 实现文件
// #include "stdafx.h"
#include "WebMFC.h"
#include "WebMFCDlg.h"
#include "afxdialogex.h"
#include <MsHTML.h>
#ifdef _DEBUG
#define new DEBUG_NEW
#endif // 用于应用程序“关于”菜单项的 CAboutDlg 对话框 class CAboutDlg : public CDialogEx
{
public:
CAboutDlg(); // 对话框数据
enum { IDD = IDD_ABOUTBOX }; protected:
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV 支持 // 实现
protected:
DECLARE_MESSAGE_MAP()
}; CAboutDlg::CAboutDlg() : CDialogEx(CAboutDlg::IDD)
{
} void CAboutDlg::DoDataExchange(CDataExchange* pDX)
{
CDialogEx::DoDataExchange(pDX);
} BEGIN_MESSAGE_MAP(CAboutDlg, CDialogEx)
END_MESSAGE_MAP() // CWebMFCDlg 对话框 IMPLEMENT_DYNAMIC(CWebMFCDlg, CDialogEx) CWebMFCDlg::CWebMFCDlg(CWnd* pParent /*=NULL*/)
: CDialogEx(CWebMFCDlg::IDD, pParent)
{
m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
} void CWebMFCDlg::DoDataExchange(CDataExchange* pDX)
{
CDialogEx::DoDataExchange(pDX);
DDX_Control(pDX, IDC_EXPLORER1, m_explo);
} BEGIN_MESSAGE_MAP(CWebMFCDlg, CDialogEx)
ON_WM_SYSCOMMAND()
ON_WM_PAINT()
ON_WM_QUERYDRAGICON()
ON_BN_CLICKED(IDOK, &CWebMFCDlg::OnBnClickedOk)
END_MESSAGE_MAP() // CWebMFCDlg 消息处理程序 BOOL CWebMFCDlg::OnInitDialog()
{
CDialogEx::OnInitDialog(); // 将“关于...”菜单项添加到系统菜单中。 // IDM_ABOUTBOX 必须在系统命令范围内。
ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
ASSERT(IDM_ABOUTBOX < 0xF000); CMenu* pSysMenu = GetSystemMenu(FALSE);
if (pSysMenu != NULL)
{
BOOL bNameValid;
CString strAboutMenu;
bNameValid = strAboutMenu.LoadString(IDS_ABOUTBOX);
ASSERT(bNameValid);
if (!strAboutMenu.IsEmpty())
{
pSysMenu->AppendMenu(MF_SEPARATOR);
pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
}
} // 设置此对话框的图标。 当应用程序主窗口不是对话框时,框架将自动
// 执行此操作
SetIcon(m_hIcon, TRUE); // 设置大图标
SetIcon(m_hIcon, FALSE); // 设置小图标 // TODO: 在此添加额外的初始化代码
//com组件的变量 CComVariant vtUrl("http://hust.myubbs.com/forum.php?mod=forumdisplay&fid=11");
CComVariant vtEmpty; //NULL
m_explo.Navigate2(&vtUrl, &vtEmpty, &vtEmpty, &vtEmpty, &vtEmpty);//打开指定的网页
m_explo.put_Silent(VARIANT_TRUE); //禁止脚本错误提示
return TRUE; // 除非将焦点设置到控件,否则返回 TRUE
} void CWebMFCDlg::OnSysCommand(UINT nID, LPARAM lParam)
{
if ((nID & 0xFFF0) == IDM_ABOUTBOX)
{
CAboutDlg dlgAbout;
dlgAbout.DoModal();
}
else
{
CDialogEx::OnSysCommand(nID, lParam);
}
} // 如果向对话框添加最小化按钮,则需要下面的代码
// 来绘制该图标。 对于使用文档/视图模型的 MFC 应用程序,
// 这将由框架自动完成。 void CWebMFCDlg::OnPaint()
{
if (IsIconic())
{
CPaintDC dc(this); // 用于绘制的设备上下文 SendMessage(WM_ICONERASEBKGND, reinterpret_cast<WPARAM>(dc.GetSafeHdc()), ); // 使图标在工作区矩形中居中
int cxIcon = GetSystemMetrics(SM_CXICON);
int cyIcon = GetSystemMetrics(SM_CYICON);
CRect rect;
GetClientRect(&rect);
int x = (rect.Width() - cxIcon + ) / ;
int y = (rect.Height() - cyIcon + ) / ; // 绘制图标
dc.DrawIcon(x, y, m_hIcon);
}
else
{
CDialogEx::OnPaint();
}
} //当用户拖动最小化窗口时系统调用此函数取得光标
//显示。
HCURSOR CWebMFCDlg::OnQueryDragIcon()
{
return static_cast<HCURSOR>(m_hIcon);
} BEGIN_EVENTSINK_MAP(CWebMFCDlg, CDialogEx)
ON_EVENT(CWebMFCDlg, IDC_EXPLORER1, , CWebMFCDlg::OnNewwindow3Explorer1, VTS_PDISPATCH VTS_PBOOL VTS_UI4 VTS_BSTR VTS_BSTR)
END_EVENTSINK_MAP() //放置调用IE
void CWebMFCDlg::OnNewwindow3Explorer1(LPDISPATCH* ppDisp, BOOL* Cancel, unsigned long dwFlags, LPCTSTR bstrUrlContext, LPCTSTR bstrUrl)
{
// TODO: Add your message handler code here
// TODO: 在此处添加消息处理程序代码 // 只在一个对话框中操作网页
*Cancel = TRUE;
CComVariant strUrl;
strUrl = bstrUrl;
CComVariant vInfo;
this->m_explo.Navigate2(&strUrl, &vInfo, &vInfo, &vInfo, &vInfo);
this->ShowWindow(SW_SHOW);
}
void CWebMFCDlg::OnBnClickedOk()
{
//开始不断的注入数据,哇哈哈哈,好开心!
while (){ CComPtr < IDispatch > spDispDoc; //从com组件中分离
spDispDoc = m_explo.get_Document(); //得到文档
CComQIPtr< IHTMLDocument2 > spDocument2 = spDispDoc; //将其转化为document页面
CComQIPtr< IHTMLElementCollection > spElementCollection; //声明一个页面容器
if (SUCCEEDED(spDocument2->get_all(&spElementCollection))) //如果得到页面容器成功
{
CComPtr<IDispatch> spDisp1, spDisp2, spDisp; //com中封住的抽象的对象
HRESULT hr1, hr2,hr;
//取一个标题
hr1 = spElementCollection->item(CComVariant("subject"), CComVariant(""), &spDisp1); //将热键获取赋予对象
//
hr2 = spElementCollection->item(CComVariant("message"), CComVariant(""), &spDisp2); hr = spElementCollection->item(CComVariant("topicsubmit"), CComVariant(""), &spDisp);
if (SUCCEEDED(hr1) && SUCCEEDED(hr2)){
CComQIPtr<IHTMLInputElement> spElem1 = spDisp1; //装换为元素
CComQIPtr<IHTMLInputElement> spElem2 = spDisp2;
spElem1->put_value(CComBSTR("it's a test!")); //注入内容 spElem2->put_value(CComBSTR("这是一份来自电脑的重复输入,测试!it's a test !"));
if (SUCCEEDED(hr)){
CComQIPtr<IHTMLFormElement> spForm = spDisp;
spForm->submit();
}
}
}
m_explo.GoBack();
}
// TODO: 在此添加控件通知处理程序代码
//CDialogEx::OnOK();
}

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

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

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

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

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

 // CWebMFCDlg 对话框

 IMPLEMENT_DYNAMIC(CWebMFCDlg, CDialogEx)  //需要补充这句

 CWebMFCDlg::CWebMFCDlg(CWnd* pParent /*=NULL*/)
: CDialogEx(CWebMFCDlg::IDD, pParent)
{
m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
}

并且:

还需要不上这些

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

在对话框.h中:

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

并且:

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

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

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

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

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

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

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

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

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

C/C++ 如何来自动优雅的涮别银家的贴子这是浏览器原理里面的一部分内容! 偷偷的盗了一张好图,这里道声谢!

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

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

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

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

效果:

C/C++ 如何来自动优雅的涮别银家的贴子然后拉倒华科的考研论坛区测试了下:C/C++ 如何来自动优雅的涮别银家的贴子第一个框中自动填充成功,但是第二,由于对方用js,写了预防注入的程序代码,就是必须输入前鼠标点击一下,不然输入不进去。所以这样单纯的填充,对于这种设置还是比较棘手!!! 当然如果c++,这边调用js来搞的话! 也许也未可知!

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

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

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

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

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

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

比如有这么一段html页面:

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

也就是百度首页:

首先在截图:

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

在console中输入:

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

会看到这:截图:

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

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

C/C++ 如何来自动优雅的涮别银家的贴子
 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 }
C/C++ 如何来自动优雅的涮别银家的贴子

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

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

C/C++ 如何来自动优雅的涮别银家的贴子
 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();
C/C++ 如何来自动优雅的涮别银家的贴子

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