C++ MessageBox character array - c++

I am having difficulties using MessageBox function with variables
I have
int main(int argc, char* argv[])
{
char* filename = argv[0];
DWORD length = strlen(filename);
MessageBox(0, TEXT("filename text"), TEXT("length text"), 0); // Works
}
But I want to output variables filename and length as:
MessageBox(0, filename, length, 0); -- compiler error
Function MessageBox has syntax:
int WINAPI MessageBox(
_In_opt_ HWND hWnd,
_In_opt_ LPCTSTR lpText,
_In_opt_ LPCTSTR lpCaption,
_In_ UINT uType
);
I tried using
MessageBox(0, (LPCWSTR)filename, (LPCWSTR)length, 0);
but the output is in some kind of hieroglyphs.

The variable length is not a string, and only strings can be used. It doesn't help that you try to cast it to a char* as then the value of length will be taken as a pointer to the string which will cause undefined behavior.
For C++, you can use e.g. std::to_string to convert non-string values to strings, like
MessageBox(0, filename, std::to_string(length).c_str(), 0);
Note that you must use the c_str function to get a char*.
If you don't have std::to_string then you can use e.g. std::istringstream instead:
std::istringstream is;
is << length;
MessageBox(0, filename, is.str().c_str(), 0);
If you want a more old-style C solution, then there's snprintf (or _snprintf in Visual Studio):
char length_string[20];
_snprintf(length_string, sizeof(length_string), "%ld", length);
MessageBox(0, filename, length_string, 0);

With a C++ win32 project in VS2015 a char array displays in a MessageBox with this code. Include header atlstr.h
// open a file in read mode.
ifstream myInfile;
myInfile.open("C:\\Users\\Desktop\\CodeOnDesktop\\myTrialMessageBox.txt");
if (myInfile.fail())
{
MessageBox(NULL,
L"We have an error trying to open the file myTrialMessageBox.txt",
L"Opening a file.",
MB_ICONERROR);
}
char data[200];
// Read the data from the file and display it.
//infile >> data; // Only gets the first word.
myInfile.getline(data, 100);
//To use CString, include the atlstr.h header.
// Cast array called data to a CString to enable use as MessageBox parameter.
CString cdata = (CString)data;
// or CString cdata = CString(_T("A string"));
MessageBox(NULL,
cdata,
L"Opening a file.",
MB_ICONERROR);
// close the opened file.
myInfile.close();

Related

WriteConsole access violation in function call but not from main()

I am trying to use WriteConsole(..) in a function call but I get access violation. When I un-comment the code in main, it prints my text to the screen with no problem in the main function. When I try to print the string in the function call I get access violation even though it does print the text to the console.
void print(char *_charArray);
int _tmain(int argc, _TCHAR* argv[])
{
HWND hConsole;
// HANDLE hFile;
char myText[] = "This is my text";
char *pMyText = myText;
LPDWORD charsWriten;
// hFile = CreateFile("CONOUT$", GENERIC_WRITE, FILE_SHARE_READ, NULL,
// OPEN_EXISTING, 0, NULL);
print(pMyText);
// WriteConsole(hFile, myText, sizeof(myText), charsWriten, NULL);
getch();
return 0;
}
void print(char *text)
{
LPDWORD charsWriten;
HANDLE hFile;
hFile = CreateFile("CONOUT$", GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_WRITE | FILE_SHARE_READ, NULL,
OPEN_EXISTING, 0, NULL);
unsigned int strn = strlen(text) + 1;
if(!WriteConsole(hFile, text, (strlen(text) + 1), charsWriten,NULL))
{
printf("Write Failed\n");
}
}
This declaration is wrong:
LPDWORD charsWriten;
The CreateFile function expects the fourth parameter to be a pointer to a variable it can write into. You don't actually allocate memory, though; you just declare a pointer—an uninitialized one at that. That won't work. You need to do:
DWORD charsWritten;
...
WriteConsole(hFile, text, (strlen(text) + 1), &charsWritten, NULL)
That will fix the access violation problem, but it doesn't explain why you are writing one character past the end of your string. You don't need to add 1 to strlen; the terminating NUL doesn't need to be written.
LPDWORD charsWriten;
LPDWORD is DWORD*. So what you have there is an uninitialized pointer. You then pass this pointer to WriteConsole, which writes to the invalid location pointed to. Instead, declare charsWritten as type DWORD, and pass its address to WriteConsole with &charsWritten.
DWORD charsWritten;
WriteConsole(hFile, text, (strlen(text) + 1), &charsWritten, NULL);
If, as you say, it works as you have it in main. That is simply bad luck. It's undefined behavior, which doesn't always have predictable results.

