snarfblam
Leaders-
Posts
2156 -
Joined
-
Last visited
-
Days Won
2
Content Type
Profiles
Forums
Blogs
Events
Articles
Resources
Downloads
Gallery
Everything posted by snarfblam
-
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 { /// /// A PictureBox control extended to allow a variety of interpolations. /// class InterpolatedBox:pictureBox { #region Interpolation Property /// Backing Field private InterpolationMode interpolation = InterpolationMode.Default; /// /// The interpolation used to render the image. /// [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 /// /// Overridden to modify rendering behavior. /// /// Painting event args. 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 ''' A PictureBox control extended to allow a variety of interpolations. Public Class InterpolatedBox Inherits PictureBox ''' The backing field for the Interpolation property Dim _interpolation As InterpolationMode = InterpolationMode.Default ''' ''' The interpolation used to render the image. ''' 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 ''' ''' Overridden to modify rendering behavior. ''' ''' Painting event args. 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
-
Presumably this exception would only be thrown on array access, so let's start by identifying which lines the error might be thrown on. Public Class Form1 Dim numberOfFiles As Integer = 0 Dim ds As New DataSet Public TechVan(,) As String = {{"", ""}} Dim NumOfVan As Integer = 0 Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load Dim x As Integer = 0 Dim y As Integer = 0 Dim num_rows As Long = 0 Dim num_cols As Long = 0 Dim file_name As String = "TechVan.csv" 'load tech name and van # into an array If File.Exists(file_name) Then Dim tmpstream As StreamReader = File.OpenText(file_name) Dim strlines() As String Dim strline() As String 'Load content of file to strLines array strlines = tmpstream.ReadToEnd().Split(CChar(Environment.NewLine)) 'Redimension the array. num_rows = UBound(strlines) NumOfVan = CInt(num_rows) [color="Red"]strline = strlines(0).Split(CChar(",")) '1[/color] num_cols = UBound(strline) ReDim TechVan(CInt(num_rows), CInt(num_cols)) 'Copy the data into the array. For x = 0 To CInt(num_rows) [color="Red"]strline = strlines(x).Split(CChar(",")) '2[/color] For y = 0 To CInt(num_cols) [color="Red"]TechVan(x, y) = strline(y).Trim() ' 3[/color] Next Next End If End Sub Number 1 shouldn't throw an exception, because String.Split should return an array with at least one element. Number 2 shouldn't throw an exception because your code contains a bounds check. That leaves number 3, in which case you're assuming that each line of the file contains at least as many entries as the first line. Assume the first line has two entries. You re-dim TechVan to have two columns, and y will loop from 0 to 1. Now, if you have a line with only one entry on it, you will attempt to access strline(1), but the array will only contain a single element at strline(0), which would produce an exception. Hopefully, if you add a check to make sure strline contains the correct number of entries (and log or display an error if this is not the case), it will eliminate the unhandled exception. For what it's worth, WinForms providing the user the option to keep running the program after an unhandled exception occurs is a very bad idea. When you click "continue", it means that a function ran half-way through before blowing up, and the program could be in an inconsistent state, creating stability issues, and possibly even security issues.
-
I'm desperate. Isometric Coordinates Translation
snarfblam replied to EFileTahi-A's topic in Graphics and Multimedia
It took me a minute of scratching my head before I figured this out. Here's what I came up with. First thing I did was get the pixel coordinates relative to the origin of the isometric grid. I'm using the image you posted as an example. The origin of the grid is at pixel coordinate (319, 0). public partial class Form1 : Form { const int origX = 319; const int origy = 0; public Form1() { InitializeComponent(); } private void pictureBox1_MouseMove(object sender, MouseEventArgs e) { int relativeToOriginX = e.X - origX; int relativeToOriginY = e.Y - origy; } } I eventually reasoned that, placing the mouse cursor over the grid, for each pixel you move down, you're moving 1/32 of a tile in both the x- and y-axes of the isometric grid. (If you move the mouse down 32 pixels, you've gone from the corner of tile (0,0) to the corner of tile (1,1).) Up is -1/32 of a tile in each axis. Moving from left to right, it takes 64 pixels to go from the "bottom-left" corner of a tile to the "top-right", thus one pixel right is +1/64 in the x-axis and -1/64 in the y-axis. Likewise, left is -1/64 and + 1/64. So, we can add some more constants to represent those values: const int origX = 319; const int origy = 0; [color="Blue"] const double isoYperPixelY = (1.0 / 32); const double isoXperPixelY = (1.0 / 32); const double isoYperPixelX = -(1.0 / 64); const double isoXperPixelX = (1.0 / 64);[/color] Now, to get grid coordinates, you can take the pixel X (relative to the origin of the grid), and multiply it by isoXperPixelX, then multiply the pixel Y by isoXperPixelY, add the two together, and viola. You've got your grid X-coordinate. Use the same process to get your grid Y-coordinate. public partial class Form1 : Form { const int origX = 319; const int origy = 0; const double isoYperPixelY = (1.0 / 32); const double isoXperPixelY = (1.0 / 32); const double isoYperPixelX = -(1.0 / 64); const double isoXperPixelX = (1.0 / 64); public Form1() { InitializeComponent(); } private void pictureBox1_MouseMove(object sender, MouseEventArgs e) { int relativeToOriginX = e.X - origX; int relativeToOriginY = e.Y - origy; [color="Blue"] double isoX = relativeToOriginX * isoXperPixelX + relativeToOriginY * isoXperPixelY; double isoY = relativeToOriginX * isoYperPixelX + relativeToOriginY * isoYperPixelY; Text = ((int)isoX).ToString() + ", " + ((int)isoY).ToString();[/color] } } Place your grid image in a picturebox, move the mouse around, and watch the form's caption. Fun Fact: I realized after the fact that this is effectively matrix multiplication. -
I'm not sure exactly how you want it represented in the property grid, but a tutorial on customizing the property grid (like this) should have all the info you need. It's not simple, but it's doable.
-
You can have a property appear on the property grid that is not actually part of the class by using a custom TypeDescriptor (check out some tutorials on customizing the property grid), but what is the actual problem you're trying to solve here? There's likely a better solution.
-
This is an issue of greedy versus lazy quantifiers. Basically, a greedy quantifier, such as *, will try to match as much as possible. Your regex describes a string with brackets on either end, which does match the string "[abc] Bbbb [7]". You want the lazy version, which will find the smallest match possible. Check out http://www.regular-expressions.info/reference.html
-
Non-VB-specific methods are generally recommended anyways since they're generally the same across all .NET languages. To get the left part of a string: ' Get left two letters Dim start As Integer = 0 Dim length As Integer = 2 Dim Beginning As String = ("Some Text").Substring(start, length) As for the "Like" operator, I've never used it but it seems to me that regular expressions would be a good substitute, if you're willing to learn it (not difficult). Dim regexMatch As Boolean = Regex.IsMatch("Some Text", "^S.*") The dot matches any character, and the asterisk modifies the dot to match zero or more any-characters (i.e. ".*" in regex behaves just like "*" in your code). The ^ matches the start of the string. I also stumbled onto this article taking a different approach.
-
I googled System.Web.Script.Serialization and it listed all the classes as being part of System.Web.Extensions.dll.
-
Does the font still scale if you set the AutoScaleMode property to None? I don't mess with the font size in Windows because it breaks the UI of some programs. They don't deal with scaling properly. (This even includes software I've written. :( ) Ideally, though, I would prefer to scale the fonts up. I do scale the fonts up in my browser, though. In earlier versions of FireFox, depending on how a font's size was set, sometimes the text wouldn't scale. It definitely bothered me.
-
Simply put, your function is calling itself (possibly indirectly) over and over again. Open up the call stack window and look at which functions are calling which to figure out why and how your code is calling itself.
-
How do you programatically open a file in c# to append?
snarfblam replied to Xarzu's topic in Visual C# .NET
One (or more) of the FileStream constructors accepts a FileMode argument, which allows you to specify FileMode.Append. Once you've created the FileStream, you can create a StreamWriter with the FileStream. Depending on what you're doing, you might also be able to use one of the handy convenience methods of the System.IO.File class. void AppendToLog(string text) { File.AppendAllText(Program.LogPath, text); } -
This function is not fully working
snarfblam replied to EFileTahi-A's topic in Graphics and Multimedia
It looks like there might be a couple of problems with your pointer math. I don't play with pointers every day, so I can't promise I'll get it 100% either, but here's what I'm noticing: First, I'm a little confused by this: int offset = dataA.Stride - width; It looks like the value of "offset" is meant to make up the difference between the length of a row's data and the row's stride (i.e. offset specifies the row's padding). That seems like a confusing way to deal with stride. What I would do is have two pointer variables per image. In addition to ptrA and ptrB, I would have what I'll call rowStartA and rowStartB. You would initalize rowStartA to dataA.Scan0, and rowStartB likewise. Then, after you process each row, add dataA.Stride to rowStartA to get the starting address of the next row. Before you loop over the pixels in each row, you would initialize prtA to the current value of rowStartA, and then increment ptrA after each byte is processed. So, something like this... rowStartA = dataA.Scan0 rowStartB = dataB.Scan0 loop over Y ptrA = rowStartA prtB = rowStartB loop over X process byte ptrA ++ ptrB ++ end loop rowStartA += dataA.Stride rowStartB += dataB.Stride end loop Secondly, your pointers walk through bytes. If I understand correctly, you are processing one byte per pixel. With a 24-bit format, it would be three bytes per pixel. With 32-bit, it would be four bytes per pixel, but you would want to skip over the alpha byte. This is what I imagine code would typically look like for an ARGB image, not taking alpha blending into account (hopefully I've got the byte order correct): for (int x = 0; x < width; x++) { // Blue int result = (ptrB[0] * ptrA[0]) / 255; ptrA[0] = (byte)result > (byte)255 ? (byte)255 : (byte)result; prtA++; ptrB++; // Green int result = (ptrB[0] * ptrA[0]) / 255; ptrA[0] = (byte)result > (byte)255 ? (byte)255 : (byte)result; prtA++; ptrB++; // Red int result = (ptrB[0] * ptrA[0]) / 255; ptrA[0] = (byte)result > (byte)255 ? (byte)255 : (byte)result; prtA++; ptrB++; // Alpha (ignored) (or you can just copy the alpha channel from image A to B) prtA++; ptrB++; } For a 24-bit format, just get rid of the last pair of increments. Hopefully that helps. -
Well, it looks like I might have been wrong. There seems to be a metro version of VS after all (http://dotnet.dzone.com/articles/visual-studio-11-beta). The real problem is that you apparently need to be a licensed developer (whatever that entails) to distribute apps, and need to distribute apps via the app store (http://techcrunch.com/2012/09/29/windows-store-metro-mode-no-sideloading-psa). I'm not sure what that means for programmers like me who only make free software. I'd be curious to see what you're cooking up, but lately, I've actually been trying to get back on top of an NES homebrew game I've been working on. I just need to muster up the patience and determination needed to finish a game in written completely in assembly.
-
Windows for ARM devices lacks the traditional desktop. At's all Metro whatever it's called now. So, as I understand it, while you can develop for ARM devices, you won't be able to develop on ARM devices.
-
Trying to Understand the Finer Details of Custom Events
snarfblam replied to Recondaddy's topic in General
Nope! Maybe you should show your code that declares, raises, and subscribes to events. Any object can subscribe to events on any other object it can get its hands on. -
I think that ideally you would want to figure out why the thread is crashing (unless, of course, you already know what the problem is). Also, what version of .NET are you using? I believe that 1.x deals with unhandled exceptions differently than other versions (failing silently versus taking the whole ship down). If you're not using 1.x and threads are silently disappearing, I'm a bit confused.
-
I understand where you're coming from, but the approach you're after just isn't possible. A composite control (user control holding everything) would be the typical approach. If that's going to cause problems like mucking up the designer, there's another solution that comes to mind. You can create a separate companion control that inherits UserControl and contains the additional controls. Inherit DataGrid and extend it to either: (1)Cooperate with the companion control. The extended DataGrid is responsible for adding/removing/managing controls within the companion. Or, (2) Expose properties that the companion can examine and manage the child controls itself. The programmer would be responsible for placing an ExtendedDataGrid and a DataGridCompanion, and wiring them together (i.e. setting dataGridCompanion1.OwnerGrid = extendedDataGrid1).
-
Maybe you should explain what the end goal is here. If you inherit a control, the base class still decides how it wants to use the space within the control (in most cases, it will consume it's entire rectangle), so you do can't things the way you would like. There is probably another way to achieve whatever you're trying to do.
-
But... I linked to a working code. Why don't you post what you've tried so far, and explain the trouble you're having. If it helps, here is another very similar but more thorough article.
-
GetPixel (either version) is notoriously slow. What you really want to do is access the raw image data. You can use a Graphics object to copy the desktop to a bitmap, and there are a bunch of tutorials around on how to access raw bitmap data in .NET.
-
Step 1 is to use a debugger and figure out on which line the error is occurring. I'm going to guess it's this line: Dim tempqty As Integer = Integer.Parse(lstQuantity.SelectedItem.Items.text) Assuming the ListBox contains only strings, lstQuantity.SelectedItem is a string, which does not have a public member named Items. This problem could probably have been avoided if you enabled Option Strict. I'm not going to go on a long rant about why it's bad to not use Option Strict, because there are already a million billion of those on the internet. All I'll say on the subject is that Option Strict is there for the sole reason of preventing errors.
-
I'm just going to add one thing. If you're writing a program with some kind of "interpreter" or using some other scenario where the user can frequently enter and run code, understand that each time you compile code, you're compiling and loading a whole new assembly, which can't be unloaded until the application exits. Things could pile up in memory pretty quickly.
-
Are you having more trouble compiling code at runtime, or having that code access your form? A search for "vb compile at runtime" gave this result. The code in the article contains errors, but it shows you everything you need to know to compile code at runtime. Note this important piece of code. For Each ASM In AppDomain.CurrentDomain.GetAssemblies() PM.ReferencedAssemblies.Add(ASM.Location) Next This adds a reference to all loaded assemblies, including your assembly containing Form1. Now that we have a reference to the assembly that defines Form1, all we need in order to get the code to interact with a Form1 is a reference to an instance of Form1. There are a few ways to do this. The code could just look through Application.OpenForms for an instance. Form1 could store an instance of itself in a public shared property that the code could read. The method I chose was to have the code being compiled to accept a Form1 in the constructor. Here is the code from the article, updated to work. You'll need a mulitline textbox named "TextBox1" and a button named "Button1." Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click Dim errors As New StringBuilder Try If TextBox1.Text.Trim <> "" Then Dim VBP As New VBCodeProvider Dim CVB As System.CodeDom.Compiler.ICodeCompiler CVB = VBP.CreateCompiler Dim PM As New System.CodeDom.Compiler.CompilerParameters PM.GenerateInMemory = True ' PM.GenerateExecutable = True PM.OutputAssembly = "Generated.dll" PM.MainClass = "ClassMain" PM.IncludeDebugInformation = True Dim ASM As System.Reflection.Assembly For Each ASM In AppDomain.CurrentDomain.GetAssemblies() PM.ReferencedAssemblies.Add(ASM.Location) Next 'Get compilation results Dim Results As System.CodeDom.Compiler.CompilerResults Results = CVB.CompileAssemblyFromSource(PM, TextBox1.Text) 'Show possible compilation errors Dim Err As System.CodeDom.Compiler.CompilerError For Each Err In Results.Errors errors.AppendLine("Error N. " & Err.ErrorNumber & _ " Message: " & Err.ErrorText & " Line " & Err.Line) Next 'Use the compiled assembly Dim RunObj As New Object [color="Red"]Dim vArgs As Object() = {Me}[/color] RunObj = Results.CompiledAssembly.[color="Orange"]CreateInstance[/color]( _ "[color="Blue"]Generated.ClassMain[/color]", True, _ Reflection.BindingFlags.CreateInstance, Nothing, _ [color="Red"]vArgs[/color], Nothing, Nothing) If Not RunObj Is Nothing Then Dim method As MethodInfo = RunObj.GetType().GetMethod("[color="Magenta"]DoIt[/color]") method.Invoke(RunObj, _ BindingFlags.Static Or BindingFlags.Instance Or BindingFlags.Public Or BindingFlags.NonPublic, _ Nothing, Nothing, Nothing) Else MessageBox.Show("Compile Error:" & vbCrLf & vbCrLf & errors.ToString()) End If Else MessageBox.Show("Write VB.Net code to compile") End If Catch err As Exception MessageBox.Show(err.Message & " " & err.StackTrace) End Try End Sub As you can see, the code looks for a class named "ClassMain" in the namespace "Generated", which has a method, "DoIt", and a constructor that accepts a Form1. Here is the code that I used that meets those criteria. Imports System.Windows.Forms Imports Microsoft.VisualBasic namespace [color="Blue"]Generated[/color] public class [color="Blue"]ClassMain[/color] public sub [color="Orange"]New[/color]([color="Red"]frm as WindowsApplication1.Form1[/color]) frm.Text = "EXPERIMENT" end sub public shared sub [color="Magenta"]DoIt[/color]() messagebox.show("It works!") end sub end class end namespace If you enter this code and click the button, the form's caption will change to "EXPERIMENT" and a message box will display "It works!".
-
The question doesn't really make sense. A program can place its registry keys just about anywhere it wants to, and there are many keys that might or might not be said to belong to a program (file associations, startup tasks, etc.). It will probably be easier to give practical suggestions if you explain what you want your program to do.
-
Does the form work properly if you launch it from the main thread? WinForms is not thread-safe, and all your UI code should be running on the same thread.