EM_GETSEL

Alles over het toepassen van API en DLL's in Liberty BASIC

Moderator: anthonio

EM_GETSEL

Berichtdoor glpape » zo jan 06, 2013 5:15 pm

Iets over het EM_GETSEL message. Deze msg intrigeert me, lees verder.
EM_GETSEL vraagt de positie op van de geselecteerde text in een Edit control.

Je verzendt de msg met de API functie "SendMessage". Zoals voor alle API calls die zich met text bemoeien moet er een A achter, voor ANSI (dus "SendMessageA"; Unicode zou W zijn).

Dit is de "SendMessage" call:

Code: Selecteer alles
calldll #user32, "SendMessageA", h as ulong, msg as long, _
        wparam as type, lparam as type, rtn as type


Vier parameters:
1. h is de handle van het venster waar de msg betrekking op heeft;
2. msg is de message: bv WM_CLOSE (WindowMessage) of EM_GETSEL (EditMessage);
3. wparam is een 32-bit parameter in 32-bits Windows. Type is meestal ulong maar kan ook een ptr of struct zijn. De w staat voor word, een 16-bit unsigned data type, voorheen; nu dus 32-bits maar de naam is gebleven.
4. lparam is ook 32-bit; de l staat voor long, een 32-bit signed datatype in 32 bits Windows.
[met 64-bit Windows heb ik geen ervaring, ik ben nog Windows-XP].
En dan de return, die is, als altijd in een functie, een enkel getal.

Per message verschillen wparam en lparam en de return; dit wordt aangegeven in de MSDN documentatie voor elke msg.
wparam en lparam vragen soms input, geven soms output, zijn soms gewoon NULL.

EM_GETSEL geeft 2 antwoorden: de positie van het laatste teken voor de selectie, en die van het laatste teken van de selectie.
En nu waarom de functie me intrigeert: deze antwoorden worden, heel ongewoon, op 2 manieren gepresenteerd:
= in de return, als een dword (DoubleWord), 32-bits, unsigned, dus <<as ulong>> in Lbty.
= in wparam en in lparam in de vorm van pointers naar numerieke waarden.

Eerst de dword. Die bestaat uit een high-order word en een low-order word (elk 16-bits), als volgt:
dword = loword + hiword*2^16.
Alles moet immers in een getal: kun je invoeren als parameter in een commando of kan de return van een functie zijn: altijd een enkel getal.
Dit is een vaak gebruikte Windows truc; op dergelijke manier organiseert Windows bv kleuren in een RGB-value:
r + g*256 + b*256*256 [r, g en b zijn elk waarden van 0-255]. Met een beetje puzzelen maak je zelf functies die r, g en b, of hiword en loword weer terug rekenen.

MSDN beveelt aan om de antwoorden te halen uit wparam en lparam, want een hiword en loword kunnen elk tellen tot maximaal 2^16 posities (0 - 65.535); als je meer letters invoert krijg je rare, foutieve returns. wparam gaat van 0 tot (2^32)-1, een paar miljard. Ik heb het geprobeerd tot 800.000 letters in een t.box, via wparam en lparam, het werd een beetje tijdrovend maar werkte prima.

Hier een voorbeeld waar je de positie van de selectie ophaalt uit de return. wparam en lparam heb je nu niet nodig en die mogen gewoon NULL zijn.
Type wat text in, selecteer een deel, en klik op de knop.
De return moet <<as ulong>>, voor waarden van 0 tot (2^32)-1. Indien <<as long>> dan wordt dit -(2^32)/2 tot ((2^32)/2)-1, en worden hiword en loword ook terug gebracht tot de helft.


Code: Selecteer alles
REM   Uses de return van  <<EM_GETSEL>>  to get selected text.

button  #W.b1, "G O", [Go], UL, 33, 99, 44, 33
textbox #W.t1, 33, 55, 222, 33
open "" for window as #W
#W "trapclose [qq]"
#W.t1 "!font courier_new 12"

wait
[qq]  Close #W  :  End


[Go]
hWt1 = hwnd(#W.t1)
calldll #user32, "SendMessageA", hWt1 as ulong, _
        _EM_GETSEL as long, _0 as ulong, 0 as long, rtn as ulong
first = lo(rtn)
last = hi(rtn)
print "first is : "; first
print "last is : "; last
wait


'  * * * * * * * * * * * * * * *  Functions  * * * * * * * * * *
Function hi(k)         ' extracts the hi-order word from a dword
hi = int(k/2^16)
End Function

Function lo(k)         ' extracts the lo-order word from a dword
lo = k mod 2^16
End Function


Nu met wparam en lparam. Lbty kent het data type ptr (32-bits) voor de positie in memory van een string. Maar dit zijn pointers naar getallen, en dan heb je in Lbty een struct nodig. We gebruiken dus een "single-member struct". Niet speciaal moeilijk maar wel weer meer toets aanslagen:

Code: Selecteer alles
REM   Uses wparam & lparam to get selected text.

button #W.b1, "G O", [Go], UL, 33, 99, 44, 33
textbox #W.t1, 33, 55, 222, 33
open "" for window as #W
#W "trapclose [qq]"
#W.t1 "!font courier_new 12"

wait
[qq]  Close #W  :  End


[Go]
hWt1 = hwnd(#W.t1)
struct F, frst as long
struct L, last as long
calldll #user32, "SendMessageA", hWt1 as ulong, _
  _EM_GETSEL as long, F as struct, L as struct, rtn as ulong
first = F.frst.struct
last  = L.last.struct
print "first is : "; first
print "last is  : "; last
wait


Tenslotte, belangrijk, EM_GETSEL is ook een simpele manier om de positie van de caret in een Edit Control te bepalen: als er geen text is geselecteerd krijg je als startpositie en als eindpositie hetzelfde getal: de positie van de caret.

Vr groet,

George Pape.
glpape
 
Berichten: 83
Geregistreerd: za nov 08, 2008 5:32 pm

Keer terug naar API/DLL

Wie is er online

Gebruikers op dit forum: Geen geregistreerde gebruikers. en 2 gasten

cron