Windows API: Unicode variable metamorphasis

I created a function that reads from a file, and fills a data structure based on that file. The function works well alone, so I decided to build an GUI around its function. I have a function that calls the Windows GUI and returns a LPOPENFILENAME structure, to which I copy the LPOPENFILENAME.lpstrFile over to a LPCWSTR.
Next, I initialize a wstring to hold the LPCWSTR value. Here's where things get a bit strange.
LPCWSTR File = FileOpenOBJ(hWnd, hInst).lpstrFile;
MessageBox(hWnd, File, L"Warning 1: File/lpstrFile assignment ", MB_ICONEXCLAMATION | MB_OK);
wstring Fileformatting(File);
Which does a runtime display of something like this:
Which is fine, since LPCWSTR File now holds the value from the LPOPENFILENAME structure, but when a wstring is initialized with the value of File, both variables seemingly go out of range or pull from a pointer location that is no longer accurate and their values appear to be something like:
The goal is to hold the file name in a string so that I can (PHP-like) escape the "\" characters to insert into my function. As such:
C:\Users\InfinityMachine\Documents\Test.obj -> C:\\Users\\InfinityMachine\\Documents\\Test.obj
In which I:
while (Fileformatting.find(L"\\") != wstring::npos){
Fileformatting.replace(Fileformatting.find(L"\\"), 2, L"\\\\");
}
How can I get the correct value of LPCWSTR File into wstring Fileformatting?
You have probably initialized lpstrFile to a variable that is local to the FileOpenOBJ function, and when that function returns you get undefined behavior when you try to use it. It appears to work the first time because the stack hasn't been exercised yet, but that changes when you make the call to MessageBox.
Moving the initialization of the wstring would mask the problem but wouldn't fix it, you're still relying on undefined behavior. The fix would be to have the structure contain a pointer that doesn't go out of scope.
In addition to what others have said about dangling pointers and such, for this kind of situation, you are better off simply having FileOpenOBJ() return a wstring instead of a copy of the original OPENFILENAME struct:
wstring FileOpenOBJ(HWND hWnd, HINSTANCE hInst)
{
WCHAR szFileName[MAX_PATH+1] = {0};
OPENFILENAME ofn = {0};
ofn.lStructSize = sizeof(ofn);
ofn.hwndOwner = hWnd;
ofn.hInstance = hInst;
ofn.lpstrFile = szFileName;
ofn.nMaxFile = MAX_PATH;
...
GetOpenFileName(&ofn);
return szFileName;
}
wstring File = FileOpenOBJ(hWnd, hInst);
MessageBoxW(hWnd, File.c_str(), L"Warning 1: File/lpstrFile assignment ", MB_ICONEXCLAMATION | MB_OK);
If you need to return other values from the OPENFILENAME, you should define your own struct to hold what you need, for example:
struct FileInfo
{
wstring FullPath;
wstring FileName;
wstring Ext;
int FilterIndex;
...
};
FileInfo FileOpenOBJ(HWND hWnd, HINSTANCE hInst)
{
WCHAR szFileName[MAX_PATH+1] = {0};
OPENFILENAME ofn = {0};
ofn.lStructSize = sizeof(ofn);
ofn.hwndOwner = hWnd;
ofn.hInstance = hInst;
ofn.lpstrFile = szFileName;
ofn.nMaxFile = MAX_PATH;
...
GetOpenFileName(&ofn);
FileInfo fi;
fi.FullPath = szFileName;
fi.FileName = &szFileName[ofn.nFileOffset];
if (ofn.nFileExtension != 0)
fi.Ext = &szFileName[ofn.nFileExtension];
fi.FilterIndex = ofn.nFilterIndex;
...
return fi;
}
FileInfo fi = FileOpenOBJ(hWnd, hInst);
MessageBoxW(hWnd, fi.FullPath.c_str(), L"Warning 1: File/lpstrFile assignment ", MB_ICONEXCLAMATION | MB_OK);
Don't expose direct access to the OPENFILENAME struct. It should be left as a private implementation detail of FileOpenOBJ()'s internal logic.

