OR - How To Shave A Koala To Stop It Looking Squashed. (But I didn't think that would make a suitably techy title)
The Problem: You have three preview images derived from a main image. The preview images are resized for standardised picture spaces on a company website, the main image can be any size image from anywhere.
Example: The main image is a hi-res image of a koala bear measuring 2000x2250. Your previews want to render the koala at 200x200, 200x50 and 250x150.
Your utility program resizes and stretches the original image to the size of your three "actual size" previews but obviously each preview looks a bit squashy and you know everyone hates to see a squashed koala.
To resolve this you add a little cropping method to your program which shaves five pixels from the preview on the desired side. This means you should be able to resize your image and unsquash your koala by shaving off the unnecessary parts of the image.
You add four buttons to each preview image picture box and create four generic methods for sending the correct shaving instructions to the crop method. You want to associate each specific button with a specific picturebox on the form, but you want to send all the click events to four generic functions.
How do you tell the generic function which of the three preview picturebox images you want it to shave in an elegant and wonderful way?
Example Code:
//cropPict=method for cropping the picture in the relevant picturebox.
//CropSide=a little enum which tells the method which side to crop.
private void btnT_Click(object sender, EventArgs e)
{
cropPict(/*Reference to PictureBox Goes Here*/, CropSide.Top);
}
private void btnB_Click(object sender, EventArgs e)
{
cropPict(/*Reference to PictureBox Goes Here*/, CropSide.Bottom);
}
private void btnR_Click(object sender, EventArgs e)
{
cropPict(/*Reference to PictureBox Goes Here*/, CropSide.Right);
}
private void btnL_Click(object sender, EventArgs e)
{
cropPict(/*Reference to PictureBox Goes Here*/, CropSide.Left);
}
EDIT: As it happens, inspired by Hans below, rather than just stuffing the PictureBox into the tag. Which was a great idea I actually put a KeyValuePair into the tag for each button like so:
btnCCB.Tag = new KeyValuePair<CropSide,PictureBox>(CropSide.Bottom,pbxKoala);
btnCCL.Tag = new KeyValuePair<CropSide, PictureBox>(CropSide.Left, pbxKoala);
btnCCR.Tag = new KeyValuePair<CropSide, PictureBox>(CropSide.Right, pbxKoala);
btnCCT.Tag = new KeyValuePair<CropSide, PictureBox>(CropSide.Top, pbxKoala);
Then I could just wire all the buttons up to a single event handler like so:
private void btnC_Click(object sender, EventArgs e)
{
Button btnSend = (Button)sender;
KeyValuePair<CropSide, PictureBox> kvCrop = (KeyValuePair<CropSide, PictureBox>)btnSend.Tag;
cropPict(kvCrop.Value,kvCrop.Key);
}
Of course, there's still plenty more to do but that pretty much sorted out my problem. Thanks Hans!
Use the Button.Tag property to store a reference to its associated PictureBox. Cast sender to Button:
public Form1()
{
InitializeComponent();
button1.Tag = pictureBox1;
button1.Click += btnT_Click;
// etc..
}
private void btnT_Click(object sender, EventArgs e)
{
var btn = (Button)sender;
cropPict((PictureBox)btn.Tag, CropSide.Top);
}
Related
I'm making a text editor, and it will have the ability to be resized. However when it is resized the close button along with a few other buttons at the top are kinda stuck in the middle. I would like to do something like this.
Ex.
private void Size_Change(object sender, EventArgs e) // Event after maximize or restore
{
Close_Button.Location = Width - (width of button);
}
what is a method of doing getting the width of a form and then subtracting from that width?
Just use anchor points on the button. Like Sani Singh Huttunen said. It's located in the properties of the button.
That way it will be resized or relocated with the form
you need change "Location" to "Left" property:
private void Size_Change(object sender, EventArgs e)
{
Close_Button.Left = this.Width - Close_Button.Width;
}
or create new Point to Location property.
Visual Studio C #
I made a calculator, and now I have to make a calculator memory (event).
There are 4 components other than the calculator: one Textbox for the answer of the calculator, two Buttons for "M" and "M+", and one Lable to display the answer again.
When the user clicks the “M” button, the contents of the Answer TextBox should be copied to a memory variable. Also make it so that when the user moves the mouse over the label, the value in the memory variable will appear in this label, and then disappear, when the mouse moves away from the label. Also add one more button, an “M+” button. When the user clicks this button, the contents of the Results box will be added to Memory. You will need to use a Global Variable to store this data.
My problem is that the label doesn't appear when the mouse over the label, and also it doens't disappear when the mouse leave the label. How can I fix it?
And also, is this way the right way to use the Global variable?
Below is my code (I just put the code for "M" and "M+" buttons, not the code for the calculator).
private String ans;
private Double answer;
private Double answerPlus;
private void btnM_Click(object sender, EventArgs e)
{
ans = txtDisplay.Text;
answer = double.Parse(ans);
lblblank.Text = answer.ToString();
}
private void lblblank_MouseEnter(object sender, EventArgs e)
{
lblblank.Show();
lblblank.Text = answer.ToString();
}
private void lblblank_MouseLeave(object sender, EventArgs e)
{
lblblank.Hide();
}
private void btnMplus_Click(object sender, EventArgs e)
{
answerPlus = answer + double.Parse(ans);
lblblank.Text = answerPlus.ToString();
}
Storing variables
The way you store your values is fine.
Events
Once you call .Hide() the next MouseEnter/MouseLeave-event will not be triggered anymore. What you could do is to take a panel, or any layout element as a wrapper/parent-element for the label and then adjust your event-callbacks to something like that:
private void panel_MouseEnter(object sender, EventArgs e)
{
lblblank.Show();
lblblank.Text = answer.ToString();
}
private void panel_MouseLeave(object sender, EventArgs e)
{
lblblank.Hide();
}
Edit
~~~
What does it mean that any layout element as a parent-element for the
label? Could you explain more?
What I meant was to just create a new panel (or layout-element) and put the label into it as a child. See the picture below:
If you set that up correctly, the code snippet I posted above will work just fine. This solution does not prevent the MouseLeave event from triggering when your mouse enters the label. Therefore you could use an alternative solution using the MouseMove event.
Alternative
using System;
using System.Windows.Forms;
using System.Drawing;
namespace WindowsFormsApp1
{
public partial class Form1 : Form
{
public Form1()
{
this.InitializeComponent();
// Subscribe to the MouseMove event
this.panel.MouseMove += this.panel_MouseMove;
}
private void panel_MouseMove(object sender, MouseEventArgs e)
{
// Checks if current mouse position is within the panel
if (this.panel.Bounds.Contains(new Point(e.X, e.Y)))
{
// Current mouse position within the panel
this.label.Show();
return;
}
// Current mouse position outside the panel
this.label.Hide();
}
}
}
I'm programing a little C# program for browsing pictures, but I got stuck.
I have a Panel full of PictureBoxes, is there any way to calculate number of the PictureBoxes that were clicked on? For example, if I have a ListBox I can easily type listBox1.SelectedIndex and get the number.
I assume that it's not that easy with Panel, but is there actually any way to do this?
It depends on what you actually want to do. There is no built-in property of PictureBoxes that make or mark them selected.
You can get the index of the PictureBox in the Panel's Controls collection in its Click event like this:
private void pictureBox_Click(object sender, EventArgs e)
{
int index = yourPanel.Controls.IndexOf(sender as PictureBox );
}
You can and probably should assign the same event to all PBs' Clicks!
If you simply want to work with the PictureBox write
PictureBox pb = sender as PictureBox;
pb.Image = ...
Or you could loop over the Controls to find one with Focus. But even if it was there that would only be the keyboard focus, and, as there can only be one, this would not persist even a single Button click.. So this is not recommended.
So if you want to refer to the last clicked PB simply store it in a class variable or maybe in the Panel's Tag:
PictureBox selectedPB = null;
private void pictureBox_Click(object sender, EventArgs e)
{
selectedPB = sender as PictureBox;
// or
yourPanel.Tag = sender as PictureBox;
}
If you want to collect several PBs you can do so by adding them to a List:
List<PictureBox> clickedBoxes = new List<PictureBox>();
private void pictureBox_Click(object sender, EventArgs e)
{
PictureBox pb = sender as PictureBox;
if (!clickedBoxes.Contains(pb) ) clickedBoxes.Add(pb);
}
and access the number as the clickedBoxes.Count ..
Try using the 'SelectedItem' property of your ListBox and bind it to a property on the ViewModel.
If you are using just something like StackPanel? Then no, StackPanel does not have this functionality built in. Use a ListBox with a custom Template.
i was trying to implemet an image button in winforms application as i can ...easy when using asp.net
the problem seem to be(i suspect) that when the mouse is over the image inside the picturebox
it is not responding or not triggering the mouseEnter event
it looks like if i had a picture that is smaller than the pictureBox Size it will accept the reason to trigger the event but over the image within the pictureBox it would Not ?
the trick was to set pictureBox to sizeMode=zoom. then do 2 things when the mouse is over the "imageButton" : change the size of PictureBox a little larger + change cursor to hand
so i will get a kind of mouse over effect as i could with asp.net
did anyone have that problem ?
at first i tried mouseHover, then i thought enter would do better as it only requiers the mouse to pass the borders of the picture box... both enter and hover events did not work for me ...
Edit :
the event does trigger , i can see that if i initially set sizemode to CenterImage and inside the event
i ask for sizemode=zoom, so the effect dose occur ..but cursor.current=Cursors.Hand will not change.
This should work
private void pictureBox1_MouseEnter(object sender, EventArgs e)
{
pictureBox1.SizeMode = PictureBoxSizeMode.StretchImage;
pictureBox1.Cursor = Cursors.Hand;
}
private void pictureBox1_MouseLeave(object sender, EventArgs e)
{
pictureBox1.SizeMode = PictureBoxSizeMode.Zoom;
pictureBox1.Cursor = Cursors.Default;
}
seem like i should have known better how to use Cursors class .
cursor=Cursors.hand;
rather than
cursor.current=Cursors.hand;
that was embarrassing ..
only add MouseMove event on pictureBox and set a Cursor for this
private void pictureBox1_MouseMove(object sender, MouseEventArgs e)
{
pictureBox1.Cursor = Cursors.Hand;
}
Regarding .Net technology,What will be the basic element of a picture viewer(like Windows Picture and Fax Viewer)? Is it a user control inside a form, or is it something other components. Could you please give me an idea in the context of C#.Net
You don't really get one that's bundled into .NET Framework (and that's probably a good thing, it's fairly large already).
If using WinForms, the nearest thing you do get is the PictureBox component, and the BackgroundImage property of some other components like Form and Panel. But you have to implement the rest of the functionality of an image viewer yourself.
WPF certainly has its own equivalents but I can't name them off the top of my head.
for making picture viewer is better to have PictureBox to show Pictures, ImageList to hold list of images due to have more that one picture and also two buttons for next pictur and previews picture.
a simple code which I suggest is as follow:
private void btnLoadImage_Click(object sender, EventArgs e)
{
imageList1.Images.Clear();
if (openFDialogImage.ShowDialog() == DialogResult.OK)
{
for (int i = 0; i < openFDialogImage.FileNames.Length; i++)
{
imageList1.Images.Add(Image.FromFile(openFDialogImage.FileNames[i]));
}
pictureBox1.Image = imageList1.Images[currentIndex];
}
}
private void BtnForward_Click(object sender, EventArgs e)
{
if(currentIndex!=imageList1.Images.Count-1 && imageList1.Images.Count > 0)
{
pictureBox1.Image = imageList1.Images[currentIndex++];
}
}
private void btnBack_Click(object sender, EventArgs e)
{
if (currentIndex!=0)
{
pictureBox1.Image = imageList1.Images[--currentIndex];
}
}
Thats all, :)