SDL2 MOUSEBUTTONUP triggers more then once - events

I've been trying to figure this out all day. I'm trying to make a simple check box. But my MOUSEBUTTONUP event keeps firing until I trigger another event like moving the mouse or clicking again.
//If a mouse button was released
if (Sdl_Setup->GetMainEvent()->type == SDL_MOUSEBUTTONUP)
{
//If the left mouse button was pressed
if (Sdl_Setup->GetMainEvent()->button.button == SDL_BUTTON_LEFT)
{
//Get the mouse offsets
SDL_GetMouseState(&mouseX, &mouseY);
//If the mouse is over the button
if ((mouseX > Button->GetX()) && (mouseX < Button->GetX() + Button->GetWidth()) && (mouseY > Button->GetY()) && (mouseY < Button->GetY() + Button->GetHeight()))
{
//Set the button sprite
state = selected;
Button->SetCrop(GetFrameX(), GetFrameY(), state);
clicked = true;
std::cout << clicked << std::endl;
}
}
}
This will just spam 1 in the console (if you dont move the mouse) when all I want is for it to trigger once. From what I've read MOUSEBUTTONUP is only supposed to be sent to the event queue once
I've tried adding a bool to stop it after it's clicked by putting it in an if statement and that works but the thing is I want to be able to toggle the box on and off so when I add an else statement that changes the bool back to false it spams 101010 instead of just one.
//If a mouse button was released
if (Sdl_Setup->GetMainEvent()->type == SDL_MOUSEBUTTONUP)
{
//If the left mouse button was pressed
if (Sdl_Setup->GetMainEvent()->button.button == SDL_BUTTON_LEFT)
{
//Get the mouse offsets
SDL_GetMouseState(&mouseX, &mouseY);
//If the mouse is over the button
if ((mouseX > Button->GetX()) && (mouseX < Button->GetX() + Button->GetWidth()) && (mouseY > Button->GetY()) && (mouseY < Button->GetY() + Button->GetHeight()))
{
if (clicked == false)
{
//Set the button sprite
state = selected;
Button->SetCrop(GetFrameX(), GetFrameY(), state);
clicked = true;
std::cout << clicked << std::endl;
}
else
{
//Set the button sprite
state = noInteraction;
Button->SetCrop(GetFrameX(), GetFrameY(), state);
clicked = false;
std::cout << clicked << std::endl;
}
}
}
}

In Sdl_Setup is where I make the window I'm using and stuff like that and the variable mainEvent is = new SDL_Event(); so then when I was calling GetMainEvent() it was just sending that to PollEvent() over and over again. So all I did is create a quick void function in Sdl_Setup to set mainEvent to a blank SDL_Event() and then call that after clicked = true; and it works.

Related

KeyUp and KeyDown events

I'm working on a typing program to learn touch typing and increase speed.
The program generates random words in the textbox (txtsrc) and the user must type the word in another textbox(txtinput) everything is going right until I stuck in this problem: I want to compare every char in txtinput when the user hit the key down if the key is correct to keep going if not change the color of char in txtsrc to red.
how can I allow the user to use the backspace to remove his errs
and how to compare the chars while the user input the text
I can't find the right algorithm please help
private void txtinput_KeyUp(object sender, KeyEventArgs e)
{
if (keycount < 0) { keycount++; }
if (e.KeyCode == Keys.Back)
{
--keycount;
txtsrc.Select(keycount, 1);
txtsrc.SelectionColor = Color.Black;
}
if (keycount >= 0 && txtinput.Text.Length > 0)
if (txtsrc.Text[keycount] != txtinput.Text[txtinput.Text.Length - 1])
{
txtsrc.Select(keycount, 1);
txtsrc.SelectionColor = Color.Red;
}
if (e.KeyCode != Keys.Back)
{
keycount++;
label1.Text = "Keycount: " + keycount.ToString();
}
}

How to solve, Keyboard hide automatically when we work with multiple view?