LPCTSTR to LPCSTR conversion

I am trying to get information of existing file using GetFileInformationByHandle(). My function that performs the required task receives LPCTSTR Filename as argument. Here is the code:
getfileinfo(LPCTSTR Filename)
{
OFSTRUCT oo;
BY_HANDLE_FILE_INFORMATION lpFileInformation;
HFILE hfile=OpenFile((LPCSTR)Filename,&oo,OF_READ);
int err=GetLastError();
GetFileInfomationByHandle((HANDLE)hfile,&lpFileInformation);
}
Above code works fine if I declare Filename as LPCSTR but as per requirement of my function I receive the filename in LPCTSTR so if I use typecasting then openfile() cannot find the specified file and returns -1.
Can anyone tell me how to get file information if filename is LPCTSTR? Or how to convert LPCTSTR to LPCSTR.
Why is this typecasting not working? I believe this should work.
Just casting the pointer doesn't change the actual data (ie filename) that is being pointed to into eight-bit characters.
Reading the docs at MSDN suggests using CreateFile instead, which handles LPCTSTR filenames.
The solution to your immediate problem is to replace OpenFile() with CreateFile(), just like the OpenFile() documentation says to do:
Note This function has limited capabilities and is not recommended. For new application development, use the CreateFile function.
For example:
getfileinfo(LPCTSTR Filename)
{
HANDLE hFile = CreateFile(FileName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);
if (hFile == INVALID_HANDLE_VALUE)
{
int err = GetLastError();
// handle error as needed ...
}
else
{
BY_HANDLE_FILE_INFORMATION FileInfo = {0};
BOOL ok = GetFileInformationByHandle(hFile, &FileInfo);
int err = GetLastError();
CloseHandle(hFile);
if (!ok)
{
// handle error as needed ...
}
else
{
// use FileInfo as needed...
}
}
}
That being said, a better solution is to not open the file at all. Most of the information that GetFileInformationByHandle() returns can be obtained using FindFirstFile() instead:
getfileinfo(LPCTSTR Filename)
{
WIN32_FIND_DATA FileData = {0};
HANDLE hFile = FindFirstFile(Filename, &FileData);
if (hFile == INVALID_HANDLE_VALUE)
{
int err = GetLastError();
// handle error as needed ...
}
else
{
FindClose(hFile);
// use FileData as needed ...
}
}
Have a look at Project Properties/Configuration Properties/General/Character Set. This is normally set to UNICODE. It can be changed to MBCS.
If it is set to MBCS, then the code does not need to be modified.
If it is set to Unicode, which I suspect it is otherwise you won't be asking this question, use widechartomultibyte to convert it from LPCTSTR (const wchar_t*) to LPSTR (const char*).

Convert int to LPCWSTR by using wsprintf

