示例#1
0
        private DocumentContainer(IHTMLWindow2 frameWindow, WindowDetails contentWindow, DocumentContainer parent)
        {
            //IWebBrowser2 webBrowser2 = frame as IWebBrowser2;
            //IHTMLDocument2 document2 = webBrowser2.Document as IHTMLDocument2;
            IHTMLDocument2 document2 = GetDocumentFromWindow(frameWindow);
            try {
                LOG.DebugFormat("frameWindow.name {0}", frameWindow.name);
            } catch {

            }
            try {
                LOG.DebugFormat("document2.url {0}",document2.url);
            } catch {

            }
            try {
                LOG.DebugFormat("document2.title {0}", document2.title);
            } catch {

            }

            this.parent = parent;
            // Calculate startLocation for the frames
            IHTMLWindow3 window3 = (IHTMLWindow3)document2.parentWindow;
            //			IHTMLElement element = window2.document.body;
            //			long x = 0;
            //			long y = 0;
            //			do {
            //				x += element.offsetLeft;
            //				y += element.offsetTop;
            //				element = element.offsetParent;
            //			} while (element != null);
            //			startLocation = new Point((int)x, (int)y);
            Point contentWindowLocation = contentWindow.ClientRectangle.Location;
            int x = window3.screenLeft - contentWindowLocation.X;
            int y = window3.screenTop - contentWindowLocation.Y;
            startLocation = new Point(x, y);
            Init(document2, contentWindow);
        }
