I'm making an application that I want the user to be able to click a button, that snaps Word or another program to take up 70% of the screen, and my application to take up the remaining 30%.
Is this possible?
Is there a native way to do it?
Is there a third party way to do it?
Thanks in advance for your help!
That is indeed possible, try this function:
[DllImport("user32.dll")]
private static extern bool GetWindowRect(IntPtr hwnd, ref Rectangle rectangle);
[DllImport("user32.dll", CharSet = CharSet.Auto)]
private static extern bool PostMessage(IntPtr hWnd, uint msg, int WPARAM, int LPARAM);
[DllImport("user32.dll", SetLastError = true)]
internal static extern bool MoveWindow(IntPtr hWnd, int X, int Y, int nWidth, int nHeight, bool bRepaint);
[DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool SetWindowPos(IntPtr hWnd, IntPtr hWndInsertAfter, int X, int, Y, int cx, int cy, uint uFlags);
public const uint WM_SYSCOMMAND = 0x0112;
public const int SC_NEXTWINDOW = 0xF040;
public static readonly IntPtr HWND_TOPMOST = new IntPtr(-1);
public static readonly IntPtr HWND_NOTOPMOST = new IntPtr(-2);
public static readonly IntPtr HWND_TOP = new IntPtr(0);
public static readonly IntPtr HWND_BOTTOM = new IntPtr(1);
public const UInt32 TOPMOST_FLAGS = 0x0002 | 0x0001;
Public void resisezeWindow(String procesname, int Width, int Height, Boolean bringtofront)
{
foreach (Process proc in Process.GetProcesses())
{
IntPtr id = proc.MainWindowHandle;
Rectangle rect = new Rectangle();
GetWindowRect(id, ref rect);
if (proc.MainWindowTitle.Contains(procesname))
{
PostMessage(proc.Handle, WM_SYSCOMMAND, SC_NEXTWINDOW, 0);
MoveWindow(id, 0, 0, Width, Height, true);
if(bringtofront) SetWindowPos(id, HWND_TOPMOST, 0, 0, 0, 0, TOPMOST_FLAGS);
proc.Refresh();
}
}
}
Klik here to see the original question.
Related
I have Binary file and run that with a batch file with this code :
call "login.exe" site sample.com -user myusername
then binar file ("login.exe") waiting for insert password (ask password from standard input)
And i want to send password with echo or sendkey to that using from batch file
I'm using from this code
call run_binary.bat
timeout /t 1
%SendKeys% "password{ENTER}"
what can i do ? that is possible ?
this is a good point to start if you want to interact with open windows from another application
using System;
using System.Collections.Generic;
using System.Text;
using System.Runtime.InteropServices;
namespace keystroke
{
public class handler
{
public const int WM_SYSCOMMAND = 0x0112;
public const int SC_CLOSE = 0xF060;
[DllImport("user32.dll")]
public static extern int FindWindow(
string lpClassName,
string lpWindowName
);
[DllImport("user32.dll")]
public static extern int SetForegroundWindow(
int hWnd
);
private const int GWL_EXSTYLE = (-20);
private const int WS_EX_TOOLWINDOW = 0x80;
private const int WS_EX_APPWINDOW = 0x40000;
public const int GW_HWNDFIRST = 0;
public const int GW_HWNDLAST = 1;
public const int GW_HWNDNEXT = 2;
public const int GW_HWNDPREV = 3;
public const int GW_OWNER = 4;
public const int GW_CHILD = 5;
public delegate int EnumWindowsProcDelegate(int hWnd, int lParam);
[DllImport("User32.Dll")]
public static extern void GetWindowText(int h, StringBuilder s, int nMaxCount);
[DllImport("user32", EntryPoint = "GetWindowLongA")]
public static extern int GetWindowLongPtr(int hwnd, int nIndex);
[DllImport("user32")]
public static extern int GetParent(int hwnd);
[DllImport("user32")]
public static extern int GetWindow(int hwnd, int wCmd);
[DllImport("user32")]
public static extern int IsWindowVisible(int hwnd);
[DllImport("user32")]
public static extern int GetDesktopWindow();
}
}
you can find if the window that on focus, and active a keylogger but this is malicious...
RenderTargetBitmap removes downgrades a RichtextBox's TextRenderingMode to GreyScale. So a captured PNG looks poor quality and doesnt match the WPF control
If I use WINDOWS ALT+PRINT SCREEN, the text is captured perfectly.
So how can I render the text control to the same quality as ALT+PRINT SCREEN.
Any advice would seriously be appreciated
All the best
You can use the same technique to render your window into the bitmap as windows using when taking a screen shot with Alt + Print Screen. The idea is to get a window handle and then render it to a bitmap using BitBlt system call.
Below is an example (you would need to reference the System.Drawing.dll assembly in your project to make it work):
public static void SaveToBitmapNative(Window window, FrameworkElement element, string fileName)
{
WindowInteropHelper helper = new WindowInteropHelper(window);
// detect the window client area position if rendering a child element
double incX = 0, incY = 0;
if (window != element)
{
System.Drawing.Point pos = new System.Drawing.Point(0, 0);
ClientToScreen(helper.Handle, ref pos);
incX = pos.X - (int)window.Left;
incY = pos.Y - (int)window.Top;
}
// transform child position to window coordinates
GeneralTransform transform = element.TransformToVisual(window);
Point point = transform.Transform(new Point(0, 0));
Rect rect = new Rect(point.X + incX, point.Y + incY, element.ActualWidth, element.ActualHeight);
// render window into bitmap
using (System.Drawing.Bitmap bitmap = new System.Drawing.Bitmap(
(int)rect.Width, (int)rect.Height, System.Drawing.Imaging.PixelFormat.Format32bppArgb))
{
using (System.Drawing.Graphics memoryGraphics = System.Drawing.Graphics.FromImage(bitmap))
{
IntPtr dc = memoryGraphics.GetHdc();
IntPtr windowDC = GetWindowDC(helper.Handle);
BitBlt(dc, 0, 0, (int)rect.Width, (int)rect.Height,
windowDC, (int)rect.Left, (int)rect.Top, TernaryRasterOperations.SRCCOPY);
memoryGraphics.ReleaseHdc(dc);
ReleaseDC(helper.Handle, windowDC);
}
// save bitmap to file
bitmap.Save(fileName);
}
}
[DllImport("gdi32.dll")]
static extern bool BitBlt(IntPtr hdcDest, int xDest, int yDest, int wDest, int hDest, IntPtr hdcSource, int xSrc, int ySrc, TernaryRasterOperations rop);
[DllImport("user32.dll")]
public static extern IntPtr GetWindowDC(IntPtr ptr);
[DllImport("user32.dll")]
static extern bool ReleaseDC(IntPtr hWnd, IntPtr hDc);
[DllImport("user32.dll")]
static extern bool ClientToScreen(IntPtr hWnd, ref System.Drawing.Point lpPoint);
public enum TernaryRasterOperations : uint
{
SRCCOPY = 0x00CC0020,
SRCPAINT = 0x00EE0086,
SRCAND = 0x008800C6,
SRCINVERT = 0x00660046,
SRCERASE = 0x00440328,
NOTSRCCOPY = 0x00330008,
NOTSRCERASE = 0x001100A6,
MERGECOPY = 0x00C000CA,
MERGEPAINT = 0x00BB0226,
PATCOPY = 0x00F00021,
PATPAINT = 0x00FB0A09,
PATINVERT = 0x005A0049,
DSTINVERT = 0x00550009,
BLACKNESS = 0x00000042,
WHITENESS = 0x00FF0062
}
here's how you can call this
private void saveButton_Click(object sender, RoutedEventArgs e)
{
// saves the entire window into the bitmap
SaveToBitmapNative(this, this, "c:\\test0.png");
// saves a child control (RichTextBox) into the bitmap
SaveToBitmapNative(this, richTextBox, "c:\\test1.png");
}
Note: this would not work for layered windows updated via UpdateLayeredWindow function.
hope this helps, regards
Winforms-How can I make dialog boxes appear centered on MainForm? That is as opposed to be based on Normal windows default which renders them in the centre of the screen.
In my case I have a small main form that may for example be positioned in a corner, the the MessageBox popup is displayed what seems a ways away.
It is possible with some servings of P/Invoke and the magic provided by Control.BeginInvoke(). Add a new class to your project and paste this code:
using System;
using System.Text;
using System.Drawing;
using System.Windows.Forms;
using System.Runtime.InteropServices;
class CenterWinDialog : IDisposable {
private int mTries = 0;
private Form mOwner;
public CenterWinDialog(Form owner) {
mOwner = owner;
owner.BeginInvoke(new MethodInvoker(findDialog));
}
private void findDialog() {
// Enumerate windows to find the message box
if (mTries < 0) return;
EnumThreadWndProc callback = new EnumThreadWndProc(checkWindow);
if (EnumThreadWindows(GetCurrentThreadId(), callback, IntPtr.Zero)) {
if (++mTries < 10) mOwner.BeginInvoke(new MethodInvoker(findDialog));
}
}
private bool checkWindow(IntPtr hWnd, IntPtr lp) {
// Checks if <hWnd> is a dialog
StringBuilder sb = new StringBuilder(260);
GetClassName(hWnd, sb, sb.Capacity);
if (sb.ToString() != "#32770") return true;
// Got it
Rectangle frmRect = new Rectangle(mOwner.Location, mOwner.Size);
RECT dlgRect;
GetWindowRect(hWnd, out dlgRect);
MoveWindow(hWnd,
frmRect.Left + (frmRect.Width - dlgRect.Right + dlgRect.Left) / 2,
frmRect.Top + (frmRect.Height - dlgRect.Bottom + dlgRect.Top) / 2,
dlgRect.Right - dlgRect.Left,
dlgRect.Bottom - dlgRect.Top, true);
return false;
}
public void Dispose() {
mTries = -1;
}
// P/Invoke declarations
private delegate bool EnumThreadWndProc(IntPtr hWnd, IntPtr lp);
[DllImport("user32.dll")]
private static extern bool EnumThreadWindows(int tid, EnumThreadWndProc callback, IntPtr lp);
[DllImport("kernel32.dll")]
private static extern int GetCurrentThreadId();
[DllImport("user32.dll")]
private static extern int GetClassName(IntPtr hWnd, StringBuilder buffer, int buflen);
[DllImport("user32.dll")]
private static extern bool GetWindowRect(IntPtr hWnd, out RECT rc);
[DllImport("user32.dll")]
private static extern bool MoveWindow(IntPtr hWnd, int x, int y, int w, int h, bool repaint);
private struct RECT { public int Left; public int Top; public int Right; public int Bottom; }
}
Sample usage:
private void button1_Click(object sender, EventArgs e) {
using (new CenterWinDialog(this)) {
MessageBox.Show("Nobugz waz here");
}
}
Note that this code works for any of the Windows dialogs. MessageBox, OpenFormDialog, FolderBrowserDialog, PrintDialog, ColorDialog, FontDialog, PageSetupDialog, SaveFileDialog.
This is for Win32 API, written in C. Translate it as you need...
case WM_NOTIFY:{
HWND X=FindWindow("#32770",NULL);
if(GetParent(X)==H_frame){int Px,Py,Sx,Sy; RECT R1,R2;
GetWindowRect(hwnd,&R1); GetWindowRect(X,&R2);
Sx=R2.right-R2.left,Px=R1.left+(R1.right-R1.left)/2-Sx/2;
Sy=R2.bottom-R2.top,Py=R1.top+(R1.bottom-R1.top)/2-Sy/2;
MoveWindow(X,Px,Py,Sx,Sy,1);
}
} break;
Add that to the WndProc code... You can set position as you like, in this case it just centres over the main program window. It will do this for any messagebox, or file open/save dialog, and likely some other native controls. I'm not sure, but I think you may need to include COMMCTRL or COMMDLG to use this, at least, you will if you want open/save dialogs.
I experimented with looking at the notify codes and hwndFrom of NMHDR, then decided it was just as effective, and far easier, not to. If you really want to be very specific, tell FindWindow to look for a unique caption (title) you give to the window you want it to find.
This fires before the messagebox is drawn onscreen, so if you set a global flag to indicate when action is done by your code, and look for a unique caption, you be sure that actions you take will only occur once (there will likely be multiple notifiers). I haven't explored this in detail, but I managed get CreateWindow to put an edit box on a messagebox dialog/ It looked as out of place as a rat's ear grafted onto the spine of a cloned pig, but it works. Doing things this way may be far easier than having to roll your own.
Crow.
EDIT: Small correction to make sure that the right window is handled. Make sure that parent handles agree throughout, and this should work ok. It does for me, even with two instances of the same program...
Write your own messagebox. A form and a label should do it. Or do you also need to globalize it?
The class proved to be applicable to two other situations. I had a FolderBrowserDialog that I wanted to be larger, and I wanted it to come up near the top-left of the parent dialog (near the button I click to open it).
I copied the CenterWinDialog class and made two new classes. One class changes the dialog size, and the other changes its position to a specific offset from the parent form. This is the usage:
using (new OffsetWinDialog(this) { PreferredOffset = new Point(75, 75 )})
using (new SizeWinDialog(this) { PreferredSize = new Size(400, 600)})
{
DialogResult result = dlgFolderBrowser.ShowDialog();
if (result == DialogResult.Cancel)
return;
}
and these are the two classes that were based on the original one.
class OffsetWinDialog : IDisposable
{
private int mTries = 0;
private Form mOwner;
public OffsetWinDialog(Form owner)
{
mOwner = owner;
owner.BeginInvoke(new MethodInvoker(findDialog));
}
public Point PreferredOffset { get; set; }
private void findDialog()
{
// Enumerate windows to find the message box
if (mTries < 0)
return;
EnumThreadWndProc callback = new EnumThreadWndProc(checkWindow);
if (EnumThreadWindows(GetCurrentThreadId(), callback, IntPtr.Zero))
{
if (++mTries < 10)
mOwner.BeginInvoke(new MethodInvoker(findDialog));
}
}
private bool checkWindow(IntPtr hWnd, IntPtr lp)
{
// Checks if <hWnd> is a dialog
StringBuilder sb = new StringBuilder(260);
GetClassName(hWnd, sb, sb.Capacity);
if (sb.ToString() != "#32770") return true;
// Got it
Rectangle frmRect = new Rectangle(mOwner.Location, mOwner.Size);
RECT dlgRect;
GetWindowRect(hWnd, out dlgRect);
MoveWindow(hWnd,
frmRect.Left + PreferredOffset.X,
frmRect.Top + PreferredOffset.Y,
dlgRect.Right - dlgRect.Left,
dlgRect.Bottom - dlgRect.Top,
true);
return false;
}
public void Dispose()
{
mTries = -1;
}
// P/Invoke declarations
private delegate bool EnumThreadWndProc(IntPtr hWnd, IntPtr lp);
[DllImport("user32.dll")]
private static extern bool EnumThreadWindows(int tid, EnumThreadWndProc callback, IntPtr lp);
[DllImport("kernel32.dll")]
private static extern int GetCurrentThreadId();
[DllImport("user32.dll")]
private static extern int GetClassName(IntPtr hWnd, StringBuilder buffer, int buflen);
[DllImport("user32.dll")]
private static extern bool GetWindowRect(IntPtr hWnd, out RECT rc);
[DllImport("user32.dll")]
private static extern bool MoveWindow(IntPtr hWnd, int x, int y, int w, int h, bool repaint);
private struct RECT { public int Left; public int Top; public int Right; public int Bottom; }
}
and
class SizeWinDialog : IDisposable
{
private int mTries = 0;
private Form mOwner;
public SizeWinDialog(Form owner)
{
mOwner = owner;
mOwner.BeginInvoke(new Action(findDialog));
}
public Size PreferredSize { get; set; }
private void findDialog()
{
// Enumerate windows to find the message box
if (mTries < 0)
return;
EnumThreadWndProc callback = new EnumThreadWndProc(checkWindow);
if (EnumThreadWindows(GetCurrentThreadId(), callback, IntPtr.Zero))
{
if (++mTries < 10)
mOwner.BeginInvoke(new MethodInvoker(findDialog));
}
}
private bool checkWindow(IntPtr hWnd, IntPtr lp)
{
// Checks if <hWnd> is a dialog
StringBuilder sb = new StringBuilder(260);
GetClassName(hWnd, sb, sb.Capacity);
if (sb.ToString() != "#32770")
return true;
// Got it
Rectangle frmRect = new Rectangle(mOwner.Location, mOwner.Size);
RECT dlgRect;
GetWindowRect(hWnd, out dlgRect);
SetWindowPos(new HandleRef(this, hWnd), new HandleRef(), dlgRect.Left, dlgRect.Top, PreferredSize.Width, PreferredSize.Height, 20 | 2);
return false;
}
public void Dispose()
{
mTries = -1;
}
// P/Invoke declarations
private delegate bool EnumThreadWndProc(IntPtr hWnd, IntPtr lp);
[DllImport("user32.dll")]
private static extern bool EnumThreadWindows(int tid, EnumThreadWndProc callback, IntPtr lp);
[DllImport("kernel32.dll")]
private static extern int GetCurrentThreadId();
[DllImport("user32.dll")]
private static extern int GetClassName(IntPtr hWnd, StringBuilder buffer, int buflen);
[DllImport("user32.dll")]
private static extern bool GetWindowRect(IntPtr hWnd, out RECT rc);
[DllImport("user32.dll", CharSet = CharSet.Auto, ExactSpelling = true)]
public static extern bool SetWindowPos(HandleRef hWnd, HandleRef hWndInsertAfter, int x, int y, int cx, int cy,
int flags);
private struct RECT { public int Left; public int Top; public int Right; public int Bottom; }
}
Create your own..
public partial class __MessageBox : Form
{
public MMMessageBox(string title, string message)
{
InitializeComponent();
this.Text = title;
this.labelString.Text = message;
}
}
How can I get the DPI in WPF?
https://learn.microsoft.com/en-us/archive/blogs/jaimer/getting-system-dpi-in-wpf-app seems to work
PresentationSource source = PresentationSource.FromVisual(this);
double dpiX, dpiY;
if (source != null) {
dpiX = 96.0 * source.CompositionTarget.TransformToDevice.M11;
dpiY = 96.0 * source.CompositionTarget.TransformToDevice.M22;
}
var dpiXProperty = typeof(SystemParameters).GetProperty("DpiX", BindingFlags.NonPublic | BindingFlags.Static);
var dpiYProperty = typeof(SystemParameters).GetProperty("Dpi", BindingFlags.NonPublic | BindingFlags.Static);
var dpiX = (int)dpiXProperty.GetValue(null, null);
var dpiY = (int)dpiYProperty.GetValue(null, null);
With .NET 4.6.2 Preview and higher, you can call VisualTreeHelper.GetDpi(Visual visual). It returns a DpiScale structure, which tells you the DPI at which the given Visual will be or has been rendered.
I have updated my answer from 2015. Here is some utility code that uses the latest DPI functions from Windows 10 (specifically GetDpiForWindow function which is the only method that supports the DPI_AWARENESS of the window/application/process, etc.) but falls back to older ones (dpi per monitor, and desktop dpi) so it should still work with Windows 7.
It has not dependency on WPF nor Winforms, only on Windows itself.
// note this class considers dpix = dpiy
public static class DpiUtilities
{
// you should always use this one and it will fallback if necessary
// https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-getdpiforwindow
public static int GetDpiForWindow(IntPtr hwnd)
{
var h = LoadLibrary("user32.dll");
var ptr = GetProcAddress(h, "GetDpiForWindow"); // Windows 10 1607
if (ptr == IntPtr.Zero)
return GetDpiForNearestMonitor(hwnd);
return Marshal.GetDelegateForFunctionPointer<GetDpiForWindowFn>(ptr)(hwnd);
}
public static int GetDpiForNearestMonitor(IntPtr hwnd) => GetDpiForMonitor(GetNearestMonitorFromWindow(hwnd));
public static int GetDpiForNearestMonitor(int x, int y) => GetDpiForMonitor(GetNearestMonitorFromPoint(x, y));
public static int GetDpiForMonitor(IntPtr monitor, MonitorDpiType type = MonitorDpiType.Effective)
{
var h = LoadLibrary("shcore.dll");
var ptr = GetProcAddress(h, "GetDpiForMonitor"); // Windows 8.1
if (ptr == IntPtr.Zero)
return GetDpiForDesktop();
int hr = Marshal.GetDelegateForFunctionPointer<GetDpiForMonitorFn>(ptr)(monitor, type, out int x, out int y);
if (hr < 0)
return GetDpiForDesktop();
return x;
}
public static int GetDpiForDesktop()
{
int hr = D2D1CreateFactory(D2D1_FACTORY_TYPE.D2D1_FACTORY_TYPE_SINGLE_THREADED, typeof(ID2D1Factory).GUID, IntPtr.Zero, out ID2D1Factory factory);
if (hr < 0)
return 96; // we really hit the ground, don't know what to do next!
factory.GetDesktopDpi(out float x, out float y); // Windows 7
Marshal.ReleaseComObject(factory);
return (int)x;
}
public static IntPtr GetDesktopMonitor() => GetNearestMonitorFromWindow(GetDesktopWindow());
public static IntPtr GetShellMonitor() => GetNearestMonitorFromWindow(GetShellWindow());
public static IntPtr GetNearestMonitorFromWindow(IntPtr hwnd) => MonitorFromWindow(hwnd, MONITOR_DEFAULTTONEAREST);
public static IntPtr GetNearestMonitorFromPoint(int x, int y) => MonitorFromPoint(new POINT { x = x, y = y }, MONITOR_DEFAULTTONEAREST);
private delegate int GetDpiForWindowFn(IntPtr hwnd);
private delegate int GetDpiForMonitorFn(IntPtr hmonitor, MonitorDpiType dpiType, out int dpiX, out int dpiY);
private const int MONITOR_DEFAULTTONEAREST = 2;
[DllImport("kernel32", CharSet = CharSet.Auto, SetLastError = true)]
private static extern IntPtr LoadLibrary(string lpLibFileName);
[DllImport("kernel32", CharSet = CharSet.Ansi, SetLastError = true)]
private static extern IntPtr GetProcAddress(IntPtr hModule, string lpProcName);
[DllImport("user32")]
private static extern IntPtr MonitorFromPoint(POINT pt, int flags);
[DllImport("user32")]
private static extern IntPtr MonitorFromWindow(IntPtr hwnd, int flags);
[DllImport("user32")]
private static extern IntPtr GetDesktopWindow();
[DllImport("user32")]
private static extern IntPtr GetShellWindow();
[StructLayout(LayoutKind.Sequential)]
private partial struct POINT
{
public int x;
public int y;
}
[DllImport("d2d1")]
private static extern int D2D1CreateFactory(D2D1_FACTORY_TYPE factoryType, [MarshalAs(UnmanagedType.LPStruct)] Guid riid, IntPtr pFactoryOptions, out ID2D1Factory ppIFactory);
private enum D2D1_FACTORY_TYPE
{
D2D1_FACTORY_TYPE_SINGLE_THREADED = 0,
D2D1_FACTORY_TYPE_MULTI_THREADED = 1,
}
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown), Guid("06152247-6f50-465a-9245-118bfd3b6007")]
private interface ID2D1Factory
{
int ReloadSystemMetrics();
[PreserveSig]
void GetDesktopDpi(out float dpiX, out float dpiY);
// the rest is not implemented as we don't need it
}
}
public enum MonitorDpiType
{
Effective = 0,
Angular = 1,
Raw = 2,
}
The only way I found to get the "real" monitor dpi is the following. All other mentioned techniques just say 96 which is not correct for the most monitors.
public class ScreenInformations
{
public static uint RawDpi { get; private set; }
static ScreenInformations()
{
uint dpiX;
uint dpiY;
GetDpi(DpiType.RAW, out dpiX, out dpiY);
RawDpi = dpiX;
}
/// <summary>
/// Returns the scaling of the given screen.
/// </summary>
/// <param name="dpiType">The type of dpi that should be given back..</param>
/// <param name="dpiX">Gives the horizontal scaling back (in dpi).</param>
/// <param name="dpiY">Gives the vertical scaling back (in dpi).</param>
private static void GetDpi(DpiType dpiType, out uint dpiX, out uint dpiY)
{
var point = new System.Drawing.Point(1, 1);
var hmonitor = MonitorFromPoint(point, _MONITOR_DEFAULTTONEAREST);
switch (GetDpiForMonitor(hmonitor, dpiType, out dpiX, out dpiY).ToInt32())
{
case _S_OK: return;
case _E_INVALIDARG:
throw new ArgumentException("Unknown error. See https://msdn.microsoft.com/en-us/library/windows/desktop/dn280510.aspx for more information.");
default:
throw new COMException("Unknown error. See https://msdn.microsoft.com/en-us/library/windows/desktop/dn280510.aspx for more information.");
}
}
//https://msdn.microsoft.com/en-us/library/windows/desktop/dd145062.aspx
[DllImport("User32.dll")]
private static extern IntPtr MonitorFromPoint([In]System.Drawing.Point pt, [In]uint dwFlags);
//https://msdn.microsoft.com/en-us/library/windows/desktop/dn280510.aspx
[DllImport("Shcore.dll")]
private static extern IntPtr GetDpiForMonitor([In]IntPtr hmonitor, [In]DpiType dpiType, [Out]out uint dpiX, [Out]out uint dpiY);
const int _S_OK = 0;
const int _MONITOR_DEFAULTTONEAREST = 2;
const int _E_INVALIDARG = -2147024809;
}
/// <summary>
/// Represents the different types of scaling.
/// </summary>
/// <seealso cref="https://msdn.microsoft.com/en-us/library/windows/desktop/dn280511.aspx"/>
public enum DpiType
{
EFFECTIVE = 0,
ANGULAR = 1,
RAW = 2,
}
This is how I managed to get a "scale factor" in WPF.
My laptop's resolution is 1920x1440.
int resHeight = System.Windows.Forms.Screen.PrimaryScreen.Bounds.Height; // 1440
int actualHeight = SystemParameters.PrimaryScreenHeight; // 960
double ratio = actualHeight / resHeight;
double dpi = resHeigh / actualHeight; // 1.5 which is true because my settings says my scale is 150%
Use GetDeviceCaps function:
static void Main(string[] args)
{
// 1.25 = 125%
var dpi = GetDpi();
}
[DllImport("user32.dll")]
public static extern int ReleaseDC(IntPtr hWnd, IntPtr hDC);
[DllImport("user32.dll")]
public static extern IntPtr GetDC(IntPtr hwnd);
[DllImport("gdi32.dll")]
static extern int GetDeviceCaps(IntPtr hdc, int nIndex);
private static float GetDpi()
{
IntPtr desktopWnd = IntPtr.Zero;
IntPtr dc = GetDC(desktopWnd);
var dpi = 100f;
const int LOGPIXELSX = 88;
try
{
dpi = GetDeviceCaps(dc, LOGPIXELSX);
}
finally
{
ReleaseDC(desktopWnd, dc);
}
return dpi / 96f;
}
You can try using ManagementClass:
public static string GetDPI()
{
using (ManagementClass mc = new ManagementClass("Win32_DesktopMonitor"))
{
using (ManagementObjectCollection moc = mc.GetInstances())
{
int PixelsPerXLogicalInch = 0; // dpi for x
int PixelsPerYLogicalInch = 0; // dpi for y
foreach (ManagementObject each in moc)
{
PixelsPerXLogicalInch = int.Parse((each.Properties["PixelsPerXLogicalInch"].Value.ToString()));
PixelsPerYLogicalInch = int.Parse((each.Properties["PixelsPerYLogicalInch"].Value.ToString()));
}
return PixelsPerXLogicalInch + "," + PixelsPerYLogicalInch;
}
}
}
There are
https://blogs.windows.com/buildingapps/2017/01/25/calling-windows-10-apis-desktop-application/#FJtMAIFjbtXiLQAp.97
January 25, 2017 3:54 pm
"Calling Windows 10 APIs From a Desktop Application"
and
https://learn.microsoft.com/en-us/uwp/api/windows.devices.display.displaymonitor
"DisplayMonitor Class"
Namespace: Windows.Devices.Display Assemblies:Windows.Devices.Display.dll, Windows.dll
Provides information about a display monitor device connected to the system.
These data include commonly used information from the monitor's Extended Display Identification Data (EDID, which is an industry-standard display descriptor block that nearly all monitors use to provide descriptions of supported modes and general device information) and DisplayID (which is a newer industry standard that provides a superset of EDID).
RawDpiX
Gets the physical horizontal DPI of the monitor (based on the monitor’s native resolution and physical size).
RawDpiY
Gets the physical vertical DPI of the monitor (based on the monitor’s native resolution and physical size).
Basic monitor info in Windows from 2006
https://learn.microsoft.com/en-us/windows/desktop/wmicoreprov/msmonitorclass
MSMonitorClass class
WmiMonitorRawEEdidV1Block class
WmiMonitorBasicDisplayParams class
MaxHorizontalImageSize ( EDID byte 21 )
MaxVerticalImageSize ( EDID byte 22 )
( Sizes in EDID are in centimeters above and in millimeters in EDID Detailed Timing Descriptor
12 Horizontal image size, mm, 8 lsbits (0–4095 mm, 161 in)
13 Vertical image size, mm, 8 lsbits (0–4095 mm, 161 in)
14 Bits 7–4 Horizontal image size, mm, 4 msbits
Bits 3–0 Vertical image size, mm, 4 msbits
)
and
https://social.msdn.microsoft.com/Forums/vstudio/en-US/e7bb9384-b343-4543-ac0f-c98b88a7196f/wpf-wmi-just-get-an-empty-string
As we all know, if the icon for a wpf window is undefined then the default icon is displayed. I want to display a window without any icon in the title bar. I realise that I could use a blank image, however this would cause the text in the title bar to be offset to the right.
Does anyone know of a way to completely remove the icon?
(I tried searching for a similar question but couldn't find anything.)
Simple, add this code to your window:
[DllImport("user32.dll")]
static extern uint GetWindowLong(IntPtr hWnd, int nIndex);
[DllImport("user32.dll")]
static extern int SetWindowLong(IntPtr hWnd, int nIndex, uint dwNewLong);
private const int GWL_STYLE = -16;
private const uint WS_SYSMENU = 0x80000;
protected override void OnSourceInitialized(EventArgs e)
{
IntPtr hwnd = new System.Windows.Interop.WindowInteropHelper(this).Handle;
SetWindowLong(hwnd, GWL_STYLE,
GetWindowLong(hwnd, GWL_STYLE) & (0xFFFFFFFF ^ WS_SYSMENU));
base.OnSourceInitialized(e);
}
While not exactly a proper solution, you could try one of the following things:
Setting the WindowStyle-Property to ToolWindow will make the Icon disappear, but the title bar (obviously) will be smaller.
Write a ControlTemplate for the whole Window. Depending on if the Window has to look like a "real" Window, there'd be much effort into trying to recreate the default Style in the Template.
I know this is answered, however Dan Rigsby's blog has an article that shows how to do this without hiding the minimize/maximize boxes.
I found this was frustrating me as I was using the articles (here and here but it kept hiding all the buttons when the sysmenu was hidden, to help I created this helper which as shown above call in OnSourceInitialized.
public static class WpfWindowHelper {
[DllImport("user32.dll")]
public static extern int GetWindowLong(IntPtr hwnd, int index);
[DllImport("user32.dll")]
public static extern int SetWindowLong(IntPtr hwnd, int index, int newStyle);
[DllImport("user32.dll")]
public static extern bool SetWindowPos(IntPtr hwnd, IntPtr hwndInsertAfter, int x, int y, int width, int height, uint flags);
public const int GWL_EXSTYLE = -20;
public const int WS_EX_DLGMODALFRAME = 0x0001;
public const int SWP_NOSIZE = 0x0001;
public const int SWP_NOMOVE = 0x0002;
public const int SWP_NOZORDER = 0x0004;
public const int SWP_FRAMECHANGED = 0x0020;
public const int GWL_STYLE = -16;
public const int WS_MAXIMIZEBOX = 0x00010000;
public const int WS_MINIMIZEBOX = 0x00020000;
public const int WS_SYSMENU = 0x00080000;
public static void HideSysMenu(this Window w) {
IntPtr hwnd = new WindowInteropHelper(w).Handle;
int extendedStyle = GetWindowLong(hwnd, GWL_EXSTYLE);
SetWindowLong(hwnd, GWL_EXSTYLE, extendedStyle | WS_EX_DLGMODALFRAME);
SetWindowPos(hwnd, IntPtr.Zero, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_FRAMECHANGED);
}
public static void HideMinimizeBox(this Window w) {
IntPtr hwnd = new WindowInteropHelper(w).Handle;
SetWindowLong(hwnd, GWL_STYLE,
GetWindowLong(hwnd, GWL_STYLE) & ~(WS_MINIMIZEBOX));
}
public static void HideMaximizeBox(this Window w) {
IntPtr hwnd = new WindowInteropHelper(w).Handle;
SetWindowLong(hwnd, GWL_STYLE,
GetWindowLong(hwnd, GWL_STYLE) & ~(WS_MAXIMIZEBOX));
}
public static void HideMinimizeAndMaximizeBoxes(this Window w) {
IntPtr hwnd = new WindowInteropHelper(w).Handle;
SetWindowLong(hwnd, GWL_STYLE,
GetWindowLong(hwnd, GWL_STYLE) & ~(WS_MAXIMIZEBOX | WS_MINIMIZEBOX));
}
}
No, this doesn't seem to be possible. Quoting from the documentation of the Icon property (emphasis mine):
A WPF window always displays an icon. When one is not provided by setting Icon, WPF chooses an icon to display based on the following rules:
Use the assembly icon, if specified.
If the assembly icon is not specified, use the default Microsoft Windows icon.
If you use Icon to specify a custom window icon, you can restore the default application icon by setting Icon to null.
So, apparently a completely transparent icon seems to be your best bet here. Or perhaps hack around all this by using Windows API functions to set the appropriate style on the window. But this may interfere with WPF's window management.
You can use an empty png image and convert it to icon and set it as icon for your window!!!
Add the following code to the main class of your Window to remove the maximize and minimize buttons, and hide the icon.
private const uint WS_MINIMIZEBOX = 0x00020000;
private const uint WS_MAXIMIZEBOX = 0x00010000;
private const int GWL_STYLE = -16;
private const int GWL_EXSTYLE = -20;
private const int SWP_NOSIZE = 0x0001;
private const int SWP_NOMOVE = 0x0002;
private const int SWP_NOZORDER = 0x0004;
private const int SWP_FRAMECHANGED = 0x0020;
private const int WM_SYSCOMMAND = 0x0112;
private const int WM_SETICON = 0x0080;
private const int WS_EX_DLGMODALFRAME = 0x0001;
[DllImport("user32.dll")]
public static extern int SendMessage(IntPtr hWnd, int wMsg, IntPtr wParam, IntPtr lParam);
[DllImport("user32.dll")]
private static extern uint GetWindowLong(IntPtr hwnd, int index);
[DllImport("user32.dll")]
private static extern int SetWindowLong(IntPtr hwnd, int index, uint newStyle);
[DllImport("user32.dll")]
private static extern bool SetWindowPos(IntPtr hwnd, IntPtr hwndInsertAfter, int x, int y, int width, int height, uint flags);
protected override void OnSourceInitialized(EventArgs e)
{
base.OnSourceInitialized(e);
IntPtr hwnd = new System.Windows.Interop.WindowInteropHelper(this).Handle;
uint styles = GetWindowLong(hwnd, GWL_STYLE);
// Remove the maximize and minimize buttons
styles &= 0xFFFFFFFF ^ (WS_MINIMIZEBOX | WS_MAXIMIZEBOX);
SetWindowLong(hwnd, GWL_STYLE, styles);
// Change to dialog modal - necessary for the final step to work!
styles = GetWindowLong(hwnd, GWL_EXSTYLE);
styles |= WS_EX_DLGMODALFRAME;
SetWindowLong(hwnd, GWL_EXSTYLE, styles);
SetWindowPos(hwnd, IntPtr.Zero, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_FRAMECHANGED);
((HwndSource)PresentationSource.FromVisual(this)).AddHook(HelpButtonHook);
// Remove the icon
SendMessage(hwnd, WM_SETICON, new IntPtr(1), IntPtr.Zero);
SendMessage(hwnd, WM_SETICON, IntPtr.Zero, IntPtr.Zero);
}
My first suggestion would be don't do it. In WinForms you can use types of formborderstyles to create a dialog box that has no icon, but only because that is a Windows standard. Only forms with those specific border types should have no icon; it's what users expect.