286 lines
11 KiB
C#
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);
|
|
}
|
|
|
|
}
|
|
}
|
|
|