How to use mciSendString("play path",0,0,0) with exe path? - c++

I'm using mciSendString("play path repeat",0,0,0) to play music in my project
and I'm using it specially for playing multiple sounds in the same time.
The problem is that I want to put the sounds in the executable path
so I used a function to get the exe path
string ExePath() {
char buffer[MAX_PATH];
GetModuleFileName( NULL, buffer, MAX_PATH );
string::size_type pos = string( buffer ).find_last_of( "\\/" );
return string( buffer ).substr( 0, pos);
}
but mciSendString() takes LPCSTR so I tried the following
string music_cmd="play "+ExePath()+"\\war1.mp3 repeat";
mciSendString(music_cmd.c_str(),0,0,0);
The program runs without Errors but it doesn't play the sound.
How can I fix this problem ?

the path should have no spaces, if you use a path like as
follows: C:\music\music 2.mp3 it will not work.
to make it work delete the space or create a new path without spaces like as follows: C:\music\music2.mp3
Other Observations: the path should have less than 255 characters, relative path will not work (it works when you compile, but when you run the program on another computer, it will not work), cannot have spaces, otherwise it will fail.
there is a workaround you can do which is simple, you will be able to play with dots and spaces on the path
mine is as follows:
path = Application.StartuPath & `\whateverMusic.mp3`
path = Chr(34) & path & Chr(34)
mciSendString("Open " & path & " alias " & oName, Nothing, 0, 0)
mciSendString("Play " & oName, Nothing, 0, 0)
Public Property Name As String
Set(value as String)
oName = value
End Set
Get
Return oName
End Get
End Property
From Here: https://www.youtube.com/watch?v=UWLTegpOuB0

Related

How to use MoveFile function of windows.h The function is prepending the path in filename

path[ ]="folder" ;
strcat(path,fname) ;
MoveFile(fname,path) ;
how to use MoveFile function of windows.h The function is prepending the path in filename
The way you are initializing path, it only has room to hold "folder", you can't append anything more to it without overflowing memory. You need to allocate more space for it, eg:
char path[MAX_PATH] = {};
strcpy(path, "folder");
strcat(path, "\\");
strcat(path, fname);
However, using the Win32 API PathCombine() (or related) function (or a 3rd party solution like boost::filesystem) would be safer:
char path[MAX_PATH] = {};
PathCombine(path, "folder", fname);
Now, with that said, you are passing fname as the first argument to MoveFile(). Assuming fname contains just a filename and no path, MoveFile() will look for the file in a path that is relative to the calling process's current working directory, which is a dynamic value that can (and usually does) change during the process's lifetime. NEVER rely on relative paths, ALWAYS use absolute paths instead.
char src[MAX_PATH] = {};
strcpy(src, "source folder");
strcat(src, "\\");
strcat(src, fname);
// or: PathCombine(src, "source folder", fname);
char dst[MAX_PATH] = {};
strcpy(dst, "destination folder");
strcat(dst, "\\");
strcat(dst, fname);
// or: PathCombine(dst, "destination folder", fname);
MoveFile(src, dst);
Thanks for reply .
I figured out what was the problem .
Actually was looping and concating the path so in each iteration the new file name was appended into path therefore the filename get changed .
But i solved it by assigning '\0' null character at the position from where i want to concat in each iteration .

Getting Path of the executable in current folder C++

I am trying get path of the exe file at the same folder where this program will been. but i couldnt figure out how to do, i did something like this but it only gets the current programs path, and i dont know how to replace filenames between my program and the program i want to get path.
so simply can you help me about get the path of an exe (i know the name of that exe ) at the same folder where this program will been...
char fullp[MAX_PATH];
char selfp[MAX_PATH] = "..//myprogram.exe";
char otherprogram[MAX_PATH] = "//test.exe";
DWORD szPath;
szPath = GetModuleFileName(NULL, selfp, sizeof(selfp));
The Win32 API has a whole bunch of Path Handling functions available.
For instance, once you have obtained the calling process's full path from GetModuleFileName(), you can use PathRemoveFileSpec() to remove the filename leaving just the folder path:
char selfdir[MAX_PATH] = {0};
GetModuleFileNameA(NULL, selfdir, MAX_PATH);
PathRemoveFileSpecA(selfdir);
And then use either PathAppend() or PathCombine() to append a different filename to that path:
char otherprogram[MAX_PATH] = {0};
lstrcpyA(otherprogram, selfdir);
PathAppendA(otherprogram, "test.exe");
char otherprogram[MAX_PATH] = {0};
PathCombineA(otherprogram, selfdir, "test.exe");
OP is most of the way there. Here is an example of how to get the rest of the way.
To simplify the solution, I'm leaving char arrays as far behind as possible and using std::string.
#include <iostream>
#include <string>
#include <windows.h>
int main()
{
char selfp[MAX_PATH];
std::string otherprogram = "Failed to get path";
DWORD szPath;
szPath = GetModuleFileName(NULL, selfp, MAX_PATH);
if (szPath != 0) // successfully got path of current program
{
// helper string to make life much, much easier
std::string helper = selfp;
//find last backslash in current program path
size_t pos = helper.find_last_of( "\\" );
if (pos != std::string::npos) // found last backslash
{
// remove everything after last backslash. This should remove
// the current program's name.
otherprogram = helper.substr( 0, pos+1);
// append new program name
otherprogram += "test.exe";
}
}
std::cout << otherprogram << std::endl;
}