示例#2
0
		private DocumentContainer(IHTMLWindow2 frameWindow, WindowDetails contentWindow, DocumentContainer parent) {
			//IWebBrowser2 webBrowser2 = frame as IWebBrowser2;
			//IHTMLDocument2 document2 = webBrowser2.Document as IHTMLDocument2;
			IHTMLDocument2 document2 = GetDocumentFromWindow(frameWindow);
			try {
				LOG.DebugFormat("frameWindow.name {0}", frameWindow.name);
				name = frameWindow.name;
			} catch {
				
			}
			try {
				LOG.DebugFormat("document2.url {0}",document2.url);
			} catch {
				
			}
			try {
				LOG.DebugFormat("document2.title {0}", document2.title);
			} catch {
				
			}

			this.parent = parent;
			// Calculate startLocation for the frames
			IHTMLWindow2 window2 = document2.parentWindow;
			IHTMLWindow3 window3 = (IHTMLWindow3)window2;
			Point contentWindowLocation = contentWindow.WindowRectangle.Location;
			int x = window3.screenLeft - contentWindowLocation.X;
			int y = window3.screenTop - contentWindowLocation.Y;

			// Release IHTMLWindow 2+3 com objects
			releaseCom(window2);
			releaseCom(window3);

			startLocation = new Point(x, y);
			Init(document2, contentWindow);
		}
        /// <summary>
        /// Private helper method for the constructors
        /// </summary>
        /// <param name="document2">IHTMLDocument2</param>
        /// <param name="contentWindow">WindowDetails</param>
        private void Init(IHTMLDocument2 document2, WindowDetails contentWindow)
        {
            this.document2 = document2;
            this.contentWindow = contentWindow;
            this.document3 = document2 as IHTMLDocument3;
            // Check what access method is needed for the document
            IHTMLDocument5 document5 = (IHTMLDocument5)document2;
            //compatibility mode affects how height is computed
            if ((document3.documentElement != null) && (!document5.compatMode.Equals("BackCompat"))) {
                isDTD = true;
            } else {
                isDTD = false;
            }
            Rectangle clientRectangle = contentWindow.WindowRectangle;
            try {
                IHTMLWindow3 window3 = (IHTMLWindow3)document2.parentWindow;
                IHTMLWindow2 window2 = (IHTMLWindow2)document2.parentWindow;
                IHTMLScreen2 screen2 = (IHTMLScreen2)window2.screen;
                IHTMLScreen screen = window2.screen;
                if (parent != null) {
                    // Copy parent values
                    zoomLevelX = parent.zoomLevelX;
                    zoomLevelY = parent.zoomLevelY;
                    viewportRectangle = parent.viewportRectangle;
                } else {
                    //DisableScrollbars(document2);

                    // Calculate zoom level
                    zoomLevelX = (double)screen2.deviceXDPI/(double)screen2.logicalXDPI;
                    zoomLevelY = (double)screen2.deviceYDPI/(double)screen2.logicalYDPI;

                    // Calculate the viewport rectangle, needed if there is a frame around the html window
                    LOG.DebugFormat("Screen {0}x{1}", ScaleX(screen.width), ScaleY(screen.height));
                    LOG.DebugFormat("Screen location {0},{1}", window3.screenLeft, window3.screenTop);
                    LOG.DebugFormat("Window rectangle {0}", clientRectangle);
                    LOG.DebugFormat("Client size {0}x{1}", ClientWidth, ClientHeight);
                    int diffX = clientRectangle.Width - ClientWidth;
                    int diffY = clientRectangle.Height - ClientHeight;
                    // If there is a border around the inner window, the diff == 4
                    // If there is a border AND a scrollbar the diff == 20
                    if ((diffX == 4 || diffX >= 20) && (diffY == 4 || diffY >= 20)) {
                        Point viewportOffset = new Point(2, 2);
                        Size viewportSize = new Size(ClientWidth, ClientHeight);
                        viewportRectangle = new Rectangle(viewportOffset, viewportSize);
                        LOG.DebugFormat("viewportRect {0}", viewportRectangle);
                    }
                }
                LOG.DebugFormat("Zoomlevel {0}, {1}", zoomLevelX, zoomLevelY);

            } catch (Exception e) {
                LOG.Warn("Can't get certain properties for documents, using default.  due to: ", e);

            }

            LOG.DebugFormat("Calculated location {0} for {1}", startLocation, document2.title);
            sourceLocation = new Point(ScaleX((int)startLocation.X), ScaleY((int)startLocation.Y));
            destinationLocation = new Point(ScaleX((int)startLocation.X), ScaleY((int)startLocation.Y));

            try {
                if (name == null) {
                    name = document2.title;
                }
            } catch {
            }
            try {
                url = document2.url;
            } catch {
            }

            if (parent != null) {
                return;
            }
            IHTMLFramesCollection2 frameCollection = (IHTMLFramesCollection2)document2.frames;
            for(int frame = 0; frame < frameCollection.length; frame++) {
                IHTMLWindow2 frameWindow = frameCollection.item(frame);
                try {
                    DocumentContainer frameData = new DocumentContainer(frameWindow, contentWindow, this);
                    // check if frame is hidden
                    if (!frameData.isHidden) {
                        LOG.DebugFormat("Creating DocumentContainer for Frame {0} found in window with rectangle {1}", frameData.name, frameData.SourceRectangle);
                        frames.Add(frameData);
                    } else {
                        LOG.DebugFormat("Skipping frame {0}", frameData.Name);
                    }
                } catch (Exception e) {
                    LOG.Warn("Problem while trying to get information from a frame, skipping the frame!", e);
                }
            }
            // Correct iframe locations
            foreach (IHTMLElement frameElement in document3.getElementsByTagName("IFRAME")){
                try {
                    CorrectFrameLocations(frameElement);
                } catch (Exception e) {
                    LOG.Warn("Problem while trying to get information from an iframe, skipping the frame!", e);
                }
            }
        }
        /// <summary>
        /// Wrapper around getElementsByTagName
        /// </summary>
        /// <param name="tagName">tagName is the name of the tag to look for, e.g. "input"</param>
        /// <param name="retrieveAttributes">If true then all attributes are retrieved. This is slow!</param>
        /// <returns></returns>
        public List<ElementContainer> GetElementsByTagName(string tagName, string[] attributes)
        {
            List<ElementContainer> elements = new List<ElementContainer>();
            foreach(IHTMLElement element in document3.getElementsByTagName(tagName)) {
                if (element.offsetWidth <= 0 || element.offsetHeight <= 0) {
                    // not visisble
                    continue;
                }
                ElementContainer elementContainer = new ElementContainer();
                elementContainer.id = element.id;

                if (attributes != null) {
                    foreach(string attributeName in attributes) {
                        object attributeValue = element.getAttribute(attributeName, 0);
                        if (attributeValue != null && attributeValue != DBNull.Value && !elementContainer.attributes.ContainsKey(attributeName)) {
                            elementContainer.attributes.Add(attributeName, attributeValue.ToString());
                        }
                    }
                }

                Point elementLocation = new Point((int)element.offsetLeft, (int)element.offsetTop);
                elementLocation.Offset(this.DestinationLocation);
                IHTMLElement parent = element.offsetParent;
                while (parent != null) {
                    elementLocation.Offset((int)parent.offsetLeft, (int)parent.offsetTop);
                    parent = parent.offsetParent;
                }
                Rectangle elementRectangle = new Rectangle(elementLocation, new Size((int)element.offsetWidth, (int)element.offsetHeight));
                elementContainer.rectangle = elementRectangle;
                elements.Add(elementContainer);
            }
            return elements;
        }
        /// <summary>
        /// Prepare the calculates for all the frames, move and fit...
        /// </summary>
        /// <param name="documentContainer"></param>
        /// <param name="capture"></param>
        /// <returns>Size of the complete page</returns>
        private static Size PrepareCapture(DocumentContainer documentContainer, ICapture capture)
        {
            // Calculate the page size
            int pageWidth = documentContainer.ScrollWidth;
            int pageHeight = documentContainer.ScrollHeight;

            // Here we loop over all the frames and try to make sure they don't overlap
            bool movedFrame;
            do {
                movedFrame = false;
                foreach(DocumentContainer currentFrame in documentContainer.Frames) {
                    foreach(DocumentContainer otherFrame in documentContainer.Frames) {
                        if (otherFrame.ID == currentFrame.ID) {
                            continue;
                        }
                        // check if we need to move
                        if (otherFrame.DestinationRectangle.IntersectsWith(currentFrame.DestinationRectangle) && !otherFrame.SourceRectangle.IntersectsWith(currentFrame.SourceRectangle)) {
                            bool horizalResize = currentFrame.SourceSize.Width < currentFrame.DestinationSize.Width;
                            bool verticalResize = currentFrame.SourceSize.Width < currentFrame.DestinationSize.Width;
                            bool horizalMove = currentFrame.SourceLeft < currentFrame.DestinationLeft;
                            bool verticalMove = currentFrame.SourceTop < currentFrame.DestinationTop;
                            bool leftOf = currentFrame.SourceRight <= otherFrame.SourceLeft;
                            bool belowOf = currentFrame.SourceBottom <= otherFrame.SourceTop;

                            if ((horizalResize || horizalMove) && leftOf) {
                                // Current frame resized horizontally, so move other horizontally
                                LOG.DebugFormat("Moving Frame {0} horizontally to the right of {1}", otherFrame.Name, currentFrame.Name);
                                otherFrame.DestinationLeft = currentFrame.DestinationRight;
                                movedFrame = true;
                            } else if ((verticalResize || verticalMove) && belowOf){
                                // Current frame resized vertically, so move other vertically
                                LOG.DebugFormat("Moving Frame {0} vertically to the bottom of {1}", otherFrame.Name, currentFrame.Name);
                                otherFrame.DestinationTop = currentFrame.DestinationBottom;
                                movedFrame = true;
                            } else {
                                LOG.DebugFormat("Frame {0} intersects with {1}", otherFrame.Name, currentFrame.Name);
                            }
                        }
                    }
                }
            } while(movedFrame);

            bool movedMouse = false;
            // Correct cursor location to be inside the window
            capture.MoveMouseLocation(-documentContainer.ContentWindow.Location.X, -documentContainer.ContentWindow.Location.Y);
            // See if the page has the correct size, as we capture the full frame content AND might have moved them
            // the normal pagesize will no longer be enough
            foreach(DocumentContainer frameData in documentContainer.Frames) {
                if (!movedMouse && frameData.SourceRectangle.Contains(capture.CursorLocation)) {
                    // Correct mouse cursor location for scrolled position (so it shows on the capture where it really was)
                    capture.MoveMouseLocation(frameData.ScrollLeft, frameData.ScrollTop);
                    movedMouse = true;
                    // Apply any other offset changes
                    int offsetX = frameData.DestinationLocation.X - frameData.SourceLocation.X;
                    int offsetY = frameData.DestinationLocation.Y - frameData.SourceLocation.Y;
                    capture.MoveMouseLocation(offsetX, offsetY);
                }

                //Get Frame Width & Height
                pageWidth = Math.Max(pageWidth, frameData.DestinationRight);
                pageHeight = Math.Max(pageHeight, frameData.DestinationBottom);
            }

            // If the mouse hasn't been moved, it wasn't on a frame. So correct the mouse according to the scroll position of the document
            if (!movedMouse) {
                // Correct mouse cursor location
                capture.MoveMouseLocation(documentContainer.ScrollLeft, documentContainer.ScrollTop);
            }

            // Limit the size as the editor currently can't work with sizes > short.MaxValue
            if (pageWidth > short.MaxValue) {
                LOG.WarnFormat("Capture has a width of {0} which bigger than the maximum supported {1}, cutting width to the maxium.", pageWidth, short.MaxValue);
                pageWidth = Math.Min(pageWidth, short.MaxValue);
            }
            if (pageHeight > short.MaxValue) {
                LOG.WarnFormat("Capture has a height of {0} which bigger than the maximum supported {1}, cutting height to the maxium", pageHeight, short.MaxValue);
                pageHeight = Math.Min(pageHeight, short.MaxValue);
            }
            return new Size(pageWidth, pageHeight);
        }
 /// <summary>
 /// Used as an example
 /// </summary>
 /// <param name="documentContainer"></param>
 /// <param name="graphicsTarget"></param>
 /// <param name="returnBitmap"></param>
 private static void ParseElements(DocumentContainer documentContainer, Graphics graphicsTarget, Bitmap returnBitmap)
 {
     foreach(ElementContainer element in documentContainer.GetElementsByTagName("input", new string[]{"greenshot"})) {
         if (element.attributes.ContainsKey("greenshot") && element.attributes["greenshot"] != null) {
             string greenshotAction = element.attributes["greenshot"];
             if ("hide".Equals(greenshotAction)) {
                 PixelizationFilter.Apply(graphicsTarget, returnBitmap, element.rectangle, 4);
             } else if ("red".Equals(greenshotAction)) {
                 using (Brush brush = new SolidBrush(Color.Red)) {
                     graphicsTarget.FillRectangle(brush, element.rectangle);
                 }
             }
         }
     }
 }
        /// <summary>
        /// Helper method which will retrieve the IHTMLDocument2 for the supplied window,
        ///  or return the first if none is supplied.
        /// </summary>
        /// <param name="browserWindowDetails">The WindowDetails to get the IHTMLDocument2 for</param>
        /// <param name="document2">Ref to the IHTMLDocument2 to return</param>
        /// <returns>The WindowDetails to which the IHTMLDocument2 belongs</returns>
        private static DocumentContainer GetDocument(WindowDetails activeWindow)
        {
            DocumentContainer returnDocumentContainer = null;
            WindowDetails returnWindow = null;
            IHTMLDocument2 returnDocument2 = null;
            // alternative if no match
            WindowDetails alternativeReturnWindow = null;
            IHTMLDocument2 alternativeReturnDocument2 = null;

            // Find the IE window
            foreach (WindowDetails ieWindow in WindowDetails.GetAllWindows("IEFrame")) {
                LOG.DebugFormat("Processing {0} - {1}", ieWindow.ClassName, ieWindow.Text);

                Accessible ieAccessible = null;
                WindowDetails directUIWD = IEHelper.GetDirectUI(ieWindow);
                if (directUIWD != null) {
                    ieAccessible = new Accessible(directUIWD.Handle);
                }
                if (ieAccessible == null) {
                    LOG.InfoFormat("Active Window is {0}", activeWindow.Text);
                    if (!ieWindow.Equals(activeWindow)) {
                        LOG.WarnFormat("No ieAccessible for {0}", ieWindow.Text);
                        continue;
                    }
                    LOG.DebugFormat("No ieAccessible, but the active window is an IE window: {0}, ", ieWindow.Text);
                }

                try {
                    // Get the Document
                    IHTMLDocument2 document2 = null;
                    uint windowMessage = User32.RegisterWindowMessage("WM_HTML_GETOBJECT");
                    if (windowMessage == 0) {
                        LOG.WarnFormat("Couldn't register WM_HTML_GETOBJECT");
                        continue;
                    }

                    WindowDetails ieServer= ieWindow.GetChild("Internet Explorer_Server");
                    if (ieServer == null) {
                        LOG.WarnFormat("No Internet Explorer_Server for {0}", ieWindow.Text);
                        continue;
                    }
                    LOG.DebugFormat("Trying WM_HTML_GETOBJECT on {0}", ieServer.ClassName);
                    UIntPtr response;
                    User32.SendMessageTimeout(ieServer.Handle, windowMessage, IntPtr.Zero, IntPtr.Zero, SendMessageTimeoutFlags.SMTO_NORMAL, 1000, out response);
                    if (response != UIntPtr.Zero) {
                        document2 = (IHTMLDocument2)Accessible.ObjectFromLresult(response, typeof(IHTMLDocument).GUID, IntPtr.Zero);
                        if (document2 == null) {
                            LOG.Error("No IHTMLDocument2 found");
                            continue;
                        }
                    } else {
                        LOG.Error("No answer on WM_HTML_GETOBJECT.");
                        continue;
                    }

                    // Get the content window handle for the shellWindow.Document
                    IOleWindow oleWindow = (IOleWindow)document2;
                    IntPtr contentWindowHandle = IntPtr.Zero;
                    if (oleWindow != null) {
                        oleWindow.GetWindow(out contentWindowHandle);
                    }

                    if (contentWindowHandle != IntPtr.Zero) {
                        // Get the HTMLDocument to check the hasFocus
                        // See: http://social.msdn.microsoft.com/Forums/en-US/vbgeneral/thread/60c6c95d-377c-4bf4-860d-390840fce31c/
                        IHTMLDocument4 document4 = (IHTMLDocument4)document2;

                        if (document4.hasFocus()) {
                            LOG.DebugFormat("Matched focused document: {0}", document2.title);
                            // Look no further, we got what we wanted!
                            returnDocument2 = document2;
                            returnWindow = new WindowDetails(contentWindowHandle);
                            break;
                        }
                        try {
                            if (ieWindow.Equals(activeWindow)) {
                                returnDocument2 = document2;
                                returnWindow = new WindowDetails(contentWindowHandle);
                                break;
                            } else if (ieAccessible != null && returnWindow == null && document2.title.Equals(ieAccessible.IEActiveTabCaption) ) {
                                LOG.DebugFormat("Title: {0}", document2.title);
                                returnDocument2 = document2;
                                returnWindow = new WindowDetails(contentWindowHandle);
                            } else {
                                alternativeReturnDocument2 = document2;
                                alternativeReturnWindow = new WindowDetails(contentWindowHandle);
                            }
                        } catch (Exception) {
                            alternativeReturnDocument2 = document2;
                            alternativeReturnWindow = new WindowDetails(contentWindowHandle);
                        }
                    }
                } catch (Exception e) {
                    LOG.Error(e);
                    LOG.DebugFormat("Major problem: Problem retrieving Document from {0}", ieWindow.Text);
                }
            }

            // check if we have something to return
            if (returnWindow != null) {
                // As it doesn't have focus, make sure it's active
                returnWindow.Restore();
                returnWindow.GetParent();

                // Create the container
                returnDocumentContainer = new DocumentContainer(returnDocument2, returnWindow);
            }

            if (returnDocumentContainer == null && alternativeReturnDocument2 != null) {
                // As it doesn't have focus, make sure it's active
                alternativeReturnWindow.Restore();
                alternativeReturnWindow.GetParent();
                // Create the container
                returnDocumentContainer =  new DocumentContainer(alternativeReturnDocument2, alternativeReturnWindow);
            }
            return returnDocumentContainer;
        }
        /// <summary>
        /// This method takes the actual capture of the document (frame)
        /// </summary>
        /// <param name="frameDocument"></param>
        /// <param name="contentWindowDetails">Needed for referencing the location of the frame</param>
        /// <returns>Bitmap with the capture</returns>
        private static void drawDocument(DocumentContainer documentContainer, WindowDetails contentWindowDetails, Graphics graphicsTarget)
        {
            documentContainer.setAttribute("scroll", 1);

            //Get Browser Window Width & Height
            int pageWidth = documentContainer.ScrollWidth;
            int pageHeight = documentContainer.ScrollHeight;
            if (pageWidth * pageHeight == 0) {
                LOG.WarnFormat("Empty page for DocumentContainer {0}: {1}", documentContainer.Name, documentContainer.Url);
                return;
            }

            //Get Screen Width & Height (this is better as the WindowDetails.ClientRectangle as the real visible parts are there!
            int viewportWidth = documentContainer.ClientWidth;
            int viewportHeight = documentContainer.ClientHeight;
            if (viewportWidth * viewportHeight == 0) {
                LOG.WarnFormat("Empty viewport for DocumentContainer {0}: {1}", documentContainer.Name, documentContainer.Url);
                return;
            }

            // Store the current location so we can set the browser back and use it for the mouse cursor
            int startLeft = documentContainer.ScrollLeft;
            int startTop = documentContainer.ScrollTop;

            LOG.DebugFormat("Capturing {4} with total size {0},{1} displayed with size {2},{3}", pageWidth, pageHeight, viewportWidth, viewportHeight, documentContainer.Name);

            // Variable used for looping horizontally
            int horizontalPage = 0;

            // The location of the browser, used as the destination into the bitmap target
            Point targetOffset = new Point();

            // Loop of the pages and make a copy of the visible viewport
            while ((horizontalPage * viewportWidth) < pageWidth) {
                // Scroll to location
                documentContainer.ScrollLeft = viewportWidth * horizontalPage;
                targetOffset.X = documentContainer.ScrollLeft;

                // Variable used for looping vertically
                int verticalPage = 0;
                while ((verticalPage * viewportHeight) < pageHeight) {
                    // Scroll to location
                    documentContainer.ScrollTop = viewportHeight * verticalPage;
                    //Shoot visible window
                    targetOffset.Y  = documentContainer.ScrollTop;

                    // Draw the captured fragment to the target, but "crop" the scrollbars etc while capturing
                    Size viewPortSize = new Size(viewportWidth, viewportHeight);
                    Rectangle clientRectangle = new Rectangle(documentContainer.SourceLocation, viewPortSize);
                    Image fragment = contentWindowDetails.PrintWindow();
                    if (fragment != null) {
                        LOG.DebugFormat("Captured fragment size: {0}x{1}", fragment.Width, fragment.Height);
                        try {
                            // cut all junk, due to IE "border" we need to remove some parts
                            Rectangle viewportRect = documentContainer.ViewportRectangle;
                            if (!viewportRect.IsEmpty) {
                                LOG.DebugFormat("Cropping to viewport: {0}", viewportRect);
                                ImageHelper.Crop(ref fragment, ref viewportRect);
                            }
                            LOG.DebugFormat("Cropping to clientRectangle: {0}", clientRectangle);
                            // Crop to clientRectangle
                            if (ImageHelper.Crop(ref fragment, ref clientRectangle)) {
                                Point targetLocation = new Point(documentContainer.DestinationLocation.X, documentContainer.DestinationLocation.Y);
                                LOG.DebugFormat("Fragment targetLocation is {0}", targetLocation);
                                targetLocation.Offset(targetOffset);
                                LOG.DebugFormat("After offsetting the fragment targetLocation is {0}", targetLocation);
                                LOG.DebugFormat("Drawing fragment of size {0} to {1}", fragment.Size, targetLocation);
                                graphicsTarget.DrawImage(fragment, targetLocation);
                                graphicsTarget.Flush();
                            } else {
                                // somehow we are capturing nothing!?
                                LOG.WarnFormat("Crop of {0} failed?", documentContainer.Name);
                                break;
                            }
                        } finally {
                            fragment.Dispose();
                        }
                    } else {
                        LOG.WarnFormat("Capture of {0} failed!", documentContainer.Name);
                    }
                    verticalPage++;
                }
                horizontalPage++;
            }
            // Return to where we were
            documentContainer.ScrollLeft = startLeft;
            documentContainer.ScrollTop = startTop;
        }
        /// <summary>
        /// Capture the actual page (document)
        /// </summary>
        /// <param name="documentContainer">The document wrapped in a container</param>
        /// <returns>Bitmap with the page content as an image</returns>
        private static Bitmap capturePage(DocumentContainer documentContainer, ICapture capture, Size pageSize)
        {
            WindowDetails contentWindowDetails = documentContainer.ContentWindow;

            //Create a target bitmap to draw into with the calculated page size
            Bitmap returnBitmap = new Bitmap(pageSize.Width, pageSize.Height, PixelFormat.Format24bppRgb);
            using (Graphics graphicsTarget = Graphics.FromImage(returnBitmap)) {
                // Clear the target with the backgroundcolor
                Color clearColor = documentContainer.BackgroundColor;
                LOG.DebugFormat("Clear color: {0}", clearColor);
                graphicsTarget.Clear(clearColor);

                // Get the base document & draw it
                drawDocument(documentContainer, contentWindowDetails, graphicsTarget);

                // Loop over the frames and clear their source area so we don't see any artefacts
                foreach(DocumentContainer frameDocument in documentContainer.Frames) {
                    using(Brush brush = new SolidBrush(clearColor)) {
                        graphicsTarget.FillRectangle(brush, frameDocument.SourceRectangle);
                    }
                }
                // Loop over the frames and capture their content
                foreach(DocumentContainer frameDocument in documentContainer.Frames) {
                    drawDocument(frameDocument, contentWindowDetails, graphicsTarget);
                }
            }
            return returnBitmap;
        }
