Not that easy, but doable. First of all, NVDA uses
watchdog.cancellableSendMessage function to send Windows messages. You
can search usages of this function in NVDA source code. I am actually
not sure why do they need this function instead of directly calling API,
but I assume they must have a reason.
As for passing structures, one example I found is
source\NVDAObjects\window\scintilla.py
numBytes = watchdog.cancellableSendMessage(self.obj.windowHandle,
SCI_GETTEXTRANGE, 0, internalTextRange)
You can probably find more examples in the source code. Also more people
are familiar with NVDA internals on nvda-addons mailing list.
HTH
On 1/28/2022 3:01 PM, Karl-Otto Rosenqvist wrote:
Thanks!** To leave the list, click on the immediately-following link:-
The first call was successful because it didn't need any params and it just returned an int.
the second one requires a struct to be passed and that struct needs to contain a string pointer so the text on the tab can be written to it.
I haven't been able to do this successfully.
The struct to be passed:
class TCITEMAStruct(Structure):
_fields_=[
("mask", c_uint),
('state', wintypes.DWORD),
('stateMask', wintypes.DWORD),
('text', c_char_p),
('textMax', c_int),
('image', c_int),
('lParam', wintypes.LPARAM),
]
If I do the following the host application crashes:
bufLen = 100
tcitemstruct = TCITEMAStruct()
tcitemstruct.mask = TCIF_TEXT
tcitemstruct.textMax = bufLen
buf = create_string_buffer(bufLen)
tcitemstruct.text = cast(buf, c_char_p)
got_it = winUser.sendMessage(obj.windowHandle, TCM_GETITEMA, tabidx , tcitemstruct)
In scintilla.py I found a way to do it by allocating memory for the process and it almost works:
bufLen = 100
tcitemstruct = TCITEMAStruct()
tcitemstruct.mask = TCIF_TEXT
tcitemstruct.textMax = bufLen
processHandle = obj.processHandle
internalBuf = winKernel.virtualAllocEx(processHandle, None, bufLen, winKernel.MEM_COMMIT, winKernel.PAGE_READWRITE)
try:
tcitemstruct.text = internalBuf
internalTCItem = winKernel.virtualAllocEx(processHandle, None, sizeof(tcitemstruct), winKernel.MEM_COMMIT, winKernel.PAGE_READWRITE)
try:
winKernel.writeProcessMemory(processHandle, internalTCItem, byref(tcitemstruct), sizeof(tcitemstruct), None)
got_it = winUser.sendMessage(obj.windowHandle, TCM_GETITEMW, tabidx , internalTCItem)
finally:
winKernel.virtualFreeEx(processHandle, internalTCItem, 0, winKernel.MEM_RELEASE)
buf = create_string_buffer(bufLen)
winKernel.readProcessMemory(processHandle, internalBuf, buf, bufLen, None)
finally:
winKernel.virtualFreeEx(processHandle, internalBuf, 0, winKernel.MEM_RELEASE)
if got_it:
ui.message("Got it!")
ui.message(buf)
The call is successful, i e got_it is true, but the buffer seems to be empty because NVDA doesn't say anything.
Does anyone have any idea on what's wrong here?
Kind regards
Karl-Otto
Karl-Otto Rosenqvist
MAWINGU
Orgnr: 750804-3937
0701- 75 98 56
karl-otto@xxxxxxxxxx
https://mawingu.se
Den 2022-01-28 kl. 18:00, skrev travis@xxxxxxxxxxxxxx:
In the case of NVDA, import winUser module. (You may also want to review it in the nvda \source folder.)** To leave the list, click on the immediately-following link:-
I'm not sure which method you need, perhaps getMessage() or sendMessage() will work.
NVDA has a lot of Windows helper function in winUser.py and something in there should do what you need.
-Travis
-----Original Message-----
From: program-l-bounce@xxxxxxxxxxxxx <program-l-bounce@xxxxxxxxxxxxx> On Behalf Of Karl-Otto Rosenqvist
Sent: Friday, January 28, 2022 10:48 AM
To: program-l@xxxxxxxxxxxxx
Subject: [program-l] Use Windows Message to get info från Python
Hi!
I'd like to enhance an add on I've created for NVDA and in order to get info about the selected tab and the text on that tab I need to send Windows Messages but I have no idea on how to do this in Python.
It is TCM_GETCURSEL and TCM_GETITEM I should use.
Thanks in advance
Karl-Otto
--
Karl-Otto Rosenqvist
MAWINGU
Orgnr: 750804-3937
0701- 75 98 56
karl-otto@xxxxxxxxxx
https://mawingu.se
** To leave the list, click on the immediately-following link:-
** [mailto:program-l-request@xxxxxxxxxxxxx?subject=unsubscribe]
** If this link doesn't work then send a message to:
** program-l-request@xxxxxxxxxxxxx
** and in the Subject line type
** unsubscribe
** For other list commands such as vacation mode, click on the
** immediately-following link:-
** [mailto:program-l-request@xxxxxxxxxxxxx?subject=faq]
** or send a message, to
** program-l-request@xxxxxxxxxxxxx with the Subject:- faq
** To leave the list, click on the immediately-following link:-
** [mailto:program-l-request@xxxxxxxxxxxxx?subject=unsubscribe]
** If this link doesn't work then send a message to:
** program-l-request@xxxxxxxxxxxxx
** and in the Subject line type
** unsubscribe
** For other list commands such as vacation mode, click on the
** immediately-following link:-
** [mailto:program-l-request@xxxxxxxxxxxxx?subject=faq]
** or send a message, to
** program-l-request@xxxxxxxxxxxxx with the Subject:- faq
** [mailto:program-l-request@xxxxxxxxxxxxx?subject=unsubscribe]
** If this link doesn't work then send a message to:
** program-l-request@xxxxxxxxxxxxx
** and in the Subject line type
** unsubscribe
** For other list commands such as vacation mode, click on the
** immediately-following link:-
** [mailto:program-l-request@xxxxxxxxxxxxx?subject=faq]
** or send a message, to
** program-l-request@xxxxxxxxxxxxx with the Subject:- faq