DwmGetWindowAttribute returns wrong RECT - c#

first time writing a question here, this site helped me a lot thru the years, thanks !
DwmGetWindowAttribute doesn't return exact rectangle where the window is and its's size using this code :
[DllImport("User32.dll")]
public static extern IntPtr GetForegroundWindow();
[DllImport("dwmapi.dll")]
public static extern int DwmGetWindowAttribute(IntPtr hwnd, DwmWindowAttribute dwAttribute, out RECT pvAttribute, int cbAttribute);
Intptr m_current_active_window_handle = GetForegroundWindow();
DwmGetWindowAttribute(m_current_active_window_handle, DwmWindowAttribute.DWMWA_EXTENDED_FRAME_BOUNDS, out RECT __rv, Marshal.SizeOf(typeof(RECT)));
I want to get capture of active/foreground window at specific occasions and I tested on 2 different versions of windows and still not working with my setup..
Dual 1440p monitors (both 100% scaling)
Windows 10 Enteprise LTSC 2019
Windows 10 Pro (19042)
I have disabled animations during minimizie/maximize, dropshadow under windows
here is what I get and sometimes it returns me window with 2 extra pixels on top and non on the other 3 sides which have black border..
ps. ignore white region around the window, it is purposely there to show extra stuff around 'window':

Related

SystemParameters.SmallIconWidth returns 16 on any dpi, so how can I check for actual best icon size?

I thought SystemParameters.SmallIconWidth would tell me what's the best size icon for a small icon. However, even when I change the dpi in Settings->Display to 150% the value of SystemParameters.SmallIconWidth remains the same.
Is there a way to check for the best icon size?
(Why I thought that it should change by dpi - this answer, and this one by a user with more than 500k rep.)
Even if you declare full DPI awareness in the application manifest and/or at run-time, some Windows functions return 96 DPI (or System DPI) values for some reason. You have to pinvoke the new API:
public enum SystemMetric:int { SM_CXSMICON = 49 }
[DllImport("user32.dll")]
static extern int GetSystemMetricsForDpi(SystemMetric smIndex, uint dpi);
[DllImport("user32.dll")]
static extern uint GetDpiForWindow(IntPtr hwnd);
HwndSource source = (HwndSource)HwndSource.FromVisual(this);
IntPtr hWnd = source.Handle;
uint dpi = GetDpiForWindow(hWnd);
int width = GetSystemMetricsForDpi(SM_CXSMICON, dpi);
These functions only exist on Windows 10 update 1607 and later. If you need to support older versions you must manually scale the incorrect DPI value yourself (x = x * dpi / 96) instead of calling these functions.
See also:
Developing a Per-Monitor DPI-Aware WPF Application

Is there a way to capture the color of the screen pixel without taking screenshot C#?

I am making a program that detects a sector of the screen to perform an action that I require and I am doing it through screenshot reviewing pixel by pixel to find the sector that I want to analyze and compare with the change that I want but I have a problem, I use a timer to taking screenshot every 20 times per second and the sentences in charge of taking the screenshot end in an exception that I don't understand at all, it works fine at times until the exception "ArgumentsException" appears and the message "Parameters are not valid", so I do not know what may be happening, I am supposed to be sending the correct parameters and I am even setting the sentences to null thinking that something was left out but no, the same thing continues and I do not understand why.
Now, I don't know if there is any other way to directly detect and without taking screenshots the pixels of the sector that I want to find since I see that there is a problem regarding the sentences to capture an image from the screen.
The code I use to take screenshots is:
screenCapture = new Bitmap(Screen.PrimaryScreen.Bounds.Width, Screen.PrimaryScreen.Bounds.Height, PixelFormat.Format32bppRgb);
g = Graphics.FromImage(screenCapture);
g.CopyFromScreen(Screen.PrimaryScreen.Bounds.X, Screen.PrimaryScreen.Bounds.Y, 0, 0, screenCapture.Size, CopyPixelOperation.SourceCopy);
Sometimes the problem is in the bitmap, other times it is the graphics that come out with the same problem, so can you recommend me for the purpose that I require?
Without taking a screenshot you can use the Win32 API GetPixel: https://www.pinvoke.net/default.aspx/gdi32/getpixel.html
using System;
using System.Drawing;
using System.Runtime.InteropServices;
sealed class Win32
{
[DllImport("user32.dll")]
static extern IntPtr GetDC(IntPtr hwnd);
[DllImport("user32.dll")]
static extern Int32 ReleaseDC(IntPtr hwnd, IntPtr hdc);
[DllImport("gdi32.dll")]
static extern uint GetPixel(IntPtr hdc, int nXPos, int nYPos);
static public System.Drawing.Color GetPixelColor(int x, int y)
{
IntPtr hdc = GetDC(IntPtr.Zero);
uint pixel = GetPixel(hdc, x, y);
ReleaseDC(IntPtr.Zero, hdc);
Color color = Color.FromArgb((int)(pixel & 0x000000FF),
(int)(pixel & 0x0000FF00) >> 8,
(int)(pixel & 0x00FF0000) >> 16);
return color;
}
}
Alternatively consider Blit's as they're cheaper than screenshots, C# - Faster Alternatives to SetPixel and GetPixel for Bitmaps for Windows Forms App

