Files
Oogynize/GUILib/GUICommon.cs

286 lines
11 KiB
C#

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
{
/// <summary>
/// This is the generic GUICommon Class, that serves us a generic implementation to
/// everyone as to isolate ourselves from OS Changes
/// </summary>
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<IntPtr,RECT> 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<IntPtr, RECT>();
}
/// <summary>
/// Performs a screen snapshot of the passed in window handle.
/// </summary>
/// <param name="hWnd">Window to Snap</param>
/// <returns>a window image</returns>
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;
}
/// <summary>
/// Positions a window in the center at Golden Ratio and takes a snapshot.
/// ~corner stone of our add workspace strategy
/// </summary>
/// <param name="hWnd">handle to the window to manipulate</param>
/// <param name="bOutOfProc">Set to true to use ButtonHook to Perform the action</param>
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;
}
/// <summary>
/// Positions a window back to where it was prior to calling PositionWindowToGoldenPosAndTakeSnapshot().
/// ~Hence, you should call this after calling that function
/// </summary>
/// <param name="hWnd">handle to the window to manipulate</param>
/// <param name="bOutOfProc">Set to true to use ButtonHook to Perform the action</param>
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);
}
/// <summary>
/// Use this generic function to set the transparency
/// </summary>
private static void SetAlphaTransparency(IntPtr hWnd, byte alpha)
{
if (s_bOutOfProc_UseBH)
BHInteracter.SetWindowTransparency(hWnd, alpha);
else
Win32_WrapperFunc.SetAlphaChannel(hWnd, alpha);
}
/// <summary>
/// The Golden Ratio (~1.618) is used for the Snapshot to give it the best look
/// </summary>
/// <param name="screen">pass in th screen for which to calculate the ratio for</param>
/// <param name="rect">the width and height to achieve the best golden ratio for that screen</param>
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;
}
/// <summary>
/// Use this to quickle fade a window
/// </summary>
/// <param name="bFadeIn">Set to true to fade in, false to Fade out</param>
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);
}
}
}
/// <summary>
/// Helper function to determine the monitor and it's center and
/// fade out the window there in GoldenRatio Siz
/// </summary>
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);
}
}
}