473,491 Members | 2,524 Online
Bytes | Software Development & Data Engineering Community
Create Post

Home Posts Topics Members FAQ

New To XNA / Programically Drawing A Texture2D

Tyler Wiebe
66 New Member
Okay, I have a few questions about auto drawing a Texture2D, to be used in an 2D Windows Game I'm making for the fun of it.

But first, a few things,

1: The code is in my own custom .dll file that I'm making for this.

2: I've taught myself everything I know about C#, so any comment about my coding style isn't important to me, but is appreciated anyway.

3: And finally, a lot of code:
Expand|Select|Wrap|Line Numbers
  1.     public class ProgressBar
  2.     {
  3.         #region Overrides
  4.  
  5.         [System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never)]
  6.         public override bool Equals(object obj) { return base.Equals(obj); }
  7.         [System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never)]
  8.         public override int GetHashCode() { return base.GetHashCode(); }
  9.         [System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never)]
  10.         public override string ToString() { return base.ToString(); }
  11.  
  12.         #endregion
  13.  
  14.         #region Texture Graphics Device & SpriteBatch
  15.  
  16.         private Microsoft.Xna.Framework.Graphics.GraphicsDevice PGraphicsDevice;
  17.         public Microsoft.Xna.Framework.Graphics.GraphicsDevice GraphicsDevice
  18.         {
  19.             get { return this.PGraphicsDevice; }
  20.             set { this.PGraphicsDevice = value; }
  21.         }
  22.  
  23.         private Microsoft.Xna.Framework.Graphics.SpriteBatch PSpriteBatch;
  24.         public Microsoft.Xna.Framework.Graphics.SpriteBatch SpriteBatch
  25.         {
  26.             get { return this.PSpriteBatch; }
  27.             set { this.PSpriteBatch = value; }
  28.         }
  29.  
  30.         #endregion
  31.  
  32.         public ProgressBar(Microsoft.Xna.Framework.Graphics.GraphicsDevice GraphicsDevice, Microsoft.Xna.Framework.Graphics.SpriteBatch SpriteBatch)
  33.         {
  34.             this.PGraphicsDevice = GraphicsDevice;
  35.             this.PSpriteBatch = SpriteBatch;
  36.  
  37.             this.PBackColor = new Microsoft.Xna.Framework.Color(210, 210, 210, 255);
  38.             this.HighlightColor = new Microsoft.Xna.Framework.Color(255, 255, 255, 170);
  39.             this.ForeColor = new Microsoft.Xna.Framework.Color(0, 255, 0, 255);
  40.         }
  41.  
  42.         #region Texture Drawing
  43.  
  44.         /// <summary>
  45.         /// Draws the texture at the specified location.
  46.         /// </summary>
  47.         public void Draw()
  48.         {
  49.             SpriteBatch.Begin();
  50.             SpriteBatch.Draw(this.GetTexture, this.Location, Microsoft.Xna.Framework.Color.White);
  51.             SpriteBatch.End();
  52.         }
  53.  
  54.         private Microsoft.Xna.Framework.Graphics.Texture2D GetTexture
  55.         {
  56.             get
  57.             {
  58.                 System.Drawing.Bitmap Texture2DBitmap = new System.Drawing.Bitmap(this.Width, this.Height);
  59.                 int BufferSize = Texture2DBitmap.Height * Texture2DBitmap.Width * 4;
  60.  
  61.                 System.Drawing.Graphics GraphicsImage = System.Drawing.Graphics.FromImage(Texture2DBitmap);
  62.  
  63.                 GraphicsImage.FillPath(new System.Drawing.SolidBrush(System.Drawing.Color.FromArgb(this.BackColor.A, this.BackColor.R, this.BackColor.G, this.BackColor.B)), this.BackgroundPath);
  64.                 GraphicsImage.FillPath(new System.Drawing.SolidBrush(System.Drawing.Color.FromArgb(this.ForeColor.A, this.ForeColor.R, this.ForeColor.G, this.ForeColor.B)), this.PercentagePath);
  65.                 if (this.Highlight) GraphicsImage.FillPath(new System.Drawing.SolidBrush(System.Drawing.Color.FromArgb(this.HighlightColor.A, this.HighlightColor.R, this.HighlightColor.G, this.HighlightColor.B)), this.HighlightPath);
  66.                 if (this.Border) GraphicsImage.DrawPath(new System.Drawing.Pen(System.Drawing.Color.FromArgb(this.BorderColor.A,this.BorderColor.R,this.BorderColor.G,this.BorderColor.B), 1), this.BackgroundPath);
  67.  
  68.                 GraphicsImage.Dispose();
  69.  
  70.                 System.IO.MemoryStream MemoryStream = new System.IO.MemoryStream(BufferSize);
  71.                 Texture2DBitmap.Save(MemoryStream, System.Drawing.Imaging.ImageFormat.Png);
  72.  
  73.                 return Microsoft.Xna.Framework.Graphics.Texture2D.FromStream(GraphicsDevice, MemoryStream);
  74.             }
  75.         }
  76.  
  77.         private System.Drawing.Drawing2D.GraphicsPath BackgroundPath
  78.         {
  79.             get
  80.             {
  81.                 System.Drawing.Drawing2D.GraphicsPath Path = new System.Drawing.Drawing2D.GraphicsPath();
  82.                 if (this.Style == Styles.Sqaured)
  83.                 {
  84.                     if (this.Border)
  85.                     {
  86.                         Path.AddLine(0, 0, this.WidthM1, 0);
  87.                         Path.AddLine(this.WidthM1, 0, this.WidthM1, this.HeightM1);
  88.                         Path.AddLine(this.WidthM1, this.HeightM1, 0, this.HeightM1);
  89.                         Path.AddLine(0, this.HeightM1, 0, 0);
  90.                     }
  91.                     else
  92.                     {
  93.                         Path.AddLine(0, 0, this.Width, 0);
  94.                         Path.AddLine(this.Width, 0, this.Width, this.Height);
  95.                         Path.AddLine(this.Width, this.Height, 0, this.Height);
  96.                         Path.AddLine(0, this.Height, 0, 0);
  97.                     }
  98.                 }
  99.                 else if (this.Style == Styles.Rounded)
  100.                 {
  101.                     if (this.Border)
  102.                     {
  103.                         Path.AddArc(0, 0, this.HeightM1, this.HeightM1, 90, 180);
  104.                         Path.AddLine(this.HeightD2, 0, this.WidthM1 - this.HeightD2, 0);
  105.                         Path.AddArc(this.WidthM1 - this.HeightM1, 0, this.HeightM1, this.HeightM1, -90, 180);
  106.                         Path.AddLine(this.WidthM1 - this.HeightD2, this.HeightM1, this.HeightD2, this.HeightM1);
  107.                     }
  108.                     else
  109.                     {
  110.                         Path.AddArc(-1, 0, this.Height, this.Height, 90, 180);
  111.                         Path.AddLine(this.HeightD2, 0, this.Width - this.HeightD2, 0);
  112.                         Path.AddArc(this.Width - this.Height, 0, this.Height, this.Height, -90, 180);
  113.                         Path.AddLine(this.Width - this.HeightD2, this.Height, this.HeightD2, this.Height);
  114.                     }
  115.                 }
  116.                 return Path;
  117.             }
  118.         }
  119.         private System.Drawing.Drawing2D.GraphicsPath PercentagePath
  120.         {
  121.             get
  122.             {
  123.                 System.Drawing.Drawing2D.GraphicsPath Path = new System.Drawing.Drawing2D.GraphicsPath();
  124.  
  125.                 if (Style == Styles.Sqaured)
  126.                 {
  127.                     Path.AddLine(0, 0, this.Width * this.PercentageD100, 0);
  128.                     Path.AddLine(this.Width * this.PercentageD100, 0, this.Width * this.PercentageD100, this.Height);
  129.                     Path.AddLine(this.Width * this.PercentageD100, this.Height, 0, this.Height);
  130.                     Path.AddLine(0, this.Height, 0, 0);
  131.                 }
  132.                 else if (Style == Styles.Rounded)
  133.                 {
  134.                     Path.AddLine(0, 0, this.Width * this.PercentageD100, 0);
  135.                     Path.AddLine(this.Width * this.PercentageD100, 0, this.Width * this.PercentageD100, this.Height);
  136.                     Path.AddLine(this.Width * this.PercentageD100, this.Height, 0, this.Height);
  137.                     Path.AddLine(0, this.Height, 0, 0);
  138.                 }
  139.  
  140.                 return Path;
  141.             }
  142.         }
  143.         private System.Drawing.Drawing2D.GraphicsPath HighlightPath
  144.         {
  145.             get
  146.             {
  147.                 System.Drawing.Drawing2D.GraphicsPath Path = new System.Drawing.Drawing2D.GraphicsPath();
  148.  
  149.                 if (this.Style == Styles.Sqaured)
  150.                 {
  151.                     Path.AddLine(0, 0, this.Width, 0);
  152.                     Path.AddLine(this.Width, 0, this.Width, this.HeightD2);
  153.                     Path.AddLine(this.Width, this.HeightD2, 0, this.HeightD2);
  154.                     Path.AddLine(0, this.HeightD2, 0, 0);
  155.                 }
  156.                 else if (this.Style == Styles.Rounded)
  157.                 {
  158.                     Path.AddArc(-1, 0, this.Height, this.Height, 180, 90);
  159.                     Path.AddLine(this.HeightD2, 0, this.Width - this.HeightD2, 0);
  160.                     Path.AddArc(this.Width - this.Height, 0, this.Height, this.Height, -90, 90);
  161.                     Path.AddLine(this.Width, this.HeightD2, 0, this.HeightD2);
  162.                 }
  163.  
  164.                 return Path;
  165.             }
  166.         }
  167.  
  168.         #endregion
  169.  
  170.         #region Texture Location
  171.  
  172.         private Microsoft.Xna.Framework.Vector2 PLocation;
  173.         /// <summary>
  174.         /// Gets or sets the location of the texture.
  175.         /// </summary>
  176.         public Microsoft.Xna.Framework.Vector2 Location
  177.         {
  178.             get { return this.PLocation; }
  179.             set { this.PLocation = value; }
  180.         }
  181.  
  182.         /// <summary>
  183.         /// Gets or sets the center point of the texture.
  184.         /// </summary>
  185.         public Microsoft.Xna.Framework.Vector2 Center
  186.         {
  187.             get { return new Microsoft.Xna.Framework.Vector2(this.PLocation.X + (this.Width / 2), this.PLocation.Y + (this.Height / 2)); }
  188.             set { this.Location = new Microsoft.Xna.Framework.Vector2(value.X - (this.Width / 2), value.Y - (this.Height / 2)); }
  189.         }
  190.  
  191.         #endregion
  192.  
  193.         #region Texture Size
  194.  
  195.         private Size PSize;
  196.         /// <summary>
  197.         /// Gets or sets the size of the texture.
  198.         /// </summary>
  199.         public Size Size
  200.         {
  201.             get
  202.             {
  203.                 if (this.PSize != null && this.PSize.Width > 0 && this.PSize.Height > 0) return this.PSize;
  204.                 else return new Size(200, 20);
  205.             }
  206.             set
  207.             {
  208.                 if (value.Width > 0 && value.Height > 0) this.PSize = value;
  209.             }
  210.         }
  211.  
  212.         /// <summary>
  213.         /// Gets or sets the width of the texture.
  214.         /// </summary>
  215.         public int Width
  216.         {
  217.             get { return this.Size.Width; }
  218.             set { this.PSize.Width = value; }
  219.         }
  220.         private int WidthM1 { get { return this.Width - 1; } }
  221.  
  222.         /// <summary>
  223.         /// Gets or sets the height of the texture.
  224.         /// </summary>
  225.         public int Height
  226.         {
  227.             get { return this.Size.Height; }
  228.             set { this.PSize.Height = value; }
  229.         }
  230.         private int HeightM1 { get { return this.Height - 1; } }
  231.         private int HeightD2 { get { return this.Height / 2; } }
  232.  
  233.         #endregion
  234.  
  235.         #region Texture Styles
  236.  
  237.         /// <summary>
  238.         /// A list of different styles that the texture can look like.
  239.         /// </summary>
  240.         public enum Styles : int
  241.         {
  242.             /// <summary>
  243.             /// The texture will be displayed as a square the exact size specified.
  244.             /// </summary>
  245.             Sqaured = 0,
  246.  
  247.             /// <summary>
  248.             /// The texture will be displayed as a square with rounded ends.
  249.             /// </summary>
  250.             Rounded = 1,
  251.         }
  252.  
  253.         private Styles PStyle;
  254.         /// <summary>
  255.         /// Gets or sets the style of the texture.
  256.         /// </summary>
  257.         public Styles Style
  258.         {
  259.             get { return this.PStyle; }
  260.             set { this.PStyle = value; }
  261.         }
  262.  
  263.         #endregion
  264.  
  265.         #region Texture Colors
  266.  
  267.         private Microsoft.Xna.Framework.Color PBackColor;
  268.         /// <summary>
  269.         /// Gets or sets the back color of the texture.
  270.         /// </summary>
  271.         public Microsoft.Xna.Framework.Color BackColor
  272.         {
  273.             get { return this.PBackColor; }
  274.             set { this.PBackColor = value; }
  275.         }
  276.  
  277.         private Microsoft.Xna.Framework.Color PForeColor;
  278.         /// <summary>
  279.         /// Gets or sets the fore color of the texture.
  280.         /// </summary>
  281.         public Microsoft.Xna.Framework.Color ForeColor
  282.         {
  283.             get { return this.PForeColor; }
  284.             set { this.PForeColor = value; }
  285.         }
  286.  
  287.         private bool PHighlight;
  288.         /// <summary>
  289.         /// Gets or sets if a highlight should be displayed on the top half of the texture.
  290.         /// </summary>
  291.         public bool Highlight
  292.         {
  293.             get { return this.PHighlight; }
  294.             set { this.PHighlight = value; }
  295.         }
  296.  
  297.         private Microsoft.Xna.Framework.Color PHighlightColor;
  298.         /// <summary>
  299.         /// Gets or sets the highlight color of the texture
  300.         /// </summary>
  301.         public Microsoft.Xna.Framework.Color HighlightColor
  302.         {
  303.             get { return this.PHighlightColor; }
  304.             set { this.PHighlightColor = value; }
  305.         }
  306.  
  307.         private bool PBorder;
  308.         /// <summary>
  309.         /// Gets or sets if a border should be displayed around the texture.
  310.         /// </summary>
  311.         public bool Border
  312.         {
  313.             get { return this.PBorder; }
  314.             set
  315.             {
  316.                 this.PBorder = value;
  317.                 if (this.Border)
  318.                 {
  319.                     if (this.Size.Width < 3) this.PSize.Width = 3;
  320.                     if (this.Size.Height < 3) this.PSize.Height = 3;
  321.                 }
  322.             }
  323.         }
  324.  
  325.         private Microsoft.Xna.Framework.Color PBorderColor;
  326.         /// <summary>
  327.         /// Gets or sets the border color of the texture
  328.         /// </summary>
  329.         public Microsoft.Xna.Framework.Color BorderColor
  330.         {
  331.             get { return this.PBorderColor; }
  332.             set { this.PBorderColor = value; }
  333.         }
  334.  
  335.         #endregion
  336.  
  337.         #region Texture Percentage
  338.  
  339.         private float PPercentageD100;
  340.         private float PercentageD100 { get { return this.PPercentageD100; } }
  341.         /// <summary>
  342.         /// Gets or sets the percentage value of the texture.
  343.         /// </summary>
  344.         public float Percentage
  345.         {
  346.             get { return this.PPercentageD100 * 100; }
  347.             set
  348.             {
  349.                 if (value >= 0 && value <= 100) this.PPercentageD100 = value / 100;
  350.                 else if (value < 0) this.PPercentageD100 = 0;
  351.                 else if (value > 100) this.PPercentageD100 = 1;
  352.             }
  353.         }
  354.  
  355.         #endregion
  356.     }
  357.  

