Problem with String Input using SDL

Started by
9 comments, last by Wooh 12 years, 5 months ago
I am new this forum and I have problem with input

It is hard to fix it string input any keys and I've not have ideas to fix "~~ ~ " ' ! @ # $ % ¨¨ & * ( ) _ + { } [ ] ´ / ; ? . , > < " etc. Becuase I want make login for online.

Thank you for the help.
Advertisement
Your question is very unclear. I assume your problem is related to translating SDL_KeyboardEvents into text. You can enable unicode translation at the start of your program, using SDL_EnableUNICODE(SDL_TRUE). You can then inspect event.key.keysym.unicode and get the text from it.

Here is a function I have used in the past for this:

char getUnicodeValue( const SDL_KeyboardEvent &key )
{
// magic numbers courtesy of SDL docs :)
const int INTERNATIONAL_MASK = 0xFF80;
const int UNICODE_MASK = 0x7F;

int uni = key.keysym.unicode;
if( uni == 0 ) // not translatable key (like up or down arrows)
{
// probably not useful as string input
// we could optionally use this to get some value
// for it: SDL_GetKeyName( key );
return '\0';
}
if( ( uni & INTERNATIONAL_MASK ) == 0 )
{
if( SDL_GetModState() & KMOD_SHIFT )
{
return (char)(toupper(uni & UNICODE_MASK));
}
else
{
return (char)(uni & UNICODE_MASK);
}
}
else // we have a funky international character. one we can't read :(
{
// we could do nothing, or we can just show some sign of input, like so:
return '?';
}
}

You can then append this character to a std::string instance, provided it is not the NUL character (the character literal '\0').
Hmmm, it bugged when I pressed any key, it will freezes my game.

Thank for you the help
You still aren't explaining your problem well. What is the program supposed to be doing? What is it actually doing? Can you post your code? Or a minimal example that demonstrates the behaviour?
Here is my code:


#pragma warning( disable : 4800 )

#ifdef main
#undef main
#endif

#include "functions.h"
#include "keyboard.h"

#include "SDL.h"
#include "SDL_image.h"
#include "SDL_ttf.h"
#include "SDL_resize.h"
//#include "SDL_net.h"

#include "tchar.h"
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include <windows.h>
#include <iostream>
#include <fstream>
#include <string>
#include <sstream>
#include <direct.h>

#include "IniWriter.h"
#include "IniReader.h"

#define DEBUG

using namespace std;

SDL_Surface *screen = NULL;

SDL_Surface *onMainBG = NULL;
SDL_Surface *onLoginTB = NULL;
SDL_Surface *onPasswordTB = NULL;

int modeX;
int modeY;
bool fullscreenS;
bool isDefaultSettingsResolution;
Uint8* keyboard;

SDL_Event event;

bool running;

/*

List of credits:
• xiaohe521 - IniWriter and IniReader
• rip-off - Helper
• http://www.freeimages.co.uk/ - Images
• http://www.libsdl.org/ - SDL and SDL_Resize
• http://www.zedwood.com/ - MD5 function

*/

char getUnicodeValue( const SDL_KeyboardEvent &key )
{
// magic numbers courtesy of SDL docs :)
const int INTERNATIONAL_MASK = 0xFF80;
const int UNICODE_MASK = 0x7F;

int uni = key.keysym.unicode;
if( uni == 0 ) // not translatable key (like up or down arrows)
{
// probably not useful as string input
// we could optionally use this to get some value
// for it: SDL_GetKeyName( key );
return '\0';
}
if( ( uni & INTERNATIONAL_MASK ) == 0 )
{
if( SDL_GetModState() & KMOD_SHIFT )
{
return (char)(toupper(uni & UNICODE_MASK));
}
else
{
return (char)(uni & UNICODE_MASK);
}
}
else // we have a funky international character. one we can't read :(
{
// we could do nothing, or we can just show some sign of input, like so:
return '?';
}
}

void onLoadFiles()
{
onMainBG = LImage(".\\data\\main\\bg.png");

if (isDefaultSettingsResolution == false)
{
SDL_Resize(onMainBG, modeX, modeY, screen, 4);
}
}

