|
Hi Bill.
I wanted to know if C# was suitable for my purpose before I went too depply into learning this language, but what I've seen so far it looks like it might be what I'm looking for.
Last year I learnt Python, but while it's easy to program in it's slow and does not create compiled files that have an exe extension so that they're easy to run. You can create an exe using py2exe program but there's a lot of work in making the code ready but adding extra information to the code.
Also it's a fairly loose language and A="Tom:A=22 works without an error, so 'A' is not protected
So after considering Visual Basic Net which tends to add extra code "If..Then.. End If, etc I'm starting to like C#.
The next step is to get a better understanding of things such as Constructors, Destructors and Polymorphism.
Brian
|
|
|
|
|
To add to Bill's comments, your example looks more like accessing a property of a class, in which case you don't need to nest the classes:
public class Game
{
public Game()
{
Inventory = new GameInventory();
}
public GameInventory Inventory { get; }
}
public class GameInventory
{
public object GetObject()
{
return ...
}
}
...
Game game = new Game();
object x = game.Inventory.GetObject();
C# Guide | Microsoft Docs[^]
"These people looked deep within my soul and assigned me a number based on the order in which I joined."
- Homer
|
|
|
|
|
I found different solutions to this sort of CRTP problem previously... but can't think of a way around it this time.
The main form used by my current project allows for moving and resizing even when it doesn't have a border. I have seen other people ask about this particular need before (it seems like a fairly common need for custom forms) and I have developed a better solution than what I have seen for answers online. I would like to provide a more generic solution than the one I am using currently for myself and others if possible so hence... my asking this prerequisite question beforehand.
I am needing to create several "controls" in my current project that have this same exact behavior so I want to write an inheritable class for all of them. Simple enough... just write a template that derives from Control. The problem is that none of the derived classes will look and perform like their actual base class in every other way without some way to use a CRTP. It would be nice not to have to write separate base classes for all the seperate possible control types, including forms. Is there a way to write a generic class to cover all controls that one would want to use? Something that effectively does what this would do if this were c++? (I realize that the where statement is c# but there are ways to accomplish the same basic idea in c++).
public class MovableControl<InheritedControl> : InheritedControl where InheritedControl : Control
{
}
In c# the above class definition doesn't compile because in .NET inheriting from a template parameter is not allowed (which is why I need an alternative solution.). Of course I will continue hunting on my own, or worst case, brute force it (by creating the separate classes) but I thought I would ask here in case someone already had an idea.
|
|
|
|
|
I will be posting this as a Tip/Trick or Article here in the future with comments and explanations, but, I'm in a rush right now, and don't have time to revise/comment my extended version of this, but, this should give you some ideas.
In a Form Load eventhandler, make some Controls movable like this:
button1.SetMovable();
textBox1.SetMovable();
panel1.SetMovable();
The code:
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Windows.Forms;
namespace YOURNAMESPACE
{
public static class ControlMovableExtensions
{
private static Control currentControl = null;
private static Control currentContainer= null;
private static List<Control> MovableControls = new List<Control>();
private static Rectangle ClippingRect;
private static Rectangle ContainerRect;
private static Point lastGoodLocation;
private static Point nextLocation;
private static int mdx, mdy;
private static bool IsMouseUp = true;
private static bool UseClipping = false;
private static bool UseCapture = false;
public static void SetMovable(this Control control)
{
if (MovableControls.Contains(control))
{
throw new ArgumentException("control already movable");
}
MovableControls.Add(control);
control.MouseDown += ControlOnMouseDown;
control.MouseUp += ControlOnMouseUp;
}
public static void RemoveMovable(this Control control)
{
if (! MovableControls.Contains(control))
{
throw new ArgumentException("control is not movable");
}
control.MouseDown -= ControlOnMouseDown;
control.MouseUp -= ControlOnMouseUp;
}
private static void ControlOnMouseMove(object sender, MouseEventArgs e)
{
if (IsMouseUp) return;
nextLocation = new Point(currentControl.Left + e.X - mdx, currentControl.Top + e.Y - mdy);
if (ContainerRect.Contains(new Rectangle(nextLocation, currentControl.Size)))
{
lastGoodLocation = nextLocation;
}
currentControl.Location = lastGoodLocation;
}
private static void ControlOnMouseUp(object sender, MouseEventArgs e)
{
IsMouseUp = true;
currentControl.MouseMove -= ControlOnMouseMove;
if (UseClipping) Cursor.Clip = Rectangle.Empty;
if (UseCapture) currentControl.Capture = false;
currentControl = null;
}
private static void ControlOnMouseDown(object sender, MouseEventArgs e)
{
currentControl = sender as Control;
if (currentControl == null)
{
throw new ArgumentException("control is null");
}
currentContainer = currentControl.Parent;
ContainerRect = currentContainer.ClientRectangle;
lastGoodLocation = currentControl.Location;
mdx = e.X;
mdy = e.Y;
if (UseClipping)
{
ClippingRect = currentContainer.RectangleToScreen(currentContainer.ClientRectangle);
Cursor.Clip = ClippingRect;
}
if (UseCapture) currentControl.Capture = true;
currentControl.MouseMove += ControlOnMouseMove;
IsMouseUp = false;
}
}
}
«Where is the Life we have lost in living? Where is the wisdom we have lost in knowledge? Where is the knowledge we have lost in information?» T. S. Elliot
modified 7-Mar-19 7:14am.
|
|
|
|
|
Interesting approach using extensions. That may work. The one problem is overriding the WndProc as that is the best way to detect resizing attempts. I supposed the override can call a static method... but that is a bit strange unless we can successfully use aggressive inlining. Perhaps we can combine our ideas and write the article together since my approach is very efficient and almost works just like an ordinary window. (There is a bit of a flicker when resizing upward and left but it still works well).
|
|
|
|
|
Hi, Yes, it does work
I am not sure why you are bringing in WndProc here, for me, use of WndProc is a last resort, and that's even more so now that .NET Core is evolving rapidly.
I use different techniques to handle the rare case when a user needs to arbitrarily re-size a Control at run-time.
I look forward to reading your article.
cheers, Bill
«Where is the Life we have lost in living? Where is the wisdom we have lost in knowledge? Where is the knowledge we have lost in information?» T. S. Elliot
|
|
|
|
|
Use a proxy. Move / resize the proxy; when done, copy the properties to the original target.
"(I) am amazed to see myself here rather than there ... now rather than then".
― Blaise Pascal
|
|
|
|
|
That's an interesting approach, one that seems like what goes on with drag-drop.
In what kind of scenario would you use this rather than just move the Control ?
thanks, Bill
«Where is the Life we have lost in living? Where is the wisdom we have lost in knowledge? Where is the knowledge we have lost in information?» T. S. Elliot
|
|
|
|
|
I actually am using a proxy system. However, the main window also uses the same (similar in the case of move) system since it is a border-less form. That is why I posted this topic to begin with. I want to write one set of code for both forms and controls.
|
|
|
|
|
Only numeric textbox
private void tbxTCKimlik_KeyPress(object sender, KeyPressEventArgs e)
{
if (!(e.KeyChar >= 48 && e.KeyChar <= 57)) e.Handled = true;
if (e.KeyChar == Convert.ToChar(8)) e.Handled = false;
}
modified 6-Mar-19 9:05am.
|
|
|
|
|
Apart from being pretty poor code, what do you expect us to do with that?
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!
|
|
|
|
|
What s the problem with codE ?
|
|
|
|
|
Undocumented, magic numbers, unnecessary else condition, doesn't work with all characters sets, difficult to reuse without copy'n'paste, can be bypassed with no effort to put non-numeric characters in the TextBox, trivial problem that has better solutions (including the use of standard controls), only works efficiently in app based code - it's a gawd awful solution for a web based project.
Even the TextBox name it's attached to violates C# naming conventions[^] ...
That's why I think it's poor quality code...
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!
|
|
|
|
|
Incidentally, I have need for a similar solution (except for my issue is with a .NET System.Windows.Forms textbox). I agree that he doesn't actually ask a question here so we are not sure how to help. However, since I am facing what appears to be a similar situation (from what I can tell...) I will try and interpret: he is probably saying that his editbox doesn't catch the backspace button. I have the same problem with an editbox that is for supplying a zip code. It works fine except that the backspace key is not accepted as a control key so it doesn't respond to backspace (the back/back delete key)
|
|
|
|
|
pr1mem0ver wrote: he is probably saying that his editbox doesn't catch the backspace button
if (e.KeyChar == Convert.ToChar(8)) Also, backspace and delete are not the same button, and have a different effect.
Bastard Programmer from Hell
If you can't read my code, try converting it here[^]
"If you just follow the bacon Eddy, wherever it leads you, then you won't have to think about politics." -- Some Bell.
|
|
|
|
|
Yeah... already tried that. It doesn't work either.
|
|
|
|
|
Then you have an error in your code
Bastard Programmer from Hell
If you can't read my code, try converting it here[^]
"If you just follow the bacon Eddy, wherever it leads you, then you won't have to think about politics." -- Some Bell.
|
|
|
|
|
@pr1mem0ver Using a sub-classed TextBox, and its KeyPress event, 'Delete is not registered because it is a Control Key.
However, 'Delete will do the usual in such a TextBox.
If you start a new post here and post your current code with a description of what your goal is, and what's not working, I'll respond in detail.
cheers, Bill
«Where is the Life we have lost in living? Where is the wisdom we have lost in knowledge? Where is the knowledge we have lost in information?» T. S. Elliot
modified 9-Mar-19 8:01am.
|
|
|
|
|
If you think you're posting that for the benefit of others, that code will only work with keyboards that are rooted in a Latin character set. Your code is limited to the straight numeric values in ASCII. Try that on a Chinese or Japanese keyboard and you'll see the problem with it.
It's also not built into its own control so it can easily be reused, which itself is easy enough to do.
There are other, much better ways to do this, but I don't have the time to go into it right now.
|
|
|
|
|
Thank you for comment. This is best what I can do. If you have better solution. Please share it.
|
|
|
|
|
|
Bayram Demirci wrote: This is best what I can do. No, this is what you've done so far, and you can do better by studying the posts in this thread carefully.
«Where is the Life we have lost in living? Where is the wisdom we have lost in knowledge? Where is the knowledge we have lost in information?» T. S. Elliot
|
|
|
|
|
|
namespace CustomControls
{
public enum NumModel
{
PositiveInteger,
PositiveFloat
}
public class NumberTextBox : TextBox
{
private NumModel numModel = NumModel.PositiveInteger;
public NumModel NumModel
{
get
{
return numModel;
}
set
{
numModel = value;
}
}
protected override void OnKeyPress(KeyPressEventArgs e)
{
if ((e.KeyChar >= '0' && e.KeyChar <= '9') || (e.KeyChar == 8) || (e.KeyChar == 46))
{
if (numModel == NumModel.PositiveInteger)
{
if ((e.KeyChar == 46))
{
e.Handled = true;
}
else
{
e.Handled = false;
}
}
else
{
if ((this.Text.Contains(".") && (e.KeyChar == 46)))
{
e.Handled = true;
}
else
{
e.Handled = false;
}
}
}
else
{
e.Handled = true;
}
}
protected override void OnKeyUp(KeyEventArgs e)
{
double num;
if (this.Text != null && this.Text != "" && !double.TryParse(this.Text, out num))
{
this.Text = this.Text.Substring(0, this.Text.Length - 1);
this.Select(this.Text.Length, 0);
}
base.OnKeyUp(e);
}
}
}
|
|
|
|
|
Hi, I'd like to update an item from my collection. I used the code below but this calls the Dispose event which I'd like to avoid.
this.CurrentUser.Companies[idx] = comp;
So instead I'd like to use something like below which works and doesn't trigger the Dispose but seems inefficient with 4 calls made. Does that make sense? Can anybody please recommend a more efficient approach?
private void UpdateCompanyFields(int idx, Company comp)
{
this.CurrentUser.Companies[idx].BusinessName = comp.BusinessName;
this.CurrentUser.Companies[idx].Address.AddressOne = comp.Address.AddressOne;
this.CurrentUser.Companies[idx].Address.AddressTwo = comp.Address.AddressTwo;
this.CurrentUser.Companies[idx].Address.City = comp.Address.City;
}
|
|
|
|