I was trying to detect Ctrl+V from a TEdit's OnKeyPress event and I've noticed that the Key parameter assumes an unusual value when pressing Ctrl+AnyKey.
Example:
procedure TForm1.Edit1KeyPress(Sender: TObject; var Key: Char);
begin
ShowMessage(IntToStr(Ord(Key)));
end;
It produces the following results:
Ctrl+Q 17
Ctrl+W 23
Ctrl+E 5
Ctrl+R 18
...
Ctrl+A 1
Ctrl+Z 26
Ctrl+C 3
Ctrl+V 22
Ctrl+X 24
I don't understand how keys are translated, what does these codes mean?
It seems it has nothing to do with the ASCII table:
Could anyone shed some light on this?
I don't understand how keys are translated, what does these codes mean?
The values you get with the Ctrl+AnyKey combinations are Ascii control codes.
They emanate from the need to enter non-printing (control) characters from the keyboard. The (typical) values for the control characters are below 32 plus the del character (127).
Some more information about the history behind and standards could be found here and here.
Related
I have a thermal printer "MPT-II" from an unknown Chinese brand, that has both USB and Bluetooth. I can successfully print text using:
Loyverse app on Android
JavaScript
Raw HEX or decimal
However, only using the Loyverse app am I able to input special characters, and by special characters I mean the Danish characters æøå/ÆØÅ.
If I open up any BLE tool on Windows (Bluetooth LE Lab for example), I can select the correct characteristic and send something like 104 101 108 108 111 13 10 which would print "hello" on the printer. I've read a bit about the ESC R and ESC t commands, but how exactly do I set those modes? I've tried prepending it to each command, such as 27 82 1 104 101 108 108 111 13 10 where the 27 82 1 corresponds to ESC R 4 and the 4 corresponds to Denmark I.
According to the printer's manual, it states the following:
GB18030 character set, ASCII characters, user defined characters, bar codes CODE39, EAN13, EAN8, CODABAR, CODE93, ITF, bitmaps.
According to that list, the Danish character set is not supported. I'm not sure how the Loyverse app is doing it correctly, but the text is the same using raw commands and Loyverse, so I don't think Loyverse is converting to a bitmap and sending that data.
So my real question is: How do I send the correct character set for my printer? Maybe the character set is already correct, but the ASCII character for æøå/ÆØÅ are wrong?
EDIT: I have confirmed that something works with the ESC XXXX commands. If I do 27 97 2 followed by my "hello" sequence, the text is printed to the right (right aligned). So that definitely works.. I have tried probably all character sets thus far using ESC R and ESC t but none of them work :(
EDIT 2: I have now tested every single combination of ESC R and ESC t. I went through the entire list printing some Chinese characters, and every single line of 150+ I tried all returned the same Chinese character. So ESC R or ESC t is definitely not the command I should be using to change the charset.
I am a little perplexed. On :
http://delphi.about.com/od/objectpascalide/l/blvkc.htm
it says that the right key for "Space" is #20. Tried that and it will not work.
However, replacing it with #32 seems to work :
procedure TForm14.cxTextEdit5KeyPress(Sender: TObject; var Key: Char);
begin
if not (Key in [#8,#32, '0'..'9']) then begin
ShowMessage('Only numbers !');
Key := #0;
end;
end;
So now I am unsure if this will work on all Windows versions ?
Yes. VK_SPACE is defined as 0x20 (in C notation hexadecimal value 20 which is equal to 32) in all versions of Windows.
Your link lists hexadecimal values, too.
Edit
As David points out, the virtual key code VK_SPACE is irrelevant in the context of an OnKeyPress event handler. (The fact that it's defined with the ASCII value of the space character should be treated as coincidental.)
You can simply rely on the fact that #32 is the correct notation for the space character (also #$20 or simply ' ').
It says that the right key for "Space" is #20.
No it does not. #20 is the character with ordinal of 20 decimal. The table you refer to contains hexadecimal values. VK_SPACE is a virtual key code, an integer, whose value is 32 in decimal, 20 in hexadecimal.
However, virtual key codes are not used by the OnKeyPress event handler and the value of VK_SPACE is simply not relevant to your question. The OnKeyPress event handler uses UTF-16 character codes. The UTF-16 character code for a space is 32 decimal, 20 hexadecimal. If you use a pre-Unicode Delphi, OnKeyPress uses ANSI instead of UTF-16.
It is worth remembering that OnKeyPress uses UTF-16/ANSI codes because it corresponds to WM_CHAR. And OnKeyDown and OnKeyUp use virtual key codes by way of being triggered from WM_KEYDOWN and WM_KEYUP.
i searched google but can't seem to find a working solution.
the situation is unique. i need to "add" lines with a comment at various times. whenever i press the F9 key, a line number will dispaly followed by a colon ":" char and then i enter some comments at the line number and cursor position.
the running output should look like this:
001: startup time
002: watched tv
003: |
where "|" is the last cursor position at runtime, waiting for me to enter some text.
but instead, when i run the program and press the F9 key, i get this:
001:
002:
003:
|
where "|" is the last cursor position at runtime, waiting for me to enter some text.
how can remove that (last) blank line in a memo?
Add() inserts a line break after the inserted text. If you do not want the line break, then use the SelText property instead, eg;
Memo1.SelStart := Memo1.GetTextLen;
Memo1.SelLength := 0;
Memo1.SelText := '003: ';
i having this problem, if i have:
mychr = ' ';
where the 'space' in mychr equival to #255 (typed manually ALT+255), and i write:
myord = ord (mychr)
to myord return value 160 and not 255. Of course, same problem is too with charater ALT+254 etc.
As i can solve this problem? I have tested on delphi xe in console mode.
Note: if i use:
mychar = #255;
then function ord() return value correctly.
I think the problem is that the Windows Alt+Num shortcuts insert characters according to the local codepage, whereas a modern Delphi use Unicode characters, and these differ (unless the value is less than or equal to 127, I think). The solution is to enter the values #255 explicitly in code. In addition, it is a very bad habit to include 'invisible' special characters in code, because you cannot tell what character it is without copying in to an external tool! In addition, you will have to trust the text encoding of the .pas file. It is much better to use constants like #255. Even better, do
const
MY_PRECIOUS_VALUE = #255;
and use this constant every time you need it.
Update
According to the English Wikipedia article on Alt code:
If the number typed has a leading 0
(zero), the character set used is the
Windows code page that matches the
current input locale. For most systems
using the Latin alphabet, this is
Windows-1252. For a complete list, see
code page. If the number does not have
a leading 0 (zero), DOS compatibility
is invoked. The character set used is
the DOS code page for the current
input locale. For systems using
English, this is code page 437. For
most other systems using the Latin
alphabet, this is code page 850. For a
complete list, see code page.
So, if you really, really want to continue entering Alt keycodes, you'd better type Alt and 0255 with the leading zero.
If you type ALT+255, DOS codepage is used; for 437 and 850 DOS codepages (one of which you probably use) #255 is NBSP (non-breaking space). In Unicode, NBSP is $A0 (160). That explains why you obtain Ord 160.
AFAIK console mode use the OEM Ansi char set. And under Delphi XE, you're not in the Ansi world, but in the UCS-2 / Unicode world.
var MyChar: char;
MyWideChar: WideChar;
MyAnsiChar: AnsiChar;
begin
MyChar := #255;
MyWideChar := #255;
MyAnsiChar := #255;
The first two variables are the same, i.e. a character with Unicode code 255 = $00FF, since in Delphi XE, char = WideChar. For the first Unicode Page, see this article.
But MyAnsiChar is what will be displayed on the console, after conversion from the current code page into the OEM console code page.
In the Unicode chart, this $00FF is a minuscule y with trema:
U+00FF ÿ Latin Small Letter Y with diaeresis
Under the console, you'll use the OEM char set, i.e. Code Page 347. So in your case $FF is NOT a character, but a special code
FF NBSP Non Breaking SPace
which is converted into U+00A0 when converted back to Unicode:
U+00A0 NBSP Non Breaking SPace
It is very likely that you are in a Windows-1252 code page, so normally the Delphi XE AnsiString will map #255 into a minuscule y with trema:
FF ÿ Latin Small Letter Y with diaeresis
You can use low-level e.g. CharToOemBuff windows functions to perform the conversion to or from OEM, or use an OEM AnsiString type:
type
TOemString = AnsiString(437);
In all cases, the console is not the best way of entering accentuated text under modern Windows, and Unicode Delphi XE.
Using InputQuery function e.g. should be safer, since it will return an Unicode string variable. ;)
Delphi 2009 Win32.
The code below tries to add a 257 length string to a memo.
It compiles and runs fine, but nothing is added to the memo.
Memo1.Lines.Add('aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa');
Looks like a compiler bug. Is it? Because if the string was 256 long, I'd get a compiler error and couldn't compile the app.
Any way to make the app break when the developer tries to do something like this?
I know I could split the string and make this code work, but my point is to prevent developers for using this invalid code without noticing.
Thanks
This is a Delphi 2009 bug with string literals, it should raise the same error as D2007.
Try latest version of Andreas IDE Fix pack, its supose to fix this bug.
http://andy.jgknet.de/blog/?page_id=246
I agree with Gamecat, however if your dealing with a string that large, I would break it
into muliple lines to assist in reading/editing.
if you are LITTERALLY trying to create 257 "a"'s then why not use the DupeString function in the StrUtils unit?
Memo.Lines.Add( DupeString('a',257) );
Much easier to read, and maintain later. If you are doing this in a loop and therefore are worried about performance, then assign the function result to a local variable and use the variable.
var
sLotsOfAs : string;
ix : integer;
begin
sLotsOfAs := DupeString('a',257);
for ix := 0 to 1000000 do
Memo.Lines.Add( sLotsOfAs );
end;
The string literal can be only 255 characters long. Not sure why they kept this limitation. But you can solve it using multiple literals:
Memo1.Lines.Add('i have 128 chars' + 'i also have 128 chars').
I don't know about D2009, but under Delphi 6 at least, string literals are limited to 255 characters, and the compiler diagnoses the error.
In Delphi 2007, I get:
[DCC Error] Unit1.pas(29): E2056 String literals may have at most 255 elements
In Delphi 5, I get:
[Error] Unit1.pas(29): String literals may have at most 255 elements
If the D2009 behavior is as you describe, then two things come to mind:
1 - They expanded the limit on the # of chars in a string, but the TMemo can still only accept up to 255.
or
2 - It's a plain old bug
As far as preventing it, the only thing I can think of is to make a regex to search for these strings in your .PAS files.