Wrong symbols in the buffer using GetWindowText - c++

There is combo box with two items and button on the main window. Combobox:
HWND hCombo;
hCombo = CreateWindow(L"COMBOBOX", L"combobox",
WS_CHILD | WS_VISIBLE | CBS_SORT | CBS_DROPDOWNLIST,
10, 55, 232, 500, hWnd, 0, hInstance, 0);
const wchar_t *langEnglish = L"English";
const wchar_t *langRussian = L"Russian";
SendMessage(hCombo, CB_ADDSTRING, 0, (LPARAM)langEnglish);
SendMessage(hCombo, CB_ADDSTRING, 0, (LPARAM)langRussian);
SendMessage(hCombo, CB_SETCURSEL, 0, 0);
I am trying to get selected item text in the WndProc by clicking on the button:
case WM_COMMAND:
{
switch(LOWORD(wParam))
{
case IDC_BUTTON_OK:
wchar_t buf[10];
hCombo = GetDlgItem(hWnd, IDC_COMBO);
GetDlgItemText(hCombo, IDC_COMBO, (LPWSTR)buf, 10);
MessageBox(hWnd, (LPCWSTR)buf, NULL, MB_OK);
break;
}
} break;
I am using breakpoint in the MSVS2010 to see buf variable. It contains chinese symbols!!! Message box shows empty message (With the title "Error"). I want to see english text. What is wrong?
This code
nIndex = SendMessage(hCombo, CB_GETCURSEL, 0, 0);
SendMessage(hCombo, CB_GETLBTEXT, nIndex, (LPARAM)buf);
fills buf with the same chinese symbols
SOLUTION:
hCombo = CreateWindow(L"COMBOBOX", L"combobox",
WS_CHILD | WS_VISIBLE | CBS_SORT | CBS_DROPDOWNLIST,
10, 55, 232, 500, hWnd, (HMENU)IDC_COMBO, hInstance, 0);

In order to get currently selected item from CBS_DROPDOWNLIST styled combo box you need CB_GETCURSEL to get selection index and then CB_GETLBTEXT to get the string.

Related

Adding ToolTip to a ComboBoxEx fails

Consider the code below where 2 different kinds of combo boxes are created(WC_COMBOBOX and WC_COMBOBOXEX), and then each is attached a tool tip.
Tool tip for WC_COMBOBOX works as expected, but WC_COMBOBOXEX fails to display the tool tip.
What is the problem?
BOOL TooltipDlg_OnInitDialog(HWND hWndDialog, HWND hWndFocus, LPARAM lParam)
{
// Load and register Tooltip, ComboBox, ComboBoxEx control classes
INITCOMMONCONTROLSEX iccx;
iccx.dwSize = sizeof(INITCOMMONCONTROLSEX);
iccx.dwICC = ICC_WIN95_CLASSES | ICC_USEREX_CLASSES;
if (!InitCommonControlsEx(&iccx))
return FALSE;
// Create combo boxes
const int idc_ComboBox = 1000;
const int idc_ComboBoxEx = 1001;
{
// create WC_COMBOBOX
CreateWindow(WC_COMBOBOX, NULL,
WS_CHILD | WS_VISIBLE | CBS_DROPDOWNLIST,
40, 80,
100, 20,
hWndDialog, (HMENU)idc_ComboBox, g_hInst,
NULL);
// create WC_COMBOBOXEX
CreateWindowEx(0, WC_COMBOBOXEX, NULL,
WS_CHILD | WS_VISIBLE | CBS_DROPDOWNLIST,
40, 110,
100, 20,
hWndDialog, (HMENU)(idc_ComboBoxEx), g_hInst,
NULL);
}
// Create tooltip
g_hwndTooltip = CreateWindowEx(0, TOOLTIPS_CLASS, L"",
TTS_ALWAYSTIP,
0, 0, 0, 0,
hWndDialog, 0, g_hInst, 0);
// attach the tooltip to controls
{
TOOLINFO ti;
ti.cbSize = sizeof(ti);
ti.uFlags = TTF_IDISHWND | TTF_SUBCLASS;
// attach to idc_ComboBox -- works fine
ti.uId = (UINT_PTR)GetDlgItem(hWndDialog, idc_ComboBox);
ti.lpszText = L"This is tooltip for WC_COMBOBOX.";
SendMessage(g_hwndTooltip, TTM_ADDTOOL, 0, (LPARAM)&ti);
// attach to idc_ComboBoxEx -- does NOT work: no tooltip displayed
ti.uId = (UINT_PTR)GetDlgItem(hWndDialog, idc_ComboBoxEx);
ti.lpszText = L"This is tooltip for WC_COMBOBOXEX.";
SendMessage(g_hwndTooltip, TTM_ADDTOOL, 0, (LPARAM)&ti);
}
return TRUE;
}
WC_COMBOBOXEX create 2 windows - parent and child combo box control, which have the same size as parent and all mouse messages go to this child, not for parent. so need subclass child combobox control. we can get it via CBEM_GETCOMBOCONTROL message. so code must look like:
HWND hwndCBex = CreateWindowEx(0, WC_COMBOBOXEX, ...);
ti.uId = (UINT_PTR)SendMessage(hwndCBex, CBEM_GETCOMBOCONTROL, 0, 0);
ti.lpszText = L"This is tooltip for WC_COMBOBOXEX.";
SendMessage(g_hwndTooltip, TTM_ADDTOOL, 0, (LPARAM)&ti);