As the following code:
int a = 16;
wchar_t *buffer = {0};
wsprintf(buffer,L"%d", a);
MessageBox(NULL, buffer, buffer, MB_OK);
I want to covert int to LPCWSTR in order to put MessageBox.
I really newbie in using wsprintf. Any one can help me explain clearly for me using this function??? (Please, I also read MSDN but still dont't clear)
I mean, I want to print "16" in MessageBox
You initialize your buffer to nullptr. Just create an array of wchar_ts that allocates enough space for you and you're off the hook:
int a = 16;
wchar_t buffer[256];
wsprintfW(buffer, L"%d", a);
MessageBoxW(nullptr, buffer, buffer, MB_OK);

EnumResourceNames Function C++

So I try to read resource types and names from given file (in my case, .msstyle on my desktop) using C++
But somehow the resinfo result is sort of weird and not accurate. It doesnt write what actually was found. For example, the msstyle gives a result of: http://pastebin.com/ZhnkPmUe
#include <windows.h>
#include <strsafe.h>
#include <stdio.h>
HANDLE g_hFile;
BOOL EnumTypesFunc(HMODULE hModule, LPTSTR lpType, LONG lParam);
BOOL EnumNamesFunc(HMODULE hModule, LPCTSTR lpType, LPTSTR lpName, LONG lParam);
BOOL EnumLangsFunc(HMODULE hModule, LPCTSTR lpType, LPCTSTR lpName, WORD wLang, LONG lParam);
void main(void)
{
HMODULE hExe;
TCHAR szBuffer[80];
DWORD cbWritten;
size_t cbString;
HRESULT hResult;
// Load the .EXE whose resources you want to list.
hExe = LoadLibrary(TEXT("C:\\Users\\Kala\\Desktop\\776.msstyles"));
g_hFile = CreateFile(TEXT("C:\\Users\\Kala\\Desktop\\resinfo.txt"), GENERIC_READ | GENERIC_WRITE, 0, (LPSECURITY_ATTRIBUTES) NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, (HANDLE) NULL);
// Find all of the loaded file's resources.
hResult = StringCchPrintf(szBuffer, sizeof(szBuffer)/sizeof(TCHAR),TEXT("The file contains the following resources:\r\n\r\n"));
hResult = StringCchLength(szBuffer, sizeof(szBuffer)/sizeof(TCHAR), &cbString);
WriteFile(g_hFile, szBuffer, (DWORD) cbString, &cbWritten, NULL);
//Calls the function to find types
EnumResourceTypes(hExe, (ENUMRESTYPEPROC)EnumTypesFunc, 0);
// Unload the executable file whose resources were
FreeLibrary(hExe);
CloseHandle(g_hFile);
}
// FUNCTION: EnumTypesFunc(HANDLE, LPSTR, LONG)
//
// PURPOSE: Resource type callback
BOOL EnumTypesFunc(HMODULE hModule, LPTSTR lpType, LONG lParam)
{
TCHAR szBuffer[80]; // print buffer for info file
DWORD cbWritten; // number of bytes written to resource info file
size_t cbString;
HRESULT hResult;
// Write the resource type to a resource information file.
// The type may be a string or an unsigned decimal
// integer, so test before printing.
if (!IS_INTRESOURCE(lpType))
{
hResult = StringCchPrintf(szBuffer, sizeof(szBuffer)/sizeof(TCHAR), TEXT("Type: %s\r\n"), lpType);
}
else
{
hResult = StringCchPrintf(szBuffer, sizeof(szBuffer)/sizeof(TCHAR), TEXT("Type: %u\r\n"), (USHORT)lpType);
}
hResult = StringCchLength(szBuffer, sizeof(szBuffer)/sizeof(TCHAR), &cbString);
WriteFile(g_hFile, szBuffer, (DWORD) cbString, &cbWritten, NULL);
// Find the names of all resources of type lpType.
EnumResourceNames(hModule, lpType, (ENUMRESNAMEPROC)EnumNamesFunc, 0);
return TRUE;
}
// FUNCTION: EnumNamesFunc(HANDLE, LPSTR, LPSTR, LONG)
//
// PURPOSE: Resource name callback
BOOL EnumNamesFunc(HMODULE hModule, LPCTSTR lpType, LPTSTR lpName, LONG lParam)
{
TCHAR szBuffer[80]; // print buffer for info file
DWORD cbWritten; // number of bytes written to resource info file
size_t cbString;
HRESULT hResult;
// Write the resource name to a resource information file.
// The name may be a string or an unsigned decimal
// integer, so test before printing.
if (!IS_INTRESOURCE(lpName))
{
hResult = StringCchPrintf(szBuffer, sizeof(szBuffer)/sizeof(TCHAR), TEXT("\tName: %s\r\n"), lpName);
}
else
{
hResult = StringCchPrintf(szBuffer, sizeof(szBuffer)/sizeof(TCHAR), TEXT("\tName: %u\r\n"), (USHORT)lpName);
}
hResult = StringCchLength(szBuffer, sizeof(szBuffer)/sizeof(TCHAR), &cbString);
WriteFile(g_hFile, szBuffer, (DWORD) cbString, &cbWritten, NULL);
return TRUE;
}
I think I must be missing something because I dont seem to get a proper strings I wanted from it, so if anyone could point me to right direction I would be very thankful
Your file is UTF-16 encoded because you are using the Unicode version of the Win32 API. Your text editor is interpreting the file as being 8 bit encoded. So you simply need to get your text editor to interpret the file as UTF-16. Probably the easiest way to do that is to put the UTF-16LE BOM at the beginning of the file.
As an aside I would advise you to stop coding to support MBCS character sets, stop using TCHAR and so on. Just write your program assuming that you will be targeting the Unicode version of the Win32 API. It will make your code much easier to read if you write L"..." rather than TEXT("...") and so on. Of course, if you need to support Windows 9x then forget I said this and carry on writing code that will compile in both MBCS and Unicode modes.