How do I resize form programmatically using C#? - c#

This seems simple enough, and I have followed advice I have found on other posts here. If my picturebox grows to accommodate a large image, I want the form to grow a little more, so there's some whitespace under the photo (otherwise, it looks like the form cropped the photo).
if ((pictureBox1.Height + 25) >= this.Height)
{
this.Size = new Size(this.Width, (pictureBox1.Height + 35));
this.Refresh(); // tried with and without refresh
}
Unfortunately, nothing happens. When going step by step, I see that the Height of the form never changes. I've read here on stack overflow that setting minimum size or maximum size can cause this behaviour, but both are set to their defaults (0,0).
Suggestions?
Thank you

What you have seems to work for me. I would try putting a break in your code at the refresh and examining the values that you are getting and then stepping through the refresh and checking again. Check to make sure that you are getting the expected values for this.Height and pictureBox1.Height.
Here is the exact code that I used to test this:
this.Size = new Size(300, 300);
PictureBox pictureBox1 = new PictureBox();
pictureBox1.Size= new Size(700, 700);
this.Controls.Add(pictureBox1);
if ((pictureBox1.Height + 25) >= this.Height)
{
this.Size = new Size(this.Width, (pictureBox1.Height + 35));
this.Refresh(); // tried with and without refresh
}
Your going to have to post more of the code in order to get much help.

Related

MS visual Studio Forms application : Can't get form to have less width then 100 Pixels

First question here so if I can improve something in anyway please let me know!
I am currently making a "multi-form" application.
It currently consists out of a launcher bar with various buttons and the launcher bar has a width of 150 pixels (This one is fine).
When the user presses a button another panel will open 10 pixels next to the the first panel with a width of 75. (I wanted to add the current buttons "subcategories" here)
But when calling the second form it keeps setting itself to 100 pixels (Well I think it is 100 pixels since it seems about 2/3 of the first panel)
private void button_click(object sender, EventArgs e)
{
if (activated == 0)
{
var new_y = new form2();
new_y.AutoSize = false;
new_y.Width = 75;
new_y.Height = this.Height;
new_y.Show();
activated = 1;
}
}
I stripped it of some additional code (positioning stuff) so if that could cause any problems please let me know.
But my question : How do I prevent the form setting itself to 100 pixels in width and make it the 75 pixels width I want it to be?
Thanks in advance!
Ps . FormBorderStyle is set to none
Try setting the MinimumSize property:
new_y.Width = 75;
new_y.Height = this.Height;
new_y.MinimumSize = new Size(75, this.Height);

(ListView?)-Control like in Windows Explorer

I'm wondering if there is any way to make a control like that one in windows explorer's auto start when you plugin a device.
I had thought that this could be a listview-control in a more or less modified way, but I was not able to find anything with Google. I also checked many CodeProject-pages.
Does anyone have an idea where I would be able to get the control or how I could make one myself? (I am not that good with OwnerDraw :P)
Thanks.
Actually tweaking a ListView is not any easier than ownerDrawing it. Here is an example that shows, how simple it really is.
You just script one event (DrawItem) and you are done.
This piece of code assumes:
The LV's View is set to List
You have a suitable ImageList added to your form
You have the LV's ownerDraw set to true
You have added two columns to hold the text shown in the two labels
You have made the 1st column wide enough to hold the whole stuff that gets drawn
You have made the LV's FontSize as large as the Images' Height (say 32)
Assign the appropriate ImageIndex values to the LV's Items
private void listView1_DrawItem(object sender, DrawListViewItemEventArgs e)
{
Point point0 = new Point(e.Bounds.Left, e.Bounds.Top);
Point point1 = new Point(imageList1.ImageSize.Width + 10, e.Bounds.Top + 5);
Point point2 = new Point(imageList1.ImageSize.Width + 10, e.Bounds.Top + 25);
Size size = new Size(listView1.ClientRectangle.Width, e.Bounds.Height);
Rectangle R = new Rectangle(point0, size);
Font F1 = new Font(listView1.Font.FontFamily, 11f, FontStyle.Bold);
Font F2 = new Font(listView1.Font.FontFamily, 10f);
if (e.Item.Focused) e.Graphics.FillRectangle(Brushes.LightBlue, R);
else if (e.ItemIndex % 2 == 1) e.Graphics.FillRectangle(Brushes.GhostWhite, R);
e.Graphics.DrawImage(imageList1.Images[e.Item.ImageIndex], point0 );
e.Graphics.DrawString(e.Item.Text, F1, Brushes.Black, point1);
e.Graphics.DrawString(e.Item.SubItems[1].Text, F2, Brushes.Black, point2);
F1.Dispose(); F2.Dispose();
}
Note that I have hard-coded a few Colors to paint every other line and also the focused item. These colors really should use the respective System colors. These come to mind:
SolidBrush brush0 = new SolidBrush(SystemColors.ControlLight);
SolidBrush brush1 = new SolidBrush(SystemColors.Highlight);
I am using the Font that is assigned to the LV but with moderate sizes. Obviously more or less anything, especially the various offsets, can be configured to your liking. But using colors from the System.Colors collection is good way to stay in keeping with your users' Windows themes.

