I'm trying to figure out if there is any way in which we can detect if shift key is pressed or if any notification is sent when shift key is pressed in UIKeyboard
- (BOOL) textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)string
does not get called for shift key press since it is a modifier key.
Don't know whether you need to know it in combination with other text or only detect the single shift tap, but here is my solution for detecting the former:
in my case this is only a single character within:
- (BOOL)textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)inText
this converts uppercase text to lowercase and sets the shiftPressed Value (ignored if the text is non letter text)
//Shift Detection
BOOL shiftPressed = NO;
//Detect non letter characters
NSCharacterSet *letterCharacterSet = [NSCharacterSet letterCharacterSet];
NSString *trimmedText = [text stringByTrimmingCharactersInSet:letterCharacterSet];
if ([text length] == 1) {
if (![trimmedText length])
{
NSString *upperCaseString = [text uppercaseString];
if ([upperCaseString isEqualToString:text]) {
NSString *lowerCaseString = [text lowercaseString];
text = lowerCaseString;
shiftPressed = YES;
}
}
}
Related
In Flutter, after a Paragraph or TextPainter has laid out it's text, you can get the Rects for the lines (or runs within a line) by calling getBoxesForSelection. If you draw the actual boxes they look something like this:
How do I programmatically get the text within each TextBox?
I wish there were a better way, but this is the only way I have found so far:
// The TextPaint has already been laid out
// select everything
TextSelection selection = TextSelection(baseOffset: 0, extentOffset: textSpan.text.length);
// get a list of TextBoxes (Rects)
List<TextBox> boxes = _textPainter.getBoxesForSelection(selection);
// Loop through each text box
List<String> lineTexts = [];
int start = 0;
int end;
int index = -1;
for (TextBox box in boxes) {
index += 1;
// Uncomment this if you want to only get the whole line of text
// (sometimes a single line may have multiple TextBoxes)
// if (box.left != 0.0)
// continue;
if (index == 0)
continue;
// Go one logical pixel within the box and get the position
// of the character in the string.
end = _textPainter.getPositionForOffset(Offset(box.left + 1, box.top + 1)).offset;
// add the substring to the list of lines
final line = rawText.substring(start, end);
lineTexts.add(line);
start = end;
}
// get the last substring
final extra = rawText.substring(start);
lineTexts.add(extra);
Notes:
To be more rebust, this should check the TextPosition affinity.
This doesn't handle right-to-left text yet.
Update:
If you are getting the text of the whole line, you can use LineMetrics (from TextPainter.computeLineMetrics()) now instead of TextBox. The process would be similar.
I'm trying to display one character at a time in processing. If I type the letter "Q" for example, how can I make it so that when I type another character, it displays in the same place as the previous one but deleting the previous one in the process?
ultimately I'm trying to make a program that would show any pressed key on different fonts; but when I attempted this, the characters just keep adding in succession.
As of now, this gives me characters in succession:
String letters = "";
void setup() {
size(100, 100);
stroke(255);
fill(0);
textSize(16);
}
void draw() {
background(204);
text(letters, 0, 50);
}
void keyPressed() {
if (key == BACKSPACE) {
if (letters.length() > 0) {
letters = letters.substring(0, letters.length()-1);
}
} else if (textWidth(letters+key) < width) {
letters = letters + key;
}
}
How is it possible to have only one character showed at all times?
Look at this line:
letters = letters + key;
Here you're adding key to the letters variable. So if letters is "ABC" and key is 'X', then letters will be "ABCX" after this line runs.
If all you want to do is display the most recent key pressed, why don't you just use the key value directly? That's exactly what it holds:
void draw() {
background(0);
text(key, 25, 25);
}
I am trying to move to the next focus of an application by transmit a TAB or ENTER character to the host from my Motorola MT2070 Barcode Scanner.
I have tried using the SendLabel method as follows
string barcode = "Hello";
int count = 1;
SendBarcode(new LabelData(barcode + "\t" + count.ToString(), Options.BarcodeType));
count++;
}
private bool SendBarcode(LabelData label)
{
RESULTCODE result = RESULTCODE.E_OK;
try
{
result = Program.ScannerServicesClient.SendLabel(label, 10000);
}
catch
{
result = RESULTCODE.E_HOST_NOT_READY;
}
if (result != RESULTCODE.E_OK)
{
MsgBox.Error(listForm, Properties.Resources.StrErrorCouldntSendBarcode);
}
return result == RESULTCODE.E_OK;
}
Unfortunately the "\t" does not translate into an actual TAB keystroke in Keyboard mode.
When scanning in NOTEPAD the 5 spaces of the tab show up, but it doesn't work to move the focus to the next field as hitting TAB does in Excel or other applications.
What should I be transmitting in place of the \t?
Thanks!
I assume this won't work, because it is not a normal/manual input from your keyboard. It is a value passed from a barcode to the text-property of your field. So you have to handle this different.
I am getting text from CEdit control. I need to imitate the same text on image. The edit control is multiline, so when I keep on typing long string the remaining part of the word goes to the next line.
I am not getting at which text index in the CEdit the character goes on the next line.
So while trying to do this, I am able to insert "\r\n" if the width of line exceed the width of the rect. But the problem is if the alignment is center the the character after the inserted "\r\n" is treated as new word by the DrawText api and purpose of the above insertion of new-line character fails.
Can someone let me know, Is there some way I can know where the line is breaking in CEdit or alternative for the same.
CString strTempFormattedText(_T(""));
LONG tempTotalWidth = 0;
for(int i = 0; i < myText.GetLength(); i++) {
TCHAR tempChar = myText.GetAt(i);
tempTotalWidth += pDC->GetTextExtent(CString(tempChar), 1).cx;
if(tempTotalWidth >= rc.Width()) {
tempTotalWidth = 0;
strTempFormattedText.Append(_T("\n\r"));
}
strTempFormattedText.AppendChar(tempChar);
}
myText = strTempFormattedText;
switch(ALIGNMENT)
{
case RIGHT:
pDC->DrawText(myText, -1, rc, DT_WORDBREAK | DT_RIGHT );
break;
case CENTER:
pDC->DrawText(myText, -1, rc, DT_WORDBREAK | DT_CENTER);
break;
case LEFT:
pDC->DrawText(myText, -1, rc, DT_WORDBREAK | DT_LEFT);
break;
}
Thanks
I think you should combine LineIndex, LineLength and PosFromChar to solve your problem. Using the API instead of the data could be useful if you will need access the more complex CRichEditText.
I've got a little text drawing puzzle under Win32. I'm trying to draw some instructions for users of my application at the top of the window.
Please refer to the following window (I've changed the background color on the text so you can see the boundaries)
(source: billy-oneal.com)
I'm currently using DrawTextEx to draw the text to my window, but the problem is that it does not fill the entire RECTangle that I give it. Not drawing that area is just fine, until the window resizes:
(source: billy-oneal.com)
When the text is re wrapped due to the window sizing, because DrawTextEx doesn't clear it's background, these artifacts are leftover.
I tried using FillRect to fill in the area behind the text drawing call, which does eliminate the visual artifacts, but then causes the text to flicker constantly, as it is completely erased and then completely redrawn to the display.
Any ideas on how one might get the area not containing text to be drawn with the background color?
EDIT: I'd like to avoid having to double buffer the form if at app possible.
EDIT2: I solved the problem by only redrawing the text when I detect that the wrapping changes during a resize.
Use double buffering?
Draw everything to a bitmap and draw the bitmap to the window. Flickering is commonly a double buffering issue.
There are many possible solutions and without seeing your code, it's hard to tell which method would be best so I'd suggest taking a look at this article on flicker free drawing
SetBkMode + SetBkColor ?
Well since nobody seems to know what to do about it, I implemented it this way:
std::vector<std::wstring> wrapString(HDC hDC, const std::wstring& text, const RECT& targetRect, HFONT font)
{
std::vector<std::wstring> result;
RECT targetRectangle;
CopyRect(&targetRectangle, &targetRect);
//Calculate the width of the bounding rectangle.
int maxWidth = targetRectangle.right - targetRectangle.left;
//Draw the lines one at a time
std::wstring currentLine;
for(std::wstring::const_iterator it = text.begin(); it != text.end(); currentLine.push_back(*it), it++)
{
if(*it == L'\r' || *it == L'\n')
{ //Hard return
while(it != text.end() && (*it == L'\r' || *it == L'\n')) it++;
result.push_back(currentLine);
currentLine.clear();
}
else
{ //Check for soft return
SIZE sizeStruct;
GetTextExtentPoint32(hDC, currentLine.c_str(), static_cast<int>(currentLine.length()), &sizeStruct);
if (sizeStruct.cx > maxWidth)
{
std::wstring::size_type lineLength = currentLine.find_last_of(L' ');
if (lineLength == currentLine.npos)
{ //Word is longer than a line.
for(;it != text.end() && !iswspace(*it);it++) currentLine.push_back(*it);
}
else
{ //Clip word to line.
//Backtrack our scan of the source text.
it -= currentLine.length() - lineLength - 1;
//Remove the clipped word
currentLine.erase(lineLength);
}
result.push_back(currentLine);
currentLine.clear();
}
}
}
//Last remaining text.
result.push_back(currentLine);
return result;
}
void DrawInstructionsWithFilledBackground(HDC hDC, const std::wstring& text, RECT& targetRectangle, HFONT font, COLORREF backgroundColor)
{
//Set up our background color.
int dcIdx = SaveDC(hDC);
HBRUSH backgroundBrush = CreateSolidBrush(backgroundColor);
SelectObject(hDC, backgroundBrush);
SelectObject(hDC, font);
SetBkColor(hDC, backgroundColor);
std::vector<std::wstring> lines(wrapString(hDC, text, targetRectangle, font));
for(std::vector<std::wstring>::const_iterator it = lines.begin(); it!=lines.end(); it++)
{
RECT backgroundRect = targetRectangle;
DrawText(hDC, const_cast<LPWSTR>(it->c_str()), static_cast<int>(it->length()), &backgroundRect, DT_CALCRECT | DT_NOCLIP | DT_SINGLELINE);
backgroundRect.left = backgroundRect.right;
backgroundRect.right = targetRectangle.right;
if (backgroundRect.right >= backgroundRect.left)
FillRect(hDC, &backgroundRect, backgroundBrush);
ExtTextOut(hDC, targetRectangle.left, targetRectangle.top, ETO_OPAQUE, NULL, it->c_str(), static_cast<UINT>(it->length()), NULL);
targetRectangle.top += backgroundRect.bottom - backgroundRect.top;
}
instructionsWrap = lines;
//Restore the DC to it's former glory.
RestoreDC(hDC, dcIdx);
DeleteObject(backgroundBrush);
}
Get/Calculate the rect used by the DrawText call and clip it with something like ExcludeClipRect before calling FillRect