|
Hi, I've had a look through my files and I never completed it as it was no longer required. You are welcome to use what I did and finish it off if you'd like. The main things that need doing are marked // ToDo: - unfortunately that includes the painting and mouse handling - but the Range struct is pretty much complete and the main code for the control is in place.
using System;
namespace DaveyM69
{
[Serializable]
public struct Range : IEquatable<Range>
{
public static readonly Range Empty = new Range();
public static readonly Range MaxRange = new Range(int.MinValue, int.MaxValue);
public static readonly Range Percentage = new Range(0, 100);
private int lower;
private int upper;
public Range(int lower, int upper)
{
if (lower > upper)
{
int newUpper = lower;
lower = upper;
upper = newUpper;
}
this.lower = lower;
this.upper = upper;
}
public static bool operator ==(Range rangeA, Range rangeB)
{
return (rangeA.lower == rangeB.lower) && (rangeA.upper == rangeB.upper);
}
public static bool operator !=(Range rangeA, Range rangeB)
{
return !(rangeA == rangeB);
}
public int Lower
{
get { return lower; }
}
public int Upper
{
get { return upper; }
}
public Range Adjust(int offset)
{
return new Range(lower + offset, upper + offset);
}
public int Contain(int value)
{
return Contain(value, false);
}
public int Contain(int value, bool excludeExtremities)
{
Range testRange = excludeExtremities ? this.Expand(-1) : this;
if (value < testRange.lower)
return testRange.lower;
if (value > testRange.upper)
return testRange.upper;
return value;
}
public Range Contain(Range range)
{
return Contain(range, false);
}
public Range Contain(Range range, bool excludeExtremities)
{
if (Contains(range, excludeExtremities))
return range;
int newLower = range.lower;
int newUpper = range.upper;
if (!Contains(range.lower, excludeExtremities))
{
newLower = lower;
if (excludeExtremities)
newLower++;
}
if (!Contains(range.upper, excludeExtremities))
{
newUpper = upper;
if (excludeExtremities)
newUpper--;
}
Range result = new Range(newLower, newUpper);
if (!Contains(result, excludeExtremities))
throw new InvalidOperationException("The span of this range is too small to contain another range");
return result;
}
public bool Contains(Range range)
{
return Contains(range, false);
}
public bool Contains(Range range, bool excludeExtremities)
{
return Contains(range.lower, excludeExtremities) && Contains(range.upper, excludeExtremities);
}
public bool Contains(int value)
{
return Contains(value, false);
}
public bool Contains(int value, bool excludeExtremities)
{
Range testRange = excludeExtremities ? this.Expand(-1) : this;
if (testRange.lower < lower)
throw new InvalidOperationException("The span of the specified range is too small to contain another range");
return (value >= testRange.lower) && (value <= testRange.upper);
}
public Range Expand()
{
return Expand(1);
}
public Range Expand(int value)
{
return new Range(lower - value, upper + value);
}
public override bool Equals(object obj)
{
return obj is Range && this == (Range)obj;
}
public bool Equals(Range other)
{
return this == other;
}
public override int GetHashCode()
{
return lower ^ upper;
}
public override string ToString()
{
return string.Format("{0}, {1}", lower, upper);
}
}
}
using System;
using System.ComponentModel;
using System.Drawing;
using System.Windows.Forms;
namespace DaveyM69.Windows.Forms
{
public class RangeControl : Control
{
private static readonly Size Default_Size = new Size(200, 50);
[Category("Range")]
public event EventHandler ExcludeExtremitiesChanged;
[Category("Range")]
public event EventHandler InnerRangeChanged;
[Category("Range")]
public event EventHandler OuterRangeChanged;
[Category("Range")]
public event EventHandler ValueChanged;
private bool excludeExtremities;
private Range innerRange;
private Range outerRange;
private int value;
public RangeControl()
{
SetStyle(
ControlStyles.AllPaintingInWmPaint |
ControlStyles.OptimizedDoubleBuffer |
ControlStyles.ResizeRedraw |
ControlStyles.Selectable |
ControlStyles.SupportsTransparentBackColor |
ControlStyles.UserPaint, true);
excludeExtremities = false;
innerRange = new Range(25, 75);
outerRange = Range.Percentage;
value = 50;
}
protected override Size DefaultSize
{
get { return Default_Size; }
}
[Category("Range"),
DefaultValue(false)]
public bool ExcludeExtremities
{
get { return excludeExtremities; }
set
{
if (excludeExtremities != value)
{
excludeExtremities = value;
OnExcludeExtremitiesChanged(EventArgs.Empty);
InnerRange = innerRange;
Value = this.value;
}
}
}
[Category("Range"),
DefaultValue(typeof(Range), "25, 75")]
public Range InnerRange
{
get { return innerRange; }
set
{
value = outerRange.Contain(value, excludeExtremities);
if (innerRange != value)
{
innerRange = value;
Invalidate();
OnInnerRangeChanged(EventArgs.Empty);
Value = this.value;
}
}
}
[Category("Range"),
DefaultValue(typeof(Range), "0, 100")]
public Range OuterRange
{
get { return outerRange; }
set
{
if (outerRange != value)
{
outerRange = value;
OnOuterRangeChanged(EventArgs.Empty);
InnerRange = innerRange;
}
}
}
[Category("Range"),
DefaultValue(50)]
public int Value
{
get { return value; }
set
{
value = innerRange.Contain(value, excludeExtremities);
if (this.value != value)
{
this.value = value;
Invalidate();
OnValueChanged(EventArgs.Empty);
}
}
}
protected virtual void OnExcludeExtremitiesChanged(EventArgs e)
{
EventHandler eh = ExcludeExtremitiesChanged;
if (eh != null)
eh(this, e);
}
protected virtual void OnInnerRangeChanged(EventArgs e)
{
EventHandler eh = InnerRangeChanged;
if (eh != null)
eh(this, e);
}
protected override void OnMouseDown(MouseEventArgs e)
{
base.OnMouseDown(e);
}
protected override void OnMouseUp(MouseEventArgs e)
{
base.OnMouseUp(e);
}
protected virtual void OnOuterRangeChanged(EventArgs e)
{
EventHandler eh = OuterRangeChanged;
if (eh != null)
eh(this, e);
}
protected override void OnPaint(PaintEventArgs e)
{
base.OnPaint(e);
}
protected virtual void OnValueChanged(EventArgs e)
{
EventHandler eh = ValueChanged;
if (eh != null)
eh(this, e);
}
}
}
DaveIf this helped, please vote & accept answer!
Binging is like googling, it just feels dirtier. (Pete O'Hanlon)
BTW, in software, hope and pray is not a viable strategy. (Luc Pattyn)
|
|
|
|
|
If you open a new MVC2 App in VS 2010 in the HomeController in the Details action method you get this:
public ActionResult Details(int id)
{
return View();
}
Can anyone tell me what the /5 is for?
Thanks
Darrall
|
|
|
|
|
I think 5 is just a sample id. That URL is the equivalent of /Home/Details.aspx?id=5.
ShamWow
|
|
|
|
|
|
Hello everyone,
How does one go about creating an array that can be passed to C++ methods (as a pointer to a DLL exported function) and an array that will not be garbage collected.
I need to create an array in c#, pass it to a C++ DLL and I want the C++ side of things to control the lifetime of the array (so to be able to call delete[] on it).
Is there any easy way to achieve this in C#?
Thanks,
Keith
|
|
|
|
|
That is not how it works. The party allocating is also responsible for freeing; having a managed object/array is fine, you can keep the GC from moving or collecting it, however it is also the managed side that should undo this.
I have an unfinished article about that and more here[^]. Have a look at the callback stuff, so your native part can report it is done with the array.
|
|
|
|
|
Thanks you. The GCHandle method seems to be exactly what I need.
Thanks,
Keith
|
|
|
|
|
you're welcome.
|
|
|
|
|
As Luc said, if creating the array in managed code, it must be freed in managed code too.
The normal way to protect stuff is to use GCHandle.Alloc[^] using GCHandleType.Pinned[^] followed when needed by GCHandle.Free[^]. However, Luc and I had a discussion about this a while ago and Luc conducted some tests which revealed some suprising results. Luc created another article with the test code here[^] which is worth study too.
DaveIf this helped, please vote & accept answer!
Binging is like googling, it just feels dirtier. (Pete O'Hanlon)
BTW, in software, hope and pray is not a viable strategy. (Luc Pattyn)
|
|
|
|
|
Hi Dave,
After our chat I have updated the P/Invoke article so it now describes three rather than two ways of passing arrays; anyway, the OP needs the GCHandle approach, which has been included from day one.
Thanks for the support though.
|
|
|
|
|
Ah, I hadn't reread the P/Invoke one
Good to have it all in one place
DaveIf this helped, please vote & accept answer!
Binging is like googling, it just feels dirtier. (Pete O'Hanlon)
BTW, in software, hope and pray is not a viable strategy. (Luc Pattyn)
|
|
|
|
|
DaveyM69 wrote: Ah, I hadn't reread the P/Invoke one
you should reread it regularly, it is work-in-progress after all.
|
|
|
|
|
I've been looking around for an answer to this puzzling question, but so far no luck:
What's the compiler's try/finally equivalent of this code:
using (new SomeIDisposableClass())
{
SomeCode();
}
Thanks!
ShamWow
|
|
|
|
|
There's a CodeProject-article[^] that shows how it is translated
I are Troll
|
|
|
|
|
Thanks for the quick response, but that article doesn't address my specific example where a variable is not explicitly declared inside the using statement.
ShamWow
|
|
|
|
|
Al Beback wrote: that article doesn't address my specific example where a variable is not explicitly declared inside the using statement.
Ah, my bad; it does almost the same the same thing, with the difference that you don't have a reference to your class. It still creates a class, disposing it in the finally.
public static void Main(string[] args)
{
using (new SomeIDisposableClass())
{
Console.WriteLine("Hello World!");
}
Console.ReadKey(true);
}
..translates to..
.method public hidebysig static
void Main(string[] args) cil managed
{
.entrypoint
.maxstack 2
.locals init (
[0] class using_test.SomeIDisposableClass CS$3$0000,
[1] bool CS$4$0001)
L_0000: nop
L_0001: newobj instance void
using_test.SomeIDisposableClass::.ctor()
L_0006: stloc.0
L_0007: nop
L_0008: ldstr "Hello World!"
L_000d: call void [mscorlib]System.Console::WriteLine(string)
L_0012: nop
L_0013: nop
L_0014: leave.s L_0026
L_0016: ldloc.0
L_0017: ldnull
L_0018: ceq
L_001a: stloc.1
L_001b: ldloc.1
L_001c: brtrue.s L_0025
L_001e: ldloc.0
L_001f: callvirt instance void
[mscorlib]System.IDisposable::Dispose()
L_0024: nop
L_0025: endfinally
L_0026: nop
L_0027: ldc.i4.1
L_0028: call valuetype
[mscorlib]System.ConsoleKeyInfo
[mscorlib]System.Console::ReadKey(bool)
L_002d: pop
L_002e: ret
.try L_0007 to L_0016 finally handler L_0016 to L_0026
}
I are Troll
|
|
|
|
|
IDisposable disposable = null;
try
{
disposable = new SomeIDisposableClass()
SomeCode();
}
finally
{
disposable.Dispose();
}
|
|
|
|
|
Sounds logical, although I would imagine the compiler would also add an extra check for whether "disposable" is null inside the finally block.
It's interesting that none of the examples you see out there for the using statement ever mention that if you don't assign your IDisposable type to an explicitly declared variable, the compiler will do it for you behind the scenes.
Thanks.
ShamWow
|
|
|
|
|
Why and when would you write a code like that?
As far as its equivalent is concerned, just see the IL through ILDAsm or reflector and it would make things a bit clear.
modified on Monday, June 14, 2010 11:55 AM
|
|
|
|
|
d@nish wrote: Why and when would you write a code like that?
When you're interested in keeping track of when "SomeCode" begins and ends -- for logging, profiling, etc.
ShamWow
|
|
|
|
|
Use interceptor pattern for that. Check out Enterprise Library's Policy Injection Block to see how logging can be done before and after method call. (Search LogCallHandler)
|
|
|
|
|
d@nish wrote: Why and when would you write a code like that?
There's even a CodeProject-article[^] to answer that one!
I are Troll
|
|
|
|
|
Nice find.
From now on, I am going to have this in my windows forms application (of course with proper comments):
public class AppCursor : IDisposable
{
Cursor _currentCursor = null;
bool _setDefault;
public AppCursor(Cursor cursor, bool setDefault)
{
_currentCursor = Cursor.Current;
_setDefault = setDefault;
Cursor.Current = cursor;
}
#region IDisposable Members
public void Dispose()
{
Cursor.Current = (_setDefault) ? Cursors.Default : _currentCursor;
_currentCursor.Dispose();
_currentCursor = null;
}
#endregion
}
|
|
|
|
|
Chris should put that in the advertising. There is an app article for that.
I know the language. I've read a book. - _Madmatt
|
|
|
|
|
d@nish wrote: As far as its equivalent is concerned, just see the IL through ILDAsm or reflector and it would make things a bit clear.
I know, but shamefully, I'm IL challenged.
ShamWow
|
|
|
|
|