Working With System.Drawing.Region - c#

I've made a test WindowForm application that takes a snapshot of the window by it's boundaries. But I can't seem to give GetBounds() what it needs. He wants graphics but it already contains the bounds, I just want his point and size:
private void CaptureBtn_Click(object sender, EventArgs e)
{
Region region = GetRegionByHWnd(GetForegroundWindow());
Rectangle rectangle = new Rectangle(
region.GetBounds().Location,
region.GetBounds().Size);
CaptureImage(rectangle.Location, Point.Empty, rectangle.Size);
}
Did that problem occur to anyone before, or knows how to fix it?

For getBound some windows for you can
use ClientRectangle property , This
property returns bound form and this
dll (ScreenCaptureLib.dll) helps you
for getImage in the desktop.
http://www.codeproject.com/script/Articles/ViewDownloads.aspx?aid=19415

First, Region implements IDisposable, so you should be wrapping it in a using statement or calling Dispose when you done with it.
Other than that we will need to see your code for GetRegionByHWnd and CaptureImage. Do you really even need that code at all? Why won't someWindow.Bounds work for you?

Perhaps that helps: RECTANGLE
I don't know your methods like captureimage. But Perhaps you need the relative position to the control?
Point to Client / Point to Screen
If not, please tell the data you expect to get and what you receive.
Also take a lookt to the RECT MSDN type instead of the Rectangle type.
Some good articles are here:
http://www.codeguru.com/csharp/csharp/cs_graphics/screencaptures/article.php/c6139
http://cid-32fd2eb6551ddb56.office.live.com/self.aspx/.Public/CaptureWindow.rar?sa=170500830
http://winapi.freetechsecrets.com/win32/WIN32Capturing_an_Image.htm
Regards

Related

How to make a line drawn by graphics selectable in .NET

A simple code for drawing a line.
using (Graphics g = this.CreateGraphics())
{
g.DrawLine(Pens.Black, new Point(50, 50), new Point(100, 100));
}
This will draw a typical line. However i want to this line to be selectable so that user can manipulate it further(streching, resizing etc) at run time. Initially i attempted to use controls that can be manipulated at runtime with the line as background however that could not work due to overlapping controls issue.
My question is how can i select this line at runtime ?
You need to write it yourself.
Write a class that wraps Line
Add all needed additional behavior to the class (what happens when the line is selected, what happens when the line is stretched, deleted, changed color ...)
Write a class that manages either object was was picked by mouse or not (RayTracer)
etc...
Or simply use: piccolo2d framework
Structured 2D Graphics Framework
I think what you're looking to do is make the Graphics object to be selectable?
If so, you could put your logic into the MouseOver and MouseButton events.
Check this out, it may give you some insight.
Selectable Graphics Object
You must create it yourself. Declare interfaces that your graphics objects implement. Suggestion:
public interface IObject
{
bool HitTest(Point mouseLocation);
void Paint(Graphics g);
List<IAdorner> Adorners { get; }
}
public interface IAdorner
{
bool HitTest(Point mouseLocation);
void Paint(Graphics g);
void StartMoving(Point mouseLocation);
void Move(Point mouseLocation);
}
The adorners are the selectable end points of a line object for instance.
Your main paint routine will look something like this:
private void drawingSurface_Paintobject sender, PaintEventArgs e)
{
foreach (IObject o in _objects) {
o.Paint(e.Graphics);
if (o == _selectedObject) {
foreach (IAdorner a in o.Adorners) {
a.Paint(e.Graphics);
}
}
}
}
And of cause you need all the mouse event handling.
These interfaces are abstract enough in order to allow the implementation of any shapes. For instance they don't include any coordinates, as different types of objects need different numbers and kinds of coordinates and parameters.
Maybe It's a little too late, since you already accepted an answer, but you should really consider WPF for this.
https://stackoverflow.com/a/15469477/643085
That's an exact sample of what you're after, in WPF + MVVM. With a real whole LOT of advantages over any winforms approach (such as NO flicker due to hardware acceleration).
Please at least give it a try. Full CSProj project Source available.
You're REALLY reiventing the wheel implementing all this yourself in GDI. And in the end it will be unusable due to flickering and stuff like that.

How to get the bitmap from a Graphics object in C#?

