Getting the wrong string from a ComboBox after executing the Sendmessage function - c++

I'm facing an issue with where I am getting the wrong string from a ComboBox after executing the Sendmessage function.
What do you think could be wrong here?
hCombo = CreateWindow(L"COMBOBOX", L"combobox",
WS_CHILD | WS_VISIBLE | CBS_SORT | CBS_DROPDOWNLIST | CBS_AUTOHSCROLL | WS_HSCROLL | WS_VSCROLL,
10, 50, 250, 500, hWnd, (HMENU)0, hInstance, NULL);
std::string text = "1 2 3 4 5 6";
SendMessage(hCombo, CB_ADDSTRING, NULL, (LPARAM)text.c_str());

The problem here is that the LPARAM cast hides your error. You are compiling with UNICODE enabled, so by default your strings should be wide (wchar_t) strings, which for string literals means prefixing them with L, ie L"1 2 3 4 5 6".
Your compiler will now tell you that the type of the text variable is wrong. That needs to be changed to std::wstring for wide strings.

c_str() returns an ANSI string. To make it work, you need do like this:
SendMessageA(hCombo, CB_ADDSTRING, NULL, (LPARAM)text.c_str());

Related

Is it possible to change font for an edit control without affecting the other lines?

Hello I want to know if it is possible to change the font of an edit control for some lines only without affecting the remaining:
In my Edit control I have a text but I want some headlines and titles in bigger font and bold while the other lines are with smaller font.
I tried SendMessage(hEdit, WM_SETFONT, (WPARAM)hfont, MAKELPARAM(0, true));
But it sets the whole text in the passed in font.
I thought some messing up with SelectObject(hDcEdit, hFont); But I don't know if it is correct and how.
A standard Edit Control (think, Notepad) does not support what you are looking for. It only supports one Font for the entire text.
What you are looking for is a RichEdit Control instead (think, Wordpad), and in particular its EM_SETCHARFORMAT message, which can be used to apply different formatting (including fonts, colors, etc) to different sections of text.
This is not working with the default Editcontrol, but you can use a Richeditcontrol
#include <Windows.h>
#include <CommCtrl.h>
HINSTANCE relib = LoadLibrary("riched32.dll");
if (relib == NULL) {
MessageBox(NULL, "couldn't load richedit32.dll", "", MB_ICONEXCLAMATION);
hEdit = CreateWindow(RICHEDIT_CLASS, "", WS_VISIBLE | WS_CHILD | ES_MULTILINE |
ES_AUTOHSCROLL | ES_AUTOVSCROLL | WS_VSCROLL | WS_HSCROLL, 0, 0, 200, 200, hWnd, NULL,
NULL, NULL);
Now to set the font to your Richeditcontrol use:
CHARFORMAT2 cf;
memset(&cf, 0, sizeof cf);
cf.cbSize = sizeof cf;
cf.dwMask = CFM_FACE;
wsprintf(cf.szFaceName, "Arial"); //Here you can set the fontname you wont (C:/Windows/Fonts)
SendMessage(hEdit, EM_SETCHARFORMAT, SCF_SELECTION, (LPARAM)&cf);

Getline with WinApi - Using WOFSTREAM / WIFSTREAM - C++ / WIN32

I am using Windows 10 (Visual Studio 2015).
Alright I just want to start off by saying is that I am using an edit box for the user to write a directory,appname,comboboxname then having wofstream output the directory,appname,comboboxname into a .txt file.
My problem is that some directories have spaces so when wifstream reads those spaces then cuts off the directory to early and stores the cut off version into one of the wchar_t variables.
What I need for the program to do (I am not sure if its possible) is output line by line.
Example:
C:\Program Files (x86)\Minecraft
MinecraftLauncher
Minecraft
Then use getline to read the whole line including the spaces, store that line into a variable and then get the next line. (But it also can't grab any extra white spaces that aren't in the directory otherwise it won't work) you guys probably know how directories work lol)
So you guys don't have to look that hard, I want this to occur in the case IDB_CLICK_ME.
Here is my code currently, something I am tinkering with before I decide to add it to my main application:
This is where I am trying to read the file (without whitespaces)
case WM_CREATE:
{
wchar_t testData[20] = L"Hai";
CreateWindow(L"button", L"CLICK ME", WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON, 5, 5, 200, 25, hwnd, (HMENU)IDB_CLICK_ME, NULL, NULL);
comboBox = CreateWindow(L"combobox", L" ", WS_VISIBLE | WS_CHILD | CBS_DROPDOWNLIST, 5, 50, 100, 100, hwnd, (HMENU)4, NULL, NULL);
hProgramName = CreateWindow(L"edit", L"Program Name", WS_VISIBLE | WS_CHILD | WS_BORDER | ES_AUTOHSCROLL, 5, 100, 200, 25, hwnd, NULL, NULL, NULL);
hProgramDirectory = CreateWindow(L"edit", L"Program Directory", WS_VISIBLE | WS_CHILD | WS_BORDER | ES_AUTOHSCROLL, 5, 130, 200, 25, hwnd, NULL, NULL, NULL);
hProgramNameComboBox = CreateWindow(L"edit", L"Name listed in ComboBox", WS_VISIBLE | WS_CHILD | WS_BORDER | ES_AUTOHSCROLL, 5, 160, 200, 25, hwnd, NULL, NULL, NULL);
std::wifstream myfile;
myfile.open("LaunchLocations.txt");
myfile >> std::noskipws >> gameLaunchtest.directory;
myfile >> std::noskipws >> gameLaunchtest.AppName;
myfile >> std::noskipws >> gameLaunchtest.ComboBoxName;
This is where I am writing it, so far this works correctly
ComboBox_AddString(comboBox, gameLaunchtest.directory);
break;
case WM_COMMAND:
switch (LOWORD(wparam))
{
case IDB_CLICK_ME:
GetWindowText(hProgramDirectory, gameLaunchtest.directory, MAX_PATH);
GetWindowText(hProgramName, gameLaunchtest.AppName, MAX_PATH);
GetWindowText(hProgramNameComboBox, gameLaunchtest.ComboBoxName, MAX_PATH);
wofstream launchLocations;
launchLocations.open("LaunchLocations.txt");
launchLocations << gameLaunchtest.directory << endl;
launchLocations << gameLaunchtest.AppName << endl;
launchLocations << gameLaunchtest.ComboBoxName << endl;
launchLocations.close();
So the way I fixed my problem (I was told by some very helper member that I must use the wifstream getline instead of the string getline)
std::wifstream myfile;
while (myfile.getline(test[number].directory, 100))
{
myfile.getline(test[number].AppName, 100);
myfile.getline(test[number].ComboBoxName, 100);
test[number].ID;
ComboBox_AddString(comboBox, test[number].ComboBoxName);
number++;
test[number].ID = test[number].ID + 1;

Win32 Edit printing incorrect characters

I am using a Win32 edit to display debugging information, and I have placed the edit, along with the rest of my basic GUI in a class. But when I output anything to the edit it displays '??????????????????????????'. I think the error lies in my MyGUI::append(LPCSTR) method, although it has always worked perfectly in the past. Any comments/ideas/solutions will be appreciated. If I need to post all the code pertaining to my GUI class please let me know so.
My class lies in the namespace Interface, along with the stand-alone WindowProcedure function, which I call when registering the application with the WNDCLASSEX object.
The win32 edit is not created in the WM_CREATE handle within the WindowProcedure(as it probably should be) as I could not place the function inside my GUI class.
Method that creates the edit:
HWND createEdit( HINSTANCE hInst, HWND hwnd, int appBott, int appTop ){
return CreateWindowEx( WS_EX_APPWINDOW,
TEXT("EDIT"), TEXT(""),
WS_BORDER | WS_CHILD | WS_VISIBLE | ES_AUTOVSCROLL | ES_AUTOHSCROLL | ES_READONLY | ES_MULTILINE| WS_VSCROLL | WS_HSCROLL,
10, 10, appBott-25, appTop-50,
hwnd,
(HMENU) 102,
hInst,
NULL );
}
Used in 'guiCreate()' method as:
HWND hEdit = createEdit( hInst, hWin, appWidth, appHeight );
Method that displays text in edit:
void Interface::MyGUI::append( LPCSTR text ){
if( created && !stopAll ){
int TextLen = SendMessage(hEdit, WM_GETTEXTLENGTH, 0, 0);
SendMessageW(hEdit, EM_SETSEL, (WPARAM)TextLen, (LPARAM)TextLen);
SendMessageW(hEdit, EM_REPLACESEL, FALSE, (LPARAM) text);
}
}
Used in main program as:
MyGUI form(); //initialize form
form.append( (LPCSTR)"Example text\n" );
Input text: 'Example text.\n'
Displayed text: '?????????????? l'
You are targeting ANSI it would seem. In that case, don't call SendMessageW, call SendMessageA or even SendMessage and let that be expanded to SendMessageA.
You call SendMessageW but pass ANSI encoded text. When you called SendMessageW you promised to send UTF-16 encoded text.
However, you should stop targeting ANSI I think. Target Unicode instead. Stop using the TEXT() macro and use the L prefix for your string literals. And stop casting string types. That (LPCSTR) cast is asking for trouble. When you cast like that you tell the compiler that you know better than it does. And usually that is not the case.

Getting battery information for Laptop and put it in label in C++

I am doing an App for laptops Called Batterlizer,
It will get all the information about the battery, So everything was going well until I wanted to get the battery percent and other things , so here is my code:
SYSTEM_POWER_STATUS BatteryPower;
if(GetSystemPowerStatus( &BatteryPower ))
{
long unsigned int BatteryFull = BatteryPower.BatteryLifeTime;
const char BatteryFullTime[900] = {BatteryFull};
BatteryLeftText = CreateWindow("static", "Battery Life:",WS_CHILD |
WS_VISIBLE | WS_TABSTOP, 0, 0, 100, 20,hwnd, (HMENU)(501),(HINSTANCE)
GetWindowLong (hwnd, GWL_HINSTANCE), NULL);
UpdatedBatteryText = CreateWindow("static",BatteryFullTime, WS_VISIBLE |
WS_CHILD | WS_TABSTOP, 90, 0, 50, 20, hwnd, (HMENU)(501),(HINSTANCE)
GetWindowLong (hwnd, GWL_HINSTANCE),NULL);
}
the problem is , it says strange letters when it comes to BatteryFullTime,
Any Ideas guys?
Try the following:
char szBatteryLifeBuffer[900] = {0};
sprintf(szBatteryLifeBuffer, "%lu", BatteryFull);
SetWindowText(UpdatedBatteryText, szBatteryLifeBuffer);
// This also should work, too.
// SendMessage(UpdatedBatteryText, WM_SETTEXT, 0, (LPARAM)(LPTSTR)szBatteryLifeBuffer);
Get rid of
// This does not work.
const char BatteryFullTime[900] = {BatteryFull};
You're using C instead of C++, that makes it harder. In C++ :
std::string BatteryFullTime = std::to_string(BatteryFull);
No need to care about length, or remember details of the conversion function. However:
SetWindowText(UpdatedBatteryText, BatteryFullTime.c_str());
The Windows function does need a C string, but it's easy to get a C string from the C++ string.

win32 WM_SETTEXT not working

i made a small textbox like this
EBX = CreateWindow(TEXT("EDIT"), TEXT(""), WS_CHILD | WS_VISIBLE | WS_TABSTOP | ES_NUMBER | WS_BORDER,
client.right - offset[1] - 200, client.top + offset[2] - 27,
45, 25, hwnd, (HMENU)ID_EDIT_SPEED, NULL, NULL);
everything is fine there but when i try to change the text inside like this i got some problems
SendMessage(EBX, WM_SETTEXT, 0, (LPARAM)"12"); // working
int a = 40;
SendMessage(EBX, WM_SETTEXT, 0, (LPARAM)a); // not working
any idea what is wrong ?
40 is not a string, "40" is.
If you want to convert a number to a string you must use a function like sprintf, etc.
E.g.
int a = 40;
char str[20];
StringCchPrintf(str, _countof(str), "%ld", a);
SendMessage(EBX, WM_SETTEXT, 0, (LPARAM)str);
You cannot, blindly typecast int to char*, use sprintf, stringstream or std::to_string to create string that holds literal representation of int value.
Or if you want to otput char with value 40 you need to pass pointer to null terminate array of chars. Like
char str[2];
str[0]=40;
str[1]=0;
convert 40 to c-string and use it in sendmessage function
char buffer [33];
int i =40;
itoa (i,buffer,10);
SendMessage(EBX, WM_SETTEXT, 0, (LPARAM)buffer);