The following is a custom class that was used in the previous code:
Expand|Select|Wrap|Line Numbers
  1.     public class Size
  2.     {
  3.         #region Overrides
  4.  
  5.         [System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never)]
  6.         public override bool Equals(object obj) { return base.Equals(obj); }
  7.         [System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never)]
  8.         public override int GetHashCode() { return base.GetHashCode(); }
  9.         [System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never)]
  10.         public override string ToString() { return base.ToString(); }
  11.  
  12.         #endregion
  13.  
  14.         private int PWidth;
  15.         public int Width
  16.         { 
  17.             get { return this.PWidth; }
  18.             set { this.PWidth = value; }
  19.         }
  20.  
  21.         private int PHeight;
  22.         public int Height
  23.         {
  24.             get { return this.PHeight; }
  25.             set { this.PHeight = value; }
  26.         }
  27.  
  28.         public Size(int Width, int Height)
  29.         {
  30.             this.Width = Width;
  31.             this.Height = Height;
  32.         }
  33.     }
  34.  

HOW TO USE THE ABOVE CODE:
Expand|Select|Wrap|Line Numbers
  1.     public class Game1 : Microsoft.Xna.Framework.Game
  2.     {
  3.         private Microsoft.Xna.Framework.GraphicsDeviceManager GraphicsDeviceManager;
  4.         private Microsoft.Xna.Framework.Graphics.SpriteBatch SpriteBatch;
  5.  
  6.         private ProgressBar ProgressBar1;
  7.  
  8.         public Game1()
  9.         {
  10.             this.GraphicsDeviceManager = new Microsoft.Xna.Framework.GraphicsDeviceManager(this);
  11.             Content.RootDirectory = "Content";
  12.         }
  13.  
  14.         protected override void Initialize()
  15.         {
  16.             base.Initialize();
  17.             this.SpriteBatch = new Microsoft.Xna.Framework.Graphics.SpriteBatch(this.GraphicsDevice);
  18.  
  19.             this.ProgressBar1 = new ProgressBar(this.GraphicsDevice, SpriteBatch);
  20.             this.ProgressBar1.Size = new Size(30, 30);
  21.             //this.ProgressBar1.Location = new Microsoft.Xna.Framework.Vector2(20, 10);
  22.             this.ProgressBar1.Center = new Microsoft.Xna.Framework.Vector2(275, 15);
  23.             this.ProgressBar1.Style = ProgressBar.Styles.Rounded;
  24.             this.ProgressBar1.BackColor = new Microsoft.Xna.Framework.Color(210, 210, 210, 255);
  25.             this.ProgressBar1.ForeColor = new Microsoft.Xna.Framework.Color(0, 255, 0, 255);
  26.  
  27.             this.ProgressBar1.Highlight = true;
  28.             this.ProgressBar1.HighlightColor = new Microsoft.Xna.Framework.Color(255, 255, 255, 170);
  29.  
  30.             this.ProgressBar1.Border = true;
  31.             this.ProgressBar1.BorderColor = new Microsoft.Xna.Framework.Color(255, 0, 0, 100);
  32.         }
  33.  
  34.         protected override void LoadContent()
  35.         {
  36.  
  37.         }
  38.  
  39.         protected override void UnloadContent()
  40.         {
  41.  
  42.         }
  43.  
  44.         protected override void Update(Microsoft.Xna.Framework.GameTime GameTime)
  45.         {
  46.             if (Microsoft.Xna.Framework.Input.Keyboard.GetState().IsKeyDown(Microsoft.Xna.Framework.Input.Keys.Left)) this.ProgressBar1.Percentage -= 1;
  47.             if (Microsoft.Xna.Framework.Input.Keyboard.GetState().IsKeyDown(Microsoft.Xna.Framework.Input.Keys.Right)) this.ProgressBar1.Percentage += 1;
  48.             base.Update(GameTime);
  49.         }
  50.  
  51.         protected override void Draw(Microsoft.Xna.Framework.GameTime GameTime)
  52.         {
  53.             GraphicsDevice.Clear(new Microsoft.Xna.Framework.Color(0, 0, 255, 0));
  54.  
  55.             this.ProgressBar1.Draw();
  56.  
  57.             base.Draw(GameTime);
  58.         }
  59.     }
  60.  