How do you get a bitmap from a graphics object (or at least a pointer to it's Scan0)?
If a graphics object really always refers to a bitmap, then it IS possible to get to the bitmap data from the graphics object. (Think: the graphics object HAS TO have a pointer to the bmp data. I'd code it in C but I'm on a project that requires everyone be hobbled by .NET.)
Applications of this would include things like:
- using unsafe code to obtain faster screenshots
- modifying what's on a control using CreateGraphics
- (and the task I'm actually trying to accomplish which would take too long to explain)
Yes, this has been asked before but never answered. I'm not looking for how to get a graphics object from a bitmap (obviously trivial).
FAIL1, FAIL2, FAIL3, FAIL4, FAIL5, FAIL6, FAIL7
I don't think what you're trying to do is possible since your assumption that "a graphics object really always refers to a bitmap" is false.
There's a good article here that shows how to render a control to bitmap if you really want a bitmap and another one here that shows how to quickly update the screen at the WndProc level. If you're more familiar with C++ that might get you going the right direction.

How to clone a Graphics in C#?

I want to provide different parts of an application with independent Graphics instances which end up painting on the same base Graphics. Simply cloning the Graphics works, but since both instances refer to the same GDI handle, there are not independent. I can't use Begin and EndContainer as well since I have a method which has to provide the new Graphics instances. -so I cannot determine when to call EndContainer. The use case is quite similar to the Graphics.create() method in Java.
I've found some workarounds, but none of them works for a Graphics provided by the PrintController.
Is there any proxy-Graphics I can use? Or is there a possibility to create another Graphics for the same device for instance?
This sounds bad. Do not store references to a Graphics object, it only ever lives temporarily and is only valid while a Paint or PrintPage event handler is running. Do make sure to pass it as an argument to whatever method does the drawing instead of storing it in a field or a global variable.
If the method is altering the state of the object then use the Save() and Restore() methods to prevent this from causing problems in subsequent methods that use that same object. Cloning it is never necessary with this approach.
Graphics objects are not meant to be persisted. You could use a backbuffer approach by drawing to a Bitmap before your final render.
Perhaps you could raise an event to which listening drawing components could subscribe, and your calling code could chain these together. That way you could use the same Graphics instance without compromising GDI efficiency.
Not sure what exactly you're trying to do but you can use CreateGraphics() on a Control or Graphics.FromImage(xx) to create a new Graphics object for the control and/or image. There's also a few more functions in Graphics.FromXXX
A possibility would be to create multiple graphics objects which are pointing to multiple targets, for example an memory image. Then after done, combine all images into one.
But the thing I don't understand is, if all graphics instances should paint to the same target why do you need multiple graphics objects in the first place?
I was facing same problem, I found the only solution is to duplicate the drawings code line !!
Like the following:
e.Graphics.DrawString(points(i).pointText, myFont, Brushes.Blue, New Point(points(i).crossPointX4, points(i).crossPointY4)) : G.DrawString(points(i).pointText, myFont, Brushes.Blue, New Point(points(i).crossPointX4, points(i).crossPointY4))

Determine the bounding rect of a WPF element relative to some parent

I consider this a pretty simple request, but I can't seem to find a conclusive answer in my searches. How can I determine the bounds of a particular visual element in my window, relative to some other parent element?
I've tried using LayoutInformation.GetLayoutSlot but this just seems to return a Rect at 0,0 and doesn't reflect the actual location of the element.
What I'm trying to do is take a "screenshot" of a window using RenderTargetBitmap and then crop it to a particular element, but I can't get the element's bounds to know what to crop the bitmap to!
It is quite simple:
public static Rect BoundsRelativeTo(this FrameworkElement element,
Visual relativeTo)
{
return
element.TransformToVisual(relativeTo)
.TransformBounds(LayoutInformation.GetLayoutSlot(element));
}
In fact it may be overkill to put it in a separate method.
The LayoutSlot option didn't work for me at all.
This ended up giving me a child position relative to a specified parent/ancestor control:
public static Rect BoundsRelativeTo(this FrameworkElement child, Visual parent)
{
GeneralTransform gt = child.TransformToAncestor(parent);
return gt.TransformBounds(new Rect(0, 0, child.ActualWidth, child.ActualHeight));
}
Taking into account a few suggestions i found here this solved the problem for me.
item.TransformToVisual( relativeToElement )
.TransformBounds( new Rect( item.RenderSize ) );
Nevermind, I finally managed to figure it out using a combination of LayoutInformation.GetLayoutSlot() (although I probably could have used either ActualWidth/ActualHeight or RenderSize) and UIElement.TranslatePoint().
Seems a rather complicated solution when it could be as simple as this:
myElement.GetBounds( relativeElement );
Oh well. Maybe time for an extension method. :)

Is there a way to check if Texture2D is currently not in use so I can execute SetData() on it?

Attempting to do SetData() on Texture2D that has been recently Draw()-n by SpriteBatch leads to following exception:
The operation was aborted. You may not modify a resource that has been set on a device, or after it has been used within a tiling bracket.
Can I determine in advance if executing SetData() will throw this exception?
Basically, you have three options:
1) See if SpriteBatch has finished it's operation and call SetData() afterwards. The drawing methods usually are asynchronous. That means that, they just get added to the please-render-me queue and the method returns immediately. What you need is either a callback notification when the drawing has finished or a synchronous call to Draw().
2) Avoiding that SetData() gets interrupted. You can do that by putting it into a critical section which I would not recommend. It should be possible to lock the texture data. It's called LockRect() in Direct3D, it should be similar in XNA.
3) There should be some method like Flush() somewhere that waits until all graphics-related operation have finished.
Sorry for the rather vague help, but you should be able to find the method names from the XNA doc.
Basically no.
The easiest thing to do is to only call SetData in your Update method.
It's bad practice to use SetData within your Draw method, as the device could be doing all kinds of voodoo magic with the old data. This is explained in detail in the "Caution" box on its MSDN page.
Now, up until XNA 3.1 you could use SetDataOptions with Texture2D.SetData. But it looks like that functionality has been removed in XNA 4.0 for textures.
Shawn Hargreaves explains here how SetDataOptions could be used tell the GPU "actually yes I do want to overwrite that data you might be using, don't complain". And why it's difficult to get right.
I've solved a problem like this by creating two textures, and switching between the active one, essentially double-buffering:
void CreateTextures()
{
depth_1 = new Texture2D(this.GraphicsDevice, width, height, false, SurfaceFormat.Single);
depth_2 = new Texture2D(this.GraphicsDevice, width, height, false, SurfaceFormat.Single);
depth_current = depth_1;
...
}
void Draw(GameTime gt)
{
depth_current = depth_current == depth_1 ? depth_2 : depth_1;
Depth.SetData(this.DepthBuffer);
...
}
In my case it wasn't possible to move the SetData outside of Draw, but I suppose that's the nicest way to do it.

Categories