C#: Need to render a form/control on an "imaginary" desktop - c#

Okay, here's what I'm trying to do. First I'll explain the end result I'm trying to achieve in case there are other ideas on how to do this.
I'm making a screen capture utility that takes a screen shot of only one window... my window (which I have total programmatic control over). However, this window may be much larger than the desktop of the computer on which the utility will run. The height, in particular, may reach several thousand pixels on a computer with 1024x768 resolution.
So I'm trying to capture the full window even though it's much larger than the screen. That's the end result I'm trying to achieve.
One hypothetical solution to this is to render the form/control on a graphics or screen object of some sort, and take the screen shot off of that object, instead of taking a screen shot of the physical desktop.
Essentially I need to draw controls on an imaginary screen that exists only in code and memory and I don't even know what to search for, so even ideas on what to put into Google (the TRUE search engine) would be helpful.
Any ideas? Thanks in advance!
EDIT: I'm using WinForms.

You didn't mention which technology your C# application uses, I'm assuming it's either WinForms or WPF.
If your implementation uses WPF, you could simply render it to a DrawingImage with the right dimensions - or even use the printing capabilities of WPF to "print" the contents of the window to an image in memory. Here's a decent example of printing in WPF that you may be able to adapt (if you're using WPF).
With a WinForms application, it is a bit trickier, because WinForm controls don't always scale well under higher resolutions, and can exhibit alignment problems. Here's a link that describes printing a WinForm screen to an image. It demonstrates printing a UserControl, but you should be able to adapt the implementation for your purposes.

Hmm, that's very odd. Have you actually written this form yet? The Form class is extremely insistent that its Size can never be larger than the screen. I've never found a workaround for this and have never seen one posted in a WF related forum.
Anyhoo, you can't make a screen shot because you don't have enough screen. The only other option is Control.DrawToBitmap().
"Several thousands of pixels" is liable to get you into trouble with OutOfMemory exceptions on 32-bit operating systems when you try to create the bitmap. Not because you don't have enough memory but because there isn't an empty hole left in the virtual memory address space that is large enough to fit the bitmap The only good workaround for that is a 64-bit operating system.

Related

WPF: GDI drawing in other process flickers

There are quite some topics available about GDI drawing and flickering issues, but I haven´t been able to find any regarding drawing in an other process.
The issue
Basically I´m trying to draw to a Hwnd using Graphics.FromHwnd. This works perfectly, but there is a lot of flickering involved. The application I´m trying to draw on is a game (not made by me) and has quite a high refresh rate, unlike forms.
Attempts
I´ve tried doing the drawing both using a GDI.Rectangle function that used the HDC to draw and using Graphics.DrawRectangle to draw to the Hwnd. I don't notice a difference in performance but 'Graphics' seems a bit easier in use since it doesn't need gdi32.dll to draw shapes, unlike GDI.
I've also tried doublebuffering but yet again I do not notice any difference.
To me it seems that the doublebuffering is not working because of the fact that I'm trying to draw in such a high refresh rate window.
Question
Is it possible to get the window's refresh rate and use that for a timer to update the graphic?
is it possible to make graphics 'stick' until updated so they don't automatically disappear?
If anyone knows how to do this, or knows other solutions to get rid of the flickering I would appreciate the help!
Thanks in advance.
After doing some research I've come to the conclusion that using a transparent window will suit my case best. Here's how I came to that conclusion:
I've used an application to read window events to check if there was any continuous event stream that could be the window invalidation, but there wasn't.
I did find out a way that should make it possible to actually read when the game invalidates the window, but it's kind of a hack: It's possible to replace the game's d3d9.dll file with your own, calling all the original functions, but catching the events. I don't have any details on how or even if it works since having to distribute a dll to end-users is not an option for me, not to mention that this is in fact hacking.

Recording video of only one Window

I need to capture my screen as a video, for that I used Expression Encoder 4, but in my application I also need to capture one single window, but I can't find a way of doing it, with EE4 I tried changing dynamically the CaptureRectangle of my ScreenCaptureJob, but that doesn't seem to be possible. So my question is, do you know anyway of doing this 'single window capture' using preferably C# or maybe C++?
You could get the window handle of the window that you're interested in, set a timer, and at each timer tick capture that window's contents. Doing so is non-trivial, but certainly possible. I did it in C many years ago, but that code is long gone.
The problem is simpler if you just want to capture a rectangular area of the screen. You can get the window handle, query its size and position, and then copy that area from the screen. In C or C++, you would get the desktop DC and copy bits from it. In C#, you could create a Bitmap that's the size of the window, call Graphics.FromImage to get a Graphics object for the image, and then call CopyFromScreen to get the window contents. The drawback is that this only works if nothing is covering the window in question. If something is covering any part of the window, you're going to capture that.
In any case, you end up with a stream of images that you need to combine into a video. There are a number of libraries that will do that. For a C# solution, you might start by looking at create video from streamed images c#. I suspect there are similar libraries for C++. There are also some command line tools that will do it, although my experience with them has been less than satisfactory.

Make entire screen monochrome and other full screen effects

