蛙蛙推荐:蛙蛙牌网页捕捉器

摘要:你有没有看到一篇好文章想保存到本地,有没有想过只保存网页选中的部分而不要那些不必要的导航和广告,本贴告诉你达到这个目的的思路及主要代码。

思路:首先我们要获取到所有IE窗口,无论是哪个IE进程的,这个我们要用引用"Microsoft Internet Controls(SHDocVw)"的com组件,用它的SHDocVw.ShellWindowsClass类来枚举用户打开的所有的IE页面。然后我们要用GetForegroundWindow API来获取前置的窗口,再用GetClassName API来获取前置窗口的Class,如果是“IEFrame”,说明当前窗口是IE,然后枚举所有的IE页面,对比每个IE页面的句柄是否是当前活动窗口的句柄,如果是,那么这个SHDocVw.InternetExplorer就是对应这当前处于活动窗口的IE的对象。为了方便操作HTML模型和IE对象,我们再引入Microsoft.mshtml程序集(这个是.NET程序集,前面那个SHDocVw是个Com互操作程序集,不过应该每台机器都装了IE,所以SHDocVw不需要单独分发)。SHDocVw.InternetExplorer.Document可以转换成mshtml.IHTMLDocument2类型,然后mshtml.IHTMLDocument2.body有innerHTML属性,就是当前网页的HTML文本了。mshtml.IHTMLDocument2.selection.createRange()表示用户在网页上选中的区域,这个做web的应该很熟,该方法返回mshtml.IHTMLTxtRange类型,该类型有htmlText属性,表示用户所选区域的html文本。
这样所有必要的因素都有了,把这些综合在一起,就可以写个工具来快速保存你感兴趣的网页了。

另外本文还演示如下技巧:
1、如何实现无标题窗口,如果拖动无标题窗口,如何让窗口永远处于前置状态;
2、如何解决前置窗口上的按钮要点击两次才能生效的问题,第一次点击是激活窗口,第二次单击按钮才会生效;
3、让窗体初始化在屏幕的右下角;

主要代码如下,不长

using System;
using System.Diagnostics;
using System.Drawing;
using System.Runtime.InteropServices;
using System.Text;
using System.Windows.Forms;
using mshtml;
using SHDocVw;

namespace CapIe
{
    public partial class Form1 : Form
    {
        private fields#region private fields

        窗口相关#region 窗口相关

        [DllImport("user32.dll")]
        private static extern int GetClassName(
            IntPtr hWnd,
            StringBuilder lpString,
            int nMaxCount
            );

        [DllImport("user32.dll")]
        private static extern IntPtr GetForegroundWindow();

        #endregion

        拖动无标题窗口相关#region 拖动无标题窗口相关

        public const int HTCAPTION = 0x0002;
        public const int SC_MOVE = 0xF010;
        public const int WM_SYSCOMMAND = 0x0112;

        [DllImport("user32.dll")]
        public static extern bool ReleaseCapture();

        [DllImport("user32.dll")]
        public static extern bool SendMessage(IntPtr hwnd, int wMsg, int wParam, int lParam);

        #endregion

        private readonly Timer _timer = new Timer();
        private IHTMLDocument2 _doc;

        #endregion

        Form 相关#region Form 相关

        public Form1()
        {
            InitializeComponent();
            TopMost = true;
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            _timer.Enabled = true;
            _timer.Tick += _timer_Tick;
            Location = new Point(Screen.PrimaryScreen.WorkingArea.Width - base.Width,
                                 Screen.PrimaryScreen.WorkingArea.Height - Height); //让窗体初始化在屏幕的右下角
        }

        #endregion

        网页捕捉相关#region 网页捕捉相关

        //监控当前窗口是否为IE
        private void _timer_Tick(object sender, EventArgs e)
        {
            try
            {
                IntPtr formHandle = GetForegroundWindow();
                if (formHandle == Handle) return;
                StringBuilder className = new StringBuilder(256);
                GetClassName(formHandle, className, className.Capacity);
                if (className.ToString() != "IEFrame")
                {
                    toolStripButton1.Enabled = false;
                    toolStripButton2.Enabled = false;
                    return;
                }
                else
                {
                    toolStripButton1.Enabled = true;
                    toolStripButton2.Enabled = true;
                }


                ShellWindows shell = new ShellWindowsClass();
                int ihandle = formHandle.ToInt32();
                foreach (InternetExplorer ie in shell)
                {
                    int iehandle;
                    try
                    {
                        iehandle = ie.HWND;
                    }
                    catch
                    {
                        continue;
                    }
                    if (ihandle != iehandle) continue;
                    try
                    {
                        _doc = ie.Document as IHTMLDocument2;
                    }
                    catch
                    {
                        continue;
                    }
                }
            }
            catch (Exception ex)
            {
                Trace.TraceError(ex.Message);
                Debugger.Break();
            }
        }

