Is it possible to reserve a screen area near an edge of the screen for your app in Windows 7? It would behave similar to the Windows taskbar (i.e. maximized windows would not overlap with it).
I'm writing a taskbar app with proper support for multiple monitors. The primary purpose is to show a taskbar on each screen containing only the apps on that screen. None of the existing solutions (Ulltramon, DisplayFusion) I know of work for Win 7, and none are open source.
C# code would be nice, but any hints are appreciated as well.
I feel silly answering my own question, but thanks to Michael's hint, I found an appropriate C# code sample.
using System;
using System.Runtime.InteropServices;
public class WorkArea
{
[System.Runtime.InteropServices.DllImport("user32.dll", EntryPoint="SystemParametersInfoA")]
private static extern Int32 SystemParametersInfo(Int32 uAction, Int32 uParam, IntPtr lpvParam, Int32 fuWinIni);
private const Int32 SPI_SETWORKAREA = 47;
public WorkArea(Int32 Left,Int32 Right,Int32 Top,Int32 Bottom)
{
_WorkArea.Left = Left;
_WorkArea.Top = Top;
_WorkArea.Bottom = Bottom;
_WorkArea.Right = Right;
}
public struct RECT
{
public Int32 Left;
public Int32 Right;
public Int32 Top;
public Int32 Bottom;
}
private RECT _WorkArea;
public void SetWorkingArea()
{
IntPtr ptr = IntPtr.Zero;
ptr = Marshal.AllocHGlobal(Marshal.SizeOf(_WorkArea));
Marshal.StructureToPtr(_WorkArea,ptr,false);
int i = SystemParametersInfo(SPI_SETWORKAREA,0,ptr,0);
}
}
I'm unsure of how to do this directly in C#, but in native code you can call SystemParametersInfo with SPI_SETWORKAREA. This is how apps like the taskbar, sidebar, and so on can prevent maximized windows from overlapping them.
http://msdn.microsoft.com/en-us/library/ms724947.aspx is the documentation for SystemParametersInfo.
http://social.msdn.microsoft.com/forums/en-US/winforms/thread/9fe831e5-ccfb-4e8d-a129-68c301c83acb/ shows P/Invoke signatures for this method.
Related
I am a beginner at coding and I want to create an application that says the width, height, and position of the window.
The problem is that I don't know how to GET the position of the window.
I searched the internet but couldn't find the answer to my question.
Here is the code I have:
using System;
namespace WindowSizeChecker
{
class Program
{
const bool alwaysTrue = true;
static void Main(string[] args)
{
while (alwaysTrue == true)
{
Console.Write("Set your console window to your prefered size and position. Then press Enter");
Console.ReadLine();
screenSizeAndPosition();
Console.WriteLine("\n\nPress enter to repeat\n\n");
Console.ReadLine();
}
}
public static void screenSizeAndPosition()
{
int consoleWidth = Console.WindowWidth;
int consoleHeight = Console.WindowHeight;
string consoleWidthString = consoleWidth.ToString();
string consoleHeightString = consoleHeight.ToString();
Console.WriteLine("\nThe width of the window is: {0}\nAnd the height of the window is: {1}", consoleWidthString, consoleHeightString);
int largestWindowWidth = Console.LargestWindowWidth;
int largestWindowHeight = Console.LargestWindowHeight;
string largestWindowWidthString = largestWindowWidth.ToString();
string largestWindowHeightString = largestWindowHeight.ToString();
Console.WriteLine("\nThe largest width of the window is: {0}\nAnd the largest height of the window is: {1}", largestWindowWidthString, largestWindowHeightString);
}
}
}
Here is the program running:
enter image description here
I am a beginner at coding and I want to create an application that says the width, height, and position of the window. The problem is that I don't know how to GET the position of the window. I searched the internet but couldn't find the answer to my question.
The information is out there, but I admit, it's not necessarily presented in the easiest to understand manner, especially for a beginner.
IMHO, two of the most relevant Stack Overflow questions you probably should read are these:
Position a small console window to the bottom left of the screen?
DwmGetWindowAttribute returns 0 with PInvoke
They aren't really duplicates of your question, and for a beginner it's probably hard to see how they answer it. But they do in fact contain almost all of the information you would need.
There are a couple of things you need to understand, besides the "how":
The Console properties you're looking at now are not pixel dimensions, but rather are in terms of character columns and rows. That is, how many characters can fit across the window in a single row, and how many rows of those characters can fit vertically.
When it comes to pixels, there are actually (at least) two different ways to look at the window size: raw screen coordinates, and "DPI-adjusted". The latter is IMHO a misnomer, because it's not taking into account any actual screen resolution (i.e. "dots per inch"), but rather the scaling factor that is set for your desktop. It's considered "DPI-adjusted" because setting the scaling factor is the Windows mechanism for attempting to keep the visual presentation of a program consistent across displays of different resolution.
As you already have seen, you can get the character-oriented dimensions straight from the .NET Console class. But to get the pixel information, you need to use .NET's native interop support to call the Windows API directly. Here are some helper classes I put together, based on available documentation and Stack Overflow posts, to do that for your scenario:
[StructLayout(LayoutKind.Sequential)]
struct Rect
{
public int Left;
public int Top;
public int Right;
public int Bottom;
public int Width => Right - Left;
public int Height => Bottom - Top;
}
class NativeConsole
{
[DllImport("kernel32")]
public static extern IntPtr GetConsoleWindow();
}
class Winuser
{
[DllImport(#"user32.dll", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool GetWindowRect(IntPtr hWnd, out Rect lpRect);
public static Rect GetWindowRect(IntPtr handle)
{
if (!GetWindowRect(handle, out Rect rect))
{
throw Marshal.GetExceptionForHR(Marshal.GetLastWin32Error());
}
return rect;
}
}
class DwmApi
{
private const int DWMWA_EXTENDED_FRAME_BOUNDS = 9;
[DllImport(#"dwmapi.dll")]
private static extern int DwmGetWindowAttribute(IntPtr hwnd, int dwAttribute, out Rect pvAttribute, int cbAttribute);
public static Rect GetExtendedFrameBounds(IntPtr hwnd)
{
int hresult = DwmGetWindowAttribute(hwnd, DWMWA_EXTENDED_FRAME_BOUNDS, out Rect rect, Marshal.SizeOf(typeof(Rect)));
if (hresult != 0)
{
throw Marshal.GetExceptionForHR(hresult);
}
return rect;
}
}
You could, of course, lump all of the above together in a single class, but I prefer to keep things organized. The above groups the various parts of the API into the same organization used in the native Win32 API itself.
With those pieces in hand, now we can put together a program similar to the one you have above, except that it will display the window position (which is what you want), along with the width and height as well (since those come for free from the native API anyway).
That looks like this:
using static System.Console;
class Program
{
static void Main(string[] args)
{
Clear();
string prompt = "Set your console window to your preferred size and position. Press X to exit";
while (true)
{
if (KeyAvailable && ReadKey(intercept: true).Key == ConsoleKey.X)
{
break;
}
ScreenSizeAndPosition(prompt);
System.Threading.Thread.Sleep(TimeSpan.FromSeconds(0.25));
}
}
static void ScreenSizeAndPosition(string prompt)
{
string format = $"{{0, {-WindowWidth}}}";
SetCursorPosition(0, 0);
Write(format, prompt);
Write(format, $"Window is {WindowWidth} columns wide and {WindowHeight} rows high");
Write(format, $"The largest window that can fit on the screen is {LargestWindowWidth} columns wide and {LargestWindowHeight} rows high");
IntPtr consoleHwnd = NativeConsole.GetConsoleWindow();
Rect winuserRect = Winuser.GetWindowRect(consoleHwnd),
dwmRect = DwmApi.GetExtendedFrameBounds(consoleHwnd);
Write(format, $"DPI-adjusted screen values: location is {{{winuserRect.Left}, {winuserRect.Top}}}, window is {winuserRect.Width} pixels wide, {winuserRect.Height} pixels high");
Write(format, $"Desktop Window Manager values: location is {{{dwmRect.Left}, {dwmRect.Top}}}, window is {dwmRect.Width} pixels wide, {dwmRect.Height} pixels high");
for (int i = 0; i < WindowHeight - 5; i++)
{
Write(format, "");
}
}
}
I did change your basic logic in the program a bit, so that it just checks every quarter second rather than waiting for the user to press a key, displaying whatever the current values are as the user changes the window size and position.
For more details on the Windows functions used above, you should read the documentation:
GetConsoleWindow()
GetWindowRect()
DwmGetWindowAttribute()
There are some additional subtleties in the ways that GetWindowRect() and DwmGetWindowAttribute() work, so it's worth checking out the docs so that you understand better what they are returning in terms of the window dimensional values.
You should call a Win32 API DwmGetWindowAttribute via PInovke to the current window position. Refer to the document and see how to use it.
So, I have been asked to figure out a way to make a program containing sensitive data more secure since we have staff that go afk and put potentially put data at risk.
I have loaded up Visual Studio for C# and found a nice way to get process of the fore mentioned application. Then grab the main window and attach a panel of my very own. This panel will basically now be used like a blind covering the application when its not in use.
Now, I have a program running in system tray waiting for the sensitive data to come on screen and my little panel hijacks the entire window and now nothing can be seen.
My problem now is how ever, that whilst my panel is attacked the main window of the application i am trying to lock out seems to just crash. I am guessing that is because my panel and the application belong to different processes.
Anyway I could do with some advise here.
Here is my panels class.
class LockingPanel : System.Windows.Forms.Panel
{
private IntPtr prn;
[DllImport("user32.dll", SetLastError = true)]
static extern IntPtr SetParent(IntPtr hWndChild, IntPtr hWndNewParent);
public void SetParent(IntPtr parent)
{
prn = parent;
SetParent(this.Handle, prn);
}
public IntPtr GetParent() {
return prn;
}
[DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
static extern bool GetWindowRect(IntPtr hWnd, ref RECT Rect);
[StructLayout(LayoutKind.Sequential)]
public struct RECT
{
public int Left; // x position of upper-left corner
public int Top; // y position of upper-left corner
public int Right; // x position of lower-right corner
public int Bottom; // y position of lower-right corner
}
public void FillParent()
{
RECT rtc = new RECT();
GetWindowRect(prn, ref rtc);
this.Location = new System.Drawing.Point(0, 0);
this.Size = new System.Drawing.Size(rtc.Right, rtc.Bottom);
}
Anybody got a better idea on how I can go about this, or at least make it so that my panel inst going to crash the application.
I want to get Screenshots of a possible hidden Window of another application that is using drawing via direct3d or opengl. I tryed a lot of ways to receive this windows content but only got black or transparent pictures. The closest i got was by using a DWM sample here
http://bartdesmet.net/blogs/bart/archive/2006/10/05/4495.aspx
this paints the window onto my c# form but i cant get the pixelcolors. If ill do a form.drawtobitmap the pixels drawn by dwm are missing.
So is their any way to use DWM to recive the capture into a image
or to get the image drawn onto my form?
To answer your question:
You can use GetPixel() Win32 function. But it's overkill in this situation.
Pinvoke GetPixel
MSDN GetPixel
The right way, is to get the device context and bit blit the content.
EDIT:
I've thrown together some code, by using PrintWindow. Seems to work quite well, even with media players. Note that GetWindowRect returns invalid rectangle for minimized Windows. But it's a decent start.
[StructLayout(LayoutKind.Sequential)]
public struct Rect
{
internal Rect(int left, int top, int right, int bottom)
{
Left = left;
Top = top;
Right = right;
Bottom = bottom;
}
public int Left;
public int Top;
public int Right;
public int Bottom;
}
[DllImport("user32.dll", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
static extern bool PrintWindow(IntPtr hwnd, IntPtr hDC, uint nFlags);
[DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool GetWindowRect(IntPtr hwnd, out Rect lpRect);
public void DumpWindow(IntPtr hwndSource, string filename)
{
Rect rc;
GetWindowRect(hwndSource, out rc);
var bmp = new Bitmap(rc.Right - rc.Left, rc.Bottom - rc.Top, PixelFormat.Format32bppArgb);
using (Graphics gBmp = Graphics.FromImage(bmp))
{
IntPtr hdcBmp = gBmp.GetHdc();
PrintWindow(hwndSource, hdcBmp, 0);
gBmp.ReleaseHdc(hdcBmp);
}
bmp.Save(filename);
}
Edit2:
And if you add a second button to DWM demo form, insert this:
private void button1_Click(object sender, EventArgs e)
{
var w = (Window)lstWindows.SelectedItem;
DumpWindow(w.Handle, "test.bmp");
Process.Start("test.bmp");
}
It still shows an empty image?
i'm using c# .net 4.5;
my question is how could i get the cmd location.
for example to get my own form location i use this.Location and i'm getting the x and the y.
how could i do it for an application which is running but has nothing to do with my own app? i know it's possible because windows 8 use something like that. :)
thanks for helping...
Your question at first glance seems you want the location of the application exe and not the position of the window. If you want the position of the window you need to use API.
[StructLayout(LayoutKind.Sequential)]
public struct Rect
{
public int left;
public int top;
public int right;
public int bottom;
}
[DllImport("user32.dll")]
public static extern IntPtr GetWindowRect(IntPtr hWnd, ref Rect rect
And then use it like so:
var proc = Process.GetProcessesByName(proccessName)[0];
Rect rect = new Rect();
GetWindowRect(proc.MainWindowHandle, ref rect);
Hope it helps
For more information look at MSDN and pInvoke
Problem
When you search for such question using google you get a lot of hits but all solutions assume you have at least one window.
But my question is just like I phrased it -- not assumptions at all. I can have a window, but I could have zero windows (because I didn't even show one or I just closed the last one). So in short the solution cannot rely on any widget or window -- the only thing is known, is there is a desktop (and app running, but it does not have any windows).
So the question is -- how to get the mouse position?
Background
I would like to show windows centered to mouse position. There is no such mode in WPF (there are only center to owner, or center to screen) so I have to do it manually. The missing piece is mouse position.
Edits
Thank you all, so now I have the first part of the solution -- raw position. Now there is a problem how to convert the data for WPF. I found such topic:
WPF Pixels to desktop pixels
but again, it assumes having some window.
Then I googled more and I found solution:
http://jerryclin.wordpress.com/2007/11/13/creating-non-rectangular-windows-with-interop/
the code includes class for scaling up/down coordinates relying only on info about desktop. So joining those two pieces, I finally get the solution :-). Thanks again.
Getting the Screen Coordinates:
[DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
static extern bool GetCursorPos(out POINT lpPoint);
[StructLayout(LayoutKind.Sequential)]
public struct POINT
{
public int X;
public int Y;
public POINT(int x, int y)
{
this.X = x;
this.Y = y;
}
}
private void WritePoint(object sender, RoutedEventArgs e)
{
POINT p;
if (GetCursorPos(out p))
{
System.Console.WriteLine(Convert.ToString(p.X) + ";" + Convert.ToString(p.Y));
}
}
Converting Pixels to WPF Units:
[DllImport("User32.dll")]
static extern IntPtr GetDC(IntPtr hwnd);
[DllImport("gdi32.dll")]
static extern int GetDeviceCaps(IntPtr hdc, int nIndex);
[DllImport("user32.dll")]
static extern bool ReleaseDC(IntPtr hWnd, IntPtr hDC);
private Point ConvertPixelsToUnits(int x, int y)
{
// get the system DPI
IntPtr dDC = GetDC(IntPtr.Zero); // Get desktop DC
int dpi = GetDeviceCaps(dDC, 88);
bool rv = ReleaseDC(IntPtr.Zero, dDC);
// WPF's physical unit size is calculated by taking the
// "Device-Independant Unit Size" (always 1/96)
// and scaling it by the system DPI
double physicalUnitSize = (1d / 96d) * (double)dpi;
Point wpfUnits = new Point(physicalUnitSize * (double)x,
physicalUnitSize * (double)y);
return wpfUnits;
}
Putting both together:
private void WriteMouseCoordinatesInWPFUnits()
{
POINT p;
if (GetCursorPos(out p))
{
Point wpfPoint = ConvertPixelsToUnits(p.X, p.Y);
System.Console.WriteLine(Convert.ToString(wpfPoint.X) + ";" + Convert.ToString(wpfPoint.Y));
}
}
Two options:
Use System.Windows.Forms.Control.MousePosition, or p/invoke
[DllImport("user32.dll", CharSet=CharSet.Auto, ExactSpelling=true)]
public static extern bool GetCursorPos([In, Out] NativeMethods.POINT pt);
The first option already does the p/invoke for you. I'm not entirely sure it requires you have some UI splashed up, but I don't think so. Yes, its winforms and not wpf, but it really doesn't have anything to do with where its located at.
If you want to skip any dependencies on system.windows.forms.dll then check out more information about the second on pinvoke.net.
I stumbled over that thread while looking for a solution for the same problem. In the meantime, I found PointToScreen, which does not require any P/Invoke. The method is available on any Visual starting .NET 3.0 (and thus UIElement, Control, etc.) and an implementation would look like this:
protected void OnMouseLeave(object Sender, MouseEventArgs e) {
var relativePosition = e.GetPosition(this);
var screenPosition = this.PointToScreen(relativePosition);
}