Sendkeys lazarus / 10-Designer ---------------------------------------------------------------------- conray · 2007-09-20 11:47 how can i perform the sendkey function in lazarus  :lol: ---------------------------------------------------------------------- Marc · 2007-09-20 15:56 not ---------------------------------------------------------------------- antonio · 2007-09-20 15:59 Do you want to simulate keyboard? Why? ---------------------------------------------------------------------- conray · 2007-09-20 16:44 The reason why i need the sendkey to emulate the keyboard press is that instead of press the key board enter button a million times ,i can get it done via software or any other key on the keyboard ---------------------------------------------------------------------- antonio · 2007-09-20 17:00 http://www.lazarus.freepascal.org/index.php?name=PNphpBB2&file=viewtop ic&t=1650&highlight=simulate+keyboard ---------------------------------------------------------------------- felipemdc · 2007-09-20 19:25 You can use the Windows API SendMessage. Of course this will only work on Windows. ---------------------------------------------------------------------- antonio · 2007-09-20 19:28 sekel: And which is the message, please? ---------------------------------------------------------------------- conray · 2007-09-20 19:29 Sekel i need it to work in linux as well :mrgreen: ---------------------------------------------------------------------- antonio · 2007-09-20 19:31 Probably there is no way. ---------------------------------------------------------------------- conray · 2007-09-20 19:36 is it possible to import .pas fle from delphi , if that is possible then it can be done  :mrgreen: ---------------------------------------------------------------------- antonio · 2007-09-20 19:38 Delphi implements this through Windows API. ---------------------------------------------------------------------- conray · 2007-09-20 19:40 Thanks ---------------------------------------------------------------------- felipemdc · 2007-09-20 20:20 It may be possible to do this using ifdefs. Use SendMessage on windows and a gtk function on linux. I have no idea which gtk function that would be, or even if there is one that does it. ---------------------------------------------------------------------- antonio · 2007-09-20 20:21 sendmessage(handle, wm_close, 0, 0) ? ---------------------------------------------------------------------- kris · 2017-12-03 05:22 First of all, to all of you, but especially to: Marc and antonio: PLEASE DO NOT say that something cannot be done just because you don't know how to do it! Now, regarding the Linux part, I think the way to gou would be with gtk_main_do_event() from libgtk-x11-2.0. The declaration in Lazarus would be:   procedure gtk_main_do_event(GDKEvent : PGDKEvent); cdecl;external 'gtk-x11-2.0' name 'gtk_main_do_event'; The PGdkEvent type is declared in gdk2 unit; The documentation mentions the call here: https://developer.gnome.org/gtk3/stable/gtk3-General.html#gtk-main-do- event and someone has a code snipped on using it for sending key event (although not in Lazarus) here: https://mail.gnome.org/archives/gtk- app-devel-list/2004-July/msg00016.html Btw, I just myself am tyring to implement this, and googled out this thread. People who comment on things not being possible without actually knowing, or questioning the asker's reason for wanting to do something in the first place ARE NOT HELPFUL ! ---------------------------------------------------------------------- kris · 2017-12-03 06:08 so far, I rewrote the code from https://mail.gnome.org/archives/gtk- app-devel-list/2004-July/msg00016.html into Lazarus, but I'm still getting crash error on gtk_main_do_event(Event); I also learned that gtk_main_do_event is already defined in the unit gtk2.pas, so you do not need to define it yourself (i shared the declaration in the previous answer). This is the code I have so far: Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i   Procedure TGtkTerm.SendKey(AKey: char);   var     Event      : PGdkEvent;     hw_keycode : ctypes.cuint16;     keys       : PGdkKeymapKey;     n_keys     : ctypes.cint;   begin     if(self.Vte=nil)then exit;     write('gdk_keymap_get_entries_for_keyval... ');     if gdk_keymap_get_entries_for_keyval(gdk_keymap_get_default(), ord(AKey), keys, @n_keys)        then try               hw_keycode                := keys[0].keycode;               writeln('done.');               writeln('hw_keycode=',hw_keycode,'; keys freed.');             finally               g_free(keys);               writeln('failed.');             end        else exit;      write('gdk_event_new (GDK_KEY_PRESS)... ');     Event := gdk_event_new(GDK_KEY_PRESS);     if(Event=nil)       then writeln('failed.')       else writeln('done.');     if(Event=nil)then exit;     try       Event^.key.window           := self.Vte^.window;     Event^.key.state            := 0;//GDK_MOD1_MASK; {alt}       Event^.key.hardware_keycode := hw_keycode;        Event^.key.keyval         := gdk_unicode_to_keyval(ord(AKey));       Event^.key.length         := 1;       writeln('key.keyval=',Event^.key.keyval);        Event^.key.send_event       := 0;       Event^.key.time             := GDK_CURRENT_TIME;        write('gtk_main_do_event(Event);... ');     try         gtk_main_do_event(Event);         writeln('done.');     except         writeln('failed.');       end;     finally       gdk_event_free(Event);     end;   end; Remarks: this is in a method of my own class wrapper around vte_terminal. I want to send keys into the terminal widget, so basically that is why I googled this thread in the first place.the "self.Vte^.window;" is in my case (Vte is PGtkWidget), you may wish to use your own widget's window.i use write/writeln to print out some debugging info, you don't need these at all.the units you will end up needing for sure are: gtk2, gdk2, ctypes, and maybe (not sure) glib2 Will try to make it work, but at least this is what I have for now, and at least i translated the lnked sample code into Lazarus for your convenience. If any of you ever get to this point and solves the error, pls share. If I fix the error, I'll share as well. ---------------------------------------------------------------------- taazz · 2017-12-03 11:01 Quote from: kris on December 03, 2017, 07:08:01 amWill try to make it work, but at least this is what I have for now, and at least i translated the lnked sample code into Lazarus for your convenience. If any of you ever get to this point and solves the error, pls share. If I fix the error, I'll share as well. A 10 year old excavation. Nice! Assuming you are looking for a way to send keys, I recommend to take a look on the mouseandkeyInput package. It claims to support sending keys. ---------------------------------------------------------------------- kris · 2017-12-03 15:41 Thank you VERY much for the hint on http://wiki.freepascal.org/MouseAndKeyInput !! I just wanted to share that before I saw your reply, I already followed similar solution on my own. Also depending on a 3rd party library, but in my case I used libxdo, used by xdotool: http://www.semicomplete.com/files/xdotool/docs/html/https://github.com /jordansissel/xdotoolAlso on the wiki about MouseAndKeyInput, under Gtk chapter it reads: Quote(...) ALT key pressing is not supported (...)and libxdo does not have that limitation. For my needs I only had to be able to send keyboard key events, no mouse. libxdo has plenty of exported functions, but I only ported these: Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i     function xdo_new(display:Pchar): pxdo_t;cdecl;external 'xdo' name 'xdo_new';  function xdo_send_keysequence_window(xdo:Pxdo_t; window: window_t; keysequence:Pchar; delay:useconds_t):longint; cdecl;external 'xdo' name 'xdo_send_keysequence_window';  function xdo_send_keysequence_window_up(xdo:Pxdo_t; window: window_t; keysequence:Pchar; delay:useconds_t):longint;cdecl;external 'xdo' name 'xdo_send_keysequence_window_up';  function xdo_send_keysequence_window_down(xdo:Pxdo_t; window: window_t; keysequence:Pchar; delay:useconds_t):longint;cdecl;external 'xdo' name 'xdo_send_keysequence_window_down'; and then I added my own wrapper function: Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i (...)implementation{ API }  var    FXDO : pxdo_t = nil;   Function SendKey(const WindowId: longint; const sequence: string): Boolean;   var     pc : pchar;   begin     if(FXDO=nil)then FXDO := xdo_new(nil);     if(FXDO=nil)then exit;     pc := pchar(sequence);   Result := xdo_send_keysequence_window(FXDO, WindowId, pc, 0)=0;   end;(...)  As you can see in the external functions headers, there are some proprietary types, but I used FPC included h2pas tool to auto-convert the xdo.h file (https://github.com/jordansissel/xdotool/blob/master/xdo.h) from c to pascal, and it did the job. I had to: add units unixtype and ctypes to the uses typeinstall dev package for xdo: $ sudo apt-get install libxdo-dev it really works flawlessly!!! ---------------------------------------------------------------------- kris · 2017-12-03 15:53 I thought that if someone would like to also use libxdo, I should extend this info by how to pass valid WindowId to the calls I shared. Manually, when using xdotool from terminal, I usually find window id with "wmctrl -l" command. Wmctrl is not installed in Ubuntu by default, so: $ sudo apt-get install wmctrl. "wmctrl -l" will list all the windows currently managed by the x11 window manager, and the very first column will be window id. The Id is a number, wmctrl prints it in hex. The format used is to prefix hex number with "0x", but Object Pascal uses '$' as default hex prefix. So, for example, "0xfefe" in Object Pascal would be: Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i const  C_HEX_VALUE = $fefe; //0xfefe also, the last column of "wmctrl -l" output is the window's title. So I wrote a function that can return window's id by window's title: Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i (...)uses  (...), Process, (...);   Procedure grep(var s: string; const grepstr: string);implementation  Procedure grep(var s: string; const grepstr: string);   var     SL : TStringList;   begin     if(grepstr='')then     begin         s := '';         exit;       end;     SL := TStringList.Create;     try       SL.Text := s; s := '';       while(SL.Count>0)do         begin           if Pos(grepstr,SL[0])>0 then s := s+SL[0]+sLineBreak;           SL.Delete(0);         end;     finally       FreeAndNil(SL);       s := trim(s);     end;   end; (...) Procedure TForm1.cmdButtonClick(Sender: TObject);  var    WindowId : longint;    s,c            : string;    p              : integer;  begin     if not Process.RunCommand('wmctrl',['-l'],s)then exit;     grep(s,'VTE Terminal');      { because the window I wanted the Id of has that title, you should use whatever applies to your case }     p := Pos(' ',s);     if(p>0)       then s := trim(Copy(s,1,p-1))       else s := '';     if Copy(s,1,2)='0x'       then Delete(s,1,2)       else exit;     WindowId := StrToIntDef('$'+s,0);     if(WindowId<=0)then exit;     writeln('WindowId='+s);     while(c<>'')do       begin         libXDO.SendKey(WindowId, Copy(c,1,1));         Delete(c,1,1);       end;     libXDO.SendKey(WindowId, 'KP_Enter');}  end;  just remember that this depends on wmctrl being installed on the system, which it is not by default on Ubuntu. That's just one way though, you could use x11 APIs from lazarus, but this way was faster for me. I once found lazarus units that have functions for listing windows and their Id, so it is definitely possible not to depend on wmctrl, but there it is, as a reference. ---------------------------------------------------------------------- kris · 2017-12-03 17:05 I published the library: https://sourceforge.net/p/all-things-ubuntu- library/code/HEAD/tree/trunk/libxdo.pas ---------------------------------------------------------------------- bytebites · 2017-12-03 17:19 Quote from: kris on December 03, 2017, 04:41:28 pm Also on the wiki about MouseAndKeyInput, under Gtk chapter it reads: Quote(...) ALT key pressing is not supported (...) Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i   VK_MENU: Result := XK_VoidSymbol; // alt key crashes app, XK_Alt_R; Actually  Alt-left works, if you change code in xkeyinput-file: Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i VK_MENU: Result := XK_Alt_L; ---------------------------------------------------------------------- kris · 2017-12-03 17:40 very interesting how this topic came back to life after all these years. Kudos to bytebites for sharing the patch I could only wish for someone knowledgeable to find this thread and also help me to figure out why the approach using gtk_main_do_event did not work for me. ---------------------------------------------------------------------- Zoran · 2017-12-03 22:11 Quote from: taazz on December 03, 2017, 12:01:39 pm A 10 year old excavation. Nice! Assuming you are looking for a way to send keys, I recommend to take a look on the mouseandkeyInput package. It claims to support sending keys. Or better don't take a look at it, unless you want to license your code under GPL (and you will have to, if you take any piece of code from it). MouseAndKeyInput package is under GPL, which makes it unusable for many Lazarus users. So, another solution with more permissive license will be welcomed. ---------------------------------------------------------------------- Thaddy · 2018-01-20 11:33 Kris, you are responding to an 11 year old thread. Better to look at the wiki under keupress http://wiki.lazarus.freepascal.org/LCL_Key_Handling That's cross-platform.