示例#10
0
        /// <summary>
        /// Capture the actual page (document)
        /// </summary>
        /// <param name="documentContainer">The document wrapped in a container</param>
        /// <returns>Bitmap with the page content as an image</returns>
        private static Bitmap capturePage(DocumentContainer documentContainer, ICapture capture)
        {
            WindowDetails contentWindowDetails = documentContainer.ContentWindow;
            // Calculate the page size
            int pageWidth = documentContainer.ScrollWidth;
            int pageHeight = documentContainer.ScrollHeight;

            // Here we loop over all the frames and try to make sure they don't overlap
            bool movedFrame;
            do {
                movedFrame = false;
                foreach(DocumentContainer currentFrame in documentContainer.Frames) {
                    foreach(DocumentContainer otherFrame in documentContainer.Frames) {
                        if (otherFrame.ID == currentFrame.ID) {
                            continue;
                        }
                        // check if we need to move
                        if (otherFrame.DestinationRectangle.IntersectsWith(currentFrame.DestinationRectangle) && !otherFrame.SourceRectangle.IntersectsWith(currentFrame.SourceRectangle)) {
                            bool horizalResize = currentFrame.SourceSize.Width < currentFrame.DestinationSize.Width;
                            bool verticalResize = currentFrame.SourceSize.Width < currentFrame.DestinationSize.Width;
                            bool horizalMove = currentFrame.SourceLeft < currentFrame.DestinationLeft;
                            bool verticalMove = currentFrame.SourceTop < currentFrame.DestinationTop;
                            bool leftOf = currentFrame.SourceRight <= otherFrame.SourceLeft;
                            bool belowOf = currentFrame.SourceBottom <= otherFrame.SourceTop;

                            if ((horizalResize || horizalMove) && leftOf) {
                                // Current frame resized horizontally, so move other horizontally
                                LOG.DebugFormat("Moving Frame {0} horizontally to the right of {1}", otherFrame.Name, currentFrame.Name);
                                otherFrame.DestinationLeft = currentFrame.DestinationRight;
                                movedFrame = true;
                            } else if ((verticalResize || verticalMove) && belowOf){
                                // Current frame resized vertically, so move other vertically
                                LOG.DebugFormat("Moving Frame {0} vertically to the bottom of {1}", otherFrame.Name, currentFrame.Name);
                                otherFrame.DestinationTop = currentFrame.DestinationBottom;
                                movedFrame = true;
                            } else {
                                LOG.DebugFormat("Frame {0} intersects with {1}", otherFrame.Name, currentFrame.Name);
                            }
                        }
                    }
                }
            } while(movedFrame);

            bool movedMouse = false;
            // Correct cursor location to be inside the window
            capture.MoveMouseLocation(-documentContainer.ContentWindow.Location.X, -documentContainer.ContentWindow.Location.Y);
            // See if the page has the correct size, as we capture the full frame content AND might have moved them
            // the normal pagesize will no longer be enough
            foreach(DocumentContainer frameData in documentContainer.Frames) {
                if (!movedMouse && frameData.SourceRectangle.Contains(capture.CursorLocation)) {
                    // Correct mouse cursor location for scrolled position (so it shows on the capture where it really was)
                    capture.MoveMouseLocation(frameData.ScrollLeft, frameData.ScrollTop);
                    movedMouse = true;
                    // Apply any other offset changes
                    int offsetX = frameData.DestinationLocation.X - frameData.SourceLocation.X;
                    int offsetY = frameData.DestinationLocation.Y - frameData.SourceLocation.Y;
                    capture.MoveMouseLocation(offsetX, offsetY);
                }

                //Get Frame Width & Height
                pageWidth = Math.Max(pageWidth, frameData.DestinationRight);
                pageHeight = Math.Max(pageHeight, frameData.DestinationBottom);
            }

            // If the mouse hasn't been moved, it wasn't on a frame. So correct the mouse according to the scroll position of the document
            if (!movedMouse) {
                // Correct mouse cursor location
                capture.MoveMouseLocation(documentContainer.ScrollLeft, documentContainer.ScrollTop);
            }

            // Limit the size as the editor currently can't work with sizes > short.MaxValue
            if (pageWidth > short.MaxValue) {
                LOG.WarnFormat("Capture has a width of {0} which bigger than the maximum supported {1}, cutting width to the maxium.", pageWidth, short.MaxValue);
                pageWidth = Math.Min(pageWidth, short.MaxValue);
            }
            if (pageHeight > short.MaxValue) {
                LOG.WarnFormat("Capture has a height of {0} which bigger than the maximum supported {1}, cutting height to the maxium", pageHeight, short.MaxValue);
                pageHeight = Math.Min(pageHeight, short.MaxValue);
            }

            //Create a target bitmap to draw into with the calculated page size
            Bitmap returnBitmap = new Bitmap(pageWidth, pageHeight, PixelFormat.Format24bppRgb);
            using (Graphics graphicsTarget = Graphics.FromImage(returnBitmap)) {
                // Clear the target with the backgroundcolor
                Color clearColor = documentContainer.BackgroundColor;
                LOG.DebugFormat("Clear color: {0}", clearColor);
                graphicsTarget.Clear(clearColor);

                // Get the base document & draw it
                drawDocument(documentContainer, contentWindowDetails, graphicsTarget);
                //ParseElements(documentContainer, graphicsTarget, returnBitmap);
                // Loop over the frames and clear their source area so we don't see any artefacts
                foreach(DocumentContainer frameDocument in documentContainer.Frames) {
                    using(Brush brush = new SolidBrush(clearColor)) {
                        graphicsTarget.FillRectangle(brush, frameDocument.SourceRectangle);
                    }
                }
                // Loop over the frames and capture their content
                foreach(DocumentContainer frameDocument in documentContainer.Frames) {
                    drawDocument(frameDocument, contentWindowDetails, graphicsTarget);
                    //ParseElements(frameDocument, graphicsTarget, returnBitmap);
                }
            }
            return returnBitmap;
        }