Way to move a file to another directory without specifying filename in destination directory?

I need a way to move a file to another directory without having to specify the file name in the destination directory.
TCHAR szFileName[MAX_PATH];
GetModuleFileName(NULL, szFileName, MAX_PATH);
wchar_t* Favfolder = 0;
SHGetKnownFolderPath(FOLDERID_Favorites, 0, NULL, &Favfolder);
wstringstream ss(szFileName);
wstringstream ff(Favfolder);
rename(ss.str(), ff.str()); //Won't work
If I use rename, ff.str()doesn't include the file name, so it won't work.
The proper way to do it would be to write:
rename(C:\\Users\\blah\\blah\\filename.exe, C:\\Users\\blah\\newdir\\filename.exe);
What I'm doing is:
rename(C:\\Users\\blah\\blah\\filename.exe, C:\\Users\\blah\\newdir);
But I can't figure out a way to include the filename.exe in the second example.
I assume that you are using wstring, not a wstringstream.
Use find_last_of(link) to find the position of last \ in the ss.
Get the filename by substr(link).
Paste the filename at the end of ff.
EDIT:
Function which do all the work:
int move(const string &oldPath, const string &newDir)
{
const size_t pos = oldPath.find_last_of('\\');
const string newPath = newDir + '\\' + (pos == string::npos ? oldPath : oldPath.substr(pos));
return rename(oldPath.c_str(), newPath.c_str());
}
Unfortunately, rename doesn't support wchar_t so I did have to use a string, not a wstring

How to get list of selected files when using GetOpenFileName() with multiselect flag?

