Historial del chat

ChatGPT

Photo Realistic Image GPT

Explorar GPT

Proyectos

Nuevo proyecto

Ayer

Serpiente y rana venenosa

7 días anteriores

Renovación y posibles problemas

30 días anteriores

Error en archivo ZIP

Problema con PayPal Checkout

Preguntar sobre webs

Ver planesAcceso ilimitado, características de Team y más

Ana Diaz

Abrir barra lateral

ChatGPT 4o mini

ChatGPT 4o mini

Compartir

Dijiste:

Como hago que para que cuando cambio el left, top, width, height de un usercontrol que captura el fondo del control para parecer transparente, como hago para que no pinte hasta que capture el fondo de la nueva posicion?

ChatGPT dijo:

Para evitar que el UserControl pinte hasta que termine de capturar el fondo en la nueva posición, puedes seguir estos pasos:

Evitar el Redibujado Automático: Desactiva cualquier redibujado automático durante el cambio de tamaño o posición. Puedes agregar una variable bandera para bloquear el redibujado temporalmente mientras actualizas las propiedades Left, Top, Width o Height del control.

Capturar el Fondo antes de Redibujar: Una vez que hayas cambiado las propiedades de ubicación o tamaño, asegúrate de capturar el fondo antes de solicitar el redibujado del UserControl. Esto asegurará que la captura correcta esté disponible antes de que el control se dibuje.

Aquí hay un ejemplo de cómo se podría implementar:

vb

Copiar

Private m_Capturing As Boolean

Public Property Let UserControlPosition(NewLeft As Single, NewTop As Single, NewWidth As Single, NewHeight As Single)
' Bloquear el redibujado del UserControl mientras se actualiza la posición
m_Capturing = True

' Actualizar posición y tamaño
UserControl.Move NewLeft, NewTop, NewWidth, NewHeight

' Capturar el fondo desde la nueva ubicación
Call CaptureBackground

' Desbloquear y solicitar redibujado
m_Capturing = False
UserControl.Refresh
End Property

Private Sub CaptureBackground()
' Implementar aquí el código para capturar el fondo del UserControl
' Esto puede ser guardar la imagen debajo del control para simular transparencia
End Sub

Private Sub UserControl_Paint()
' Solo pintar si no se está en proceso de captura
If Not m_Capturing Then
' Código para pintar el control con el fondo capturado
End If
End Sub

Explicación del código:

m_Capturing es una bandera que indica si se está en proceso de actualizar la posición del UserControl y capturar el fondo.

UserControlPosition es una propiedad que permite cambiar Left, Top, Width y Height. Durante este proceso, establece la bandera m_Capturing en True para evitar que el UserControl se pinte mientras se ajustan las propiedades.

CaptureBackground se llama después de mover el UserControl para capturar el fondo en la nueva ubicación.

UserControl_Paint se modifica para comprobar la bandera m_Capturing. Si la bandera está activa, el control no se dibuja.

Con este enfoque, aseguras que el UserControl no intente dibujarse hasta que haya terminado de capturar el fondo de la nueva ubicación, evitando que se vea un fondo incorrecto o parcialmente actualizado.

Dijiste:

No quiero añadir nueva propiedad, solo que cuando se cambie el left, top, width o height, haga algo para mover el control, pero antes de pintarlo darle a al funcion de captura

ChatGPT dijo:

En ese caso, puedes interceptar los eventos de cambio de tamaño (Resize) y movimiento (Move) del UserControl y realizar la captura antes de permitir que el control se pinte. Esto se puede lograr desactivando temporalmente el redibujado automático del control (AutoRedraw), realizando la captura del fondo y luego activando de nuevo el redibujado.

Aquí te muestro cómo puedes hacerlo:

Interceptar Move y Resize: Utiliza los eventos UserControl_Resize y UserControl_Move para capturar el fondo cada vez que haya un cambio de tamaño o de posición.

Desactivar AutoRedraw Temporalmente: Antes de la captura, desactiva AutoRedraw y vuelve a activarlo una vez que la captura haya terminado.

Evitar Redibujado durante el Movimiento: Controla que el pintado no ocurra hasta que se haya completado la captura.

