How do I create a border made of picture boxes, I'm trying to make a snake game and I want to first make a border for the playing area, using picture boxes, so far I have used a while loop to make the top row but I feel there would be a better way to make the whole thing, I heard a helper function may help but I'm not sure how to go about that either
int i = 1;
public Snake()
{
InitializeComponent();
}
private void Snake_Load(object sender, EventArgs e)
{
while (i < 404)
{
var picture = new PictureBox
{
Name = "pictureBox",
Size = new Size(20, 20),
Location = new Point(i, 0),
BackColor = Color.FromArgb(0,0,0),
};
this.Controls.Add(picture);
i += 20;
}
}
Related
I have a list of texts placed in WrapPanel, representing nested text blocks... The texts are clickable so I wanted to emphasize it, so when user enters mouse over them, I make them bigger (basically I'm just increasing the font by one). The problem is that this changes size of the framework element which affects layout in WrapPanel, meaning the panel can move last item into next row. Normally there is enough space, or even if not, it's not a problem when hovering over some text in the middle. But if user want's to click last element when it's near the edge of the panel, he basically can't. Because as soon as the element grows, it moves to next row and the cursor is not longer over it, so it shrinks again and panel moves it back to first row, where it is under cursor again, and so on...
Here you can see this scenario:
public partial class MainWindow : Window {
public MainWindow() {
InitializeComponent();
var wp = new WrapPanel() {
Background = Brushes.Blue,
Orientation = Orientation.Horizontal,
VerticalAlignment = VerticalAlignment.Top,
Children = {
createChild(),
createChild(),
createChild(),
createChild(),
}
};
Content = new Grid() {
Background = Brushes.Gray,
Children = { wp }
};
}
private UIElement createChild() {
var g = new Grid() {
Width = 100,
Height = 20,
Margin = new Thickness(5),
Background = Brushes.Red,
};
g.MouseEnter += (s, e) => { g.Width *= 2; g.Background = Brushes.White; };
g.MouseLeave += (s, e) => { g.Width *= .5; g.Background = Brushes.Red; };
return g;
}
}
How can I avoid it?
I was thinking of some "margin" property I could specify in WrapPanel so it will move the child to next row earlier when it's close to the edge whiting that margin (even if it could actually fit), but I didn't found such thing.
I have been working with windows forms for a short while and have noticed that button controls always appear one pixels smaller in each direction than I am trying to make them.
To illustrate, the TextBoxes and Button in the image bellow are set to the exact same size but are different sizes.
wrong size buttons
Here is the code that I used to generate the buttons:
public Form1() {
InitializeComponent();
this.Size = new Size(216, 239)
TB1 = new TextBox();
TB1.Multiline = true;
TB1.Size = new Size(100, 100);
TB1.Location = new Point(100, 0);
Controls.Add(TB1);
TB2 = new TextBox();
TB2.Multiline = true;
TB2.Size = new Size(100, 100);
TB2.Location = new Point(0, 100);
Controls.Add(TB2);
TestButton = new Button();
TestButton.Text = "sdfsdf";
TestButton.Size = new Size(100, 100);
TestButton.Location = new Point(100, 100);
Controls.Add(TestButton);
}
From the Image you can see that there is white space around the button. I have tried changing the Control.Margin and Control.Padding but this extra space around the button is unaffected by those.
In order to make the button appear 100x100 (the way I want it) you have to move it one pixel up and to the left and make it two pixels wider and taller. (TextButton.Size = new Size(102, 102); TextButton.Location = new Point(99, 99);)
What I would like to do is make the buttons actually the size I set them to be. Because of the number of buttons in my program, it is undesirable to manually increase the size of each button and I am looking for a more elegant long term solution that I can use going forwards.
I have tried to create a wrapper class around the button class called MyButton but it doesn't work with polymorphism (explained bellow):
class MyButton : Button {
public MyButton() : base() {}
public new Size Size {
get;
set {
int width = value.Width + 2; // make it two wider
int height = value.Height + 2; // make it two taller
Size size = new Size(width, height);
base.Size = size;
}
}
public new Point Location {
get;
set {
Console.WriteLine("running"); // used to make sure this is actually being run
int x = value.X - 1; // move it one left
int y = value.Y - 1; // move it one up
Point point = new Point(x, y);
base.Location = point;
}
}
}
When I create a MyButton object and use myButtonObject.Size = ... it works perfectly and the button sizing and location works out. However, at another place in my code I have a function that takes a Control object as input and here my code from the MyButton class is not being used.
MyButton btn1 = new MyButton();
btn1.Size = new Size(100, 100);
btn.Location = new Point(100, 100);
// ^ this works great and the button is the right size
public void ControlFormatter(Control control) {
control.Size = new Size(100, 100);
control.Location = new Point(100, 100);
}
MyButton btn2 = new MyButton();
ControlFormatter(btn2);
// ^ this doesn't work
Using the Console.WriteLine("running") print statement that I put in MyButton.Location.Set, I can tell that when control.Location is called inside ControlFormatter() the code that I wrote is not run (I can only assume that it is using the default Control.Location property and thus making the buttons the wrong size.
I guess I'm asking two things
Is there an easier/better/cleaner way to make the buttons the right size?
How can I make it so that ControlFormatter() uses MyButton.Size when it can and not Control.Size?
Thanks, also I'm fairly new to C# so grace is appreciated.
I opted for the quicker and dirtier fix of testing whether or not the Control was a Button in my ControlFormatter() function.
public void ControlFormatter(Control control) {
int width = 100;
int height = 100;
if (control is Button) {
width -= 2;
height -= 2;
}
control.Size = new Size(width, height);
control.Position = new Point(); // you get the jist
}
I am working on a simple Windows Forms application which consists of a Panel where I draw graphics with Graphic. Let's say, my panel is now of size 300x300 but the content inside is 500x500. Obviously, I need to add scrollbars to the Panel.
My code so far:
public CircuitControl()
{
// Initialize empty list of circuit objects
CircuitObjects = new List<CircuitObject>();
drawingAreaPanel.AutoScroll = true;
drawingAreaPanel.VerticalScroll.Enabled = true;
drawingAreaPanel.VerticalScroll.Visible = true;
drawingAreaPanel.HorizontalScroll.Enabled = true;
drawingAreaPanel.MaximumSize = new Size(300, 300);
drawingAreaPanel.Size = new Size(600, 600);
}
But none of these codes create actually a scroll bar. My question is: Where and how do I set the size of the Panel where I actually drew? I think this is the part which is missing. Thanks.
The scrollbars won't show up until there's actually something in the Panel that you can't see all of.
Try placing a larger control, such as a PictureBox, inside the Panel, and setting the PictureBox's initial size as larger than the Panel.
Just add:
drawingAreaPanel.AutoScroll = true;
And it will be done automatically.
€dit: Don't forget to set the anchors in order to get the scrollbars.
A clean and simple approach is to set AutoScrollMinSize. This shows the scrollbars (or just one if you leave the other value at 0).
Now drawing through the graphics object will not be scrolled automatically.
This can be easily achieved with a transformation matrix, which is set before painting and translates the drawing by the scroll offset.
A pretty example: (this flickers of course without further optimizations)
private void button1_Click(object sender, EventArgs e)
{
using(Form frm = new Form())
{
Panel pnl = new Panel();
pnl.Paint += delegate (Object snd, PaintEventArgs e2) {
Matrix mtx = new Matrix();
mtx.Translate(pnl.AutoScrollPosition.X, pnl.AutoScrollPosition.Y);
e2.Graphics.Transform = mtx;
e2.Graphics.Clear(Color.Black);
for(int i=0; i <= 125; i++)
for(int j=0; j <= 125; j++)
using(Brush b = new SolidBrush(Color.FromArgb(255, 255-i*2, j*2, (i*j) % 255)))
e2.Graphics.FillRectangle(b, new Rectangle(5+j*20, 5+i*20, 20, 20));
};
pnl.AutoScrollMinSize = new Size(126*20+10, 126*20+10);
pnl.Dock = DockStyle.Fill;
frm.Controls.Add(pnl);
frm.Padding = new Padding(25);
frm.ShowDialog(this);
}
}
I have a winform that starts out with a sizable border around it. On the form is a button which, when pressed, changes the form to border style none.
The problem is that then the inner part of the form moves up and to the left slightly. I want to make it that, no matter what border is used, the "inner" part of the form will always stay in the same spot (note: but I do still want the form to be moved around when it has a movable border selected)
Thanks.
The Borderless form moves up and slightly left because thats the location that the form currently has,you need to count for the border.To achieve the result you are after you need to reassign the location property and to do that you need to account for the client size and the whole size(with border),the code i think is simple and it will be self-explanatory i believe:
private void button1_Click(object sender, EventArgs e)
{
var X = (this.Size.Width - this.ClientRectangle.Width) / 2;
var Y = (this.Size.Height - this.ClientRectangle.Height) - X;
Point p = new Point(Location.X + X, Location.Y + Y);
this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.None;
this.Location = p;
}
Another option is to set the padding on the parent that contains the panel with the border. E.g.
public class Form10 : Form {
Button btn = new Button { Text = "Button", Location = new Point(100, 100) };
Panel border = new Panel { Dock = DockStyle.Fill, BorderStyle = BorderStyle.Fixed3D };
public Form10() {
Controls.Add(border);
border.Controls.Add(btn);
btn.Click += delegate {
if (border.BorderStyle == BorderStyle.Fixed3D) {
border.BorderStyle = BorderStyle.None;
border.Parent.Padding = new Padding(2);
}
else {
border.BorderStyle = BorderStyle.Fixed3D;
border.Parent.Padding = new Padding(0);
}
};
}
}
I'm making instrument to select part of image. I have PictrureBox, and simple way to make it :
void StartPanel(object sender, MouseEventArgs args)
{
xStart = args.X;
yStart = args.Y;
panelStarted = true;
pan.Location = new Point(xStart, yStart);
}
void FinishPanel(object sender, MouseEventArgs args)
{
xFinish = args.X;
yFinish = args.Y;
panelStarted = false;
}
void UpdatePanel(object sender, MouseEventArgs args)
{
if (panelStarted)
{
int x = args.X;
int y = args.Y;
int newxstart = xStart;
int newystart = yStart;
int neww = 0;
int newh = 0;
if (x >= xStart)
neww = x - xStart;
else
{
neww = xStart - x;
newxstart = x;
}
if (y >= yStart)
newh = y - yStart;
else
{
newh = yStart - y;
newystart = y;
}
pan.Size = new Size(neww, newh);
pan.Location = new Point(newxstart, newystart);
}
}
When I move mouse right and down, it is absolutely ok. But when I move it left or up I can see blinks at my area. So I have understood, that it is because when I move mouse left or up, my panel is redrawed, because Panel.Location is changed, and when I move mouse right and down, location is not changed, only size is changed, so it is not redrawed, just some pixels are added to panel. What is standart solution for this?
It's not easy trying to see what you are trying to do, but I guess you are using a panel as a draggable control to drag over the picturebox surface capturing the portion of image below (like a lens) - yes?
If so, then this is not the best way to do it. It is better to just draw a rectangle on the picturebox surface and "drag" that around - this is simple with just using the mouse events to sets the top left corner and use the onpaint to draw the unfilled rectangle over the image. Capturing the image when you are ready is simple too using whatever event you wish, then copy the image giving the same positions to the new bitmap.
Putting one control over another often causes flickers - even with double buffering. It also takes far more code.
Since you are describing a drawing issue when resizing the panel, probably the easiest fix is to replace the panel you are using with one that is double buffered and will invalidate on resize a event:
public class BufferedPanel : Panel {
public BufferedPanel() {
this.DoubleBuffered = true;
this.ResizeRedraw = true;
}
}