[Rd] Rgui.exe 4.2.0 does not receive characters via the Windows API's PostMessage function
Tomas Kalibera
tom@@@k@||ber@ @end|ng |rom gm@||@com
Mon May 16 19:21:28 CEST 2022
Dear Jose,
On 5/15/22 01:31, jcfaria wrote:
> Dear Tomas,
>
> I am very grateful for your attention!
>
> I've been reading some things about the GraphApp
> toolkit(http://enchantia.com/software/graphapp/) that is being used in
> the development of new versions of Rgui.
>
> Really, if it's a matter of choice, the problems I reported cannot be
> considered a "bug". It's up to us - GUI and IDE application developers
> - to adapt to the new features.
>
> I'm studying how to get around the problem, but I still haven't found
> a simple way.
>
> The solution you proposed (code below) ran fine here in all versions
> of Rgui I have installed, but it's working only for very simple
> strings, like the one I tested. When testing the needs close to the
> real I found some problems.
>
> For example, when sending the string below:
> - char *s = "(s <- c('á', 'b', 'c', 'í'))";
>
> Rgui receives:
> > 9s ,- c9'', 'b', 'c', ''00
> Error: unexpected symbol in "9s"
> >
>
>
> #include <windows.h>
> #include <stdio.h>
> #include <string.h>
>
> int main(int argc, char **argv) {
> HWND hw;
> int i, res;
>
> printf("Getting Rgui window...\n");
> hw = FindWindow(NULL, "R Console (64-bit)");
>
> printf("Got window: %x\n", hw);
> if (hw == NULL) {
> printf("Could not get Rgui window: %x\n", GetLastError());
> return 2;
> }
>
> //Samples to send:
> // char *s = "sd";
> char *s = "(s <- c('á', 'b', 'c', 'í'))";
>
> for(i = 0; i < strlen(s); i++) {
> res = PostMessage(hw, WM_KEYDOWN, VkKeyScan(s[i]), 0);
> printf("Sending char %c: %d.\n", s[i], res);
> }
>
> res = PostMessage(hw, WM_KEYDOWN, VK_RETURN, 0);
> printf("Sending return: %d\n.", res);
> return 0;
> }
>
> The idea of Tinn-R communicating with Rgui.exe is to take advantage of
> the great stability of Rgui. Since communication with Rterm is done
> via pipe.
>
> I believe that developing a new interface using the resources of the
> R.dll library, as proposed, is outside the simple purposes of the
> Tinn-R project.
>
> Any help in this regard is welcome.
If embedding R seems too involved, and the hack above doesn't work well
enough, perhaps you could use SendInput() (also mentioned in the blog
post [1] below as a more correct way to inject input as WM_KEYDOWN).
This is an example:
---
#include <windows.h>
#include <stdio.h>
int main(int argc, char **argv) {
HWND hw, ow;
int i, res;
hw = FindWindow(NULL, "R Console (64-bit)");
if (hw == NULL) {
printf("Could not get Rgui window: %x\n", GetLastError());
return 2;
}
ow = GetForegroundWindow();
if (ow == NULL)
printf("Foreground window is NULL\n");
if (!SetForegroundWindow(hw))
printf("Could not set Rgui as foreground window\n");
char *sd = "sd";
for(i = 0; i < strlen(sd); i++) {
INPUT input;
ZeroMemory(&input, sizeof(INPUT));
input.type = INPUT_KEYBOARD;
input.ki.dwFlags = KEYEVENTF_UNICODE;
input.ki.wScan = (unsigned) sd[i];
res = SendInput(1, &input, sizeof(INPUT));
printf("Sending char %c (%x): %d.\n", sd[i], sd[i], res);
}
{
INPUT input[2];
ZeroMemory(input, 2*sizeof(INPUT));
input[0].type = input[1].type = INPUT_KEYBOARD;
input[1].ki.dwFlags = KEYEVENTF_KEYUP;
input[0].ki.wVk = input[1].ki.wVk = VK_RETURN;
res = SendInput(2, input, sizeof(INPUT));
printf("Sending return: %d.\n", res);
}
if (!SetForegroundWindow(ow))
printf("Could not set the original window as foreground");
return 0;
}
---
This example works for me with R 4.1.3 and with R-devel 82368. It
doesn't work with R 4.2.0 (see a related thread about Dasher on this list).
Best
Tomas
>
> Best,
> ///\\\///\\\///\\\///\\\///\\\///\\\///\\\///\\\///\\\///\\\
> Jose Claudio Faria
> UESC/DCET/Brasil
> joseclaudio.faria at gmail.com
> Telefones:
> 55(73)3680.5545 - UESC
> 55(73)99966.9100 - VIVO
> ///\\\///\\\///\\\///\\\///\\\///\\\///\\\///\\\///\\\///\\\
> If you have software to deal with statistics, you have arms,
> if you have good software, you have arms and legs,
> if you have software like R, you have arms, legs and wings...
> the height of your flight depends only on you.
>
> ------ Mensagem original ------
> De: "Tomas Kalibera" <tomas.kalibera using gmail.com>
> Para: "jcfaria" <joseclaudio.faria using gmail.com>; "Duncan Murdoch"
> <murdoch.duncan using gmail.com>; r-devel using r-project.org
> Enviado(s): 11/05/2022 13:32:23
> Assunto: Re: [Rd] Rgui.exe 4.2.0 does not receive characters via the
> Windows API's PostMessage function
>
>>
>> On 5/11/22 15:39, Tomas Kalibera wrote:
>>>
>>> On 5/11/22 08:15, Tomas Kalibera wrote:
>>>>
>>>> On 5/11/22 03:02, jcfaria wrote:
>>>>> Dear Tomas,
>>>>> I've tried, but I don't have the necessary C/C++ programming
>>>>> skills to fulfill your request.
>>>>>
>>>>> Maybe someone can help us by transcribing the little code in
>>>>> object Pascal that I sent to C/C++.
>>>>>
>>>>> If a small executable, made in Object Pascal, can help in your
>>>>> debug, I can provide.
>>>>
>>>> Dear Jose,
>>>>
>>>> no problem, I can try out with the Pascal code.
>>>> Is there a free compiler I can use to build and run it?
>>>
>>> Actually I can reproduce it in a C program doing the same thing.
>>>
>>> The primary cause is that Rgui is using GraphApp Unicode windows on
>>> systems running in a multi-byte locale, which affects most systems
>>> since R 4.2 because of the switch to UTF-8. While Unicode windows
>>> have been used even in older versions of R, it was only on systems
>>> then running in a multi-byte locale, and apparently this hasn't been
>>> reported.
>>>
>>> When I modify R-devel to use non-Unicode GraphApp windows, the
>>> message sending works again. I will have a closer look, thanks for
>>> the report.
>>
>> I had a closer look and this doesn't really seem to be a bug in R to
>> me. For Unicode Windows, GraphApp uses WM_IME_COMPOSITION messages to
>> read the keys instead of WM_CHAR, which it uses for non-Unicode
>> windows. This is internal functionality of Rgui and a legitimate
>> choice. Rgui cannot simply handle both messages in Unicode windows,
>> because the characters would be doubled (if you see an easy, elegant
>> change to Rgui that would mimic the previous behavior, let me know).
>> This is certainly not a documented interface for Rgui, so I am afraid
>> you would have to change something in your application.
>>
>> I read that using PostMessage to simulate keyboard input is
>> considered wrong, see [1], and then one should instead use SendInput
>> (which then requires bringing the window to the foreground), if at
>> all simulating keyboard input. Maybe one could create a better
>> working solution that way, or using some automation library.
>>
>> As a quick hack, I found that [2] happens to be working on my system,
>> but again relying on the current implementation of Rgui (simply you
>> send WM_KEYDOWN also for the characters other than the
>> newline/return). It seems to be working also with R 4.1 for me.
>>
>> The usual way for GUIs/front-ends is to "embed" R, to link it as a
>> DLL. Rgui itself does it and also external applications such as
>> RStudio. Typically you would want to have a thin layer application
>> embedding R and make your GUI communicate with that, but switching to
>> that from sending the messages would require some work.
>>
>> Best
>> Tomas
>>
>> [1] https://devblogs.microsoft.com/oldnewthing/20050530-11/?p=35513
>>
>> [2]
>> #include <windows.h>
>> #include <stdio.h>
>> #include <string.h>
>>
>> int main(int argc, char **argv) {
>> HWND hw;
>> int i, res;
>>
>> printf("Getting Rgui window...\n");
>> hw = FindWindow(NULL, "R Console (64-bit)");
>>
>> printf("Got window: %x\n", hw);
>> if (hw == NULL) {
>> printf("Could not get Rgui window: %x\n", GetLastError());
>> return 2;
>> }
>>
>> char *sd = "sd";
>> for(i = 0; i < strlen(sd); i++) {
>> res = PostMessage(hw, WM_KEYDOWN, VkKeyScan(sd[i]), 0);
>> printf("Sending char %c: %d.\n", sd[i], res);
>> }
>>
>> res = PostMessage(hw, WM_KEYDOWN, VK_RETURN, 0);
>> printf("Sending return: %d\n.", res);
>> return 0;
>> }
>>
>>
>>>
>>> For reference, to reproduce I ran
>>>
>>> Rgui --sdi
>>>
>>> and used this C example:
>>>
>>> #include <windows.h>
>>> #include <stdio.h>
>>> #include <string.h>
>>>
>>> int main(int argc, char **argv) {
>>> HWND hw;
>>> int i, res;
>>>
>>> printf("Getting Rgui window...\n");
>>> hw = FindWindow(NULL, "R Console (64-bit)");
>>>
>>> printf("Got window: %x\n", hw);
>>> if (hw == NULL) {
>>> printf("Could not get Rgui window: %x\n", GetLastError());
>>> return 2;
>>> }
>>>
>>> char *sd = "sd";
>>> for(i = 0; i < strlen(sd); i++) {
>>> res = PostMessage(hw, WM_CHAR, (unsigned int) sd[i], 0);
>>> printf("Sending char %c: %d.\n", sd[i], res);
>>> }
>>>
>>> res = PostMessage(hw, WM_KEYDOWN, VK_RETURN, 0);
>>> printf("Sending return: %d\n.", res);
>>> return 0;
>>> }
>>>
>>> Best
>>> Tomas
>>>
>>>
>>>>
>>>> Thanks
>>>> Tomas
>>>>
>>>>>
>>>>> Grateful for the attention,,
>>>>> ///\\\///\\\///\\\///\\\///\\\///\\\///\\\///\\\///\\\///\\\
>>>>> Jose Claudio Faria
>>>>> UESC/DCET/Brasil
>>>>> joseclaudio.faria at gmail.com
>>>>> Telefones:
>>>>> 55(73)3680.5545 - UESC
>>>>> 55(73)99966.9100 - VIVO
>>>>> ///\\\///\\\///\\\///\\\///\\\///\\\///\\\///\\\///\\\///\\\
>>>>> If you have software to deal with statistics, you have arms,
>>>>> if you have good software, you have arms and legs,
>>>>> if you have software like R, you have arms, legs and wings...
>>>>> the height of your flight depends only on you.
>>>>>
>>>>> ------ Mensagem original ------
>>>>> De: "Tomas Kalibera" <tomas.kalibera using gmail.com>
>>>>> Para: "jcfaria" <joseclaudio.faria using gmail.com>; "Duncan Murdoch"
>>>>> <murdoch.duncan using gmail.com>; r-devel using r-project.org
>>>>> Enviado(s): 06/05/2022 04:24:44
>>>>> Assunto: Re: [Rd] Rgui.exe 4.2.0 does not receive characters via
>>>>> the Windows API's PostMessage function
>>>>>
>>>>>>
>>>>>> On 5/6/22 07:03, jcfaria wrote:
>>>>>>> Dear Duncan,
>>>>>>> I believe the problem is of a different nature.
>>>>>>> I get TRUE 3 times running the code below:
>>>>>>>
>>>>>>> procedure TfMain.btnPasteClick(Sender: TObject);
>>>>>>> var
>>>>>>> i: integer;
>>>>>>> sTmp: string;
>>>>>>> hBN: HWND;
>>>>>>> j: bool;
>>>>>>>
>>>>>>> begin
>>>>>>> hBN:= FindWindowA(nil,
>>>>>>> 'R Console (64-bit)');
>>>>>>>
>>>>>>> sTmp:= 'sd';
>>>>>>>
>>>>>>> for i:= 1 to Length(sTmp) do begin
>>>>>>> j:= PostMessage(hBN,
>>>>>>> WM_CHAR,
>>>>>>> Ord(sTmp[i]),
>>>>>>> 0);
>>>>>>>
>>>>>>> ShowMessage(BoolToStr(j,
>>>>>>> True));
>>>>>>> end;
>>>>>>>
>>>>>>> j:= PostMessage(hBN,
>>>>>>> WM_KEYDOWN,
>>>>>>> VK_RETURN, 0);
>>>>>>>
>>>>>>> ShowMessage(BoolToStr(j,
>>>>>>> True));
>>>>>>> end;
>>>>>>>
>>>>>>> That is, Rgui is receiving the message of the characters (via
>>>>>>> PostMessage), but it is blocking because it does not show them
>>>>>>> in the console.
>>>>>>> The only thing Rgui blames is Carriage Return, as it adds an
>>>>>>> additional prompt with each run.
>>>>>>
>>>>>> I can't provide a good guess what impacted your use, but if you
>>>>>> could give me a full example, ideally in C, which can be compiled
>>>>>> with Rtools42 (so gcc, MinGW) and I can edit/recompile, and works
>>>>>> with R 4.1, I am happy to help debugging on 4.2.
>>>>>>
>>>>>> Rgui now uses GraphApp Unicode windows on systems where it didn't
>>>>>> before, because it uses UTF-8 also on systems it didn't before
>>>>>> (on systems that would use a single-byte locale in R 4.1). These
>>>>>> Unicode windows are a different code path and there may be bugs
>>>>>> not reported previously, including processing inputs (recently I
>>>>>> fixed handling of accents, for example). Otherwise indeed R now
>>>>>> uses UTF-8 as native encoding and UCRT as the C runtime.
>>>>>>
>>>>>> Best
>>>>>> Tomas
>>>>>>
>>>>>>
>>>>>>>
>>>>>>> >
>>>>>>> >
>>>>>>>
>>>>>>> Best,
>>>>>>> ///\\\///\\\///\\\///\\\///\\\///\\\///\\\///\\\///\\\///\\\
>>>>>>> Jose Claudio Faria
>>>>>>> UESC/DCET/Brasil
>>>>>>> joseclaudio.faria at gmail.com
>>>>>>> Telefones:
>>>>>>> 55(73)3680.5545 - UESC
>>>>>>> 55(73)99966.9100 - VIVO
>>>>>>> ///\\\///\\\///\\\///\\\///\\\///\\\///\\\///\\\///\\\///\\\
>>>>>>> If you have software to deal with statistics, you have arms,
>>>>>>> if you have good software, you have arms and legs,
>>>>>>> if you have software like R, you have arms, legs and wings...
>>>>>>> the height of your flight depends only on you.
>>>>>>>
>>>>>>> ------ Mensagem original ------
>>>>>>> De: "Duncan Murdoch" <murdoch.duncan using gmail.com>
>>>>>>> Para: "jcfaria" <joseclaudio.faria using gmail.com>;
>>>>>>> r-devel using r-project.org
>>>>>>> Enviado(s): 05/05/2022 13:17:53
>>>>>>> Assunto: Re: [Rd] Rgui.exe 4.2.0 does not receive characters via
>>>>>>> the Windows API's PostMessage function
>>>>>>>
>>>>>>>> On 05/05/2022 11:17 a.m., jcfaria wrote:
>>>>>>>>> Hello,
>>>>>>>>>
>>>>>>>>> Rgui.exe 4.2.0 does not receive characters via the Windows API's
>>>>>>>>> PostMessage function.
>>>>>>>>>
>>>>>>>>> The Tinn-R project sends messages to Rgui.exe (SDI mode) via
>>>>>>>>> the Windows
>>>>>>>>> API's PostMessage function.
>>>>>>>>> A simplification of the code (in object Pascal) can be seen
>>>>>>>>> below.
>>>>>>>>>
>>>>>>>>> procedure TfMain.btnPasteClick(Sender: TObject);
>>>>>>>>> var
>>>>>>>>> i: integer;
>>>>>>>>> sTmp: WideString;
>>>>>>>>> hBN: HWND;
>>>>>>>>>
>>>>>>>>> begin
>>>>>>>>> hBN:= FindWindowA(nil,
>>>>>>>>> 'R Console (64-bit)');
>>>>>>>>>
>>>>>>>>> sTmp:= 'sd';
>>>>>>>>>
>>>>>>>>> for i:= 1 to Length(sTmp) do begin
>>>>>>>>> PostMessage(hBN,
>>>>>>>>> WM_CHAR,
>>>>>>>>> Ord(sTmp[i]),
>>>>>>>>> 0);
>>>>>>>>> end;
>>>>>>>>>
>>>>>>>>> PostMessage(hBN,
>>>>>>>>> WM_KEYDOWN,
>>>>>>>>> VK_RETURN, 0);
>>>>>>>>> end;
>>>>>>>>>
>>>>>>>>> This code has always worked fine for all versions of Rgui.exe
>>>>>>>>> with the
>>>>>>>>> exception of the last one released, ie 4.2.0.
>>>>>>>>>
>>>>>>>>> We've been trying to get around the problem on the Object
>>>>>>>>> Pascal side,
>>>>>>>>> but without success so far.
>>>>>>>>>
>>>>>>>>> Does anyone connected to the compilation of Rqui.exe know what
>>>>>>>>> the
>>>>>>>>> problem is?
>>>>>>>>
>>>>>>>> It could be that the new build enforces Windows security more
>>>>>>>> stringently. More details are described in the answer to this
>>>>>>>> question: https://stackoverflow.com/a/40139498/2554330, but at
>>>>>>>> a minimum you should be checking the return value from
>>>>>>>> PostMessage.
>>>>>>>>
>>>>>>>> Duncan Murdoch
>>>>>>>>
>>>>>>>>>
>>>>>>>>> Best,
>>>>>>>>> ///\\\///\\\///\\\///\\\///\\\///\\\///\\\///\\\///\\\///\\\
>>>>>>>>> Jose Claudio Faria
>>>>>>>>> UESC/DCET/Brasil
>>>>>>>>> joseclaudio.faria at gmail.com
>>>>>>>>> Telefones:
>>>>>>>>> 55(73)3680.5545 - UESC
>>>>>>>>> 55(73)99966.9100 - VIVO
>>>>>>>>> ///\\\///\\\///\\\///\\\///\\\///\\\///\\\///\\\///\\\///\\\
>>>>>>>>> If you have software to deal with statistics, you have arms,
>>>>>>>>> if you have good software, you have arms and legs,
>>>>>>>>> if you have software like R, you have arms, legs and wings...
>>>>>>>>> the height of your flight depends only on you.
>>>>>>>>>
>>>>>>>>> [[alternative HTML version deleted]]
>>>>>>>>>
>>>>>>>>> ______________________________________________
>>>>>>>>> R-devel using r-project.org mailing list
>>>>>>>>> https://stat.ethz.ch/mailman/listinfo/r-devel
>>>>>>>>
>>>>>>>
>>>>>>> ______________________________________________
>>>>>>> R-devel using r-project.org mailing list
>>>>>>> https://stat.ethz.ch/mailman/listinfo/r-devel
>>>>>
>
More information about the R-devel
mailing list