Ejemplo:

vb

Copiar

Private m_Capturing As Boolean

Private Sub UserControl_Resize()
' Captura el fondo antes de redibujar en el nuevo tamaño
HandleMoveOrResize
End Sub

Private Sub UserControl_Move()
' Captura el fondo antes de redibujar en la nueva posición
HandleMoveOrResize
End Sub

Private Sub HandleMoveOrResize()
' Bloquear el redibujado durante la captura
m_Capturing = True
UserControl.AutoRedraw = False

' Capturar el fondo desde la nueva ubicación y/o tamaño
CaptureBackground

' Activar redibujado y desbloquear
UserControl.AutoRedraw = True
m_Capturing = False

' Forzar el repintado ahora que la captura ha finalizado
UserControl.Refresh
End Sub

Private Sub CaptureBackground()
' Código para capturar el fondo debajo del UserControl
' Esto asegura que el fondo se capture antes del repintado
End Sub

Private Sub UserControl_Paint()
' Solo pintar si no se está en proceso de captura
If Not m_Capturing Then
' Código para pintar el control con el fondo capturado
End If
End Sub

Explicación:

Eventos UserControl_Resize y UserControl_Move: Cada vez que cambias el tamaño o mueves el UserControl, se llama a HandleMoveOrResize para preparar la captura.

HandleMoveOrResize: Este subproceso:

Bloquea el repintado (m_Capturing = True).

Desactiva AutoRedraw para evitar redibujados hasta que termine la captura.

Llama a CaptureBackground para capturar el fondo desde la nueva posición o tamaño.

Vuelve a activar AutoRedraw y desbloquea el redibujado (m_Capturing = False).

Llama a UserControl.Refresh para forzar el redibujado, asegurando que el fondo ya haya sido capturado.

UserControl_Paint: Solo se permite pintar cuando no se está capturando (m_Capturing = False). Esto evita que el UserControl intente dibujarse cuando el fondo todavía no está capturado.

Este enfoque garantiza que, al cambiar Left, Top, Width o Height, siempre se captura el fondo antes de repintar, evitando cualquier parpadeo o problemas de fondo incorrecto.

Dijiste:

Resize se dispara antes de pintar el control, o despues?

ChatGPT dijo:

El evento Resize en un UserControl de VB6 se dispara antes de que ocurra el evento Paint. Cuando se cambia el tamaño del control, el proceso típico es:

Primero, se dispara el evento Resize.

Luego, se repinta el control, lo cual ejecuta el evento Paint.

Esto significa que si quieres realizar alguna acción (como capturar el fondo) antes de que el UserControl se dibuje en su nueva posición o tamaño, el evento Resize es el lugar adecuado para hacerlo, ya que ocurre antes de que el control intente repintarse. De esta forma, cualquier preparación que necesites hacer, como ajustar el tamaño o capturar el fondo, se puede hacer antes de que se ejecute el evento Paint y el control se dibuje visualmente.

Por lo tanto, capturar el fondo dentro del evento Resize te dará la oportunidad de actualizar la información del fondo antes de que el control se vuelva a pintar, asegurando que se vea correctamente en el nuevo tamaño o ubicación.

Dijiste:

Ok, buena noticia

ChatGPT dijo:

¡Me alegra que sea una buena noticia para ti! 😊 Si necesitas más ayuda para ajustar tu UserControl o cualquier otra cosa, no dudes en decírmelo. Estoy aquí para ayudarte. ¡Espero que tu proyecto siga avanzando sin problemas!

Dijiste:

Me sigue haciendo flick, y antes de resize que sucede cuando se cambia el tamaño o posicon?

ChatGPT dijo:

Cuando cambias el tamaño o la posición de un UserControl en VB6, hay una serie de eventos que ocurren en una secuencia específica. El "flicker" (parpadeo) puede ser causado por varios redibujados intermedios. A continuación, describo la secuencia típica de eventos que ocurre y algunas sugerencias para reducir el parpadeo.

Secuencia de Eventos al Cambiar Tamaño o Posición