And finally, the questions:

1: How do I get rid of the use of the System.Drawing and System.Drawing.Drawing2D namespaces and replace them with something in the XNA framework?

2: For the rounded style, how would I make the progress bar look proper when the percentage gets increased? Is there a way to erase the outside of a GraphicsPath? Drawing on the outside won't help, it actually needs to be erased. (From what I'm aware of atleast.)

3: Is there a way to make it so I don't have to change the BackgroundPath depending on whether or not there is supposed to be a border?

4: The reason the GetTexture is private is because I can't seem to make it get stored, so every time the draw function is called, it gets redrawn, but I'd like to be able to store the texture, and change it when the percentage value changes, so that way it doesn't have to keep redrawing.

5: How would I go about making the Background Path into a BoundingBox to detect collisions?

6: If you think I should be doing something completely different, please let me know.

And that is all.
Any help is appreciated.
Nov 5 '11 #1
5 4844
GaryTexmo
1,501 Recognized Expert Top Contributor
Trying to understand what you're doing here...

Are you replacing a progress control that was done in GDI with an XNA one and dropping it on a windows form, or are you trying to recode this progress bar control so that can use it in an XNA game?

I'm thinking it's the latter and if so, the question is how do you replace the GraphicsPath code with something that exists solely in the XNA framework? I assume you want to do this so your code will run on the XBox360... as if you were deploying on a PC you could continue to use this :)