int main( int argc, char* args[] )
{
ifstream CheckFile(".\\settings.ini");

if ( !CheckFile.is_open() )
{
int msok = MessageBox(NULL, "Can't find \"settings.ini\".", "Error", MB_OK | MB_ICONQUESTION );
if ( msok )
{
int msyesno = MessageBox(NULL, "Do you want create settings?", "Request", MB_YESNOCANCEL | MB_ICONQUESTION );
if ( msyesno == 6 )
{
ofstream CheckFile(".\\settings.ini");
CheckFile << "[Graphics]\n";
CheckFile << "ResolutionX=800\n";
CheckFile << "ResolutionY=600\n";
CheckFile << "Fullscreen=false\n";
}
else
{
return 1;
}
}
}

CIniReader iniReader(".\\settings.ini");
modeX = iniReader.ReadInteger("Graphics", "ResolutionX", 800);
modeY = iniReader.ReadInteger("Graphics", "ResolutionY", 600);
fullscreenS = iniReader.ReadBoolean("Graphics", "Fullscreen", true);

if (modeX == 800 || modeY == 600) { isDefaultSettingsResolution = true; }
else { isDefaultSettingsResolution = false; }

if( SDL_Init( SDL_INIT_EVERYTHING ) == -1 )
{
MessageBox( NULL, "Can't run this game." , "ERROR", MB_OK | MB_ICONERROR );
return 1;
}
else
{
SDL_WM_SetCaption( "The RPG", NULL );
SDL_WM_SetIcon( IMG_Load(".\\icon.ico"), NULL );
showMouse(false);
if (fullscreenS == true) { screen = SDL_SetVideoMode( modeX, modeY, 32, SDL_SWSURFACE|SDL_FULLSCREEN ); }
else { screen = SDL_SetVideoMode( modeX, modeY, 32, SDL_SWSURFACE ); }
if ( screen == NULL ) { MessageBox( NULL, "Can't create windows.", "Error", MB_OK | MB_ICONERROR ); return 1; }
if ( TTF_Init() == -1 ) { return 1; }
}

const int FPS=30;
Uint32 StartFPS;
int testi = 0;
string keystring;



onLoadFiles();
SDL_EnableUNICODE( SDL_TRUE );

running = true;

while( running )
{
StartFPS = SDL_GetTicks();
while( SDL_PollEvent( &event ) )
{

switch ( event.type )
{
case SDL_QUIT:
running = false;

case SDL_KEYUP:
switch ( event.key.state )
{
case SDL_RELEASED:
switch ( event.key.keysym.sym )
{
case SDLK_LSHIFT:
SDL_CapsLock(false);
case SDLK_RSHIFT:
SDL_CapsLock(false);
}
}
case SDL_KEYDOWN:

keystring += getUnicodeValue(event.key);

switch ( event.key.keysym.sym )
{
case SDLK_ESCAPE:
running = false;
}
switch ( event.key.state )
{
case SDL_PRESSED:

switch ( event.key.keysym.sym )
{
case SDLK_LSHIFT:
SDL_CapsLock(true);
case SDLK_RSHIFT:
SDL_CapsLock(true);
}

}
}
}

SDL_FillRect( screen, &screen->clip_rect, SDL_MapRGB(screen->format, 0xff, 0xff, 0xff) );

drawImage(0, 0, onMainBG, screen, NULL);

drawText(0, 255, 0, 255, IntToString(testi), ".\\data\\font\\font3.fon", "center", 32, 100, 0, screen);
drawText(0, 255, 0, 255, keystring, ".\\data\\font\\font3.fon", "center", 32, 100, 20, screen);




if( SDL_Flip( screen ) == -1 ) { return 1; }
if( 1000/FPS>(SDL_GetTicks()-StartFPS) ) { SDL_Delay(1000/FPS-(SDL_GetTicks()-StartFPS)); }
}

SDL_FreeSurface(onMainBG);
SDL_Quit();
return 0;
}
There are some bugs in your code. The main one is that your switch statements don't contain "break" statements - which results in far more code being executed for each event.