        //捕获全部网页
        private void toolStripButton1_Click(object sender, EventArgs e)
        {
            if (_doc == null) return;
            ShowWeb showWeb = new ShowWeb(_doc.body.innerHTML);
            showWeb.ShowDialog(this);
        }


        //捕获选取的网页
        private void toolStripButton2_Click(object sender, EventArgs e)
        {
            if (_doc == null) return;
            IHTMLTxtRange range = _doc.selection.createRange() as IHTMLTxtRange;
            if (range == null) return;
            ShowWeb showWeb = new ShowWeb(range.htmlText);
            showWeb.ShowDialog(this);
        }

        #endregion

        窗体拖动相关#region 窗体拖动相关

        private void panel1_MouseDown(object sender, MouseEventArgs e)
        {
            ReleaseCapture();
            SendMessage(Handle, WM_SYSCOMMAND, SC_MOVE + HTCAPTION, 0);
        }

        private void panel1_MouseHover(object sender, EventArgs e)
        {
            Cursor = Cursors.SizeAll;
        }

        private void panel1_MouseLeave(object sender, EventArgs e)
        {
            Cursor = Cursors.Default;
        }

        #endregion

        下拉菜单处理#region 下拉菜单处理

        private void 退出ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            Application.Exit();
        }

        #endregion

        private void toolStrip1_MouseHover(object sender, EventArgs e)
        {
            Focus(); //解决按钮要点击两次的bug
        }
    }
}

改进:目前只能当IE为活动窗口时,才能捕捉网页,我们可以先获取鼠标位置,然后用WindowFromPoint获取鼠标所在区域的窗口,再获取这个窗口的Class,看是否是“Internet Explorer_Server”,然后下面的步骤和上面的一样,这样的做的好处是一些IE内核的浏览器,比如傲游啦,GreenBrowser等浏览器也能想办法捕捉网页,因为只要是IE内核,显示网页的那部分的的Window的Class都是"Internet Explorer_Server"。找到这个窗口后再调用GetParent获取上层的窗口,再和ShellWindows枚举出来的窗口句柄对比,找到当前打开的网页。

[DllImport("user32")]
private static extern IntPtr WindowFromPoint(
Point Point  //坐标
);
[DllImport("User32.dll")]
public static extern IntPtr GetParent(IntPtr hWnd);

int x = Cursor.Position.X;
int y = Cursor.Position.Y;
Point p = new Point(x, y);
IntPtr formHandle = WindowFromPoint(p);

另外,就是像IE7这种的多标签浏览器,获取当前窗口,还要获取当前激活的标签页是哪个,否则捕获的网页可能不对,这就需要再想办法了,留给大家吧,想实现的话具体大家参考相关链接吧。

点击下载示例(不包含Microsoft.mshtml.dll,应该在C:/Program Files/Microsoft.NET/Primary Interop Assemblies目录下) cap_ie.zip

相关链接:

SOS!!!如何获取鼠标再在的窗口的句柄
http://topic.csdn.net/t/20010612/14/156129.html

GetWindowRect,GetClientRect,和ScreenToClient
http://hi.baidu.com/yh121212/blog/item/521172c646b7211b9c163d3c.html

请教out参数的用法
http://topic.csdn.net/t/20050304/12/3824234.html

从C#程序中调用非受管DLLs [择自博客园]
http://blog.csdn.net/ericksky/archive/2006/07/27/988128.aspx

GetCursorPos/WindowFromPoint/SendMessage (用API函数向Edit框发送字符)
http://hi.baidu.com/gamevip/blog/item/cd4ac8119cef2111b8127b35.html

如何连接到 Internet Explorer 的运行实例
http://support.microsoft.com/kb/176792
FileNotFoundException error using SHDocVw.ShellWindows
http://bytes.com/forum/thread656636.html

VB Webbrowser控件使用方法
http://www.zxbc.cn/html/20080216/31664_3.html

从HWnd得到IWebbrowser2接口
http://www.zxboy.com/article.asp?id=100

GetActiveWindow与GetForegroundWindow两者有何区别?
http://www.qqgb.com/Program/VC/VCJQ/Program_166012.html

MSHTML, Dom, and copying objects from a WebBrowser Control
http://lazycoders.blogspot.com/2007/06/mshtml-dom-and-copying-objects-from.html

我想找到当前IE(7)当前的文档对象,已有部分代码,请求大家帮忙!C#_WinFrom 
http://topic.csdn.net/u/20070404/20/17979fe9-a223-44dc-aab5-b8edb8fbffd0.html

Internet Explorer Activity Monitor
http://www.codeproject.com/KB/cs/IE_Activity_Monitor.aspx?fid=229256&df=90&mpp=25&noise=3&sort=Position&view=Quick&select=1350993

C#获得IE进程内的IDocument对象代码
http://blog.csdn.net/shiff/archive/2007/12/05/1919000.aspx