c# winform screen resolution

I have a C# WinForms application and when I give the executable to different users the application displays in different sizes (based on their screen resolution). Some of the parts of the application can't be seen.
how can I set absolute 1280X800 for my forms and make sure that the form size will not be changed whatever resolution is!
You can use Control.ScaleControl and Control.Scale
private void MainForm_Load( object sender, EventArgs e )
{
float width_ratio = (Screen.PrimaryScreen.Bounds.Width / 1280);
float heigh_ratio = (Screen.PrimaryScreen.Bounds.Height / 800f);
SizeF scale = new SizeF(width_ratio, heigh_ratio);
this.Scale(scale);
//And for font size
foreach (Control control in this.Controls)
{
control.Font = new Font("Microsoft Sans Serif", c.Font.SizeInPoints * heigh_ratio * width_ratio);
}
}
Hope this helps.
Use the MaximumSize property of the form.
form.MaximumSize = new Size(1280, 800);
You can also set a MinimumSize if you don't want the user to make it smaller than a desired size.
You can instead design the GUI so it scrolls up and down more easily.You can make use of the following
Layout Managers
Docking
Anchors
The property
Screen.PrimaryScreen.WorkingArea
is very useful for form sizing and positioning. For example this code:
this.Width = Screen.PrimaryScreen.WorkingArea.Width/2;
this.Height = Screen.PrimaryScreen.WorkingArea.Height/2;
this.Top = (Screen.PrimaryScreen.WorkingArea.Top + Screen.PrimaryScreen.WorkingArea.Height)/4;
this.Left = (Screen.PrimaryScreen.WorkingArea.Left + Screen.PrimaryScreen.WorkingArea.Width)/4;
will place the form in which it is executed in the middle of the screen and size it to half the screen.
The WorkingArea var is used to exclude stuff like the task bar and other docked items on the desktop when calculating the size of the screen.
Hope this helps.

How to fit Windows Form to any screen resolution?

