Seleccionar una Region - GDI+

21/09/2004 - 02:05 por Mark | Informe spam
Como hago para seleccionar un region (c-sharp) que se encuentra dibujada en
el formulario.
Deseo mostrar visualmente que la región esta seleccionada, para luego
poderlo arrastrar y moverlo en otra posición del formulario.
Espero que me puedan ayudar en esto.
Saludos
 

Leer las respuestas

#1 Angel J. Hernández
28/09/2004 - 15:58 | Informe spam
Saludos Mark, a continuación te paso un código que acabo de hacer para
explicarte como podrías hacerlo. Aunque el mismo
funciona tiene un par de detalles ;-) (los menciono adelante)

// Necesario para PInvoke
using System.Runtime.InteropServices;

// Declaro estos miembros
private Rectangle m_rectangle = Rectangle.Empty;
private bool m_iscapturing;
private Point m_originalpt = Point.Empty;
private System.Windows.Forms.PictureBox pictureBox1;
private Point m_workingpt = Point.Empty;

// En el constructor coloco lo siguiente para disminuir el
"parpadeo" de la pantalla cuando esté seleccionando la región
SetStyle(ControlStyles.AllPaintingInWmPaint |
ControlStyles.UserMouse, true);

// Establezco una imagen de fondo del formulario, sobre esta voy a
"recortar" (Recuerda
// cambiar el nombre del archivo)
private void Form1_Load(object sender, System.EventArgs e) {
BackgroundImage=
Image.FromFile(System.IO.Path.GetDirectoryName(Application.ExecutablePath)+
@"\DarthMaul.jpg");
}

// Código del evento MouseDown
private void Form1_MouseDown(object sender,
System.Windows.Forms.MouseEventArgs e) {
if (e.Button.Equals(MouseButtons.Left)) {
APICalls.SetCapture(Handle);
m_iscapturing = true;
m_originalpt.X= e.X;
m_originalpt.Y = e.Y;
}
}

// Código del evento MouseMove
private void Form1_MouseMove(object sender,
System.Windows.Forms.MouseEventArgs e) {
if (e.Button.Equals(MouseButtons.Left) && m_iscapturing) {
m_workingpt.X = e.X;
m_workingpt.Y = e.Y;

m_rectangle = new Rectangle(m_originalpt, new
Size(m_workingpt));
Invalidate(m_rectangle);
}
}


// Código del evento MouseUp
private void Form1_MouseUp(object sender,
System.Windows.Forms.MouseEventArgs e) {
if (e.Button.Equals(MouseButtons.Left) && m_iscapturing) {
pictureBox1.Image = null;
Graphics graph = Graphics.FromHwnd(Handle);
Region rgn = new Region(m_rectangle);
graph.SetClip(rgn, CombineMode.Exclude);
IntPtr hdc = graph.GetHdc();
IntPtr dchandle = APICalls.CreateCompatibleDC(hdc);
IntPtr bmphandle = APICalls.CreateCompatibleBitmap(hdc,
m_rectangle.Width, m_rectangle.Height);
IntPtr select = APICalls.SelectObject(dchandle, bmphandle);
int success = APICalls.BitBlt(dchandle, m_rectangle.X,
m_rectangle.Y, m_rectangle.Width,
m_rectangle.Height,
hdc, 0, 0, 13369376); // SRCCOPY

Image imagen = Bitmap.FromHbitmap(bmphandle); // Obtenemos
el bitmap a partir de su handle

try {
rgn.Dispose();
graph.Dispose();
} catch {}

pictureBox1.Image = imagen;

APICalls.ReleaseCapture();
m_iscapturing = false;
m_workingpt = Point.Empty;
m_originalpt = Point.Empty;
m_rectangle = Rectangle.Empty;
Invalidate();
}
}


// Código del evento Paint
private void Form1_Paint(object sender,
System.Windows.Forms.PaintEventArgs e) {
Graphics g = e.Graphics;

if (m_iscapturing) g.DrawRectangle(Pens.Blue, m_rectangle);
}


Necesitamos hacer llamadas al API por lo que todas las funciones usadas
las "encapsulamos" en una clase la cual
muestro a continuación:

class APICalls {
[DllImport("User32.dll")]
public static extern IntPtr SetCapture(IntPtr hWnd);

[DllImport("User32.dll")]
public static extern bool ReleaseCapture();

[DllImport("Gdi32.dll")]
public static extern IntPtr CreateCompatibleDC(IntPtr hdc);

[DllImport("Gdi32.dll")]
public static extern IntPtr CreateCompatibleBitmap(IntPtr hdc, int
width, int height);

[DllImport("Gdi32.dll")]
public static extern IntPtr SelectObject(IntPtr hdc, IntPtr
hgdiobj);

[DllImport("Gdi32.dll")]
public static extern int BitBlt(IntPtr hdcdest, int nxdest, int
nydest, int nwidth,
int nheight, IntPtr
hdcsrc, int nxsrc, int nysrc, int raster);
}

Pues bien... este programa carga inicialmente una imagen que posteriormente
puedo seleccionar con el ratón alguna
área y copiarla mostrando la copia en un PictureBox. Los dos detalles que
presenta (no me dió tiempo de hacerlo ;-)
es el cálculo del área seleccionada así como el rectángulo de selección
(este lo hace a medias) del resto todo creo que
cumple con lo que necesitas. Las funciones importadas del API son:

SetCapture: Establece la captura del ratón a la ventana especificada que
pertenezca al hilo o proceso actual. Solo una ventana a la vez puede
capturar el ratón.

ReleaseCapture: Libera la captura del ratón y comienza a procesar los
mensajes del mismo normalmente.

CreateCompatibleDC: Crea un dispositivo de contexto (DC) en memoria
compatible con el dispositivo especificado

CreateCompatibleBitmap: Crea un Bitmap compatible con el dispositivo
asociado con el dispositivo de contexto asociado.

SelectObject: Selecciona un objeto en el dispositivo de contexto (DC)
especificado. El nuevo objeto reemplaza al objeto anterior del mismo tipo.

BitBlt: Realiza una transferecia de bloque-bit de datos del color
correspondiente a un rectángulo de píxeles del dispositivo de origen al
destino.

La imagen es creada a partir un handle obtenido. Sin embargo necesitamos
obtener el HDC del objeto graph dentro del evento Paint pues a partir de ahí
podemos obtener los demás valores. En tu caso supongo que no deseas
mostrarlo en un PictureBox bueno deberías escribir ese código.

Espero que te sirva,

Angel J. Hernández M.
MCSD


"Mark" escribió en el mensaje
news:
Como hago para seleccionar un region (c-sharp) que se encuentra dibujada
en
el formulario.
Deseo mostrar visualmente que la región esta seleccionada, para luego
poderlo arrastrar y moverlo en otra posición del formulario.
Espero que me puedan ayudar en esto.
Saludos


Preguntas similares