[VBA/Excel] Botones de minimizar y maximizar para UserForm
Resuelto
alecomte
Mensajes publicados
37
Estado
Miembro
-
alecomte Mensajes publicados 37 Estado Miembro -
alecomte Mensajes publicados 37 Estado Miembro -
Bonjour,
El código a continuación permite agregar los botones de minimizar y maximizar junto a la cruz roja de un UserForm.
Sin embargo, mi proyecto contiene no uno, sino cuatro formularios.
Después de la prueba, las líneas UserForm1.Hide y UserForm1.Show me parecieron innecesarias, así que las eliminé.
Con un proyecto que tiene solo un formulario, el código sigue funcionando sin problemas.
Pero con varios formularios:
- el botón de maximizar funciona bien
- Pero el botón de minimizar presenta un problema.
Si hago clic en el botón de minimizar una vez, funciona la primera vez. Pero si hago clic nuevamente en el botón, cierra abruptamente el libro de Excel y por lo tanto pierdo todos mis datos no guardados.
¿Cómo puedo hacer funcionar este código con varios UserForms? (y más precisamente el botón de minimizar) ?
¡Gracias por tu ayuda!
En un módulo
En el módulo del UserForm
El código a continuación permite agregar los botones de minimizar y maximizar junto a la cruz roja de un UserForm.
Sin embargo, mi proyecto contiene no uno, sino cuatro formularios.
Después de la prueba, las líneas UserForm1.Hide y UserForm1.Show me parecieron innecesarias, así que las eliminé.
Con un proyecto que tiene solo un formulario, el código sigue funcionando sin problemas.
Pero con varios formularios:
- el botón de maximizar funciona bien
- Pero el botón de minimizar presenta un problema.
Si hago clic en el botón de minimizar una vez, funciona la primera vez. Pero si hago clic nuevamente en el botón, cierra abruptamente el libro de Excel y por lo tanto pierdo todos mis datos no guardados.
¿Cómo puedo hacer funcionar este código con varios UserForms? (y más precisamente el botón de minimizar) ?
¡Gracias por tu ayuda!
En un módulo
Public Declare Function FindWindow& _ Lib "user32" Alias "FindWindowA" _ (ByVal lpClassName$, ByVal lpWindowName$) Public Declare Function GetWindowLong& _ Lib "user32" Alias "GetWindowLongA" _ (ByVal hwnd&, ByVal nIndex&) Public Declare Function SetWindowLong& _ Lib "user32" Alias "SetWindowLongA" _ (ByVal hwnd&, ByVal nIndex&, ByVal dwNewLong&) Private Declare Function EnableWindow& _ Lib "user32" _ (ByVal hwnd&, ByVal fEnable&) Private Declare Function CallWindowProc& _ Lib "user32" Alias "CallWindowProcA" _ (ByVal lpPrevWndFunc&, ByVal hwnd&, ByVal Msg&, ByVal wParam&, ByVal lParam&) Public Const GWL_WNDPROC& = -4&, WM_SYSCOMMAND& = &H112& Public BaseUFProc&, BaseXLProc&, AncState& Function UFProc&(ByVal hwnd&, ByVal uMsg&, ByVal wParam&, ByVal lParam&) Dim HwndXL& Const SC_MINIMIZE& = &HF020& If uMsg = WM_SYSCOMMAND Then If wParam = (SC_MINIMIZE And &HFFF0&) Then HwndXL = FindWindow("XLMAIN", Application.Caption) EnableWindow HwndXL, True UserForm1.Hide AncState = Application.WindowState Application.WindowState = xlMinimized BaseXLProc = SetWindowLong(HwndXL, GWL_WNDPROC, AddressOf XLProc) UFProc = 1& Exit Function End If End If UFProc = CallWindowProc(BaseUFProc, hwnd, uMsg, wParam, lParam) End Function Function XLProc&(ByVal hwnd&, ByVal uMsg&, ByVal wParam&, ByVal lParam&) Const SC_MAXIMIZE& = &HF030&, _ SC_RESTORE& = &HF120&, SC_CLOSE& = &HF060& If uMsg = WM_SYSCOMMAND Then If wParam = (SC_MAXIMIZE And &HFFF0&) Or wParam = (SC_RESTORE _ And &HFFF0&) Or wParam = SC_CLOSE Then SetWindowLong hwnd, GWL_WNDPROC, BaseXLProc Application.WindowState = AncState UserForm1.Show XLProc = 1& Exit Function End If End If XLProc = CallWindowProc(BaseXLProc, hwnd, uMsg, wParam, lParam) End Function En el módulo del UserForm
Option Explicit Private HandleUF& Private Sub UserForm_Initialize() Const WS_MAXIMIZEBOX& = &H10000, _ WS_MINIMIZEBOX& = &H20000, GWL_STYLE& = -16& HandleUF = FindWindow(vbNullString, Me.Caption) SetWindowLong HandleUF, GWL_STYLE, _ GetWindowLong(HandleUF, GWL_STYLE) Or WS_MAXIMIZEBOX Or WS_MINIMIZEBOX BaseUFProc = SetWindowLong(HandleUF, GWL_WNDPROC, BaseUFProc) End Sub Private Sub UserForm_Terminate() SetWindowLong HandleUF, GWL_WNDPROC, BaseUFProc End Sub
12 respuestas
-
Para poner a todos de acuerdo ;)
Simplicidad y eficacia:
En un módulo estándar
Private Declare Function FindWindow Lib "User32" Alias "FindWindowA" (ByVal lpClassName As String, ByVal lpWindowName As String) As Long Private Declare Function SetWindowLong Lib "User32" Alias "SetWindowLongA" (ByVal hWnd As Long, ByVal nIndex As Long, ByVal dwNewLong As Long) As Long Private Declare Function GetWindowLong Lib "User32" Alias "GetWindowLongA" (ByVal hWnd As Long, ByVal nIndex As Long) As Long Private Const GWL_STYLE As Long = (-16) 'El desplazamiento del estilo de una ventana Private hWnd, IStyle Public Sub toto(F As Object) hWnd = FindWindow(vbNullString, F.Caption) iStyle = GetWindowLong(hWnd, GWL_STYLE) Or &H70000 SetWindowLong hWnd, GWL_STYLE, iStyle End Sub
y en cada UserForm:
Private Sub UserForm_Initialize() toto Me End Sub
Y porque no pretendo robar el trabajo de otro: https://codes-sources.commentcamarche.net/#6
¡gracias a ucfoutu! -
Buenas noches alecomte, lermite222,
Ok, el código funciona muy bien para los cuatro formularios, pero lermite222 no se equivoca.
Dáte cuenta por ti mismo, su código solo ocupa unas pocas líneas, con, además, una pequeña llamada por formulario... en cuanto a peso, claridad y eficacia, ¡no hay nada mejor!
¡Tú decides! -
Hola,
De hecho, ¿lo que quieres son los botones del sistema para minimizar y maximizar tus UF?
Si es así, hay una manera mucho más sencilla de lograrlo.
Si estás en Excel 97-2003, elimina las líneas que tienen que ver con el zoom, que no está disponible en esas versiones, al menos en la 2000.
¡Hasta luego!
Si te chocas con un tarro y suena hueco, no necesariamente es el tarro que está vacío. ;-)(Confucio)
NOTA: No respondo a los mensajes privados para preguntas técnicas. -
pues prueba mi propuesta y no tendrás más problemas, al menos tómate la molestia de mirarla. Pero bueno, tú decides.
Después de todo, si prefieres 50 líneas de código en lugar de tres....Grrr
Si te topas con una olla y suena hueca, no necesariamente es la olla la que está vacía. ;-)(Confucio)
NOTA: No respondo a los MP para preguntas técnicas. -
Suponiendo mantener las líneas,
UserForm1.Hide
UserForm1.Show
Pensé que tal vez un bucle del estilo:
Dim Usf as UserForm
For i = 1 to 4
Usf & i ...
pero la definición de variable As UserForm requiere usar un módulo de clase que luego genera un error en
Public Const GWL_WNDPROC& = -4&, WM_SYSCOMMAND& = &H112&
debido a una imposibilidad de tener una constante en un módulo de clase.. -
Buenas noches alecomte,
No entiendo dónde está el problema, porque en mi casa todo funciona muy bien... el único problema es que cuando se minimiza el formulario, se coloca en el escritorio (esquina inferior izquierda)... no muy bonito, pero bueno.
Entonces, si hay que hacer pruebas, habrá que enviar los documentos... el libro PERO sin los datos confidenciales, como de costumbre, por ejemplo en https://www.cjoint.com/
Con gusto -
@Heliotte
¿Qué haces con las líneas UserForm1.Hide y UserForm1.Show?
Porque aclaro bien que tengo un error al tener varios formularios ¡solo!
Y curiosamente solo con el botón de minimizar del formulario en el segundo clic ¿?!
(mientras que con un solo formulario en mi proyecto todo funciona perfectamente)
Intentaré de nuevo y te envío un archivo de prueba a través de https://www.cjoint.com/
@lermitte22
Estoy en Excel 2007 y 2010 (en casa) y en 97/2003 (en el trabajo).
Pero encuentro el mismo error en las 3 versiones.
Gracias a los dos -
¡Gracias por sus respuestas (¡y su rapidez!) Estoy revisando eso y les mantendré informados ;)
-
lermite222, creo que tu código resumido está muy bien, ¡bravo!
Sin embargo, el zoom es un poco exagerado y sobre todo desigual para mi formulario: algunos caracteres se agrandan más que otros (aunque este detalle es negligible).
La ventaja del código modificado por Heliotte es que, al evitar el zoom, el aumento a pantalla completa me permite mostrar más contenido del formulario en la pantalla.
Además, creo que la función de reducir es más adecuada. Uno podría preguntarse dónde ha ido a parar el formulario con tu método... a pesar de que lo encontré rápidamente gracias al comentario de Heliotte.
Finalmente, creo que cada uno decidirá según su formulario (y tal vez su vista, jaja) ¡Yo mismo voy a mantener las dos opciones y juzgaré caso por caso! Así que un gran gracias a los dos :) !
P.D.: Dicho esto, creo haber leído que tu código lermite222 solo funciona a partir de la versión Excel 2007... así que con mi Excel 2003 del trabajo, creo que me orientaré hacia el primer código para el formulario presente. -
Hola alecomte,
Quiero tranquilizarte.
El código de lermite222 funciona muy bien en una hoja de cálculo de Excel versión 2003. -
Esto es realmente para joder a la gente. grrrf<f&zhuzuzoulou
Es exactamente lo que propongo en mi demo, además podemos elegir los botones que queremos añadir. Y la guinda del pastel, las flechas dobles para que el usuario ajuste el tamaño.
Haré bien en dejar tus pseudónimos a un lado, y confía en mí, no volveré a intentar ayudarte y, dado tu puesto en CS, aún tienes muchas carencias.
A++-
Lo siento, pero efectivamente he notado que este código, al igual que el tuyo, no permite reducir el libro sino solo el formulario. Así que revisa bien en el enlace, sigo buscando modificar los dos códigos (tu propuesta y la de ucfoutu) para realmente recuperar el handle de la ventana de Excel para reducirla ;)
Como las líneas de código no son rigurosamente las mismas en vuestros dos códigos (pero al final me pierdo en eso), pensé que te gustaría conocer el método que me habían mencionado por otro lado. Así que no es mi intención ofenderte, de hecho, me sorprende... -
Lo siento, mi culpa, he revisado tu código y efectivamente es rigurosamente el mismo. Parece que me he enredado al recopilar los diferentes códigos en mi archivo de trabajo. Pero tengo efectivamente lagunas, de ahí mi publicación, de otra forma no sería útil. Así que gracias de nuevo por tu ayuda y lo siento, partía de una buena intención al compartirte la propuesta sobre CS ;)
-
Sí, no intentes caer de pie, es demasiado tarde.
Y sería bueno que aprendieras cómo funcionan los foros.
En CS, dudo que tu "amigo" te responda de nuevo, ni siquiera te tomaste la molestia de validar su respuesta aunque te lo pidió.
Y aquí, no te tomaste la molestia de marcar tu publicación como resuelta, tuve que hacerlo por ti.
Otra observación, para aquellos que te responden, no hay nada más desconsiderado que ver que haces la misma pregunta en varios foros y que al final vienes a burlarte con la misma respuesta que te dieron.
Y es una lástima, el problema que mencionas es tan sencillo, pero diviértete. -
-
-
Bueno, tras tus disculpas por MP, voy a considerar que estos malentendidos son el resultado de tu inexperiencia en los foros.
Algunas reglas fundamentales, sin embargo...
Ucfoutu te pasa una función que te conviene, tú la transcribes y te das cuenta de errores porque has puesto Option Explicit y él ha omitido ("Oh, horrible error") declarar las variables. Tu respuesta en lugar de ser un agradecimiento, es decir, "de acuerdo, gracias", es más bien un reproche diciendo... "no eres capaz de ponerme algo adecuado..."
Tu respuesta...
Olvidaste la definición de las variables
Private hWnd, IStyle
antes de la Public Sub toto...
¡De lo contrario, impecable, GRACIAS!
¿Crees que es agradable recibir esto? Piénsalo. Y evita hacerte el listo, no olvides que eres tú el que está pidiendo.
2) Haz una pregunta en UN foro y SÍGUELA, si te dan pistas, SÍGUE LAS.
Si al final no tienes las respuestas deseadas, ve a otro lado, pero no a los 2 o 3 a la vez, eso también es desconsiderado para las personas que se esfuerzan por responderte.
Nunca olvides, las personas que te responden son voluntarios, te ayudan según sus conocimientos y su disponibilidad, evita hacer que parezcan menos que nada, incluso si la respuesta que te dan no es la correcta. Una pregunta a menudo puede ser interpretada de múltiples maneras y es muy a menudo el ayudante quien no ha expresado bien su problema.
Finalmente, para terminar, como eres tú quien está aprendiendo, te recomiendo "humildad", "amabilidad", "paciencia".
Espero que tomes esto en cuenta y, para, al final, demostrar que ya no te guardo rencor...
en el evento resize del U.F.
encuentras la línea
If Me.Width < 300 Or Me.Height < 200 Or Fini Then Exit Sub
agregas...
If Me.Width < 300 Or Me.Height < 200 Then application.WindowsState=0 : Exit Sub
Pero no está del todo correcto... busca y si no es así como lo quieres, dilo...
Vamos... al final, sin rencor.
Nota: No tengo el hábito de hacer todo un tratado, pero pienso que eres joven y que, en vista de tus MP, mereces, al menos de mi parte, una segunda oportunidad.
¡Nos vemos!
--
Si te chocas con una maceta y suena hueca, no necesariamente es la maceta la que está vacía. ;-)(Confucio)
NOTA: No respondo a MP para preguntas técnicas.