I have tried googling, but people seem to have the same problem: we can't get a list of the selected files.
This is a simple piece of working code that is similar to what I use:
OPENFILENAME ofn = { sizeof ofn };
wchar_t file[1024];
file[0] = '\0';
ofn.lpstrFile = file;
ofn.nMaxFile = 1024;
ofn.Flags = OFN_ALLOWMULTISELECT | OFN_EXPLORER;
GetOpenFileName(&ofn);
How do I actually get the filenames I selected? Currently I can only get it to work without OFN_ALLOWMULTISELECT flag, so it returns the one selected filename into ofn.lpstrFile. I tried to print out all the string variables inside that struct, but found nothing. It only shows the main folder of the selected files.
It looks like the ofn.lpstrFile contains all the filenames, separated with a NULL and ending with another NULL (effectively ending with an empty string).
If the OFN_ALLOWMULTISELECT flag is set and the user selects multiple files, the buffer contains the current directory followed by the file names of the selected files. For Explorer-style dialog boxes, the directory and file name strings are NULL separated, with an extra NULL character after the last file name. For old-style dialog boxes, the strings are space separated and the function uses short file names for file names with spaces. You can use the FindFirstFile function to convert between long and short file names. If the user selects only one file, the lpstrFile string does not have a separator between the path and file name.
From MSDN.
A possible implementation to parse the contents could be;
wchar_t* str = ofn.lpstrFile;
std::wstring directory = str;
str += ( directory.length() + 1 );
while ( *str ) {
std::wstring filename = str;
str += ( filename.length() + 1 );
// use the filename, e.g. add it to a vector
}
Checking nFileExtension may NOT be reliable because it can also be 0 if the user entered no file extension (but just the dot, like "file.").
I think to distinguish between single and multi file selection one has to check if there is a null character (terminator) at position nFileOffset - 1.
Try this:
wchar_t file[1025] = {0}; // room for an extra null terminator, just in case
...
ofn.nMaxFile = 1024;
...
wchar_t* ptr = ofn.lpstrFile;
ptr[ofn.nFileOffset-1] = 0;
std::wcout << L"Directory: " << ptr << std::endl;
ptr += ofn.nFileOffset;
while (*ptr)
{
std::wcout << L"File: " << ptr << std::endl;
ptr += (lstrlenW(ptr)+1);
}
If you select a single file when using OFN_ALLOWMULTISELECT, the nFileExtension field contains the offset to the extension. If you select multiple files, the nFileExtension field contains 0.
This way you can determine if a single file was selected, and just read/copy the buffer pointed to by the lpstrFile field (which will be a single null terminated string containing the full path and filename including extension)
or if multiple files where selected, then you parse the buffer pointed to by the lpstrFile field, using nFileOffset to read/copy the folder first (using lstrcpyn for example and specifying length to read as the nFileOffset value) and then read/copy from nFileOffset to next null which is file1 string, add the file string length +1 to get next position to read/copy next file string etc till you reach a file string that starts with null - which is the double null for end of all files (as the last string before this is null terminated)
Here is a more complete version of the answers by Niall and Remy.
vector<string> &filePaths;
if ( GetOpenFileName( &ofn ) == TRUE )
{
wchar_t *p = ofn.lpstrFile;
wstring path = p;
p += path.size() + 1;
if ( *p == 0 )
{
// there is only one string, being the full path to the file
filePaths.push_back( ConvertWideCharToUtf8( path.c_str() ) );
}
else
{
// multiple files follow the directory
for ( ; *p != 0 ; )
{
wstring fileName = p;
filePaths.push_back( ConvertWideCharToUtf8( ( path + L"\\" + fileName ).c_str() ) );
p += fileName.size() + 1;
}
}
}
Where we also have the function:
string ConvertWideCharToUtf8( const wchar_t *wideText )
{
int len = WideCharToMultiByte( CP_UTF8, 0, wideText, -1, NULL, 0, NULL, NULL );
char *buffer = (char *)malloc( len );
WideCharToMultiByte( CP_UTF8, 0, wideText, -1, buffer, len, NULL, NULL );
string s = buffer;
free( buffer );
return s;
}

C++: Trying to create a Run key, All i get is Chinese characters in registry.

Please save me! I am new to this, trying to figure this out. I would like to have my program add a run key to run itself on startup . Here is "my" code:
HKEY hKey = 0;
RegOpenKeyEx( HKEY_LOCAL_MACHINE,
L"Software\\Microsoft\\Windows\\CurrentVersion\\Run",
0,
KEY_ALL_ACCESS,
&hKey );
const unsigned char Path[ MAX_PATH ] = "C:\\test.exe";
RegSetValueEx( hKey, L"Testing", 0, 1, Path, strlen("C:\\test.exe") );
RegCloseKey(hKey);
This "works" except they key added reads "㩃瑜獥⹴硥" under data . Took me a while to figure out that the key is going to WoW6432Node too, thought it complied but wasn't working for the first 5 hours, much head to wall action there...
I am sure this has something to do with the way my string is formatted, ANSII vs ASCII vs the other 10 types of strings C++ doesn't seem to be able to convert between... I've tried using (BYTE*)"C:\virus.exe" and anything else i could think of... If i set the length to 1, the first character shows fine. But if its any other length, Chinese starts to show again.
Please help! I am about ready to start choking kittens here!
The problem is this:
const unsigned char Path[ MAX_PATH ] = "C:\\test.exe";
You have defined an ANSI string and then attempted to use the Unicode (UTF-16) version of RegSetValueEx:
RegSetValueEx( hKey, L"Testing", 0, 1, Path, strlen("C:\\test.exe") );
Under the hood, RegSetValueEx is a macro that aliases to RegSetValueExW because you defined the macro UNICODE.
The correct solution is to use a Unicode string literal:
const wchar_t Path[] = L"C:\\test.exe";
RegSetValueEx( hKey, L"Testing", 0, 1, (const BYTE *) Path, sizeof(Path) );
Here I used sizeof because the string is an array of characters whose size is known at compile time. For dynamic strings, use (wcslen(Path) + 1) * sizeof(*Path) instead.
Note: There is no need to specify the length of a constant literal in the declaration because the compiler can automatically deduce that in this specific scenario. It's also bad idea to duplicate the string literal inside your strlen/wcslen because if it goes out of sync your code could be broken and trigger undefined behavior.