I'd like to capture a screenshot of an application's window. I can do this using the below. However, is it possible to do this in parrall or does it have to happen sequentially?
I am currently making use of this:
ScreenCapture sc = new ScreenCapture(); // capture entire screen, and save it to a file
Image img = sc.CaptureScreen(); // display image in a Picture control named imageDisplay
this.imageDisplay.Image = img; // capture this window, and save it
sc.CaptureWindowToFile(this.Handle,"C:\\temp2.gif",ImageFormat.Gif);
Is there any way I can take screen-shots in parallel for two or more application windows?
I have never used that library before but from your code example it seems you are not capturing a specific window but your entire screen.
it seems you want to use the function
public void CaptureWindowToFile(IntPtr handle, string filename, ImageFormat format)
and pass it the handle of the window of the application you want to capture. It seems you can use that on as many windows as you want with the library it is just a matter of getting the handle of the correct window.
you may want to look into "threads":
http://www.albahari.com/threading/
http://msdn.microsoft.com/en-us/library/aa645740(v=vs.71).aspx
Basically, you should launch concurrent threads to handle a specific work, eg giving the window handle as a parameter for the thread job.
Related
I am developing a windows service which processes video input and sends results of interest to a separate platform. I do not need to display the frames in this context. I am having a problem getting the correct camera input.
I want to save a Bitmap resulting retrieved from am EMGU capture object. To make sure that the capture is actually reading the video stream, I save the bitmap to a file, as follows:
Mat frame = mCapture.QueryFrame();
Template = frame.Bitmap;
Template.Save("frozen.jpg");
The capture is initialized as follows:
CvInvoke.UseOpenCL = false;
int index = int.Parse(ConfigurationManager.AppSettings["Index"]);
mCapture = new Capture(index);
One test platform is a Lenovo laptop running 64-bit Windows 10, with a built-in camera and a second camera attached through a USB port. The input of interest is the second camera. However, whatever index I use to open the Capture object, the input comes from the built-in camera.
The other platform is a Meego Pad, running 32-bit Windows 10, with the same camera attached. In this case, I simply get blank frames as video input. For both platforms, running the camera application shows the video input as expected. What is the problem with my initialization of the Capture object?
Further Investigation Shows...
First, I was using the wrong index to create the capture, so that created some of the confusion. But more confusion follows.
When I call the QueryFrame() method in an event delegate, as shown in this simple example I successfully retrieve the frame from the camera. Example code looks like this:
Application.Idle += new EventHandler(delegate(object sender, EventArgs e)
{ //run this until application closed (close button click on image viewer)
viewer.Image = capture.QueryFrame(); //draw the image obtained from camera
});
viewer.ShowDialog(); //show the image viewer
When I call the same method in a different thread (in response to a communication event) I get an empty image. On the gripping hand, when I call the method in a timer callback, I get the correct image.
I won't call this closed, because I would still like to know why QueryFrame() acts correctly in some threads, but not in others. However, I can work with this, so the question is now mostly academic.
I am working with a fingerprint sensor under C# .NET. It shows the captured fingerprint by handling a control, like this:
this.Sensor.SetDisplay((int)this.PictureBoxFingerprint.Handle);
I need to get the image the sensor displays and save it to an Image control. However, PictureBoxFingerprint.Image does not contain any data (because of the handling strategy, I suppose).
I have tried to use the DrawToBitmap method from the containing form, setting all the coordinates where the fingerprint image is placed, without any luck also.
Is there another way of accomplishing this?
Thanks!
Sounds like a sub-standard library if you can't get the image.
Assuming PictureBoxFingerprint is a standard window control you might get some mileage from basic interop; get the control dc and bitblit (copy) the content to an in memory bitmap. This article [1] should point you in the right direction; start with the int CaptureAnImage(HWND hWnd) method.
There is of course the problem that the quality of the image you get may not be all that good depending on what has happened to it on the way to the screen. Good Luck
[1] http://msdn.microsoft.com/en-gb/library/windows/desktop/dd183402(v=vs.85).aspx
I am trying to get the output of a camera and display it in a c# gui using OpenCvSharp. This is the code I have based on samples. However, this code pops up a second window, CvWindow, which I would like to remove. Is this possible? Removing the CvWindow from my code makes the camera stream not appear.
CvCapture cap= CvCapture.FromCamera(0);
CvWindow win= new CvWindow("camera");
while (CvWindow.WaitKey(10) < 0)
{
IplImage img= Capture.QueryFrame();
Bitmap bmp= BitmapConverter.ToBitmap(img);
pictureBox1.Image = bmp;
}
win.Close();
This is how I display OpenCvSharp video feeds in a Windows Form. http://www.prodigyproductionsllc.com/articles/programming/use-opencv-in-a-windows-form-application-in-c/.
The best way to hide the window is to not show it in the first place. So, remove the line where you construct a new CvWindow. Then, you need to move your while-loop into a new thread and make it continuous with something like "while(true)". If you do not run it on a separate thread, your app will freeze.
Well, it turns out using the Win32 API to hide the window was the way to go. However, you have to make sure to hide parent window of the CvWindow.
I need to print a screenshot of a silverlight UserControl, which I have tried doing the usual way with PrintDocument, but unfortunately it takes too long and because it has to take place on the UI thread the whole application is locked up for too long. It takes so long because the control contains a grid that needs to be measured and printed over many pages.
So I'm looking for a way to do this without locking up the UI thread. Is there any way I can render these controls again (separately from the originally rendered visible controls) on a background thread? The plan would be to then send those to the PrintDocument, or if that isn't possible to use a WritableBitmap to take screenshots of them.
I've had a quick go already but of course I always get thread affinity issues. Given that I don't want these controls to be visible to the user though I'm hoping there is a way to get around that?
Cheers
You can use WriteableBitmap
Get a reference to the root element that you want to reference. You can use XamlReader if you want to load up the XAML dynamically from an external source if you want. Call it ScreenshotRoot
WriteableBitmap bmp = new WriteableBitmap(ScreenshotRoot.RenderSize.Width, ScreenshotRoot.RenderSize.Height)
bmp.Render(ScreenshotRoot, new MatrixTransform());
bmp.Invalidate();
You should be able to do this in another thread.
I have a C# Windows application that I want to ensure will show up on a second monitor if the user moves it to one. I need to save the main form's size, location and window state - which I've already handled - but I also need to know which screen it was on when the user closed the application.
I'm using the Screen class to determine the size of the current screen but I can't find anything on how to determine which screen the application was running on.
Edit: Thanks for the responses, everyone! I wanted to determine which monitor the window was on so I could do proper bounds checking in case the user accidentally put the window outside the viewing area or changed the screen size such that the form wouldn't be completely visible anymore.
You can get an array of Screens that you have using this code.
Screen[] screens = Screen.AllScreens;
You can also figure out which screen you are on, by running this code (this is the windows form you are on)
Screen screen = Screen.FromControl(this); //this is the Form class
in short check out the Screen class and static helper methods, they might help you.
MSDN Link, doesn't have much..I suggest messing around in the code by yourself.
If you remember the window's location and size, that will be enough. When you set the position to the previously used position, if it happened to be on the second monitor it will go back there.
For example, if you have 2 monitors, both sized 1280x1024 and you set your window's left position to be 2000px, it will appear on the second monitor (assuming the second monitor is to the right of the first.) :)
If you are worried about the second monitor not being there when the application is started the next time, you can use this method to determine if your window intersects any of the screens:
private bool isWindowVisible(Rectangle rect)
{
foreach (Screen screen in Screen.AllScreens)
{
if (screen.Bounds.IntersectsWith(rect))
return true;
}
return false;
}
Just pass in your window's desired location and it will tell you if it will be visible on one of the screens. Enjoy!
You can get the current Screen with
var s = Screen.FromControl(this);
where this is the Form (or any control on the Form). As about how to remember that is a little tricky, but I would go for the index in the Screen.AllScreens array, or maybe s.DeviceName. In either case, check before using the settings on startup, to prevent using a monitor that was disconnected.
The location of the form will tell you which screen the form is on. I don't really understand why you'd need to know what screen it is on, because if you restore it using the location you saved it should just restore to the same location (maybe you can expand as to why).
Otherwise you can do something like this:
Screen[] scr = Screen.AllScreens;
scr[i].Bounds.IntersectsWith(form.Bounds);
Each screen has a Bounds property which returns a Rectangle. You can use the IntersectsWith() function to determine if the form is within the screen.
Also, they basically provide a function that does this as well on the Screen class
Screen screen = Screen.FromControl(form);
You can use the 'Screen' object:
System.Windows.Forms.Screen
Start playing with something like this:
Screen[] screens = Screen.AllScreens;
for (int i = 0; i < screens.Length ; i++)
{
Debug.Print(screens[i].Bounds.ToString());
Debug.Print(screens[i].DeviceName);
Debug.Print(screens[i].WorkingArea.ToString());
}
It may get you what you need