WinForms Graphics PictureBox with dynamic width - c#

I'm making a winform .NET app. It must show a graphic in bars format. I'm using a picturebox because it's the only way I know how to do it (if someone knows a better way, please tell me).
I'm adding dynamically the lines (the bars of the graphic) with this code:
int currentX = this.lineAmmount * (lineWidth + lineMargin);
pictureBox.CreateGraphics().DrawLine(new Pen(color, lineWidth), //Pen
currentX, pictureBox.Height, //Starting (x, y)
currentX, pictureBox.Height - Convert.ToInt32(value * graphicsScale)); //Ending (x, y)
this.lineAmmount++;
That works just perfect.
What I want now is the pictureBox to have an horizontal scroll bar. So what I put the pictureBox into a panel with autoscroll = true. Now what I needed its to dynamically increase the pictureBox width. So I added this code after I add each line:
pictureBox.Width = Math.Max(this.lineAmmount * (lineWidth + lineMargin), 205);
(205 is the minimum width I want).
That code also works greate. The width is increased. With the first lines Math.Max always returns 205, after a couple of lines it starts returning the orher value. From that moment on ALL THE LINES DISAPPEAR!!!
Please help!!
Thanks in advance and sorry for my bad english,
Diego

I found out the Chart control. It does all that automatically.

Where is written that code, that you posted in first box? Is it in update method of the control?
Sure, chart will be more appropriate here

Related

Set MinimumSize according the controls residing inside form

Title of my question could be make it look like a duplicate but please read ahead as my problem is a bit different.
I am trying to replicate the minimum size functionality of some popular media players like MPC-HC or VLC where when you try to make it small the minimum size it achieves is when only MenuStrip and Player Controls are visible.
The code I've written to attain this is:
public NewMain()
{
InitializeComponent();
int ClientTop = RectangleToScreen(ClientRectangle).Top;
int height = menuStrip1.Height + panel1.Height + ClientTop - Top;
label4.Text = height.ToString();
MinimumSize = new Size(373, height);
}
The problem is that when it runs, its not working perfectly and the menuStrip1 is still getting blocked a little at bottom from the panel1 (Docked at bottom) where the player controls will be placed.
Below is the Image of what I was able to attain with above code.
Next Image is what I expected:
Note that label on left updates when resize the form and the label on the right is the determined height via code.
My Idea was to add the difference of Form's Top and the Top of total rectangle visible on the screen i.e. the height of the title bar otherwise the resulting height will be even smaller and hide the menuStrip1 completely. I don't want to hardcode any values because it'll make the interface less adaptable to the changes that I might be doing later on.
To correctly determine the minimum height in this case is to keep the calculations relative which can be attained by:
int height = Height - (panel1.Top - menuStrip1.Bottom);
All credit goes to Hans Passant who provided this code. I'm just posting it as an answer to mark my question solved. Thank you.

How to adjust axis scales for datavisualization.charting after resizing a chart?

