|
For starters, don't make fields public - use properties instead, and keep fields private.
Public fields mean that the interior workings of your class are exposed to the outside world, and you have to think long and hard before you make any changes at all which might affect them. Properties don't. (And they have other advantages when it comes to being used as a DataSource, serialization, and so forth.)
Secondly, Point is a struct not a class, so you only need to use the new keyword if the constructor needs to be called - it doesn't for Point.
class Human
{
private string _Name = "none";
public string Name { get { return _Name; } set { _Name = value; }}
public Point Location { get; set;}
It's also a bad idea to "mock" events in your class:
public void Paint(object sender, System.Windows.Forms.PaintEventArgs e) Is not an event handler, so don't make it look like one! )or someone will try to attach a handler, and get confused.
Instead, just pass the data it needs: the graphics context:
public void Paint(Graphics g)
{
g.DrawString(Name, new Font("Arial", 9), new SolidBrush(Color.Black), location.X - 5, location.Y - 15);
g.FillRectangle(new SolidBrush(Color.Red), new Rectangle(location.X, location.Y, 20, 20));
}
private void Form1_Paint(object sender, PaintEventArgs e)
{
female.Paint(e.Graphics);
}
That way, it's also easier to call it when you want to draw the name when you enter the control.
Finally - and I think I've mentioned this before recently, but I'm not sure if it's to you: Human is a class, but it isn't derived from Control. Which means it doesn't have any interaction directly with the user, and that includes Mouse events. Adding the line
public event EventHandler MouseEnter; doesn;t "hook" your class into the "Mouse events" system, it just creates an event called "MouseEnter" which is never raised by anything. If you want a MouseEnter that actually does something then the class which processes it MUST be based on Control: A Form, a Panel, or a UserControl perhaps.
You can't just add a handler and hope the system will sort it all out for you!
Sent from my Amstrad PC 1640
Never throw anything away, Griff
Bad command or file name. Bad, bad command! Sit! Stay! Staaaay...
AntiTwitter: @DalekDave is now a follower!
|
|
|
|
|
Thank you mister OriginalGriff,
Now I made the suggested rectifications:
public class Human : UserControl
{
public void hPaint(Graphics g)
{
g.DrawString(Name, new Font("Arial", 9), new SolidBrush(Color.Black), Location.X - 5, Location.Y - 15);
g.FillRectangle(new SolidBrush(Color.Red), new Rectangle(Location.X, Location.Y, 20, 20));
}
public override event EventHandler MouseEnter;
}
|
|
|
|
|
Just add a handler, and add the instance to the form's Controls collection.
Sent from my Amstrad PC 1640
Never throw anything away, Griff
Bad command or file name. Bad, bad command! Sit! Stay! Staaaay...
AntiTwitter: @DalekDave is now a follower!
|
|
|
|
|
Make an example for me, Please.
I think in Form1 i must do this? >> Controls.Add(female);
|
|
|
|
|
Try this: remove the line
public override event EventHandler MouseEnter;
And drag your Human class from the toolbox onto your form.
Try it!
Sent from my Amstrad PC 1640
Never throw anything away, Griff
Bad command or file name. Bad, bad command! Sit! Stay! Staaaay...
AntiTwitter: @DalekDave is now a follower!
|
|
|
|
|
i've made a red square there in the paint event.
It is not showing at all.
Only the text from the same paint event is visible.
When i drag the control from toolbox into my form, a very large grey square appear, but not my red square and its text.
I want the area to be as large as that red square (20,20). When I move my mouse over this red square area, I want the text to change. All this graphics must "float" over other controls. In this way, I can intersect many other controls like these between them.
|
|
|
|
|
Did you add the Paint event handler to your UserControl? Check in the designer!
Sent from my Amstrad PC 1640
Never throw anything away, Griff
Bad command or file name. Bad, bad command! Sit! Stay! Staaaay...
AntiTwitter: @DalekDave is now a follower!
|
|
|
|
|
alright, now is showing in Form1 after I add this class object to Controls.
I also get rid of the custom paint event i made earlier.
If its not good what i did here, please correct me.
public class Human : UserControl
{
public Human()
{
Paint += new PaintEventHandler(Human_Paint);
}
void Human_Paint(object sender, PaintEventArgs e)
{
e.Graphics.DrawString(Name, new Font("Arial", 9), new SolidBrush(Color.Black), Location.X - 5, Location.Y - 15);
e.Graphics.FillRectangle(new SolidBrush(Color.Red), new Rectangle(Location.X, Location.Y, 20, 20));
}
}
|
|
|
|
|
Just as an aside: dont; create Font and Brush (or any graphics items) willy nilly - they all use something called Handles which are in short supply. If you create a graphics item, it needs a fresh handle, so unless you specifically Dispose of it when you are finished, you will crash your app with an "out of memory" exception pretty quickly because the whole system will run out of Handles and become unstable. It's a very good idea to create a static class level Font and Brush item, and use them, or use a using block around the item construction so that it is automatically Disposed when it goes out of scope.
Sent from my Amstrad PC 1640
Never throw anything away, Griff
Bad command or file name. Bad, bad command! Sit! Stay! Staaaay...
AntiTwitter: @DalekDave is now a follower!
|
|
|
|
|
I tell you what: stop what you are doing.
Create a new solution, WinForms, call it "HumanDemo"
Add a UserControl to the project, call it Human.
In the designer, add event handlers to the Human control: MouseEnter, MouseLeave, Paint.
In the Human code, add a field and a property:
private bool isIn = false;
public string Name { get; set; }
In the Human Constructor, add a line, so it looks like this:
public Human()
{
InitializeComponent();
Name = "A name";
}
Then edit the three handlers so they look like this:
private void Human_MouseEnter(object sender, EventArgs e)
{
isIn = true;
Invalidate();
}
private void Human_MouseLeave(object sender, EventArgs e)
{
isIn = false;
Invalidate();
}
private void Human_Paint(object sender, PaintEventArgs e)
{
Graphics g = e.Graphics;
Rectangle rect = e.ClipRectangle;
rect.Inflate(-1, -1);
g.DrawRectangle(Pens.Red, rect);
if (isIn)
{
g.DrawString(Name, Font, Brushes.Black, new Point(10, 10));
}
}
Compile your project.
Go to the main form in teh designer, and drag a Human control from your toolbox and drop it on the form.
Run your application. Move the mouse into and out of the red rectangle.
That's how simple it is!
Sent from my Amstrad PC 1640
Never throw anything away, Griff
Bad command or file name. Bad, bad command! Sit! Stay! Staaaay...
AntiTwitter: @DalekDave is now a follower!
|
|
|
|
|
i made it work now.
modified 22-Dec-18 5:00am.
|
|
|
|
|
See how easy it is?
Sent from my Amstrad PC 1640
Never throw anything away, Griff
Bad command or file name. Bad, bad command! Sit! Stay! Staaaay...
AntiTwitter: @DalekDave is now a follower!
|
|
|
|
|
Your code is not good at all.
Look here in my screenshot:
http://i64.tinypic.com/29dijx3.jpg[^]
The first red square must be visible under the second square control !
With my code, I can make it show one beneath the other one.
|
|
|
|
|
Two things:
1) no image.
2) You didn't think it might have something to do with the order in which you added the controls? Google "Z-order" and start thinking about what you are doing instead of guessing ...
Sent from my Amstrad PC 1640
Never throw anything away, Griff
Bad command or file name. Bad, bad command! Sit! Stay! Staaaay...
AntiTwitter: @DalekDave is now a follower!
|
|
|
|
|
|
And did you google "Z-order"?
Sent from my Amstrad PC 1640
Never throw anything away, Griff
Bad command or file name. Bad, bad command! Sit! Stay! Staaaay...
AntiTwitter: @DalekDave is now a follower!
|
|
|
|
|
i know what z-order is - its not that. I intersect the 2 squares, not putting one on top of the other. Both are z-order dependent but with diferent meanings... you will get my point very easy from my screenshot.
|
|
|
|
|
|
Right - you can't do that with controls at all; you have to use Paint and draw yyour rectancgles your self.
Which means that you have to do the "entry" and "exit" code yourself, by handling MouseMove in your Parent container, and manually checking which of your rectangles the mouse is currently in:you cannot use MouseEnter and MouseLeave on your own rectangles because - unless they are Controls and in which case transparent backgrounds don't work - only Controls can react to mouse events.
Remove UserControl, and go back to drawing them yourself - but you will have to work out where the mouse is yourself, the system will not help you!
Sent from my Amstrad PC 1640
Never throw anything away, Griff
Bad command or file name. Bad, bad command! Sit! Stay! Staaaay...
AntiTwitter: @DalekDave is now a follower!
|
|
|
|
|
Excellent answer so far, mister OriginalGriff: "you will have to work out where the mouse is yourself, the system will not help you". Can you help me making such "manual" class? I am aware I am asking a lot...
|
|
|
|
|
I'd do two things: Add a Paint method to the class which takes a single parameter: the Graphics context from the Containing classes Paint event.
And I'd add a Contains method returning a bool, which again takes a single parameter: a Point which it checks is inside it's "boundaries" (using the Location and Size information it contains). This could change the Name to be drawn, or that could be done externally, it depends what - exactly - you are trying to do, and how it all fits together as a complete system.
The containers MouseMove calls each Human instance's Contains method so they "know" if the mouse in over them or not. (The containers MouseExit event handler can reset them all)
This can call Invalidate to force a redraw as needed.
The Containers Paint event also calls each Human instance's Paint method so it draws itself.
Make sense?
Sent from my Amstrad PC 1640
Never throw anything away, Griff
Bad command or file name. Bad, bad command! Sit! Stay! Staaaay...
AntiTwitter: @DalekDave is now a follower!
|
|
|
|
|
yes, it makes sense...because I was thinking in the same direction too.
I will go with your idea.
I am building it now.
|
|
|
|
|
This is the working code so far. I will experiment with it further and I will update with new problems on the way. Also, you update it too if you feel you can help it more.
I was thinking on using refractor and actually look inside original mouse move event to see how they did it there, and copy it into my class... but is planned for the future.
Now, i am happy. It's some work to do but i get the transparency of the objects !
public class Human
{
private string _Name = "none";
public string Name { get { return _Name; } set { _Name = value; } }
public Point Location { get; set; }
public Size Size { get; set; }
public void Paint(Graphics g)
{
g.DrawString(Name, new Font("Arial", 9), new SolidBrush(Color.Black), Location.X, Location.Y - 15);
g.FillRectangle(new SolidBrush(Color.Red), new Rectangle(Location.X, Location.Y, Size.Width, Size.Height));
}
public bool Contains(Point point)
{
if (point.X >= Location.X & point.X <= Location.X + Size.Width &
point.Y >= Location.Y & point.Y <= Location.Y + Size.Height)
{
return true;
}
else
{
return false;
}
}
}
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
DoubleBuffered = true;
female.Name = "Alina";
female.Location = new Point(20, 20);
female.Size = new Size(30, 30);
}
Human female = new Human();
private void Form1_Paint(object sender, PaintEventArgs e)
{
female.Paint(e.Graphics);
}
private void Form1_MouseMove(object sender, MouseEventArgs e)
{
if (female.Contains(e.Location))
{
female.Name = "Gaga";
}
else
{
female.Name = "Alina";
}
Invalidate();
}
}
|
|
|
|
|
Thank you so far, mister OriginalGriff !
|
|
|
|
|
You're welcome!
Sent from my Amstrad PC 1640
Never throw anything away, Griff
Bad command or file name. Bad, bad command! Sit! Stay! Staaaay...
AntiTwitter: @DalekDave is now a follower!
|
|
|
|
|