|
Hi Wayne Macdaid,
I think I need to give a little more explanation for my code. And I am sorry that I omitted to mention that you need to drag and drop two buttons on the form! Any way, here is a more detailed explanation of the code:
First create a 'Windows application' project (not console application) in Visual Studio (VS).
By default, you will have one blank form open in VS. Drag and drop two buttons. Name the first button "None" and the second "Ellipse". Now clicking the button1 sets the variable 'SelectedShape' to "None". So the application stops drawing ellipses. When you click button2 it sets the variable 'SelectedShape' to "Ellipse" and the application now starts drawing the ellipse whenever you start clicking and dragging on the form. In short, these buttons switch 'On' and switch 'Off' the drawing of the ellipse. By default, the variable 'SelectedShape' is set to 'None' at the time of initialisation of the application.
Now about the events.
We want to draw an ellipse only when 'SelectedShape' is set to 'Ellipse'. So when you press the mouse button down (see code Form1_MouseDown event)we check whether 'SelectedShape' has been set to "Ellipse". If so we store the X,Y co-ordinates from the mouse event as the top-left co-ords. of the SelectionRectangle.
After you press the left mouse button down, you have to drag the mouse to draw the ellipse ( and also, if needed, the bounding rectangle i.e. SelectionRectangle). When you move the mouse over the form, Windows generates 'MouseMove' events. So we have to handle this event when the mouse moves. We do this inside 'Form1_MouseMove'. Here, we first check if the left mouse button is still down. (Otherwise, the mouse button has been released). If so, we calculate the width and height of the SelectionRectangle using the the top-left co-ords. of the SelectionRectangle and the current mouse pointer position. Now one important point to note here is that we want to show a 'rubberbanding' effect in drawing the rectangle and ellipse. This will actually be done by the 'Form1_Paint' event. Since any changes in the size of the SelectionRectangle should be reflected on the Form immediately. So we first 'Invalidate' the form and then call 'Update' method. This will cause the 'Form1_Paint' event to be executed immediately.
Inside the 'Form1_Paint' event, we first check to see if the 'SelectedShape' is "Ellipse". If it is so, we proceed to draw the rectangle and the ellipse.
When we finish drawing the ellipse and releases the mouse button, we just store the re-calculated width and height of the 'SelectionRectangle' and again call 'Invalidate' and 'Update' and exit.
One important thing to note while doing graphics under Windows is that, Windows re-draws the contents of a window every now and then. i.e. when it is minimized, maximized, moved, is overlapped by any window or part of it etc. When redrawing it clears everything on its surface first. So what has been drawn outside of the window's 'OnPaint' event gets erased. So all drawing should be done inside the 'Paint' event. This is one major error committed by beginners to graphics under Windows.
Hope this clears your doubts.
Happy coding,
Lamrin
|
|
|
|
|
Thank you Lamrin - I will give this a try.
|
|
|
|
|
Lamrin
Instead of dragging two buttons; can I just put them on the toolbar. I would like to use button2 to also click button1 when clicked. Is this possible?
|
|
|
|
|
Hi,
Instead of dragging two buttons onto the form, you can very well use two buttons on the toolbar.Or even create a 'toolbox' like the one you find in the 'MS Paint' software. I dragged and dropped two buttons (as example) onto the form just to demonstrate how to draw an ellipse interactively!
But why do you want to click button titled 'Ellipse' when you click button titled 'None' automatically? My code is just a demonstration. The reason why I used two buttons are these :
1) There may be times when you don't want your program to draw an ellipse when the left mouse button is pressed and dragged on the form. So how to indicate to the program that you want to stop drawing ellipse? Set the variable 'SelectedShape' to 'None'.
2) Later when you want to again start drawing an ellipse, you click second button titled 'Ellipse' to save 'SelectedShape' to 'Ellipse'. The program now knows that it has to draw an ellipse whenever you press the left mouse button down and drag the mouse. How ? Because, the variable 'SelectedShape' now hold the value 'Ellipse'.
The purpose of the buttons is therefore to set a value for the 'SelectedShape' variable. The value set in this variable will be used by the code in the 'Paint' event to either draw an ellipse (if the varilable is set to 'Ellipse') or not to draw anything ( if the variable is set to 'None'). It is just my logic. You can design your own!
Now, if you want to click 'None' button automatically when you click the 'ellipse' button what do you expect the program to do ? To draw an ellipse or not ?
It may be possible to automatically click button 'None' when button 'Ellipse' is also clicked. But in this case it does not seem to logical as these two buttons do two opposite things!
|
|
|
|
|
Thanks Lamrin I understand now why there are two buttons. It seems to work OK. I do have a couple bugs to iron out. The application I did draws a line or rectangle with reversible frame. I have a button for either on the toolbar. It works well. Also on the menu under file is "New" and "Exit". The new button clears what is drawn on the form and exit closes the form. If I want to do the ellipse, I press the none button and then the ellipse button; I see the rectangle drawn; but, the ellipse doesn't show until I hit the New button? Then it does not clear the form until I hit None, then New. Just some bugs to work out.
I'll keep working on it. I then have to figure out where I can get info on adding a color button so the user can fill the drawn object with a color. I have a button "Color" where a drop down palette appears. The problems with this is that the palette eliminates anything drawn that it covers when it drops down. Also, it doesn't transfer color to the drawn item. I can get it to change the color of the button. Is there a section in MSDN to find this type of code? Thank you again for the information.
|
|
|
|
|
Hi Wayne Macdaid,
The reason why your drop down pallete wipes whatever was drawn previously when it drops down is due to the peculiarity of GUI system of Windows.
As your probably know, though you create your form with all the controls in C# (or any in any language with GUI features), it the Windows operating system which actually draws everything in the background.
You know that Windows can open multiple windows on our screen. When you click any window, it becomes activated and comes to the forefront and whatever was in the front goes back. Actually there are no layers on a computer screen. But Windows only visually simulates. How ? Windows redraws the currently activated windows over whatever is on the screen thus overlapping whatever was on the screen. Now you can see this window above all other windows. When you move any window (let us call it Window1) over another (let us call it Window2), the Window1 is redrawn over the Window2 and some part of the Window2 get erased. But if you click any visible part of Window2 again, it becomes active and Windows OS redraws Window2 completely so that all parts of it is fully visible. Thus the Windows Operating System frequently redraws either completely or some part of each window as appropriate.
Now, in your case you draw something on your form (I presume). Then when pull down your drop down palette, Windows OS actually redraws the pallete in a bigger size (as specified by you) and thus some part of your form is erased. Now when you minimize your palette after choosing your color, the area previosly erased has to be redrawn by Windows OS. But Windows OS has nothing to remember what was in that space earlier. So it just paints the background color. In effect, what was there before you pulled the palette down is erased!
How can you prevent it ? I don't know what type of software you are writing. But suppose it is something like MS Paint, then whenever your draw any shape, save its details into a suitable data structure. Then, in the paint event of the form, read that details of each shape in the data structure and redraw it again. This way your drawings won't seem to disappear. For example, create a class in C# as follows :
public class Shape<br />
{<br />
String ShapeName ;
}<br />
<br />
public class Line : Shape<br />
{<br />
Point StartPoint;<br />
Point EndPoint;<br />
<br />
public Line() : base()<br />
{<br />
ShapeName = "Line";<br />
.<br />
.<br />
.<br />
}<br />
}<br />
<br />
public class Circle : Shape<br />
{<br />
Point Centre;<br />
int Radius;<br />
<br />
public Circle()<br />
{<br />
ShapeName = "Circle";<br />
Radius = 0;<br />
Centre = new Point(0,0);
}<br />
}<br />
<br />
ArrayList ShapeList = new ArrayList();
Now add all shapes to the ShapeList whenever you create a shape. In 'Paint' event of the form (or any other control you are using), use the details of each shape in the ShapeList to redraw the shapes. That's all.
Well, I don't remember any section in MSDN suitable for you. But do a 'Google' search.
Happy coding!
|
|
|
|
|
Thank you, Lamrin I will work on this and Google the other subjects.
Thanks again
|
|
|
|
|
I'm a hobbyist learning slowly about C# & OOD & N-Tier. I was looking at a couple of how-tos on the web today. Both had the business layer talking to the data layer like this example-
public class BusinessLayer
{
public int Method1(string firstName, string lastName)
{
DataLayer dataLayer = new DataLayer();
return dataLayer.DoSomething(firstName, lastName);
}
public int Method2(int personID, string firstName, string lastName, int age)
{
DataLayer dataLayer = new DataLayer();
return dataLayer.DoSomethingElse(personID, firstName, lastName, age);
}
}
I would have coded it like this -
public class BusinessLayer
{
private DataLayer dataLayer = new DataLayer();
public int Method1(string firstName, string lastName)
{
return dataLayer.DoSomething(firstName, lastName);
}
public int Method2(int personID, string firstName, string lastName, int age)
{
return dataLayer.DoSomethingElse(personID, firstName, lastName, age);
}
}
Assuming my way is wrong, why is their way correct? Is it an encapsulation principle that I don't understand correctly or something else? Thanks.
|
|
|
|
|
I've seen it done the first way when the number of users of the system exceeds the number of database licenses.
The DataLayer connects only for a short time to get the needed data. This way you can have 10 users on a database with 5 licenses. The DataLayer waits for an open connection then quickly connects/disconnects so the next query can be processed.
Your way of connection will provide data more quickly but you need enough database licenses for all users.
|
|
|
|
|
Ah ha! That makes a lot of sense. Thank you.
|
|
|
|
|
If you need the dataLayer to be around for the entire class, your way is right.
Remember this object will be lying around for the duration of the existince of the BusinessLayer class - it will not be garbage collected.
If you create it within a method, it will be garbage collected if you are running out of space.
Personally, I would write this piece of code the way you have written it.
The funniest thing about this particular signature is that by the time you realise it doesn't say anything it's too late to stop reading it.
My latest tip/trick
Visit the Hindi forum here.
|
|
|
|
|
Good question (I've 5'd you) but personally, I think there are better solutions than both of the above. The business layer should be agnostic of the data layer as far as possible. The Data layer should have CRUD operations for the business objects, not the business layer calling the data layer. This is better separation of concerns IMO.
If you are actually "just" interested in persisting models (as opposed to doing this as an exercise in itself) it is worth giving the Entity Framework a look, or NHibernate. They map object model to relational models whilst having minimal/little impact on the purity of the object model itself.
|
|
|
|
|
The former approach is also used when it's desirable to keep the business object alive while at the same time releasing the data-layer object for garbage collection.
|
|
|
|
|
Nor of the two is fundamentally wrong. As other posters have pointed out it depends on the required life-time of the DataLayer object. I would however recommend to decouple the dependency between the layers via interfaces:
public interface IDataLayer {
void DoSomething(string firstName, string lastName);
}
public interface IDataLayerFactory {
IDataLayer Generate();
}
Then, your first and second alternatives become:
public class BusinessLayer {
private IDataLayerFactory dataLayerFactory;
protected BusinessLayer() {
dataLayerFactory = null;
}
public BusinesLayer(IDataLayerFactory pDataLayerFactory) {
dataLayerFactory = pDataLayerFactory;
}
public int Method1(string firstName, string lastName) {
return dataLayerFactor.Generate().DoSomething(firstName, lastName);
}
}
public class BusinessLayer {
private IDataLayer dataLayer;
protected BusinessLayer() {
dataLayer = null;
}
public BusinesLayer(IDataLayer pDataLayer) {
dataLayer = pDataLayer;
}
public int Method1(string firstName, string lastName) {
return dataLayer.DoSomething(firstName, lastName);
}
}
Of course there has to be an implementation:
class ASpecificDataLayer : IDataLayer {
public void DoSomething(string firstName, string lastName) {
}
};
class ASpecificDataLayerFactory : IDataLayerFactory {
public IDataLayer Generate() {
return new ASpecificDataLayer();
}
};
The fundamental difference is that your buiness layer does not depend on a specific implementation of a data layer, it only depends on the interface which can be implemented in various ways. This idiom is fundamental in OOD and is called dependency inversion. There is a lot of support for this pattern at framework level in form of so called dependency containers or service locators. Please google on the boldified termini for further information.
Cheers,
Paul
|
|
|
|
|
I already am aware the built in C# class can obtain the file version and product version 'strings' but I need to obtain the raw numeric values.
Is anyone aware of a public code base to do this?
I don't want to go off and make a DLL to be called by Interop or COM if I don't have to.
Thanks.
|
|
|
|
|
Hi , have a good day
Open a new C# Windows Application Project , Then :
- Menu -> Project -> "Your Project Properties" -> Settings
- Add new Setting , for example : "Setting1"
Execute the following code only once:
Properties.Settings.Default.Setting1 = "Hi , From setting1";
Properties.Settings.Default.Save();
Close your application
Then Run your Application again and Execute the following code :
MessageBox.Show(Properties.Settings.Default.Setting1);
The Question is :
Where is the value of setting1 saved ?
I know nothing , I know nothing ...
|
|
|
|
|
A file called "YourProjectName.exe.config"
It's just plain old XML.
|
|
|
|
|
Thank you so much ,
I was doing it the hard way , searching inside registry , system folder , windows folder
And it's was in front of me ( I am ashamed ) , Also I was confused with the other files in the debug folder
I know nothing , I know nothing ...
|
|
|
|
|
Just for your reference, I'm pretty sure a backup copy of those settings are embedded into the DLL (in case the config file gets deleted, I suppose). It doesn't change when you do the updates to the settings at runtime (only stores them when yo compile the DLL). At least I think that's how it works.
|
|
|
|
|
I am not sure if my subject line makes sense. But I want to create a simple user control that when consumed in aspx should have the following capability:
<uc1:addresscontrol id="AddressControl2" runat="server">
<addresslabel>Postal Address
<addresslabelcss>label
Where AddressLabel and AddressLabelCss are the properties of the control. This is just an example. But eventually I want a address control that will have labels and textboxes for address, city, state, zip. And want to give the user option to define the order himself. Something like gridview control. Example:
<uc1:addresscontrol runat="server">
..
<state>..
<city>..
Is this possible?
|
|
|
|
|
|
Hi Experts,
I want to make a website for selling my product. Please suggest should i go for website development in asp.net or php.
Since linux server does not support .net so i have to use windows server in case i select asp.net.
I do not have idea about which server is more secure (linux or windows)
Also which website provides better performance aspx or php
Please suggest.
|
|
|
|
|
Linux does support .NET via Mono.
Real men don't use instructions. They are only the manufacturers opinion on how to put the thing together.
|
|
|
|
|
I would suggest you choose whichever technology you are more comfortable in.
The funniest thing about this particular signature is that by the time you realise it doesn't say anything it's too late to stop reading it.
My latest tip/trick
Visit the Hindi forum here.
modified on Friday, October 15, 2010 11:11 AM
|
|
|
|
|
He should choose the technology you are most comfortable in?
|
|
|
|
|