|
|
Hey everyone!
This is my first question that I've asked on this forum. I'm a fairly experienced C# coder who has browsed this site but never posted anything.
My question is simple, fairly straight forward. I would like to be able to select an object I have drawn with the System.Drawing.Graphics class. I would like to know how I could process the drawn-on control's MouseDown event so that the program can detect which objects have been drawn
this.CreateGraphics().DrawLine(new Pen(Color.Blue) { Width = 2.5f }, new Point(0, 0), new Point(50, 150));
This kind of drawing. I don't want to create a new control for every object being drawn on the screen, unless of course there is some way of doing it that doesn't hamper performance.
I have 2 ideas, but they aren't efficient enough, especially with a managed language such as C#. It is as follows: the program stores the information of which points inside the control are painted on. For example, the software could know that there is a blue pixel at point (20; 40). If the MouseDown event has to process every point, than I would imagine this method is extremely inefficient. Also, working out the area of a completely irregularly shaped object would be possible, but not in this case considering there are going to be user-defined/created objects drawn on screen.
Any advice on how I should do this? Any advice would be very helpful. Code samples would be a huge help.
Thanks A Lot,
Genius Mchlahla, (Amateur South African Programmer)
|
|
|
|
|
Which out of the following are you doing? I can give you an answer for any of them...
- Hit-testing individual shapes - i.e. determining whether the mouse is over a shape, and if so, which one of the shapes on your control it is over.
- Hit-testing the entire control - i.e. determining whether the mouse is over any drawn object on the control
- Determining redraw or clipping areas
I'll assume the first one for now, so here's a fairly efficient way to hit-test to determine which individual shape, if any, the mouse (or any other single point) is over.
First, you need to set up code to create a GraphicsPath for the shape that matches what's being drawn. For example, a GraphicsPath for a set of circles could be created like this:
var gp = new GraphicsPath();
gp.AddEllipse(myCircleRect1);
gp.AddEllipse(myCircleRect2);
Now, you can call gp.IsVisible(pt) to determine if a given point is over any filled part (as opposed to the outline) of the shape if it is a filled shape, or gp.IsOutlineVisible(pt, pen) to determine if a point is within the outline of the shape if it is not filled. If you want to check both the outline and the inside of a shape at the same time, use gp.Widen(pen) when you create the graphics path, after adding the shapes. In either case, be sure that your pen has all the characteristics of the one being used to actually draw the shape - width, mitre mode, end caps, dash type, etc. The GraphicsPath hit testing methods take these into account, which saves you a huge amount of coding to determine the actual line's hit test area.
To make use of this efficiently, this is probably the best way:
1. Re-build the shape's graphics path when the shape and/or drawing pen changes. Use gp.GetBounds() to get the outer bounding rectangle of the graphics path. Make sure to either pass the pen to GetBounds(), or use gp.Widen() when creating it as I mentioned above. Store the bounds of the shape with the object itself. If you have a whole lot of shapes, don't keep the graphics path around - call Dispose() on it and get rid of it. If you have a smaller number of shapes, you might want to store the GraphicsPath along with the cached bounds.
2. When a mouse down event happens, search through your list of objects (sorted by z-order so that you check the topmost shapes first), and find the first bounding rectangle that contains the mouse cursor point. When you find one, either retrieve your stored graphics path or create a new one (as above), and use IsVisible() or IsOutlineVisible() as above to find out if the mouse is actually over the shape. If not, continue to check bounding rectangles until you find another one that the mouse is within, and test the graphics path on that one, etc.
If you store the graphics paths, sure to cache the bounding rectangle when an individual shape changes, instead of calling GetBounds() on each object each time the mouse is clicked. Otherwise you won't be saving some CPU expense that you could otherwise save. Also no matter what you do with the GraphicsPath objects (caching them or discarding them immediately), always call Dispose() when you're completely done with them, just like you do with Graphics, Pen, and Brush objects.
Also note that the bounding rectangle is good to do hit testing with, but if you're determining the drawn area for redraw purposes or for clipping, you'll need to widen the bounds by a pixel in each direction to account for the possibility of antialiasing effects that could be outside of the hit testing bounds.
|
|
|
|
|
Thank you! I've been trying to figure this out myself but to no avail... This code is helpful
|
|
|
|
|
Glad to help
|
|
|
|
|
Can anyone explain how to edit one of the text fields in a report based off the an entry submitted by a user on a form textbox.
|
|
|
|
|
|
Collin Jasnoch wrote: Anyone done any speed comparisons in getting the info to file or the Event Logs?
Never done so; logging an exception is something that happens exceptionally, not every second. The EventLog is not the right place if you're logging a lot of traffic, but it is the right place to report problems to the SysAdmin of that network.
I think that you shouldn't be checking whether it's "speedy" enough, but rather if you can easily get all the information from it that you need. The fact that one can read an EventLog remotely doesn't matter much to me, as one can do the same with a simple text file.
I are Troll
|
|
|
|
|
|
Collin Jasnoch wrote: So what would be the right place?
For a lot of traffic, I'd go for a textfile and import that into a database. Easy to zip & mail, and appending text to a file doesn't cost much cpu-time. This is ideal for logging lots of data, as you can simply dump it without much ado. It would also be the best place to hide your exceptions from the customer if you wanted to - you can encrypt the string before writing it.
The EventLog would be the ideal place for exceptions, and general diagnostic events. Things like starting a service, or registering a new license.
|
|
|
|
|
Never had reason to test it, but I'm quite confident that speed is not an issue.
I'd use a framework such as the Microsoft Enterprise Library Exception Handling Block and Logging Application Block to give you the flexibily to change where and how you store such information if an issue does arise with one method.
I know the language. I've read a book. - _Madmatt
|
|
|
|
|
Lookup TracerX. Very good at logging Messages/Exceptions. You can also set the level of the logs.
|
|
|
|
|
Log4Net provides a good way of performing the logging you need. The speed has allways been more than adequate for my purposes.
The Log file can be configured in the app.config file and can be sent to single or multiple destinations (event log, database, text file etc), and what is logged is customisable.
Log4Net is also fail-safe (ie almost never throws and error that stops your code), which is good for trace and error logging. Logging is not guaranteed (due to the fail-safe nature, a failure results in no message) and is therefore no good for audit requirements, but once you have it is configured and tested, I've not seen a message missed so it is pretty reliable.
CCC solved so far: 2 (including a Hard One!)
37!?!! - Randall, Clerks
|
|
|
|
|
Hi
i need help ...
i want to make program which can dial a phone using modem connected with a telephone line..and similarly record a
conversation and also set up a voice mail..i'm a bit familiar with c sharp language so would like to do in a c sharp language..if anyone had got any idea about it then..plz help me..
Thank You
|
|
|
|
|
In our company we use TopTAPI (the dll-version) to do this maybe you should test it. TopTAPI (its not freeware)!
Alternativly take a look at the TAPI (I would use TAPI3).
At least 1 hint: Its not fun to do this for analog connectors/telephones because you need a special modem (full-duplex and some other stuff I forgot) to do this and also in most cases the connection is only a one way (both are connected but only one of them could speak).
So just use it with ISDN and above (for example VoIP, but I never tested with TAPI).
Greetings
Covean
|
|
|
|
|
Hi!Covean
Thank x for your suggestion...isn't it possible with the inbuilt modem in a computer(the one which is used to connect dial up line)..what i want is if the phone line is connected to the computer via modem then..is it possible that all the phone works i.e. dialling or receiving call...could be done with the application..this is wht all i want..
Regards
DRS2010
|
|
|
|
|
As said before, it depends on the caps of the modem. But in theory it should work.
But here some impressions of mine, I made during our "virtual portier"-project.
Some day a customer of us wanted this solution but on a analog telephone system (we only installed it on ISDN before). This project really drove me cracy. We tested about 5 modem-types. Sometimes we had a full connection, sometimes only one of us could speak and so on... Till the end of the project we never found a stable solution for this (at least we solved it with an analog<->ISDN converter)!
So it should be possible but I would not recommend it!
Edit: To your question: I don't think that you will be able or happy to do this with the build-in-modem. But checking the line status, dialing and recieving calls will be able with TAPI.
Greetings
Covean
modified on Tuesday, January 19, 2010 3:48 AM
|
|
|
|
|
Hi Covean
Thank x a lot for your idea
So dialling and receiving calls is possible with TAPI.Do you have any idea about such type of application i mean phone dialling and receing application with the use of TAPI.
Regards
|
|
|
|
|
No I do not because the TopTAPI.dll (I mentioned in my first post) were cheaper then the time I had needed to develop it on my own, so our company decided to just buy it.
Sorry that I can't help you any further.
Greetings
Covean
|
|
|
|
|
Hi,
Good
modified 3-Jul-12 4:58am.
|
|
|
|
|
1. Not everyone can see that. Since it is not yet approved.
2. People have already posted their view below the article and through votes.
50-50-90 rule: Anytime I have a 50-50 chance of getting something right, there's a 90% probability I'll get it wrong...!!
|
|
|
|
|
Lame attempt at self promotion. Based on the votes so far I doubt anyone will even see this "article"
I know the language. I've read a book. - _Madmatt
|
|
|
|
|
Hi all,
I want to execute an executable file under particular user account in my C# application.
can any body tell me how to do the same?
Thanking You,
Sunil G.
|
|
|
|
|
you could check the "runas" command
specify the executable and particular user as arguments.
|
|
|
|
|
using Process.Start [^], it supports launching a process under a particular user;
MSDN states:
Use this overload to create a new process and its primary thread by specifying its file name, command-line arguments, user name, password, and domain. The new process then runs the specified executable file in the security context of the specified credentials (user, domain, and password).
I are Troll
|
|
|
|
|