If this is all the case... I'm looking at the GraphicsPath and it looks like it's used to define a series of lines, then you can use the FillPath method on a Graphics object to get your texture in the shape of your GraphicsPath. Effectively, it looks like you're masking your texture to the shape you want.

I don't think there's anything built into the XNA code that does this. The closest I can think of is an overload on the SpriteBatch.Draw method which takes a rectangle as the source rectangle to draw. This will clip your source image and would let you cover your non-rounded corner case. I did a quick google and couldn't find anything that does this... which doesn't mean it doesn't exist, just that I can't find it ;)

From my perspective, I think you're going to have to do this yourself. That said, it's an algorithm that should be fairly possible. I can think of a few ways to do it, though I'm not sure how fast they will be. I'll describe them here...

Method 1: Polygon containment
Create your own object to define a path, then add points to it... this will effectively define a polygon. Then when you fill the image, you can check to see if a pixel in the source image is inside your polygon or not. To see if a point is inside a polygon or not, check to see if the line defined by the point and a point outside the polygon (top-left of the image, for example) intersects an odd number of times with that polygon. If so, the point is inside the polygon.

Method 2: Dynamic Image Generation and Masking
You could also dynamically create a masking Texture2D object with what you want. and then use that to mask your images directly.

Method 3: Pre-generated Masks with Scaling
The final option I can think of is kind of an extension of the above. You can always create your masks as bitmap objects, then use scaling on them to size them appropriately, then mask your progress bar with them. If you did the whole image for the progress bar (with rounded corners) you run the risk of squishing it at smaller portions, so you might also just want to build a composite of endpoint cap masks with a middle section that's just a scaled rectangle.

