I have two separate processes- one is a console application and one is a winform application. Now, if the winform is minimized then the console application should normalize it and vice versa. How can i do this? Also, the console application starts the winform and on start it should be in its normalized position. How can i go about this on the following lines
var processes = Process.GetProcessesByName("MyWinformApp");
if (processes.Length == 0)
{
Process.Start("MyWinformApp.exe");
How to be sure that the winform will open up in Normalized state
}
else
{
IntPtr handle = processes[0].MainWindowHandle;
//If winform minimized the normalize and vice versa ....What to do here
//Maybe use GetWindowPlacement
??
handle = processes[0].MainWindowHandle;
if(if winform was minimized) //how to find this???
{
ShowWindow(handle, Normal);
}
else
{
ShowWindow(handle, Minimize);
}
}
I did find information on pinvoke.net but was confused so would appreciate some help.
Thanks
The following code does that and the other part of the question was answered by DeeMac above
#region For getting the hadnle and min/max operation
private const int SW_Minimize = 6;
private const int SW_Normal = 1;
[DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
static extern bool ShowWindow(IntPtr hWnd, int nCmdShow);
private static WINDOWPLACEMENT GetPlacement(IntPtr hwnd)
{
WINDOWPLACEMENT placement = new WINDOWPLACEMENT();
placement.length = Marshal.SizeOf(placement);
GetWindowPlacement(hwnd, ref placement);
return placement;
}
[DllImport("user32.dll", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
internal static extern bool GetWindowPlacement(
IntPtr hWnd, ref WINDOWPLACEMENT lpwndpl);
[Serializable]
[StructLayout(LayoutKind.Sequential)]
internal struct WINDOWPLACEMENT
{
public int length;
public int flags;
public ShowWindowCommands showCmd;
public System.Drawing.Point ptMinPosition;
public System.Drawing.Point ptMaxPosition;
public System.Drawing.Rectangle rcNormalPosition;
}
internal enum ShowWindowCommands : int
{
Hide = 0,
Normal = 1,
Minimized = 2,
Maximized = 3,
}
#endregion
var processes = Process.GetProcessesByName("MyWinformApp");
if (processes.Length == 0)
{
Process.Start("MyWinformApp.exe");
}
else
{
IntPtr handle = processes[0].MainWindowHandle;
var placement = GetPlacement(handle);
if (String.Equals(placement.showCmd.ToString(), "Minimized"))
{
ShowWindow(handle, SW_Normal);
}
else
{
ShowWindow(handle, SW_Minimize);
}
}
Related
I'd like to check, if any screen hosts application in fullscreen mode. I have solution only for one screen which is code copied from here: [WPF] [C#] How-to : Detect if another application is running in full screen mode. This solution is based on
[DllImport("user32.dll")]
private static extern IntPtr GetForegroundWindow();
which gathers only active window handle. The problem is, I have two screens. I've searched many sites but none of them answers my question. It is not about capturing screenshot, which is simple and doesn't rely on P/Invoke.
Is this possible?
No ready-to-use solution here, but let's see..
Get list of all displayed windows and check positions and sizes of those windows - possible, lots of tools does it, many articles on that, I'll skip this one. Then, you can call MonitorFromWindow for each or some windows and compare window dimensions&position against monitor info. If windowpos ~= 0,0 and windowsize ~= monitorresolution you could assume that this window is in fullscreen mode.
On the other hand, if already having a list of all HWNDs, then why not just Query the window for its placement and check the WINDOWPLACEMENT.showCmd for SW_MAXIMIZE/SW_SHOWMAXIMIZED flags. That won't tell you which monitor is it, but should tell you at least if the window is maximized and if it's enough for you..
I don't know how fast/slow would it be to do it like that, but, yes, it seems possible.
You could use EnumWindows in conjunction with Screen.FromHandle. And maybe GetWindowRect() for calculations.
Something like (pseudo-code!):
//------------------------------
//this sample code is taken from http://pinvoke.net/default.aspx/user32/EnumWindows.html
public delegate bool EnumedWindow(IntPtr handleWindow, ArrayList handles);
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool EnumWindows(EnumedWindow lpEnumFunc, ArrayList lParam);
public static ArrayList GetWindows()
{
ArrayList windowHandles = new ArrayList();
EnumedWindow callBackPtr = GetWindowHandle;
EnumWindows(callBackPtr, windowHandles);
return windowHandles;
}
private static bool GetWindowHandle(IntPtr windowHandle, ArrayList windowHandles)
{
windowHandles.Add(windowHandle);
return true;
}
//------------------------------
[DllImport("user32.dll")]
private static extern bool GetWindowRect(IntPtr hWnd, [In,Out] ref Rect rect);
[StructLayout(LayoutKind.Sequential)]
private struct Rect
{
public int Left;
public int Top;
public int Right;
public int Bottom;
}
static void Main() {
foreach(IntPtr handle in GetWindows())
{
Screen scr = Screen.FromHandle(handle);
if(IsFullscreen(handle, scr))
{
// the window is fullscreen...
}
}
}
private bool IsFullscreen(IntPtr wndHandle, Screen screen)
{
Rect r = new Rect();
GetWindowRect(wndHandle, ref r);
return new Rectangle(r.Left, r.Top, r.Right-r.Left, r.Bottom-r.Top)
.Contains(screen.Bounds);
}
I wrote piece of code which is working:
namespace EnumWnd
{
using System;
using System.Runtime.InteropServices;
using System.Text;
[StructLayout(LayoutKind.Sequential)]
public struct Rect
{
public int Left;
public int Top;
public int Right;
public int Bottom;
}
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
internal struct MonitorInfoEx
{
public int cbSize;
public Rect rcMonitor;
public Rect rcWork;
public UInt32 dwFlags;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)] public string szDeviceName;
}
internal class Program
{
[DllImport("user32.dll")]
public static extern bool GetWindowRect(IntPtr hWnd, out Rect lpRect);
[DllImport("user32.dll", CharSet = CharSet.Unicode)]
protected static extern int GetWindowText(IntPtr hWnd, StringBuilder strText, int maxCount);
[DllImport("user32.dll", CharSet = CharSet.Unicode)]
protected static extern int GetWindowTextLength(IntPtr hWnd);
[DllImport("user32.dll")]
protected static extern bool EnumWindows(EnumWindowsProc enumProc, IntPtr lParam);
[DllImport("user32.dll")]
protected static extern bool IsWindowVisible(IntPtr hWnd);
[DllImport("User32")]
public static extern IntPtr MonitorFromWindow(IntPtr hWnd, int dwFlags);
[DllImport("user32", EntryPoint = "GetMonitorInfo", CharSet = CharSet.Auto,
SetLastError = true)]
internal static extern bool GetMonitorInfoEx(IntPtr hMonitor, ref MonitorInfoEx lpmi);
protected static bool EnumTheWindows(IntPtr hWnd, IntPtr lParam)
{
const int MONITOR_DEFAULTTOPRIMARY = 1;
var mi = new MonitorInfoEx();
mi.cbSize = Marshal.SizeOf(mi);
GetMonitorInfoEx(MonitorFromWindow(hWnd, MONITOR_DEFAULTTOPRIMARY), ref mi);
Rect appBounds;
GetWindowRect(hWnd, out appBounds);
int size = GetWindowTextLength(hWnd);
if (size++ > 0 && IsWindowVisible(hWnd))
{
var sb = new StringBuilder(size);
GetWindowText(hWnd, sb, size);
if (sb.Length > 20)
{
sb.Remove(20, sb.Length - 20);
}
int windowHeight = appBounds.Right - appBounds.Left;
int windowWidth = appBounds.Bottom - appBounds.Top;
int monitorHeight = mi.rcMonitor.Right - mi.rcMonitor.Left;
int monitorWidth = mi.rcMonitor.Bottom - mi.rcMonitor.Top;
bool fullScreen = (windowHeight == monitorHeight) && (windowWidth == monitorWidth);
sb.AppendFormat(" Wnd:({0} | {1}) Mtr:({2} | {3} | Name: {4}) - {5}", windowWidth, windowHeight, monitorWidth, monitorHeight, mi.szDeviceName, fullScreen);
Console.WriteLine(sb.ToString());
}
return true;
}
private static void Main()
{
while (true)
{
EnumWindows(EnumTheWindows, IntPtr.Zero);
Console.ReadKey();
Console.Clear();
}
}
protected delegate bool EnumWindowsProc(IntPtr hWnd, IntPtr lParam);
}
}
Thanks for #SamAxe and #quetzalcoatl for providing me useful tips.
I need to check what window the user currently has selected, and do stuff if they have a specific program selected.
I haven't used the GetForegroundWindow function before, and can't find any information on how to use it in this manner.
I simply need an if comparing the current window to see if its a specific program. However the GetForegroundWindow function doesn't give back a string or int it seems. So mainly I don't know how to find out the value of the program window I want to compare it to.
I currently have the code to get the current window:
[DllImport("user32.dll")]
private static extern IntPtr GetForegroundWindow();
IntPtr selectedWindow = GetForegroundWindow();
I need to be able to apply it as follows ideally:
If (selectedWindow!="SpecificProgram")
{
<Do this stuff>
}
I'm hoping the GetForegroundWindow value/object is unique to each program and doesn't function in some way that each specific program/window has different values each-time.
I'm also doing this as part of a windows form though I doubt it matters.
-Thanks for any help
Edit: This way works, and uses the tile of the current window, which makes it perfect for checking if the window is right easily:
[DllImport("user32.dll")]
static extern IntPtr GetForegroundWindow();
[DllImport("user32.dll")]
static extern int GetWindowText(IntPtr hWnd, StringBuilder text, int count);
private string GetActiveWindowTitle()
{
const int nChars = 256;
StringBuilder Buff = new StringBuilder(nChars);
IntPtr handle = GetForegroundWindow();
if (GetWindowText(handle, Buff, nChars) > 0)
{
return Buff.ToString();
}
return null;
}
and then I can just do:
if (GetActiveWindowTitle()=="Name of Window")
{
DoStuff.jpg
}
It has some code but it works:
#region Retrieve list of windows
[DllImport("user32")]
private static extern int GetWindowLongA(IntPtr hWnd, int index);
[DllImport("USER32.DLL")]
private static extern int GetWindowText(IntPtr hWnd, StringBuilder lpString, int nMaxCount);
[DllImport("USER32.DLL")]
private static extern bool EnumWindows(EnumWindowsProc enumFunc, int lParam);
[DllImport("user32.dll")]
private static extern IntPtr GetForegroundWindow();
private const int GWL_STYLE = -16;
private const ulong WS_VISIBLE = 0x10000000L;
private const ulong WS_BORDER = 0x00800000L;
private const ulong TARGETWINDOW = WS_BORDER | WS_VISIBLE;
internal class Window
{
public string Title;
public IntPtr Handle;
public override string ToString()
{
return Title;
}
}
private List<Window> windows;
private void GetWindows()
{
windows = new List<Window>();
EnumWindows(Callback, 0);
}
private bool Callback(IntPtr hwnd, int lParam)
{
if (this.Handle != hwnd && (GetWindowLongA(hwnd, GWL_STYLE) & TARGETWINDOW) == TARGETWINDOW)
{
StringBuilder sb = new StringBuilder(100);
GetWindowText(hwnd, sb, sb.Capacity);
Window t = new Window();
t.Handle = hwnd;
t.Title = sb.ToString();
windows.Add(t);
}
return true; //continue enumeration
}
#endregion
And to check user window:
IntPtr selectedWindow = GetForegroundWindow();
GetWindows();
for (i = 0; i < windows.Count; i++)
{
if(selectedWindow == windows[i].Handle && windows[i].Title == "Program Title X")
{
//Do stuff
break;
}
}
Valter
I have a Windows Forms application which is persisting the location of a tool window with the following code:
ToolWindow = new ToolViewer(TransformedResult);
ToolWindow.FormClosed += (_1, _2) =>
{
this.ToolWindowPlacement = WindowPlacement.GetPlacement(ToolWindow.Handle);
this.ToolWindow = null;
};
ToolWindow.Show();
WindowPlacement.SetPlacement(ToolWindow.Handle, ToolWindowPlacement);
It works fine, unless the tool window is maximized. If it is maximized, the window keeps showing up on my main monitor, rather than the one on which it was maximized when it was closed.
WindowPlacement.cs:
// from http://blogs.msdn.com/b/davidrickard/archive/2010/03/09/saving-window-size-and-location-in-wpf-and-winforms.aspx
static class WindowPlacement
{
[DllImport("user32.dll")]
private static extern bool SetWindowPlacement(IntPtr hWnd, [In] ref WINDOWPLACEMENT lpwndpl);
[DllImport("user32.dll")]
private static extern bool GetWindowPlacement(IntPtr hWnd, out WINDOWPLACEMENT lpwndpl);
private const int SW_SHOWNORMAL = 1;
private const int SW_SHOWMINIMIZED = 2;
public static void SetPlacement(IntPtr windowHandle, WINDOWPLACEMENT placement)
{
if (placement.length == 0)
return;
placement.length = Marshal.SizeOf(typeof(WINDOWPLACEMENT));
placement.flags = 0;
placement.showCmd = (placement.showCmd == SW_SHOWMINIMIZED ? SW_SHOWNORMAL : placement.showCmd);
SetWindowPlacement(windowHandle, ref placement);
}
public static WINDOWPLACEMENT GetPlacement(IntPtr windowHandle)
{
WINDOWPLACEMENT placement = new WINDOWPLACEMENT();
GetWindowPlacement(windowHandle, out placement);
return placement;
}
}
For reasons beyond my knowledge, I had to remove the default WindowState of Maximized which was set for the form in order to get SetWindowPlacement to restore maximized windows to the correct monitor.
We want our application to run in full screen mode with no title bar on a Win CE 5.0 powered device. The application is being developed using .NET Compact Framework 3.5 (C#).
I have followed this tutorial, but I encountered an error. Here is my code:
namespace DatalogicDeviceControl
{
public partial class Form1 : Form
{
public const int SWP_ASYNCWINDOWPOS = 0x4000;
public const int SWP_DEFERERASE = 0x2000;
public const int SWP_DRAWFRAME = 0x0020;
public const int SWP_FRAMECHANGED = 0x0020;
public const int SWP_HIDEWINDOW = 0x0080;
public const int SWP_NOACTIVATE = 0x0010;
public const int SWP_NOCOPYBITS = 0x0100;
public const int SWP_NOMOVE = 0x0002;
public const int SWP_NOOWNERZORDER = 0x0200;
public const int SWP_NOREDRAW = 0x0008;
public const int SWP_NOREPOSITION = 0x0200;
public const int SWP_NOSENDCHANGING = 0x0400;
public const int SWP_NOSIZE = 0x0001;
public const int SWP_NOZORDER = 0x0004;
public const int SWP_SHOWWINDOW = 0x0040;
public const int HWND_TOP = 0;
public const int HWND_BOTTOM = 1;
public const int HWND_TOPMOST = -1;
public const int HWND_NOTOPMOST = -2;
public Form1()
{
InitializeComponent();
HideStartBar();
}
[DllImport("coredll.dll", EntryPoint = "FindWindowW", SetLastError = true)]
private static extern IntPtr FindWindowCE(string lpClassName, string lpWindowName);
[DllImport("user32.dll", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool SetWindowPos(IntPtr hWnd, int hWndInsertAfter, int x, int y, int cx, int cy, uint uFlags);
public void HideStartBar()
{
IntPtr handle;
try
{
// Find the handle to the Start Bar
handle = FindWindowCE("HHTaskBar", null);
// If the handle is found then hide the start bar
if (handle != IntPtr.Zero)
{
// Hide the start bar
SetWindowPos(handle, 0, 0, 0, 0, 0, SWP_HIDEWINDOW);
}
}
catch
{
MessageBox.Show("Could not hide Start Bar.");
}
}
}
}
I have encountered the following error:
The best overloaded method match for 'DatalogicDeviceControl.Form1.SetWindowPos(System.IntPtr, int, int, int, int, uint)' has some invalid arguments
#dzerow: Your answer is correct: Windows Mobile does not support the user32.dll library.
Use the coredll.dll library instead.
private const int SRCCOPY = 0x00CC0020;
private const string CORE_DLL = "coredll.dll";
private static IntPtr _taskBar;
private static IntPtr _sipButton;
private static string _deviceId, _deviceIp;
private static DateTime _lastUpdateCheck, _startTime;
[DllImport(CORE_DLL)]
public static extern int BitBlt(IntPtr hdcDest, int nXDest, int nYDest, int nWidth, int nHeight, IntPtr hdcSrc, int nXSrc, int nYSrc, uint dwRop);
[DllImport(CORE_DLL)]
public static extern bool CeRunAppAtEvent(string appName, int Event);
[DllImport(CORE_DLL, EntryPoint = "FindWindowW", SetLastError = true)]
public static extern IntPtr FindWindowCE(string lpClassName, string lpWindowName);
[DllImport(CORE_DLL)]
private static extern IntPtr GetDC(IntPtr hwnd);
[DllImport(CORE_DLL)]
public static extern bool MessageBeep(int uType);
[DllImport(CORE_DLL, SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool SetWindowPos(IntPtr hWnd, IntPtr hWndInsertAfter, int x, int y, int cx, int cy, uint uFlags);
Below is a lot of the code from an application I used to manage. Parts of it may be incomplete and there could be too much info. If something is missing, just comment and I will fill that in.
Basically, the routine I have written enables you to call ShowWindowsMenu(bool enable) to either enable or disable the HHTaskBar (task bar) and the MS_SIPBUTTON (soft input button).
public static void ShowWindowsMenu(bool enable) {
try {
if (enable) {
if (_taskBar != IntPtr.Zero) {
SetWindowPos(_taskBar, IntPtr.Zero, 0, 0, 240, 26, (int)WindowPosition.SWP_SHOWWINDOW); // display the start bar
}
} else {
_taskBar = FindWindowCE("HHTaskBar", null); // Find the handle to the Start Bar
if (_taskBar != IntPtr.Zero) { // If the handle is found then hide the start bar
SetWindowPos(_taskBar, IntPtr.Zero, 0, 0, 0, 0, (int)WindowPosition.SWP_HIDEWINDOW); // Hide the start bar
}
}
} catch (Exception err) {
ErrorWrapper(enable ? "Show Start" : "Hide Start", err);
}
try {
if (enable) {
if (_sipButton != IntPtr.Zero) { // If the handle is found then hide the start bar
SetWindowPos(_sipButton, IntPtr.Zero, 0, 0, 240, 26, (int)WindowPosition.SWP_SHOWWINDOW); // display the start bar
}
} else {
_sipButton = FindWindowCE("MS_SIPBUTTON", "MS_SIPBUTTON");
if (_sipButton != IntPtr.Zero) { // If the handle is found then hide the start bar
SetWindowPos(_sipButton, IntPtr.Zero, 0, 0, 0, 0, (int)WindowPosition.SWP_HIDEWINDOW); // Hide the start bar
}
}
} catch (Exception err) {
ErrorWrapper(enable ? "Show SIP" : "Hide SIP", err);
}
}
Be sure to turn these features back on when your program exits, or the user will have to reboot the device to get those re-enabled.
EDIT: I forgot the WindowPosition enumerated value I created:
public enum WindowPosition {
SWP_HIDEWINDOW = 0x0080,
SWP_SHOWWINDOW = 0x0040
}
Sorry about that.
Anything else?
Unfortunately Windows Mobile doesn't contain user32.dll, as well as many other normal Windows API DLLs. I had to P/Invoke into coredll.dll instead. For signatures, see PInvoke.net's section (at the bottom left) for "Smart Device Functions".
Just like the question says. Can I see if someone else, program, is running full screen?
Full screen means that the entire screen is obscured, possibly running in a different video mode than the desktop.
Here is some code that does it. You want to take care about the multi screen case, especially with applications like Powerpoint
[StructLayout(LayoutKind.Sequential)]
private struct RECT
{
public int left;
public int top;
public int right;
public int bottom;
}
[DllImport("user32.dll")]
private static extern bool GetWindowRect(HandleRef hWnd, [In, Out] ref RECT rect);
[DllImport("user32.dll")]
private static extern IntPtr GetForegroundWindow();
public static bool IsForegroundFullScreen()
{
return IsForegroundFullScreen(null);
}
public static bool IsForegroundFullScreen(Screen screen)
{
if (screen == null)
{
screen = Screen.PrimaryScreen;
}
RECT rect = new RECT();
GetWindowRect(new HandleRef(null, GetForegroundWindow()), ref rect);
return new Rectangle(rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top).Contains(screen.Bounds);
}
I did some modifications. With the code below it doesn't falsely return true when taskbar is hidden or on a second screen. Tested under Win 7.
[StructLayout(LayoutKind.Sequential)]
public struct RECT
{
public int left;
public int top;
public int right;
public int bottom;
}
[DllImport("user32.dll", SetLastError = true)]
public static extern uint GetWindowThreadProcessId(IntPtr hWnd, out uint lpdwProcessId);
[DllImport("user32.dll")]
private static extern bool GetWindowRect(HandleRef hWnd, [In, Out] ref RECT rect);
[DllImport("user32.dll")]
private static extern IntPtr GetForegroundWindow();
public static bool IsForegroundFullScreen()
{
return IsForegroundFullScreen(null);
}
public static bool IsForegroundFullScreen(System.Windows.Forms.Screen screen)
{
if (screen == null)
{
screen = System.Windows.Forms.Screen.PrimaryScreen;
}
RECT rect = new RECT();
IntPtr hWnd = (IntPtr)GetForegroundWindow();
GetWindowRect(new HandleRef(null, hWnd), ref rect);
/* in case you want the process name:
uint procId = 0;
GetWindowThreadProcessId(hWnd, out procId);
var proc = System.Diagnostics.Process.GetProcessById((int)procId);
Console.WriteLine(proc.ProcessName);
*/
if (screen.Bounds.Width == (rect.right - rect.left) && screen.Bounds.Height == (rect.bottom - rect.top))
{
Console.WriteLine("Fullscreen!")
return true;
}
else {
Console.WriteLine("Nope, :-(");
return false;
}
}