La batallita del agüelo (introducción que dirían otros):
Este código surge a raíz de una consulta en los grupos de noticias de
Microsoft (de Visual Basic .NET), y como resulta que no tenía yo este de rotar
imágenes, pues me he decidido a publicar "el truco".
El tema que contiene este artículo es: Trocear imágenes, y te lo explico
tanto para Visual Basic como para Visual C#, yo he usado el Visual Studio
2008 para crear los proyectos, pero al menos con Visual Studio 2005 debe
funcionar sin problemas, y es posible que también en las versiones
anteriores, pero no lo he comprado, así que... no me arriesgo a
asegurártelo.
El código también contiene cómo seleccionar un fichero y asignarlo al
control PictureBox, además de poder cargar el fichero indicado en la caja de
textos cuando se pulsa la tecla INTRO (o si lo prefieres ENTER), sobre esto,
decirte que he tenido que usar el evento KeyUp en lugar del "previsto", es
decir, el KeyPress, pero este último decía que nones, es decir, que como si
hablaras con la pared, vamos, que ni puñetero caso me hacía, así que...
antes de complicarme la vida, corté por lo sano y he usado el evento KeyUp (podría
haber usado el evento KeyDown, pero... cosas de tener que elegir, es decir,
o elegía el evento KeyUp o elegía el evento KeyDown, y he elegido el KeyUp,
no me preguntes porqué, simplemente porque ese es el que suelo usar... ¡yo
que se porqué! ¿qué importa? nada ¿verdad? pues eso...).
Este código usa los valores de configuración (Settings) en particular dos
valores, uno para saber el nombre del último fichero asignado al control
PictureBox y el otro para saber qué tipo de rotación hemos usado por última
vez.
En el código de Visual Basic uso el objeto My.Settings, sin embargo en
C#, como no está tan accesible, ya que hay que escribir
Properties.Settings.Default, que aunque no es mucho más, pues...
costumbres... Total, que he echado mano del código ese que tengo sobre
cómo "simular" el
objeto My de VB desde C# y lo he usado. He modificado un poco el código
mostrado en la página esa del link anterior, más que nada para incluir bien
las importaciones de los espacios de nombres y esas cosas, así que... te
recomiendo que uses el código que te he puesto más abajo:
El código del objeto My (versión para C#) (a ver si me
acuerdo y pongo una actualización en el otro artículo).
La aplicación de ejemplo
En la figura 1 tienes el formulario en tiempo de diseño, que
como puedes ver es muy simple:
Una caja de textos (txtFic) para el nombre del fichero a
mostrar, un botón (btnExaminar) para seleccionar el fichero a
mostrar, un PictureBox (pic) para mostrar la imagen, tres
RadioButtons (optRotarIzq, optRotarDer y optRotarLibre) para
diferentes opciones de rotación y un botón para rotar la imagen
(btnRotar).
Figura 1. El formulario en modo diseño
En la figura 2 tienes una captura del programa en tiempo de ejecución,
con la imagen rotada un par de veces a la izquierda (cada vez que pulsas se
va rotando 90º):
Figura 2. El programa en tiempo de ejecución
Y no hay mucho más que contar, el código lo tienes abajo y ya
sabes que está tanto para Visual Basic 2005 (o
superior) como para Visual C# 2005 (o
superior).
Y si no tienes ganas de teclear (en realidad solo tendrías
que copiar y pegar), pero bueno, para que te resulte más cómodo,
más abajo tienes el ZIP con los dos proyectos
para usar con Visual Studio 2008, también valdrá para las
versiones Express de Visual Basic 2008 o Visual C# 2008.
Espero que te sea de utilidad.
Nos vemos.
Guillermo
P.S.
El código está coloreado
con mi utilidad gsColorearCodigo.
La imagen mostrada en la figura 2 es del anuncio de mi libro y la petición de
ayuda a Juanma
publicado en el periódico local de Nerja (y Maro) InfoAquí (o InfoNerja, como
prefieras).
El código para Visual Basic .NET (Visual Basic 2005 o superior)
'------------------------------------------------------------------------------
' rotarImagenes_VB (26/Abr/08)
'
' ©Guillermo 'guille' Som, 2008
'------------------------------------------------------------------------------
Option Strict On
Imports Microsoft.VisualBasic
Imports System
Imports System.Windows.Forms
Imports System.Drawing
Public Class Form1
Private inicializando As Boolean = True
Private Sub Form1_Load(ByVal sender As Object, _
ByVal e As EventArgs) _
Handles MyBase.Load
pic.SizeMode = PictureBoxSizeMode.StretchImage
txtFic.Text = My.Settings.txtPic
' Si existe la imagen, cargarla
If System.IO.File.Exists(txtFic.Text) Then
pic.Load(txtFic.Text)
End If
Select Case My.Settings.optRotar
Case -1
optRotarIzq.Checked = True
optRotarDer.Checked = False
optRotarLibre.Checked = False
Case 0
optRotarIzq.Checked = False
optRotarDer.Checked = True
optRotarLibre.Checked = False
Case Else
optRotarIzq.Checked = False
optRotarDer.Checked = False
optRotarLibre.Checked = True
End Select
inicializando = False
End Sub
Private Sub optRotarIzq_CheckedChanged(ByVal sender As Object, _
ByVal e As EventArgs) _
Handles optRotarIzq.CheckedChanged, _
optRotarDer.CheckedChanged, _
optRotarLibre.CheckedChanged
' Este evento se produce al asignar el valor inicial
' y si eso ocurre, no vale de nada el valor de Settings
If inicializando Then Exit Sub
Select Case True
Case optRotarIzq.Checked
My.Settings.optRotar = -1
Case optRotarDer.Checked
My.Settings.optRotar = 0
Case Else
My.Settings.optRotar = 1
End Select
End Sub
Private Sub txtFic_KeyUp(ByVal sender As Object, _
ByVal e As KeyEventArgs) _
Handles txtFic.KeyUp
If e.KeyCode = Keys.Return Then
e.Handled = True
' Si existe la imagen, cargarla
If System.IO.File.Exists(txtFic.Text) Then
pic.Load(txtFic.Text)
End If
End If
End Sub
Private Sub btnExaminar_Click(ByVal sender As Object, _
ByVal e As EventArgs) _
Handles btnExaminar.Click
Dim ofd As New OpenFileDialog
With ofd
.FileName = txtFic.Text
.Filter = "Imágenes|*.jpg;*.png;*.gif;*.bmp|Todos (*.*)|*.*"
If .ShowDialog = DialogResult.OK Then
txtFic.Text = .FileName
My.Settings.txtPic = txtFic.Text
pic.Load(.FileName)
End If
End With
End Sub
Private Sub btnRotar_Click(ByVal sender As Object, _
ByVal e As EventArgs) _
Handles btnRotar.Click
Dim bmp As Image = pic.Image
If optRotarIzq.Checked Then
bmp.RotateFlip(RotateFlipType.Rotate90FlipXY)
ElseIf optRotarDer.Checked Then
bmp.RotateFlip(RotateFlipType.Rotate270FlipXY)
Else
bmp.RotateFlip(RotateFlipType.Rotate90FlipNone)
End If
pic.Image = bmp
End Sub
End Class
El código para C# (Visual C# 2005 o superior)
//-----------------------------------------------------------------------------
// rotarImagenes_CS (26/Abr/08)
//
// ©Guillermo 'guille' Som, 2008
//-----------------------------------------------------------------------------
using System;
using System.Drawing;
using System.Windows.Forms;
namespace rotarImagenes_CS
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private bool inicializando = true;
private void Form1_Load(object sender, EventArgs e)
{
pic.SizeMode = PictureBoxSizeMode.StretchImage;
txtFic.Text = My.Settings.txtPic;
// Si existe la imagen, cargarla
if(System.IO.File.Exists(txtFic.Text))
{
pic.Load(txtFic.Text);
}
switch(My.Settings.optRotar)
{
case -1:
optRotarIzq.Checked = true;
optRotarDer.Checked = false;
optRotarLibre.Checked = false;
break;
case 0:
optRotarIzq.Checked = false;
optRotarDer.Checked = true;
optRotarLibre.Checked = false;
break;
default:
optRotarIzq.Checked = false;
optRotarDer.Checked = false;
optRotarLibre.Checked = true;
break;
}
inicializando = false;
}
private void Form1_FormClosing(object sender, FormClosingEventArgs e)
{
My.Settings.Save();
}
private void optRotarIzq_CheckedChanged(object sender, EventArgs e)
{
// Este evento se produce al asignar el valor inicial
// y si eso ocurre, no vale de nada el valor de Settings
if(inicializando) return;
if(optRotarIzq.Checked)
{
My.Settings.optRotar = -1;
}
else if(optRotarDer.Checked)
{
My.Settings.optRotar = 0;
}
else
{
My.Settings.optRotar = 1;
}
}
private void txtFic_KeyUp(object sender, KeyEventArgs e)
{
// Si se pulsa INTRO
if(e.KeyCode == Keys.Return)
{
e.Handled = true;
// Si existe la imagen, cargarla
if(System.IO.File.Exists(txtFic.Text))
{
pic.Load(txtFic.Text);
}
}
}
private void btnExaminar_Click(object sender, EventArgs e)
{
OpenFileDialog ofd = new OpenFileDialog();
ofd.FileName = txtFic.Text;
ofd.Filter = "Imágenes|*.jpg;*.png;*.gif;*.bmp|Todos (*.*)|*.*";
if(ofd.ShowDialog() == DialogResult.OK)
{
txtFic.Text = ofd.FileName;
My.Settings.txtPic = txtFic.Text;
pic.Load(ofd.FileName);
}
}
private void btnRotar_Click(object sender, EventArgs e)
{
Image bmp = pic.Image;
if(optRotarIzq.Checked)
{
bmp.RotateFlip(RotateFlipType.Rotate90FlipXY);
}
else if(optRotarDer.Checked)
{
bmp.RotateFlip(RotateFlipType.Rotate270FlipXY);
}
else
{
bmp.RotateFlip(RotateFlipType.Rotate90FlipNone);
}
pic.Image = bmp;
}
}
}
//-----------------------------------------------------------------------------
// rotarImagenes_CS (26/Abr/08)
//
// Simular (en parte) el objeto My de Visual Basic 2005 (o superior)
//
// ©Guillermo 'guille' Som, 2008
//-----------------------------------------------------------------------------
using System;
using System.Reflection;
using System.Diagnostics;
namespace rotarImagenes_CS
{
// My.Settings y My.Application.Info
static class My
{
// My.Settings
public static Properties.Settings Settings
{
get
{
return Properties.Settings.Default;
}
}
// My.Application.Info
public static class Application
{
public static class Info
{
static FileVersionInfo fvi;
static Assembly ensamblado;
static AssemblyName an;
static Info()
{
ensamblado = Assembly.GetExecutingAssembly();
fvi = FileVersionInfo.GetVersionInfo(ensamblado.Location);
an = ensamblado.GetName();
}
/// <summary>
/// La versión del ensamblado
/// Equivale al atributo AssemblyVersion
/// </summary>
public static Version Version
{
get
{
return an.Version;
}
}
/// <summary>
/// La versión del ensamblado (FileVersion)
/// equivale al atributo: AssemblyFileVersion
/// </summary>
public static Version FileVersion
{
get
{
return new Version(fvi.FileVersion);
}
}
public static string Title
{
get
{
return fvi.FileDescription;
// antes mostraba esto: fvi.ProductName;
}
}
public static string Copyright
{
get
{
return fvi.LegalCopyright;
}
}
public static string ProductName
{
get
{
return fvi.ProductName;
}
}
public static string CompanyName
{
get
{
return fvi.CompanyName;
}
}
public static string Trademark
{
get
{
return fvi.LegalTrademarks;
}
}
public static string Description
{
get
{
return fvi.Comments;
}
}
}
}
}
}
Espacios de nombres usados en el código de este artículo:
System.Drawing
System.Windows.Forms
System.Reflection
System.Diagnostics
System.IO