I am trying to capture the screen of the PC connected to my PC via HDMI using Direct-show. I am using capture card as the hardware and Direct show's sample grabber method to render those captured frames.
The issue is I am not able to render the full screen of the secondary monitor on to my computer. Both PC's are of different configuration. I have tried giving different frame size values like 1366*768 but it just picks up 1280*768 I believe .
Moreover I have set the frame size to be captured as 1366*768 and even my PC is set to the same display setting still it does not render the full screen.
Here is the code I am using for capturing and rendering. Capture class has a property called frame size whose size has been set to 1366*768 but as soon as I do that and run the code it shows a total blank screen and when i change the setting to 1280*768 it will render the secondary monitor but won't render the full screen of it.
Size size = new Size(1366, 768);
capture.FrameSize = size;
where capture class has the below given property
public Size FrameSize
{
get
{
BitmapInfoHeader bmiHeader;
bmiHeader = (BitmapInfoHeader) getStreamConfigSetting( videoStreamConfig, "BmiHeader" );
// Size size = new Size( bmiHeader.Width, bmiHeader.Height );
Size size = new Size(1280, 768);
return( size );
}
set
{
BitmapInfoHeader bmiHeader;
bmiHeader = (BitmapInfoHeader) getStreamConfigSetting( videoStreamConfig, "BmiHeader" );
bmiHeader.Width = 1280;
bmiHeader.Height = 768;
setStreamConfigSetting( videoStreamConfig, "BmiHeader", bmiHeader );
//#if NEWCODE
this.videoCaps = null;
//#endif
}
}
Any suggestions or findings that how can I capture the full screen of the secondary monitor will be really appreciated.
Related
I am using Opencvsharp from shimat for building an application. Code simply opens camera, saves the image and close it using below code.
using OpenCvSharp;
VideoCapture capture;
Mat frame;
private void btn_Camera_Click(object sender, EventArgs e)
{
capture = new VideoCapture();
frame = new Mat();
capture.Open(1);
capture.Read(frame);
if (capture.Read(frame))
{
frame.SaveImage("#test.jpg");
}
capture.Release();
}
However the picture is saved at 640x480 resolution whereas the camera is capable of capturing 1280x720 resolution pictures.
I tried setting the VideoCapture properties like below
capture.Set(VideoCaptureProperties.FrameHeight, 720);
capture.Set(VideoCaptureProperties.FrameWidth, 1280);
But still the saved image is of 480p resolution. Is there a way to save it at 720p resolution, like the default windows camera app does.
Also I don't want to save it in 480p and then resize to 720p as that doesn't help in getting the details that needs to captured.
I know in opencv Python its possible. Am looking for something similar in C# with Opencvsharp4
When capturing via OpenCvSharp, 640x480 is the default resolution.
You must set the desired resolution before the device is opened (which is done implicitly when you grab frames) e.g.:
int frameWidth = 1280;
int frameHeight = 720;
int cameraDeviceId = 1;
var videoCapture = VideoCapture.FromCamera(cameraDeviceId);
if (!videoCapture.Set(VideoCaptureProperties.FrameWidth, frameWidth))
{
logger.LogWarning($"Failed to set FrameWidth to {frameWidth}");
}
if (!videoCapture.Set(VideoCaptureProperties.FrameHeight, frameHeight))
{
logger.LogWarning($"Failed to set FrameHeight to {frameHeight}");
}
using (videoCapture)
{
videoCapture.Grab();
var image = videoCapture.RetrieveMat();
logger.LogInformation($"Image size [{image.Width} x {image.Height}]");
}
I'm trying to display an overlay during an auto login HTTP call.
I've found this code, which seems outdated somehow, but found nothing more recent.
Anyway, the Overlay is showing but not covering the whole screen as expected.
The calling code is this:
AppDelegate.FinishedLaunching
var avc = new AutoLoginViewController();
var navController = new UINavigationController(avc);
AutoLoginViewController.ViewDidLoad
var bounds = UIScreen.MainScreen.Bounds;
// show the loading overlay on the UI thread using the correct orientation sizing
loadPop = new LoadingOverlay(bounds, NSBundle.MainBundle.GetLocalizedString("connecting"));
View.Add(loadPop);
But the result is the following:
If I set a breakpoint in the LoadingOverlay constructor, I can see that the screen bounds (iPhone 6) are fine:
{{X=0,Y=0,Width=375,Height=667}}
public class LoadingOverlay : UIView
{
public LoadingOverlay(CGRect frame, string text) : base(frame)
{
// configurable bits
BackgroundColor = UIColor.Black;
Alpha = 0.75f;
AutoresizingMask = UIViewAutoresizing.FlexibleDimensions;
...
}
}
Clearly the UIView width is incorrect.
Because we're in 2020, maybe there is another way.
Any help appreciated.
EDIT: The app breaks on iPhone 8 iOS 13.3 simulator, So I can't say if this is tied to a particular screen size (1x in my case).
Cause :
It seems that you didn't set the LaunchImage , So whether on a simulator or real device , the value of bounds is a static value .
Solution:
The easiest way is set the size of overlay as bounds of View .
var bounds = View.Bounds;
Or you could set all size of LaunchImage of different screen .
In the below version of App.xaml.cs, written using Visual Studio 2019, associated with my Windows C# UWP solution / project called Example_Application, class App's constructor successfully resizes the blue app window that appears when starting the app. My question: Assuming a resolution scale of 1, just to make things easier, how do I change 1920 and 1080 to the two numbers comprising my Windows-10 display resolution?
namespace Example_Application
{
sealed partial class App : Windows.UI.Xaml.Application
{
public App()
{
Windows.UI.ViewManagement.ApplicationView.PreferredLaunchViewSize = new Windows.Foundation.Size(1920, 1080);
Windows.UI.ViewManagement.ApplicationView.PreferredLaunchWindowingMode = Windows.UI.ViewManagement.ApplicationViewWindowingMode.PreferredLaunchViewSize;
}
protected override void OnLaunched(Windows.ApplicationModel.Activation.LaunchActivatedEventArgs e)
{
Windows.UI.Xaml.Controls.Frame rootFrame = new Windows.UI.Xaml.Controls.Frame();
Windows.UI.Xaml.Window.Current.Content = rootFrame;
rootFrame.Navigate(typeof(MainPage), e.Arguments);
Windows.UI.Xaml.Window.Current.Activate();
}
}
}
Things I've tried:
Changing "PreferredLaunchViewSize" to "Maximized" does not maximize my blue window on my monitor. Changing "PreferredLaunchViewSize" to "FullScreen" does make my application take up the full screen, but this is not what I want because I want to be able to see my application title bar and my Windows-10 taskbar.
I can write Windows.Foundation.Rect visibleBounds = Windows.UI.ViewManagement.ApplicationView.GetForCurrentView().VisibleBounds; only at the very end of OnLaunched, and bounds' Width and Height properties return present application width and height, not Windows-10 display resolution.
I can write uint screenWidthInRawPixels = Windows.Graphics.Display.DisplayInformation.GetForCurrentView().ScreenWidthInRawPixels; only at the very end of OnLaunched, and screenWidthInRawPixels is the present application width, not Windows-10 display width.
To get the screen resolution in UWP apps, you could try to use DisplayInformation.ScreenHeightInRawPixels Property and DisplayInformation.ScreenWidthInRawPixels Property.
Like the following code:
protected override void OnLaunched(LaunchActivatedEventArgs e)
{
Frame rootFrame = Window.Current.Content as Frame;
........
Window.Current.Activate();
}
//screen resolution
string heightsize = DisplayInformation.GetForCurrentView().ScreenHeightInRawPixels.ToString();
string widthsize = DisplayInformation.GetForCurrentView().ScreenWidthInRawPixels.ToString();
Size mysize = new Size(Convert.ToDouble(widthsize), Convert.ToDouble(heightsize));
ApplicationView.PreferredLaunchViewSize = mysize;
ApplicationView.PreferredLaunchWindowingMode = ApplicationViewWindowingMode.PreferredLaunchViewSize;
}
My resolution is 1920*1080. In my test, it could get my screen resolution correctly as 1920*1080.
Ultimately, I choose to maximize my UWP App (written in C#) in my workspace, that area of my screen above my Windows taskbar. I would like to provide minimal instructions for creating a maximized app that you know is working.
I created a new default Blank App (Universal Windows) using C# in Visual Studio Community 2019, called "Draw Bounding Boxes". I included spaces here so that I could access "Draw Bounding Boxes" with spaces from my Start Menu.
I replaced the contents of "App.xaml.cs" with the following code block.
namespace Draw_Bounding_Boxes
{
/// <summary>
/// Provides application-specific behavior to supplement the default Application class.
/// </summary>
sealed partial class App : Windows.UI.Xaml.Application
{
/// <summary>
/// Invoked when the application is launched normally by the end user. Other entry points
/// will be used such as when the application is launched to open a specific file.
/// </summary>
/// <param name="e">Details about the launch request and process.</param>
protected override void OnLaunched(Windows.ApplicationModel.Activation.LaunchActivatedEventArgs e)
{
// Resize app.
uint screenWidthInRawPixels = Windows.Graphics.Display.DisplayInformation.GetForCurrentView().ScreenWidthInRawPixels;
uint screenHeightInRawPixels = Windows.Graphics.Display.DisplayInformation.GetForCurrentView().ScreenHeightInRawPixels;
double rawPixelsPerViewPixel = Windows.Graphics.Display.DisplayInformation.GetForCurrentView().RawPixelsPerViewPixel;
double screenWidthInViewPixels = System.Convert.ToDouble(screenWidthInRawPixels) / rawPixelsPerViewPixel;
double screenHeightInViewPixels = System.Convert.ToDouble(screenHeightInRawPixels) / rawPixelsPerViewPixel;
// If offsetToScreenWidthInViewPixels is less than 15,
// on first load app will be of default size, and on second load app will be full screen.
// A loaded image will have height equal to full screen height minus app title bar height minus app toolbar height minus 5 view pixels of padding.
// Part of a loaded image with aspect ratio less than one will be behind Windows taskbar.
// This is all very complicated and undesirable.
// If offsetToScreenHeightInViewPixels is less than 40,
// on first load app will be of default size, and on second load app will be full screen.
// A loaded image will have height equal to full screen height minus app title bar height minus app toolbar height minus 5 view pixels of padding.
// Part of a loaded image with aspect ratio less than one will be behind Windows taskbar.
// This is all very complicated and undesirable.
// If offsetToScreenWidthInViewPixels is greater than or equal to 15 and offsetToScreenHeightInViewPixels is greater than or equal to 40,
// on first load app will be of PreferredLaunchViewSize, and a loaded image with aspect ratio less than one will have height exactly equal to height of app minus app title bar height minus app toolbar height.
// If PreferredLaunchViewSize.Height is only screenHeightInViewPixels - offsetToScreenHeightInViewPixels,
// part of app and a loaded image with aspect ratio less than one will be behind taskbar.
// If taskbarHeight is taken off of screenHeightInViewPixels - offsetToScreenHeightInViewPixels,
// bottom of app and coincident bottom of loaded image will be slightly above taskbar.
// I consider this ideal.
double offsetToScreenWidthInViewPixels = 15;
double offsetToScreenHeightInViewPixels = 40;
double taskbarHeight = 40;
Windows.UI.ViewManagement.ApplicationView.PreferredLaunchViewSize = new Windows.Foundation.Size(screenWidthInViewPixels - offsetToScreenWidthInViewPixels, screenHeightInViewPixels - offsetToScreenHeightInViewPixels - taskbarHeight);
Windows.UI.ViewManagement.ApplicationView.PreferredLaunchWindowingMode = Windows.UI.ViewManagement.ApplicationViewWindowingMode.PreferredLaunchViewSize;
// Set the app window to a new Frame.
Windows.UI.Xaml.Controls.Frame rootFrame = new Windows.UI.Xaml.Controls.Frame();
Windows.UI.Xaml.Window.Current.Content = rootFrame;
// Navigate the frame to the initial default page.
rootFrame.Navigate(typeof(MainPage), e.Arguments);
// Attempts to activate the application window by bringing it to the foreground and setting the input focus to it.
Windows.UI.Xaml.Window.Current.Activate();
} // protected override void OnLaunched
} // sealed partial class App
} // namespace Draw_Bounding_Boxes
I added property x:Name="page" to the <Page> tag in "MainPage.xaml".
I removed the <Grid> </Grid> environment from MainPage.xaml.
I replaced the contents of "MainPage.xaml.cs" with the following code block.
// Create namespace Draw_Bounding_Boxes to contain all classes associated with our app.
namespace Draw_Bounding_Boxes
{
// Create class MainPage that inherits fields and methods from Windows.UI.Xaml.Controls.Page and
// is used to declare and define user-interface elements and functionality.
public sealed partial class MainPage : Windows.UI.Xaml.Controls.Page
{
// Create constructor public MainPage.
public MainPage()
{
// Necessary to instantiate this Page, add a stackPanel to this Page, et cetera.
this.InitializeComponent();
// Find width of app in view pixels and height between bottom of app and bottom of title bar in view pixels.
double widthOfAppInViewPixels = Windows.UI.ViewManagement.ApplicationView.PreferredLaunchViewSize.Width;
double heightBetweenBottomOfAppAndBottomOfTitleBarInViewPixels = Windows.UI.ViewManagement.ApplicationView.PreferredLaunchViewSize.Height;
// Create a stackPanel.
Windows.UI.Xaml.Controls.StackPanel stackPanel = new Windows.UI.Xaml.Controls.StackPanel();
// Create a toolbar with width equal to the width of the app, height equal to 50 view pixels, and background color of light blue that has one row and four columns.
Windows.UI.Xaml.Controls.Grid toolbar = new Windows.UI.Xaml.Controls.Grid();
toolbar.Width = widthOfAppInViewPixels;
toolbar.Height = 50;
toolbar.Background = new Windows.UI.Xaml.Media.SolidColorBrush(Windows.UI.Colors.AliceBlue);
Windows.UI.Xaml.Controls.RowDefinition row = new Windows.UI.Xaml.Controls.RowDefinition();
toolbar.RowDefinitions.Add(row);
Windows.UI.Xaml.Controls.ColumnDefinition column = new Windows.UI.Xaml.Controls.ColumnDefinition();
column.Width = new Windows.UI.Xaml.GridLength(widthOfAppInViewPixels);
toolbar.ColumnDefinitions.Add(column);
stackPanel.Children.Add(toolbar);
page.Content = stackPanel;
}
}
}
My winform can't change the size. The wince device is 480*764. I debugged and got a new size:
But the size still unchanged. What happened?
Try putting your sizing code into the constructor not the Load event. Don't think that FormBorderStyle needs to be sizable (is this even supported in the .NET Compact Framework which I assume you are using?). Our forms have a style of FixedDialog. If you need to centre the form you can use this helper function which you call immediately after setting the size:
public static void SetFormPosition(Form frmChild)
{
// Set the form position on the Windows CE panel
if (frmChild != null)
{
// Get the size of the screen (should be 480x768)
Rectangle rctScreen = Screen.PrimaryScreen.WorkingArea;
// Now calculate the position of the form
int nPosX = ((rctScreen.Width - frmChild.Width) / 2);
int nPosY = ((rctScreen.Height - frmChild.Height) / 2);
// Set the position
frmChild.Location = new Point(nPosX, nPosY);
}
}
I'm trying to write some code to detect a wallhack for a game.
Basically, some hacks exist which create a windows aero transparent window, and they draw the hack onto this external window, so it can't be detected by taking a screenshot of the game itself.
My approach at the moment is to -
1. take a screenshot of the game window.
2. take a screenshot of the windows desktop for the same coordinates.
3. perform image analysis to compare screenshot 1 to screenshot 2 to see if there is a difference.
My problem is that screenshot 1 and screenshot 2 are not performed simultaneously so new game frames can be drawn between the two screenshots, causing false positives when the images are compared.
I want to know if there is a way to coordinate the screenshots so they occur at exactly the same time ? or somehow stop the screen drawing any new frames until my screenshots are finished?
This is the code I use for taking screenshots.
Note, I have even tried to take the 2 screenshots in parallel by queuing two work items.
However, even this doesn't result in the screenshots happening at exactly the same time.
So I wonder if there is some way to stop any further updates to screen from the graphics card until my screenshots finish? Or any other way I can do this?
public void DoBitBlt(IntPtr dest, int width, int height, IntPtr src)
{
GDI32.BitBlt(dest, 0, 0, width, height, src, 0, 0, GDI32.SRCCOPY);
}
public struct Windows
{
public Bitmap window;
public Bitmap desktop;
}
public Windows CaptureWindows(IntPtr window, IntPtr desktop, User32.RECT coords)
{
Windows rslt = new Windows();
// get te hDC of the target window
IntPtr hdcSrcWindow = User32.GetWindowDC(window);
IntPtr hdcSrcDesktop = User32.GetWindowDC(desktop);
// get the size
int width = coords.right - coords.left;
int height = coords.bottom - coords.top;
// create a device context we can copy to
IntPtr hdcDestWindow = GDI32.CreateCompatibleDC(hdcSrcWindow);
IntPtr hdcDestDesktop = GDI32.CreateCompatibleDC(hdcSrcDesktop);
// create a bitmap we can copy it to,
// using GetDeviceCaps to get the width/height
IntPtr hBitmapWindow = GDI32.CreateCompatibleBitmap(hdcSrcWindow, width, height);
IntPtr hBitmapDesktop = GDI32.CreateCompatibleBitmap(hdcSrcDesktop, width, height);
// select the bitmap object
IntPtr hOldWindow = GDI32.SelectObject(hdcDestWindow, hBitmapWindow);
IntPtr hOldDesktop = GDI32.SelectObject(hdcDestDesktop, hBitmapDesktop);
// bitblt over
var handle1 = new ManualResetEvent(false);
var handle2 = new ManualResetEvent(false);
Action actionWindow = () => { try { DoBitBlt(hdcDestWindow, width, height, hdcSrcWindow); } finally { handle1.Set(); } };
Action actionDesktop = () => { try { DoBitBlt(hdcDestDesktop, width, height, hdcSrcDesktop); } finally { handle2.Set(); } };
ThreadPool.QueueUserWorkItem(x => actionWindow());
ThreadPool.QueueUserWorkItem(x => actionDesktop());
WaitHandle.WaitAll(new WaitHandle[] { handle1, handle2 });
rslt.window = Bitmap.FromHbitmap(hBitmapWindow);
rslt.desktop = Bitmap.FromHbitmap(hBitmapDesktop);
// restore selection
GDI32.SelectObject(hdcDestWindow, hOldWindow);
GDI32.SelectObject(hdcDestDesktop, hOldDesktop);
// clean up
GDI32.DeleteDC(hdcDestWindow);
GDI32.DeleteDC(hdcDestDesktop);
User32.ReleaseDC(window, hdcSrcWindow);
User32.ReleaseDC(desktop, hdcSrcDesktop);
// free up the Bitmap object
GDI32.DeleteObject(hBitmapWindow);
GDI32.DeleteObject(hBitmapDesktop);
return rslt;
}
You are not going to be able to have both screenshots simultaneously, unless you resource to some graphic accelarators, meaning that that will not work in every computer...
About stopping rendering, as it is a game, I think this is not so good idea... you want your game to run smoothly.
Instead I would like to suggest to store recently rendered images of your game in memory, and when you take the screenshot compare it to them. If you can add some visual clue to decide which of the recent frames to compare to then it will work much better, because otherwise you will have to compare the screenshot to all of them and that will certainly eat some CPU/GPU time.
Are you using GDI to render? if so, what you want is to store the frames of your game in DIBs (Device Independent Bitmaps) to be able to compare them.
As for the clue to decide which image to use, I would go for some sort of time representation on screen, maybe a single pixel that changes color. If so, you will read the color of that pixel, use it to find the right frame, and them proced to compare the whole picture.