I'm writing a C++ project with RAD Studio, but this also applies to Delphi.
I need an edit control where user can only enter floats (2 decimal places) and can restore the original value (taken from a variable, not important here) clilcking on a button (actullay an icon) inside the edit control itself.
This is what I've done, using a TJvCalcEdit
from JEDI library.
Control definition:
object Sconto1: TJvCalcEdit
[non-important attributes...]
ButtonFlat = True
Glyph.Data = {
D6020000424DD6020000000000003600000028000000100000000E0000000100
180000000000A0020000130B0000130B00000000000000000000FFFFFFFFFFFF
FFFFFFFFFFFFFFFFFF999EC29396C3FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF9198C48694CBA7BAFE8493CA72
75B9FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8B96C5
8695CBA7BAFEA7BAFEA7BAFEA7BAFE747EB66D71B5FFFFFFFFFFFFFFFFFFFFFF
FFFFFFFFFFFFFFFFFFFF8493CAA7BAFEA7BAFEA7BAFEA7BAFEA7BAFEA7BAFE84
93CA7E83CE6D71B4FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8F94C3A7BAFE
A7BAFEA7BAFEA7BAFEA7BAFEA7BAFE8492CA8288D27B7FCA6D71B4FFFFFFFFFF
FFFFFFFFFFFFFFFFFFFFFFFFFF8492CAA7BAFEA7BAFEA7BAFE828ECA7B82C993
96FA6D6FB67B7FCA7B7FCA6D6FB4FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF9299C2
A5B7FE7E88CA787DC99396FA9396FA9396FA9396FA6D6FB67B7FCA7B7FCA6D6F
B4FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF7678C89396FA9396FA9396FA9396FA93
96FA9396FA9396FA6D6FB67B7FCA7B7FCA6C6FB3FFFFFFFFFFFFFFFFFFFFFFFF
FFFFFF7678C89396FA9396FA9396FA9396FA9396FA9396FA9396FA6D6FB67B7F
CA7B7FCA7576B0FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF7678C89396FA9396FA93
96FA9396FA9396FA9396FA9396FA6D6FB67B7FCA6266A2D6D0E2FFFFFFFFFFFF
FFFFFFFFFFFFFFFFFF7678C89396FA9396FA9396FA9396FA9396FA9396FA9396
FA6D6FB67B7FCA7C7EB0FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF7678C893
96FA9396FA9396FA9396FA9396FA9396FA9396FA7679C66B6DACFFFFFFFFFFFF
FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF7678C89396FA9396FA9093F58B8EEC7678
C87C7FC6ACABE5FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
FFFF7678C88283C5A4A4E7C4C1EBFFFFFFFFFFFFFFFFFFFFFFFF}
ImageKind = ikCustom
DecimalPlacesAlwaysShown = False
OnButtonClick = EScontoButtonClick
end
Method called on button click:
void __fastcall TFRigOrd::EScontoButtonClick(TObject *Sender)
{
TJvCalcEdit* edit = dynamic_cast<TJvCalcEdit*>(Sender);
edit->Value = oldSconto1;
}
The problem: at the end of this method a calculator popup appears below the control, requiring an action by the user. I don't want this to happen because I'm changing the value programmatically. I guess it's a default value due to the fact that such button is made for triggering the calculator. Moreover the value you see (255) appears without decimal point, with will be shown only once the calculator is closed.
So, can I disable this behaviour? Or can someone suggest me a solution with another control (standard, open source or free anyway)?
I'd use a TButtonedEdit
to get the button, and to enforce floating-point input with a maximum of two decimals after the point, I'd do
TButtonedEdit = class(ExtCtrls.TButtonedEdit)
protected
procedure KeyPress(var Key: Char); override;
procedure WMPaste(var Message: TWMPaste); message WM_PASTE;
end;
...
procedure TButtonedEdit.KeyPress(var Key: Char);
function InvalidInput: boolean;
var
dc: integer;
begin
result := false;
if Character.IsControl(Key) then Exit;
dc := Pos(DecimalSeparator, Text);
if not (Key in ['0'..'9', DecimalSeparator]) then Exit(true);
if Pos(DecimalSeparator, Text) > 0 then
begin
if Key = DecimalSeparator then Exit(true);
if (Length(Text) - dc > 1)
and (Pos(DecimalSeparator, Text) < SelStart + 1) and
(SelLength = 0) then Exit(true);
end;
end;
begin
inherited;
if InvalidInput then
begin
Key := #0;
beep;
end;
end;
procedure TButtonedEdit.WMPaste(var Message: TWMPaste);
var
s: string;
i: integer;
hasdc: boolean;
NewText: string;
NewSelStart: integer;
begin
if Clipboard.HasFormat(CF_TEXT) then
begin
s := Clipboard.AsText;
NewText := Text;
Delete(NewText, SelStart + 1, SelLength);
Insert(s, NewText, SelStart + 1);
// Validate
hasdc := false;
for i := 1 to Length(NewText) do
begin
if NewText[i] = DecimalSeparator then
if hasdc then
begin
beep;
Exit;
end
else
hasdc := true
else if not (NewText[i] in ['0'..'9']) then
begin
beep;
Exit;
end;
end;
// Trim
if hasdc then
NewText := Copy(NewText, 1, Pos(DecimalSeparator, NewText) + 2);
NewSelStart := SelStart + Length(s);
Text := NewText;
SelStart := NewSelStart;
SelLength := 0;
end
else
inherited;
end;