You also don't check the return value of getUnicodeValue(), which returns the NUL character (0 or '\0') when it encounters a non-textual character.

Here is a small program demonstrating how to use it. It uses the window caption to display the text:

#include "SDL.h"

#include <iostream>
#include <string>

char getUnicodeValue( const SDL_KeyboardEvent &key )
{
// magic numbers courtesy of SDL docs :)
const int INTERNATIONAL_MASK = 0xFF80;
const int UNICODE_MASK = 0x7F;

int uni = key.keysym.unicode;
if( uni == 0 ) // not translatable key (like up or down arrows)
{
// probably not useful as string input
// we could optionally use this to get some value
// for it: SDL_GetKeyName( key );
return '\0';
}
if( ( uni & INTERNATIONAL_MASK ) == 0 )
{
if( SDL_GetModState() & KMOD_SHIFT )
{
return (char)(toupper(uni & UNICODE_MASK));
}
else
{
return (char)(uni & UNICODE_MASK);
}
}
else // we have a funky international character. one we can't read :(
{
// we could do nothing, or we can just show some sign of input, like so:
return '?';
}
}

int main( int argc, char* args[] )
{
int modeX = 800;
int modeY = 600;
bool fullscreen = false;

if( SDL_Init( SDL_INIT_EVERYTHING ) == -1 )
{
std::cerr << "Failed to initialise SDL: " << SDL_GetError() << '\n';
return 1;
}

Uint32 flags = fullscreen ? SDL_FULLSCREEN : SDL_SWSURFACE;
SDL_Surface *screen = SDL_SetVideoMode( modeX, modeY, 32, flags);

if (!screen)
{
std::cerr << "Failed to set video mode: " << SDL_GetError() << '\n';
return 1;
}

std::string keystring;

SDL_EnableUNICODE( SDL_TRUE );

bool running = true;
SDL_Event event;
while( running )
{
while( SDL_PollEvent( &event ) )
{
switch ( event.type )
{
case SDL_QUIT:
running = false;
break;
case SDL_KEYDOWN:
switch ( event.key.keysym.sym )
{
case SDLK_ESCAPE:
running = false;
break;

case SDLK_BACKSPACE:
if(!keystring.empty())
{
keystring.erase(keystring.end() - 1);
}
break;

case SDLK_RETURN:
keystring.erase(keystring.begin(), keystring.end());
break;

default:
char key = getUnicodeValue(event.key);
if(key != '\0')
{
keystring += key;
}
break;
}
}
}

SDL_FillRect( screen, NULL, 0);
const char *title = keystring.empty() ? "(no input)" : keystring.c_str();
SDL_WM_SetCaption(title, NULL);
if( SDL_Flip( screen ) == -1 )
{
return 1;
}
}

SDL_Quit();
return 0;
}

Again, you haven't really describe what is or isn't happening. I had to distill the likely problems from examining the source, and refining it into a minimal example. Your example had too many dependencies to be considered minimal.

Not everyone would go to this amount of effort to help you out. Not everyone would have time to. I would seriously suggest you consider making more of an effort to clearly and concisely explain the problems you have.
Wow, thank you very much. I forget about break; and I didnt know there is flags "Uint32"

You'll be added credis

EDIT:
How do i give you a +rep?
If I tell you will you give me one?

Hit the Like This button in the lower-right of the post.


L. Spiro


P.S.: I was joking about giving me one.

I restore Nintendo 64 video-game OST’s into HD! https://www.youtube.com/channel/UCCtX_wedtZ5BoyQBXEhnVZw/playlists?view=1&sort=lad&flow=grid

Thanks[color="#B57438"] YogurtEmperor[color="#000000"].

One more,

Is there fix for "¹²³£¢¬" ?

Sorry for the stupid questions again.

Edit:
Again is there no "é è ã â ê ê `` ´´" ;(
Bump.

I need it working 100% any keys.

This topic is closed to new replies.

Advertisement