蛙蛙推荐:蛙蛙牌网页捕捉器相关推荐

  1. 蛙蛙推荐:蛙蛙牌软件注册码算法

    蛙蛙推荐:蛙蛙牌软件注册码算法 摘要:辛辛苦苦写个共享软件,又怕被人破解,所以就会想到用注册码的方式来激活软件.本蛙给大家一个简单的思路来实现软件注册码算法,当然.net做的东西很容易被人破解,反编译 ...

  2. 蛙蛙推荐:蛙蛙浏览器

    蛙蛙推荐:蛙蛙浏览器 摘要:google推出了自己的网页浏览器,现在web浏览器的竞争更激烈了,各有各的用户群.其实有另一个领域没有多少竞争,那就是应用程序浏览器,今天给大家演示的蛙蛙浏览器,不仅可以 ...

  3. 蛙蛙推荐:蛙蛙教你文本聚类 - 蛙蛙王子 - 博客园

    蛙蛙推荐:蛙蛙教你文本聚类 - 蛙蛙王子 - 博客园 蛙蛙推荐:蛙蛙教你文本聚类 - 蛙蛙王子 - 博客园 蛙蛙推荐:蛙蛙教你文本聚类 摘要:文本聚类是搜索引擎和语义web的基本技术,这次本蛙和大家一 ...

  4. 蛙蛙推荐:蛙蛙教你文本聚类

    蛙蛙推荐:蛙蛙教你文本聚类 摘要:文本聚类是搜索引擎和语义web的基本技术,这次本蛙和大家一起学习一下简单的文本聚类算法,可能不能直接用于实际应用中,但对于想学搜索技术的初学者还是有一定入门作用的.这 ...

  5. 网页转图片捕捉器 v1.0 官方

    Welcome to my blog! <script language="javascript" src="http://avss.b15.cnwg.cn/cou ...

  6. html静态网页制作的博客,[推荐]初学制作静态网页HTML推荐标准_

    [推荐]初学制作静态网页HTML推荐标准_ (2012-05-19 10:46:32) 标签: 网页 制作 杂谈 a双 定义一个链接name=text 本网页内目标名称(书签),可为数字或文本href ...

  7. 直播播放器+html5,10款html5网页播放器推荐(总有一款适合你)

    整理了5款html5网页播放器,总有一款适合你吧. 酷播云HTML5倍速功能视频播放器 介绍: 重要提示:本播放器为酷播云在线产品,用户可以免费注册使用,下载包仅提供代码使用示例及演示,并非播放器的下 ...

  8. 网吧做直播,制做网页播放器代码全集

    <script src="/script/ShowHidden.js" type="text/javascript"></script>

  9. jw player flash网页播放器 参数说明以及应用配置

    jw player flash网页播放器 参数说明以及应用配置 1.参数解释 这些参数可以配置被嵌入到html中的播放器的行为和外观.如果使用swfobject.js,可以用addVariable() ...

最新文章

  1. Virtual Machine--Vmware(2)
  2. mysql 存储过程 主键_存储过程生成主键
  3. android中播放gif动画之二
  4. librtmp实时消息传输协议(RTMP)库代码浅析
  5. SAP系统和微信集成的系列教程之十:如何在SAP C4C系统里直接回复消息给微信用户
  6. 数据结构与算法--B树原理及实现
  7. do还是doing imagine加to_Want后面竟然可以跟doing?!to do和doing有什么区别?
  8. NFT商城/NFT盲盒/虚拟盲盒/NFT交易/可定制二开
  9. 创建Oracle定时任务及其各项操作
  10. python 类的执行中保部存值_VisualFoxPro的报表文件.FRX中保存的是______。
  11. 全球与中国激光共焦扫描显微镜市场深度研究分析报告
  12. 西奥电梯服务器无响应,干货│西奥电梯故障分析和技术文件
  13. IP地址分类及对应范围
  14. python编程助手_用Python做一个久坐提醒小助手的示例代码
  15. C语言——计算某日是该年的第几天
  16. 【神经网络】FNN——前馈神经网络、前向传播、反向传播详解
  17. 使用java爬取国家统计局的12位行政区划代码
  18. cf_global_round7
  19. 被字句15个_小学语文必考知识:15类句式转换解题方法与练习(附答案)
  20. 人工智能-深度学习Tensorflow2.0-python

热门文章

  1. 郝斌c语言视频错误的在哪里,根据郝斌C语言视频学的解简单一元二次方程的代码总是敲错,求大神帮忙看看...
  2. eclipse怎样设置字体及推荐字体
  3. [教程] KGFMapSystem - 快速创建游戏中的迷你地图
  4. scp是什么,有什么用
  5. php微信退款aes,关于微信支付退款req_info字段解密问题
  6. 《月薪5千与月薪5万的文案区别》!如何用立体思维去解决问题
  7. 英文文献检索网站(转)
  8. 用python自动制作ppt第一讲——了解11种默认布局
  9. 112-RTKLIB中关于dcb文件读取的问题
  10. MySQL主从配置和gtid主从配置