How do I create two different comboboxes with different strings of items?

I have created a combo box having a list of items. How do I create another one with different strings of items? Can I in anyway change the hWnd because it seems the first already has the hWndCombobxes. Thus, when I apply it to the second, I get an error message, indicating that there is a duplicate value.
Below is the code I have. What function should I call else?
case WM_CREATE: {
HWND hWndComboBox = CreateWindow (TEXT("COMBOBOX"), TEXT (""),
CBS_DROPDOWN| CBS_HASSTRINGS | WS_VSCROLL| WS_VISIBLE | WS_CHILD ,
100, 150, 200, 150,
hwnd ,(HMENU) ID_COMBOBOX 1, NULL, NULL);
// ADD 2 ITEMS
SendMessage (
hWndComboBox,
(UINT) CB_ADDSTRING,
(WPARAM) 0, (LPARAM) TEXT ("Item 1"));
SendMessage (
hWndComboBox ,
(UINT) CB_ADDSTRING,
(WPARAM) 0, (LPARAM) TEXT ("Item 2"));
// SEND THE CB_SETCURSEL MESSAGE TO DISPLAY AN INITIAL ITEM IN SELECTION FIELD
SendMessage (hWndComboBox , LB_SETCURSEL , (WPARAM) 0, (LPARAM) 1);
// put this declaration somewhere up (or better move it to an include file)
#define ID_COMBOBOX_1 1001
#define ID_COMBOBOX_2 1002
// end defines
case WM_CREATE: {
// it is preferably to use SendDlgItemMessage instead of SendMessage
// this make things easier
// you will not need combobox's HWND, just ComboBox ID
TCHAR *Combo_1_Data[]={
TEXT("Item 1"),
TEXT("Item 2")
};
TCHAR *Combo_2_Data[]={
TEXT("Element 1"),
TEXT("Element 2")
};
int i;
// create two different ComboBoxs
CreateWindow (TEXT("COMBOBOX"), TEXT (""),
CBS_DROPDOWN| CBS_HASSTRINGS | WS_VSCROLL| WS_VISIBLE | WS_CHILD ,
100, 150, 200, 150,
hwnd ,(HMENU) ID_COMBOBOX_1, NULL, NULL);
CreateWindow (TEXT("COMBOBOX"), TEXT (""),
CBS_DROPDOWN| CBS_HASSTRINGS | WS_VSCROLL| WS_VISIBLE | WS_CHILD ,
208, 150, 200, 150,
hwnd ,(HMENU) ID_COMBOBOX_2, NULL, NULL);
// Fill first Combo with its Data
for( i = 0 ; i < (sizeof(Combo_1_Data) / sizeof(Combo_1_Data[0]) ) ; i++ ){
SendDlgItemMessage (hwnd,ID_COMBOBOX_1 ,CB_ADDSTRING, 0, (LPARAM) Combo_1_Data[i]);
}
SendDlgItemMessage (hwnd, ID_COMBOBOX_1 , LB_SETCURSEL , (WPARAM) 0, (LPARAM) 1);
// Fill second Combo with its Data
for( i = 0 ; i < (sizeof(Combo_2_Data) / sizeof(Combo_2_Data[0] )) ; i++ ){
SendDlgItemMessage (hwnd,ID_COMBOBOX_2 ,CB_ADDSTRING, 0, (LPARAM) Combo_2_Data[i]);
}
SendDlgItemMessage (hwnd, ID_COMBOBOX_2 , LB_SETCURSEL , (WPARAM) 0, (LPARAM) 1);
Copy and paste the other combobox. Do the same for the 'Send message' function. Then change the hWnd of the second Combobox to hWndListBox. Do the same to 'Send message'.
HWND hWndListBox = CreateWindow (TEXT("COMBOBOX"), TEXT (""),
CBS_DROPDOWN| CBS_HASSTRINGS | WS_VSCROLL| WS_VISIBLE | WS_CHILD ,
100, 70, 200, 90,
hwnd ,(HMENU) NULL, NULL, NULL);
HWND hWndComboBox = CreateWindow (TEXT("COMBOBOX"), TEXT (""),
CBS_DROPDOWN| CBS_HASSTRINGS | WS_VSCROLL| WS_VISIBLE | WS_CHILD ,
100, 150, 200, 100,
hwnd ,(HMENU) NULL, NULL, NULL);
SendMessage (
hWndComboBox ,
(UINT) CB_ADDSTRING,
(WPARAM) 0, (LPARAM) TEXT ("Item 2"));
SendMessage (
hWndListBox ,
(UINT) CB_ADDSTRING,
(WPARAM) 0, (LPARAM) TEXT ("Item 1"));
// SEND THE CB_SETCURSEL MESSAGE TO DISPLAY AN INITIAL ITEM IN SELECTION FIELD
SendMessage (hWndComboBox , CB_SETCURSEL , (WPARAM) 0, (LPARAM) 0);
SendMessage (hWndListBox , CB_SETCURSEL , (WPARAM) 0, (LPARAM) 0);

Use radio buttons for switching different views in the main window

I have an application in Win32/C++ that has three buttons located in the left side of the main window. When clicking on one of them, a group of radiobuttons has to be displayed to allow the user to switch views among different submenus.
The code looks like this:
case WM_CREATE:
{
HWND hWndButton=CreateWindowEx(NULL,
"BUTTON",
"Inserting",
WS_TABSTOP|WS_VISIBLE|
WS_CHILD|BS_DEFPUSHBUTTON,
10,
10,
100,
24,
hWnd,
(HMENU)INSERT_BUTTON,
GetModuleHandle(NULL),
NULL);
HWND hWndButton2=CreateWindowEx(NULL,
"BUTTON",
"Listing",
WS_TABSTOP|WS_VISIBLE|
WS_CHILD|BS_DEFPUSHBUTTON,
10,
60,
100,
24,
hWnd,
(HMENU)LIST_BUTTON,
GetModuleHandle(NULL),
NULL);
HWND hWndButton3=CreateWindowEx(NULL,
"BUTTON",
"Consulting",
WS_TABSTOP|WS_VISIBLE|
WS_CHILD|BS_DEFPUSHBUTTON,
10,
110,
100,
24,
hWnd,
(HMENU)SELECT_BUTTON,
GetModuleHandle(NULL),
NULL);
}
break;
case WM_COMMAND:
switch(LOWORD(wParam))
{
case INSERT_BUTTON:
{
HWND hGrpButtons=CreateWindowEx(WS_EX_WINDOWEDGE,
"BUTTON",
"Select a table:",
WS_VISIBLE | WS_CHILD| BS_GROUPBOX, // Styles
150,30,470,70,
hWnd,
NULL,
GetModuleHandle(NULL), NULL);
HWND hwndCB1 = CreateWindowEx(WS_EX_WINDOWEDGE, "BUTTON", "TSector", WS_VISIBLE | WS_CHILD | BS_AUTORADIOBUTTON | WS_GROUP,
160, 60, 80, 20, hWnd,(HMENU)CB1, GetModuleHandle(NULL), NULL);
HWND hwndCB2 = CreateWindowEx(WS_EX_WINDOWEDGE, "BUTTON", "TSeccio", WS_VISIBLE | WS_CHILD | BS_AUTORADIOBUTTON ,
250, 60, 80, 20, hWnd,(HMENU)CB2, GetModuleHandle(NULL), NULL);
HWND hwndCB3 = CreateWindowEx(WS_EX_WINDOWEDGE, "BUTTON", "TActivitat", WS_VISIBLE | WS_CHILD | BS_AUTORADIOBUTTON,
340, 60, 80, 20, hWnd,(HMENU)CB3, GetModuleHandle(NULL), NULL);
HWND hwndCB4 = CreateWindowEx(WS_EX_WINDOWEDGE, "BUTTON", "TClasse", WS_VISIBLE | WS_CHILD | BS_AUTORADIOBUTTON,
430, 60, 80, 20, hWnd,(HMENU)CB4, GetModuleHandle(NULL), NULL);
HWND hwndCB5 = CreateWindowEx(WS_EX_WINDOWEDGE, "BUTTON", "TQuantitat", WS_VISIBLE | WS_CHILD | BS_AUTORADIOBUTTON,
520, 60, 85, 20, hWnd,(HMENU)CB5, GetModuleHandle(NULL), NULL);
switch(HIWORD(wParam))
{
case CB1:
//Do something
break;
}
}
break;
}
break;
Maybe the switch after creating the radiobuttons is not well implemented but anyway, when compiling, any of the menus that I want to display when clicking on each radiobuttons are not recognised: the compile error I'm retrieving says that I need to declare each menu.
It sounds weird to me because it works in other cases.
Any help would be much appreciated.
CB1 is the identifier of your control, if it is undeclared then just declare using the #define, like this:
#define CB1 1000
the identifier cannot be repeated with id of others controls.
a good way to create menus is to create all the submenus hidden, and when someone click in an option, you just show the submenu using the ShowWindow function.
to create a hidden submenu, just remove the WS_VISIBLE in the CreateWindowEx.
see this example:
// Opts
#define Fruits 1
#define Colors 2
// Fruits
#define Apple 5
#define Pineapple 6
// Colors
#define Red 10
#define Blue 11
void HideAll(HWND hwnd)
{
// Fruits
ShowWindow(GetDlgItem(hwnd, Apple), SW_HIDE);
ShowWindow(GetDlgItem(hwnd, Pineapple), SW_HIDE);
// Colors
ShowWindow(GetDlgItem(hwnd, Red), SW_HIDE);
ShowWindow(GetDlgItem(hwnd, Blue), SW_HIDE);
}
LRESULT CALLBACK WindowProcedure (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message) /* handle the messages */
{
case WM_CREATE:
// Menus - All created visible
CreateWindowEx(WS_EX_WINDOWEDGE, "BUTTON", "Fruits", WS_VISIBLE | WS_CHILD,
10, 10, 80, 20, hwnd,(HMENU)Fruits, GetModuleHandle(NULL), NULL);
CreateWindowEx(WS_EX_WINDOWEDGE, "BUTTON", "Colors", WS_VISIBLE | WS_CHILD,
10, 40, 80, 20, hwnd,(HMENU)Colors, GetModuleHandle(NULL), NULL);
// Fruits - All created Invisible
CreateWindowEx(WS_EX_WINDOWEDGE, "BUTTON", "Apple", WS_CHILD,
100, 10, 80, 20, hwnd,(HMENU)Apple, GetModuleHandle(NULL), NULL);
CreateWindowEx(WS_EX_WINDOWEDGE, "BUTTON", "Pineapple", WS_CHILD,
100, 40, 80, 20, hwnd,(HMENU)Pineapple, GetModuleHandle(NULL), NULL);
// Colors - All created Invisible
CreateWindowEx(WS_EX_WINDOWEDGE, "BUTTON", "Red", WS_CHILD,
100, 10, 80, 20, hwnd,(HMENU)Red, GetModuleHandle(NULL), NULL);
CreateWindowEx(WS_EX_WINDOWEDGE, "BUTTON", "Blue", WS_CHILD,
100, 40, 80, 20, hwnd,(HMENU)Blue, GetModuleHandle(NULL), NULL);
break;
case WM_COMMAND:
switch(LOWORD(wParam))
{
case Fruits:
// Hide old
HideAll(hwnd);
// Show new
ShowWindow(GetDlgItem(hwnd, Apple), SW_SHOW);
ShowWindow(GetDlgItem(hwnd, Pineapple), SW_SHOW);
break;
case Colors:
// Hide old
HideAll(hwnd);
// Show new
ShowWindow(GetDlgItem(hwnd, Red), SW_SHOW);
ShowWindow(GetDlgItem(hwnd, Blue), SW_SHOW);
break;
}
break;
case WM_DESTROY:
PostQuitMessage (0); /* send a WM_QUIT to the message queue */
break;
default: /* for messages that we don't deal with */
return DefWindowProc (hwnd, message, wParam, lParam);
}
return 0;
}
This is the result of the program:
and when someone click in fruits, it show the fruits suboptions:
and when someone click in colors, the ShowWindow hide the old suboptions and show new suboptions:

Up-Down control doesn't show its position in its buddy window

I created an up-down control by the following code.
HWND hEdit, hUpDown;
hEdit = CreateWindowExW(WS_EX_CLIENTEDGE,
L"EDIT",
Content.c_str(),
ES_LEFT | WS_VISIBLE | WS_CHILD,
600,
260,
100,
25,
hWndParent,
NULL,
hInstance,
NULL);
INITCOMMONCONTROLSEX iccx;
iccx.dwSize = sizeof(INITCOMMONCONTROLSEX);
iccx.dwICC = ICC_UPDOWN_CLASS;
InitCommonControlsEx(&iccx);
hUpDown = CreateWindowExW( 0,
UPDOWN_CLASSW,
L"",
UDS_ARROWKEYS | UDS_ALIGNRIGHT | WS_VISIBLE | WS_CHILD,
0,
0,
0,
0,
hWndParent,
NULL,
hInstance,
NULL);
SendMessageW(hUpDown, UDM_SETBUDDY, (WPARAM) hEdit, (LPARAM) NULL);
SendMessageW(hUpDown, UDM_SETRANGE32, (WPARAM) 0, (LPARAM) 100);
Sleep(5000);
SendMessageW(hUpDown, UDM_SETPOS32, (WPARAM) NULL, (LPARAM) 20);
Sleep(5000);
SendMessageW(hUpDown, UDM_SETPOS32, (WPARAM) NULL, (LPARAM) 60);
I checked the return values of the SendMessageW() functions. They terminate successfully by returning the previous position value as documented.
The created up-down control looks normal:
The problem is, sending the UDM_SETPOS32 message, clicking the up and down arrows and pressing the up and down keys on the keyboard have no effect. I can't change the contents of the edit control (the buddy window of the up-down control) without directly typing something into it. It just stays empty.
I am able to type anything in it manually by using keyboard:
How do I change the position/value of this up-down control by pressing keyboard arrow keys, by clicking the arrows in the GUI and by sending UDM_SETPOS32 in the code? What am I missing in my code?
Use the style UDS_SETBUDDYINT to the up-down control while creating it.
From MSDN documentation:
UDS_SETBUDDYINT
Causes the up-down control to set the text of the buddy window (using the WM_SETTEXT message) when the position changes. The text consists of the position formatted as a decimal or hexadecimal string.
Change the creation code of the up-down control like this by adding the UDS_SETBUDDYINT style:
hUpDown = CreateWindowExW( 0,
UPDOWN_CLASSW,
L"",
UDS_SETBUDDYINT | UDS_ARROWKEYS | UDS_ALIGNRIGHT | WS_VISIBLE | WS_CHILD,
0,
0,
0,
0,
hWndParent,
NULL,
hInstance,
NULL);

Appending text to an edit control running out of room?

So here is my problem, it works fine until it reaches a certain amount of data. I can't show a whole html file for example that is about 1MB in the window it gets cut off.
Window:
case WM_CREATE:
hEdit = CreateWindowEx(WS_EX_CLIENTEDGE, "EDIT", "",
WS_CHILD | WS_VISIBLE | WS_VSCROLL | ES_READONLY | WS_HSCROLL | ES_MULTILINE | ES_AUTOVSCROLL | ES_AUTOHSCROLL,
0, 0, 100, 100, hWnd, (HMENU)IDC_MAIN_EDIT, GetModuleHandle(NULL), NULL);
if(hEdit == NULL)
MessageBox(hWnd, "Could not create edit box.", "Error", MB_OK | MB_ICONERROR);
hfDefault = (HFONT)GetStockObject(DEFAULT_GUI_FONT);
SendMessage(hEdit, WM_SETFONT, (WPARAM)hfDefault, MAKELPARAM(FALSE, 0));
LogText(hEdit,logstring);
break;
Function:
void LogText(HWND hEdit, const char * logstring)
{
const char * logstring2="\r\n";
int iLength = GetWindowTextLength(hEdit);
SendMessage(hEdit, EM_SETSEL, iLength, iLength);
SendMessage(hEdit, EM_REPLACESEL, 0, (LPARAM) logstring);
SendMessage(hEdit, WM_VSCROLL, SB_BOTTOM, (LPARAM)NULL);
int iLength2 = GetWindowTextLength(hEdit);
SendMessage(hEdit, EM_SETSEL, iLength2, iLength2);
SendMessage(hEdit, EM_REPLACESEL, 0, (LPARAM) logstring2);
SendMessage(hEdit, WM_VSCROLL, SB_BOTTOM, (LPARAM)NULL);
}
Usage:
logstring="Test";
LogText(hEdit, logstring);
Like I said, it works perfect, except it stops working after its spit out an unknown amount of data which I've noticed is a very consistent number.
You can change the text limit of an edit box with the EM_SETLIMITTEXT message. Just define the upper limit before you attempt to assign text to the edit box.