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

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.

Related

Are multiple GraphicsDeviceManagers in MonoGame (XNA) DirectX11 allowed

Using MonoGame (Basically XNA) I have some code which allows you to host a DirectX11 window inside of a System.Windows.Controls.Image, the purpose of which is to allow you to display the window as a standard WPF control.
I created this code by looking at a number of online code examples which demonstrated similar functionality (as I am a complete newbie to game dev). Among some of the code that I have leveraged there is a method of specific interest to me which looks like this:
private static void InitializeGraphicsDevice(D3D11Host game, int width, int height)
{
lock (GraphicsDeviceLock)
{
_ReferenceCount++;
if (_ReferenceCount == 1)
{
// Create Direct3D 11 device.
_GraphicsDeviceManager = new WpfGraphicsDeviceManager(game, width, height);
_GraphicsDeviceManager.CreateDevice();
}
}
}
This code is called on the creation of the hosting object (i.e. System.Windows.Controls.Image) and clearly it appears the intent is to limit the creation of multiple GraphicsDeviceManagers. However I have ended up in the situation where this code prevents me from creating multiple game windows, as needed.
I have changed this code from static to instance and removed the counter and everything seems to be working fine BUT I am concerned that there is something fundamental I don't understand which might come up later.
So, why does the above code prevent creating multiple DeviceManagers? Is it legal for me to create multiple graphics device managers in XNA (MonoGame)? I have to assume there must have been a reason for it?
I think it's because of the fundamental design thought behind xna. You have one game loop, one window for graphic output and so on.
If I remember correctly it should be no problem to create multiple graphic devices on different handles (in your case different windows).

DrawGeometry slow

I have a set of Coordinates that is drawn on my override method OnRender using DrawGeometry. One of the Polygons im trying to draw is 121000 points which is a lot. This slows down my map control.
Also when this OnRender happens the points are already in memory I'm just passing the points to DrawGeomerty
here is an example what happens OnRender
MapProjection pa = new MapProjection();
if (this.mapCommunication.MapLayers == null)
{
return;
}
foreach (KeyValuePair<Guid, MapLayerHelper> coordinatePointsLayer in this.mapCommunication.MapLayers)
{
if (!coordinatePointsLayer.Value.IsVisible)
{
continue;
}
if (coordinatePointsLayer.Value.State != LayerEnum.Visible)
{
continue;
}
foreach (CoordinateHelper coordinatePoints in coordinatePointsLayer.Value.Coordinates)
{
foreach (StreamGeometry item in coordinatePoints.GeomertyPoints)
{
drawingContext.DrawGeometry(null, penDrawing, item);
}
}
}
My Question is what direction should i take from here should i optimize, or should i try and incorporate DirectX would this help or what approach should i take?
Thanks for help i pretty new to render this much data.
What i eventually figured out was help me out if I'm wrong :) WPF is already build upon Direct X so would not help me much if i tried accessing through something like SharpDX, because i was going for dubble buffering and that is already implemented.
So what i implemented was instead of reading the point in the OnRender is used a Canvas with a fixed size and added System.Windows.Shapes.Path adding my Geometry that way.
This caused WPF to better manage dubble buffering and the Points rendered much faster.

Are extension methods the solution to this problem?