I updated a chart from essentially being 72dpi, to 300dpi. This is because I am using itextsharp to add an image to my pdf and the quality was poor. So I increased the size of the image by 3X and the image does look better, but here is the problem.
DPI has increased, but detail has become very hard to see.
Original Chart Image
Refactored Chart Image
Code
This is how I resized my chart.
private static System.Drawing.Bitmap GetChartBitmap()
{
System.Drawing.Rectangle targetBounds = new System.Drawing.Rectangle(0, 0, chart_runs.Width, chart_runs.Height);
System.Drawing.Bitmap bitmap = new System.Drawing.Bitmap(targetBounds.Width, targetBounds.Height);
bitmap.SetResolution(1000, 1000);
chart_runs.DrawToBitmap(bitmap, targetBounds);
bitmap.Save(#"C:\Temp\OriginalChartImage.bmp");
System.Drawing.Bitmap bitmap3 = new System.Drawing.Bitmap(1650, 990);
bitmap3.SetResolution(300, 300);
chart_runs.DrawToBitmap(bitmap3, new System.Drawing.Rectangle(0, 0, 1650, 990));
bitmap3.Save(#"C:\Temp\RefactoredChartImage.png");
//This stuff below is for my code elsewhere. Using bitmap3 to be added to pdf.
//chart_runs.DrawToBitmap(bitmap, targetBounds);
string path = System.IO.Path.GetTempPath();
bitmap1.Save(path + #"\Image.png");
return bitmap1;
}
I have looked at the Microsoft msdn examples and haven't found anything that addresses my problem. Namely, how can I either increase the size of my labels so people can read them again. OR, is there a way for me to increase the DPI and keep the same label x and label y scale that was used in the first picture? That is, have a larger image and 300DPI, but scale 0 to 300 by 20's and not 5's like my refactored picture?
Attempts to fix
Scaling the axis? See here. I don't think this is working right. Not much success here.
Been trying to find a way in Chart class to see if there is a way to specify strict scales. (20 on y scale vs 15 seconds on x scale).
Most online resources are pleased just to increase the scale of the picture and walk away. And things like this here.
I would greatly appreciate any help and assistance.
Couple different questions, with a couple different answers. The easiest would be to change the font size of your axis labels to be bigger. This can be done via
chart1.ChartAreas[0].AxisX.LabelStyle.Font = new Font...;
Without doing that, your labels won't be readable no matter what else you do, and that's just because you changed the DPI (that's exactly what changing the DPI does).
If you want the labels to be displayed every 20 units on the y axis and every 15 on the x, you can use the Interval and IntervalType properties of the axis. The IntervalType is used when you have DateTime objects being displayed:
chart1.ChartAreas[0].AxisX.Interval = 15;
chart1.ChartAreas[0].AxisX.IntervalType = DateTimeIntervalType.Seconds;
chart1.ChartAreas[0].AxisY.Interval = 20;
Your first link about scaling the axis is essentially zooming in or out, which is why you haven't had success.

How to determine the proper maximum value for scrollbar c# .NET (how does windows do it?)

Before I go into my question, let me explain my setup:
First: I have a PictureBox that holds a Bitmap which is generated at runtime. This Bitmap can be different widths but always the same height.
Second: PictureBoxes do not support scrolling, therefore, I have the PictureBox docked in a panel. Initially, I had used the panel's autoscroll feature, but abandoned that after I discovered through this article that PictureBoxes have a size limit. I also learned that it's better to instead have small PictureBoxes and only draw what needs to be seen instead of the whole image.
Third: So I added a HScrollBar, which is fine and dandy, but I can't seem to figure out the math behind how big to make the scroller. I tried setting the maximum of the scrollbar to the length of the bitmap, but as you can see the size of the scroller is much smaller in mine than the one Windows puts in if I use the autoscroll feature.
My question is, what is the math behind the scroller size and how do I emulate that in my custom scrollbar?
Let me know if my question is unclear and I will try my best to make it more understandable. And thanks in advance for your help!
I figured out what was the problem. Perhaps I should have tried a little longer. :)
The answer lies in the LargeChange property. I let the Maximum at the total width of the bitmap and then set the LargeChange to the width of what I wanted to show. (i.e. the width of the PictureBox)
The size of the "scroller" is determined by the ratio of the value of LargeChange to the value of Maximum. For example, if the width to show (LargeChange) is 100 and the total width (Maximum) is 300 then the "scroller" size will be 1/3 of the scrollbar length. (100/300).
I got same problem too and tried to figure it out, I have a panel which contain another panel inside it called panelChild, and the default scrollbar is small, I need lager scrollbar, so I use HScrollBar to do that (display over-top of default scrollbar), I post my solution here, may be it helpful to someone
public Form() {
InitializeComponent();
hScrollBar.Maximum = panelChild.Width;
hScrollBar.LargeChange = panel.Width; // panel which contain panelChild, and this hScrollBar will same as panel scrollbar
hScrollBar.Scroll += HScrollBar_Scroll;
}
private void HScrollBar_Scroll(object sender, ScrollEventArgs e)
{
int diference = e.OldValue - e.NewValue;
foreach (Control c in panel.Controls)
{
c.Location = new Point(c.Location.X + diference, c.Location.Y);
}
}

How to set autosize font in zedgraph

I'm using ZedGraph in my c# project.
My X axis has text labels (used for bar chart), but with the default setting of XAxis.Scale.IsPreventLabelOverlap = true every second label is missing. When I change it to false with XAxis.Scale.MajorStep = 1 every label is shown, but font size remains the same, and labels overlap.
Is there any way to change font size of labels ? or preferably switch it to autosize ?
I hate to let you know but as far as I know you cannot change the axis label font size directly. You can change the axis title font size, but not the labels themselves. You can change whether or not they autosize though and scale at which they autosize and it seems that is sort of what you want and that may end up helping you. This is the resource at which I was looking.
Set the PaneBase.IsFontsScaled property to true and then you can change the scale factor by using the PaneBase.ScaleFactor() method. Look through that resource I linked and I think you will be able to get it done. I don't have ZedGraph installed so I can't test it but I'm sure it will be something like that.
Good luck!
my solution is ;
curve.Label.FontSpec = zg1.GraphPane.Legend.FontSpec.Clone();
curve.Label.FontSpec.Size = 6;
I've forgotten about this question long ago.
I've found my own solution, which isn't so clean. I've rewritten the PaneBase.CalcScaleFactor() method by changing return scaleFactor; to something like return scaleFactor * 0.75f;. Now it works as it should.

Draw a Grid over a Picturebox in c#

I am trying to make a tool in c# which allows the user to put a grid on the screen on a picturebox. At the moment i don't know how to do this, so when a button is clicked, the picturebox comes up with a grid. It needs to be a grid which is spaced out enough that users can find out locations of objects on the picture in the picturebox. Help with what code i can use to do this would be very helpful as i was going to use ControlPaint.DrawGrid but not sure of the values i need to put in it to get my desired effect?
Thanks
Form the Documentation od controlpaint.Drawgrid,
I suppose you need to decide on the cell size in x- amd y-direction and pass this as a size parameter to Drawgrid:
public static void DrawGrid(
Graphics graphics,
Rectangle area,
Size pixelsBetweenDots,
Color backColor
)
for example, a 100*200 pixels square grid would be generated by
setting graphcis to the context you want to draw upon,
Setting area to the top left right and bottom parameters of your image
setting size.x to 100 and size.y to 200
setting color to any color you like.
Update
Something like this should do.
Rectangle myRect = new System.drawings.Rectangle();
myRect.Location := new System.Drawing.Point(0,0);
myRect.Height = 50;
myRect.Width = 50;
Drawgrid(FromImage(yourImage), mygrid , yourImage.Size, System.Drawing.Color.Black);
Disclaimer: i don't develope in c#, so above code is not tested for anything. I just picked stuff from the documentation (msdn).

Categories