Anyway, I apologize for the large amount of rambling I've done there... hopefully it gives you some ideas of where you want to go, and hopefully I've read your question correctly and given you something you can use :)
Nov 7 '11 #2
Tyler Wiebe
66 New Member
Thanks for your reply, and you're right about it being for an XNA game, and it is for a the PC, but I was hoping to make it for the Xbox 360 eventually, but if this is the case, I guess it'll stay a PC game.

But about your response of how to cut off the sides of the rounded progress bar, I'm sorry, but I'm sadly not understanding what you mean.
And do you have any opinion on question number three? It's no big deal, but it's rather annoying needing to change the pattern depending whether or not there is supposed to be a border.

And that's it for now, thanks again for your reply.
Nov 8 '11 #3
GaryTexmo
1,501 Recognized Expert Top Contributor
You only have to stay PC if you want to keep the reliance on this... and yea, you can change it to be however you like. This is one method of making a progress bar, but there are others.

Regarding your question 3, I'm not sure what you mean. I don't know enough about what your paths are actually doing to say, I'm sorry. As I understand it, you're masking your image in different ways so you'd have to change the path, wouldn't you?

Finally, regarding my method 3 (your question on cutting off the sides of a rounded progress bar), it's a bit complicated but the general idea would be to use PNG files for the caps of your progress bar and another PNG file for the center part that you scaled to the correct width and put in the center.

