views:

52

answers:

1

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!

+3  A: 

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);
}
Hans Passant
I like this. I was hacking together a variation on this theme but this is better.
One Monkey
Looks pretty good to me to, you could get away with just 4 event handlers.
asawyer
The bit that does it for me is that I was adding the control id to the tag and implementing a "find control" method. Just storing the actual control in the button's tag makes things much simpler.
One Monkey
@one - sounds like you're motoring. Don't forget to close your question by marking the answer.
Hans Passant
As soon as I've implemented it, which should be in about twenty minutes I certainly will!
One Monkey