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.
Related
Here's the code I'm using:
private void Button_Click(object sender, RoutedEventArgs e) {
SendMessage(GetDesktopWindow(), LVM_ARRANGE, LVA_SNAPTOGRID, 0);
}
public const uint LVM_ARRANGE = 0x1000 + 22;
public const int LVA_SNAPTOGRID = 0x0005;
[DllImport("User32.dll", CharSet = CharSet.Auto)]
public static extern IntPtr GetDesktopWindow();
[DllImport("user32.dll")]
public static extern int SendMessage(IntPtr hWnd, uint msg, int wParam, int lParam);
Nothing happens when I run it. Code is borrowed from https://www.codeproject.com/Messages/1168961/Re-Auto-Arrange-desktop-icons.aspx
Tried different Windows versions too.
This code worked for me. Note that it doesn't appear to change the options, so although it arranges to the grid for me the View->Align Icons To Grid is still unchecked. The issue is outlined here: How do I get the window handle of the desktop?
Your problem results from a fairly widespread confusion over what the
desktop window actually is. The GetDesktopWindow function does
precisely what it's documented to do: it returns a handle to the
desktop window. This, however, is not the same window that contains
the desktop icons.
So I used the answer here: Get handle to desktop / shell window but with replacing or adding methods and p/invoke calls until I had everything necessary because that link only gives method calls and not the dll imports (I may have left some superfluous stuff in here).
static void Main()
{
SendMessage(GetDesktopWindow(DesktopWindow.SysListView32), LVM_ARRANGE, LVA_SNAPTOGRID, 0);
Console.ReadLine();
}
public const int LVM_ARRANGE = 4118;
public const int LVA_SNAPTOGRID = 5;
[DllImport("user32.dll")]
static extern IntPtr GetShellWindow();
[DllImport("user32.dll", CharSet = CharSet.Unicode)]
static extern IntPtr FindWindowEx(IntPtr parentHandle, IntPtr childAfter, string lclassName, string windowTitle);
[DllImport("User32.dll", CharSet = CharSet.Auto)]
public static extern IntPtr GetDesktopWindow();
[DllImport("user32.dll")]
public static extern int SendMessage(IntPtr hWnd, uint msg, int wParam, int lParam);
[DllImport("user32.dll")]
private static extern bool EnumWindows(EnumWindowsProc enumProc, IntPtr lParam);
public delegate bool EnumWindowsProc(IntPtr hWnd, IntPtr lParam);
[DllImport("user32.dll", CharSet = CharSet.Unicode)]
private static extern int GetWindowText(IntPtr hWnd, StringBuilder strText, int maxCount);
[DllImport("user32.dll", CharSet = CharSet.Unicode)]
private static extern int GetWindowTextLength(IntPtr hWnd);
public enum DesktopWindow
{
ProgMan,
SHELLDLL_DefViewParent,
SHELLDLL_DefView,
SysListView32
}
public static IntPtr GetDesktopWindow(DesktopWindow desktopWindow)
{
IntPtr _ProgMan = GetShellWindow();
IntPtr _SHELLDLL_DefViewParent = _ProgMan;
IntPtr _SHELLDLL_DefView = FindWindowEx(_ProgMan, IntPtr.Zero, "SHELLDLL_DefView", null);
IntPtr _SysListView32 = FindWindowEx(_SHELLDLL_DefView, IntPtr.Zero, "SysListView32", "FolderView");
if (_SHELLDLL_DefView == IntPtr.Zero)
{
EnumWindows((hwnd, lParam) =>
{
if (GetWindowText(hwnd) == "WorkerW")
{
IntPtr child = FindWindowEx(hwnd, IntPtr.Zero, "SHELLDLL_DefView", null);
if (child != IntPtr.Zero)
{
_SHELLDLL_DefViewParent = hwnd;
_SHELLDLL_DefView = child;
_SysListView32 = FindWindowEx(child, IntPtr.Zero, "SysListView32", "FolderView"); ;
return false;
}
}
return true;
}, IntPtr.Zero);
}
switch (desktopWindow)
{
case DesktopWindow.ProgMan:
return _ProgMan;
case DesktopWindow.SHELLDLL_DefViewParent:
return _SHELLDLL_DefViewParent;
case DesktopWindow.SHELLDLL_DefView:
return _SHELLDLL_DefView;
case DesktopWindow.SysListView32:
return _SysListView32;
default:
return IntPtr.Zero;
}
}
public static string GetWindowText(IntPtr hWnd)
{
int size = GetWindowTextLength(hWnd);
if (size > 0)
{
var builder = new StringBuilder(size + 1);
GetWindowText(hWnd, builder, builder.Capacity);
return builder.ToString();
}
return String.Empty;
}
I need a solution to show/hide desktop icons programmatically with C# WPF
Now one possible way is to change the this registry value:
HKEY_CURRENT_USER\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\Advanced
HideIcons = 1
But to make it take effect I need to restart Explorer.exe which is not an option.
Cause my program runs on desktop background. and killing Explorer kills the program and I have restart it.
I also tried this:
Stackoverflow Link
But it didn't work on Windows 10
So, is there any other way to do it? Please Help !
Create Class Library add this code in it
and add namespace System.Runtime.InteropServices
[DllImport("user32.dll", SetLastError = true)]
static extern IntPtr FindWindow(string lpClassName, string lpWindowName);
[DllImport("user32.dll", SetLastError = true)]
static extern IntPtr GetWindow(IntPtr hWnd, GetWindow_Cmd uCmd);
enum GetWindow_Cmd : uint
{
GW_HWNDFIRST = 0,
GW_HWNDLAST = 1,
GW_HWNDNEXT = 2,
GW_HWNDPREV = 3,
GW_OWNER = 4,
GW_CHILD = 5,
GW_ENABLEDPOPUP = 6
}
[DllImport("user32.dll", CharSet = CharSet.Auto)]
static extern IntPtr SendMessage(IntPtr hWnd, UInt32 Msg, IntPtr wParam, IntPtr lParam);
private const int WM_COMMAND = 0x111;
public static void ToggleDesktopIcons()
{
var toggleDesktopCommand = new IntPtr(0x7402);
IntPtr hWnd = GetWindow(FindWindow("Progman", "Program Manager"), GetWindow_Cmd.GW_CHILD);
SendMessage(hWnd, WM_COMMAND, toggleDesktopCommand, IntPtr.Zero);
}
[return: MarshalAs(UnmanagedType.Bool)]
[DllImport("user32.dll", SetLastError = true)]
private static extern bool GetWindowInfo(IntPtr hwnd, ref WINDOWINFO pwi);
[StructLayout(LayoutKind.Sequential)]
public struct RECT
{
private int _Left;
private int _Top;
private int _Right;
private int _Bottom;
}
[StructLayout(LayoutKind.Sequential)]
struct WINDOWINFO
{
public uint cbSize;
public RECT rcWindow;
public RECT rcClient;
public uint dwStyle;
public uint dwExStyle;
public uint dwWindowStatus;
public uint cxWindowBorders;
public uint cyWindowBorders;
public ushort atomWindowType;
public ushort wCreatorVersion;
public WINDOWINFO(Boolean? filler)
: this() // Allows automatic initialization of "cbSize" with "new WINDOWINFO(null/true/false)".
{
cbSize = (UInt32)(Marshal.SizeOf(typeof(WINDOWINFO)));
}
}
public static bool IsVisible()
{
IntPtr hWnd = GetWindow(GetWindow(FindWindow("Progman", "Program Manager"), GetWindow_Cmd.GW_CHILD), GetWindow_Cmd.GW_CHILD);
WINDOWINFO info = new WINDOWINFO();
info.cbSize = (uint)Marshal.SizeOf(info);
GetWindowInfo(hWnd, ref info);
return (info.dwStyle & 0x10000000) == 0x10000000;
}
add this dll reference to your project..
and call dllClass_name.ToggleDesktopIcon();
i would like to have the possibility to change the monitors brightness from a .NET desktop application. (running on win7 with nvidia gpu)
i found this winapi function:
https://msdn.microsoft.com/en-us/library/windows/desktop/dd692972(v=vs.85).aspx
and there are some SO questions with examples, but calling this does nothing for me.
but i found that my nvidia control panel allows to adjust the brightness with a slider.
so i was wondering if there is an API to use this functionality? and if maybe someone has some sample code on how to access it?
I am running win7 with AMD card and following example has worked for me.
SetBrightness expects argument in 0-100 range.
I have only one monitor to test so I set brightness just for first one.
using System;
using System.Runtime.InteropServices;
namespace SampleBrightness
{
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
public struct PHYSICAL_MONITOR
{
public IntPtr hPhysicalMonitor;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 128)]
public string szPhysicalMonitorDescription;
}
public class BrightnessController : IDisposable
{
[DllImport("user32.dll", EntryPoint = "MonitorFromWindow")]
public static extern IntPtr MonitorFromWindow([In] IntPtr hwnd, uint dwFlags);
[DllImport("dxva2.dll", EntryPoint = "DestroyPhysicalMonitors")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool DestroyPhysicalMonitors(uint dwPhysicalMonitorArraySize, ref PHYSICAL_MONITOR[] pPhysicalMonitorArray);
[DllImport("dxva2.dll", EntryPoint = "GetNumberOfPhysicalMonitorsFromHMONITOR")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool GetNumberOfPhysicalMonitorsFromHMONITOR(IntPtr hMonitor, ref uint pdwNumberOfPhysicalMonitors);
[DllImport("dxva2.dll", EntryPoint = "GetPhysicalMonitorsFromHMONITOR")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool GetPhysicalMonitorsFromHMONITOR(IntPtr hMonitor, uint dwPhysicalMonitorArraySize, [Out] PHYSICAL_MONITOR[] pPhysicalMonitorArray);
[DllImport("dxva2.dll", EntryPoint = "GetMonitorBrightness")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool GetMonitorBrightness(IntPtr handle, ref uint minimumBrightness, ref uint currentBrightness, ref uint maxBrightness);
[DllImport("dxva2.dll", EntryPoint = "SetMonitorBrightness")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool SetMonitorBrightness(IntPtr handle, uint newBrightness);
private uint _physicalMonitorsCount = 0;
private PHYSICAL_MONITOR[] _physicalMonitorArray;
private IntPtr _firstMonitorHandle;
private uint _minValue = 0;
private uint _maxValue = 0;
private uint _currentValue = 0;
public BrightnessController(IntPtr windowHandle)
{
uint dwFlags = 0u;
IntPtr ptr = MonitorFromWindow(windowHandle, dwFlags);
if (!GetNumberOfPhysicalMonitorsFromHMONITOR(ptr, ref _physicalMonitorsCount))
{
throw new Exception("Cannot get monitor count!");
}
_physicalMonitorArray = new PHYSICAL_MONITOR[_physicalMonitorsCount];
if (!GetPhysicalMonitorsFromHMONITOR(ptr, _physicalMonitorsCount, _physicalMonitorArray))
{
throw new Exception("Cannot get phisical monitor handle!");
}
_firstMonitorHandle = _physicalMonitorArray[0].hPhysicalMonitor;
if (!GetMonitorBrightness(_firstMonitorHandle, ref _minValue, ref _currentValue, ref _maxValue))
{
throw new Exception("Cannot get monitor brightness!");
}
}
public void SetBrightness(int newValue)
{
newValue = Math.Min(newValue, Math.Max(0, newValue));
_currentValue = (_maxValue - _minValue) * (uint)newValue / 100u + _minValue;
SetMonitorBrightness(_firstMonitorHandle, _currentValue);
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
protected virtual void Dispose(bool disposing)
{
if (disposing)
{
if (_physicalMonitorsCount > 0)
{
DestroyPhysicalMonitors(_physicalMonitorsCount, ref _physicalMonitorArray);
}
}
}
}
}
Hope this helps.
I'm trying to recover some items from Windows taskmanager.
With this code i recovered the SysListView32 handle from Process TAB:
(dlgItem)
IntPtr mainWindowHandle = Process.GetProcessesByName("taskmgr")[0].MainWindowHandle;
Api.WindowPlacement lpwndpl = new Api.WindowPlacement();
lpwndpl.length = Marshal.SizeOf((object) lpwndpl);
Api.GetWindowPlacement(mainWindowHandle, ref lpwndpl);
bool flag1 = lpwndpl.showCmd == 1 || lpwndpl.showCmd == 3;
IntPtr dlgItem = Api.GetDlgItem(Api.FindWindowEx(mainWindowHandle, IntPtr.Zero, (string) null, (string) null), 1009);
How can i recover the handle for SysListView32 Services TAB?
Some API definitions im using:
internal static class Api
{
public struct Rect
{
private int left;
private int top;
private int right;
private int bottom;
}
public struct Point
{
private int x;
private int y;
}
public struct WindowPlacement
{
public int length;
public int flags;
public int showCmd;
public Api.Point ptMinPosition;
public Api.Point ptMaxPosition;
public Api.Rect rcNormalPosition;
}
[DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool GetWindowPlacement(IntPtr hWnd, ref Api.WindowPlacement lpwndpl);
[DllImport("user32.dll")]
public static extern IntPtr GetDlgItem(IntPtr hDlg, int nIDDlgItem);
[DllImport("user32.dll", SetLastError = true)]
public static extern IntPtr FindWindowEx(IntPtr hwndParent, IntPtr hwndChildAfter, string lpszClass, string lpszWindow);
}
You must use FindWindowEx with a class name (lpszClass) equal to "#32770" and a Window Title (lpszWindow) equal to "Services". The ID of the child SysListView32 is then 3504 (0x0000db0).
Those datas come from Spy++, used on a French Windows Seven Pro 32bits OS.
I've tried to send text messages to various applications in Windows 7 (eg. Notepad++, Notepad etc.). SendMessage is working fine for Notepad but not for Notepad++.
If i'm sending text to Notepad everything appears fine, whole text and i'm getting 1 as return from SendMessage method. But for Notepad++ only first letter appears and method SendMessage is returning 0, however Marshal.GetLastWin32Error() is not returning any error (result 0)?
Here's the code:
GUITHREADINFO gti = new GUITHREADINFO();
IntPtr hWnd = GetForegroundWindow();
uint processId;
uint activeThreadId = GetWindowThreadProcessId(hWnd, out processId);
if (GetInfo(activeThreadId, out gti))
{
int EM_REPLACESEL = 0x00C2;
int error = Marshal.GetLastWin32Error();
int result = SendMessageW(gti.hwndCaret, EM_REPLACESEL, -1, passed);//3rd param doesn't change anything
error = Marshal.GetLastWin32Error();
}
WinAPI functions and GetInfo method as long with required structures are defined as:
[DllImport("User32.dll", EntryPoint = "SendMessageW", SetLastError = true, CharSet = CharSet.Unicode)]
public static extern int SendMessageW(IntPtr hWnd, int uMsg, int wParam, string lParam);
[DllImport("user32.dll")]
static extern IntPtr GetForegroundWindow();
[DllImport("user32.dll", SetLastError = true)]
static extern uint GetWindowThreadProcessId(IntPtr hWnd, out uint lpdwProcessId);
//"Borrowed" code
public static bool GetInfo(uint hwnd, out GUITHREADINFO lpgui)
{
uint lpdwProcessId;
uint threadId = GetWindowThreadProcessId(hwnd, out lpdwProcessId);
lpgui = new GUITHREADINFO();
lpgui.cbSize = Marshal.SizeOf(lpgui);
return GetGUIThreadInfo(threadId, ref lpgui);
}
[StructLayout(LayoutKind.Sequential)]
public struct RECT
{
public int iLeft;
public int iTop;
public int iRight;
public int iBottom;
}
[StructLayout(LayoutKind.Sequential)]
public struct GUITHREADINFO
{
public int cbSize;
public int flags;
public IntPtr hwndActive;
public IntPtr hwndFocus;
public IntPtr hwndCapture;
public IntPtr hwndMenuOwner;
public IntPtr hwndMoveSize;
public IntPtr hwndCaret;
public RECT rectCaret;
}
So well i wonder what should i do to fix it so it would work (fully) for all windows not only for edit control in Notepad?