0

I'm trying to create a program that plays different sounds when you press different keys. I was planning to take the char key , add the string ".wav" and input that new string called "sound" into the line:

PlaySound(TEXT(sound), NULL, SND_FILENAME | SND_ASYNC);

The code does not compile and gives the error "identifier 'Lsound' is undefined" I've tried replacing "TEXT" with "string" but it gives the error message "no suitable conversion function from 'std::string' to 'LPCWSRT' exists".

Any help with a solution would be greatly appreciated.

#include <iostream>
#include <Windows.h>

using namespace std;

int main() {

    char i;

    while (true) {
        for (i = 8; i <= 255; i++) {
            if (GetAsyncKeyState(i) == -32767) {
                string sound = i + ".wav";
                PlaySound(TEXT(sound), NULL, SND_FILENAME | SND_ASYNC);
            }   
        }
    }
    return 0;
}

  • 1
    Why this failed: the `TEXT` macro converts a string literal to wide character, IF unicode is enabled, by prepending an `L` to the macro's argument.`TEXT("string"`)` is preprocessed into `L"string"`. Macros are utterly stupid, so it doesn't care that you're not using a string literal here; it mindlessly slaps an `L` onto the front of the variable name. – user4581301 Jul 06 '20 at 19:19
  • `TEXT` was implemented as a solution to a problem from the late 1990s as Microsoft switched from the simple-but-limited world of ANSI characters to Unicode characters and had tools and operating systems simultaneously supporting both. This hasn't really been an issue since Windows XP killed off all of its predecessors in the early 2000s. It's 2020 now. You can mess around converting the string this way and that, but it's often a lot easier to simply start in Unicode and stay in Unicode. – user4581301 Jul 06 '20 at 19:19

3 Answers3

0

You must convert the string to LPCTSTR

Using How to convert std::string to LPCWSTR in C++ (Unicode)

#include <iostream>
#include <Windows.h>

using namespace std;

std::wstring s2ws(const std::string& s)
{
    int len;
    int slength = (int)s.length() + 1;
    len = MultiByteToWideChar(CP_ACP, 0, s.c_str(), slength, 0, 0);
    wchar_t* buf = new wchar_t[len];
    MultiByteToWideChar(CP_ACP, 0, s.c_str(), slength, buf, len);
    std::wstring r(buf);
    delete[] buf;
    return r;
}


int main() {
    while (true) {
        for (int i = 8; i <= 255; i++) {
            if (GetAsyncKeyState(i) == -32767) {
                string sound = i + ".wav";
                PlaySound(s2ws(sound).c_str(), NULL, SND_FILENAME | SND_ASYNC);
            }
        }
    }
    return 0;
}
JonathanK
  • 198
  • 1
  • 10
0

Just pass a wide string from the start.

std::wstring sound = i + L".wav";
PlaySound(sound.c_str(), NULL, ... 

In Windows, native strings are UTF-16 and are represented by wchar_t and variants of w in STL (wstring etc).

Michael Chourdakis
  • 10,345
  • 3
  • 42
  • 78
0

The solution depends on what your "Character Set" property (Project Properties / Advanced / Character Set) is set to.

In case of "Use Multi-Byte Character Set":

string sound = to_string(i) + ".wav";
PlaySound(sound.c_str(), NULL, SND_FILENAME | SND_ASYNC);

In case of "Use Unicode Character Set":

wstring sound = to_wstring(i) + L".wav";
PlaySound(sound.c_str(), NULL, SND_FILENAME | SND_ASYNC);

Also, don't forget to include the string header file with #include <string>.

Doeus
  • 430
  • 1
  • 3
  • 7
  • If I'm not mistaken, `to_string(i)` will take `i`, convert it to `int`, and spit out a number, rather than the intended letter representing the key. – user4581301 Jul 06 '20 at 19:27
  • You are right, I misinterpreted the question. In this case, there're two more things that have to be addressed. First, there're non-printable characters in that range. Second, `string sound = i + ".wav";` is a pointer arithmetic, so that also have to be handled. – Doeus Jul 06 '20 at 21:02