Editor de Texto Fecha: 16/Jun/2005 (13/06/2005) E_Mail: [email protected] - [email protected] ¡¡ Los peruanos SÍ podemos !! |
Esta vez deseo presentarles un programilla que tiene la funcionalidad de un Editor de Texto. Debo decirles que el presente viene a constituir la versión beta; bueno, decidí llamarlo así debido a que "falta" agregar algunas funcionalidades muy básicas las cuales serán implementadas más adelante en la versión totalmente completada... ok.? Sin embargo, esta versión reune toda la funcionalidad para que usted pueda editar texto de una manera cómoda y amigable. Incluye funcionalidades que le permitirá, por ejemplo, copiar, pegar y cortar texto. Además, podrá abrir documentos txt y rtf, editarlos y guardar los cambios como también configurarlos e imprimirlos rápidamente.
Debo recomendarle que previamente debe conocer muchos conceptos sumamente importantes en la construcción de aplicaciones MDI y SDI. Bueno, si no entiende esto, no corra!...porque a continuación le explicaré estas cosillas. También debe conocer todo respecto a cuadros de diálogos comunes y el control RichTextBox, todo esto le explico a continuación.
Empezemos primero por entender que es una aplicación MDI y una aplicación SDI.
Utilizar el Patron Singleton con formularios MDI
En dias anteriores estaba creando una aplicación en la cual requería crear una sola instancia de los formularios hijos de una MDI padre. Buscando en la documentación de Microsoft encontré este Pattern llamado Singleton. Acá les muestro una sencilla implementación en formularios MDI para tener solamente una instancia abierta por formulario. Lo primero que hay que hacer es modificar el constructor del formulario hijo, o sea, el formulario que queremos que solo tenga una instancia en la aplicación. En este constructor inicialmente aparece como publico (public).
#Region " Windows Form Designer generated code " Public Sub New() MyBase.New() 'This call is required by the Windows Form Designer. InitializeComponent() 'Add any initialization after the InitializeComponent() call End Sub ..... Lo modificaremos y lo haremos privado (private) para evitar llamados a este formulario.#Region " Windows Form Designer generated code " Private Sub New() MyBase.New() 'This call is required by the Windows Form Designer. InitializeComponent() 'Add any initialization after the InitializeComponent() call End Sub .....Luego lo que haremos será crear una variable global en este mismo formulario hijo para que controle la instancia y la haremos shared para que pueda ser accesada desde el formulario padre. 'Variable global Private Shared frmInstance As frmReport = NothingFinalmente crearemos una función shared que será la que finalmente controlara la creación o manejo de la instancia del formulario, logrando obtener solo un formulario abierto para este form1.'Funcion que crea una sola instancia del form1 Public Shared Function Instance() As form1 If frmInstance Is Nothing OrElse frmInstance.IsDisposed = True Then frmInstance = New form1 End If frmInstance.BringToFront() Return frmInstance End Function Ahora en el padre escribiremos el llamado al hijo para crear la instancia, o si ya esta creada, entonces pondrá el formulario hijo en frente para que lo podamos ver.Dim frmHijo as form1 = form1.Instance frmHijo.MdiParent = Me frmHijo.ShowLas aplicaciones de interfaz con múltiples documentos (MDI) le permiten mostrar múltiples documentos al mismo tiempo con cada documento que aparece en su ventana propia. Las aplicaciones MDI con frecuencia tienen un elemento del menú de Windows con submenús para cambiar entre ventanas y documentos. El fundamento de una Aplicación con interfaz de múltiples documentos (MDI) es el formulario primario MDI. Este es el formulario que contiene las ventanas secundarias MDI, que son las "sub-ventanas" en donde el usuario interactúa con la aplicación MDI.
Para establecer un formulario como primario MDI, configure la propiedad IsMdiContainer = True.
Para crear un formulario secundario MDI nuevo tiene que configurar la propiedad a MdiParent.Las aplicaciones con interfaz de un único documento (SDI) están formadas por una o más ventanas independientes, cada una de las cuales aparece como ventana independiente en el escritorio de Windows. Microsoft Exchange es un ejemplo de una aplicación SDI, en la que cada mensaje que abra aparece en su propia ventana independiente.
VB .NET
… Protected Sub MDIChildNew_Click( _ ByVal sender As System.Object, _ ByVal e As System.EventArgs) Handles _ MenuItem2.Click Dim NewMDIChild As New Form2 'Configurar el Formulario primario de la Ventana secundaria. NewMDIChild.MdiParent = Me 'Mostrar el nuevo formulario. NewMDIChild.Show() End Sub ...C# .NET
... protected void MDIChildNew_Click(object sender, System.EventArgs e) { Form2 newMDIChild = new Form2(); // Set the Parent Form of the Child window. newMDIChild.MdiParent = this; // Display the new form. newMDIChild.Show(); } ... Bueno ya terminamos de explicar una parte. La otra parte se encargará usted de revisarla, para esto le recomiendo ver:
Espero que le haya sido de utilidad este programa que implementé. Bueno, me siento algo cansado y deseo descanzar, mañana debo continuar con mis actividades.
A continuación podemos ver los resultados de editar un documento (por cierto, es un mensaje para novia....jejejeje)
Observamos por ejemplo, la alineación de nuestras áreas de trabajo, previamente editado.
Ahora dejo a su disposición todo el código que hace posible obtener los beneficios de un editor de texto.
Imports System.Drawing.Drawing2D Public Class Form1 Inherits System.Windows.Forms.Form <STAThread()> Shared Sub main() Try Application.Run(New Form1) Catch ex As Exception MessageBox.Show("Error no controlado: " & ex.Message) End Try End Sub #Region "PintarMDI" Dim oControlMDI As MdiClient Public Sub FrmLoad(ByVal sender As Object, ByVal e As System.EventArgs) Dim oControl As Control For Each oControl In Me.Controls Try oControlMDI = CType(oControl, MdiClient) oControlMDI.BackColor = Color.AntiqueWhite AddHandler oControlMDI.Paint, AddressOf PintarFondoAreaCliente Catch ex As InvalidCastException End Try Next End Sub Private Sub PintarFondoAreaCliente(ByVal sender As Object, ByVal _ e As System.Windows.Forms.PaintEventArgs) Dim GradientePanel As New LinearGradientBrush(New RectangleF(0, 0, _ oControlMDI.Width, oControlMDI.Height), Color.Orange, Color.PapayaWhip, _ LinearGradientMode.ForwardDiagonal) e.Graphics.FillRectangle(GradientePanel, New RectangleF(0, 0, _ oControlMDI.Width, oControlMDI.Height)) End Sub Private Sub TfrmMain_Resize(ByVal sender As Object, ByVal e As System.EventArgs) _ Handles MyBase.Resize If Not (Me.oControlMDI Is Nothing) Then Me.PintarFondoAreaCliente(Me.oControlMDI, New PaintEventArgs(Me.oControlMDI.CreateGraphics, _ New Rectangle(Me.oControlMDI.Location, Me.oControlMDI.Size))) End If End Sub Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) _ Handles MyBase.Load FrmLoad(sender, e) Me.Size = New Size(800, 600) End Sub #End Region Public contador As Integer = 0 Private Sub MenuNuevo_Click(ByVal sender As System.Object, _ ByVal e As System.EventArgs) Handles MenuNuevo.Click If Me.ActiveMdiChild Is Nothing Then contador = 0 End If Dim oFrm As New FrmChild contador += 1 oFrm.MdiParent = Me oFrm.Text = "Documento de texto " & "[" & contador & "]" oFrm.StartPosition = FormStartPosition.CenterParent oFrm.Show() End Sub Private Sub MenuCascada_Click(ByVal sender As System.Object, _ ByVal e As System.EventArgs) Handles MenuCascada.Click Me.LayoutMdi(MdiLayout.Cascade) End Sub Private Sub MenuMHorizontal_Click(ByVal sender As System.Object, _ ByVal e As System.EventArgs) Handles MenuMHorizontal.Click Me.LayoutMdi(MdiLayout.TileHorizontal) End Sub Private Sub MenuMVertical_Click(ByVal sender As System.Object, _ ByVal e As System.EventArgs) Handles MenuMVertical.Click Me.LayoutMdi(MdiLayout.TileVertical) End Sub Private Sub VistaPrevia(ByVal TipoFuente As String, ByVal TamañoFuente As Byte, _ ByVal TextoImpresion As String, ByVal e As System.Drawing.Printing.PrintPageEventArgs) Dim Fuente As New Font(TipoFuente, TamañoFuente) Dim AreaImpresion_Alto, AreaImpresion_Ancho, MargenIzquierdo, MargenSuperior As Integer With Me.PrintDocument1.DefaultPageSettings 'Area Neta de Impresion (se descuenta los margenes) AreaImpresion_Alto = .PaperSize.Height - .Margins.Top - .Margins.Bottom AreaImpresion_Ancho = .PaperSize.Width - .Margins.Left - .Margins.Right MargenIzquierdo = .Margins.Left MargenSuperior = .Margins.Top 'Verificar si se ha elegido el modo horizontal If .Landscape Then Dim NroTemp As Integer NroTemp = AreaImpresion_Alto AreaImpresion_Alto = AreaImpresion_Ancho AreaImpresion_Ancho = NroTemp End If Dim Formato As New StringFormat(StringFormatFlags.LineLimit) Dim Rectangulo As New RectangleF(MargenIzquierdo, MargenSuperior, _ AreaImpresion_Ancho, AreaImpresion_Alto) Dim NroLineasImpresion As Integer = CInt(AreaImpresion_Alto / Fuente.Height) Dim NroLineasRelleno, NroLetrasLinea As Integer Static CaracterActual As Integer e.Graphics.MeasureString(Mid(Me.ActiveMdiChild.Controls(0).Text, +1), Fuente, _ New SizeF(AreaImpresion_Ancho, AreaImpresion_Alto), Formato, NroLetrasLinea, _ NroLineasRelleno) e.Graphics.DrawString(Mid(TextoImpresion, CaracterActual + 1), Fuente, _ Brushes.Black, Rectangulo, Formato) CaracterActual += NroLetrasLinea If CaracterActual < TextoImpresion.Length Then e.HasMorePages = True Else e.HasMorePages = False CaracterActual = 0 End If End With End Sub 'PrintDocument.PrintPage (Evento): Se produce cuando se necesita el 'resultado que se va a imprimir para la página actual. Private Sub PrintDocument1_PrintPage(ByVal sender As System.Object, _ ByVal e As System.Drawing.Printing.PrintPageEventArgs) _ Handles PrintDocument1.PrintPage VistaPrevia("Arial", 12, Me.ActiveMdiChild.Controls(0).Text, e) End Sub Private Sub ToolBar1_ButtonClick(ByVal sender As System.Object, _ ByVal e As System.Windows.Forms.ToolBarButtonClickEventArgs) _ Handles ToolBar1.ButtonClick If e.Button Is ToolBarNuevo Then MenuNuevo_Click(sender, e) ElseIf e.Button Is ToolBarGuardar Then MenuGuardar_Click(sender, e) ElseIf e.Button Is ToolBarAbrir Then MenuAbrir_Click(sender, e) ElseIf e.Button Is ToolBarCortar Then MenuCortar_Click(sender, e) ElseIf e.Button Is ToolBarPegar Then MenuPegar_Click(sender, e) ElseIf e.Button Is ToolBarImprimir Then MenuImprimir_Click(sender, e) End If End Sub Private Sub MenuSalir_Click(ByVal sender As System.Object, _ ByVal e As System.EventArgs) Handles MenuSalir.Click Me.Close() End Sub Private Sub MnuColores_Click(ByVal sender As System.Object, _ ByVal e As System.EventArgs) Handles MnuColores.Click If ColorDialog1.ShowDialog() = DialogResult.OK Then Me.ActiveMdiChild.Controls(0).BackColor = Me.ColorDialog1.Color End If End Sub Private Sub MnuFuente_Click(ByVal sender As System.Object, _ ByVal e As System.EventArgs) Handles MnuFuente.Click With FontDialog1 .ShowColor = True .ShowApply = True If .ShowDialog() = DialogResult.OK Then Me.ActiveMdiChild.ActiveControl.ForeColor = .Color Me.ActiveMdiChild.ActiveControl.Font = .Font End If End With End Sub Private Sub MnuVistaPrevia_Click(ByVal sender As System.Object, _ ByVal e As System.EventArgs) Handles MenuVistaPrevia.Click PrintPreviewDialog1.Document = PrintDocument1 PrintPreviewDialog1.ShowDialog() End Sub Private Sub MnuConfiguracion_Click(ByVal sender As System.Object, _ ByVal e As System.EventArgs) Handles MenuConfiguracion.Click PageSetupDialog1.Document = PrintDocument1 PageSetupDialog1.PageSettings = PrintDocument1.DefaultPageSettings If PageSetupDialog1.ShowDialog = DialogResult.OK Then PrintDocument1.DefaultPageSettings = PageSetupDialog1.PageSettings End If End Sub Private Sub MenuAbrir_Click(ByVal sender As System.Object, _ ByVal e As System.EventArgs) Handles MenuAbrir.Click Try With OpenFileDialog1 .Filter = "Archivo de Texto (*.txt)|*.txt|Archivo de Texto Enrriquecido (*.rtf)|*.rtf" .InitialDirectory = Application.StartupPath .RestoreDirectory = True .FilterIndex = 1 Dim UserResponse As DialogResult = .ShowDialog If UserResponse = DialogResult.OK Then If .FileName <> "" Then MenuNuevo_Click(sender, e) Me.ActiveMdiChild.Text = .FileName If Microsoft.VisualBasic.Right(.Filter.ToString, 3) = "txt" Then Dim LeerEn As New System.IO.StreamReader(.FileName) Me.ActiveMdiChild.Controls(0).Text = LeerEn.ReadToEnd If Not LeerEn Is Nothing Then LeerEn.Close() End If ElseIf Microsoft.VisualBasic.Right(.Filter.ToString, 3) = "rtf" Then Dim Rtbox As RichTextBox = Me.ActiveMdiChild.ActiveControl Rtbox.LoadFile(.FileName, RichTextBoxStreamType.RichText) Me.ActiveMdiChild.ActiveControl = Rtbox End If End If End If End With Catch ex As Exception MsgBox(ex.Message) End Try End Sub Private Sub MenuGuardar_Click(ByVal sender As System.Object, _ ByVal e As System.EventArgs) Handles MenuGuardar.Click If Me.MdiChildren.Length <> 0 Then With SaveFileDialog1 .FileName = "Documento de texto " & Microsoft.VisualBasic.Mid(Me.ActiveMdiChild.Text, 21, 1) .Filter = "Archivo de Texto (*.txt)|*.txt|Archivo de Texto Enrriquecido (*.rtf)|*.rtf" .FilterIndex = 1 .InitialDirectory = Application.StartupPath If .ShowDialog = DialogResult.OK Then If .FileName <> "" Then If Microsoft.VisualBasic.Right(.Filter.ToString, 3) = "txt" Then Dim GuardarEn As New System.IO.StreamWriter(.FileName) GuardarEn.WriteLine(Me.ActiveMdiChild.ActiveControl.Text, _ RichTextBoxStreamType.PlainText) If Not GuardarEn Is Nothing Then GuardarEn.Close() End If ElseIf Microsoft.VisualBasic.Right(.Filter.ToString, 3) = "rtf" Then Dim oRtbox As RichTextBox = Me.ActiveMdiChild.ActiveControl oRtbox.SaveFile(.FileName, RichTextBoxStreamType.RichText) End If End If End If End With Else MsgBox("Debe crear previamente un documento") End If End Sub Private Sub MenuCortar_Click(ByVal sender As System.Object, _ ByVal e As System.EventArgs) Handles MenuCortar.Click Dim ObjRichTextBox As RichTextBox = Me.ActiveMdiChild.Controls(0) Clipboard.SetDataObject(ObjRichTextBox.SelectedText) ObjRichTextBox.SelectedText = "" End Sub Private Sub MenuCopiar_Click(ByVal sender As System.Object, _ ByVal e As System.EventArgs) Handles MenuCopiar.Click Dim ObjRichTextBox As RichTextBox = Me.ActiveMdiChild.Controls(0) Clipboard.SetDataObject(ObjRichTextBox.SelectedText) End Sub Private Sub MenuPegar_Click(ByVal sender As System.Object, _ ByVal e As System.EventArgs) Handles MenuPegar.Click Dim ObjRichTextBox As RichTextBox = Me.ActiveMdiChild.Controls(0) Dim idata As IDataObject = Clipboard.GetDataObject If idata.GetDataPresent(DataFormats.Text) Then Me.ActiveMdiChild.Controls(0).Text &= idata.GetData(DataFormats.Text) End If End Sub Private Sub MenuSelecionarTodo_Click(ByVal sender As System.Object, _ ByVal e As System.EventArgs) Handles MenuSelecionarTodo.Click Dim ObjRichTextBox As RichTextBox = Me.ActiveMdiChild.Controls(0) ObjRichTextBox.SelectAll() End Sub Private Sub MenuCerrar_Click(ByVal sender As System.Object, _ ByVal e As System.EventArgs) Handles MenuCerrar.Click If Not Me.ActiveMdiChild Is Nothing Then Me.ActiveMdiChild.Dispose() Else MsgBox("No existe algún documento abierto") End If End Sub Private Sub MenuAutor_Click(ByVal sender As System.Object, _ ByVal e As System.EventArgs) Handles MenuAutor.Click MsgBox("Percy Reyes Paredes") End Sub Private Sub MenuMicrosoft_Click(ByVal sender As System.Object, _ ByVal e As System.EventArgs) Handles MenuMicrosoft.Click MsgBox("Microsoft Corporation") End Sub Private Sub MenuMinimizar_Click(ByVal sender As System.Object, _ ByVal e As System.EventArgs) Handles MenuMinimizar.Click Me.ActiveMdiChild.WindowState = FormWindowState.Minimized End Sub Private Sub MenuMaximizar_Click(ByVal sender As System.Object, _ ByVal e As System.EventArgs) Handles MenuMaximizar.Click Me.ActiveMdiChild.WindowState = FormWindowState.Maximized End Sub Private Sub MenuRestaurar_Click(ByVal sender As System.Object, _ ByVal e As System.EventArgs) Handles MenuRestaurar.Click Me.ActiveMdiChild.WindowState = FormWindowState.Normal End Sub Private Sub MenuCerrarTodo_Click(ByVal sender As System.Object, _ ByVal e As System.EventArgs) Handles MenuCerrarTodo.Click Dim n As Integer = 0 If Not Me.ActiveMdiChild Is Nothing Then For n = 0 To (Me.MdiChildren.Length) - 1 Me.MdiChildren(n).Dispose() Next End If End Sub Private Sub MenuImprimir_Click(ByVal sender As System.Object, ByVal _ e As System.EventArgs) Handles MenuImprimir.Click PrintDialog1.Document = PrintDocument1 If PrintDialog1.ShowDialog = DialogResult.OK Then PrintDocument1.Print() End If End Sub Private Sub MenuVprevia_Click(ByVal sender As System.Object, ByVal _ e As System.EventArgs) Handles MenuVprevia.Click Me.MenuVistaPrevia.PerformClick() End Sub Private Sub MenuEditor_Click(ByVal sender As System.Object, _ ByVal e As System.EventArgs) Handles MenuEditor.Click MsgBox("Este Editor fue desarrollado gracias a un gran esfuerzo de parte de su autor. " _ & " A la vez este Editor viene a ser más que un Bloc de notas, es simplemente una manera " & _ " de demostrarte que todo se puede y que el conocimiento es del mundo y para el mundo." & _ No olvides de darme tu voto en www.PanoramaBox.com")" End Sub Private Sub MenuPantComp_Click(ByVal sender As System.Object, ByVal _ e As System.EventArgs) Handles MenuPantComp.Click If Me.MdiChildren.Length <> 0 Then Dim control As New Control Dim AreaCliente As New MdiClient For Each control In Me.Controls If control.GetType.Equals(AreaCliente.GetType) Then Me.ActiveMdiChild.Location = New Point(control.Location.X, _ control.Location.Y - Me.ToolBar1.Height) Me.ActiveMdiChild.Size = Me.ClientSize Exit For End If Next End If End Sub End Class
No olvides de darme tu voto en PanoramaBox, de esta manera seguiré compartiendo contigo lo que voy aprendiendo. Gracias.
Espacios de nombres usados en el código de este artículo:
System.Drawing.Drawing2D
Arbis Percy Reyes Paredes es peruano, tiene 21 años y se dedica a la construcción de software de manera profesional, joven desarrollador de aplicaciones Web y Servicios Web XML en VB .NET y C# .NET con bases de datos SQL Server 2000, aplicaciones basadas en Windows con VB .NET y C# .NET, VB 6.0, y controles y bibliotecas ActiveX; actualmente estudia en la Universidad Nacional de Trujillo, la carrera de Ingeniería de Sistemas. Le encanta el desarrollo de aplicaciones para dispositivos móviles tanto como la programación gráfica y programación avanzada de Videojuegos.
Fichero con el código de ejemplo: Percynet_EditorTexto.zip - Tamaño 36 KB