We have two search textbox that will dynamically showing. One for portrait view and second for landscape view. We handled input text using flag in ViewDidLayoutSubviews() method. We have written a keyboard hide notification method as KeyboardWillHide(NSNotification notification) for text value handling.
We are getting these issue. Please have a look
1. When we start typing ViewDidLayoutSubviews() method every time call on key press and reload textbox. So my keyboard unable to up. We have fixe this with checking a flag if keyboard will then return.
2. Now we are getting same issue that keyboard hide automatic when we press on mic for speak to write. KeyboardWillHide(NSNotification notification) method every time call and hide keyboard. Its also call when we touch on tableview. 
How to solve these issue ,Please help
private void KeyboardWillHide(NSNotification notification)
{
string orientation = this.InterfaceOrientation.ToString();
if ((orientation.ToString() == "Portrait" || orientation.ToString() == "PortraitUpsideDown") && KeyboardHideSameView == false )
{
SearchText= txtSearchKeywordLS.Text;
txtSearchKeyword.Text = txtSearchKeywordLS.Text;
}
else if ((orientation.ToString() == "LandscapeRight" || orientation.ToString() == "LandscapeLeft") && KeyboardHideSameView == false )
{
SearchText = txtSearchKeyword.Text;
txtSearchKeywordLS.Text = txtSearchKeyword.Text;
}
txtSearchKeyword.ResignFirstResponder();
txtSearchKeywordLS.ResignFirstResponder();
isKeyboardApear = false;
KeyboardHideSameView = false;
}
public override void ViewDidLayoutSubviews()
{
base.ViewDidLayoutSubviews();
if (isKeyboardApear == true) return;
applyViewGradient();
var orientation = this.InterfaceOrientation;
if (orientation.ToString() == "Portrait" || orientation.ToString() == "PortraitUpsideDown")
{
PortraitConst(this.View.Bounds.Height, this.View.Bounds.Width);
this.vwLandscapeHead.Hidden = true;
this.vwPortraitHead.Hidden = false;
this.txtSearchKeyword.Text = SearchText;
txtSearchKeyword.ResignFirstResponder();
txtSearchKeywordLS.ResignFirstResponder();
}
else if (orientation.ToString() == "LandscapeRight" || orientation.ToString() == "LandscapeLeft")
{
//Console.WriteLine("Landscape Mode");
// this.addSubview(landscapeView, containerView);
LandscapeConst(UIScreen.MainScreen.Bounds.Height, UIScreen.MainScreen.Bounds.Width);
applyViewGradient();
this.vwPortraitHead.Hidden = true;
this.vwLandscapeHead.Hidden = false;
this.txtSearchKeywordLS.Text = SearchText;
txtSearchKeyword.ResignFirstResponder();
txtSearchKeywordLS.ResignFirstResponder();
}
// this.containerView.NeedsUpdateConstraints();
}
We have solved it logically by using flags.
We have declare a boolean flag isKeyboardAppear=false when view appear first. When keyboard appear we set this flag to true And we noticed ViewDidLayoutSubviews() method are calling on every key press, so we write this code
public override void ViewDidLayoutSubviews()
{
base.ViewDidLayoutSubviews();
if (isKeyboardAppear == true)
{
return;
}
}
When we hide keyboard manually we reset flag isKeyboardAppear=false .

how to make jqgrid advanced search dialog keyboard accessible