Does anyone know how to apply effects to the entire screen, in c# or any programming language.
I'm mostly interested in making the screen monochrome (specifically green-white instead of black white).
I know a cross-graphic card solution is possible because I found a program that can do it:
http://www.freedomscientific.com/products/lv/magic-bl-product-page.asp
Anyone knows how to accomplish something this or where to look?
Thanks !!
There is no easy Windows API to modify the entire screen contents. But this could be done at the device driver level.
Otherwise you have to resort to some Windows API tricks: place a "fake" window over the entire desktop, in a loop: grab the entire screen contents without grabbing fake window contents, do your processing to get the monochrome effect, then display that on the fake window. Yes, it's hacky and slow, but possible. Even more hacky, when you get mouse clicks to "go through" the fake window (lots of SetWindowsRgn calls).
So cross-platform here means using GDI, though some older DirectDraw APIs might work, in that case, you have a much easier time with hardware overlays (and better performance). Though I'm not sure how many cards actually support hardware overlays, and if newer versions of windows support the older DirectDraw APIs.
One more possibility is if the video card has a C# or C++ or C API, then you can do whatever you want with the card without writing device driver code.
Then there's CUDA, but I haven't yet tried that out. I know it's for stream processing on nVidia boards, but I wonder if it could get you an easy backdoor into the video display stuff.
To help people in the future who are interested in this:
This is possible with the Magnification API's color effect method. This allows one to use a matrix that can be applied to the whole screen.
NegativeScreen is an open source project that implements the feature you are describing in C#.
Unfortunately, this only works with affine transformations, as the API takes only an augmented matrices rather than a delegate or something.

C#: Creating a graphical screensaver

I am thinking about creating a screen saver. I have the whole thing, its graphics and the back-end kind of ready in my head. But I am not quite sure how to get the graphics out in code.
What I would like is a slide show of images with a bit of movement (kind of like the slide show in media center) and some floating text and shapes on top. The shapes somehow translucent.
I currently have a very simple static slideshow made in WinForms. Just a simple application that goes fullscreen and displays some images and pretends to fade them in and out in a hackish kind of way. But it is not very well made, and the performance is not very good. For example to prevent lag, I fade in a black square on top of the image, instead of fading in the actual image. Silly perhaps, but it kind of worked :p
Anyways, I would like to do a better job. But not sure where to start. Is WPF a good solution for this? Or should I look into DirectX or OpenGL? Is this something that could be handled well with XNA, or is that too game spesific?
WPF is not a bad idea. It takes advantage of DirectX and hardware acceleration for its animations and effects.
You will get better performance if you write this kind of stuff natively (against directx or opengl), but the cost of writing it will be much higher. It's quite possible you will not need that edge anyway.
Have a look at hanselman's baby smash (which is a full screen wpf app with animations) to get a grasp of what you can do with wpf.
Note: I did write a slide show kind of thingy in WPF way back, the key to getting this to work smoothly is loading up the images in a background thread and freezing it.
I guess XNA works well. There's a sample screensaver in C# Express, by the way.
Actually XNA works pretty well. For example: this is an (advanced) example of what can be made with XNA. The community is quite helpful and XNA has great potential.
A few weeks ago I wrote a two-part article describing how to create a Windows screen saver with GDI+. I am not displaying a slide show in my screen saver, but instead I am randomly drawing shapes. I did however explain the fundamentals of creating a screen saver for Windows which should be of some help if you have never created a screen saver before.
Create a Screen Saver Using C# – Part 1
Create a Screen Saver Using C# – Part 2
If you want to go with just GDI and GDI+, I wrote some info here about how to speed them up when rendering images and drawing them to screen. There is also fully functional screen saver source code at the above link (which I wrote myself after digging for some of the more obscure screen saver details), in case that helps.
Recently I finished with my first WPF (I wanted to see, how it can be done with WPF) screen-saver. You can check-it out on YouTube. Try to see HD-version.
Though I never tried XNA, I'm really pleased with WPF so far. Easy and flexible. But I guess you probably wouldn't get an XNA-performance (or am I wrong here?).
You can google for GDI+ or WPF ScreenSaver-templates to start with.

Take screenshot of any external application using C#

We have a C# (WPF) application in which we want to take a screenshot of an arbitrary application launched by us (i.e. so we have a reference to the Process we started).
The application may be minimized or behind other windows but we still only want the image of the individual application, not overlapping pixels.
I know the typical P/Invoke solutions using BitBlt or PrintWindow work most of the time, but those fail (I only get black/transparent pixels) when dealing with an DirectX or OpenGL application that draws directly to the graphics device. I have found this article on taking a screenshot of a Direct3D app from C#, so I think I have that case covered.
So my question is this:
How would I do this for an OpenGL application?
What is the easiest way to determine the appropriate method to use (PW/DX/GL)?
Is there a single universal way of doing this?
For #2, am I relegated to inspecting the modules loaded by the executable and seeing if an DirectX or OpenGL DLL/Assembly is loaded?
This only has to run on Windows XP (not cross-platform and not going to Vista/7 anytime soon if ever for this application).
Answer to 1: In OpenGL, you can call glReadBuffer and glReadPixels to get the screen bitmap. However, this is slow (so you don't call it repeatedly every frame) and you might also have problems when th GL window is overlapped by another application / window. The correct way to do this is to "render to texture" (google it) by using a pbuffer.
Idea for 2: If you have the handle to window, you might be able to get the pixelformatdescriptor structure it has and check it. Never tried it though.
For 3: By the way, I don't think there is a single universal way of doing this without any problems..

Categories