有没有办法隐藏Chrome窗口并捕获屏幕截图或将Chrome窗口转换为图像?

时间:2013-07-01 00:09:26

标签: c#

我有这一行:

Process.Start("chrome.exe",
                "http://www.cnn.com");

它正在打开一个新的Chrome浏览器窗口。 我想做两件事:

  1. 将Chrome窗口转换/保存为图像。
  2. 隐藏此窗口。
  3. 这是我现在在新课程中尝试的代码:

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Runtime.InteropServices;
    using System.Diagnostics;
    using System.Drawing.Imaging;
    using System.Drawing;
    
    namespace GatherLinks
    {
        class WebSiteScreenShot
        {
            [DllImport("user32.dll")]
            private static extern bool ShowWindowAsync(IntPtr hWnd, int nCmdShow);
            [DllImport("user32.dll")]
            public static extern bool GetWindowRect(IntPtr hWnd, out RECT lpRect);
            [DllImport("user32.dll")]
            public static extern bool PrintWindow(IntPtr hWnd, IntPtr hdcBlt, int nFlags);
    
            public WebSiteScreenShot()
            {
    
            }
    
            public void WhateverMethod()
            {
                //initialize process and get hWnd
                Process putty = Process.Start("chrome.exe",
                    "http://www.cnn.com");
                putty.WaitForInputIdle();
                IntPtr winHandle = putty.MainWindowHandle;
    
                //print screen
                RECT rc;
                GetWindowRect(winHandle, out rc);
    
                Bitmap bmp = new Bitmap(rc.Width, rc.Height, PixelFormat.Format32bppArgb);
                Graphics gfxBmp = Graphics.FromImage(bmp);
                IntPtr hdcBitmap = gfxBmp.GetHdc();
    
                PrintWindow(winHandle, hdcBitmap, 0);
    
                gfxBmp.ReleaseHdc(hdcBitmap);
                gfxBmp.Dispose();
    
                bmp.Save("c:\\temp\\test.png", ImageFormat.Png);
    
                //hides window
                ShowWindowAsync(winHandle, 0);
            }
    
            [StructLayout(LayoutKind.Sequential)]
            public struct RECT
            {
                private int _Left;
                private int _Top;
                private int _Right;
                private int _Bottom;
    
                public RECT(RECT Rectangle)
                    : this(Rectangle.Left, Rectangle.Top, Rectangle.Right, Rectangle.Bottom)
                {
                }
                public RECT(int Left, int Top, int Right, int Bottom)
                {
                    _Left = Left;
                    _Top = Top;
                    _Right = Right;
                    _Bottom = Bottom;
                }
    
                public int X
                {
                    get { return _Left; }
                    set { _Left = value; }
                }
                public int Y
                {
                    get { return _Top; }
                    set { _Top = value; }
                }
                public int Left
                {
                    get { return _Left; }
                    set { _Left = value; }
                }
                public int Top
                {
                    get { return _Top; }
                    set { _Top = value; }
                }
                public int Right
                {
                    get { return _Right; }
                    set { _Right = value; }
                }
                public int Bottom
                {
                    get { return _Bottom; }
                    set { _Bottom = value; }
                }
                public int Height
                {
                    get { return _Bottom - _Top; }
                    set { _Bottom = value + _Top; }
                }
                public int Width
                {
                    get { return _Right - _Left; }
                    set { _Right = value + _Left; }
                }
                public Point Location
                {
                    get { return new Point(Left, Top); }
                    set
                    {
                        _Left = value.X;
                        _Top = value.Y;
                    }
                }
                public Size Size
                {
                    get { return new Size(Width, Height); }
                    set
                    {
                        _Right = value.Width + _Left;
                        _Bottom = value.Height + _Top;
                    }
                }
    
                public static implicit operator Rectangle(RECT Rectangle)
                {
                    return new Rectangle(Rectangle.Left, Rectangle.Top, Rectangle.Width, Rectangle.Height);
                }
                public static implicit operator RECT(Rectangle Rectangle)
                {
                    return new RECT(Rectangle.Left, Rectangle.Top, Rectangle.Right, Rectangle.Bottom);
                }
                public static bool operator ==(RECT Rectangle1, RECT Rectangle2)
                {
                    return Rectangle1.Equals(Rectangle2);
                }
                public static bool operator !=(RECT Rectangle1, RECT Rectangle2)
                {
                    return !Rectangle1.Equals(Rectangle2);
                }
    
                public override string ToString()
                {
                    return "{Left: " + _Left + "; " + "Top: " + _Top + "; Right: " + _Right + "; Bottom: " + _Bottom + "}";
                }
    
                public override int GetHashCode()
                {
                    return ToString().GetHashCode();
                }
    
                public bool Equals(RECT Rectangle)
                {
                    return Rectangle.Left == _Left && Rectangle.Top == _Top && Rectangle.Right == _Right && Rectangle.Bottom == _Bottom;
                }
    
                public override bool Equals(object Object)
                {
                    if (Object is RECT)
                    {
                        return Equals((RECT)Object);
                    }
                    else if (Object is Rectangle)
                    {
                        return Equals(new RECT((Rectangle)Object));
                    }
    
                    return false;
                }
            }
    
        }
    }
    

    首先,镀铬的窗口是打开的,而不是隐藏。 第二次我开始在线上开始例外:

    Bitmap bmp = new Bitmap(rc.Width, rc.Height, PixelFormat.Format32bppArgb);
    

    例外是:

    ArguemntException 参数无效

    我看到bmp为null,Width和Height为0

    我在Form1中使用了这样的代码:

    WebSiteScreenShot wsss;
    

    然后在构造函数中:

    wsss = new WebSiteScreenShot();
    wsss.WhateverMethod();
    

    使用断点并获得异常。

    这是异常完整消息:

    System.ArgumentException was unhandled
      HResult=-2147024809
      Message=Parameter is not valid.
      Source=System.Drawing
      StackTrace:
           at System.Drawing.Bitmap..ctor(Int32 width, Int32 height, PixelFormat format)
           at GatherLinks.WebSiteScreenShot.WhateverMethod() in d:\C-Sharp\GatherLinks\GatherLinks-2\GatherLinks\GatherLinks\WebSiteScreenShot.cs:line 38
           at GatherLinks.Form1..ctor() in d:\C-Sharp\GatherLinks\GatherLinks-2\GatherLinks\GatherLinks\Form1.cs:line 71
           at GatherLinks.Program.Main() in d:\C-Sharp\GatherLinks\GatherLinks-2\GatherLinks\GatherLinks\Program.cs:line 18
           at System.AppDomain._nExecuteAssembly(RuntimeAssembly assembly, String[] args)
           at System.AppDomain.ExecuteAssembly(String assemblyFile, Evidence assemblySecurity, String[] args)
           at Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly()
           at System.Threading.ThreadHelper.ThreadStart_Context(Object state)
           at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
           at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
           at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
           at System.Threading.ThreadHelper.ThreadStart()
      InnerException: 
    

