Window actions implemented. Keyboard controls implemented.
This commit is contained in:
parent
e2f8bb5c7e
commit
bc28da6c93
|
|
@ -13,6 +13,7 @@ using System.Windows.Media.Imaging;
|
||||||
using System.Windows.Navigation;
|
using System.Windows.Navigation;
|
||||||
using System.Windows.Shapes;
|
using System.Windows.Shapes;
|
||||||
using Valve.VR;
|
using Valve.VR;
|
||||||
|
using VDash.Overlay;
|
||||||
|
|
||||||
namespace VDash
|
namespace VDash
|
||||||
{
|
{
|
||||||
|
|
@ -25,7 +26,7 @@ namespace VDash
|
||||||
{
|
{
|
||||||
InitializeComponent();
|
InitializeComponent();
|
||||||
|
|
||||||
//Connect to VR runtime...
|
///Connect to VR runtime...
|
||||||
EVRInitError initError = EVRInitError.None;
|
EVRInitError initError = EVRInitError.None;
|
||||||
|
|
||||||
var ret = OpenVR.Init(ref initError, EVRApplicationType.VRApplication_Overlay);
|
var ret = OpenVR.Init(ref initError, EVRApplicationType.VRApplication_Overlay);
|
||||||
|
|
@ -35,25 +36,38 @@ namespace VDash
|
||||||
throw new Exception($"Error connecting to VR: {initError.ToString()}");
|
throw new Exception($"Error connecting to VR: {initError.ToString()}");
|
||||||
}
|
}
|
||||||
|
|
||||||
//ulong desktopOverlay = 0;
|
|
||||||
|
|
||||||
//var err = OpenVR.Overlay.FindOverlay("valve.steam.desktop", ref desktopOverlay);
|
StartOverlayWindow("Discord");
|
||||||
|
|
||||||
//HmdVector2_t vec = new HmdVector2_t();
|
StartOverlayWindow("Microsoft Visual Studio");
|
||||||
|
|
||||||
//OpenVR.Overlay.GetOverlayMouseScale(desktopOverlay, ref vec);
|
StartOverlayWindow("Notepad++");
|
||||||
|
|
||||||
//var discordSelector = new WindowSelectors.FromWindowTitle("Discord", WindowSelectors.FromWindowTitle.TitleSearchType.Contains);
|
//StartOverlayWindow("Putty");
|
||||||
//Overlay.WindowOverlay discordOverlay = new Overlay.WindowOverlay("discord", "Discord", discordSelector, true);
|
|
||||||
//discordOverlay.Create();
|
|
||||||
|
|
||||||
var vsSelector = new WindowSelectors.FromWindowTitle("Microsoft Visual Studio", WindowSelectors.FromWindowTitle.TitleSearchType.Contains);
|
StartOverlayWindow("Paint");
|
||||||
Overlay.WindowOverlay vsOverlay = new Overlay.WindowOverlay("vs", "Visual Studio", vsSelector, true);
|
|
||||||
vsOverlay.Create();
|
|
||||||
|
|
||||||
//Overlay.WindowOverlay obsOverlay = new Overlay.WindowOverlay("obs", "OBS", new WindowSelectors.FromProcessName("obs64"), false);
|
Overlay.WindowOverlay obsoverlay = new Overlay.WindowOverlay("obs", "obs", new WindowSelectors.FromProcessName("obs64"), false);
|
||||||
//obsOverlay.Create();
|
obsoverlay.Create();
|
||||||
|
obsoverlay.DestroyOnNoWindowFound = true;
|
||||||
|
var bringWindow = new Overlay.Actions.BringWindowToFrontAction(true);
|
||||||
|
obsoverlay.OverlayShownActions.Add(bringWindow);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//This is just for debugging I swear
|
||||||
|
int count = 0;
|
||||||
|
IOverlay StartOverlayWindow(string windowFilter)
|
||||||
|
{
|
||||||
|
var ws = new WindowSelectors.FromWindowTitle(windowFilter, WindowSelectors.FromWindowTitle.TitleSearchType.Contains);
|
||||||
|
Overlay.WindowOverlay overlay = new Overlay.WindowOverlay($"ws{count}", "Loading...", ws, true);
|
||||||
|
overlay.Create();
|
||||||
|
|
||||||
|
var bringWindow = new Overlay.Actions.BringWindowToFrontAction(true);
|
||||||
|
overlay.OverlayShownActions.Add(bringWindow);
|
||||||
|
count++;
|
||||||
|
return overlay;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,54 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.ComponentModel;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using VDash.Utilities;
|
||||||
|
|
||||||
|
namespace VDash.Overlay.Actions
|
||||||
|
{
|
||||||
|
public class BringWindowToFrontAction : IOverlayAction
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Unminimize the window if it's minimized.
|
||||||
|
/// </summary>
|
||||||
|
public bool UnminimizeIfMinimized { get; set; }
|
||||||
|
public bool Enabled { get; set; } = true;
|
||||||
|
|
||||||
|
public BringWindowToFrontAction(bool unminimizeIfMinimized)
|
||||||
|
{
|
||||||
|
UnminimizeIfMinimized = unminimizeIfMinimized;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void PreformAction(IOverlay intOverlay)
|
||||||
|
{
|
||||||
|
if (!Enabled) { return; }
|
||||||
|
if (!intOverlay.GetType().IsAssignableFrom(typeof(WindowOverlay)))
|
||||||
|
{
|
||||||
|
Console.WriteLine("This action cannot be performed on a non-WindowOverlay overlay.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
WindowOverlay overlay = (WindowOverlay)intOverlay;
|
||||||
|
IntPtr handle = overlay.Selector.GetWindowHandle();
|
||||||
|
PreformAction(handle);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void PreformAction(IntPtr handle)
|
||||||
|
{
|
||||||
|
//Make sure window isn't minimized
|
||||||
|
User32.WINDOWPLACEMENT placement = new User32.WINDOWPLACEMENT();
|
||||||
|
placement.Length = Marshal.SizeOf(placement);
|
||||||
|
User32.GetWindowPlacement(handle, ref placement);
|
||||||
|
|
||||||
|
if (placement.ShowCmd == User32.ShowWindowCommands.ShowMinimized)
|
||||||
|
{
|
||||||
|
User32.ShowWindow(handle, User32.ShowWindowCommands.Normal);
|
||||||
|
}
|
||||||
|
|
||||||
|
User32.SetForegroundWindow(handle);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,14 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace VDash.Overlay.Actions
|
||||||
|
{
|
||||||
|
public interface IOverlayAction
|
||||||
|
{
|
||||||
|
void PreformAction(IOverlay overlay);
|
||||||
|
bool Enabled { get; set; }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,34 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using VDash.Utilities;
|
||||||
|
|
||||||
|
namespace VDash.Overlay.Actions
|
||||||
|
{
|
||||||
|
public class MaximizeWindowAction : IOverlayAction
|
||||||
|
{
|
||||||
|
public bool Enabled { get; set; }
|
||||||
|
|
||||||
|
public void PreformAction(IOverlay intOverlay)
|
||||||
|
{
|
||||||
|
if (!Enabled) { return; }
|
||||||
|
if (!intOverlay.GetType().IsAssignableFrom(typeof(WindowOverlay)))
|
||||||
|
{
|
||||||
|
Console.WriteLine("This action cannot be performed on a non-WindowOverlay overlay.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
WindowOverlay overlay = (WindowOverlay)intOverlay;
|
||||||
|
IntPtr handle = overlay.Selector.GetWindowHandle();
|
||||||
|
PreformAction(handle);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void PreformAction(IntPtr handle)
|
||||||
|
{
|
||||||
|
User32.ShowWindow(handle, User32.ShowWindowCommands.Maximize);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,47 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using VDash.Utilities;
|
||||||
|
|
||||||
|
namespace VDash.Overlay.Actions
|
||||||
|
{
|
||||||
|
public class ResizeWindowAction : IOverlayAction
|
||||||
|
{
|
||||||
|
public int NewWidth { get; set; }
|
||||||
|
public int NewHeight { get; set; }
|
||||||
|
public bool Enabled { get; set; }
|
||||||
|
|
||||||
|
public ResizeWindowAction(int newWidth, int newHeight)
|
||||||
|
{
|
||||||
|
NewWidth = newWidth;
|
||||||
|
NewHeight = newHeight;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void PreformAction(IOverlay intOverlay)
|
||||||
|
{
|
||||||
|
if (!Enabled) { return; }
|
||||||
|
if (!intOverlay.GetType().IsAssignableFrom(typeof(WindowOverlay)))
|
||||||
|
{
|
||||||
|
Console.WriteLine("This action cannot be performed on a non-WindowOverlay overlay.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
WindowOverlay overlay = (WindowOverlay)intOverlay;
|
||||||
|
IntPtr handle = overlay.Selector.GetWindowHandle();
|
||||||
|
PreformAction(handle);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void PreformAction(IntPtr handle)
|
||||||
|
{
|
||||||
|
//Retain old rect
|
||||||
|
User32.Rect rect = new User32.Rect();
|
||||||
|
User32.GetWindowRect(handle, ref rect);
|
||||||
|
|
||||||
|
User32.SetWindowPos(handle, IntPtr.Zero, rect.left, rect.bottom, NewWidth, NewHeight, User32.SetWindowPosFlags.DoNotActivate |
|
||||||
|
User32.SetWindowPosFlags.IgnoreMove | User32.SetWindowPosFlags.IgnoreZOrder |
|
||||||
|
User32.SetWindowPosFlags.DoNotChangeOwnerZOrder);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,35 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using VDash.Utilities;
|
||||||
|
|
||||||
|
namespace VDash.Overlay.Actions
|
||||||
|
{
|
||||||
|
public class RestoreWindowAction : IOverlayAction
|
||||||
|
{
|
||||||
|
|
||||||
|
public bool Enabled { get; set; }
|
||||||
|
|
||||||
|
public void PreformAction(IOverlay intOverlay)
|
||||||
|
{
|
||||||
|
if (!Enabled) { return; }
|
||||||
|
if (!intOverlay.GetType().IsAssignableFrom(typeof(WindowOverlay)))
|
||||||
|
{
|
||||||
|
Console.WriteLine("This action cannot be performed on a non-WindowOverlay overlay.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
WindowOverlay overlay = (WindowOverlay)intOverlay;
|
||||||
|
IntPtr handle = overlay.Selector.GetWindowHandle();
|
||||||
|
PreformAction(handle);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void PreformAction(IntPtr handle)
|
||||||
|
{
|
||||||
|
User32.ShowWindow(handle, User32.ShowWindowCommands.Restore);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
@ -1,4 +1,6 @@
|
||||||
using System;
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using VDash.Overlay.Actions;
|
||||||
|
|
||||||
namespace VDash.Overlay
|
namespace VDash.Overlay
|
||||||
{
|
{
|
||||||
|
|
@ -7,13 +9,18 @@ namespace VDash.Overlay
|
||||||
event EventHandler OverlayShown;
|
event EventHandler OverlayShown;
|
||||||
event EventHandler OverlayHidden;
|
event EventHandler OverlayHidden;
|
||||||
|
|
||||||
ulong Handle { get; }
|
List<IOverlayAction> OverlayShownActions { get; }
|
||||||
|
List<IOverlayAction> OverlayHiddenActions { get; }
|
||||||
|
|
||||||
|
ulong OverlayHandle { get; }
|
||||||
string Name { get; }
|
string Name { get; }
|
||||||
string Key { get; }
|
string Key { get; }
|
||||||
|
|
||||||
void Create();
|
void Create();
|
||||||
void Destroy();
|
void Destroy();
|
||||||
string GetOverlayName();
|
string GetOverlayName();
|
||||||
|
float GetOverlayWidth();
|
||||||
|
void SetOverlayWidth(float width);
|
||||||
void SetOverlayName(string newName);
|
void SetOverlayName(string newName);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,7 @@
|
||||||
using SharpDX.Direct3D11;
|
using SharpDX.Direct3D11;
|
||||||
using SharpDX.DXGI;
|
using SharpDX.DXGI;
|
||||||
using System;
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
using System.ComponentModel;
|
using System.ComponentModel;
|
||||||
using System.Drawing;
|
using System.Drawing;
|
||||||
using System.Drawing.Imaging;
|
using System.Drawing.Imaging;
|
||||||
|
|
@ -9,8 +10,12 @@ using System.Runtime.InteropServices;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
using System.Windows.Forms;
|
||||||
using Valve.VR;
|
using Valve.VR;
|
||||||
|
using VDash.Overlay.Actions;
|
||||||
|
using VDash.Utilities;
|
||||||
using VDash.WindowSelectors;
|
using VDash.WindowSelectors;
|
||||||
|
using System.Linq;
|
||||||
|
|
||||||
namespace VDash.Overlay
|
namespace VDash.Overlay
|
||||||
{
|
{
|
||||||
|
|
@ -20,20 +25,21 @@ namespace VDash.Overlay
|
||||||
public event EventHandler OverlayShown;
|
public event EventHandler OverlayShown;
|
||||||
public event EventHandler OverlayHidden;
|
public event EventHandler OverlayHidden;
|
||||||
|
|
||||||
public CVRSystem VRSystem { get; private set; }
|
public bool UpdateDashboardName { get; set; } = false;
|
||||||
|
public bool DestroyOnNoWindowFound { get; set; } = false;
|
||||||
|
public int CurrentFPS { get; private set; }
|
||||||
|
|
||||||
private Task m_EventPumpTask = null;
|
private Task m_EventPumpTask = null;
|
||||||
|
/// <summary>
|
||||||
|
/// Tracks whether or not this overlay is actually created.
|
||||||
|
/// </summary>
|
||||||
bool m_Created = false;
|
bool m_Created = false;
|
||||||
bool m_Running = true;
|
bool m_Running = true;
|
||||||
public bool UpdateDashboardName { get; set; } = false;
|
|
||||||
|
|
||||||
internal ulong m_Handle;
|
internal ulong m_OverlayHandle;
|
||||||
public ulong Handle
|
public ulong OverlayHandle { get { return m_OverlayHandle; } }
|
||||||
{
|
internal ulong m_ThumbnailIcon;
|
||||||
get
|
public ulong ThumbnailIcon { get { return m_ThumbnailIcon; } }
|
||||||
{
|
|
||||||
return m_Handle;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
internal string m_Key;
|
internal string m_Key;
|
||||||
public string Key { get { return m_Key; } }
|
public string Key { get { return m_Key; } }
|
||||||
|
|
@ -41,38 +47,64 @@ namespace VDash.Overlay
|
||||||
internal string m_Name;
|
internal string m_Name;
|
||||||
public string Name { get { return m_Name; } }
|
public string Name { get { return m_Name; } }
|
||||||
|
|
||||||
IWindowSelector m_Selector = null;
|
|
||||||
|
public IWindowSelector Selector { get; private set; } = null;
|
||||||
|
|
||||||
|
public List<IOverlayAction> OverlayShownActions { get; private set; } = new List<IOverlayAction>();
|
||||||
|
public List<IOverlayAction> OverlayHiddenActions { get; private set; } = new List<IOverlayAction>();
|
||||||
|
|
||||||
|
char[] specialKeys = { '+', '^', '%', '~', '(', ')', '{', '}', '[', ']' };
|
||||||
|
|
||||||
public WindowOverlay(string key, string name, IWindowSelector selector, bool updateDashboardName)
|
public WindowOverlay(string key, string name, IWindowSelector selector, bool updateDashboardName)
|
||||||
{
|
{
|
||||||
m_Key = key;
|
m_Key = key;
|
||||||
m_Name = name;
|
m_Name = name;
|
||||||
m_Selector = selector;
|
Selector = selector;
|
||||||
UpdateDashboardName = updateDashboardName;
|
UpdateDashboardName = updateDashboardName;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Represents whether or not an external caller wants this to stay destroyed, really.
|
||||||
|
/// To keep the DestroyOnNoWindowFound stuff in check. Don't want it creating when it shouldn't.
|
||||||
|
/// </summary>
|
||||||
|
bool m_Destroyed = true;
|
||||||
|
|
||||||
public void Create()
|
public void Create()
|
||||||
|
{
|
||||||
|
m_Destroyed = false;
|
||||||
|
createInternal();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void createInternal()
|
||||||
{
|
{
|
||||||
if (m_Created) { throw new Exception("This overlay has already been created."); }
|
if (m_Created) { throw new Exception("This overlay has already been created."); }
|
||||||
//ConsoleManager.Show();
|
|
||||||
ulong thumbHandle = OpenVR.k_ulOverlayHandleInvalid;
|
|
||||||
|
|
||||||
//Actually create the overlay
|
//Actually create the overlay
|
||||||
var overlay = OpenVR.Overlay;
|
var overlay = OpenVR.Overlay;
|
||||||
EVROverlayError err = overlay.CreateDashboardOverlay(m_Key, m_Name, ref m_Handle, ref thumbHandle);
|
EVROverlayError err = overlay.CreateDashboardOverlay(m_Key, m_Name, ref m_OverlayHandle, ref m_ThumbnailIcon);
|
||||||
|
|
||||||
if (err != EVROverlayError.None)
|
if (err != EVROverlayError.None)
|
||||||
{
|
{
|
||||||
throw new Exception($"Error creating overlay: {err}");
|
throw new Exception($"Error creating overlay: {err}");
|
||||||
}
|
}
|
||||||
overlay.SetOverlayInputMethod(m_Handle, VROverlayInputMethod.Mouse);
|
overlay.SetOverlayInputMethod(m_OverlayHandle, VROverlayInputMethod.Mouse);
|
||||||
|
|
||||||
m_Running = true;
|
m_Running = true;
|
||||||
m_EventPumpTask = Task.Factory.StartNew(() => { EventPump(); });
|
m_EventPumpTask = Task.Factory.StartNew(() => { EventPump(); });
|
||||||
m_Created = true;
|
m_Created = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public bool IsCreated() { return m_Created; }
|
||||||
|
|
||||||
|
|
||||||
public void Destroy()
|
public void Destroy()
|
||||||
|
{
|
||||||
|
m_Destroyed = true;
|
||||||
|
destroyInternal();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void destroyInternal()
|
||||||
{
|
{
|
||||||
if (!m_Created) { throw new Exception("This object is not created."); }
|
if (!m_Created) { throw new Exception("This object is not created."); }
|
||||||
m_Created = false;
|
m_Created = false;
|
||||||
|
|
@ -83,19 +115,25 @@ namespace VDash.Overlay
|
||||||
//Wait for render thread to exit
|
//Wait for render thread to exit
|
||||||
m_EventPumpTask.Wait();
|
m_EventPumpTask.Wait();
|
||||||
|
|
||||||
var err = OpenVR.Overlay.DestroyOverlay(m_Handle);
|
var err = OpenVR.Overlay.DestroyOverlay(m_OverlayHandle);
|
||||||
|
|
||||||
if( err != EVROverlayError.None)
|
if( err != EVROverlayError.None)
|
||||||
{
|
{
|
||||||
throw new Exception($"Error destroying overlay: {err}");
|
throw new Exception($"Error destroying overlay: {err}");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
m_OverlayHandle = OpenVR.k_ulOverlayHandleInvalid;
|
||||||
|
m_ThumbnailIcon = OpenVR.k_ulOverlayHandleInvalid;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void EventPump()
|
private void EventPump()
|
||||||
{
|
{
|
||||||
#region Rendering setup
|
|
||||||
var overlay = OpenVR.Overlay;
|
var overlay = OpenVR.Overlay;
|
||||||
|
|
||||||
|
DateTime lastClick = DateTime.MinValue;
|
||||||
|
|
||||||
|
#region Rendering setup
|
||||||
|
|
||||||
//Partially taken from here: https://stackoverflow.com/questions/6812068/c-sharp-which-is-the-fastest-way-to-take-a-screen-shot
|
//Partially taken from here: https://stackoverflow.com/questions/6812068/c-sharp-which-is-the-fastest-way-to-take-a-screen-shot
|
||||||
//Desktop Duplication didn't work well, hence is why we're sticking with GDI. Still this is faster than using SetTextureRaw.
|
//Desktop Duplication didn't work well, hence is why we're sticking with GDI. Still this is faster than using SetTextureRaw.
|
||||||
|
|
||||||
|
|
@ -120,60 +158,107 @@ namespace VDash.Overlay
|
||||||
int frames = 0;
|
int frames = 0;
|
||||||
DateTime lastFps = DateTime.MinValue;
|
DateTime lastFps = DateTime.MinValue;
|
||||||
DateTime lastNameCheck = DateTime.MinValue;
|
DateTime lastNameCheck = DateTime.MinValue;
|
||||||
|
|
||||||
while (m_Running)
|
while (m_Running)
|
||||||
{
|
{
|
||||||
//Update the SteamVR dash name if necessary, only once a second.
|
if (DestroyOnNoWindowFound)
|
||||||
if (UpdateDashboardName && DateTime.Now.Subtract(lastNameCheck).TotalMilliseconds >= 1000)
|
|
||||||
{
|
{
|
||||||
var window = m_Selector.GetWindowInfo();
|
//Check to see if the window actually exists. Act accordingly.
|
||||||
|
if (!Selector.WindowExists())
|
||||||
|
{
|
||||||
|
if (IsCreated())
|
||||||
|
{
|
||||||
|
destroyInternal();
|
||||||
|
Console.WriteLine($"Destroyed {m_Key} because it's window does not exist.");
|
||||||
|
}
|
||||||
|
|
||||||
|
Thread.Sleep(100);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
else if(Selector.WindowExists() && !m_Created && !m_Destroyed)
|
||||||
|
{
|
||||||
|
createInternal();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//This technically should never happen, buuuut...
|
||||||
|
IntPtr windowHandle = IntPtr.Zero;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
windowHandle = Selector.GetWindowHandle();
|
||||||
|
}
|
||||||
|
catch (WindowNotFoundException)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
//Update the SteamVR dash name if necessary, only once a second.
|
||||||
|
if (Selector.WindowExists() && UpdateDashboardName && DateTime.Now.Subtract(lastNameCheck).TotalMilliseconds >= 1000)
|
||||||
|
{
|
||||||
|
var window = Selector.GetWindowInfo();
|
||||||
if(GetOverlayName() != window.Title)
|
if(GetOverlayName() != window.Title)
|
||||||
{
|
{
|
||||||
SetOverlayName(window.Title);
|
SetOverlayName(window.Title);
|
||||||
}
|
}
|
||||||
|
|
||||||
lastNameCheck = DateTime.Now;
|
lastNameCheck = DateTime.Now;
|
||||||
|
|
||||||
|
|
||||||
|
#region Thumbnail rendering
|
||||||
|
using (var icon = User32.GetAppIcon(windowHandle))
|
||||||
|
{
|
||||||
|
using (var iconBmp = icon.ToBitmap())
|
||||||
|
{
|
||||||
|
var data = iconBmp.LockBits(new Rectangle(0, 0, iconBmp.Width, iconBmp.Height), ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb);
|
||||||
|
|
||||||
|
overlay.SetOverlayRaw(m_ThumbnailIcon, data.Scan0, (uint)data.Width, (uint)data.Height, 4);
|
||||||
|
|
||||||
|
iconBmp.UnlockBits(data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
}
|
}
|
||||||
|
|
||||||
//Skip rendering if overlay isn't visible
|
//Skip rendering if overlay isn't visible
|
||||||
#if !DEBUG
|
#if !DEBUG
|
||||||
if ((m_Handle == Openvr.k_uloverlayhandleinvalid) || overlay == null || (!overlay.isoverlayvisible(m_handle)))
|
if ((m_OverlayHandle == OpenVR.k_ulOverlayHandleInvalid) || overlay == null || (!overlay.IsOverlayVisible(m_OverlayHandle)))
|
||||||
{
|
{
|
||||||
thread.sleep(100);
|
Thread.Sleep(100);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
IntPtr windowHandle = IntPtr.Zero;
|
|
||||||
try
|
|
||||||
{
|
|
||||||
windowHandle = m_Selector.GetWindowHandle();
|
|
||||||
}
|
|
||||||
catch (WindowNotFoundException)
|
|
||||||
{
|
|
||||||
//Console.WriteLine($"[{m_Key}] {m_Name}: Window not found.");
|
|
||||||
}
|
|
||||||
|
|
||||||
#region VR Events
|
#region VR Events
|
||||||
VREvent_t vrEvent = new VREvent_t();
|
VREvent_t vrEvent = new VREvent_t();
|
||||||
|
|
||||||
while (OpenVR.Overlay.PollNextOverlayEvent(m_Handle, ref vrEvent, (uint)Marshal.SizeOf(vrEvent)))
|
while (OpenVR.Overlay.PollNextOverlayEvent(m_OverlayHandle, ref vrEvent, (uint)Marshal.SizeOf(vrEvent)))
|
||||||
{
|
{
|
||||||
switch ((EVREventType)vrEvent.eventType)
|
switch ((EVREventType)vrEvent.eventType)
|
||||||
{
|
{
|
||||||
case EVREventType.VREvent_MouseMove:
|
case EVREventType.VREvent_MouseMove:
|
||||||
{
|
{
|
||||||
|
//Prevent the cursor from moving while we click. Super fkn annoying.
|
||||||
|
if(DateTime.Now.Subtract(lastClick).TotalMilliseconds < 400)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
//Make sure the window still exists
|
||||||
if (windowHandle != IntPtr.Zero)
|
if (windowHandle != IntPtr.Zero)
|
||||||
{
|
{
|
||||||
var vrX = vrEvent.data.mouse.x;
|
var vrX = vrEvent.data.mouse.x;
|
||||||
var vrY = vrEvent.data.mouse.y;
|
var vrY = vrEvent.data.mouse.y;
|
||||||
|
|
||||||
var rect = new User32.Rect();
|
var rect = new User32.Rect();
|
||||||
User32.GetWindowRect(windowHandle, ref rect);
|
|
||||||
|
User32.GetClientRect(windowHandle, ref rect);
|
||||||
|
|
||||||
int width = rect.right - rect.left;
|
int width = rect.right - rect.left;
|
||||||
int height = rect.bottom - rect.top;
|
int height = rect.bottom - rect.top;
|
||||||
|
|
||||||
|
var point = new System.Drawing.Point() { X = (int)vrX, Y = height - (int)vrY };
|
||||||
|
|
||||||
|
|
||||||
var point = new User32.POINT() { x = (int)vrX, y = height - (int)vrY };
|
|
||||||
var succ = User32.ClientToScreen(windowHandle, ref point);
|
var succ = User32.ClientToScreen(windowHandle, ref point);
|
||||||
|
|
||||||
if (!succ)
|
if (!succ)
|
||||||
|
|
@ -182,7 +267,7 @@ namespace VDash.Overlay
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
succ = User32.SetCursorPos((int)point.x, (int)point.y);
|
succ = User32.SetCursorPos((int)point.X, (int)point.Y);
|
||||||
|
|
||||||
if (!succ)
|
if (!succ)
|
||||||
{
|
{
|
||||||
|
|
@ -195,7 +280,6 @@ namespace VDash.Overlay
|
||||||
case EVREventType.VREvent_MouseButtonDown:
|
case EVREventType.VREvent_MouseButtonDown:
|
||||||
{
|
{
|
||||||
var clickType = (EVRMouseButton)vrEvent.data.mouse.button;
|
var clickType = (EVRMouseButton)vrEvent.data.mouse.button;
|
||||||
Console.WriteLine($"Mouse button down: {clickType}");
|
|
||||||
|
|
||||||
var winClickType = User32.MouseEventFlags.MOUSEEVENTF_LEFTDOWN;
|
var winClickType = User32.MouseEventFlags.MOUSEEVENTF_LEFTDOWN;
|
||||||
|
|
||||||
|
|
@ -219,13 +303,13 @@ namespace VDash.Overlay
|
||||||
}
|
}
|
||||||
|
|
||||||
User32.mouse_event(winClickType, 0, 0, 0, UIntPtr.Zero);
|
User32.mouse_event(winClickType, 0, 0, 0, UIntPtr.Zero);
|
||||||
|
lastClick = DateTime.Now;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case EVREventType.VREvent_MouseButtonUp:
|
case EVREventType.VREvent_MouseButtonUp:
|
||||||
{
|
{
|
||||||
var clickType = (EVRMouseButton)vrEvent.data.mouse.button;
|
var clickType = (EVRMouseButton)vrEvent.data.mouse.button;
|
||||||
Console.WriteLine($"Mouse button up: {clickType}");
|
|
||||||
var winClickType = User32.MouseEventFlags.MOUSEEVENTF_LEFTUP;
|
var winClickType = User32.MouseEventFlags.MOUSEEVENTF_LEFTUP;
|
||||||
|
|
||||||
switch (clickType)
|
switch (clickType)
|
||||||
|
|
@ -248,16 +332,83 @@ namespace VDash.Overlay
|
||||||
}
|
}
|
||||||
|
|
||||||
User32.mouse_event(winClickType, 0, 0, 0, UIntPtr.Zero);
|
User32.mouse_event(winClickType, 0, 0, 0, UIntPtr.Zero);
|
||||||
|
lastClick = DateTime.MinValue;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case EVREventType.VREvent_OverlayShown:
|
case EVREventType.VREvent_OverlayShown:
|
||||||
{
|
{
|
||||||
OverlayShown?.Invoke(this, new EventArgs());
|
OverlayShown?.Invoke(this, new EventArgs());
|
||||||
|
|
||||||
|
if (Selector.WindowExists())
|
||||||
|
{
|
||||||
|
foreach (var action in OverlayShownActions)
|
||||||
|
{
|
||||||
|
action.PreformAction(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case EVREventType.VREvent_OverlayHidden:
|
case EVREventType.VREvent_OverlayHidden:
|
||||||
{
|
{
|
||||||
OverlayHidden?.Invoke(this, new EventArgs());
|
OverlayHidden?.Invoke(this, new EventArgs());
|
||||||
|
|
||||||
|
if (Selector.WindowExists())
|
||||||
|
{
|
||||||
|
foreach (var action in OverlayHiddenActions)
|
||||||
|
{
|
||||||
|
action.PreformAction(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case EVREventType.VREvent_KeyboardCharInput:
|
||||||
|
{
|
||||||
|
//Console.WriteLine($"Got char input: {vrEvent.data.keyboard.cNewInput}");
|
||||||
|
var input = vrEvent.data.keyboard.cNewInput;
|
||||||
|
|
||||||
|
//We should only be getting one keypress at a time.
|
||||||
|
switch (input)
|
||||||
|
{
|
||||||
|
case "\b":
|
||||||
|
{
|
||||||
|
SendKeys.SendWait("{BACKSPACE}");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case "\n":
|
||||||
|
{
|
||||||
|
SendKeys.SendWait("{ENTER}");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
{
|
||||||
|
if (specialKeys.Contains(input[0]))
|
||||||
|
{
|
||||||
|
SendKeys.SendWait("{" + input + "}");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
SendKeys.SendWait(input);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case EVREventType.VREvent_ButtonPress:
|
||||||
|
{
|
||||||
|
EVRButtonId button = (EVRButtonId)vrEvent.data.controller.button;
|
||||||
|
//Console.WriteLine($"Button pressed: {button}");
|
||||||
|
|
||||||
|
switch (button)
|
||||||
|
{
|
||||||
|
case EVRButtonId.k_EButton_Knuckles_A:
|
||||||
|
{
|
||||||
|
overlay.ShowKeyboardForOverlay(m_OverlayHandle, (int)EGamepadTextInputMode.k_EGamepadTextInputModeNormal,
|
||||||
|
(int)EGamepadTextInputLineMode.k_EGamepadTextInputLineModeSingleLine, "desc?", 1024, "", true, 0);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -265,162 +416,166 @@ namespace VDash.Overlay
|
||||||
}
|
}
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region Acutally Render
|
#region Acutally Render
|
||||||
|
//Redundant check, but w/e
|
||||||
if (windowHandle != IntPtr.Zero)
|
if (Selector.WindowExists() && windowHandle != IntPtr.Zero)
|
||||||
{
|
{
|
||||||
var rect = new User32.Rect();
|
var rect = new User32.Rect();
|
||||||
User32.GetWindowRect(windowHandle, ref rect);
|
User32.GetClientRect(windowHandle, ref rect);
|
||||||
|
System.Drawing.Point pnt = new Point { X = 0, Y = 0 };
|
||||||
|
|
||||||
|
User32.ClientToScreen(windowHandle, ref pnt);
|
||||||
|
|
||||||
int width = rect.right - rect.left;
|
int width = rect.right - rect.left;
|
||||||
int height = rect.bottom - rect.top;
|
int height = rect.bottom - rect.top;
|
||||||
|
|
||||||
|
//Make sure the coords are actually valid. Could be minimized or something.
|
||||||
|
if (width > 0 && height > 0)
|
||||||
using (var bmp = new Bitmap(width, height, PixelFormat.Format32bppArgb))
|
|
||||||
{
|
{
|
||||||
using (Graphics graphics = Graphics.FromImage(bmp))
|
using (var bmp = new Bitmap(width, height, PixelFormat.Format32bppArgb))
|
||||||
{
|
{
|
||||||
graphics.CopyFromScreen(rect.left, rect.top, 0, 0, new Size(width, height), CopyPixelOperation.SourceCopy);
|
using (Graphics graphics = Graphics.FromImage(bmp))
|
||||||
|
|
||||||
//Draw cursor
|
|
||||||
User32.CURSORINFO pci;
|
|
||||||
pci.cbSize = System.Runtime.InteropServices.Marshal.SizeOf(typeof(User32.CURSORINFO));
|
|
||||||
|
|
||||||
if (User32.GetCursorInfo(out pci))
|
|
||||||
{
|
{
|
||||||
|
graphics.CopyFromScreen((int)pnt.X, (int)pnt.Y, 0, 0, new Size(width, height), CopyPixelOperation.SourceCopy);
|
||||||
|
|
||||||
User32.POINT cursorPoint = new User32.POINT() { x = pci.ptScreenPos.X, y = pci.ptScreenPos.Y};
|
#region Cursor drawing
|
||||||
|
User32.CURSORINFO pci;
|
||||||
|
pci.cbSize = System.Runtime.InteropServices.Marshal.SizeOf(typeof(User32.CURSORINFO));
|
||||||
|
|
||||||
if (User32.ScreenToClient(windowHandle, ref cursorPoint))
|
if (User32.GetCursorInfo(out pci))
|
||||||
{
|
{
|
||||||
|
|
||||||
if (pci.flags == User32.CURSOR_SHOWING)
|
System.Drawing.Point cursorPoint = new System.Drawing.Point() { X = pci.ptScreenPos.X, Y = pci.ptScreenPos.Y };
|
||||||
|
|
||||||
|
if (User32.ScreenToClient(windowHandle, ref cursorPoint))
|
||||||
{
|
{
|
||||||
User32.DrawIcon(graphics.GetHdc(), (int)cursorPoint.x, (int)cursorPoint.y, pci.hCursor);
|
|
||||||
graphics.ReleaseHdc();
|
if (pci.flags == User32.CURSOR_SHOWING)
|
||||||
|
{
|
||||||
|
User32.DrawIcon(graphics.GetHdc(), (int)cursorPoint.X, (int)cursorPoint.Y, pci.hCursor);
|
||||||
|
graphics.ReleaseHdc();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Console.WriteLine("Error getting coords to draw cursor.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Console.WriteLine("Error getting coords to draw cursor.");
|
string errorMessage = new Win32Exception(Marshal.GetLastWin32Error()).Message;
|
||||||
|
Console.WriteLine($"Error getting cursor info: {errorMessage}");
|
||||||
}
|
}
|
||||||
}
|
#endregion
|
||||||
else
|
|
||||||
{
|
|
||||||
string errorMessage = new Win32Exception(Marshal.GetLastWin32Error()).Message;
|
|
||||||
Console.WriteLine($"Error getting cursor info: {errorMessage}");
|
|
||||||
}
|
|
||||||
|
|
||||||
|
var data = bmp.LockBits(new Rectangle(0, 0, width, height), ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb);
|
||||||
|
|
||||||
var data = bmp.LockBits(new Rectangle(0, 0, width, height), ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb);
|
if (screenTexture == null || (lastWidth != data.Width || lastHeight != data.Height))
|
||||||
|
|
||||||
|
|
||||||
if (screenTexture == null || (lastWidth != data.Width || lastHeight != data.Height))
|
|
||||||
{
|
|
||||||
lastWidth = data.Width;
|
|
||||||
lastHeight = data.Height;
|
|
||||||
|
|
||||||
if (screenTexture != null)
|
|
||||||
{
|
{
|
||||||
screenTexture.Dispose();
|
lastWidth = data.Width;
|
||||||
|
lastHeight = data.Height;
|
||||||
|
|
||||||
//Dispose not freeing screenTexture: https://gamedev.stackexchange.com/questions/93311/freeing-texture-memory-in-sharpdx-what-am-i-missing
|
if (screenTexture != null)
|
||||||
device.ImmediateContext.ClearState();
|
|
||||||
device.ImmediateContext.Flush();
|
|
||||||
}
|
|
||||||
|
|
||||||
var textureDesc = new Texture2DDescription
|
|
||||||
{
|
|
||||||
CpuAccessFlags = CpuAccessFlags.Write,
|
|
||||||
BindFlags = BindFlags.ShaderResource,
|
|
||||||
Format = Format.B8G8R8A8_UNorm,
|
|
||||||
//Format = Format.B8G8R8A8_UNorm_SRgb,
|
|
||||||
Width = data.Width,
|
|
||||||
Height = data.Height,
|
|
||||||
OptionFlags = ResourceOptionFlags.None,
|
|
||||||
MipLevels = 1,
|
|
||||||
ArraySize = 1,
|
|
||||||
SampleDescription = { Count = 1, Quality = 0 },
|
|
||||||
Usage = ResourceUsage.Dynamic
|
|
||||||
};
|
|
||||||
screenTexture = new Texture2D(device, textureDesc);
|
|
||||||
stream = new DataStream(4 * width * height, true, true);
|
|
||||||
|
|
||||||
overlay.SetOverlayWidthInMeters(m_Handle, 2.5f);
|
|
||||||
|
|
||||||
HmdVector2_t vecWindowSize = new HmdVector2_t() { v0 = width, v1 = height };
|
|
||||||
OpenVR.Overlay.SetOverlayMouseScale(m_Handle, ref vecWindowSize);
|
|
||||||
Console.WriteLine("Updated!");
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
//Render using graphics card, in DirectX context.
|
|
||||||
|
|
||||||
//using ()
|
|
||||||
{
|
|
||||||
var screenView = new ShaderResourceView(device, screenTexture);
|
|
||||||
device.ImmediateContext.PixelShader.SetShaderResource(0, screenView);
|
|
||||||
|
|
||||||
var dr = new SharpDX.DataRectangle(data.Scan0, data.Stride);
|
|
||||||
|
|
||||||
DataBox databox = device.ImmediateContext.MapSubresource(screenTexture, 0, MapMode.WriteDiscard,
|
|
||||||
SharpDX.Direct3D11.MapFlags.None, out stream);
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if (!databox.IsEmpty)
|
|
||||||
{
|
|
||||||
int count = 4 * data.Width * data.Height;
|
|
||||||
|
|
||||||
//Stride compensation. Sometimes the BMP and DX texture strides are different. This fixes it.
|
|
||||||
if (databox.RowPitch == data.Stride)
|
|
||||||
{
|
{
|
||||||
stream.Write(data.Scan0, 0, count);
|
screenTexture.Dispose();
|
||||||
|
|
||||||
|
//Dispose not freeing screenTexture: https://gamedev.stackexchange.com/questions/93311/freeing-texture-memory-in-sharpdx-what-am-i-missing
|
||||||
|
device.ImmediateContext.ClearState();
|
||||||
|
device.ImmediateContext.Flush();
|
||||||
}
|
}
|
||||||
//Truncate the extra BMP bytes.
|
|
||||||
else if (databox.RowPitch < data.Stride)
|
var textureDesc = new Texture2DDescription
|
||||||
{
|
{
|
||||||
for (int i = 0; i < data.Height; i++)
|
CpuAccessFlags = CpuAccessFlags.Write,
|
||||||
|
BindFlags = BindFlags.ShaderResource,
|
||||||
|
Format = Format.B8G8R8A8_UNorm,
|
||||||
|
//Format = Format.B8G8R8A8_UNorm_SRgb,
|
||||||
|
Width = data.Width,
|
||||||
|
Height = data.Height,
|
||||||
|
OptionFlags = ResourceOptionFlags.None,
|
||||||
|
MipLevels = 1,
|
||||||
|
ArraySize = 1,
|
||||||
|
SampleDescription = { Count = 1, Quality = 0 },
|
||||||
|
Usage = ResourceUsage.Dynamic
|
||||||
|
};
|
||||||
|
screenTexture = new Texture2D(device, textureDesc);
|
||||||
|
stream = new DataStream(4 * width * height, true, true);
|
||||||
|
|
||||||
|
overlay.SetOverlayWidthInMeters(m_OverlayHandle, 2.5f);
|
||||||
|
|
||||||
|
HmdVector2_t vecWindowSize = new HmdVector2_t() { v0 = data.Width, v1 = data.Height };
|
||||||
|
OpenVR.Overlay.SetOverlayMouseScale(m_OverlayHandle, ref vecWindowSize);
|
||||||
|
Console.WriteLine("Updated!");
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
//Render using graphics card, in DirectX context.
|
||||||
|
|
||||||
|
//using ()
|
||||||
|
{
|
||||||
|
var screenView = new ShaderResourceView(device, screenTexture);
|
||||||
|
device.ImmediateContext.PixelShader.SetShaderResource(0, screenView);
|
||||||
|
|
||||||
|
var dr = new SharpDX.DataRectangle(data.Scan0, data.Stride);
|
||||||
|
|
||||||
|
DataBox databox = device.ImmediateContext.MapSubresource(screenTexture, 0, MapMode.WriteDiscard,
|
||||||
|
SharpDX.Direct3D11.MapFlags.None, out stream);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
if (!databox.IsEmpty)
|
||||||
|
{
|
||||||
|
int count = 4 * data.Width * data.Height;
|
||||||
|
|
||||||
|
//Stride compensation. Sometimes the BMP and DX texture strides are different. This fixes it.
|
||||||
|
if (databox.RowPitch == data.Stride)
|
||||||
{
|
{
|
||||||
stream.Write(data.Scan0, (data.Stride * i), databox.RowPitch);
|
stream.Write(data.Scan0, 0, count);
|
||||||
|
}
|
||||||
|
//Truncate the extra BMP bytes.
|
||||||
|
else if (databox.RowPitch < data.Stride)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < data.Height; i++)
|
||||||
|
{
|
||||||
|
stream.Write(data.Scan0, (data.Stride * i), databox.RowPitch);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//Add some junk on empty bytes on the end to make everyone happy.
|
||||||
|
else if (databox.RowPitch > data.Stride)
|
||||||
|
{
|
||||||
|
int difference = databox.RowPitch - data.Stride;
|
||||||
|
byte[] junk = new byte[difference];
|
||||||
|
for (int i = 0; i < data.Height; i++)
|
||||||
|
{
|
||||||
|
stream.Write(data.Scan0, (data.Stride * i), data.Stride);
|
||||||
|
stream.Write(junk, 0, difference);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//Add some junk on empty bytes on the end to make everyone happy.
|
|
||||||
else if(databox.RowPitch > data.Stride)
|
|
||||||
|
VRTextureBounds_t bounds = new VRTextureBounds_t();
|
||||||
|
OpenVR.Overlay.GetOverlayTextureBounds(m_OverlayHandle, ref bounds);
|
||||||
|
|
||||||
|
var texture = new Texture_t();
|
||||||
|
texture.handle = screenTexture.NativePointer;
|
||||||
|
texture.eType = ETextureType.DirectX;
|
||||||
|
texture.eColorSpace = EColorSpace.Auto;
|
||||||
|
EVROverlayError result = overlay.SetOverlayTexture(m_OverlayHandle, ref texture);
|
||||||
|
if (result != EVROverlayError.None)
|
||||||
{
|
{
|
||||||
int difference = databox.RowPitch - data.Stride;
|
|
||||||
byte[] junk = new byte[difference];
|
Console.WriteLine($"Error rendering: {result}");
|
||||||
for (int i = 0; i < data.Height; i++)
|
|
||||||
{
|
|
||||||
stream.Write(data.Scan0, (data.Stride * i), data.Stride);
|
|
||||||
stream.Write(junk, 0, difference);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
device.ImmediateContext.UnmapSubresource(screenTexture, 0);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
frames++;
|
||||||
|
|
||||||
|
bmp.UnlockBits(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
VRTextureBounds_t bounds = new VRTextureBounds_t();
|
|
||||||
OpenVR.Overlay.GetOverlayTextureBounds(m_Handle, ref bounds);
|
|
||||||
|
|
||||||
var texture = new Texture_t();
|
|
||||||
texture.handle = screenTexture.NativePointer;
|
|
||||||
texture.eType = ETextureType.DirectX;
|
|
||||||
texture.eColorSpace = EColorSpace.Auto;
|
|
||||||
EVROverlayError result = overlay.SetOverlayTexture(m_Handle, ref texture);
|
|
||||||
if (result != EVROverlayError.None)
|
|
||||||
{
|
|
||||||
|
|
||||||
Console.WriteLine($"Error rendering: {result}");
|
|
||||||
}
|
|
||||||
|
|
||||||
device.ImmediateContext.UnmapSubresource(screenTexture, 0);
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
frames++;
|
|
||||||
|
|
||||||
bmp.UnlockBits(data);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -432,83 +587,24 @@ namespace VDash.Overlay
|
||||||
if (DateTime.Now.Subtract(lastFps).TotalMilliseconds > 1000)
|
if (DateTime.Now.Subtract(lastFps).TotalMilliseconds > 1000)
|
||||||
{
|
{
|
||||||
//Console.WriteLine($"{frames} fps.");
|
//Console.WriteLine($"{frames} fps.");
|
||||||
|
CurrentFPS = frames;
|
||||||
frames = 0;
|
frames = 0;
|
||||||
lastFps = DateTime.Now;
|
lastFps = DateTime.Now;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//Clean up after we exit while loop.
|
//Clean up after we exit while loop.
|
||||||
|
screenTexture.Dispose();
|
||||||
|
device.ImmediateContext.ClearState();
|
||||||
|
device.ImmediateContext.Flush();
|
||||||
|
|
||||||
|
CurrentFPS = 0;
|
||||||
|
|
||||||
device.Dispose();
|
device.Dispose();
|
||||||
adapter.Dispose();
|
adapter.Dispose();
|
||||||
factory.Dispose();
|
factory.Dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
private class User32
|
|
||||||
{
|
|
||||||
[StructLayout(LayoutKind.Sequential)]
|
|
||||||
public struct Rect
|
|
||||||
{
|
|
||||||
public int left;
|
|
||||||
public int top;
|
|
||||||
public int right;
|
|
||||||
public int bottom;
|
|
||||||
}
|
|
||||||
|
|
||||||
[StructLayout(LayoutKind.Sequential)]
|
|
||||||
public struct POINT
|
|
||||||
{
|
|
||||||
public long x;
|
|
||||||
public long y;
|
|
||||||
}
|
|
||||||
|
|
||||||
[StructLayout(LayoutKind.Sequential)]
|
|
||||||
public struct CURSORINFO
|
|
||||||
{
|
|
||||||
public Int32 cbSize;
|
|
||||||
public Int32 flags;
|
|
||||||
public IntPtr hCursor;
|
|
||||||
public Point ptScreenPos;
|
|
||||||
}
|
|
||||||
public const Int32 CURSOR_SHOWING = 0x00000001;
|
|
||||||
|
|
||||||
[DllImport("user32.dll")]
|
|
||||||
public static extern IntPtr GetWindowRect(IntPtr hWnd, ref Rect rect);
|
|
||||||
|
|
||||||
[DllImport("user32.dll")]
|
|
||||||
[return: MarshalAs(UnmanagedType.Bool)]
|
|
||||||
public static extern bool SetCursorPos(int x, int y);
|
|
||||||
|
|
||||||
[DllImport("user32.dll")]
|
|
||||||
public static extern bool ClientToScreen(IntPtr hwnd, ref POINT lpPoint);
|
|
||||||
|
|
||||||
[DllImport("user32.dll")]
|
|
||||||
public static extern bool ScreenToClient(IntPtr hWnd, ref POINT lpPoint);
|
|
||||||
|
|
||||||
[DllImport("user32.dll")]
|
|
||||||
public static extern bool GetCursorInfo(out CURSORINFO pci);
|
|
||||||
|
|
||||||
[DllImport("user32.dll")]
|
|
||||||
public static extern bool DrawIcon(IntPtr hDC, int X, int Y, IntPtr hIcon);
|
|
||||||
|
|
||||||
[DllImport("user32.dll")]
|
|
||||||
public static extern void mouse_event(MouseEventFlags dwFlags, int dx, int dy, uint dwData, UIntPtr dwExtraInfo);
|
|
||||||
public enum MouseEventFlags
|
|
||||||
{
|
|
||||||
MOUSEEVENTF_ABSOLUTE = 0x8000,
|
|
||||||
MOUSEEVENTF_LEFTDOWN = 0x0002,
|
|
||||||
MOUSEEVENTF_LEFTUP = 0x0004,
|
|
||||||
MOUSEEVENTF_MIDDLEDOWN = 0x0020,
|
|
||||||
MOUSEEVENTF_MIDDLEUP = 0x0040,
|
|
||||||
MOUSEEVENTF_MOVE = 0x0001,
|
|
||||||
MOUSEEVENTF_RIGHTDOWN = 0x0008,
|
|
||||||
MOUSEEVENTF_RIGHTUP = 0x0010,
|
|
||||||
MOUSEEVENTF_XDOWN = 0x0080,
|
|
||||||
MOUSEEVENTF_XUP = 0x0100,
|
|
||||||
MOUSEEVENTF_WHEEL = 0x0800,
|
|
||||||
MOUSEEVENTF_HWHEEL = 0x01000
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Dispose()
|
public void Dispose()
|
||||||
{
|
{
|
||||||
Destroy();
|
Destroy();
|
||||||
|
|
@ -518,14 +614,26 @@ namespace VDash.Overlay
|
||||||
{
|
{
|
||||||
EVROverlayError err = EVROverlayError.None;
|
EVROverlayError err = EVROverlayError.None;
|
||||||
StringBuilder sb = new StringBuilder(255);
|
StringBuilder sb = new StringBuilder(255);
|
||||||
uint res = OpenVR.Overlay.GetOverlayName(m_Handle, sb, 255, ref err);
|
uint res = OpenVR.Overlay.GetOverlayName(m_OverlayHandle, sb, 255, ref err);
|
||||||
return sb.ToString();
|
return sb.ToString();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void SetOverlayName(string newName)
|
public void SetOverlayName(string newName)
|
||||||
{
|
{
|
||||||
OpenVR.Overlay.SetOverlayName(m_Handle, newName);
|
OpenVR.Overlay.SetOverlayName(m_OverlayHandle, newName);
|
||||||
m_Name = newName;
|
m_Name = newName;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public float GetOverlayWidth()
|
||||||
|
{
|
||||||
|
float width = 0f;
|
||||||
|
OpenVR.Overlay.GetOverlayWidthInMeters(m_OverlayHandle, ref width);
|
||||||
|
return width;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SetOverlayWidth(float width)
|
||||||
|
{
|
||||||
|
OpenVR.Overlay.SetOverlayWidthInMeters(m_OverlayHandle, width);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,98 @@
|
||||||
|
using System;
|
||||||
|
using System.Diagnostics;
|
||||||
|
using System.IO;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
using System.Security;
|
||||||
|
|
||||||
|
[SuppressUnmanagedCodeSecurity]
|
||||||
|
public static class ConsoleManager
|
||||||
|
{
|
||||||
|
private const string Kernel32_DllName = "kernel32.dll";
|
||||||
|
|
||||||
|
[DllImport(Kernel32_DllName)]
|
||||||
|
private static extern bool AllocConsole();
|
||||||
|
|
||||||
|
[DllImport(Kernel32_DllName)]
|
||||||
|
private static extern bool FreeConsole();
|
||||||
|
|
||||||
|
[DllImport(Kernel32_DllName)]
|
||||||
|
private static extern IntPtr GetConsoleWindow();
|
||||||
|
|
||||||
|
[DllImport(Kernel32_DllName)]
|
||||||
|
private static extern int GetConsoleOutputCP();
|
||||||
|
|
||||||
|
public static bool HasConsole
|
||||||
|
{
|
||||||
|
get { return GetConsoleWindow() != IntPtr.Zero; }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Creates a new console instance if the process is not attached to a console already.
|
||||||
|
/// </summary>
|
||||||
|
public static void Show()
|
||||||
|
{
|
||||||
|
//#if DEBUG
|
||||||
|
if (!HasConsole)
|
||||||
|
{
|
||||||
|
AllocConsole();
|
||||||
|
InvalidateOutAndError();
|
||||||
|
}
|
||||||
|
//#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// If the process has a console attached to it, it will be detached and no longer visible. Writing to the System.Console is still possible, but no output will be shown.
|
||||||
|
/// </summary>
|
||||||
|
public static void Hide()
|
||||||
|
{
|
||||||
|
//#if DEBUG
|
||||||
|
if (HasConsole)
|
||||||
|
{
|
||||||
|
SetOutAndErrorNull();
|
||||||
|
FreeConsole();
|
||||||
|
}
|
||||||
|
//#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void Toggle()
|
||||||
|
{
|
||||||
|
if (HasConsole)
|
||||||
|
{
|
||||||
|
Hide();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Show();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void InvalidateOutAndError()
|
||||||
|
{
|
||||||
|
Type type = typeof(System.Console);
|
||||||
|
|
||||||
|
System.Reflection.FieldInfo _out = type.GetField("_out",
|
||||||
|
System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.NonPublic);
|
||||||
|
|
||||||
|
System.Reflection.FieldInfo _error = type.GetField("_error",
|
||||||
|
System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.NonPublic);
|
||||||
|
|
||||||
|
System.Reflection.MethodInfo _InitializeStdOutError = type.GetMethod("InitializeStdOutError",
|
||||||
|
System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.NonPublic);
|
||||||
|
|
||||||
|
Debug.Assert(_out != null);
|
||||||
|
Debug.Assert(_error != null);
|
||||||
|
|
||||||
|
Debug.Assert(_InitializeStdOutError != null);
|
||||||
|
|
||||||
|
_out.SetValue(null, null);
|
||||||
|
_error.SetValue(null, null);
|
||||||
|
|
||||||
|
_InitializeStdOutError.Invoke(null, new object[] { true });
|
||||||
|
}
|
||||||
|
|
||||||
|
static void SetOutAndErrorNull()
|
||||||
|
{
|
||||||
|
Console.SetOut(TextWriter.Null);
|
||||||
|
Console.SetError(TextWriter.Null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,596 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Drawing;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace VDash.Utilities
|
||||||
|
{
|
||||||
|
|
||||||
|
public class User32
|
||||||
|
{
|
||||||
|
[StructLayout(LayoutKind.Sequential)]
|
||||||
|
public struct Rect
|
||||||
|
{
|
||||||
|
public int left;
|
||||||
|
public int top;
|
||||||
|
public int right;
|
||||||
|
public int bottom;
|
||||||
|
}
|
||||||
|
|
||||||
|
[StructLayout(LayoutKind.Sequential)]
|
||||||
|
public struct CURSORINFO
|
||||||
|
{
|
||||||
|
public Int32 cbSize;
|
||||||
|
public Int32 flags;
|
||||||
|
public IntPtr hCursor;
|
||||||
|
public Point ptScreenPos;
|
||||||
|
}
|
||||||
|
public const Int32 CURSOR_SHOWING = 0x00000001;
|
||||||
|
|
||||||
|
[DllImport("user32.dll")]
|
||||||
|
public static extern IntPtr GetWindowRect(IntPtr hWnd, ref Rect rect);
|
||||||
|
|
||||||
|
[DllImport("user32.dll")]
|
||||||
|
public static extern bool GetClientRect(IntPtr hWnd, ref Rect lpRect);
|
||||||
|
|
||||||
|
[DllImport("user32.dll")]
|
||||||
|
[return: MarshalAs(UnmanagedType.Bool)]
|
||||||
|
public static extern bool SetCursorPos(int x, int y);
|
||||||
|
|
||||||
|
[DllImport("user32.dll")]
|
||||||
|
public static extern bool ClientToScreen(IntPtr hwnd, ref System.Drawing.Point lpPoint);
|
||||||
|
|
||||||
|
[DllImport("user32.dll")]
|
||||||
|
public static extern bool ScreenToClient(IntPtr hWnd, ref System.Drawing.Point lpPoint);
|
||||||
|
|
||||||
|
[DllImport("user32.dll")]
|
||||||
|
public static extern bool GetCursorInfo(out CURSORINFO pci);
|
||||||
|
|
||||||
|
[DllImport("user32.dll")]
|
||||||
|
public static extern bool DrawIcon(IntPtr hDC, int X, int Y, IntPtr hIcon);
|
||||||
|
|
||||||
|
[DllImport("user32.dll")]
|
||||||
|
public static extern void mouse_event(MouseEventFlags dwFlags, int dx, int dy, uint dwData, UIntPtr dwExtraInfo);
|
||||||
|
public enum MouseEventFlags
|
||||||
|
{
|
||||||
|
MOUSEEVENTF_ABSOLUTE = 0x8000,
|
||||||
|
MOUSEEVENTF_LEFTDOWN = 0x0002,
|
||||||
|
MOUSEEVENTF_LEFTUP = 0x0004,
|
||||||
|
MOUSEEVENTF_MIDDLEDOWN = 0x0020,
|
||||||
|
MOUSEEVENTF_MIDDLEUP = 0x0040,
|
||||||
|
MOUSEEVENTF_MOVE = 0x0001,
|
||||||
|
MOUSEEVENTF_RIGHTDOWN = 0x0008,
|
||||||
|
MOUSEEVENTF_RIGHTUP = 0x0010,
|
||||||
|
MOUSEEVENTF_XDOWN = 0x0080,
|
||||||
|
MOUSEEVENTF_XUP = 0x0100,
|
||||||
|
MOUSEEVENTF_WHEEL = 0x0800,
|
||||||
|
MOUSEEVENTF_HWHEEL = 0x01000
|
||||||
|
}
|
||||||
|
|
||||||
|
public const int GCL_HICONSM = -34;
|
||||||
|
public const int GCL_HICON = -14;
|
||||||
|
|
||||||
|
public const int ICON_SMALL = 0;
|
||||||
|
public const int ICON_BIG = 1;
|
||||||
|
public const int ICON_SMALL2 = 2;
|
||||||
|
|
||||||
|
public const int WM_GETICON = 0x7F;
|
||||||
|
|
||||||
|
public static IntPtr GetClassLongPtr(IntPtr hWnd, int nIndex)
|
||||||
|
{
|
||||||
|
if (IntPtr.Size > 4)
|
||||||
|
return GetClassLongPtr64(hWnd, nIndex);
|
||||||
|
else
|
||||||
|
return new IntPtr(GetClassLongPtr32(hWnd, nIndex));
|
||||||
|
}
|
||||||
|
|
||||||
|
[DllImport("user32.dll", EntryPoint = "GetClassLong")]
|
||||||
|
public static extern uint GetClassLongPtr32(IntPtr hWnd, int nIndex);
|
||||||
|
|
||||||
|
[DllImport("user32.dll", EntryPoint = "GetClassLongPtr")]
|
||||||
|
public static extern IntPtr GetClassLongPtr64(IntPtr hWnd, int nIndex);
|
||||||
|
|
||||||
|
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = false)]
|
||||||
|
static extern IntPtr SendMessage(IntPtr hWnd, int Msg, int wParam, int lParam);
|
||||||
|
|
||||||
|
public static Icon GetAppIcon(IntPtr hwnd)
|
||||||
|
{
|
||||||
|
IntPtr iconHandle = SendMessage(hwnd, WM_GETICON, ICON_SMALL2, 0);
|
||||||
|
if (iconHandle == IntPtr.Zero)
|
||||||
|
iconHandle = SendMessage(hwnd, WM_GETICON, ICON_SMALL, 0);
|
||||||
|
if (iconHandle == IntPtr.Zero)
|
||||||
|
iconHandle = SendMessage(hwnd, WM_GETICON, ICON_BIG, 0);
|
||||||
|
if (iconHandle == IntPtr.Zero)
|
||||||
|
iconHandle = GetClassLongPtr(hwnd, GCL_HICON);
|
||||||
|
if (iconHandle == IntPtr.Zero)
|
||||||
|
iconHandle = GetClassLongPtr(hwnd, GCL_HICONSM);
|
||||||
|
|
||||||
|
if (iconHandle == IntPtr.Zero)
|
||||||
|
return null;
|
||||||
|
|
||||||
|
Icon icn = Icon.FromHandle(iconHandle);
|
||||||
|
|
||||||
|
return icn;
|
||||||
|
}
|
||||||
|
|
||||||
|
[Flags()]
|
||||||
|
public enum SetWindowPosFlags : uint
|
||||||
|
{
|
||||||
|
/// <summary>If the calling thread and the thread that owns the window are attached to different input queues,
|
||||||
|
/// the system posts the request to the thread that owns the window. This prevents the calling thread from
|
||||||
|
/// blocking its execution while other threads process the request.</summary>
|
||||||
|
/// <remarks>SWP_ASYNCWINDOWPOS</remarks>
|
||||||
|
AsynchronousWindowPosition = 0x4000,
|
||||||
|
/// <summary>Prevents generation of the WM_SYNCPAINT message.</summary>
|
||||||
|
/// <remarks>SWP_DEFERERASE</remarks>
|
||||||
|
DeferErase = 0x2000,
|
||||||
|
/// <summary>Draws a frame (defined in the window's class description) around the window.</summary>
|
||||||
|
/// <remarks>SWP_DRAWFRAME</remarks>
|
||||||
|
DrawFrame = 0x0020,
|
||||||
|
/// <summary>Applies new frame styles set using the SetWindowLong function. Sends a WM_NCCALCSIZE message to
|
||||||
|
/// the window, even if the window's size is not being changed. If this flag is not specified, WM_NCCALCSIZE
|
||||||
|
/// is sent only when the window's size is being changed.</summary>
|
||||||
|
/// <remarks>SWP_FRAMECHANGED</remarks>
|
||||||
|
FrameChanged = 0x0020,
|
||||||
|
/// <summary>Hides the window.</summary>
|
||||||
|
/// <remarks>SWP_HIDEWINDOW</remarks>
|
||||||
|
HideWindow = 0x0080,
|
||||||
|
/// <summary>Does not activate the window. If this flag is not set, the window is activated and moved to the
|
||||||
|
/// top of either the topmost or non-topmost group (depending on the setting of the hWndInsertAfter
|
||||||
|
/// parameter).</summary>
|
||||||
|
/// <remarks>SWP_NOACTIVATE</remarks>
|
||||||
|
DoNotActivate = 0x0010,
|
||||||
|
/// <summary>Discards the entire contents of the client area. If this flag is not specified, the valid
|
||||||
|
/// contents of the client area are saved and copied back into the client area after the window is sized or
|
||||||
|
/// repositioned.</summary>
|
||||||
|
/// <remarks>SWP_NOCOPYBITS</remarks>
|
||||||
|
DoNotCopyBits = 0x0100,
|
||||||
|
/// <summary>Retains the current position (ignores X and Y parameters).</summary>
|
||||||
|
/// <remarks>SWP_NOMOVE</remarks>
|
||||||
|
IgnoreMove = 0x0002,
|
||||||
|
/// <summary>Does not change the owner window's position in the Z order.</summary>
|
||||||
|
/// <remarks>SWP_NOOWNERZORDER</remarks>
|
||||||
|
DoNotChangeOwnerZOrder = 0x0200,
|
||||||
|
/// <summary>Does not redraw changes. If this flag is set, no repainting of any kind occurs. This applies to
|
||||||
|
/// the client area, the nonclient area (including the title bar and scroll bars), and any part of the parent
|
||||||
|
/// window uncovered as a result of the window being moved. When this flag is set, the application must
|
||||||
|
/// explicitly invalidate or redraw any parts of the window and parent window that need redrawing.</summary>
|
||||||
|
/// <remarks>SWP_NOREDRAW</remarks>
|
||||||
|
DoNotRedraw = 0x0008,
|
||||||
|
/// <summary>Same as the SWP_NOOWNERZORDER flag.</summary>
|
||||||
|
/// <remarks>SWP_NOREPOSITION</remarks>
|
||||||
|
DoNotReposition = 0x0200,
|
||||||
|
/// <summary>Prevents the window from receiving the WM_WINDOWPOSCHANGING message.</summary>
|
||||||
|
/// <remarks>SWP_NOSENDCHANGING</remarks>
|
||||||
|
DoNotSendChangingEvent = 0x0400,
|
||||||
|
/// <summary>Retains the current size (ignores the cx and cy parameters).</summary>
|
||||||
|
/// <remarks>SWP_NOSIZE</remarks>
|
||||||
|
IgnoreResize = 0x0001,
|
||||||
|
/// <summary>Retains the current Z order (ignores the hWndInsertAfter parameter).</summary>
|
||||||
|
/// <remarks>SWP_NOZORDER</remarks>
|
||||||
|
IgnoreZOrder = 0x0004,
|
||||||
|
/// <summary>Displays the window.</summary>
|
||||||
|
/// <remarks>SWP_SHOWWINDOW</remarks>
|
||||||
|
ShowWindow = 0x0040,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Changes the size, position, and Z order of a child, pop-up, or top-level window. These windows are ordered
|
||||||
|
/// according to their appearance on the screen. The topmost window receives the highest rank and is the first window
|
||||||
|
/// in the Z order.
|
||||||
|
/// <para>See https://msdn.microsoft.com/en-us/library/windows/desktop/ms633545%28v=vs.85%29.aspx for more information.</para>
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="hWnd">C++ ( hWnd [in]. Type: HWND )<br />A handle to the window.</param>
|
||||||
|
/// <param name="hWndInsertAfter">
|
||||||
|
/// C++ ( hWndInsertAfter [in, optional]. Type: HWND )<br />A handle to the window to precede the positioned window in
|
||||||
|
/// the Z order. This parameter must be a window handle or one of the following values.
|
||||||
|
/// <list type="table">
|
||||||
|
/// <itemheader>
|
||||||
|
/// <term>HWND placement</term><description>Window to precede placement</description>
|
||||||
|
/// </itemheader>
|
||||||
|
/// <item>
|
||||||
|
/// <term>HWND_BOTTOM ((HWND)1)</term>
|
||||||
|
/// <description>
|
||||||
|
/// Places the window at the bottom of the Z order. If the hWnd parameter identifies a topmost
|
||||||
|
/// window, the window loses its topmost status and is placed at the bottom of all other windows.
|
||||||
|
/// </description>
|
||||||
|
/// </item>
|
||||||
|
/// <item>
|
||||||
|
/// <term>HWND_NOTOPMOST ((HWND)-2)</term>
|
||||||
|
/// <description>
|
||||||
|
/// Places the window above all non-topmost windows (that is, behind all topmost windows). This
|
||||||
|
/// flag has no effect if the window is already a non-topmost window.
|
||||||
|
/// </description>
|
||||||
|
/// </item>
|
||||||
|
/// <item>
|
||||||
|
/// <term>HWND_TOP ((HWND)0)</term><description>Places the window at the top of the Z order.</description>
|
||||||
|
/// </item>
|
||||||
|
/// <item>
|
||||||
|
/// <term>HWND_TOPMOST ((HWND)-1)</term>
|
||||||
|
/// <description>
|
||||||
|
/// Places the window above all non-topmost windows. The window maintains its topmost position
|
||||||
|
/// even when it is deactivated.
|
||||||
|
/// </description>
|
||||||
|
/// </item>
|
||||||
|
/// </list>
|
||||||
|
/// <para>For more information about how this parameter is used, see the following Remarks section.</para>
|
||||||
|
/// </param>
|
||||||
|
/// <param name="X">C++ ( X [in]. Type: int )<br />The new position of the left side of the window, in client coordinates.</param>
|
||||||
|
/// <param name="Y">C++ ( Y [in]. Type: int )<br />The new position of the top of the window, in client coordinates.</param>
|
||||||
|
/// <param name="cx">C++ ( cx [in]. Type: int )<br />The new width of the window, in pixels.</param>
|
||||||
|
/// <param name="cy">C++ ( cy [in]. Type: int )<br />The new height of the window, in pixels.</param>
|
||||||
|
/// <param name="uFlags">
|
||||||
|
/// C++ ( uFlags [in]. Type: UINT )<br />The window sizing and positioning flags. This parameter can be a combination
|
||||||
|
/// of the following values.
|
||||||
|
/// <list type="table">
|
||||||
|
/// <itemheader>
|
||||||
|
/// <term>HWND sizing and positioning flags</term>
|
||||||
|
/// <description>Where to place and size window. Can be a combination of any</description>
|
||||||
|
/// </itemheader>
|
||||||
|
/// <item>
|
||||||
|
/// <term>SWP_ASYNCWINDOWPOS (0x4000)</term>
|
||||||
|
/// <description>
|
||||||
|
/// If the calling thread and the thread that owns the window are attached to different input
|
||||||
|
/// queues, the system posts the request to the thread that owns the window. This prevents the calling
|
||||||
|
/// thread from blocking its execution while other threads process the request.
|
||||||
|
/// </description>
|
||||||
|
/// </item>
|
||||||
|
/// <item>
|
||||||
|
/// <term>SWP_DEFERERASE (0x2000)</term>
|
||||||
|
/// <description>Prevents generation of the WM_SYNCPAINT message. </description>
|
||||||
|
/// </item>
|
||||||
|
/// <item>
|
||||||
|
/// <term>SWP_DRAWFRAME (0x0020)</term>
|
||||||
|
/// <description>Draws a frame (defined in the window's class description) around the window.</description>
|
||||||
|
/// </item>
|
||||||
|
/// <item>
|
||||||
|
/// <term>SWP_FRAMECHANGED (0x0020)</term>
|
||||||
|
/// <description>
|
||||||
|
/// Applies new frame styles set using the SetWindowLong function. Sends a WM_NCCALCSIZE message
|
||||||
|
/// to the window, even if the window's size is not being changed. If this flag is not specified,
|
||||||
|
/// WM_NCCALCSIZE is sent only when the window's size is being changed
|
||||||
|
/// </description>
|
||||||
|
/// </item>
|
||||||
|
/// <item>
|
||||||
|
/// <term>SWP_HIDEWINDOW (0x0080)</term><description>Hides the window.</description>
|
||||||
|
/// </item>
|
||||||
|
/// <item>
|
||||||
|
/// <term>SWP_NOACTIVATE (0x0010)</term>
|
||||||
|
/// <description>
|
||||||
|
/// Does not activate the window. If this flag is not set, the window is activated and moved to
|
||||||
|
/// the top of either the topmost or non-topmost group (depending on the setting of the hWndInsertAfter
|
||||||
|
/// parameter).
|
||||||
|
/// </description>
|
||||||
|
/// </item>
|
||||||
|
/// <item>
|
||||||
|
/// <term>SWP_NOCOPYBITS (0x0100)</term>
|
||||||
|
/// <description>
|
||||||
|
/// Discards the entire contents of the client area. If this flag is not specified, the valid
|
||||||
|
/// contents of the client area are saved and copied back into the client area after the window is sized or
|
||||||
|
/// repositioned.
|
||||||
|
/// </description>
|
||||||
|
/// </item>
|
||||||
|
/// <item>
|
||||||
|
/// <term>SWP_NOMOVE (0x0002)</term>
|
||||||
|
/// <description>Retains the current position (ignores X and Y parameters).</description>
|
||||||
|
/// </item>
|
||||||
|
/// <item>
|
||||||
|
/// <term>SWP_NOOWNERZORDER (0x0200)</term>
|
||||||
|
/// <description>Does not change the owner window's position in the Z order.</description>
|
||||||
|
/// </item>
|
||||||
|
/// <item>
|
||||||
|
/// <term>SWP_NOREDRAW (0x0008)</term>
|
||||||
|
/// <description>
|
||||||
|
/// Does not redraw changes. If this flag is set, no repainting of any kind occurs. This applies
|
||||||
|
/// to the client area, the nonclient area (including the title bar and scroll bars), and any part of the
|
||||||
|
/// parent window uncovered as a result of the window being moved. When this flag is set, the application
|
||||||
|
/// must explicitly invalidate or redraw any parts of the window and parent window that need redrawing.
|
||||||
|
/// </description>
|
||||||
|
/// </item>
|
||||||
|
/// <item>
|
||||||
|
/// <term>SWP_NOREPOSITION (0x0200)</term><description>Same as the SWP_NOOWNERZORDER flag.</description>
|
||||||
|
/// </item>
|
||||||
|
/// <item>
|
||||||
|
/// <term>SWP_NOSENDCHANGING (0x0400)</term>
|
||||||
|
/// <description>Prevents the window from receiving the WM_WINDOWPOSCHANGING message.</description>
|
||||||
|
/// </item>
|
||||||
|
/// <item>
|
||||||
|
/// <term>SWP_NOSIZE (0x0001)</term>
|
||||||
|
/// <description>Retains the current size (ignores the cx and cy parameters).</description>
|
||||||
|
/// </item>
|
||||||
|
/// <item>
|
||||||
|
/// <term>SWP_NOZORDER (0x0004)</term>
|
||||||
|
/// <description>Retains the current Z order (ignores the hWndInsertAfter parameter).</description>
|
||||||
|
/// </item>
|
||||||
|
/// <item>
|
||||||
|
/// <term>SWP_SHOWWINDOW (0x0040)</term><description>Displays the window.</description>
|
||||||
|
/// </item>
|
||||||
|
/// </list>
|
||||||
|
/// </param>
|
||||||
|
/// <returns><c>true</c> or nonzero if the function succeeds, <c>false</c> or zero otherwise or if function fails.</returns>
|
||||||
|
/// <remarks>
|
||||||
|
/// <para>
|
||||||
|
/// As part of the Vista re-architecture, all services were moved off the interactive desktop into Session 0.
|
||||||
|
/// hwnd and window manager operations are only effective inside a session and cross-session attempts to manipulate
|
||||||
|
/// the hwnd will fail. For more information, see The Windows Vista Developer Story: Application Compatibility
|
||||||
|
/// Cookbook.
|
||||||
|
/// </para>
|
||||||
|
/// <para>
|
||||||
|
/// If you have changed certain window data using SetWindowLong, you must call SetWindowPos for the changes to
|
||||||
|
/// take effect. Use the following combination for uFlags: SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER |
|
||||||
|
/// SWP_FRAMECHANGED.
|
||||||
|
/// </para>
|
||||||
|
/// <para>
|
||||||
|
/// A window can be made a topmost window either by setting the hWndInsertAfter parameter to HWND_TOPMOST and
|
||||||
|
/// ensuring that the SWP_NOZORDER flag is not set, or by setting a window's position in the Z order so that it is
|
||||||
|
/// above any existing topmost windows. When a non-topmost window is made topmost, its owned windows are also made
|
||||||
|
/// topmost. Its owners, however, are not changed.
|
||||||
|
/// </para>
|
||||||
|
/// <para>
|
||||||
|
/// If neither the SWP_NOACTIVATE nor SWP_NOZORDER flag is specified (that is, when the application requests that
|
||||||
|
/// a window be simultaneously activated and its position in the Z order changed), the value specified in
|
||||||
|
/// hWndInsertAfter is used only in the following circumstances.
|
||||||
|
/// </para>
|
||||||
|
/// <list type="bullet">
|
||||||
|
/// <item>Neither the HWND_TOPMOST nor HWND_NOTOPMOST flag is specified in hWndInsertAfter. </item>
|
||||||
|
/// <item>The window identified by hWnd is not the active window. </item>
|
||||||
|
/// </list>
|
||||||
|
/// <para>
|
||||||
|
/// An application cannot activate an inactive window without also bringing it to the top of the Z order.
|
||||||
|
/// Applications can change an activated window's position in the Z order without restrictions, or it can activate
|
||||||
|
/// a window and then move it to the top of the topmost or non-topmost windows.
|
||||||
|
/// </para>
|
||||||
|
/// <para>
|
||||||
|
/// If a topmost window is repositioned to the bottom (HWND_BOTTOM) of the Z order or after any non-topmost
|
||||||
|
/// window, it is no longer topmost. When a topmost window is made non-topmost, its owners and its owned windows
|
||||||
|
/// are also made non-topmost windows.
|
||||||
|
/// </para>
|
||||||
|
/// <para>
|
||||||
|
/// A non-topmost window can own a topmost window, but the reverse cannot occur. Any window (for example, a
|
||||||
|
/// dialog box) owned by a topmost window is itself made a topmost window, to ensure that all owned windows stay
|
||||||
|
/// above their owner.
|
||||||
|
/// </para>
|
||||||
|
/// <para>
|
||||||
|
/// If an application is not in the foreground, and should be in the foreground, it must call the
|
||||||
|
/// SetForegroundWindow function.
|
||||||
|
/// </para>
|
||||||
|
/// <para>
|
||||||
|
/// To use SetWindowPos to bring a window to the top, the process that owns the window must have
|
||||||
|
/// SetForegroundWindow permission.
|
||||||
|
/// </para>
|
||||||
|
/// </remarks>
|
||||||
|
|
||||||
|
[DllImport("user32.dll", SetLastError = true)]
|
||||||
|
public static extern bool SetWindowPos(IntPtr hWnd, IntPtr hWndInsertAfter, int X, int Y, int cx, int cy, SetWindowPosFlags uFlags);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Brings the thread that created the specified window into the foreground and activates the window. Keyboard input is
|
||||||
|
/// directed to the window, and various visual cues are changed for the user. The system assigns a slightly higher
|
||||||
|
/// priority to the thread that created the foreground window than it does to other threads.
|
||||||
|
/// <para>See for https://msdn.microsoft.com/en-us/library/windows/desktop/ms633539%28v=vs.85%29.aspx more information.</para>
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="hWnd">
|
||||||
|
/// C++ ( hWnd [in]. Type: HWND )<br />A handle to the window that should be activated and brought to the foreground.
|
||||||
|
/// </param>
|
||||||
|
/// <returns>
|
||||||
|
/// <c>true</c> or nonzero if the window was brought to the foreground, <c>false</c> or zero If the window was not
|
||||||
|
/// brought to the foreground.
|
||||||
|
/// </returns>
|
||||||
|
/// <remarks>
|
||||||
|
/// The system restricts which processes can set the foreground window. A process can set the foreground window only if
|
||||||
|
/// one of the following conditions is true:
|
||||||
|
/// <list type="bullet">
|
||||||
|
/// <listheader>
|
||||||
|
/// <term>Conditions</term><description></description>
|
||||||
|
/// </listheader>
|
||||||
|
/// <item>The process is the foreground process.</item>
|
||||||
|
/// <item>The process was started by the foreground process.</item>
|
||||||
|
/// <item>The process received the last input event.</item>
|
||||||
|
/// <item>There is no foreground process.</item>
|
||||||
|
/// <item>The process is being debugged.</item>
|
||||||
|
/// <item>The foreground process is not a Modern Application or the Start Screen.</item>
|
||||||
|
/// <item>The foreground is not locked (see LockSetForegroundWindow).</item>
|
||||||
|
/// <item>The foreground lock time-out has expired (see SPI_GETFOREGROUNDLOCKTIMEOUT in SystemParametersInfo).</item>
|
||||||
|
/// <item>No menus are active.</item>
|
||||||
|
/// </list>
|
||||||
|
/// <para>
|
||||||
|
/// An application cannot force a window to the foreground while the user is working with another window.
|
||||||
|
/// Instead, Windows flashes the taskbar button of the window to notify the user.
|
||||||
|
/// </para>
|
||||||
|
/// <para>
|
||||||
|
/// A process that can set the foreground window can enable another process to set the foreground window by
|
||||||
|
/// calling the AllowSetForegroundWindow function. The process specified by dwProcessId loses the ability to set
|
||||||
|
/// the foreground window the next time the user generates input, unless the input is directed at that process, or
|
||||||
|
/// the next time a process calls AllowSetForegroundWindow, unless that process is specified.
|
||||||
|
/// </para>
|
||||||
|
/// <para>
|
||||||
|
/// The foreground process can disable calls to SetForegroundWindow by calling the LockSetForegroundWindow
|
||||||
|
/// function.
|
||||||
|
/// </para>
|
||||||
|
/// </remarks>
|
||||||
|
// For Windows Mobile, replace user32.dll with coredll.dll
|
||||||
|
[DllImport("user32.dll")]
|
||||||
|
[return: MarshalAs(UnmanagedType.Bool)]
|
||||||
|
public static extern bool SetForegroundWindow(IntPtr hWnd);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Retrieves the show state and the restored, minimized, and maximized positions of the specified window.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="hWnd">
|
||||||
|
/// A handle to the window.
|
||||||
|
/// </param>
|
||||||
|
/// <param name="lpwndpl">
|
||||||
|
/// A pointer to the WINDOWPLACEMENT structure that receives the show state and position information.
|
||||||
|
/// <para>
|
||||||
|
/// Before calling GetWindowPlacement, set the length member to sizeof(WINDOWPLACEMENT). GetWindowPlacement fails if lpwndpl-> length is not set correctly.
|
||||||
|
/// </para>
|
||||||
|
/// </param>
|
||||||
|
/// <returns>
|
||||||
|
/// If the function succeeds, the return value is nonzero.
|
||||||
|
/// <para>
|
||||||
|
/// If the function fails, the return value is zero. To get extended error information, call GetLastError.
|
||||||
|
/// </para>
|
||||||
|
/// </returns>
|
||||||
|
[DllImport("user32.dll", SetLastError = true)]
|
||||||
|
[return: MarshalAs(UnmanagedType.Bool)]
|
||||||
|
public static extern bool GetWindowPlacement(IntPtr hWnd, ref WINDOWPLACEMENT lpwndpl);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Sets the show state and the restored, minimized, and maximized positions of the specified window.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="hWnd">
|
||||||
|
/// A handle to the window.
|
||||||
|
/// </param>
|
||||||
|
/// <param name="lpwndpl">
|
||||||
|
/// A pointer to a WINDOWPLACEMENT structure that specifies the new show state and window positions.
|
||||||
|
/// <para>
|
||||||
|
/// Before calling SetWindowPlacement, set the length member of the WINDOWPLACEMENT structure to sizeof(WINDOWPLACEMENT). SetWindowPlacement fails if the length member is not set correctly.
|
||||||
|
/// </para>
|
||||||
|
/// </param>
|
||||||
|
/// <returns>
|
||||||
|
/// If the function succeeds, the return value is nonzero.
|
||||||
|
/// <para>
|
||||||
|
/// If the function fails, the return value is zero. To get extended error information, call GetLastError.
|
||||||
|
/// </para>
|
||||||
|
/// </returns>
|
||||||
|
[DllImport("user32.dll", SetLastError = true)]
|
||||||
|
[return: MarshalAs(UnmanagedType.Bool)]
|
||||||
|
public static extern bool SetWindowPlacement(IntPtr hWnd, [In] ref WINDOWPLACEMENT lpwndpl);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Contains information about the placement of a window on the screen.
|
||||||
|
/// </summary>
|
||||||
|
[Serializable]
|
||||||
|
[StructLayout(LayoutKind.Sequential)]
|
||||||
|
public struct WINDOWPLACEMENT
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// The length of the structure, in bytes. Before calling the GetWindowPlacement or SetWindowPlacement functions, set this member to sizeof(WINDOWPLACEMENT).
|
||||||
|
/// <para>
|
||||||
|
/// GetWindowPlacement and SetWindowPlacement fail if this member is not set correctly.
|
||||||
|
/// </para>
|
||||||
|
/// </summary>
|
||||||
|
public int Length;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Specifies flags that control the position of the minimized window and the method by which the window is restored.
|
||||||
|
/// </summary>
|
||||||
|
public int Flags;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The current show state of the window.
|
||||||
|
/// </summary>
|
||||||
|
public ShowWindowCommands ShowCmd;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The coordinates of the window's upper-left corner when the window is minimized.
|
||||||
|
/// </summary>
|
||||||
|
public Point MinPosition;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The coordinates of the window's upper-left corner when the window is maximized.
|
||||||
|
/// </summary>
|
||||||
|
public Point MaxPosition;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The window's coordinates when the window is in the restored position.
|
||||||
|
/// </summary>
|
||||||
|
public Rect NormalPosition;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the default (empty) value.
|
||||||
|
/// </summary>
|
||||||
|
public static WINDOWPLACEMENT Default
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
WINDOWPLACEMENT result = new WINDOWPLACEMENT();
|
||||||
|
result.Length = Marshal.SizeOf(result);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public enum ShowWindowCommands
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Hides the window and activates another window.
|
||||||
|
/// </summary>
|
||||||
|
Hide = 0,
|
||||||
|
/// <summary>
|
||||||
|
/// Activates and displays a window. If the window is minimized or
|
||||||
|
/// maximized, the system restores it to its original size and position.
|
||||||
|
/// An application should specify this flag when displaying the window
|
||||||
|
/// for the first time.
|
||||||
|
/// </summary>
|
||||||
|
Normal = 1,
|
||||||
|
/// <summary>
|
||||||
|
/// Activates the window and displays it as a minimized window.
|
||||||
|
/// </summary>
|
||||||
|
ShowMinimized = 2,
|
||||||
|
/// <summary>
|
||||||
|
/// Maximizes the specified window.
|
||||||
|
/// </summary>
|
||||||
|
Maximize = 3, // is this the right value?
|
||||||
|
/// <summary>
|
||||||
|
/// Activates the window and displays it as a maximized window.
|
||||||
|
/// </summary>
|
||||||
|
ShowMaximized = 3,
|
||||||
|
/// <summary>
|
||||||
|
/// Displays a window in its most recent size and position. This value
|
||||||
|
/// is similar to <see cref="Win32.ShowWindowCommand.Normal"/>, except
|
||||||
|
/// the window is not activated.
|
||||||
|
/// </summary>
|
||||||
|
ShowNoActivate = 4,
|
||||||
|
/// <summary>
|
||||||
|
/// Activates the window and displays it in its current size and position.
|
||||||
|
/// </summary>
|
||||||
|
Show = 5,
|
||||||
|
/// <summary>
|
||||||
|
/// Minimizes the specified window and activates the next top-level
|
||||||
|
/// window in the Z order.
|
||||||
|
/// </summary>
|
||||||
|
Minimize = 6,
|
||||||
|
/// <summary>
|
||||||
|
/// Displays the window as a minimized window. This value is similar to
|
||||||
|
/// <see cref="Win32.ShowWindowCommand.ShowMinimized"/>, except the
|
||||||
|
/// window is not activated.
|
||||||
|
/// </summary>
|
||||||
|
ShowMinNoActive = 7,
|
||||||
|
/// <summary>
|
||||||
|
/// Displays the window in its current size and position. This value is
|
||||||
|
/// similar to <see cref="Win32.ShowWindowCommand.Show"/>, except the
|
||||||
|
/// window is not activated.
|
||||||
|
/// </summary>
|
||||||
|
ShowNA = 8,
|
||||||
|
/// <summary>
|
||||||
|
/// Activates and displays the window. If the window is minimized or
|
||||||
|
/// maximized, the system restores it to its original size and position.
|
||||||
|
/// An application should specify this flag when restoring a minimized window.
|
||||||
|
/// </summary>
|
||||||
|
Restore = 9,
|
||||||
|
/// <summary>
|
||||||
|
/// Sets the show state based on the SW_* value specified in the
|
||||||
|
/// STARTUPINFO structure passed to the CreateProcess function by the
|
||||||
|
/// program that started the application.
|
||||||
|
/// </summary>
|
||||||
|
ShowDefault = 10,
|
||||||
|
/// <summary>
|
||||||
|
/// <b>Windows 2000/XP:</b> Minimizes a window, even if the thread
|
||||||
|
/// that owns the window is not responding. This flag should only be
|
||||||
|
/// used when minimizing windows from a different thread.
|
||||||
|
/// </summary>
|
||||||
|
ForceMinimize = 11
|
||||||
|
}
|
||||||
|
|
||||||
|
[DllImport("user32.dll")]
|
||||||
|
public static extern bool ShowWindow(IntPtr hWnd, ShowWindowCommands nCmdShow);
|
||||||
|
|
||||||
|
[DllImport("user32.dll")]
|
||||||
|
[return: MarshalAs(UnmanagedType.Bool)]
|
||||||
|
public static extern bool IsWindow(IntPtr hWnd);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -66,6 +66,7 @@
|
||||||
<Reference Include="System" />
|
<Reference Include="System" />
|
||||||
<Reference Include="System.Data" />
|
<Reference Include="System.Data" />
|
||||||
<Reference Include="System.Drawing" />
|
<Reference Include="System.Drawing" />
|
||||||
|
<Reference Include="System.Windows.Forms" />
|
||||||
<Reference Include="System.Xml" />
|
<Reference Include="System.Xml" />
|
||||||
<Reference Include="Microsoft.CSharp" />
|
<Reference Include="Microsoft.CSharp" />
|
||||||
<Reference Include="System.Core" />
|
<Reference Include="System.Core" />
|
||||||
|
|
@ -84,7 +85,13 @@
|
||||||
<Generator>MSBuild:Compile</Generator>
|
<Generator>MSBuild:Compile</Generator>
|
||||||
<SubType>Designer</SubType>
|
<SubType>Designer</SubType>
|
||||||
</ApplicationDefinition>
|
</ApplicationDefinition>
|
||||||
|
<Compile Include="Overlay\Actions\BringWindowToFrontAction.cs" />
|
||||||
|
<Compile Include="Overlay\Actions\IOverlayAction.cs" />
|
||||||
|
<Compile Include="Overlay\Actions\MaximizeWindowAction.cs" />
|
||||||
|
<Compile Include="Overlay\Actions\ResizeWindowAction.cs" />
|
||||||
|
<Compile Include="Overlay\Actions\RestoreWindowAction.cs" />
|
||||||
<Compile Include="Overlay\IOverlay.cs" />
|
<Compile Include="Overlay\IOverlay.cs" />
|
||||||
|
<Compile Include="Utilities\User32.cs" />
|
||||||
<Compile Include="WindowSelectors\FromProcessName.cs" />
|
<Compile Include="WindowSelectors\FromProcessName.cs" />
|
||||||
<Compile Include="WindowSelectors\FromWindowName.cs" />
|
<Compile Include="WindowSelectors\FromWindowName.cs" />
|
||||||
<Compile Include="WindowSelectors\IWindowSelector.cs" />
|
<Compile Include="WindowSelectors\IWindowSelector.cs" />
|
||||||
|
|
@ -96,7 +103,7 @@
|
||||||
<DependentUpon>App.xaml</DependentUpon>
|
<DependentUpon>App.xaml</DependentUpon>
|
||||||
<SubType>Code</SubType>
|
<SubType>Code</SubType>
|
||||||
</Compile>
|
</Compile>
|
||||||
<Compile Include="Debug\ConsoleManager.cs" />
|
<Compile Include="Utilities\ConsoleManager.cs" />
|
||||||
<Compile Include="MainWindow.xaml.cs">
|
<Compile Include="MainWindow.xaml.cs">
|
||||||
<DependentUpon>MainWindow.xaml</DependentUpon>
|
<DependentUpon>MainWindow.xaml</DependentUpon>
|
||||||
<SubType>Code</SubType>
|
<SubType>Code</SubType>
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using VDash.Utilities;
|
||||||
|
|
||||||
namespace VDash.WindowSelectors
|
namespace VDash.WindowSelectors
|
||||||
{
|
{
|
||||||
|
|
@ -17,9 +18,15 @@ namespace VDash.WindowSelectors
|
||||||
m_ProcName = procName;
|
m_ProcName = procName;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Process[] processes = null;
|
||||||
public Process[] GetProcesses()
|
public Process[] GetProcesses()
|
||||||
{
|
{
|
||||||
return Process.GetProcessesByName(m_ProcName);
|
if(processes == null)
|
||||||
|
{
|
||||||
|
processes = Process.GetProcessesByName(m_ProcName);
|
||||||
|
}
|
||||||
|
|
||||||
|
return processes;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Process GetProcess()
|
public Process GetProcess()
|
||||||
|
|
@ -46,5 +53,10 @@ namespace VDash.WindowSelectors
|
||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public bool WindowExists()
|
||||||
|
{
|
||||||
|
return User32.IsWindow(GetWindowHandle());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -80,6 +80,19 @@ namespace VDash.WindowSelectors
|
||||||
return Window;
|
return Window;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public bool WindowExists()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var window = Window;
|
||||||
|
}
|
||||||
|
catch (WindowNotFoundException)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
public enum TitleSearchType
|
public enum TitleSearchType
|
||||||
{
|
{
|
||||||
Contains = 0,
|
Contains = 0,
|
||||||
|
|
|
||||||
|
|
@ -9,6 +9,7 @@ namespace VDash.WindowSelectors
|
||||||
{
|
{
|
||||||
IntPtr GetWindowHandle();
|
IntPtr GetWindowHandle();
|
||||||
WindowInfo GetWindowInfo();
|
WindowInfo GetWindowInfo();
|
||||||
|
bool WindowExists();
|
||||||
}
|
}
|
||||||
|
|
||||||
public class WindowNotFoundException : Exception
|
public class WindowNotFoundException : Exception
|
||||||
|
|
@ -53,6 +54,10 @@ namespace VDash.WindowSelectors
|
||||||
return Title;
|
return Title;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets a list of all windows in the current desktop session.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns></returns>
|
||||||
public static WindowInfo[] GetWindowList()
|
public static WindowInfo[] GetWindowList()
|
||||||
{
|
{
|
||||||
List<WindowInfo> windows = new List<WindowInfo>();
|
List<WindowInfo> windows = new List<WindowInfo>();
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue