lunes, 12 de diciembre de 2011

Personalizar DataGridView (II) - Bloquear columnas de solo lectura

Personalizar DataGridView - Actualizaciones
Personalizar DataGridView (II.1) - Bloquear columnas de solo lectura.
Personalizar DataGridView (III) - Cambiar Diseñador.

Bien, continuando con el articulo "Personalizar DataGridView (I) - Pintar área vacía", ahora lo que haré es darle al control la funcionalidad de bloquear las columnas cuya propiedad "ReadOnly" se establezca en "true", entiéndase por "Bloquear" el evitar que las columnas cuya propiedad "ReadOnly=true" puedan recibir el foco, ya sea por el teclado o por el ratón (mouse).

Para tal objetivo agregare una nueva propiedad al control la cual llamare "AllowFocusReadOnlyColumns" cuyo valor predeterminado sera "true", en caso de ser "false" las columnas marcadas como solo lectura no recibirán el foco.

También le daré la funcionalidad de poder avanzar a la siguiente columna al presionar la tecla "ENTER" agregando otra propiedad que llamare "EnterMoveNextColumn" cuyo valor predeterminado sera "true"

[C#]
 
private bool vAllowFocusReadOnlyColumns;
private bool vEnterMoveNextColumn;

[DefaultValue(true)]
public bool AllowFocusReadOnlyColumns
{
    get { return vAllowFocusReadOnlyColumns; }
    set { vAllowFocusReadOnlyColumns = value; }
}

[DefaultValue(true)]
public bool EnterMoveNextColumn
{
    get { return vEnterMoveNextColumn; }
    set { vEnterMoveNextColumns = value; }
}
 
[VB.NET]
 
Private vAllowFocusReadOnlyColumns As Boolean
Private vEnterMoveNextColumn As Boolean

<DefaultValue(True)> _
Public Property AllowFocusReadOnlyColumns() As Boolean
    Get 
        Return vAllowFocusReadOnlyColumns
    End Get
    Set (ByVal value As Boolean)
        vAllowFocusReadOnlyColumns = value
    End Set
End Property

<DefaultValue(True)> _
Public Property EnterMoveNextColumn() As Boolean
    Get
        Return vEnterMoveNextColumn
    End Get
    Set (ByVal value As Boolean)
        vEnterMoveNextColumn = value
    End Set
End Property
 
Para agregarle esta funcionalidad al control sobre escribiré el método "WndProc" para escuchar el mensaje del teclado "WM_KEYDOWN" y los mensajes del ratón (mouse) "WM_LBUTTONDBLCLK", "WM_LBUTTONDOWN" y el mensaje "WM_SETFOCUS", en caso de no permitir que las columnas marcadas como solo lectura reciban el foco, estos mensajes no serán procesados por el método base del control. 

[C#]
 
[PermissionSet(SecurityAction.Demand, Name = "FullTrust")]
protected override void WndProc(ref Message m)
{
    switch (m.Msg)
    {
        case NativeMethods.WM_SETFOCUS:
            this.WmSetFocus(ref m);
            break;
        case NativeMethods.WM_LBUTTONDBLCLK:
            this.WmLButtonDblClk(ref m);
            return;
        case NativeMethods.WM_LBUTTONDOWN:
            this.WmLButtonDown(ref m);
            return;
        case NativeMethods.WM_KEYDOWN:
            this.WmKeyDown(ref m);
            return;
    }
    base.WndProc(ref m);
}
 
[VB.NET]
 
<PermissionSet(SecurityAction.Demand, Name:="FullTrust")> _
Protected Overrides Sub WndProc(ByRef m As System.Windows.Forms.Message)
    Select Case m.Msg
        Case NativeMethods.WM_SETFOCUS
            Me.WmSetFocus(m)
        Case NativeMethods.WM_LBUTTONDBLCLK
            Me.WmLButtonDblClk(m)
            Return
        Case NativeMethods.WM_LBUTTONDOWN
            Me.WmLButtonDown(m)
            Return
        Case NativeMethods.WM_KEYDOWN
            Me.WmKeyDown(m)
            Return
    End Select

    MyBase.WndProc(m)
End Sub
 
Y a continuación los proyectos para que los descarguen.

Código fuente [C#]
Código fuente [VB.NET]

En el próximo articulo lo que haré sera agregar un evento al control para poder indicar si la columna puede recibir el foco sin necesidad de que la propiedad "ReadOnly" este establecida en "true", ya que el algunos casos no necesitamos que la celda reciba el foco pero si que pueda ser editada.

Espero sea de utilidad este articulo y no olviden dejar sus comentarios.

Salu2,