TEdit Input Validation on C++ Builder XE8 - c++

I am very new to C++ Builder XE8.
I want the minimum and maximum length of numbers that must be typed is as much as six numbers, also I need to make sure that only number is entered (0 is exception), and not an alphabetic character, backspace, punctuation, etc.
I would also like to produce an error box if anything other than a number is entered.
I've tried a few combinations of codes, three of which can be seen below, but none of those codes works.
Any help would sure be appreciated!
(1).
void __fastcall TForm1::Edit1KeyPress(TObject *Sender, System::WideChar &Key)
{
Edit1->MaxLength = 6;
if (!((int)Key == 1-9)) {
ShowMessage("Please enter numerals only");
Key = 0;
}
}
(2).
void __fastcall TForm1::Edit1KeyPress(TObject *Sender, System::WideChar &Key)
{
Edit1->MaxLength = 6;
if (Key <1 && Key >9) {
ShowMessage("Please enter numerals only");
Key = 0;
}
}
(3).
void __fastcall TForm1::Edit1KeyPress(TObject *Sender, System::WideChar &Key)
{
Edit1->MaxLength = 6;
if( Key == VK_BACK )
return;
if( (Key >= 1) && (Key <= 9) )
{
if(Edit1->Text.Pos(1-9) != 1 )
ShowMessage("Please enter numerals only");
Key = 1;
return;
}
}

TEdit has a NumbersOnly property:
Allows only numbers to be typed into the text edit.
Set it to true and let the OS handle the validation for you. But, if you want to validate it manually, use this:
void __fastcall TForm1::Edit1KeyPress(TObject *Sender, System::WideChar &Key)
{
// set this at design-time, or at least
// in the Form's constructor. It does not
// belong here...
//Edit1->MaxLength = 6;
if( Key == VK_BACK )
return;
if( (Key < L'0') || (Key > L'9') )
{
ShowMessage("Please enter numerals only");
Key = 0;
}
}

Check out TMaskEdit: http://docs.embarcadero.com/products/rad_studio/delphiAndcpp2009/HelpUpdate2/EN/html/devwin32/idh_useop_textcontrols_xml.html
TMaskEdit is a special edit control that validates the text entered against a mask that encodes the valid forms the text can take. The mask can also format the text that is displayed to the user.
EDIT: To set a minimum length
void __fastcall TForm1::MaskEdit1Exit(TObject *Sender)
{
if (MaskEdit1->Text.length() < 6)
{
//your error message, or throw an exception.
}
}

Related

ToUnicodeEx not printing "Greater Than"

I wrote a function which processes the user keyboard in order to write text in an app.
In order to do that I use the ToUnicodeEx function which uses an array of Key states.
The function is working perfectly fine for every possible input, except for one : I cannot display the ">" sign, which is supposed to be the combination of "SHIFT + <" : it displays the "<" sign instead, as if the SHIFT key was not pressed, whereas it knows it it pressed.
Has somebody already experienced the same and knows what the problem is?
You will find my function code below :
void MyFunction(bool bCapsLockDown)
{
IOClass io = GetMyIOInstance();
HKL layout = GetKeyboardLayout( 0 );
uchar uKeyboardState[256];
WCHAR oBuffer[5] = {};
//Initialization of KeyBoardState
for (uint i = 0; i < 256; ++i)
{
uKeyBoardState[i] = 0;
}
// Use of my ConsultKeyState to get the status of pressed keys
if ( ConsultKeyState( VK_SHIFT ) || bCapsLockDown )
{
uKeyboardState[VK_CAPITAL] = 0xff;
}
if ( ConsultKeyState( VK_CONTROL ) )
{
uKeyboardState[VK_CONTROL] = 0xff;
}
if ( ConsultKeyState( VK_MENU ) )
{
uKeyboardState[VK_MENU] = 0xff;
}
if ( ConsultKeyState( VK_RMENU ) )
{
uKeyboardState[VK_MENU] = 0xff;
uKeyboardState[VK_CONTROL] = 0xff;
}
for ( uint iVK = 0; iVK < 256; ++iVK )
{
bool bKeyDown = ConsultKeyState( iVK ) != 0;
uint iSC = MapVirtualKeyEx( iVK, MAPVK_VK_TO_VSC, layout );
bool bKeyAlreadyDown = io.KeysDown[iVK];
io.KeysDown[iVK] = bKeyDown;
if ( io.KeysDown[iVK] && bKeyAlreadyDown == false )
{
int iRet = ToUnicodeEx( iVK, iSC, uKeyboardState, (LPWSTR)oBuffer, 4, 0, layout );
if( iRet > 0 && (iswgraph( (unsigned short) oBuffer[0] ) || oBuffer[0] == ' ') )
io.AddInputCharacter( (unsigned short) oBuffer[0] );
}
}
}
Edit :
To summarize, my question is :
What would be the good combination VirtualKey + KeyBoardState to get a ">" displayed?
The problem is that shift and caps lock do not have the same effect on a keyboard. For example, (on a UK keyboard) pressing shift+1 = !, but pressing 1 with caps lock on still give you 1.
Your code currently treats them the same, though, and it is using VK_CAPITAL in both cases. This will give you the same effect as if caps lock were on, which is not what you want in this case.
The solution is therefore to break out your logic and use VK_SHIFT when you really want shift to be pressed and VK_CAPITAL when you want caps lock to be active.

