PDA

View Full Version : Sdl/OpenGl Keyboard management



code_glitch
13-03-2011, 08:06 PM
Found a stumbling block when doing some work on a map editor. I am building it all from the ground up and I at some point need to specify a file to load. Thus you must type out the path & name. However, sdl which I am using at the moment to manage my events has other plans:

Every time I hit backspace, Caps, Shift, Num and etc I get garbage data. The key registers but doesnt actually change all the keys to upercase or whatever they are supposed to be... is there either:
a) a sdl_enablecaps/num or something I am missing
b) a better way to manage eventd than sdl?

cheers,
code_glitch.

User137
14-03-2011, 06:42 AM
This works for me:


Form1.Keypreview:=true;

procedure TForm1.FormKeyPress(Sender: TObject; var Key: char);
begin
memo1.Lines.Add(key); // key will automatically be in caps/non caps
end;

code_glitch
14-03-2011, 07:37 AM
Although I am not using delphi/lazarus here its just plain pascal.... So what units do you use to make that work? I might be able to take a look at the source and take what I need. Cheers for such a simple solution though.

Chesso
14-03-2011, 08:57 AM
Is this cross platform, or could you just use the Windows API?

User137's solution involves using Delphi's VCL etc, the units Forms and I think Standard Controls (plus the units they use, so and so forth) would be the minimum, probably overkill for what you need.

User137
14-03-2011, 11:39 AM
Actually Lazarus VCL to be precise. Compiler should be smart enough to only compile with those classes and functions that are actually used. I'm quite happy with 1Mb executable size with larger graphical projects, and that's before UPX pack.

As for the problem i don't know what key events are used for it. You might have some chance with checking if Shift key is held. Checking for Caps lock needs some crossplatform function which maybe Freepascal has. WinAPI maybe but that's Windows-only.

Edit: By shift i mean, 'A' is code 65 and 'a' is 97. Basically if shift is held, then reduce 32 from ascii value. This will not work with any other characters than A..Z.

code_glitch
14-03-2011, 06:19 PM
Chesso: Yes, this is cross platform so windowze API is no go, especially since I don't use windowze...
User137: Yes, I am looking at doing a -32 on a-z keys automatically, but does it also work with caps, backspace and num lock?

I've had no luck at all getting it to work. So I guess there is no sdl function to do this? Or does anyone have an engine that has that functionality integrated (open source please)? I don't use lazarus so my plain fpc install wont have the VCL. My executable size is already knocking on 800k due to all the libs I'm using. :)

cheers,
code_glitch.

User137
14-03-2011, 06:54 PM
Lazarus seems to use CN_CHAR message for onKeyPress. Look up TWinControl in controls.pas and wincontrol.inc.
TWinControl.CNChar() sends to DoKeyPress(). Seems pretty complicated process to me and there was no documentation for CN_CHAR.

Backspace is very simple... if key number is VK_BACK then text:=copy(text,1,length(text)-1);
At least if not allowing cursor moving to the middle of text, or selecting part of text. I'm afraid for graphical application all funtionality of TEdit has to be coded by self.

If you can simulate onKeyPress event by some means there is some hints from my UI class:

// note: caretPos is a property with built in limitations to value range.

procedure TUIEdit.KeyPress(c: char);
var l: integer;
begin
if byte(c)>31 then begin
FText:=UTF8toSys(FText);
l:=length(FText);
SetText(SysToUTF8(copy(FText,1,caretPos)+c+copy(FT ext,caretPos+1,l-caretPos)));
caretPos:=caretPos+1;
end;
end;

procedure TUIEdit.KeyDown(key: word; shift: TShiftState);
var l,p: integer;
begin
l:=length(text);
case byte(key) of
VK_LEFT: caretPos:=caretPos-1;
VK_RIGHT: caretPos:=caretPos+1;
VK_HOME: caretPos:=0;
VK_END: caretPos:=l;
VK_DELETE:
if (caretPos<l) and (l>0) then begin
FText:=UTF8toSys(FText);
SetText(SysToUTF8(copy(text,1,caretPos)+copy(text, caretPos+2,l-caretPos)));
end;
VK_BACK:
if caretPos>0 then begin
p:=caretPos; caretPos:=caretPos-1;
FText:=UTF8toSys(FText);
SetText(SysToUTF8(copy(text,1,p-1)+copy(text,p+1,l-p)));
end;
VK_RETURN: Focused:=false;
end;
end;

code_glitch
14-03-2011, 08:20 PM
Thanks for those, will start implementing it all in my code as soon as I can... A little pressed for time recently, but its nice to get all solutions done so they are ready to be implemented the next time I get some time.

paul_nicholls
14-03-2011, 10:16 PM
Perhaps this SDL tutorial "Getting String Input" might help?

http://www.lazyfoo.net/SDL_tutorials/lesson23/index.php

It isn't Pascal, but should be easy to get info from :)

cheers,
Paul

code_glitch
15-03-2011, 07:38 AM
Thanks paul, looked through and sure enough a solution for sdl to handle it automatically which is indeed very nice as it means I dont have to re-write my event handlers.

cheers for that great find.

code_glitch
15-03-2011, 06:02 PM
Just for future reference let me say that the solution for this is to use SdlEvent^.Key.KeySym.Unicode rather then SdlEvent^.Key.KeySym.Sym with Sdl_EnableUnicode(1) and then using chr() and ord() as required to get special characters, upper-case, lower-case and etc...

End of line.

paul_nicholls
15-03-2011, 07:33 PM
Good to know :)

cheers,
Paul