So then your draw would look something like...

Expand|Select|Wrap|Line Numbers
  1. spriteBatch.Draw(leftCapGraphic, new Vector2(this.X, this.Y));
  2. spriteBatch.Draw(midGraphic, new Vector2(this.X + leftCapGraphic.Width, this.Y), ..., new Vector2(this.Width - leftCapGraphic.Width - rightCapGraphic.Width, 1), ...); // Where that second Vector2 is the scale
  3. spritebatch.Draw(rightCapGraphic, new Vector2(this.X + leftCapGraphic.Width + (this.Width - leftCapGraphic.Width - rightCapGraphic.Width), this.Y));
This works if the colour of your progress bar is the same all along the horizontal and can be reduced to a single pixel in width. Then you can just scale it to fit the middle portion that you require. You will run into some troubles when your current progress bar is less than the width of both caps, but clever scaling and cropping will take care of that.
Nov 8 '11 #4
Tyler Wiebe
66 New Member
I just got back to my computer and thought a bit about what you said before, and I got an idea of how I could achieve my goal, it's different then your suggestion that I now see, but if you're suggestion is right, it should have the same result, but sadly, I'm not understanding it, so I'm just use my idea. And if you wouldn't mind, tell me what you think of it.

First, I made it so it would store the BackgroundPath so it wouldn't need to recreate it every time the draw method was called, which from what I'm aware of, will save some time on the rendering.

Secondly, the BackgroundPath is the only path now, and is called DesignPath.