In my program the source rectangle for drawing can either be a regular rectangle, an empty rectangle, or a rectangle with an X or Y of -1. If the rectangle is normal (example being (0, 0, 64, 64)) then it just draws that from the texture. If it is Rectangle.Empty it draws nothing and just continues with the loop. If the source rectangle has an X or Y of -1 then it is determined to be a collision tile.
The problem with this is that it -1 is not intuitive. It is confusing and a bad solution. Also if there come to be more tile types it will start getting ridiculous like -2 meaning a slow tile or -3 meaning a water tile.
Another problem is that since I did not know there were going to be collision tiles early on and regular XNA rectangles were fine, the entire system (thankfully only around 1,000 of lines of code at the moment) uses XNA rectangles. I figure I'm going to have to make a separate class at this point and update everything but I'm not sure.
What would be a good solution to this? I have not really dabbled in extension methods at all. Could they be applied to the Rectangle class and be given methods like IsCollisionTile() or IsBlankTile()? Initially I was hoping I could derive from the Rectangle class to make a Tile class but unfortunately the class is sealed. I suppose another simple solution could be just making a global constants class with -1 being CollisionTile, 0 being BlankTile, et cetera. This would at least make it slightly more understandable but this still looks ugly to me:
if (tiles[y, x].X == Constants.BlankTile)
continue;
if (tiles[y, x].X == Constants.CollisionTile)
{
Utility.DrawRectangle(spriteBatch, new Rectangle(x * TileSize, y * TileSize, TileSize, TileSize), collisionTileColor);
continue;
}
spriteBatch.Draw(tileset, new Rectangle(x * TileSize, y * TileSize, TileSize, TileSize), tiles[y, x], Color.White);
If only there was a property I could use like Tag with controls. I'd really like to not abandon using the Rectangle class because it is so embedded in to the system and the program is purely functional, just not aesthetic in this regard. Ideally, I'd prefer a solution that just allows the Rectangle class to be extended to somehow be able to communicate with its clients what kind of tile it is supposed to be.
Well then, that took a lot more typing than I had originally hoped for. Sorry for the long read x_x
I would recommend setting global constants. The problem with extension methods in this case arises because Rectangle is a struct, a value type. That means that your extension method is working with a copy of the rectangle, not the original.
If the class can't be inherited from (which would usually be the appropriate solution here. Shame on you Microsoft!) then extension methods could defiantly work as you described.
Problem is - IMO it's less in style with C# and OOP in general to use methods that function like getters. That's what getters are for.
Because of that, I think the global constants option is more in line with the general style, but that's just my opinion.
From a totally programmatic POV - both methods are valid where the global constant class might be slightly faster (though I'm not sure of this)
At the beginning, you should consider, when do you use your Methods
IsCollisionTile() and IsBlankTile()
You have two choices:
*) You wanna use it globally, then you should better write a Utility-Class to have your Methods right there where you need them:
public static class CollisionHelper
{
public static Boolean IsCollisionTile(ITile tileToCheck)
{
...
}
}
*) Second, if you wanna use it only in connection with your tiles, you should definitly write an extension method, e.g. to accept every ITile-Object. Extensions methods are a great way to widely EXTEND the capabilities of classes. A sample could be:
public class RectangleTile : ITile
{
public static Boolean IsCollisionTile(this ITile tileToCheck)
{
...
}
}
I hope you have now an idea about Extension-Methods and how you could use them to solve your problem very easily ;)

Working With System.Drawing.Region

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

Which class has the responsibility of setting Piece's pixels on a Board(2d matrix)? The Piece or the Board?

So, I currently have a Board class that is composed of Pieces. Each Piece has a color and a string that describes the kind of piece. It also has a 2d matrix with bits either set on or off, that allows me to know which pixels to paint with the desired color or not.
My question is, which class should have the responsability to draw the pieces on the board? On one hand, I'd say the Piece class should do it. But to do it, I'd have to pass a Board as reference to Piece's Draw() method and although it's not terrible I find it kinda awkward. This raises the problem that Piece would have "to know" the Board class.
On the other hand, I could just have the Piece have a
Boolean[,] IsPixelSet(int x, int y)
and Board would then have a method of the form:
void DrawPieceOnBoard() {
for (int y = 0; y < height; ++y) {
for (int x = 0; x < width; ++x) {
if (piece.IsPixelSet(x, y) {
board.DrawPixelAt(x, y, piece.GetColor());
}
}
}
}
How would you do it? And why? I can't see a clear winner in any of these approaches.
Thanks
edit
I'm not talking about actually drawing things on screen. What happens is that I'm implementing a Tetris game (currently, no GUI) and I need at every moment to set the Pixels of a Square on different positions on the board as it falls to the ground. The board basically only has an accessor and a mutator for each one of the (x, y) points. Let's now say I want to draw a Square(a type of Piece) on the Board. Should the Piece know of the board and its Draw() method make the changes to the Board, or should the Board access Piece's getter method and do it itself?
FWIW, in general MVC theory, neither class should draw itself.
Presentation would be a concern of a separate view.
I'd say the Piece draws. For example, your function does not allow to enhance the Piece to allow them to have several colors.
The Piece does not have to know all the Board, just some method (maybe part of an interface) Draw(x,y,color).
In my opinion the Piece should draw the piece and the Board should draw the board.
I would have something like this:
class Piece
{
Image Render(Rectangle bounds) { /* */ }
}
class Board
{
void Render(Graphics g)
{
//Draw the base
foreach (piece in Pieces)
{
var rect = figureOutPosition(); //Positioning logic to
g.DrawImage(location, rect, piece.Render(rect));
}
//Draw any overlays
}
}
I agree with nonnb, there's no logical concept of "drawing" for a chess piece or a board, it could be argued that the board has references to all the pieces, so it should draw itself. But that argument equally says that it could be a helper object, or the environment that does the drawing.
I'd personally opt for a rendering class (for example, maybe you want to be able to print the board in ASCII for a record of all the moves), or maybe in the future upgrade to a 3d rendering engine or something... that's just my 0.2ยข
It does not matter. What you may want to do is to make it so that either board depends on piece or piece on board for everything you do.
I'd go for the Composite Design Pattern - mostly the same solution as #Pondidum.
Drawable has the method draw()
Board isA Drawable
Piece isA Drawable
Board hasA array of Drawable.

Categories