示例#11
0
		/// <summary>
		/// Helper method which will retrieve the IHTMLDocument2 for the supplied window,
		///  or return the first if none is supplied.
		/// </summary>
		/// <param name="browserWindow">The WindowDetails to get the IHTMLDocument2 for</param>
		/// <param name="document2">Ref to the IHTMLDocument2 to return</param>
		/// <returns>The WindowDetails to which the IHTMLDocument2 belongs</returns>
		private static DocumentContainer CreateDocumentContainer(WindowDetails browserWindow) {
			DocumentContainer returnDocumentContainer = null;
			WindowDetails returnWindow = null;
			IHTMLDocument2 returnDocument2 = null;
			// alternative if no match
			WindowDetails alternativeReturnWindow = null;
			IHTMLDocument2 alternativeReturnDocument2 = null;

			// Find the IE windows
			foreach (WindowDetails ieWindow in GetIEWindows()) {
				LOG.DebugFormat("Processing {0} - {1}", ieWindow.ClassName, ieWindow.Text);
				
				Accessible ieAccessible = null;
				WindowDetails directUIWD = IEHelper.GetDirectUI(ieWindow);
				if (directUIWD != null) {
					ieAccessible = new Accessible(directUIWD.Handle);
				}
				if (ieAccessible == null) {
					if (browserWindow != null) {
						LOG.InfoFormat("Active Window is {0}", browserWindow.Text);
					}
					if (!ieWindow.Equals(browserWindow)) {
						LOG.WarnFormat("No ieAccessible for {0}", ieWindow.Text);
						continue;
					}
					LOG.DebugFormat("No ieAccessible, but the active window is an IE window: {0}, ", ieWindow.Text);
				}

				try {
					// Get the Document
					IHTMLDocument2 document2 = getHTMLDocument(ieWindow);
					if (document2 == null) {
						continue;
					}

					// Get the content window handle for the shellWindow.Document
					IOleWindow oleWindow = (IOleWindow)document2;
					IntPtr contentWindowHandle = IntPtr.Zero;
					if (oleWindow != null) {
						oleWindow.GetWindow(out contentWindowHandle);
					}

					if (contentWindowHandle != IntPtr.Zero) {
						// Get the HTMLDocument to check the hasFocus
						// See: http://social.msdn.microsoft.com/Forums/en-US/vbgeneral/thread/60c6c95d-377c-4bf4-860d-390840fce31c/
						IHTMLDocument4 document4 = (IHTMLDocument4)document2;

						if (document4.hasFocus()) {
							LOG.DebugFormat("Matched focused document: {0}", document2.title);
							// Look no further, we got what we wanted!
							returnDocument2 = document2;
							returnWindow = new WindowDetails(contentWindowHandle);
							break;
						}
						try {
							if (ieWindow.Equals(browserWindow)) {
								returnDocument2 = document2;
								returnWindow = new WindowDetails(contentWindowHandle);
								break;
							}
							if (ieAccessible != null && returnWindow == null && document2.title.Equals(ieAccessible.IEActiveTabCaption) ) {
								LOG.DebugFormat("Title: {0}", document2.title);
								returnDocument2 = document2;
								returnWindow = new WindowDetails(contentWindowHandle);
							} else {
								alternativeReturnDocument2 = document2;
								alternativeReturnWindow = new WindowDetails(contentWindowHandle);								
							}
						} catch (Exception) {
							alternativeReturnDocument2 = document2;
							alternativeReturnWindow = new WindowDetails(contentWindowHandle);
						}
					}
				} catch (Exception e) {
					LOG.ErrorFormat("Major problem: Problem retrieving Document from {0}", ieWindow.Text);
					LOG.Error(e);
				}
			}

			// check if we have something to return
			if (returnWindow != null) {
				// As it doesn't have focus, make sure it's active
				returnWindow.Restore();
				returnWindow.GetParent();

				// Create the container
				try {
					returnDocumentContainer = new DocumentContainer(returnDocument2, returnWindow);
				} catch (Exception e) {
					LOG.Error("Major problem: Problem retrieving Document.");
					LOG.Error(e);
				}
			}

			if (returnDocumentContainer == null && alternativeReturnDocument2 != null) {
				// As it doesn't have focus, make sure it's active
				alternativeReturnWindow.Restore();
				alternativeReturnWindow.GetParent();
				// Create the container
				try {
					returnDocumentContainer = new DocumentContainer(alternativeReturnDocument2, alternativeReturnWindow);
				} catch (Exception e) {
					LOG.Error("Major problem: Problem retrieving Document.");
					LOG.Error(e);
				}
			}
			return returnDocumentContainer;
		}