|
| | En la primara parte de este articulo trate de los formularios empaquetados en componentes de código y que se presentarán como modales. Bien, ese caso es relativamente sencillo comparado con la utilización de formularios no modales en componentes. Realmente esto requiere un dominio de Visual Basic algo más depurado. Existe una precaución en la utilización de formularios no modales en componentes en proceso, pero realmente no hay porque prescindir de este recurso si se usa un modelo de código bien diseñado. El ejemplo más frecuente y util de formularios no modales en DLLs, lo representan las ToolBar emergentes, por lo tanto expondré este diseño. De otra parte, también es posible manejar en código formularios instansiables no modales. |
| '//CLASE: cls_ToolBox '//DESCRIPCIÖN : Envuelve un Formulario No Modal Flotante Option Explicit '//EVENTS Public Event ReturnOption(Value As Integer, Name As String) '//FORM Private WithEvents frm As frmToolBoxSample '//API for floating window '//Based in a Tip of MVP Joe LeVasseur, VBONLINE Private Declare Function SetWindowPos Lib "user32" ( _ ByVal hwnd As Long, ByVal hWndInsertAfter As Long, _ ByVal x As Long, ByVal y As Long, ByVal cx As Long, _ ByVal cy As Long, ByVal wFlags As Long) As Long Private Const SWP_NOMOVE As Long = &H2 Private Const SWP_NOSIZE As Long = &H1 Private Const SWP_NOACTIVATE As Long = &H10 Private Const SWP_SHOWWINDOW As Long = &H40 Private Const HWND_TOPMOST As Long = -1 Private Const HWND_NOTOPMOST As Long = -2 Private Sub Class_Terminate() If Not frm Is Nothing Then Unload frm End If End Sub Private Sub frm_ReturnOption(Value As Integer, Name As String) '//Delega el evento RaiseEvent ReturnOption(Value, Name) End Sub Public Sub ShowForm(Optional Floating As Boolean = True) If frm Is Nothing Then Set frm = New frmToolBoxSample Load frm End If '//Muestra el formulario If Floating Then If SetWindowPos( _ frm.hWnd, HWND_TOPMOST, 0, 0, 0, 0, _ SWP_NOMOVE Or SWP_NOSIZE Or SWP_SHOWWINDOW Or SWP_NOACTIVATE _ ) Then frm.SetFocus End If Else frm.Show vbModeless End If End Sub |
| '//FORM : TOOLBOX SAMPLE '//DESCRIPCIÖN : Formulario No Modal Flotante (opcional) Option Explicit Public Event ReturnOption(Value As Integer, Name As String) Private Sub cmdOption_Click(Index As Integer) RaiseEvent ReturnOption(Index, cmdOption(Index).Caption) End Sub Private Sub Form_QueryUnload(Cancel As Integer, UnloadMode As Integer) If UnloadMode = vbFormControlMenu Then Cancel = True Hide Else Unload Me End If End Sub |
| Option Explicit '//OBJETOS Private WithEvents tbSample As cls_ToolBox '//algun comando que muestra el ToolBox Private Sub cmdToolBoxSample_Click() tbSample.ShowForm End Sub Private Sub Form_Load() Set tbSample = New cls_ToolBox End Sub Private Sub Form_Unload(Cancel As Integer) Set tbSample = Nothing End Sub Private Sub tbSample_ReturnOption(Value As Integer, Name As String) '//Este evento se genera cuando se selecciona un ítem Me.SetFocus '//Importante cuando se usa una ventana flotante MsgBox "Fue seleccionada la opción: " & Value '//Hace algo con los parámetros retornados End Sub |
| | La presentación de formularios no modales desde componentes en proceso requiere comunicación con el bucle de mensajes del cliente. No todos los clientes lo permiten. Para ver una explicación de esta limitación, vea "Presentar formularios desde componentes de código" en "Generar componentes de código". |
| '// CLASE : cls_ModelessNotes '// DESCRIPCION : Modelo de clase que envuelve un formulario no modal Option Explicit '//EVENTS Public Event Busy(Value As Boolean) Public Event CustomError(Index As Long) '//Filter another Forms in component Private Const FormClassName As String = "frmNotes" Public Sub ShowModeless(IdForm As Long, IdWell As Variant) Dim frm As Form Dim Cont As Boolean Cont = True RaiseEvent Busy(True) For Each frm In Forms If frm.Name = FormClassName Then If IdForm = frm.IdForm Then frm.SetFocus Cont = False Exit For End If End If Next If Cont Then Call LoadInstance(IdForm, IdWell) End If RaiseEvent Busy(False) End Sub Private Function LoadInstance( _ IdForm As Long, _ IdWell As Variant _ ) As Boolean Dim frm As frmNotes Dim Cont As Boolean Dim ErrIndex As Long Set frm = New frmNotes Load frm frm.IdForm = IdForm '//Validate iniatization Cont = frm.Init(IdWell, ErrIndex) If Not Cont Then Unload frm Set frm = Nothing RaiseEvent CustomError(ErrIndex) Else frm.Show vbModeless End If Set frm = Nothing LoadInstance = Cont End Function Private Sub Class_Terminate() Call UnloadAll End Sub Public Sub UnloadAll() Dim frm As Form For Each frm In Forms If frm.Name = FormClassName Then Unload frm End If Next End Sub |
| | Es preferible usar la tecnología de control de errores de Visual Basic, para más información, consultar «Generar y tratar errores en los componentes ActiveX», de la documentación MSDN o Libros en Pantalla (VB5). |
| '//FORMULARIO : frmNotes '//DESCRIPCIÓN : Modelo de formulario no modal Option Explicit '//KEY FORM Private m_IdForm As Long Private Sub Form_Resize() If Not Me.WindowState = vbMinimized Then txtMemo.Move 0, 0, Me.ScaleWidth, Me.ScaleHeight End If End Sub Public Property Get IdForm() As Long IdForm = m_IdForm End Property Public Property Let IdForm(ByVal v As Long) m_IdForm = v End Property Public Function Init(IdWell As Variant, ErrIndex As Long) As Boolean '//Required if the form must be configurate '//Sample: On Error GoTo ErrHandler Me.Caption = "Form of Key " & m_IdForm txtMemo = "IdWell = " & IdWell Init = True Exit Function ErrHandler: ErrIndex = Err.Number End Function |
| Option Explicit '//Formulario no modal multiples instancias Private WithEvents mn As cls_ModelessNotes Private Sub cmsModelessNotes_Click() '//Ejemplos mn.ShowModeless 12345, "DOR00012_E" mn.ShowModeless 12377, "ADORX018_X" End Sub Private Sub Form_Load() Set mn = New cls_ModelessNotes End Sub Private Sub Form_Unload(Cancel As Integer) Set mn = Nothing End Sub |