Screen.PrimaryScreen.WorkingArea not always returning correct values

I am using Screen.PrimaryScreen.WorkingArea to place a popup window in the lower right corner of the primary screen. Normally, this works as it is intented to, but it has some issues when the application is being run on
a computer that is connected to different screens with different resolutions (like a laptop being moved between offices).
a computer that is an RDP server, which is connected to from clients with different resolutions (like a home computer being connected to from different offices).
It looks like the values of WorkingArea is not always up-to-date after having changed the resolution multiple (?) times in one of the above mentioned scenarios, which makes it difficult to correctly position the popup window.
Is there a way to force Screen.PrimaryScreen.WorkingArea to refresh, or is there any other ways of getting the screen resolution in a Windows Forms application that can be used instead?
You could try Pinvoke
[DllImport("user32.dll", SetLastError = false)]
static extern IntPtr GetDesktopWindow();
[DllImport("user32.dll", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
static extern bool GetWindowRect(IntPtr hWnd, ref RECT lpRect);
RECT scBounds = new RECT();
GetWindowRect(GetDesktopWindow(), ref scBounds);

Extending caption bar without glass

I saw that Windows 7 Wizard has the title bar extended without requiring Aero Glass. Look at this:
I made my application to work with Aero Glass, but how about withiut it?
Thanks in advance!
I haven't test this yet, but I think it will work, mark it as answer if you agree:
[DllImport("uxtheme")]
static extern int DrawThemeBackground(IntPtr hTheme, IntPtr hdc, int iPartId, int iStateId, ref RECT pRect, ref RECT pClipRect);
This method works, loog at this
You shouldn't need to do anything. The DWM is still running when using the Basic theme, it's just not doing any accelerated rendering.

Webcam snapp-shot without showing Camera Window c# Vista, Windows 7

Hi all am creating an message application but as soon as the app snatch a picture from my webcam it starts showing a window to choice a camera know its only one camera installed
[DllImport("user32", EntryPoint = "SendMessage")]
static extern int SendMessage(int hWnd, uint Msg, int wParam, int lParam);
[DllImport("avicap32.dll", EntryPoint = "capCreateCaptureWindowA")]
static extern int capCreateCaptureWindowA(string lpszWindowName, int dwStyle,
int X, int Y, int nWidth, int nHeight, int hwndParent, int nID);
const int WM_CAP_CONNECT = 1034;
const int WM_CAP_DISCONNECT = 1035;
const int WM_CAP_COPY = 1054;
const int WM_CAP_GET_FRAME = 1084;
This api works on windows xp with a service application so i created service app which pipe communicate with the appliaction and transfer the picture in bytes but note it only works on windows xp
how can i catch a webcam picture without this window am using some api in windows vista,7,8
Thanks B.
The API you are referring to (Video for Windows) is not supposed to operate without a window. The window however does not need to be visible, and you can move it out of work area too. It does not have to paint actually captured video as well, the window purpose is to communicate with the API. So it is usable in Window 7 too, provided of course that you have a well operating driver for these operating systems as well.
Other APIs you might want to look at are DirectShow and Media Foundation. DirectShow is the richest and best compatible throughout versions of Windows API, and you can do the task mentioned in the subject (capture without showing). From C# you typically work with it via DirectShow.NET library/binding and it has decent samples to look at on the website.

Categories