Expand|Select|Wrap|Line Numbers
  1.         private System.Drawing.Drawing2D.GraphicsPath PDesignPath;
  2.         public System.Drawing.Drawing2D.GraphicsPath DesignPath { get { return this.PDesignPath; } }
  3.         private void CreateDesignPath()
  4.         {
  5.             this.PDesignPath = new System.Drawing.Drawing2D.GraphicsPath();
  6.             if (this.Style == Styles.Sqaured)
  7.             {
  8.                 if (this.Border)
  9.                 {
  10.                     this.PDesignPath.AddLine(0, 0, this.WidthM1, 0);
  11.                     this.PDesignPath.AddLine(this.WidthM1, 0, this.WidthM1, this.HeightM1);
  12.                     this.PDesignPath.AddLine(this.WidthM1, this.HeightM1, 0, this.HeightM1);
  13.                     this.PDesignPath.AddLine(0, this.HeightM1, 0, 0);
  14.                 }
  15.                 else
  16.                 {
  17.                     this.PDesignPath.AddLine(0, 0, this.Width, 0);
  18.                     this.PDesignPath.AddLine(this.Width, 0, this.Width, this.Height);
  19.                     this.PDesignPath.AddLine(this.Width, this.Height, 0, this.Height);
  20.                     this.PDesignPath.AddLine(0, this.Height, 0, 0);
  21.                 }
  22.             }
  23.             else if (this.Style == Styles.Rounded)
  24.             {
  25.                 if (this.Border)
  26.                 {
  27.                     this.PDesignPath.AddArc(0, 0, this.HeightM1, this.HeightM1, 90, 180);
  28.                     this.PDesignPath.AddLine(this.HeightD2, 0, this.WidthM1 - this.HeightD2, 0);
  29.                     this.PDesignPath.AddArc(this.WidthM1 - this.HeightM1, 0, this.HeightM1, this.HeightM1, -90, 180);
  30.                     this.PDesignPath.AddLine(this.WidthM1 - this.HeightD2, this.HeightM1, this.HeightD2, this.HeightM1);
  31.                 }
  32.                 else
  33.                 {
  34.                     this.PDesignPath.AddArc(-1, 0, this.Height, this.Height, 90, 180);
  35.                     this.PDesignPath.AddLine(this.HeightD2, 0, this.Width - this.HeightD2, 0);
  36.                     this.PDesignPath.AddArc(this.Width - this.Height, 0, this.Height, this.Height, -90, 180);
  37.                     this.PDesignPath.AddLine(this.Width - this.HeightD2, this.Height, this.HeightD2, this.Height);
  38.                 }
  39.             }
  40.         }
  41.  
I placed a call to the CreateDesignPath function into anything that will change the shape of the progress bar(Border, Size, Style), which in turn is what makes it get called far less often.

The reason there is only one GraphicsPath now is because I modified the GetTexture function into this:

Expand|Select|Wrap|Line Numbers
  1.         private Microsoft.Xna.Framework.Graphics.Texture2D GetTexture()
  2.         {
  3.             System.Drawing.Bitmap MainBitmap = new System.Drawing.Bitmap(this.Width, this.Height);
  4.             System.Drawing.Graphics MainBitmapGraphics = System.Drawing.Graphics.FromImage(MainBitmap);
  5.  
  6.             MainBitmapGraphics.FillPath(new System.Drawing.SolidBrush(System.Drawing.Color.FromArgb(this.BackColor.A, this.BackColor.R, this.BackColor.G, this.BackColor.B)), this.DesignPath);
  7.  
  8.             if ((int)(this.Width * this.PercentageD100) > 0)
  9.             {
  10.                 System.Drawing.Bitmap PercentageBitmap = new System.Drawing.Bitmap((int)(this.Width * this.PercentageD100), this.Height);
  11.                 System.Drawing.Graphics PercentageBitmapGraphics = System.Drawing.Graphics.FromImage(PercentageBitmap);
  12.                 PercentageBitmapGraphics.FillPath(new System.Drawing.SolidBrush(System.Drawing.Color.FromArgb(this.ForeColor.A, this.ForeColor.R, this.ForeColor.G, this.ForeColor.B)), this.DesignPath);
  13.                 MainBitmapGraphics.DrawImage(PercentageBitmap, 0, 0);
  14.  
  15.                 PercentageBitmapGraphics.Dispose();
  16.             }
  17.             if (this.Highlight)
  18.             {
  19.                 System.Drawing.Bitmap HighlightBitmap = new System.Drawing.Bitmap(this.Width, this.HeightD2);
  20.                 System.Drawing.Graphics HighlightBitmapGraphics = System.Drawing.Graphics.FromImage(HighlightBitmap);
  21.                 HighlightBitmapGraphics.FillPath(new System.Drawing.SolidBrush(System.Drawing.Color.FromArgb(this.HighlightColor.A, this.HighlightColor.R, this.HighlightColor.G, this.HighlightColor.B)), this.DesignPath);
  22.                 MainBitmapGraphics.DrawImage(HighlightBitmap, 0, 0);
  23.  
  24.                 HighlightBitmapGraphics.Dispose();
  25.             }
  26.             if (this.Border) MainBitmapGraphics.DrawPath(new System.Drawing.Pen(System.Drawing.Color.FromArgb(this.BorderColor.A,this.BorderColor.R,this.BorderColor.G,this.BorderColor.B), 1), this.DesignPath);
  27.  
  28.             MainBitmapGraphics.Dispose();
  29.  
  30.             System.IO.MemoryStream MemoryStream = new System.IO.MemoryStream(this.BufferSize);
  31.             MainBitmap.Save(MemoryStream, System.Drawing.Imaging.ImageFormat.Png);
  32.             return Microsoft.Xna.Framework.Graphics.Texture2D.FromStream(GraphicsDevice, MemoryStream);
  33.         }
  34.  
