[Risolto] Movimento ScrollBar Orizzontale da VBA

di il
6 risposte

[Risolto] Movimento ScrollBar Orizzontale da VBA

Un saluto a tutti.

Esiste un comando VBA per spostare la Scrollbar Orizzontale di una form in un determinato punto (in particolare all'estrema sinistra) ?

Attualmente uso una specie di "workaround" e ottengo l'effetto voluto:
1) setto la proprietà left di un controllo in maschera;
2) Faccio setfocus sul controllo appena spostato.

Poco elegante ma efficace.

Altri suggerimenti?

6 Risposte

  • Re: [Risolto] Movimento ScrollBar Orizzontale da VBA

    Tecnicamente il modo giusto è inviare all'handle della ScrollBar un messaggio con il Valore... si tratta di scrivere qualche riga di chiamate API per recuperare l'Hwnd della HorizontalScrollBar ed usare SendMessage per poi inviare all'handle il valore.
    
    Public Const SB_THUMBPOSITION = 4
    lngRet = SendMessage(lngScrollHwnd, WM_HSCROLL, (lngNewPos * 65536) + SB_THUMBPOSITION, 0)
    Il propblema è recuperare l'hWnd della ScrollBar.... che ha cambiato ClassName con le Versioni...
    Usavo SPY++ per queste cose... la Scroll si cerca tra i Child della Form in cui risiede, puntando all'hWnd con ClassName "NUIScrollbar"

    Non è una cosa banalissima... e francamente non mi sento di suggerirtela... ma funziona bene.
    Altrimenti qualche cosa di EMPIRICO, è usare SelLeft di Maschera... ma non è così banale in quanto il riferimento è relativo e cambia... tuttavia si può memorizzare la posizione ZERO, tutto a Sinistra e da li muoverla...
  • Re: [Risolto] Movimento ScrollBar Orizzontale da VBA

    Errata Corrige non era SelLeft ma CurrentSectionLeft.... ma devi fare qualche prova... io uso le API per mia abitudine.
  • Re: [Risolto] Movimento ScrollBar Orizzontale da VBA

    Ciao Alex,
    ti ringrazio per le indicazioni che mi hai fornito.

    Sono riuscito ad implementare la parte EMPIRICA ma sono incuriosito anche da quella che utilizza la API (x mia formazione (o deformazione professionale )

    Lo scenario in cui opero è il seguente;
    Nella form "frm_MAIN" ho una subform per la quale vorrei poter controllare lo scroll orizzontale

    Sperando che io abbia effettivamente individuato la voce giusta nel TV di SPY++, volevo chiederti quali valori di quelli riportati in immagine devo considerare... è la 1 volta che mi cimento nell'uso di SPY.
    Allegati:
    13935_0d43aeb7743920398a565c7c4c285c98.jpg
    13935_0d43aeb7743920398a565c7c4c285c98.jpg

    13935_4e84ef76e8ed91501197d9cb2ea64ad3.jpg
    13935_4e84ef76e8ed91501197d9cb2ea64ad3.jpg

    13935_587877087ea56959a7230a60b16709c5.jpg
    13935_587877087ea56959a7230a60b16709c5.jpg
  • Re: [Risolto] Movimento ScrollBar Orizzontale da VBA

    Come vedi [00260894] è l'Handle della ScrollBar Orizzontale, ma la cosa che importa per te è il ClassName che appunto è quello che dicevo prima.
    Non vorrei scoraggiarti ma i messaggi del S.O. non sono immediati da interpretare...
    Sostanzialmente con SPY riesci ad analizzare o filtrare i messaggi dei singoli hWnd, e dovresti, filtrando la ScrollBar, riuscire a vedere quando la muovi i messaggi del S.O.
    Per inviare i messaggi, che sono tutti codificati in MSDN, si può usare SendMessage.
    IN sostanza analizzando i messaggi puoi capire come inviare alla ScrollBar la posizione... ma credo servirà qualche cosa in più di una chiacchiera come questa.
    Io ci giocavo qualche decina di anni fa quando mi divertivo con il SubClassing... ora nemmeno ci penserei più...

    In ogni caso, ti risparmio molto lavoro ma al contempo potrai trovare conferme con Spy di quanto ho detto.
    Scarica qusto demo:
    http://codekabinett.com/page.php?Theme=10&Lang=2#Microsoft-Access-Sync-ScrollBars-Sample
    Lascia perdere che simula la sincronizzazione di 2 ScrollBar di 2 SubForm, sfruttando il Timer in quanto il SubCLassing con Access è da evitare..., quello che interessa al tuo scopo sono poche cose, ovvero il contenuto del Modulo [modScrollBar] ed ovviamente come agisce l'Evento Timer della Form [frmScrollMaster] in quanto muovendo una sincronizza l'altra...

    Buon divertimento.
  • Re: [Risolto] Movimento ScrollBar Orizzontale da VBA

    Ciao, alla fine mi sono divertito sul serio!!!

    Non mi sono limitato a studiare solo il modo di settare il valore della scroll ma ho studiato anche quello relativo alla lettura della posizione attuale perchè credo che lo riutilizzerò.

    Per il settaggio della posizione della Scroll credo sia sufficiente conoscere anche solo HWND della maschera che lo ospita (io ho dovuto accedere a quello della subform).
    ' Dichiarazione personalizzata per funzionare in SO 64 bit
    Public Declare PtrSafe Function SendMessage Lib "user32" Alias "SendMessageA" (ByVal hwnd As Long, ByVal wMsg As Long, ByVal wParam As Long, lParam As Any) As Long
    
    Public Const WM_HSCROLL = &H114
    Public Const SB_THUMBPOSITION = 4
    
    Dim lngRetVal As Long
    'Posizione rappresenta il valore che deve assumere la scrollbar
    lngRetVal = SendMessage(Me.SubForm.Form.hwnd, WM_HSCROLL, MakeDWord(Posizione, SB_THUMBPOSITION), 0)
    
    Per la parte relativa alla lettura della posizione invece:

    E' necessario HWND della scrollbar solo quando si vuole leggere il valore attualmente impostato nella stessa.
    In tal caso sarà necessario richiamare anche EnumChildWindows, GetWindowLong, GetClassName e GetScrollPos.
    in particolare segnalo che, nel caso dei SO 64 bit la funzione "EnumChildWindows" andrà richiamata come segue:
    Public Declare PtrSafe Function EnumChildWindows Lib "user32" (ByVal hWndParent As LongPtr, ByVal lpEnumFunc As LongPtr, ByVal lParam As LongPtr) As Long
    e non
    Public Declare PtrSafe Function EnumChildWindows Lib "user32" (ByVal hWndParent As Long, ByVal lpEnumFunc As Long, ByVal lParam As Long) As Long
    Analizzando il codice del file scaricato nel link che mi hai proposto ho capito che:
    - HWND è un valore variabile che cambia ogni volta che sia apre la maschera;
    - Conoscere il ClassName è necessario in quanto, altrimenti, non si ha un valore di riferimento con cui confrontare quello degli oggetti figlio, e quindi a ricavarene il relativo HWND necessario alla lettura delle relative informazioni (questo avviene nella funzione cwCBProc)
    - Per conoscere i ClassName Spi++ può essere unostrumento valido;
    - il 2 parametro della funzione "findscrollbar" avente valore "AddressOf cwCBProc", nel momento in cui viene eseguita l'istruzione EnumChildWindows serve a determinare hwnd (ma quin non ho capito bene come funziona il tutto anche se ne intuisco il funzionamento... magari mi confonde "AddressOf");


    Ho vuoluto elencare queste considerazioni per avere conferma che effettivamente ho intuito bene il codice proposto nel link che mi hai suggerito e per condividere con chi dovesse incorrere nelle stesse necessità.

    Grazie.
  • Re: [Risolto] Movimento ScrollBar Orizzontale da VBA

    Angelo_Tbp ha scritto:


    Ciao, alla fine mi sono divertito sul serio!!!
    ....
    Analizzando il codice del file scaricato nel link che mi hai proposto ho capito che:
    - HWND è un valore variabile che cambia ogni volta che sia apre la maschera;
    il S.O. di Windows funziona a Puntatori... ogni Oggetto ha un Pointer, che rappresenta la PK dello stesso, è un numero Long o LongPrt a seconda dei BIT del S.O.
    Quindi a parte Access che lavora in modo un po strano con i propri oggetti o Excel che(le UserForms) sono WindowLess, tutto il resto funziona così...
    Di fatto per puntare ad un Oggetto si usa l'hWnd(Handle), per oggetto si intende Maschera,Controlli e quant'altro abbia un'interfaccia grafica.
    Dicevo di Access che è strano in quanto ha una definizione degli hwnd solo per la Form, tutti gli altri controlli come TextBox ecc sono disegnati, ed acquisiscono l'hwnd solo nel momento in cui assumono il focus, quindi risulta sempre molto complicato interacire con Access e le API.

    Angelo_Tbp ha scritto:


    - Conoscere il ClassName è necessario in quanto, altrimenti, non si ha un valore di riferimento con cui confrontare quello degli oggetti figlio, e quindi a ricavarene il relativo HWND necessario alla lettura delle relative informazioni (questo avviene nella funzione cwCBProc)
    - Per conoscere i ClassName Spi++ può essere unostrumento valido;
    - il 2 parametro della funzione "findscrollbar" avente valore "AddressOf cwCBProc", nel momento in cui viene eseguita l'istruzione EnumChildWindows serve a determinare hwnd (ma quin non ho capito bene come funziona il tutto anche se ne intuisco il funzionamento... magari mi confonde "AddressOf");[/code]
    L'operatore "AddressOf" non è altro che un esecutore, che effettua una chiamata o CallBack alla Funzione [cwCBProc].
    Quì vengono ciclati gli HandleChild, e cerca l'andle cel ClassName della Scrollbar, e, se l'handle ha ClassName della ScrollBar lo assegna alla proprietà della Form [HScollBarHWnd].

    Angelo_Tbp ha scritto:


    Ho vuoluto elencare queste considerazioni per avere conferma che effettivamente ho intuito bene il codice proposto nel link che mi hai suggerito e per condividere con chi dovesse incorrere nelle stesse necessità.
    Grazie.
    [/quote]
    Spero sia sufficiente.

    @Alex
Devi accedere o registrarti per scrivere nel forum
6 risposte