2 个答案:

答案 0 :(得分:0)

修改

我添加了一个进程刷新和线程等待,可以解决Chrome启动时没有MainWindowHandle的问题。

注意事项:

Process.Refresh仅在另一个chrome实例 NOT 运行时才有效(如果chrome已经在运行,新的Process将导致新的选项卡被打开并将退出,因此process.Refresh将失败) - 其他方法可以避免这个问题。

可能需要根据您的需要调整线程休眠值,但是需要某种等待时间来创建窗口句柄和要加载的页面。

编辑结束

这应该做到

  • 启动进程(本例中为notepad.exe)
  • 等待加载用户输入并获取主窗口句柄
  • 获取给定过程的打印屏幕(我使用了Maurice在Get a screenshot of a specific application提出的解决方案,它比其他一些方法更复杂,但不要求过程在前台)< / LI>
  • 将图像保存到c:\ temp \ test.png
  • 使用ShowWindowAsync隐藏进程窗口

...
using System;
using System.Runtime.InteropServices;
using System.Diagnostics;
using System.Drawing.Imaging;
...
...
        [DllImport("user32.dll")]
        private static extern bool ShowWindowAsync(IntPtr hWnd, int nCmdShow);
        [DllImport("user32.dll")]
        public static extern bool GetWindowRect(IntPtr hWnd, out RECT lpRect);
        [DllImport("user32.dll")]
        public static extern bool PrintWindow(IntPtr hWnd, IntPtr hdcBlt, int nFlags);


        public WhateverMethod()
        {
             //initialize process and get hWnd
            Process chrome = Process.Start("chrome.exe","http://www.cnn.com");

            //wait for chrome window to open AND page to load (important for process refresh)
            //you might need to increase the sleep time for the page to load or monitor the "loading" title on Chrome

            System.Threading.Thread.Sleep(4000);
            chrome.Refresh();
            IntPtr mainHandle = chrome.MainWindowHandle;    

           RECT rc;
           GetWindowRect(mainHandle, out rc);

            Bitmap bmp = new Bitmap(rc.Width, rc.Height, PixelFormat.Format32bppArgb);
            Graphics gfxBmp = Graphics.FromImage(bmp);
            IntPtr hdcBitmap = gfxBmp.GetHdc();

            PrintWindow(mainHandle, hdcBitmap, 0);

            gfxBmp.ReleaseHdc(hdcBitmap);
            gfxBmp.Dispose();

            bmp.Save("c:\\temp\\test.png", ImageFormat.Png);
            ShowWindowAsync(mainHandle, 0);
        }

        [StructLayout(LayoutKind.Sequential)]
        public struct RECT
        {
            private int _Left;
            private int _Top;
            private int _Right;
            private int _Bottom;

            public RECT(RECT Rectangle)
                : this(Rectangle.Left, Rectangle.Top, Rectangle.Right, Rectangle.Bottom)
            {
            }
            public RECT(int Left, int Top, int Right, int Bottom)
            {
                _Left = Left;
                _Top = Top;
                _Right = Right;
                _Bottom = Bottom;
            }

            public int X
            {
                get { return _Left; }
                set { _Left = value; }
            }
            public int Y
            {
                get { return _Top; }
                set { _Top = value; }
            }
            public int Left
            {
                get { return _Left; }
                set { _Left = value; }
            }
            public int Top
            {
                get { return _Top; }
                set { _Top = value; }
            }
            public int Right
            {
                get { return _Right; }
                set { _Right = value; }
            }
            public int Bottom
            {
                get { return _Bottom; }
                set { _Bottom = value; }
            }
            public int Height
            {
                get { return _Bottom - _Top; }
                set { _Bottom = value + _Top; }
            }
            public int Width
            {
                get { return _Right - _Left; }
                set { _Right = value + _Left; }
            }
            public Point Location
            {
                get { return new Point(Left, Top); }
                set
                {
                    _Left = value.X;
                    _Top = value.Y;
                }
            }
            public Size Size
            {
                get { return new Size(Width, Height); }
                set
                {
                    _Right = value.Width + _Left;
                    _Bottom = value.Height + _Top;
                }
            }

            public static implicit operator Rectangle(RECT Rectangle)
            {
                return new Rectangle(Rectangle.Left, Rectangle.Top, Rectangle.Width, Rectangle.Height);
            }
            public static implicit operator RECT(Rectangle Rectangle)
            {
                return new RECT(Rectangle.Left, Rectangle.Top, Rectangle.Right, Rectangle.Bottom);
            }
            public static bool operator ==(RECT Rectangle1, RECT Rectangle2)
            {
                return Rectangle1.Equals(Rectangle2);
            }
            public static bool operator !=(RECT Rectangle1, RECT Rectangle2)
            {
                return !Rectangle1.Equals(Rectangle2);
            }

            public override string ToString()
            {
                return "{Left: " + _Left + "; " + "Top: " + _Top + "; Right: " + _Right + "; Bottom: " + _Bottom + "}";
            }

            public override int GetHashCode()
            {
                return ToString().GetHashCode();
            }

            public bool Equals(RECT Rectangle)
            {
                return Rectangle.Left == _Left && Rectangle.Top == _Top && Rectangle.Right == _Right && Rectangle.Bottom == _Bottom;
            }

            public override bool Equals(object Object)
            {
                if (Object is RECT)
                {
                    return Equals((RECT)Object);
                }
                else if (Object is Rectangle)
                {
                    return Equals(new RECT((Rectangle)Object));
                }

                return false;
            }
        }

答案 1 :(得分:-1)

我认为给你一个答案是迟到的,但对于遇到此问题的任何人,请尝试:wkhtmltopdf and wkhtmltoimage。 这些是开源(LGPLv3)命令行工具,使用Qt WebKit渲染引擎将HTML呈现为PDF和各种图像格式。这些完全是&#34;无头&#34;并且不需要显示或显示服务。

基本上,您可以将整个网页转换为PDF或图像格式。