Change char inserted using Alt+Unicode in CRichEdit

I want to change a unicode char inserted using Alt+Unicode code from the keyboard.
I used PretranslateMessage for changing the chars inserted directly from the keyboard and it worked. But with the Alt+Unicode code method it does not.
Here is the code:
Microsoft Word has this functionality when enabling show/hide paragraph marks.
BOOL CEmphasizeEdit::PreTranslateMessage(MSG* msg)
{
if (msg->hwnd == m_hWnd)
{
if (msg->message == WM_CHAR)
{
if (TheApp.Options.m_bShowWSpaceChars)
{
if (msg->wParam == ' ') // This works in both cases Space key pressed or Alt + 3 + 2 in inserted
{
msg->wParam = '·';
}
else if (msg->wParam == (unsigned char)' ') // this does not work
{
msg->wParam = (unsigned char)'°';
}
}
}
}
return CRichEditCtrl::PreTranslateMessage(msg);
}
If I insert from the keyboard Alt + 0 + 1 + 6 + 0 which is ' '(No-Break Space), I want the CRichEditCtrl to display '°' or another char that I specify.
How can I handle this to make it work?
Alt+Space is reserved for program's close menu.
You should use another sequence like Ctrl+Space or Alt+Ctrl+Space
' ' and (unsigned char)' ' are the same thing, therefore the code never reaches else if (msg->wParam == (unsigned char)' '). You should remove that.
Use GetAsyncKeyState to see if Alt or Ctrl key is pressed down.
BOOL IsKeyDown(int vkCode)
{
return GetAsyncKeyState(vkCode) & 0x8000;
}
...
if (msg->wParam == ' ')
{
if (IsKeyDown(VK_CONTROL))
msg->wParam = L'°';
else
msg->wParam = L'+';
}
...
I had to get the cursor position send an append string to the control and then set the selection after the inserted character. When this happens I have to skip CRichEditCtrl::PreTranslateMessage(msg);
BOOL CEmphasizeEdit::PreTranslateMessage(MSG* msg)
{
if (msg->hwnd == m_hWnd)
{
if (msg->message == WM_CHAR)
{
TCHAR text[2];
text[1] = 0x00;
BOOL found = 1;
switch (msg->wParam)
{
case 0x20: text[0] = _C('·'); break;
case 0xA0: text[0] = 0xB0; break;
}
CHARRANGE cr;
GetSel(cr);
cr.cpMax++;
cr.cpMin++;
ReplaceSel(text);
SetSel(cr);
return 1;
}
}
return CRichEditCtrl::PreTranslateMessage(msg);
}

C++ Parsing char array as a script file (syntax)

