using System; using System.Collections.Generic; using System.Text; using System.Drawing; using System.Windows.Forms; using System.Diagnostics; // Ooganizer Namespaces using Foo.Platform; using Foo.Platform.Interacters; using Foo.Platform.Win32; namespace Foo.GUILib { /// /// This is the generic GUICommon Class, that serves us a generic implementation to /// everyone as to isolate ourselves from OS Changes /// public class GUICommon { // Keep track of all the origianl window positions that go // thru here, ~we delete them when position back to org position // get's called. private static Dictionary s_orgWindowPosMap; private static bool s_bOutOfProc_UseBH = false; // public properties public static bool OutOfProc { get { return s_bOutOfProc_UseBH; } } // keep track of Window Positions static GUICommon() { s_orgWindowPosMap = new Dictionary(); } /// /// Performs a screen snapshot of the passed in window handle. /// /// Window to Snap /// a window image public static Image PerformSnapshot(IntPtr hWnd) { if (hWnd != IntPtr.Zero) { ScreenCapture screencap = new ScreenCapture(); if (Env.Theme == Env.Themes.AeroTheme) return screencap.SaveWindowUsingFullScreenShotCrop(hWnd); else return screencap.SaveWindowUsingDCNBitBlt(hWnd, false); } return null; } /// /// Positions a window in the center at Golden Ratio and takes a snapshot. /// ~corner stone of our add workspace strategy /// /// handle to the window to manipulate /// Set to true to use ButtonHook to Perform the action public static Image PositionWindowToGoldenPosAndTakeSnapshot(IntPtr hWnd, bool bOutOfProc) { // use ButtonHook, Yes / No? s_bOutOfProc_UseBH = bOutOfProc; // First thing to do is to save the org position RECT rect; Win32Functions.GetWindowRect(hWnd, out rect); s_orgWindowPosMap[hWnd] = rect; // First we fade the window totally away FadeWindow(hWnd, true); // now we want to fade it out of the monitor center // However using the golden ratio as the size FadeWindowOutOfMonitorCenterInGoldenRatio(hWnd, rect); // Make sure we are in position and drawing at this point, // perform the snapshot and return System.Threading.Thread.Sleep(10); //PositionWindowBackToWhereItWas(hWnd); Image image = PerformSnapshot(hWnd); //image.Save(@"D:\Users\HPInvent\Desktop\Snapshot1.png", System.Drawing.Imaging.ImageFormat.Png); //return null; return image; } /// /// Positions a window back to where it was prior to calling PositionWindowToGoldenPosAndTakeSnapshot(). /// ~Hence, you should call this after calling that function /// /// handle to the window to manipulate /// Set to true to use ButtonHook to Perform the action public static void PositionWindowBackToWhereItWas(IntPtr hWnd, bool bOutOfProc) { // use ButtonHook, Yes / No? s_bOutOfProc_UseBH = bOutOfProc; // try to retrieve the org value from the map if (!s_orgWindowPosMap.ContainsKey(hWnd)) return; RECT orgRect = s_orgWindowPosMap[hWnd]; // Set the Window totally invisible SetAlphaTransparency(hWnd, 0); // As part of the effect, wait a little System.Threading.Thread.Sleep(60); // Now just flat out position it back to where it was Win32Functions.SetWindowPos(hWnd, IntPtr.Zero, orgRect.left, orgRect.top, orgRect.AsRectangle.Width, orgRect.AsRectangle.Height, (uint)SetWindowPosFlags.SWP_SHOWWINDOW); // Now Fade the Window out FadeWindow(hWnd, false); //SetAlphaTransparency(hWnd, 0); // invisible //SetAlphaTransparency(hWnd, 255); // visible // since we positioned the window back to where it was, // we no longer need to keep track of it's org position s_orgWindowPosMap.Remove(hWnd); } /// /// Use this generic function to set the transparency /// private static void SetAlphaTransparency(IntPtr hWnd, byte alpha) { if (s_bOutOfProc_UseBH) BHInteracter.SetWindowTransparency(hWnd, alpha); else Win32_WrapperFunc.SetAlphaChannel(hWnd, alpha); } /// /// The Golden Ratio (~1.618) is used for the Snapshot to give it the best look /// /// pass in th screen for which to calculate the ratio for /// the width and height to achieve the best golden ratio for that screen private static void CalculateGoldenRatio(Screen screen, out RECT rect) { const int _MAXHEIGHT = 1100; // max pleasing height const double _fGoldenRatio = 1.618; const double _fsafetybuffer = 10; // 10% just in case // safety buffer for height/width int maxHeight = screen.WorkingArea.Height; int maxWidth = screen.WorkingArea.Width; // is this a potrait screen? bool bIsPortrait = maxHeight > maxWidth; // calculated height and width int height = 0; int width = 0; // Normal Screen if (!bIsPortrait) { // calculated height and width; height = maxHeight - (int)(((double)maxHeight / 100) * _fsafetybuffer); width = (int)((double)height / _fGoldenRatio); } else // Portrait { width = maxWidth - (int)(((double)maxWidth / 100) * _fsafetybuffer); height = (int)((double)width * _fGoldenRatio); } // Enforce that the height is not bigger than _MAXHEIGHT, anything bigger than // that just look unpleasant. if (height >= _MAXHEIGHT) { height = _MAXHEIGHT; width = (int)((double)height / _fGoldenRatio); } // pass out the calculated height and width rect.left = 0; rect.top = 0; rect.bottom = height; rect.right = width; } /// /// Use this to quickle fade a window /// /// Set to true to fade in, false to Fade out private static void FadeWindow(IntPtr hWnd, bool bFadeIn) { // Stole Increment Fading from Buttonhook const int LOWER_INCREMENT = 7; const int MIDDLE_INCREMENT = 15; const int UPPER_INCREMENT = 25; // Increment Points *inverted* const int LOWER_POINT = 60; const int MIDDLE_POINT = 160; const int UPPER_POINT = 230; // Fade in or Fade out? byte alpha = (!bFadeIn)? (byte)0 : (byte)255; bool bDone = false; if (!bFadeIn) // FadeOut { while (!bDone) { if (alpha >= UPPER_POINT) { alpha = 255; // just show the thing already bDone = true; } else if (alpha <= LOWER_POINT) alpha += LOWER_INCREMENT; else if (alpha <= MIDDLE_POINT) alpha += MIDDLE_INCREMENT; else alpha += UPPER_INCREMENT; SetAlphaTransparency(hWnd, alpha); System.Threading.Thread.Sleep(20); } } else // FadeIn { while (!bDone) { if (alpha <= (255 - UPPER_POINT)) //25 { alpha = 0; // just hide the thing already bDone = true; } else if (alpha >= (255 - LOWER_POINT)) //195 alpha -= LOWER_INCREMENT; else if (alpha >= (255 - MIDDLE_POINT)) // 95 alpha -= MIDDLE_INCREMENT; else alpha -= UPPER_INCREMENT; SetAlphaTransparency(hWnd, alpha); System.Threading.Thread.Sleep(20); } } } /// /// Helper function to determine the monitor and it's center and /// fade out the window there in GoldenRatio Siz /// private static void FadeWindowOutOfMonitorCenterInGoldenRatio(IntPtr hWnd, RECT orgRect) { // get the screen the original rect was mostly located Screen screen = Screen.FromRectangle(orgRect.AsRectangle); // now figure out the best rect to use for this screen RECT goldenRect; CalculateGoldenRatio(screen, out goldenRect); // calculate where we must place the golden window // (centering it on the screen) Point pt = new Point(); pt.Y = (screen.Bounds.Height - goldenRect.AsRectangle.Height) / 2; pt.X = (screen.Bounds.Width - goldenRect.AsRectangle.Width) / 2; // Calculate the window center according to the screen pt.Y = screen.Bounds.Top + pt.Y; pt.X = screen.Bounds.Left + pt.X; // Make the window totally transparent and show it in the golden ratio position SetAlphaTransparency(hWnd, 0); Win32Functions.SetWindowPos(hWnd, IntPtr.Zero, pt.X, pt.Y, goldenRect.AsRectangle.Width, goldenRect.AsRectangle.Height, (uint) SetWindowPosFlags.SWP_SHOWWINDOW); // Now Fade the Window out FadeWindow(hWnd, false); } } }