Now all that has to do is save a GraphicsPath to DesignPath for every change of appearance, and then it all it has to do is create three bitmaps using the DesignPath, cut them to the right size, put them into one bitmap, and change that one bitmap into a Texture2D every time the draw method is called.

I hope you understood that, if not, I don't think I can explain it any better. But I do assume that because it doesn't have to do as much math as before, and is only done once(Unless the appearance gets changed), that it saves some rendering time. Am I correct about that? It worked fine before, but an increase of rendering speed never hurts, right?

And thanks again for your help.
Nov 8 '11 #5
GaryTexmo
1,501 Recognized Expert Top Contributor
I think that's a great approach... with XNA, the less you do in a draw method the better. So caching your image and only updating it when something triggers a change is absolutely the way to go :)

You're still reliant on paths here so you can't port easily to XBox360 (which is where my suggestions come in) but you know what? My advice to you would be to just carry on. Try to keep your new code going forward away from the winforms .NET library if you can, but for this? Just worry about the port if/when you decide to code for XBox360. You have the correct design approach here in that your code is completely modular and outputs something that XNA can understand. So if you ever need to move away from the winforms .NET stuff and into full XNA support your public interface won't change, just the guts of your class.
Nov 9 '11 #6

Sign in to post your reply or Sign up for a free account.

Similar topics

2
12289
by: Champika Nirosh | last post by:
Hi, I want to create drawing board application that can draw Line, rectagle, circle and free hand drawing. Each drawing need to be transparent, moveable (draggable), have bring to front and...
1
3209
by: Hadar | last post by:
Hi, I'm getting "object is currently in use elsewhere" when I use System.Drawing.Graphics.MesureString. This is what I do: My controls use a utility class the helps it to mesure strings. To...
9
15310
by: Merlin | last post by:
Hi, My code below doesn't work does anyone have any pointers? All my controls are programically added. Dim i As Int16 For i = 0 To Me.Controls.Count - 1 If Me.Controls(i).Name <>...
2
1658
by: Daniel Friend | last post by:
Hello, I have added a custom usercontrol programically and all works fine... I would like to change some custom properties that I have set in that usercontrol. Any help would be greatly...
2
5021
by: Agnes | last post by:
In myDatagrid, there is 3 columns, account code, debit,credit. If the user input some particular a account code in column1 , i need to based on the contect of column1, to disable...
3
1782
by: Jim | last post by:
I have a datagrid with a DataAdapter as the DataSource. The user fills in their data for 3 columns and I want to programically add a value to the 4th (invisible) column (employee number). That way...
2
1806
by: dtarczynski | last post by:
Hello. Im trying to add new EventHandler to DropDownList programically. Im doing something like this: DropDownList ddlCate = new DropDownList(); ddlCate.ID = String.Format("ddlCategory{0}",...
5
2582
by: superjacent | last post by:
Hope someone can help. I have a saved parent form containing an unbound sub-form. I set the SourceObject (form) after the Parent Form opens/loads. The sub-form (datasheet view) basically...
0
1211
by: abduzalam | last post by:
Hi Members, I am in a serious trouble,My problem is i want to develop a software as my academic project, it is network back up database, that is a remote machine hold sql databses, and when...
2
2310
by: ThatsIT.net.au | last post by:
I have this code that writes a pie chart in a asp.net page, but I want to use it in a server control. When I try I get a error on the last line "Response.OutputStream" Obviously there is no...
0
6978
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can...
0
7154
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers,...
0
7360
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each...
0
5451
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing,...
1
4881
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 1 May 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome a new...
0
3086
by: TSSRALBI | last post by:
Hello I'm a network technician in training and I need your help. I am currently learning how to create and manage the different types of VPNs and I have a question about LAN-to-LAN VPNs. The...
0
3076
by: adsilva | last post by:
A Windows Forms form does not have the event Unload, like VB6. What one acts like?
1
633
muto222
by: muto222 | last post by:
How can i add a mobile payment intergratation into php mysql website.
0
280
bsmnconsultancy
by: bsmnconsultancy | last post by:
In today's digital era, a well-designed website is crucial for businesses looking to succeed. Whether you're a small business owner or a large corporation in Toronto, having a strong online presence...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.