I have made a simple Script reading class in C++ which allows me to read and parse scripts.
Basically there's a FILE class, which then I proceed to open with "fopen".
In functions I proceed to call "fgetc" and "ftell" to parse the script file as needed, note this ain't an interpreter.
Every script file is supposed to follow a syntax, but this is why I'm asking here for a solution.
Here's how a script looks like:
# Script File Comment
USERNAME = "Joe"
PASSWORD = "pw0001"
ACCESSLEVEL = 3
DATABASE = ("localhost",3306,"db","user","password")
Basically I have a few functions:
// This function searches for "variables"
nextToken();
// After I have the variable, e.g: USERNAME, PASSWORD, ACCESSLEVEL or DATABASE
// I proceed to call this function
// This function reads the char array for (,-{}()[]=) these are symbols
readSymbol();
// In a condition I check what "token/variable" I got and proceed to read
// it accordingly
// e.g; for USERNAME I do:
readString(); // reads text inside "
// e.g; for ACCESSLEVEL I do:
readNumber(); // reads digits until the next char ain't a digit
// e.g; for DATABASE I do:
readSymbol(); // (
readString(); // 127.0.0.1
readSymbol(); // ,
readNumber(); // 3306
readSymbol(); // ,
readString(); // db
readSymbol(); // ,
readString(); // user
readSymbol(); // ,
readString(); // password
readSymbol(); // )
I would like to be able to read a variable declaration like this:
DATABASELIST = {"data1","data2","data3"}
or
DATABASELIST = {"data1"}
I could easily do readSymbol and readString to read for 3 different string definitions inside the variable, however this list is supposed to have custom user data, like 5 different strings, or 8 different strings - depends.
And I seriously have no idea how can I do this with the parser I wrote.
Please note that I am basing this in some Pseudo code I took from a scripter for this type of format, I have the pseudo code extracted from IDA, if you would like to see it for better understanding post here
Here's an example of my "readSymbol" function.
READSYMBOL
int TReadScriptFile::readSymbol()
{
int currentData = 0;
int stringStart = -1;
// Check if we can't read anymore
if (end)
return 0;
while (true)
{
// Basically get chars in the script
currentData = fgetc(File);
// Check for end of file
if (currentData == -1)
{
end = true;
break;
}
if (stringStart == -1)
{
if (isdigit(currentData) || isalpha(currentData))
{
printf("TReadScriptFile::readSymbol: Symbol expected\n");
close();
return 0;
}
else if
(
currentData == '=' || currentData == ',' ||
currentData == '(' || currentData == ')' ||
currentData == '{' || currentData == '}' ||
currentData == '>' || currentData == '<' ||
currentData == ':' || currentData == '-'
)
{
#ifdef __DEBUG__
printf("Symbol: %c\n", currentData);
#endif
stringStart = ftell(File);
break;
}
}
}
return 1;
}
NEXTTOKEN
int TReadScriptFile::nextToken()
{
int currentData = 0;
int stringStart = -1;
int stringEnd = -1;
RecursionDepth = -1;
memset(String, 0, 4000);
// Check if we can't read anymore
if (end)
return 0;
while (true)
{
// ** Syntax **
if (isdigit(getNext()) || getNext() == -1)
{
printf("No more tokens left.\n");
end = true;
close();
return 0;
}
// End
// Basically get chars in the script
currentData = fgetc(File);
// Check for end of file
if (currentData == -1)
{
end = true;
break;
}
// Syntax Checking Part, this really isn't needed but w/e
if (stringStart == -1)
{
if (currentData == '=' || isdigit(currentData))
{
printf("TReadScriptFile::nextToken: Syntax Error: string expected\n");
close();
return 0;
}
}
// End Syntax Checking
// It's a comment line, we should skip
if (currentData == '#')
{
seekNewLn();
continue;
}
// There are no variables, yet
if (stringStart == -1)
{
// We found a letter, we are near a token!
if (isalpha(currentData))
{
stringStart = ftell(File);
// We might as well add the letter to the string
RecursionDepth++;
String[RecursionDepth] = currentData;
continue;
}
}
else if (stringStart != -1)
{
// Let's wait until we get an identifier or space
// We found a digit, error
if (isdigit(currentData))
{
printf("TReadScriptFile::nextToken: string expected\n");
close();
return 0;
}
// We found a space, maybe we should stop looking for tokens?
else if (isspace(currentData))
{
#ifdef __DEBUG__
printf("Token: %s\n", String);
#endif
break;
}
RecursionDepth++;
String[RecursionDepth] = currentData;
}
}
return 1;
}
I found a good example of the approach I followed here:
http://llvm.org/docs/tutorial/LangImpl1.html
One mechanism to deal with DATABASE_LIST would be this:
After finding the variable DATABASE_LIST read a symbol using readSymbol() checking if it is a { then in a loop do readString() add it to a std::vector (or some other suitable container) then check for a , or } (using readSymbol()) . If it is a ,(comma) then you go back and read another string add to the vector etc. until you do finally reach } . When you are finished you'd have a vector (dynamic array) of strings that represent a DATABASE_LIST

