win32 WM_SETTEXT not working - c++

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);

Related

Getting the wrong string from a ComboBox after executing the Sendmessage function

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());

Populate a Virtual ListView with std::vector<std::string>

I have a vector of thousands of strings:
std::vector<std::wstring> a;
filled with some algorithms.
Following the method described here, here is how I create a ListView as a "virtual list":
hList = CreateWindowEx(0, WC_LISTVIEW, L"", WS_CHILD | WS_VISIBLE | LVS_REPORT | LVS_OWNERDATA, 0, 0, 800, 400, hWnd, (HMENU)ID_LISTVIEW, hInst, NULL);
LV_COLUMN lvcol;
...
ListView_InsertColumn(hList, 0, &lvcol);
ListView_SetItemCountEx(hList, 100000, LVSICF_NOSCROLL);
...
// in the message loop
case WM_NOTIFY:
pdi = (NMLVDISPINFO*) lParam;
pi = pdi->item;
switch (pdi->hdr.code)
{
case LVN_GETDISPINFO:
{
pi.mask = LVIF_TEXT;
pi.pszText = a[pi.iItem]; // the nth item should be the nth string in the vector
}
}
I tried a lot of variations on:
pi.pszText = a[pi.iItem];
but they all failed with such kind of errors:
Error C2440: '=' : cannot convert from 'std::basic_string,std::allocator>' to 'LPWSTR'
What could help to do this?
Note: in fact I would like to display on row n of the ListView : the nth string of vector a concatenated with the number n, like this Blabla217 on the row 217.
Note2: even after Igor's suggestion (i.e. a cast pi.pszText = LPWSTR(a[pi.iItem].c_str());), the ListView is still empty, instead of displaying elements.
I'm not exact sure about the problem you're facing, but one thing for sure, you're passing multi-byte string (std::string, using char) while it is asking for wide-char string (std::wstring, using WCHAR).
Here is a handy code that converts std::string to std::wstring.
inline std::wstring WideFromMulti(
std::string const & multi,
UINT codepage)
{
int cchWide = MultiByteToWideChar(codepage, 0, multi.c_str(), -1, nullptr, 0);
LPWSTR szWide = new wchar_t[cchWide];
MultiByteToWideChar(codepage, 0, multi.c_str(), -1, szWide, cchWide);
std::wstring wide(szWide);
delete[] szWide;
return wide;
}
inline std::wstring WideFromUtf8(
std::string const & utf8)
{
return WideFromMulti(utf8, CP_UTF8);
}
Then you can get LPCWSTR by c_str().
std::string test_str;
std::wstring test_wstr = WideFromUtf8(test_str);
LPCWSTR wszTest = test_wstr.c_str();
What about LPWSTR? Well if you're sure that the string won't get modified, you can cast it by const_cast<LPWSTR>(wszTest). If you're strongly against const_cast, you may create a temporary copy of LPWSTR like this:
std::wstring test(L"Hello world");
LPCWSTR szTestConst = test.c_str();
int cchMax = ::lstrlenW(szTestConst) + 1;
std::vector<WCHAR> v(cchMax);
::lstrcpynW(&v[0], szTestConst, cchMax);
LPWSTR szTest = &v[0];
I don't really know why, but this solved it:
case WM_NOTIFY:
pdi = (NMLVDISPINFO*) lParam;
//pi = pdi->item;
switch (pdi->hdr.code)
{
case LVN_GETDISPINFO:
{
//pi.mask = LVIF_TEXT;
pdi->item.mask = LVIF_TEXT;;
//pi.pszText = a[pi.iItem];
pdi->item.pszText = a[pi.iItem];
}
}

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.

Getting weird characters from conversion of char to TCHAR

I'm getting really weird characters from the conversion. Any idea why? I get the "data" from an external device and i need to display it to win32 GUI. It had no problem when i
printf("%s\n",data);
in the console mode but having trouble when i migrate it to win32 which requires me to convert to TCHAR to display.
CHAR data[256];
TCHAR data1[256];
MultiByteToWideChar(CP_ACP,MB_COMPOSITE,data,-1,data1,0);
CreateWindow(TEXT("STATIC"), data1, WS_VISIBLE | WS_CHILD |
10, 50,300,300,hWnd, (HMENU) none, NULL, NULL);
By the way, using
hDLL=LoadLibrary("MyKad.dll");
in win32 couldn't work so I had to used
hDLL=LoadLibrary(TEXT("MyKad.dll"));
May I know is this right? Thanks
The reason that your code fails is that you pass 0 in the final parameter of MultiByteToWideChar. You can fix your code by passing the length if data1:
MultiByteToWideChar(CP_ACP, MB_COMPOSITE, data, -1, data1, 256);
Note also that you should be checking for errors when calling API functions. Had you done so you would have discovered that MultiByteToWideChar was failing.
I use the following function to convert to UTF-16:
std::wstring MultiByteStringToWideString(const std::string& MultiByte,
const UINT CodePage)
{
std::wstring result;
int cchWideChar = MultiByteToWideChar(CodePage, 0, MultiByte.c_str(), -1,
NULL, 0);
if (cchWideChar > 0)
{
wchar_t* bufferW = new wchar_t[cchWideChar];
if (MultiByteToWideChar(CodePage, 0, MultiByte.c_str(), -1, bufferW,
cchWideChar) != 0)
{
result = std::wstring(bufferW);
}
delete[] bufferW;
}
return result;
}
So you could use this as follows:
std::wstring windowName = MultiByteStringToWideString(data, CP_ACP);
CreateWindow(L"STATIC", windowName.c_str(), ...);

C++ why setWindowText doesn't display any text?

I have code as below, and my question is why in the cell A[0][0] setWindowText put nothing?
if(LOWORD( wParam ) == 104){
int td;
int td_width=80;
int tr = 0;
int tr_height=20;
for (tr=0;tr<2;tr++) {
for (td=0;td<10;td++) {
HWND A[tr][td];
A[tr][td] = CreateWindowEx( 0, "EDIT", NULL, WS_CHILD | WS_VISIBLE | WS_BORDER | ES_MULTILINE | ES_AUTOVSCROLL,
td*td_width, tr*tr_height+50, td_width+1, tr_height+1, hwnd, NULL, hInstance, NULL );
}
SetWindowText(A[0][0], "MK" );
}
}
You're defining A[tr][td] inside the inner most loop. This restricts its scope to just that loop. In other words, on each iteration, you're creating a brand new array and assigning just one of its elements.
It's a little surprising that this even compiles. I guess you have another A array defined somewhere else, and that's the one you're referencing in the SetWindowText call.
As Peter said, you are declaring your array in the wrong spot. But more than that, you are also declaring the array as fixed-length but using run-time values to specify its bounds. That will not work, and should not even compile. A fixed-length array's bounds must be known at compile-time, not at run-time.
Try this instead:
if (LOWORD(wParam) == 104)
{
const int td_width = 80;
const int tr_height = 20;
HWND A[2][10];
for (int tr = 0; tr < 2; ++tr)
{
for (int td = 0; td < 10; ++td)
{
A[tr][td] = CreateWindowEx( 0, TEXT("EDIT"), NULL, WS_CHILD | WS_VISIBLE | WS_BORDER | ES_MULTILINE | ES_AUTOVSCROLL, td*td_width, tr*tr_height+50, td_width+1, tr_height+1, hwnd, NULL, hInstance, NULL );
}
}
SetWindowText(A[0][0], TEXT("MK") );
}