Jump to content
Xtreme .Net Talk

snarfblam

Leaders
  • Posts

    2156
  • Joined

  • Last visited

  • Days Won

    2

Everything posted by snarfblam

  1. Just so you know, VB6 longs can translate not only into Integer, but also IntPtr and possibly a couple other uncommon types. You might want to download API Viewer. It doesn't make use of the IntPtr type, which is the correct type for hWnds and other handle types, but for the most part it is very handy.
  2. 1-based collections are an oddity mostly unique to VB. As far as I can remember all other version of Basic and all other languages I have ever used have 0-based arrays and collections, and in the end it is simpler and more logical. At the moment you might not agree with that, but maybe once you get used to it you will appreciate it.
  3. If you add properties to the form, as long as they don't depend on inherited properties/functions, they will always work, even if the form is closed and disposed. So, yes, if you add int and bool properties and set them before/when the form is closed (backed by a field, as opposed of reading values from a textbox or something like that) it will work. And this may be your best approach. Another option might be to create a new event and a new EventArgs class. When the form is closed, you could put the relevant data in the EventArgs object and raise the event.
  4. If you are drawing on a control, then you should know that each control also supplies a CreateGraphics method. [color="SeaGreen"]'Draw a circle that extends to the edges of SomeControl[/color] [color="Blue"]Dim[/color] g [color="Blue"]As[/color] Graphics = SomeControl.CreateGraphics() g.DrawEllipse( _ Pens.Black, SomeControl.Bounds) g.Dispose() [/Code] Note that you should always dispose of your Graphics objects.
  5. Frankly, I don't see the need for multi-quote. What will it do except clog up the threads? (I'm not being sarcastic, I'm just wondering if there is something I'm missing.) And the skyscraper ad banner... well, I'd rather see an extra ad at the top or bottom of each page. I can't see anyone, not even the regulars, closing the ad on each and every page. Vertical space is infinite on the web. Of horizontal space we have precious little. But anyone who has been around these boards long enough knows it takes me a while to warm up to new things. That's all I'm gonna say because it's not like I'm the one paying to host the site.
  6. Cool, maybe my C# Express window won't crash or mysteriously vanish anymore while I'm creating controls. The download for each Express application is also only ~30 megs.
  7. What happened to syntax highlighting on VB and C# code? I've gone color blind, and I have double vision (or, at least, all the newlines are doubled). And to make matters worse, the new advertisement banner squeezes this hard-to-read code into a tighter space. Is this a temporary issue?
  8. Attached tutorial here because of hosting problems.BitmapTutorial.zip
  9. This is just an overview of what a good DotNet programmer should know about garbage collection and disposable objects, prompted by this post. Garbage Collection There are plenty of thorough articles about garbage collection, so I will only quickly cover the basics. All class objects, or "reference type" objects, are tracked by the garbage collector. At certain points that the garbage collector deems safe, execution of a program is halted and the garbage collector identifies which objects are reachable and which objects aren't. This is done by starting at certain "roots" and tracing references to see which objects are still connected to the program one way or another. These roots include static ("shared" in VB) variables, call stacks for all threads, unmanaged callbacks, and more. The garbage collector also uses a generation system. When an object is created it is first generation. Each time a collection occurs, all objects that are checked but not collected move to the next generation (stopping at the third generation). Most garbage collections only check first generation objects, fewer check second generation objects, and fewer yet check third generation objects. This way, objects that are used for longer periods of time are checked less frequently. Disposable Objects The IDisposable interface exists primarily to allow you to explicitly release unmanaged resources (close files and connections and free Windows resources). You should implement this interface in the following scenarios: When you directly acquire unmanaged resources (you will most likely be using some sort of interop in this case, such as COM or P/invoke) When your object retains other disposable objects When there is important finalization for your object that should be done as soon as possible. All IDisposable objects should be disposed when you are done with them. That means that you will need to keep a reference to the object one way or another until you call Dispose. And just because you dispose an object doesn't mean that the garbage collector is done with it, so you should also release your reference to the object after you dispose it. To Handle The GC Or Not To? That is the question. Almost always, it is best to let the garbage collector do its own thing. (That is the answer.) The two reasons for this are, firstly, that the garbage collector is there so you don't have to worry about managing memory, and secondly, that it does it's job well. So when should you explicitly invoke GC.Collect and force a garbage collection? You should do this when you are incredibly familiar with the garbage collection system, have decided that this will improve garbage collection performance, and are willing to perform thorough tests to confirm that you are indeed making an improvement by stepping in and bossing the garbage collector around. If you are really interested in optimizing garbage collection here are some tips. When you are done with an object, set the reference to null to "disconnect" the object from your program and allow it to be collected (if the variable will go out of scope it isn't necessary to clear the reference, as long is it disappears one way or another). Don't cache objects unless it is very expensive to instantiate them. For smaller or simpler objects, it can often be best to use a structure instead of a class because the memory that they use is released immediately when the object goes out of scope. Just make sure that you understand how structures and classes behave differently. What Category (Managed/Unmanaged) Do Most Controls Fall Into? All Windows Forms controls use unmanaged resources because they wrap or are based on a Windows control. For the most part, all of your controls will be disposed automatically when the form is disposed (and the form is usually disposed when the user closes the form). The most common scenario where one might need to explicitly dispose of controls is when controls are dynamically created and destroyed. Other common classes that are disposable are FileStreams, DataBase objects, RegistryKeys, and web connections. How Do I Know If An Object Should Be Disposed? The easiest way to test this programatically is to see if an object implements IDisposable. [Color=Green]// C#[/Color] [Color=Blue]if[/Color](someObject [Color=Blue]is [/Color]IDisposable) someObject.Dispose(); [Color=Green]' VB[/Color] [Color=Blue]If TypeOf[/Color] SomeObject [Color=Blue]Is[/Color] IDisposable [Color=Blue]Then[/Color] SomeObject.Dispose() [/Code] Generally you won't find yourself doing this, though, because the code that created or acquired the disposable object will track it and dispose it when necessary. [b]How To Properly Write A Dispose Method[/b] First, the obvious. You should implement the IDisposable interface and create the Dispose method (sometimes it may be more appropriate to name this method a more descriptive name such as "Close" or "Release"). This method should release unmanaged resources and perform any necessary cleanup. Secondly, the not-so-obvious. The Dispose method should be programmed such that calling it more than one time should not cause an error. Also, unless there is a reason not to, the Dispose method should call the GC.SupressFinalize method (specifying itself) to inform the garbage collector that this object needs no further finalization. In fact, the finalizer almost always only serves the purpose of a fall back in case an object is not disposed. In your finalize method you should invoke the Dispose method. Many disposable objects use a slightly more complicated pattern. They implement IDisposable and have a Dispose (or Close) method, but they also have a private Dispose overload which accepts a boolean. The public Dispose method calls the private Dispose method and passes a true. The finalizer calls Dispose and passes a false. This boolean indicates whether the object is disposed explicitly (in code) or implicitly (by a finalizer). When the object is disposed explicitly extra cleanup can be performed, such as releasing references to other objects so that they may be garbaged collected sooner. This extra cleanup isn't necessary (especially when the object is disposed by the finalizer, since this often means that the program is closing anyways), but can improve garbage collection performance. This pattern should only be used when it represents a significant optimization. [b]Simple Tests To Determine If Your Objects Are Finalized And/Or Disposed.[/b] A good profiler would probably be helpful in this situation. Off the top of my head, another possibility would be to add debug code to track objects. For instance, a debug build of an application could use some static variables to count how many objects of a particular type are created, how many are disposed, and how many are finalized. You could go one step further and use a static dictionary object which stores stack traces to find out where undisposed objects are created. [b]Language Differences And IDisposable.[/b] The IDisposable interface is a .Net feature, not a language specific feature. Different languages have additional features, though, related to this interface. C# (all versions) and VB (version 8 and up) have "using blocks", where objects are disposed of when the scope of the using block ends or an exception is thrown. [code=csharp] using(FileStream someStream = new FileStream("C:\\textfile.txt", FileMode.Create)) { someStream.Write(new byte[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }, 0, 11); } // The stream will be closed when execution gets here. C++/CLI uses a modified destructor syntax to implicitly implement IDisposable. It is also worth noting that C# uses destructor syntax to implement finalizers, where as VB requires that users explicitly override the Finalize method. Any info that others wish to share is more than welcome.
      • 1
      • Like
  10. Sorry if we are pulling the thread a little off topic. I will see what, if anything, there is in the tutor's corner about the GC and disposable objects (and probably add a thread on the topic). Any further discussion on the topic where it does not pertain the the original post will hopefully go there or in random thoughts.
  11. Ever wish the picture box could scale images without using bilinear filtering (for example, when viewing/editing video game graphics)? In the past I had written controls from scratch that emulate the PictureBox but used my desired interpolation. Then I was hit with a stroke of common sense. I've extended the PictureBox class to enhance it with the ability to use various interpolation modes, including the video game creator's best friend, nearest neighbor. using System.Windows.Forms; using System.Drawing.Drawing2D; using System.ComponentModel; using System; namespace iLab { /// <summary> /// A PictureBox control extended to allow a variety of interpolations. /// </summary> class InterpolatedBox:pictureBox { #region Interpolation Property /// <summary>Backing Field</summary> private InterpolationMode interpolation = InterpolationMode.Default; /// <summary> /// The interpolation used to render the image. /// </summary> [DefaultValue(typeof(InterpolationMode), "Default"), Description("The interpolation used to render the image.")] public InterpolationMode Interpolation { get { return interpolation; } set { if(value == InterpolationMode.Invalid) throw new ArgumentException("\"Invalid\" is not a valid value."); // (Duh!) interpolation = value; Invalidate(); // Image should be redrawn when a different interpolation is selected } } #endregion /// <summary> /// Overridden to modify rendering behavior. /// </summary> /// <param name="pe">Painting event args.</param> protected override void OnPaint(PaintEventArgs pe) { // Before the PictureBox renders the image, we modify the // graphics object to change the interpolation. // Set the selected interpolation. pe.Graphics.InterpolationMode = interpolation; // Certain interpolation modes (such as nearest neighbor) need // to be offset by half a pixel to render correctly. pe.Graphics.PixelOffsetMode = PixelOffsetMode.Half; // Allow the PictureBox to draw. base.OnPaint(pe); } } } Since I'm such a swell guy, I translated it to VB too. Imports System.Drawing.Drawing2D Imports System.ComponentModel ''' <summary>A PictureBox control extended to allow a variety of interpolations.</summary> Public Class InterpolatedBox Inherits PictureBox ''' <summary>The backing field for the Interpolation property</summary> Dim _interpolation As InterpolationMode = InterpolationMode.Default ''' <summary> ''' The interpolation used to render the image. ''' </summary> <DefaultValue(GetType(InterpolationMode), "Default"), _ Description("The interpolation used to render the image.")> _ Public Property Interpolation() As InterpolationMode Get Return _interpolation End Get Set(ByVal value As InterpolationMode) If value = InterpolationMode.Invalid Then _ Throw New ArgumentException("""Invalid"" is not a valid value.") '(duh.) _interpolation = value Invalidate() 'Image should be redrawn when a different interpolation is selected End Set End Property ''' <summary> ''' Overridden to modify rendering behavior. ''' </summary> ''' <param name="pe">Painting event args.</param> Protected Overrides Sub OnPaint(ByVal pe As System.Windows.Forms.PaintEventArgs) ' Before the PictureBox renders the image, we modify the ' graphics object to change the interpolation. ' Set the selected interpolation. pe.Graphics.InterpolationMode = _interpolation ' Certain interpolation modes (such as nearest neighbor) need ' to be offset by half a pixel to render correctly. pe.Graphics.PixelOffsetMode = PixelOffsetMode.Half ' Allow the PictureBox to draw. MyBase.OnPaint(pe) End Sub End Class
  12. Well, call me crazy, but when I worked up enough energy to open VB and test my previous statement, I ran into results contrary to what you stated (i.e. in agreement with my original understanding). In a VB winforms app, with one form named Form1 containing one button named Button1, I used the following code: Public Class Form1 Dim theform As Form1 Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click If (theform Is Nothing) Then theform = New Form1() End If theform.Show() End Sub End Class When I click the button, close the new form, then click the button again (which will attempt to re-show the form) I get an ObjectDisposedException. Now, that an exception occurs is understandable. One might expect that Windows resources are freed when a window is closed, even if it is not disposed, but that the exception explicitly states that the object is disposed, well, I guess that's my point. Keep in mind that there is not necessarily any reason why certain properties of any IDisposable object can't be read after said object is disposed. When you create an IDisposable object, do you add a check in all properties to see if the object is disposed? In fact, when I modified the code to: Public Class Form1 Dim theform As Form1 Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click [i] If (Not theform Is Nothing) Then MessageBox.Show(theform.IsDisposed.ToString()) End If[/i] If (theform Is Nothing) Then theform = New Form1() End If theform.Show() End Sub End Class The output did indicate that the form had been disposed.
  13. Nerseus, maybe you should be using VB so you can take advantage of the RaiseEvent keyword. There is an advantage to being able to check if there are handlers attached (checking for null). For example, you don't need to bother creating your EventArgs object if there are no handlers (which is not really a huge deal, but just think about how many events are thrown in WinForms apps). You can't take advantage of this in VB. Of course, it would be nice if we didn't have to check. As far as the discussion on whether DotNet events are an implementation of the observer pattern, I think the discussion does have its merits. The question, really, is whether the DotNet event system is the idea expressed by the concept of the observer pattern. The observer pattern an OOP concept, and DotNet events are not 100% OO (as nice as delegates are, they aren't very OO). So it is hard to decide whether they are the same idea. Does it really, truly make a difference? Of course not. But I enjoy talking about it.
  14. I am nearly certain (unfortunately, I'm too lazy to check) that a form is disposed when the user closes the form, unless you intercept the form close, cancel it, and hide the form.
  15. Try opening reflector with reflector. I don't know what is inside, but I know it runs on the .Net framework, so it is possible that Reflector.exe is the API. As far as determining what classes another class depends on (without using third party libraries), all that should be involved is looping through all the members of a class and determining what types each field/property/return/parameter is.
  16. Quite frankly, I have a tendency to arrogantly make certain assumptions as I go along without verifying my statements (as I think of it, although leap frogging one's though, I suppose, would be another way of putting it if one were less arrogant than I), as I think we all do to some extent (but I am the king and the master, which is why I always win arguments... unless a moderator closes the thread... oops, didn't mean to type that... or that). For the sake of actual intelligent discussion, however, I will stick to the Observer Pattern as discussed by Wikipedia. Wikipedia does list the DotNet event system as an implementation of the observer pattern. Generally, the observer pattern is based on interfaces (since they allow a class to implement multiple observation scenarios), however base classes should also be acceptable. If we were to look at DotNet events as an observer pattern, the event handlers would (obviously) be considered the subscriber, where it could be said that any method that matches an event signature implies a subscriber interface (as they do indeed, provided that we regard delegates as a simplified form of the interface type). The publisher, on the other hand, is not based on any standard interface composed of pure code (pure VB or pure C#), but, rather, the publisher is implemented in part as language (C#/VB) code, in part as MSIL code created by the compiler, and in part by DotNet metadata. At run-time all we really have on the publisher end is the invocation of a function pointer. Although the spirit here is the same as the observer pattern, it is difficult to come to the conclusion here that we do have a representation of a publisher interface. It ultimately breaks down to the question, then, of whether the pattern must be based upon interfaces. I would say that it depends on your definition of the observer pattern (Is there a correct definition? If so, I would love to see it.) and how loosely you interpret it. Wikipedia does not list an interface or base-class implementation as a requisite for an implementation of the observer pattern. It states that publishers generally maintain a list of observers, who must register and unregister, and use a call-back mechanism. Based on this description, DotNet events certainly qualify as an observer pattern. We haven't wandered off topic, have we?
  17. This old thread might be relevant.
  18. You will need to have a program run in the background one way or another in order to do this. You could use a "lightweight" program that runs using either of the aforementioned techniques (the former is probably best since it would allow you to have a notify/system tray icon). This program could implement the scheduling interface and when a scheduled event occurs, it could run the program that will handle the scheduled event. Or you could incorporate it all into one application, although this would likely require more resources while it sits idle in the background. As far as how you go about timing the scheduled events, using a timer would be one option (probably the least desirable, but I suppose it is a viable option). Off the top of my head, I can't think of any other great suggestions. You might want to consider looking for something along the lines of the Application.Idle event (although that, specifically, is not what you are looking for). Some sort of WinAPI action might be due.
  19. It will take you some time to get used to the C# syntax, but once you get past all the curly braces and semi-colons, you will realize that it is basically the same thing as VB. A good place to get started would be C# to/from VB.Net Recipes. The biggest changes you will notice are that every statement in C# ends with a semicolon, comments use // instead of ', and that instead of using this type of syntax: [color=Blue]Construct[/color] [Color=Green]' Code [/Color][color=Blue]End Construct[/color] it uses this type of syntax: [color=Blue]Construct [/color]{ [Color=Green]// Code [/Color]} [/Code]
  20. A base class that could provide data to your lazily initialized objects. /// <summary> /// Defines a base class for a data source that will initialize objects. /// </summary> /// <typeparam name="T"></typeparam> public abstract class DataBase<T> where T:LazyBase { /// <summary> /// Override to initialize an object with data from this data source. /// </summary> /// <param name="dataObject">The object to initialize.</param> public abstract void Initialize(T dataObject); } A data container class that supports lazy intialization (just as an example). /// <summary> /// Define an object to hold data (in our case, an int). /// </summary> public class LazyIntDataContainer:LazyBase { /// <summary>The source of our data. It might be smarter to incorporate /// this into your base class.</summary> RandomDataSource data; public LazyIntDataContainer(RandomDataSource data) { this.data = data; } /// <summary> /// This is the action that will be performed when this object needs to be initialized. /// Here we use our "DataBase" object to intialize the object. We don't /// really need to do that, but it allows us to use different types of data /// sources to initialize the same kind of data container (provided that /// the data source inherits from the DataBase class). /// </summary> protected override void PerformLazyInitialize() { base.PerformLazyInitialize(); data.Initialize(this); } private int value; /// <summary> /// Gets/sets this data containers data. /// </summary> public int Value { get { // The object must be initialized before this property can be accessed. CheckInitialize(); return value; } set { // The object must be initialized before this property can be accessed. CheckInitialize(); this.value = value; } } } The data source for our lazy data container. Since this is for demonstrative purposed only, this class simply provides random data. /// <summary> /// Data source that provides random integers. /// </summary> public class RandomDataSource: DataBase<LazyIntDataContainer> { /// <summary>Random number generator.</summary> Random rand = new Random(); /// <summary> /// Initialize data containers. /// </summary> /// <param name="dataObject">Data container to initialize.</param> public override void Initialize(LazyIntDataContainer dataObject) { dataObject.Value = rand.Next(); } } The LazyIntDataContainer class does not benefit here from lazy initialization, but it demonstrates using the abstract classes I posted for lazy initialization and separation between the data and initialization.
  21. I think you may need to be more specific on certain points. Does the data all come from one source (or one kind of source)? Or is it all channeled through one class? There needs to be some way to make the connections between the container and the data source, whether it be a URL, a RegistryKey object, a file path, etc.. This connection could be stored in the data container, or it could, for example, be stored in a static dictionary where the data object is the key and the data source is the value (I personally would prefer the former). The object will need some way of invoking the initializer, which means that it will need to do something like (1)Invoke the object that accesses data so that that object may initialize the data container, which requires that the data container maintain a reference to the object that will initialize it, and possibly a string to identify the data source (URL/filename) or (2)be able to access the data and initialize itself. Also, the data container class would need to perform a check on every method and property access (or, at least, every member that should trigger lazy initialization). Most likely you will encapsulate this into a single method. Either way, it will have a performance penalty (most likely minor, though). Here is a very simple shell for a lazily initialized class, and a possible derivation. /// <summary> /// Defines a base class for lazy initialization /// </summary> abstract class LazyBase { public LazyBase() { } /// <summary>Tracks whether or not this object is initialized.</summary> bool initialized = false; /// <summary> /// Gets whether this object is initialized. /// </summary> public bool IsInitialized { get { return initialized; } } /// <summary> /// This method should be called at the beginning of any method or property /// that may invoke lazy initialization. /// </summary> protected void CheckInitialize() { if(!initialized) PerformLazyInitialize(); } /// <summary> /// This method should be overridden to implement initialization. The /// overriding implementation must call the base method. /// </summary> protected virtual void PerformLazyInitialize() { initialized = true; } }
  22. Are you alright? Seriously. The method I posted to you isn't... ssssllllooooowwww... at all. Not if you write code that is optimized for speed. It might not be blazing C++ pointer fast, but it is pretty fast and skips the unmanaged world of the API and pointer math. Realize that you are working in a managed environment. You are a big step away from the hardware. DMA isn't meant to be an option. But the method I posted is pretty close. The overhead isn't huge. If you are clever you will allocate a single buffer and recycle it. If you are clever you will write reusable code and it will be easy to implement the next time you need it. (In fact, I frequently use the approach that was in my tutorial, but I created drop-in classes that let me obtain image data buffers with only a few lines of code.) Do I live in la-la land? Is this some sort of dream world? Well, if you say so, I must agree. RAD with C-style syntax? JIT compilation that gives me near-native execution speed? An extremely comprehensive, thoroughly documented, very consistent and easy to use programming API? VB with OOP? Cross-language interoperability? And I downloaded the Express versions for free from Microsoft? Sounds like a dream come true. But here you are complaining because it doesn't provide for DMA?? You want the best of both worlds. You want C++ power and VB ease of use. Who is living in la-la land? Maybe the one being insulting and offensive to those who want to help? FYI, this is a board for getting help. Blogs are for venting.
×
×
  • Create New...