BeginDrag / Move: Cuando empiezas a mover o cambiar el tamaño de un control, primero ocurre el proceso de "mover" o "ajustar tamaño". Este es el momento en el que se están actualizando las propiedades Left, Top, Width, y Height del control. No hay un evento explícito para BeginDrag en los controles estándar, pero el Move es lo primero que se ejecuta.

UserControl_Move: Este evento ocurre si el Left o Top del control ha cambiado. Aquí puedes interceptar y manejar la lógica antes de redibujar.

UserControl_Resize: Este evento ocurre si el Width o Height del control ha cambiado. Es útil para prepararte antes del redibujado, pero aún así podría haber parpadeos si hay redibujos intermedios.

UserControl_Paint: Este evento ocurre cuando el control se redibuja visualmente en la pantalla, ya sea por cambios de posición, tamaño o porque fue cubierto por otra ventana y vuelve a ser visible.

¿Por qué ocurre el Flicker?

El parpadeo ocurre principalmente porque:

Múltiples repintados durante el proceso de cambio de tamaño o posición.

Redibujado parcial antes de completar la captura del fondo.

Redibujado sin doble buffering, lo cual significa que el control se repinta directamente en la pantalla en lugar de primero hacerlo en una superficie temporal.

Sugerencias para Reducir el Flicker

Doble Buffering:
Utilizar doble buffering es la mejor forma de evitar el parpadeo. Puedes dibujar primero en una imagen en memoria y luego volcar esa imagen completa al control. Esto evita que el usuario vea el proceso de redibujado parcial.

Ejemplo sencillo de doble buffering:

vb

Copiar

Private Sub UserControl_Paint()
Dim Buffer As StdPicture
Set Buffer = UserControl.Image ' Crear un buffer en memoria con el control completo

' Dibujar en el buffer en lugar de en pantalla directamente
' (Dibuja aquí todo el contenido)

' Finalmente, copiar la imagen completa del buffer al UserControl
UserControl.Cls
UserControl.PaintPicture Buffer, 0, 0
End Sub

Evitar Redibujado Automático:

Antes de iniciar el proceso de cambio de tamaño o posición, desactiva el redibujado automático.

Reactívalo solo cuando todos los cambios estén completos.

Puedes usar algo como:

vb

Copiar

UserControl.AutoRedraw = False
' Capturar el fondo o realizar la lógica de cambio de tamaño/posición
UserControl.AutoRedraw = True
UserControl.Refresh

Captura del Fondo antes del Redibujado:
Asegúrate de capturar el fondo del UserControl antes de activar cualquier tipo de redibujado. Esto se puede hacer durante el evento Move o Resize para asegurarte de que la captura esté lista antes de que ocurra el Paint.

Suspender Temporalmente la Actualización del Control (LockWindowUpdate):
Utiliza la API de Windows LockWindowUpdate para suspender el redibujado del UserControl durante el cambio de tamaño o posición, y reactívalo al final. Esto reduce el parpadeo significativamente.

vb

Copiar

Private Declare Function LockWindowUpdate Lib "user32" (ByVal hwndLock As Long) As Long

Private Sub UserControl_Resize()
' Suspender redibujado
LockWindowUpdate UserControl.hWnd

' Capturar el fondo antes de redibujar
CaptureBackground

' Reactivar redibujado
LockWindowUpdate 0

' Forzar repintado con el nuevo fondo capturado
UserControl.Refresh
End Sub

Utilizando LockWindowUpdate evitarás cualquier repintado intermedio hasta que termines de realizar los cambios y capturar el fondo.

Estas técnicas combinadas deberían ayudar a reducir el parpadeo. El uso de doble buffering y LockWindowUpdate son especialmente efectivos para asegurarte de que el control se redibuje solo una vez que todo esté listo, evitando así el "flick" visual.

Dijiste:

