I have a number of TStringGrids inside TTab's and have been using
if (Key==VK_RETURN) for years (its an old app) as the trigger to execute code pertaining the the cell entry.
I would now like the option to delete the Cell contents, by writing a empty string to it, so tried using
if (Key==VK_DELETE)
yet the Delete Button does not trigger the OnKeyPress event at all in my case.
I was hoping to capture the event via the following code pertaining to the specific active Stringrid1
void __fastcall TPagesDlgLoadEditorFixed::StringGrid1KeyPress(TObject
*Sender, char &Key)
{
int Grid = 1;
EntriesOnStringGrid(Key, Grid);
}
and with the KeyPress then passed on code that is common to all the StringGrids, as follows:
void TPagesDlgLoadEditorFixed::EntriesOnStringGrid(char &Key, int Grid)
{
if (Key==VK_RETURN)
{
//code works fine
}
if (Key==VK_DELETE)
{
//code has no effect
}
}
However whilst in debug mode, one can see that the StringGrid1KeyPress event is not triggered at all by the "Delete" button.
Any advise would be greatly appreciated.
It's generally better to use OnKeyUp and OnKeyDown when checking for virtual key codes instead of OnKeyPress.
So using that should fix your problem and then it will detect VK_DELETE when it's pressed or let go.
Related
I have a ListGrid defined like this:
ListGrid lgrid = new ListGrid();
ListGridField first = new ListGridField("first",first");
ListGridField second = new ListGridField("second ",second ");
lgrid.setFields(first, second);
lgrid.setShowFilterEditor(true);
¿How can i put the keyboard focus in the first filter editor field after i call show() in the layout?
Thxs in advance.
Depending on what your use case is (which would be useful to provide a more focused answer), the solution you posted might not be what you really need, because if you scroll on your ListGrid, it could trigger a new data fetch (if there are more records to show), and move the cursor to the filter editor as a result (if your user is editing some records at that point, the cursor moving to the filter row is not what she would want to happen!!).
In such a case, you probably just want to call grid.focusInFilterEditor("fieldToFocus") after the listGrid.show() statement or in the ClickHandler of some button you use to fetch the data, etc.
Anyway, you don't need the Timer either. This works:
listGrid.addDataArrivedHandler(new DataArrivedHandler() {
#Override
public void onDataArrived(DataArrivedEvent event) {
grid.focusInFilterEditor("fieldToFocus");
}
});
I got the solution, its focusInFilterEditor, this is an example to set the focus after the data arrived to the grid:
// Put the focus on the first listGrid field when is loaded
listGrid.addDataArrivedHandler(new DataArrivedHandler() {
#Override
public void onDataArrived(DataArrivedEvent event) {
Timer t = new Timer() {
public void run() {
if(listGrid.getFilterEditorCriteria() == null){
listGrid.focusInFilterEditor("fieldToFocus");
}
}
};
t.schedule(600);
}
});
I couldn't find an implementation of a double tap for Appium that was straightforward and allowed you to pass in the element locator strategy, so here goes:
public static void doubleTapElementBy(By by) {
WebElement el = getDriver().findElement(by);
MultiTouchAction multiTouch = new MultiTouchAction(getDriver());
TouchAction action0 = new TouchAction(getDriver()).tap(el).waitAction(50).tap(el);
try {
multiTouch.add(action0).perform();
} catch (WebDriverException e) {
logger.info("Unable to do second tap on element, probably because element requieres single tap on this Android version");
}
}
You can also try below approach using tap method in TouchAction class.
TouchAction taction = new TouchAction(driver);
taction.tap(tapOptions().withElement(ElementOption.element(YOUR_WebElement))
.withTapsCount(2)).perform();
You will need to add below static import as well:
import static io.appium.java_client.touch.TapOptions.tapOptions;
This is a workaround in pseudocode and possibly there's a more "official" way to do it, but it should do the work if no other solution is available:
Interpretmessages(){
switch(msg)
{
OnClick:
{ if (lastClicked - thisTime() < 0.2) //if it was clicked very recently
{doubleTapped()} //handle it as a double tap
else{lastClicked = thisTime()} //otherwise keep the time of the tap
} //end of OnClick
} //End of Message Handler
}//End of switch
}//End of messageHandler
If you have access to ready timer functions, you can set a function to be executed 0.2s after the click has gone off:
OnClick: if (!functionWaiting) // has the timer not been set?
{
enableTimer(); // set a function to go off in x time
clicks = 0; //we'll tell it that there's been one click in a couple of lines
} //set it for the first click
clicks++; //if it's already clicked, it'll become 2 (double tap) otherwise it's just one
So, the idea is that when you get a tap, you check if there's been another one recently (a. by checking the relative times, b. by checking if the function is still pending) and you handle it dependingly, only note that you will have to implement a timer so your function fires a bit later so you have time to get a second tap
The style draws upon the Win32's message handling, I'm pretty sure it works there, it should work for you too.
Double tap and hold -- Use below code:
new TouchAction(driver).press(112,567).release().perform().press(112,567).perform();
Double tap -- Use below code:
new TouchAction(driver).press(112,567).release().perform().press(112,567).release().perform();
I'm working with the Blackberry Touch Event and I need to process the TouchEvent.MOVE, TouchEvent.UP and TouchEvent.DOWN to move a carousel of images and the TouchEvent.CLICK to generate some specific action.
My problem is that the touchEvent() method is being called several times. How can I prevent this? Because the behaviour is getting all messed up.
For example: when I just want to capture the TouchEvent.CLICK event, the UP-DOWN-MOVE-CLICK are being triggered one after the next.
My code does the following:
protected boolean touchEvent(TouchEvent message) {
if (message.getEvent() == TouchEvent.CLICK) {
//CHANGE THE CONTENT OF A FIELD
return true;
} else if ((message.getEvent() == TouchEvent.MOVE)
|| (message.getEvent() == TouchEvent.UP)
|| (message.getEvent() == TouchEvent.DOWN)) {
//DELETE THE FIELD
//MOVE A CAROUSEL OF IMAGES
} else {
return false;
}
}
public void moverTouch(int dx) {
//ADD THE FIELD PREVIOUSLY DELETED
}
As you can see, when the CLICK event is captured, I need to change the content of a field, but when the MOVE or UP or DOWN event is captured, I need to delete that Field from his manager, do some working with a carousel of images, and then re-add the field previously deleted.
The carousel moving part works fine, but when I try to capture JUST the CLICK event, and the others are being triggered as well, but the moverTouch() function doesn't get triggered because there is no actual movement on the carousel of images, I end up with a deleted field that I need to update its content.
At a glance:
I think you need to differentiate touch gestures (I believe you are "listening" for something like a swipe gesture to scroll the gallery image) from "normal" touch events (specifically you need to process TouchEvent.CLICK to apply "some specific action" to the clicked image).
To decide whether the TouchEvent represents a gesture there is a TouchEvent.GESTURE constant. Then it is possible to know what exactly TouchGesture it represents by calling TouchEvent.getGesture().
Some sample code for touch gestures can be viewed here.
I am dealing with KeywordFilterField which is populated with the list of the countries. Now the problem i am facing is that when i click the particular country it should move to the next screen as I have written the pushScreen code in the trackwheelClick event after checking that _keywordFilterField is focusable or not, but this is not the case. The Menu opens when trackwheelClick event is fired, at the center of the screen, rather than moving onto the next screen.Can anybody have the idea why Menu dialog opens on the trackwheelclick event instead of going to the next screen.
See what i have done on trackwheel click event:
protected boolean trackwheelClick(int status, int time) {
if (_keywordFilterField.isFocus()) {
int index = _keywordFilterField.getSelectedIndex();
ReadableList readableList = _keywordFilterField.getResultList();
Object selectedCountry = readableList.getAt(index);
String countryName=selectedCountry.toString();
urlutf8Encoder=new URLUTF8Encoder();
String newCountry=urlutf8Encoder.encode(countryName);
pushToSearchResult(newCountry,countryName);//To Next SCreen
return true;
}
return false;
}
But it looks like:
The trackwheelClick event returns a boolean that indicates whether the event is consumed. Once an event is consumed, it stops propagating to other UI elements. If you return true, the menu will stop appearing.
I have a C# application that uses SpreadsheetGear's WorkbookView control. A user wants to be able to have changes he makes to comments on a cell saved.
Does anyone know of a way to capture changes when a user edits a comment. The cell edit events are not fired when a comment is edited and I can not find any way to capture changes a user makes to comments.
Before I read Joe's reply not knowing of a way to save comments individually, I decided to save comments by looping through the cells in a workbookView and grabbing the comments as the form is closing.
After seeing his reply, I found a way to get a comment right after it is entered using a combination of the workbookView1_ShapeSelectionChanged and workbookView1_ShapeAction events. The workbookView1_ShapeSelectionChanged event fires when the comment box is opened for editing and when the comment box is closed for editing. When it fires for the comment box opening, I get the ActiveCell because it may no longer be the ActiveCell when the comment box closes. I use that cell for getting the comment when the comment box closes if a comment has changed. The workbookView1_ShapeAction event fires everytime a new character is entered in the comment box which is useful for marking the comment as changed. After the comment is saved, the commentChanged variable is set back to false. Here is the code using the code that Joe posted in his answer:
private void workbookView1_ShapeAction(object sender, SpreadsheetGear.Windows.Forms.ShapeActionEventArgs e)
{
switch (e.ShapeActionType)
{
case SpreadsheetGear.Windows.Forms.ShapeActionType.TextChanged:
if (e.Shape.Type == SpreadsheetGear.Shapes.ShapeType.Comment)
{
//set comment changed flag to true
_commentChanged = true;
}
break;
}
}
private void workbookView1_ShapeSelectionChanged(object sender, SpreadsheetGear.Windows.Forms.ShapeSelectionChangedEventArgs e)
{
if (_commentChanged)
{
//get comment
string comment = _commentCell.Comment.Shape.TextFrame.Characters.Text;
//save comment
//....
//set comment changed flag to false
_commentChanged = false;
}
else
{
//get the cell whose comment is being edited
_commentCell = workbookView1.ActiveCell;
}
}
Unfortunately, the answer is "sort of but not really".
You can catch the ShapeAction event as demonstrated below, but the ShapeAction event is really designed for shapes and not for comments so you cannot get the current text (the text hsa not yet been stored in the shape) and you cannot even get the cell which the comment belongs to. Still, I will paste in some code since it might be of use to you:
private void workbookView1_ShapeAction(object sender, SpreadsheetGear.Windows.Forms.ShapeActionEventArgs e)
{
switch (e.ShapeActionType)
{
case SpreadsheetGear.Windows.Forms.ShapeActionType.TextChanged:
if (e.Shape.Type == SpreadsheetGear.Shapes.ShapeType.Comment)
{
// Unfortunately, this is as far as we can get since IShape
// does not have a way to get back to the cell which owns the comment.
//
// Furthermore, the text is not yet stored in the IShape, so we
// cannot get the current text either.
}
break;
}
}
If you send email to support at SpreadsheetGear requesting this capability they will add this feature request to their list with your email address associated with it.