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.
Related
Hello: I am trying to create an app which will display a moving sphere. App will vary speed and direction. I've tried Adobe Flash but cannot get it smooth. Smoothness is essential in this case. So I am trying C#.
Initially, I can see that this can be implemented by:
1) Creating a PictureBox of a sphere, and using a Timer, change its coordinates. or
2) Using the this.paint function to draw a filled circle, and somehow, with a timer, erasing and redrawing it.
Can someone recommend the best path to take? I'll have a main menu where the user will chose speed/direction/how many etc... and then simply show the "game window" with the moving spheres. Any guidance would be much appreciated.
This is to be displayed on a PC only.
Thanks
-Ed
I just answered a similar question here.
NOTE: Depending on your needs, it is possible to achieve smooth animations under winforms (under certain conditions) though you are responsible for everything. wpf provides an animation framework but wpf is perhaps a milestone harder.
It probably does not matter should you pursue winforms first or WPF. You arguably could learn the basics under winforms then move over to wpf. wpf may require you to learn quite a bit before you can do anything.
Summary
Essentially what this does is to create an offscreen bitmap that we will draw into first. It is the same size as the UserControl. The control's OnPaint calls DrawOffscreen passing in the Graphics that is attached to the offscreen bitmap. Here we loop around just rendering the tiles/sky that are visible and ignoring others so as to improve performance.
Once it's all done we zap the entire offscreen bitmap to the display in one operation. This serves to eliminate:
Flicker
Tearing effects (typically associated with lateral movement)
There is a Timer that is scheduled to update the positions of all the tiles based on the time since the last update. This allows for a more realistic movement and avoids speed-ups and slow-downs under load. Tiles are moved in the OnUpdate method.
If you note in the code for Timer1OnTick I call Invalidate(Bounds); after animating everything. This does not cause an immediate paint rather Windows will queue a paint operation to be done at a later time. Consecutive pending operations will be fused into one. This means that we can be animating positions more frequently than painting during heavy load. Animation mechanic is independent of paint. That's a good thing, you don't want to be waiting for paints to occur. xna does a similar thing
Please refer to my full SO answer complete with sample code
Here are a few hints to get you going:
First you will need to come to a decision about which platform to target: WPF or Winforms.
Then you should know what to move across what; a nice Bitmap or just a circle across an empty background or a Bitmap or a Form with controls on it.
In Winforms both your approaches will work, esp. if you set a circular region see here for an example of that. (The part in the fun comment!)
And yes, a Timer is the way to animate the sphere. Btw, a Panel or even a Label can display an Bitmap just as well as a PictureBox.
For smooth movements make sure to set the Form.Doublebuffered=true, if you move across a Form. If you move across any other control (except a PictureBox or a Label) you will need to subclass it to get access to the DoubleBuffered property!
It is often also a good idea to keep the Location of a moving item in a variable as a PointF and use floats for its speed because this way you can fine grain the speed and Location changes and also the Timer Intervals!
I have a control that uses D3DImage to host a SharpDX DirectX9 surface and allows use to pan, zoom, and interact with world objects and the result is really awesome. Performance is actually an amazing consistent 60fps EXCEPT when the window is minimized and brought back up or the user locks and then unlocks the screen. When the window regains focus the fps drop to about 25-30fps. I can "fix" the issue by unloading and loading the control back into its container and then BOOM, 60fps.
I call the main render function using a DispatcherTimer set at 10ms. Before, I was using the CompositionTarget.Rendering event but performance wasn't as good as using the DispatcherTimer. I fairly certain that I'm handling lost resources correctly. Any ideas about these missing frames per second?
EDIT: I am having this same exact problem. Unfortunately, doing an automatic device reset doesn't fix the issue but if I have a button that executes the same reset method then my fps goes back to normal.
Locking / Unlocking the screen causes a device lost. But you probably know that.
Anyway I use D3DImage in WPF as well. My performance problems ended when I called
D3DImage.SetBackBuffer(D3DResourceType.IDirect3DSurface9, IntPtr.Zero)
on each device lost. I used to have responsiveness issues after a device lost until I realized WPF was still holding a reference to a texture. Of course you should later re-set the backbuffer when you have an updated texture.
Although it is unclear what exactly is going wrong behind the scenes, it is clear that D3DImage keeps a refcount to your texture, which can prohibit a successful recovery in the case of a device lost. In my case, we simply had no updates.
Sorry for the anectodal answer... But until a real D3DImage expert enters the room, it's better than nothing.
P.S. I am using SlimDX but I don't think it matters... For all that I know SharpDX is a fork of SlimDX.
There's an overload to SetBackBuffer that takes an additional Boolean flag:
D3DImage.SetBackBuffer(D3DResourceType, IntPtr, Boolean)
When you call the SetBackBuffer(D3DResourceType, IntPtr) overload, or call the SetBackBuffer(D3DResourceType, IntPtr, Boolean) overload with the enableSoftwareFallback parameter set to false, the [WPF] rendering system releases its reference to the back buffer when the front buffer becomes unavailable and nothing is displayed.
I'm no expert either, but I would guess that this is what's happening; Because you didn't set that flag to 'true', WPF is calling Release() on what happens to be the last COM ref count for your D3D surface as soon as it exits the lock. This would seem to require that you be maintaining an additional ref count of your own.
For one thing, I've noticed that, even after getting your "used" surface "back" from a WPF lock/unlock round-trip, you need to still not release it until your next surface takes its place (i.e. in a successful call to d3dimg.SetBackBuffer). Otherwise, you'll get flickering when the WPF window is dragged around the screen. Given that that's the only reliable method I've discovered for detecting when WPF is truly done with your buffer, it does seem pointless for WPF to be concerned with AddRef'ing or Release'ing it.
What's generally confusing with D3DImage is that the IDirect3DDevice9 that's running WPF is not really associated with the IDirect3DDevice9 that generated the surface you're putting forth as a back buffer... for WPF. The whole Lock/Unlock business is presumably for WPF's benefit, and has nothing to do with your own (possibly lockable?) IDirect3DSurface9 rendertarget's survival.
Beware!If using D3DImage.TryLock, beware of its, um... shall we say, unconventional semantics: You must call Unlock even in the case where TryLock returns false. For more information, see https://stackoverflow.com/a/39581727/147511.
I need to write a complete diffrent looking textbox than the original winforms textbox. In fact I need a different background, how can I achieve this? I tried owner drawing with SetStyle(ControlStyles.UserPaint, true); but this caused a lot of flickers and the text was completly wrong drawn, wrong font, size etc.
Wrtiting a textbox from scratch would be overkill, I think.
This is not possible. The TextBox class is a wrapper around a native Windows control that has been around since Windows version 2. It had to run on some seriously sucky hardware, they had to break a few rules to make this work. One of which is that it draws parts of itself without using the standard Windows paint cycle. Invalidate() and OnPaint() in Winforms terms. Fixing this behavior wasn't possible due to app-compat problems. Way too much code out there that hacked the control in creative but unpredictable ways.
Accordingly, it isn't possible to intercept the drawing to prevent it from erasing parts of your background image. There is no workaround for this, creating your own is a lot of work. Consider WPF.
If you specifically need a different background on a text box, one work-around is offered here.
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.
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.