Es un RichTextBox subclaseado, y [arece que la propiedad left - y creo que las otras 3, top, width y height - no sirven de nada, le pongo un punto de interrupcon, y no se para nunca en la propiedad

ChatGPT dijo:

En el caso de un RichTextBox que ha sido subclaseado, las propiedades estándar como Left, Top, Width, y Height no funcionan de la manera habitual porque el subclasificado (subclassing) desvía los mensajes del sistema operativo que normalmente serían manejados por el control. Esto puede provocar que no se dispare la lógica asociada a esas propiedades en tu código.

Por qué No Funcionan las Propiedades Estándar

Cuando subclaseas un control, estás interceptando los mensajes de la ventana (WM_ mensajes) para hacer cambios en el comportamiento del control. Dependiendo de cómo hayas subclaseado el RichTextBox, es posible que los mensajes relacionados con el movimiento y el cambio de tamaño del control (WM_MOVE y WM_SIZE) no lleguen correctamente al código predeterminado de VB6. Esto explica por qué no ves que se activen los puntos de interrupción en Left, Top, Width, o Height, ya que estos mensajes están siendo interceptados antes de llegar al control.

Solución para Mover o Cambiar el Tamaño de un Control Subclaseado

Para gestionar el movimiento y cambio de tamaño de un RichTextBox subclaseado, es mejor trabajar directamente con las API de Windows para forzar los cambios de posición y tamaño del control. Aquí te muestro cómo puedes hacer esto:

Usar la API SetWindowPos para Cambiar Tamaño y Posición:
Puedes usar la función API SetWindowPos para mover o cambiar el tamaño del control sin depender de las propiedades Left, Top, Width y Height.

vb

Copiar

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_NOZORDER As Long = &H4
Private Const SWP_NOACTIVATE As Long = &H10

' Procedimiento para mover/cambiar el tamaño del RichTextBox
Private Sub MoveRichTextBox(hWndRTB As Long, NewLeft As Long, NewTop As Long, NewWidth As Long, NewHeight As Long)
SetWindowPos hWndRTB, 0, NewLeft, NewTop, NewWidth, NewHeight, SWP_NOZORDER Or SWP_NOACTIVATE
End Sub

Explicación:

SetWindowPos se utiliza para establecer la posición y el tamaño de una ventana/control.

hWndRTB es el identificador de la ventana del RichTextBox, que puedes obtener usando RichTextBox1.hWnd.

SWP_NOZORDER y SWP_NOACTIVATE son banderas que aseguran que el control no cambie su orden de Z (es decir, no se mueva al frente o al fondo) y que no active la ventana mientras se mueve.

Interceptar Mensajes WM_MOVE y WM_SIZE:
En el proceso de subclasificación, asegúrate de interceptar los mensajes WM_MOVE y WM_SIZE si necesitas realizar alguna acción específica cuando el control se mueva o cambie de tamaño. Aquí tienes un ejemplo básico de cómo hacerlo:

vb

Copiar

Private Const WM_MOVE As Long = &H3
Private Const WM_SIZE As Long = &H5

' En tu procedimiento de subclasificación
Select Case uMsg
Case WM_MOVE
' Realizar alguna acción cuando el RichTextBox se mueva
Case WM_SIZE
' Realizar alguna acción cuando el RichTextBox cambie de tamaño
End Select

Asegurarte de que el Código de Movimiento sea Atómico:
Cuando cambias la posición o el tamaño de un control subclaseado, debes asegurarte de que el proceso sea atómico para evitar múltiples redibujados que podrían causar parpadeo. La idea es:

Desactivar el redibujado antes de mover/cambiar el tamaño.

Realizar los cambios de posición o tamaño.

Reactivar el redibujado después de que los cambios hayan sido realizados.

vb

Copiar

Private Declare Function LockWindowUpdate Lib "user32" (ByVal hwndLock As Long) As Long

Private Sub UpdateRichTextBoxPosition(hWndRTB As Long, NewLeft As Long, NewTop As Long, NewWidth As Long, NewHeight As Long)
' Suspender el redibujado
LockWindowUpdate hWndRTB

' Cambiar la posición y el tamaño
MoveRichTextBox hWndRTB, NewLeft, NewTop, NewWidth, NewHeight

' Reactivar el redibujado
LockWindowUpdate 0

' Forzar un repintado
InvalidateRect hWndRTB, ByVal 0&, True
End Sub

En este ejemplo:

LockWindowUpdate se usa para suspender el redibujado del control durante el proceso de actualización de tamaño/posición.

InvalidateRect fuerza un repintado del control para asegurarse de que se vea correctamente actualizado.

Resumen

Las propiedades estándar (Left, Top, Width, Height) no funcionan bien en controles subclaseados porque los mensajes del sistema operativo que normalmente las actualizan están siendo desviados.

Utiliza la API SetWindowPos para gestionar directamente el movimiento y cambio de tamaño del RichTextBox.

Asegúrate de que los cambios sean atómicos, desactivando el redibujado mientras realizas el cambio y activándolo una vez termines.

Este enfoque debería permitirte mover y cambiar el tamaño del RichTextBox de manera efectiva sin depender de las propiedades estándar que pueden ser ignoradas por el subclasificado.

Dijiste:

Que mensaje WM_ es = 24?

ChatGPT dijo:

El mensaje WM_ cuyo valor es 24 es el WM_GETMINMAXINFO.

Descripción de WM_GETMINMAXINFO

Valor numérico: 0x24 (36 en decimal).

Función: WM_GETMINMAXINFO se envía a una ventana para que pueda determinar su tamaño y posición máximos y mínimos antes de que se cambie su tamaño o se mueva.

Uso: Se utiliza principalmente para restringir el tamaño y la posición de una ventana cuando el usuario la está redimensionando o moviendo, ya sea manualmente o mediante código.

El mensaje WM_GETMINMAXINFO permite al desarrollador especificar los límites que definen el tamaño mínimo y máximo que puede tener una ventana, así como el área de trabajo disponible en la pantalla.

Ejemplo de Uso

En una subclase de ventana, puedes interceptar WM_GETMINMAXINFO para establecer límites de tamaño:

vb

Copiar

Private Const WM_GETMINMAXINFO As Long = &H24

Private Sub WindowProc(ByVal hWnd As Long, ByVal uMsg As Long, ByVal wParam As Long, ByVal lParam As Long)
Select Case uMsg
Case WM_GETMINMAXINFO
' Definir un tamaño mínimo y máximo para la ventana
Dim mmi As MINMAXINFO
CopyMemory mmi, ByVal lParam, LenB(mmi)

' Establecer tamaño mínimo de la ventana (ej. 200x150 píxeles)
mmi.ptMinTrackSize.x = 200
mmi.ptMinTrackSize.y = 150

' Establecer tamaño máximo de la ventana (ej. 800x600 píxeles)
mmi.ptMaxTrackSize.x = 800
mmi.ptMaxTrackSize.y = 600

' Copiar la información modificada de vuelta
CopyMemory ByVal lParam, mmi, LenB(mmi)
End Select
End Sub

MINMAXINFO

El mensaje WM_GETMINMAXINFO usa una estructura llamada MINMAXINFO, que contiene la información de restricción de tamaño y posición. Aquí hay una descripción básica de sus principales campos:

ptMinTrackSize: Especifica el tamaño mínimo permitido para la ventana.

ptMaxTrackSize: Especifica el tamaño máximo permitido para la ventana.

Al interceptar WM_GETMINMAXINFO y modificar la estructura MINMAXINFO, puedes establecer límites para el tamaño y la posición de la ventana, lo cual es útil para evitar que el usuario redimensione la ventana a un tamaño no deseado.

Dijiste:

24 en decimal

ChatGPT dijo:

El mensaje WM_ cuyo valor es 24 en decimal corresponde a WM_SETREDRAW.

Descripción de WM_SETREDRAW

Valor numérico: 24 en decimal (0x18 en hexadecimal).

Función: WM_SETREDRAW se utiliza para habilitar o deshabilitar la actualización/redibujado de una ventana. Cuando el redibujado está deshabilitado, cualquier cambio en la interfaz de usuario no se muestra hasta que se vuelve a habilitar.

Este mensaje se utiliza cuando se necesita hacer una serie de cambios visuales y se desea evitar parpadeos causados por los múltiples redibujados intermedios. Una vez que se han realizado todos los cambios, se puede volver a habilitar el redibujado para actualizar la ventana de una sola vez.

Uso típico

WM_SETREDRAW se usa para optimizar el rendimiento cuando se realizan múltiples actualizaciones a un control o una ventana. Un ejemplo típico es cuando necesitas agregar muchos elementos a un ListBox o RichTextBox, y deseas evitar que el control se repinte por cada adición, lo cual puede causar parpadeos innecesarios.

Para enviar el mensaje WM_SETREDRAW a un control, puedes usar la API SendMessage:

vb

Copiar

Private Declare Function SendMessage Lib "user32" Alias "SendMessageA" _
(ByVal hWnd As Long, ByVal wMsg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long

Private Const WM_SETREDRAW As Long = 24

' Ejemplo para desactivar el redibujado
SendMessage RichTextBox1.hWnd, WM_SETREDRAW, 0, 0

' Realizar múltiples cambios...

' Ejemplo para activar el redibujado
SendMessage RichTextBox1.hWnd, WM_SETREDRAW, 1, 0

' Forzar el repintado
RichTextBox1.Refresh

Explicación

wParam = 0: Desactiva el redibujado.

wParam = 1: Activa el redibujado.

RichTextBox1.Refresh: Se llama para forzar la actualización visual del control después de que se hayan realizado todos los cambios.

Esto ayuda a evitar el parpadeo y mejora la eficiencia cuando se realizan cambios masivos o repetitivos en un control visual.

Dijiste:

Y 70 y 71 en decimal?

ChatGPT dijo:

Los mensajes WM_ cuyo valor es 70 y 71 en decimal son:

WM_WINDOWPOSCHANGING (Valor: 70 en decimal / 0x46 en hexadecimal)

Valor numérico: 70 en decimal (0x46 en hexadecimal).

Función: Este mensaje se envía a una ventana antes de que su posición o tamaño cambie. Proporciona una oportunidad para modificar la estructura de WINDOWPOS antes de que los cambios se apliquen.

Uso: Puedes usar WM_WINDOWPOSCHANGING para ajustar el comportamiento de cómo se mueve o redimensiona una ventana. Por ejemplo, para limitar el movimiento, ajustar el tamaño mínimo o evitar ciertos cambios específicos.

Ejemplo de cómo interceptar WM_WINDOWPOSCHANGING:

vb

Copiar

Private Const WM_WINDOWPOSCHANGING As Long = 70

' En tu procedimiento de subclasificación
Select Case uMsg
Case WM_WINDOWPOSCHANGING
' Se puede manipular la estructura de WINDOWPOS aquí para modificar el movimiento o redimensionado de la ventana
End Select

WM_WINDOWPOSCHANGED (Valor: 71 en decimal / 0x47 en hexadecimal)

Valor numérico: 71 en decimal (0x47 en hexadecimal).

Función: Este mensaje se envía a una ventana después de que su posición o tamaño haya cambiado.

Uso: Se utiliza para realizar acciones que dependen de que el control haya cambiado su posición o tamaño. A diferencia de WM_WINDOWPOSCHANGING, este mensaje se envía después de que la posición o tamaño haya cambiado, por lo que no se puede impedir o modificar el cambio en sí, solo reaccionar a él.

Ejemplo de cómo interceptar WM_WINDOWPOSCHANGED:

vb

Copiar

Private Const WM_WINDOWPOSCHANGED As Long = 71

' En tu procedimiento de subclasificación
Select Case uMsg
Case WM_WINDOWPOSCHANGED
' Realizar acciones después de que el control haya sido movido o redimensionado
End Select

Resumen

WM_WINDOWPOSCHANGING (70): Se envía antes de que cambien la posición o el tamaño de una ventana. Permite modificar el cambio antes de que se aplique.

WM_WINDOWPOSCHANGED (71): Se envía después de que la posición o el tamaño de una ventana hayan cambiado. Permite responder a los cambios.

Estos mensajes son útiles si necesitas un control más fino sobre cómo se comporta la ventana cuando se mueve o se cambia su tamaño, especialmente cuando estás trabajando con subclaseado.

Dijiste:

Ok...

ChatGPT dijo:

¡Me alegra que te haya servido la información! 😊

Si tienes alguna otra pregunta o necesitas más ayuda con el subclaseado o cualquier otro aspecto de tu proyecto, estaré encantado de asistirte. ¡Sigue adelante con tu buen trabajo y cualquier cosa aquí estoy!

Dijiste:

Me podrias dar las decalraciones de los 3?

ChatGPT dijo:

Claro, te proporcionaré las declaraciones necesarias para trabajar con los mensajes WM_GETMINMAXINFO, WM_WINDOWPOSCHANGING y WM_WINDOWPOSCHANGED. Aquí están las constantes y las estructuras involucradas, así como algunas declaraciones de funciones que serán útiles:

Constantes de los Mensajes

vb

Copiar

Private Const WM_GETMINMAXINFO As Long = &H24
Private Const WM_WINDOWPOSCHANGING As Long = &H46
Private Const WM_WINDOWPOSCHANGED As Long = &H47

Declaraciones de Funciones y Estructuras

Para trabajar con estos mensajes, necesitarás algunas estructuras y funciones API que te permitan manipular la información adecuadamente.

WM_GETMINMAXINFO - Estructura MINMAXINFO
Este mensaje usa la estructura MINMAXINFO, que define los límites de tamaño y posición.

vb

Copiar

Private Type POINTAPI
x As Long
y As Long
End Type

Private Type MINMAXINFO
ptReserved As POINTAPI
ptMaxSize As POINTAPI
ptMaxPosition As POINTAPI
ptMinTrackSize As POINTAPI
ptMaxTrackSize As POINTAPI
End Type

Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (Destination As Any, Source As Any, ByVal Length As Long)

La función CopyMemory (también conocida como RtlMoveMemory) se usa para copiar datos hacia y desde la estructura MINMAXINFO, ya que se pasa como un puntero.

WM_WINDOWPOSCHANGING y WM_WINDOWPOSCHANGED - Estructura WINDOWPOS
Estos mensajes usan la estructura WINDOWPOS, que contiene información sobre el tamaño y la posición de la ventana.

vb

Copiar

Private Type WINDOWPOS
hwnd As Long
hwndInsertAfter As Long
x As Long
y As Long
cx As Long
cy As Long
flags As Long
End Type

Campos de WINDOWPOS:

hwnd: Identificador de la ventana que está siendo movida o redimensionada.

hwndInsertAfter: Indicador del orden Z.

x, y: Coordenadas de la nueva posición de la esquina superior izquierda.

cx, cy: Nuevo ancho y alto de la ventana.

flags: Indicador de banderas que determinan cómo se aplica el movimiento o redimensionamiento.

Declaración de la API SendMessage y GetWindowLong
Utilizarás la función SendMessage para enviar mensajes a la ventana y GetWindowLong para obtener información sobre la ventana.

vb

Copiar

Private Declare Function SendMessage Lib "user32" Alias "SendMessageA" ( _
ByVal hWnd As Long, _
ByVal wMsg As Long, _
ByVal wParam As Long, _
lParam As Any) As Long

Private Declare Function GetWindowLong Lib "user32" Alias "GetWindowLongA" ( _
ByVal hWnd As Long, _
ByVal nIndex As Long) As Long

Constantes para GetWindowLong
Estas constantes te permitirán usar GetWindowLong para acceder a diferentes propiedades de la ventana.

vb

Copiar

Private Const GWL_STYLE As Long = (-16)
Private Const GWL_EXSTYLE As Long = (-20)

Ejemplo de Uso

Cuando estés subclaseando la ventana y necesites procesar estos mensajes, puedes usar el siguiente patrón:

vb

Copiar

Private Function WindowProc(ByVal hWnd As Long, ByVal uMsg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
Select Case uMsg
Case WM_GETMINMAXINFO
Dim mmi As MINMAXINFO
CopyMemory mmi, ByVal lParam, LenB(mmi)

' Establecer límites de tamaño, por ejemplo, mínimo de 300x200 y máximo de 800x600
mmi.ptMinTrackSize.x = 300
mmi.ptMinTrackSize.y = 200
mmi.ptMaxTrackSize.x = 800
mmi.ptMaxTrackSize.y = 600

CopyMemory ByVal lParam, mmi, LenB(mmi)

Case WM_WINDOWPOSCHANGING
Dim wp As WINDOWPOS
CopyMemory wp, ByVal lParam, LenB(wp)

' Puedes ajustar las coordenadas o tamaño antes de que se apliquen
' Por ejemplo, asegurarse de que la ventana no se mueva fuera de la pantalla

CopyMemory ByVal lParam, wp, LenB(wp)

Case WM_WINDOWPOSCHANGED
' Realiza alguna acción después de que la ventana haya cambiado de posición o tamaño
' Por ejemplo, forzar un repintado o ajustar alguna propiedad
End Select

' Llamar al procedimiento original para continuar con el procesamiento por defecto
WindowProc = CallWindowProc(PrevWndProc, hWnd, uMsg, wParam, lParam)
End Function

WM_GETMINMAXINFO: Utiliza CopyMemory para leer y escribir en la estructura MINMAXINFO para establecer límites de tamaño de la ventana.

WM_WINDOWPOSCHANGING y WM_WINDOWPOSCHANGED: También utilizan CopyMemory para manipular la estructura WINDOWPOS, permitiendo modificar el comportamiento antes (CHANGING) o reaccionar después (CHANGED) del cambio.

Estas declaraciones y ejemplos deberían ayudarte a manejar adecuadamente estos mensajes cuando estés trabajando con controles o ventanas subclaseadas en VB6.

Dijiste:

Y el de WM_SETREDRAW

ChatGPT dijo:

Claro, aquí te doy la declaración necesaria para trabajar con el mensaje WM_SETREDRAW.

WM_SETREDRAW

Valor numérico: 24 en decimal (0x18 en hexadecimal).

Función: Este mensaje se utiliza para habilitar o deshabilitar la actualización/redibujado de una ventana o control.

Declaración de WM_SETREDRAW

Primero necesitas definir la constante para el mensaje:

vb

Copiar

Private Const WM_SETREDRAW As Long = &H18

Declaración de la API SendMessage

Para enviar el mensaje WM_SETREDRAW a un control o ventana, debes usar la API SendMessage:

vb

Copiar

Private Declare Function SendMessage Lib "user32" Alias "SendMessageA" ( _
ByVal hWnd As Long, _
ByVal wMsg As Long, _
ByVal wParam As Long, _
ByVal lParam As Long) As Long

Uso de WM_SETREDRAW

El WM_SETREDRAW se utiliza para desactivar y reactivar el redibujado de un control o ventana. Esto es útil si deseas realizar varios cambios y luego actualizar el control solo una vez, evitando parpadeos.

wParam = 0: Deshabilita el redibujado.

wParam = 1: Habilita el redibujado.

Ejemplo de Uso

Supongamos que tienes un RichTextBox y quieres agregar múltiples líneas de texto sin que el control se redibuje cada vez:

vb

Copiar

' Desactivar redibujado
SendMessage RichTextBox1.hWnd, WM_SETREDRAW, 0, 0

' Realizar múltiples cambios en el RichTextBox
RichTextBox1.Text = RichTextBox1.Text & "Primera línea" & vbCrLf
RichTextBox1.Text = RichTextBox1.Text & "Segunda línea" & vbCrLf
RichTextBox1.Text = RichTextBox1.Text & "Tercera línea" & vbCrLf

' Activar redibujado
SendMessage RichTextBox1.hWnd, WM_SETREDRAW, 1, 0

' Forzar un repintado del control
RichTextBox1.Refresh

Explicación

Desactivar redibujado:

Enviando WM_SETREDRAW con wParam = 0, desactivas el redibujado del RichTextBox. Esto evita parpadeos durante múltiples cambios.

Realizar cambios:

Realiza todos los cambios que desees en el control sin que el control se redibuje cada vez.

Activar redibujado:

Enviando WM_SETREDRAW con wParam = 1, vuelves a activar el redibujado.

Forzar un repintado:

Finalmente, llama a RichTextBox1.Refresh para asegurarte de que el control se redibuje correctamente después de haber realizado todos los cambios.

Esta técnica es útil para evitar parpadeos cuando realizas una serie de modificaciones en un control visual.

Esta conversación está archivada. Para continuar, desarchívala primero.

Desarchivar

?