Answer in how to enable enter in jqgrid advanced search window describes how to enable enter and other keys in jqgrid advanced search dialog.
After clicking Add group, Add subgrup, Delete rule or Delete group button in advanced search dialog Enter and other keys are still ignored. How set focus to added element or after delete remaining element to enable Enter and other keys?
The current version of the Advanced Searching dialog (see definition of jqFilter in the grid.filter.js) recreate all controls of the dialog on change of someone. See the code of reDraw which looks
this.reDraw = function() {
$("table.group:first",this).remove();
var t = this.createTableForGroup(p.filter, null);
$(this).append(t);
if($.isFunction(this.p.afterRedraw) ) {
this.p.afterRedraw.call(this, this.p);
}
};
How one can see the first line $("table.group:first",this).remove(); delete the content of all filter. The current focus will be lost and one have the problems which you described.
I suggest to fix the code of reDraw using document.activeElement element which was introduced in Internet Explorer originally (at least in IE4) and which is supported now in all web browsers because it's part of HTML5 standard (see here). The element which has focus originally will be destroyed and one will unable to set focus on it later. So I suggest to save the element name of the element and it's classes (like input.add-group or input.add-rule.ui-add) and to find the position of the element on the searching dialog. Later, after the dialog element will be recreated we'll set focus on the element with the same index.
I suggest to change the code of reDraw to the following
this.reDraw = function() {
var activeElement = document.activeElement, selector, $dialog, activeIndex = -1, $newElem, $buttons,
buttonClass,
getButtonClass = function (classNames) {
var arClasses = ['add-group', 'add-rule', 'delete-group', 'delete-rule'], i, n, className;
for (i = 0, n = classNames.length; i < n; i++) {
className = classNames[i];
if ($.inArray(className, arClasses) >= 0) {
return className;
}
}
return null;
};
if (activeElement) {
selector = activeElement.nodeName.toLowerCase();
buttonClass = getButtonClass(activeElement.className.split(' '));
if (buttonClass !== null) {
selector += '.' + buttonClass;
if (selector === "input.delete-rule") {
$buttons = $(activeElement).closest('table.group')
.find('input.add-rule,input.delete-rule');
activeIndex = $buttons.index(activeElement);
if (activeIndex > 0) {
// find the previous "add-rule" button
while (activeIndex--) {
$newElem = $($buttons[activeIndex]);
if ($newElem.hasClass("add-rule")) {
activeElement = $newElem[0];
selector = activeElement.nodeName.toLowerCase() + "." +
getButtonClass(activeElement.className.split(' '));
break;
}
}
}
} else if (selector === "input.delete-group") {
// change focus to "Add Rule" of the parent group
$newElem = $(activeElement).closest('table.group')
.parent()
.closest('table.group')
.find('input.add-rule');
if ($newElem.length > 1) {
activeElement = $newElem[$newElem.length-2];
selector = activeElement.nodeName.toLowerCase() + "." +
getButtonClass(activeElement.className.split(' '));
}
}
$dialog = $(activeElement).closest(".ui-jqdialog");
activeIndex = $dialog.find(selector).index(activeElement);
}
}
$("table.group:first",this).remove();
$(this).append(this.createTableForGroup(this.p.filter, null));
if($.isFunction(this.p.afterRedraw) ) {
this.p.afterRedraw.call(this, this.p);
}
if (activeElement && activeIndex >=0) {
$newElem = $dialog.find(selector + ":eq(" + activeIndex + ")");
if ($newElem.length>0) {
$newElem.focus();
} else {
$dialog.find("input.add-rule:first").focus();
}
}
};
Like one can see on the next demo the focus in the Searching Dialog stay unchanged after pressing on the "Add subgroup" or "Add rule" buttons. I set it on the "Add rule" buttons of the previous row group in case of pressing "Delete group".
One more demo use jQuery UI style of the buttons and the texts in the buttons (see the answer). After clicking on the "Delete" (rule or group) button I tried to set the focus to the previous "Add Rule" button because setting of the focus on another "Delete" (rule or group) button I find dangerous.
Additionally in the demo I use
afterShowSearch: function ($form) {
var $lastInput = $form.find(".input-elm:last");
if ($lastInput.length > 0) {
$lastInput.focus();
}
}
because it seems me meaningful to set initial focus on the last input field at the dialog opening.
UPDATED: I find additionally meaningful to set focus on the current clicked buttons "Add subgroup", "Add rule" or "Delete group". The advantage one sees in the case it one first click some button with the mouse and then want to continue the work with keyboard. So I suggest to change the line
inputAddSubgroup.bind('click',function() {
to
inputAddSubgroup.bind('click',function(e) {
$(e.target).focus();
To change the line
inputAddRule.bind('click',function() {
to
inputAddRule.bind('click',function(e) {
$(e.target).focus();
and the line
inputDeleteGroup.bind('click',function() {
to
inputDeleteGroup.bind('click',function(e) {
$(e.target).focus();
and the line
ruleDeleteInput.bind('click',function() {
to
ruleDeleteInput.bind('click',function(e) {
$(e.target).focus();

One button selected at a time in listbox (background color)

So I want to set the currently selected button to green background in a listbox while all buttons that are not selected should stay black. How can I do this. View examplecode below.. cant get it working though.
foreach(Button btn in ListBox.Items)
btn.Background = new SolidColorBrush(Colors.Black);
Button clickedButton = sender as Button;
clickedButton.Background = new SolidColorBrush(Colors.Green);
If you want it that way (without Binding and converters) here you go:
(I'm also assuming that only a button is in the listbox item)
for (int i = 0; i < ListBox.Items.Count; i++)
{
Button currentButton = ListBox.Items[i] as Button;
if(currentButton != null)
{
if (i == ListBox.SelectedIndex)
currentButton.Background = new SolidColorBrush(Colors.Green);
else
currentButton.Background = new SolidColorBrush(Colors.Black);
}
}

Inputs in SDL (on key pressed)

I would like to know how can I detect the press of a key or release of a key in a while loop in SDL. Now, I know you can get the events with SDL like OnKeyPressed, OnKeyReleased, OnKeyHit, etc, but I want to know how to build functions like 'KeyPressed' that returns a boolean, instead of being an event. Example:
while not KeyHit( KEY_ESC )
{
//Code here
}
I know you have already selected an answer.. but here is some actual code of how I typically do it with one array. :)
first define this somewhere.
bool KEYS[322]; // 322 is the number of SDLK_DOWN events
for(int i = 0; i < 322; i++) { // init them all to false
KEYS[i] = false;
}
SDL_EnableKeyRepeat(0,0); // you can configure this how you want, but it makes it nice for when you want to register a key continuously being held down
Then later, create a keyboard() function which will register keyboard input
void keyboard() {
// message processing loop
SDL_Event event;
while (SDL_PollEvent(&event)) {
// check for messages
switch (event.type) {
// exit if the window is closed
case SDL_QUIT:
game_state = 0; // set game state to done,(do what you want here)
break;
// check for keypresses
case SDL_KEYDOWN:
KEYS[event.key.keysym.sym] = true;
break;
case SDL_KEYUP:
KEYS[event.key.keysym.sym] = false;
break;
default:
break;
}
} // end of message processing
}
Then when you actually want to use the keyboard input i.e. a handleInput() function, it may look something like this:
void handleInput() {
if(KEYS[SDLK_LEFT]) { // move left
if(player->x - player->speed >= 0) {
player->x -= player->speed;
}
}
if(KEYS[SDLK_RIGHT]) { // move right
if(player->x + player->speed <= screen->w) {
player->x += player->speed;
}
}
if(KEYS[SDLK_UP]) { // move up
if(player->y - player->speed >= 0) {
player->y -= player->speed;
}
}
if(KEYS[SDLK_DOWN]) { // move down
if(player->y + player->speed <= screen->h) {
player->y += player->speed;
}
}
if(KEYS[SDLK_s]) { // shoot
if(SDL_GetTicks() - player->lastShot > player->shotDelay) {
shootbeam(player->beam);
}
}
if(KEYS[SDLK_q]) {
if(player->beam == PLAYER_BEAM_CHARGE) {
player->beam = PLAYER_BEAM_NORMAL;
} else {
player->beam = PLAYER_BEAM_CHARGE;
}
}
if(KEYS[SDLK_r]) {
reset();
}
if(KEYS[SDLK_ESCAPE]) {
gamestate = 0;
}
}
And of course you can easily do what you're wanting to do
while(KEYS[SDLK_s]) {
// do something
keyboard(); // don't forget to redetect which keys are being pressed!
}
**Updated version on my website: **
For the sake of not posting a lot of source code, you can view a complete SDL Keyboard class in C++ that supports
Single Key Input
Simultaneous Key Combos (Keys all pressed in any order)
Sequential Key Combonations (Keys all pressed in specific order)
http://kennycason.com/posts/2009-09-20-sdl-simple-space-shooter-game-demo-part-i.html (if you have any problems, let me know)
There is an SDL function for this: SDL_GetKeyboardState
Example to check whether left or right CTRL key is pressed:
const Uint8* state = SDL_GetKeyboardState(nullptr);
if (state[SDL_SCANCODE_LCTRL] || state[SDL_SCANCODE_RCTRL]) {
std::cerr << "ctrl pressed" << std::endl;
}
I had this problem in LuaJIT with FFI, this is how I solved it:
Global:
KEYS = {}
Event code:
ev = ffi.new("SDL_Event[1]")
function event()
while sdl.SDL_PollEvent(ev) ~= 0 do
local e = ev[0]
local etype = e.type
if etype == sdl.SDL_QUIT then
return false -- quit
-- os.exit() -- prevents interactive mode
elseif etype == sdl.SDL_KEYDOWN then
if e.key.keysym.sym == sdl.SDLK_ESCAPE then
return false -- quit
-- os.exit()
end
print("Pressed: ", e.key.keysym.scancode, "\n")
KEYS[tonumber(e.key.keysym.sym)] = true
-- print("Pressed: ", (e.key.keysym.sym == sdl.SDLK_w), "\n");
elseif etype == sdl.SDL_KEYUP then
KEYS[tonumber(e.key.keysym.sym)] = false
elseif etype == sdl.SDL_VIDEORESIZE then
-- print("video resize W:".. e.resize.w .. " H:" .. e.resize.h)
width = e.resize.w
height = e.resize.h
onResize()
end
end
return true -- everything ok
end
Update function:
if KEYS[sdl.SDLK_w] == true then
rot = rot + 1
end
Most time i wasted on this:
KEYS[tonumber(e.key.keysym.sym)] = false
Because FFI is returning a CData object, which was used as the array-key, but it needs the integer.
You should have 2 tables of booleans for keys. One table, in which you set keys true or false based on the SDL keydown/keyup events, and another one, that you initialize with false. When checking keyPressed, you just compare the second table key with the first table key, and if different, if second table key is false, then it was pressed, else it was released. After that, you do secondTable[key] := not secondTable[key]. Works!

Resources