Output formatted text to Screen

I have a vector that stores pairs. Each pair contains a CString and a bool.
If the CString is meant to be underlined then bool is true, else it is false.
I want to output the text in the vector to the screen making sure that text is underlined in the correct places.
So far I have the following code:
void CEmergenceView::AppendText( CString msg ) {
int nBegin;
CRichEditCtrl &rec = GetRichEditCtrl();
nBegin = rec.GetTextLength();
rec.SetSel(nBegin, nBegin); // Select last character
rec.ReplaceSel(msg); // Append, move cursor to end of text
rec.SetSel(-1,0); // Remove Black selection bars
nBegin = rec.GetTextLength(); // Get New Length
rec.SetSel(nBegin,nBegin); // Cursor to End of new text
// Fix annoying "do you want to save your changes?" when program exits
GetDocument()->SetModifiedFlag(FALSE); // -Optional- (sometimes you want this)
}
int nEnd = 0;
// loop through start of text to end of text
for(int k = 0; k < groups.size(); k++) {
rEditCtrl.SetSel(nEnd, nEnd);
rEditCtrl.GetSelectionCharFormat(cf);
if(groups.at(k).second) {
if(!cf.dwEffects & !CFE_UNDERLINE) {
CRichEditView::OnCharUnderline();
}
}
else if(!groups.at(k).second) {
if(cf.dwEffects & CFE_UNDERLINE) {
CRichEditView::OnCharUnderline();
}
}
AppendText(groups.at(k).first);
nEnd = nEnd + (groups.at(k).first.GetLength());
}
However, this is not underlining at all....Can anyone tell me what I'm doing wrong?? Thanks!
I think you should implement the OnCharUnderline
Try to call yours own function instead of the default one:
You can get it from here:
void CMyRichEditView::OnCharUnderline ()
{
CHARFORMAT2 cf;
cf = GetCharFormatSelection();
if (!(cf.dwMask & CFM_UNDERLINE) || !(cf.dwEffects & CFE_UNDERLINE))
cf.dwEffects = CFE_UNDERLINE;
else
cf.dwEffects = 0;
cf.dwMask = CFM_UNDERLINE;
SetCharFormat(cf);
}

Management inputs Mouse with DirectX DirectInput

I try to use DirectX Input to manage input mouse. But when I try to get X and Y coordinates of my mouse, values are incorrect (negative or seem to be random).
I show you the code that I used :
bool System::frame()
{
bool result;
if (input->isButtonDown(BUTTON_L)) //if left button is down
{
result = ReadMouse();
if(!result)
return false;
ProcessInput();
}
}
bool System::ReadMouse()
{
HRESULT result;
//this->mouseState is a DIMOUSESTATE ; this->mouse is a LDIRECTINPUTDEVICE8
result = this->mouse->GetDeviceState(sizeof(DIMOUSESTATE), (LPVOID)&this->mouseState);
if(FAILED(result))
{
if((result == DIERR_INPUTLOST) || (result == DIERR_NOTACQUIRED))
this->mouse->Acquire();
else
return false;
}
return true;
}
void System::ProcessInput()
{
this->mouseX = this->mouseState.lX;
this->mouseY = this->mouseState.lY;
if(this->mouseX < 0)
this->mouseX = 0;
if(this->mouseY < 0)
this->mouseY = 0;
if(this->mouseX > this->ScreenWidth)
this->mouseX = this->ScreenWidth;
if(this->mouseY > this->ScreenHeight)
this->mouseY = this->ScreenHeight;
return;
}
My last test give this->mouseX = -657 and this->mouseY = -36 instead of 200 and 200 (approximately). I check the function when I initialize the mouse, they seem to works (I followed a tutorial).
I think the reason is that DirectInput gives you relative data for the position of the mouse.
Please see: http://msdn.microsoft.com/en-us/library/windows/desktop/ee418272(v=vs.85).aspx for an explanation of how to interpret data from mouse and how to switch to absolute mode.
It is recommended to use the Raw Input API instead of DirectInput.
(http://msdn.microsoft.com/en-us/library/windows/desktop/ms645536(v=vs.85).aspx)