I work on VS 2008 with C#. This below code does not work for me. My form was designed in 1024 x 768 resolution.
Our clients laptop is in 1366 x 768 resolution. To solve this problem, I set below code in Form Load event:
this.Location = new Point(0, 0);
this.Size = Screen.PrimaryScreen.WorkingArea.Size;
but the form does not resize as per screen resolution and bottom of my form gets hidden or cut or I miss the scroll bar.
Is there any way to solve this problem? Please show me the syntax.
Can't you start maximized?
Set the System.Windows.Forms.Form.WindowState property to FormWindowState.Maximized
If you want to set the form size programmatically, set the form's StartPosition property to Manual. Otherwise the form's own positioning and sizing algorithm will interfere with yours. This is why you are experiencing the problems mentioned in your question.
Example: Here is how I resize the form to a size half-way between its original size and the size of the screen's working area. I also center the form in the working area.
On computers with multiple monitors, the user probably expects the form to open on the same screen that the mouse pointer is on. We can get it with Screen.FromPoint(Cursor.Position).
public MainView()
{
InitializeComponent();
StartPosition = FormStartPosition.Manual;
Rectangle screen = Screen.FromPoint(Cursor.Position).WorkingArea;
int w = Width >= screen.Width ? screen.Width : (screen.Width + Width) / 2;
int h = Height >= screen.Height ? screen.Height : (screen.Height + Height) / 2;
Location = new Point(screen.Left + (screen.Width - w) / 2, screen.Top + (screen.Height - h) / 2);
Size = new Size(w, h);
}
Note that setting WindowState to FormWindowState.Maximized alone does not change the size of the restored window. So the window might look good as long as it is maximized, but when restored, the window size and location can still be wrong. So I suggest setting size and location even when you intend to open the window as maximized.
Probably a maximized Form helps, or you can do this manually upon form load:
Code Block
this.Location = new Point(0, 0);
this.Size = Screen.PrimaryScreen.WorkingArea.Size;
And then, play with anchoring, so the child controls inside your form automatically fit in your form's new size.
Set the form property to open in maximized state.
this.WindowState = FormWindowState.Maximized;
int h = Screen.PrimaryScreen.WorkingArea.Height;
int w = Screen.PrimaryScreen.WorkingArea.Width;
this.ClientSize = new Size(w , h);
You can simply set the window state
this.WindowState = System.Windows.Forms.FormWindowState.Maximized;
simply set Autoscroll = true for ur windows form.. (its not good solution but helpful)..
try for panel also(Autoscroll property = true)
You can always tell the window to start in maximized... it should give you the same result... Like this: this.WindowState = FormWindowState.Maximized;
P.S. You could also try (and I'm not recommending this) to subtract the taskbar height.

How to implement pan/zoom on gigapixel bitmaps?

In my project, I'm using (uncompressed 16-bit grayscale) gigapixel images which come from a high resolution scanner for measurement purposes. Since these bitmaps can not be loaded in memory (mainly due to memory fragmentation) I'm using tiles (and tiled TIFF on disc). (see StackOverflow topic on this)
I need to implement panning/zooming in a way like Google Maps or DeepZoom. I have to apply image processing on the fly before presenting it on screen, so I can not use a precooked library which directly accesses an image file. For zooming I intend to keep a multi-resolution image in my file (pyramid storage). The most useful steps seem to be +200%, 50% and show all.
My code base is currently C# and .NET 3.5. Currently I assume Forms type, unless WPF gives me great advantage in this area. I have got a method which can return any (processed) part of the underlying image.
Specific issues:
hints or references on how to implement this pan/zoom with on-demand generation of image parts
any code which could be used as a basis (preferably commercial or LGPL/BSD like licenses)
can DeepZoom be used for this (i.e. is there a way that I can provide a function to provide a tile at the right resulution for the current zoom level?) ( I need to have pixel accurate addressing still)
This CodeProject article: Generate...DeepZoom Image Collection might be a useful read since it talks about generating a DeepZoom image source.
This MSDN article has a section Dynamic Deep Zoom: Supplying Image Pixels at Run Time and links to this Mandelbrot Explorer which 'kinda' sounds similar to what you're trying to do (ie. he is generating specific parts of the mandelbrot set on-demand; you want to retrieve specific parts of your gigapixel image on-demand).
I think the answer to "can DeepZoom be used for this?" is probably "Yes", however as it is only available in Silverlight you will have to do some tricks with an embedded web browser control if you need a WinForms/WPF client app.
Sorry I can't provide more specific answers - hope those links help.
p.s. I'm not sure if Silverlight supports TIFF images - that might be an issue unless you convert to another format.
I decided to try something myself. I came up with a straightforward GDI+ code, which uses the tiles I've already got. I just filter out the parts which are relevant for current clipping region. It works like magic! Please find my code below.
(Form settings double buffering for the best results)
protected override void OnPaint(PaintEventArgs e)
{
base.OnPaint(e);
Graphics dc = e.Graphics;
dc.ScaleTransform(1.0F, 1.0F);
Size scrollOffset = new Size(AutoScrollPosition);
int start_x = Math.Min(matrix_x_size,
(e.ClipRectangle.Left - scrollOffset.Width) / 256);
int start_y = Math.Min(matrix_y_size,
(e.ClipRectangle.Top - scrollOffset.Height) / 256);
int end_x = Math.Min(matrix_x_size,
(e.ClipRectangle.Right - scrollOffset.Width + 255) / 256);
int end_y = Math.Min(matrix_y_size,
(e.ClipRectangle.Bottom - scrollOffset.Height + 255) / 256);
// start * contain the first and last tile x/y which are on screen
// and which need to be redrawn.
// now iterate trough all tiles which need an update
for (int y = start_y; y < end_y; y++)
for (int x = start_x; x < end_x; x++)
{ // draw bitmap with gdi+ at calculated position.
dc.DrawImage(BmpMatrix[y, x],
new Point(x * 256 + scrollOffset.Width,
y * 256 + scrollOffset.Height));
}
}
To test it, I've created a matrix of 80x80 of 256 tiles (420 MPixel). Of course I'll have to add some deferred loading in real life. I can leave tiles out (empty) if they are not yet loaded. In fact, I've asked my client to stick 8 GByte in his machine so I don't have to bother about performance too much. Once loaded tiles can stay in memory.
public partial class Form1 : Form
{
bool dragging = false;
float Zoom = 1.0F;
Point lastMouse;
PointF viewPortCenter;
private readonly Brush solidYellowBrush = new SolidBrush(Color.Yellow);
private readonly Brush solidBlueBrush = new SolidBrush(Color.LightBlue);
const int matrix_x_size = 80;
const int matrix_y_size = 80;
private Bitmap[,] BmpMatrix = new Bitmap[matrix_x_size, matrix_y_size];
public Form1()
{
InitializeComponent();
Font font = new Font("Times New Roman", 10, FontStyle.Regular);
StringFormat strFormat = new StringFormat();
strFormat.Alignment = StringAlignment.Center;
strFormat.LineAlignment = StringAlignment.Center;
for (int y = 0; y < matrix_y_size; y++)
for (int x = 0; x < matrix_x_size; x++)
{
BmpMatrix[y, x] = new Bitmap(256, 256, PixelFormat.Format24bppRgb);
// BmpMatrix[y, x].Palette.Entries[0] = (x+y)%1==0?Color.Blue:Color.White;
using (Graphics g = Graphics.FromImage(BmpMatrix[y, x]))
{
g.FillRectangle(((x + y) % 2 == 0) ? solidBlueBrush : solidYellowBrush, new Rectangle(new Point(0, 0), new Size(256, 256)));
g.DrawString("hello world\n[" + x.ToString() + "," + y.ToString() + "]", new Font("Tahoma", 8), Brushes.Black,
new RectangleF(0, 0, 256, 256), strFormat);
g.DrawImage(BmpMatrix[y, x], Point.Empty);
}
}
BackColor = Color.White;
Size = new Size(300, 300);
Text = "Scroll Shapes Correct";
AutoScrollMinSize = new Size(256 * matrix_x_size, 256 * matrix_y_size);
}
Turned out this was the easy part. Getting async multithreaded i/o done in the background was a lot harder to acchieve. Still, I've got it working in the way described here. The issues to resolve were more .NET/Form multithreading related than to this topic.
In pseudo code it works like this:
after onPaint (and on Tick)
check if tiles on display need to be retrieved from disc
if so: post them to an async io queue
if not: check if tiles close to display area are already loaded
if not: post them to an async io/queue
check if bitmaps have arrived from io thread
if so: updat them on screen, and force repaint if visible
Result: I now have my own Custom control which uses roughly 50 MByte for very fast access to arbitrary size (tiled) TIFF files.
I guess you can address this issue following the steps below:
Image generation:
segment your image in multiple subimages (tiles) of a small resolution, for instace, 500x500. These images are depth 0
combine a series of tiles with depth 0 (4x4 or 6x6), resize the combination generating a new tile with 500x500 pixels in depth 1.
continue with this approach until get the entire image using only a few tiles.
Image visualization
Start from the highest depth
When user drags the image, load the tiles dynamically
When the user zoom a region of the image, decrease the depth, loading the tiles for that region in a higher resolution.
The final result is similar to Google Maps.

Categories