I'm trying to learn how to make a GUI for a C++ using visual studio. but I have encountered some problems while using the GetWindowText() function. It does not change the LPTSTR title to the text in the textbox and I also get an error when debugging saying: “Exception thrown at 0x74F8207D (user32.dll) in Win32Project1.exe: 0xC0000005: Access violation writing location 0x002B8D38.” The code can be seen below what am I doing wrong?
#define ID_BUTTON1 1
#define ID_BUTTON2 2
#define ID_TEXT3 3
static HWND hWndTextbox;
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message)
{
case WM_CREATE:
{
HMENU hMenubar = CreateMenu();
HMENU hFile = CreateMenu();
HMENU hOptions = CreateMenu();
AppendMenu(hMenubar, MF_POPUP, (UINT_PTR)hFile, L"File");
AppendMenu(hMenubar, MF_POPUP, NULL, L"Edit");
AppendMenu(hMenubar, MF_POPUP, (UINT_PTR)hOptions, L"Options");
AppendMenu(hFile, MF_STRING, NULL, L"Exit");
AppendMenu(hOptions, MF_STRING, NULL, L"option 1");
AppendMenu(hOptions, MF_STRING, NULL, L"option 2");
SetMenu(hWnd, hMenubar);
CreateWindow(TEXT("button"), TEXT("Hello"),
WS_VISIBLE | WS_CHILD,
10, 10, 80, 25,
hWnd, (HMENU) ID_BUTTON1, NULL, NULL);
static HWND hWndTextbox = CreateWindow(TEXT("edit"), TEXT("tekst goes here"),
WS_VISIBLE | WS_CHILD|WS_BORDER | ES_AUTOHSCROLL,
90, 120, 300, 20,
hWnd, (HMENU) ID_TEXT3, NULL, NULL);
CreateWindow(TEXT("button"), TEXT("shiny"),
WS_VISIBLE | WS_CHILD,
50, 50, 80, 50,
hWnd, (HMENU) ID_BUTTON2, NULL, NULL);
}
break;
case WM_COMMAND:
{
if (LOWORD(wParam) == ID_BUTTON1) {
MessageBox(hWnd, L"Button has been clicked", L"title for popup", MB_ICONINFORMATION);
}
if (LOWORD(wParam) == ID_BUTTON2) {
// create some default vars
// int length = GetWindowTextLength(hWndTextbox) + 1;
LPTSTR title = L"test" ;
GetWindowText(hWndTextbox, title, GetWindowTextLength(hWndTextbox) + 1);
MessageBox(hWnd, title, L"Message box", MB_OK);
}
break;
int wmId = LOWORD(wParam);
// Parse the menu selections:
switch (wmId)
{
case IDM_ABOUT:
DialogBox(hInst, MAKEINTRESOURCE(IDD_ABOUTBOX), hWnd, About);
break;
case IDM_EXIT:
DestroyWindow(hWnd);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
}
break;
case WM_PAINT:
{
PAINTSTRUCT ps;
HDC hdc = BeginPaint(hWnd, &ps);
// TODO: Add any drawing code that uses hdc here...
EndPaint(hWnd, &ps);
}
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
return 0;
}
the rest of the code was auto generated by visual studio so I have only included the part where I made changes.
The documentation for GetWindowText() states that parameter lpString is supposed to point to a "buffer that will receive the text", which implies a writable buffer.
With the code LPTSTR title = L"test"; you create a pointer to a string literal which usually is located in read-only memory. When GetWindowText() tries to write to that memory, it causes an access violation.
To solve the issue, use a writable buffer like this:
// Allocate buffer including terminating null
std::wstring title( GetWindowTextLength(hWndTextbox) + 1, 0 );
// Address of first character is used to obtain pointer to non-const data
// (as opposed to wstring::c_str()).
int size = GetWindowText( hWndTextbox, &title[0], title.size() );
// Resize buffer to the actual text length
title.resize( size );
// MessageBox only needs pointer to const string, so we can use wstring::c_str() here.
MessageBox(hWnd, title.c_str(), L"Message box", MB_OK);
Related
When I build the program in visual studio It takes a long time to build and does not display properly, during this proccess it loads and unloads lots of what appears to be dll files in the console. If I remove the one line that starts with CreateWindowW(L"EDIT" the program will run perfectly. I have read through the documentation and I cant find what is wrong with it. Any help is appreciated.
Here is full code
#ifndef UNICODE
#define UNICODE
#endif
#include <windows.h>
#include<iostream>
#define file_menu_new 1
#define help_menu 2
#define file_menu_open 3
#define file_menu_exit 4
void AddMenus(HWND hwind);
HMENU hMenu;
void AddControls(HWND hwnd);
LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
int WINAPI WinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE hPrevInstance,_In_ PSTR szCmdLine, _In_ int iCmdShow)
{
// Register the window class.
const wchar_t CLASS_NAME[] = L"Sample Window Class";
WNDCLASS wc = { };
wc.lpfnWndProc = WindowProc;
wc.hInstance = hInstance;
wc.lpszClassName = CLASS_NAME;
//regesters class above with operateing system
RegisterClass(&wc);
// Create the window.
HWND hwnd = CreateWindowEx(
0, // Optional window styles.
CLASS_NAME, // Window class
L"Learn to Program Windows", // Window text
WS_OVERLAPPEDWINDOW | WS_VISIBLE, // Window style
// Size and position
500, 200, 800, 500,//WS_DEFAULT OR SOMETHING LIKE THAT
NULL, // Parent window
NULL, // Menu
hInstance, // Instance handle
NULL // Additional application data
);
if (hwnd == NULL)
{
return 0;
}
ShowWindow(hwnd, iCmdShow);
// Run the message loop.
MSG msg = { };
while (GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return 0;
}
LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
switch (uMsg)
{
case WM_COMMAND:
{
switch (wParam)
{
case file_menu_new:
MessageBeep(MB_OK);//this creates a sound
break;
case file_menu_exit:
DestroyWindow(hwnd);
break;
case file_menu_open:
MessageBeep(MB_ICONINFORMATION);
default:
break;
}
}
case WM_CREATE:
{
AddControls(hwnd);
AddMenus(hwnd);
break;
}
case WM_DESTROY:
{
PostQuitMessage(0);
break;
}
case WM_PAINT:
{
PAINTSTRUCT ps;
HDC hdc = BeginPaint(hwnd, &ps);
FillRect(hdc, &ps.rcPaint, (HBRUSH)(COLOR_WINDOW + 1));
EndPaint(hwnd, &ps);
break;
}
}
return DefWindowProc(hwnd, uMsg, wParam, lParam);
}
void AddMenus(HWND hwind)
{
hMenu = CreateMenu();//main menu bar
HMENU hFileMenu = CreateMenu();//this is a drop down menu for the file part of main menu
//AppendMenu(hMenu, MF_STRING, 1, L"File");//1 is the identity of this main menu
AppendMenu(hMenu, MF_POPUP, (UINT_PTR)hFileMenu, L"File");//this is how you make it pop up another menu
AppendMenu(hFileMenu, MF_STRING, file_menu_new, L"New");//adds stuff to hFileMenu with the id of 1
AppendMenu(hFileMenu, MF_STRING, file_menu_open, L"Open");//adds stuff to hFileMenu with the id of 3
AppendMenu(hFileMenu, IMFT_SEPARATOR, NULL, NULL);//creates a seperator or a line under open
AppendMenu(hFileMenu, MF_STRING, file_menu_exit, L"Exit");
AppendMenu(hMenu, MF_STRING, help_menu, L"Help");//2 is the identity of this main menu
//sets the hMenu to the hwind menu or the main menu
SetMenu(hwind, hMenu);
}
void AddControls(HWND hwnd)
{
CreateWindowW(L"static", L"Enter Text here: ", WS_VISIBLE | WS_CHILD | WS_BORDER | SS_CENTER | WS_EX_TRANSPARENT,
200, 100, 100, 50, hwnd, NULL, NULL, NULL);
CreateWindowW(L"EDIT", L"Enter Text here: ", WS_VISIBLE | WS_CHILD | WS_BORDER | SS_CENTER,
200, 160, 100, 50, hwnd, NULL, NULL, NULL);
}
Add wc.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1); and remove WM_PAINT. If you don't set a class background you need to handle WM_ERASEBKGND or otherwise validate the background color painting.
I give the background main window color by registering the window class with the hbrBackground property like this :
wcex.hbrBackground = (HBRUSH)GetStockObject(DKGRAY_BRUSH);
and then :
RegisterClassExW(&wcex);
The result window is white. I have the darkgray color when I minimize/maximize the window.
How can I obtain the darkgray background immediately ?
Thank you !
EDIT : The callback function :
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
static HWND hgGroupBox1;
static HWND hsFileSize;
static HWND hsFileName;
static HWND hsStatic1;
static HWND hsStatic2;
static HWND hsStatic3;
static HWND hsStatic4;
static HWND hsFileID;
static HWND hlbTagV2Frames;
static HWND hStatus;
static HBRUSH hbrBkgnd;
int hauteur, largeur;
std::wstringstream lbFrames;
switch (message)
{
case WM_CREATE:
hsStatic1 = CreateWindowEx(0, L"STATIC", L"Fichier :", WS_CHILD | WS_VISIBLE, 5, 5, 60, 20, hWnd, (HMENU)ID_STATIC1, (HINSTANCE)GetWindowLongPtr(hWnd, GWLP_HINSTANCE), nullptr);
hsFileName = CreateWindowEx(0, L"STATIC", L"", WS_CHILD | WS_VISIBLE, 65, 5, 800, 20, hWnd, (HMENU)ID_STATICFILENAME, (HINSTANCE)GetWindowLongPtr(hWnd, GWLP_HINSTANCE), nullptr);
hgGroupBox1 = CreateWindowEx(0, L"BUTTON", L"TagV2", WS_CHILD | WS_VISIBLE | BS_GROUPBOX, 5, 30, 420, hauteur - 100, hWnd, (HMENU)ID_GROUPEBOX1, (HINSTANCE)GetWindowLongPtr(hWnd, GWLP_HINSTANCE), nullptr);
hsStatic2 = CreateWindowEx(0, L"STATIC", L"Taille :", WS_CHILD | WS_VISIBLE, 15, 50, 100, 20, hWnd, (HMENU)ID_STATIC2, (HINSTANCE)GetWindowLongPtr(hWnd, GWLP_HINSTANCE), nullptr);
hsFileSize = CreateWindowEx(0, L"STATIC", nullptr, WS_CHILD | WS_VISIBLE | WS_BORDER, 15, 75, 100, 20, hWnd, (HMENU) ID_STATICFILESIZE, (HINSTANCE) GetWindowLongPtr(hWnd, GWLP_HINSTANCE), nullptr);
hsStatic3 = CreateWindowEx(0, L"STATIC", L"Entête :", WS_CHILD | WS_VISIBLE, 15, 100, 100, 20, hWnd, (HMENU)ID_STATIC3, (HINSTANCE)GetWindowLongPtr(hWnd, GWLP_HINSTANCE), nullptr);
hsFileID = CreateWindowEx(0, L"STATIC", nullptr, WS_CHILD | WS_VISIBLE | WS_BORDER, 15, 125, 200, 20, hWnd, (HMENU)ID_STATICENTETEID, (HINSTANCE)GetWindowLongPtr(hWnd, GWLP_HINSTANCE), nullptr);
hsStatic4 = CreateWindowEx(0, L"STATIC", L"Attributs du tagV2 :", WS_CHILD | WS_VISIBLE, 15, 150, 150, 20, hWnd, (HMENU)ID_GROUPEBOX1, (HINSTANCE)GetWindowLongPtr(hWnd, GWLP_HINSTANCE), nullptr);
hlbTagV2Frames = CreateWindow(L"LISTBOX", L"", WS_VISIBLE | WS_CHILD | WS_BORDER | LBS_NOTIFY, 15, 175, 400, 200, hWnd, (HMENU)ID_LISTBOXFRAMES, (HINSTANCE)GetWindowLongPtr(hWnd, GWLP_HINSTANCE), nullptr);
ShowWindow(hsStatic1, SW_SHOW);
ShowWindow(hgGroupBox1, SW_SHOW);
ShowWindow(hsStatic2, SW_SHOW);
ShowWindow(hsFileSize, SW_SHOW);
ShowWindow(hsStatic3, SW_SHOW);
ShowWindow(hsFileID, SW_SHOW);
ShowWindow(hStatus, SW_SHOW);
ShowWindow(hsStatic4, SW_SHOW);
ShowWindow(hlbTagV2Frames, SW_SHOW);
break;
case WM_COMMAND:
{
int wmId = LOWORD(wParam);
// Analyse les sélections de menu :
switch (wmId)
{
case IDM_FICHIER_OUVRIR:
//Here comes the file treatement code.
}
break;
case IDM_ABOUT:
DialogBox(hInst, MAKEINTRESOURCE(IDD_ABOUTBOX), hWnd, About);
break;
case IDM_EXIT:
DestroyWindow(hWnd);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
}
break;
case WM_PAINT:
{
PAINTSTRUCT ps;
HDC hdc = BeginPaint(hWnd, &ps);
// TODO: Ajoutez ici le code de dessin qui utilise hdc...
EndPaint(hWnd, &ps);
}
break;
case WM_CTLCOLORSTATIC:
{
HDC hdcStatic = (HDC)wParam;
SetTextColor(hdcStatic, RGB(0, 0, 0));
SetBkColor(hdcStatic, DKGRAY_BRUSH);
hbrBkgnd = CreateSolidBrush(DKGRAY_BRUSH);
return (INT_PTR)hbrBkgnd;
}
}
case WM_CTLCOLORBTN:
{
HDC hdcButton = (HDC)wParam;
SetTextColor(hdcButton, RGB(255, 255, 255));
SetBkColor(hdcButton, DKGRAY_BRUSH);
}
hbrBkgnd = CreateSolidBrush(DKGRAY_BRUSH);
return (INT_PTR)hbrBkgnd;
case WM_ERASEBKGND:
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
return 0;
WM_ERASEBKGND : Sent when the window background must be erased (for example, when a window is resized). The message is sent to
prepare an invalidated portion of a window for painting.
The simplest solution: delete WM_ERASEBKGND message or add return DefWindowProc(hWnd, message, wParam, lParam) in the WM_ERASEBKGND message if you do not want delete WM_ERASEBKGND.
You could use WM_PAINT to fill the main window with the Brush using FillRect in your windows procedure. That should accomplish what you want.
case WM_PAINT: {
PAINTSTRUCT ps;
HDC hdc = BeginPaint(hwnd, &ps);
FillRect(hdc, &ps.rcPaint, reinterpret_cast<HBRUSH>(COLOR_ACTIVECAPTION + 1));
EndPaint(hwnd, &ps);
} return 0;
See the FillRect function https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-fillrect
Having simple window, button which opens dialog. But I want to add close button to it.
I have tried to add close button with adding WM_SYSMENU, with adding EnableMenuItem, but it didn't work:
Minimal code is:
resource.rc:
IDD_FORMVIEW DIALOGEX 0, 0, 178, 86
STYLE DS_SETFONT | DS_CONTROL | WS_VISIBLE | WS_SYSMENU
EXSTYLE WS_EX_OVERLAPPEDWINDOW
CAPTION "TEST"
FONT 12, "Microsoft Sans Serif", 400, 0, 0xCC
BEGIN
CTEXT "Test",IDC_STATIC,46,4,74,8,0,WS_EX_CLIENTEDGE
END
resource.h:
#define IDD_FORMVIEW 101
Test.cpp:
hwndButton = CreateWindowW(L"BUTTON",
L"ENTER",
WS_CHILD | WS_VISIBLE | BS_DEFPUSHBUTTON | WS_CLIPSIBLINGS,
605, 510, 255, 45,
hWnd, (HMENU)1, NULL, NULL);
case WM_COMMAND:
{
switch (LOWORD(wParam)) {
case 2: {
if (hwndHTDW == NULL) {
hwndHTDW = CreateDialog(hInstance, MAKEINTRESOURCE(IDD_FORMVIEW), hWnd, DialogProc);
ShowWindow(hwndHTDW, SW_SHOW);
UpdateWindow(hwndHTDW);
}
}
break;
}
}
{
switch (msg) {
case WM_INITDIALOG: {
EnableMenuItem(GetSystemMenu(hwnd, FALSE), SC_CLOSE,
MF_BYCOMMAND | MF_ENABLED);
return TRUE;
}
break;
default:
return FALSE;
}
return TRUE;
Modify your code a little bit.
BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
{
hInst = hInstance; // Store instance handle in our global variable
HWND hWnd = CreateWindowW(szWindowClass, szTitle, WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, nullptr, nullptr, hInstance, nullptr);
hwndButton = CreateWindowW(L"BUTTON",
L"ENTER",
WS_CHILD | WS_VISIBLE | BS_DEFPUSHBUTTON | WS_CLIPSIBLINGS,
605, 510, 255, 45,
hWnd, (HMENU)1, NULL, NULL);
if (!hWnd)
{
return FALSE;
}
ShowWindow(hWnd, nCmdShow);
UpdateWindow(hWnd);
return TRUE;
}
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message)
{
case WM_COMMAND:
{
int wmId = LOWORD(wParam);
// Parse the menu selections:
switch (wmId)
{
case IDM_ABOUT:
DialogBox(hInst, MAKEINTRESOURCE(IDD_ABOUTBOX), hWnd, About);
break;
case IDM_EXIT:
DestroyWindow(hWnd);
break;
case 1:
{
if (hwndHTDW == NULL)
{
hwndHTDW = CreateDialog(hInst, MAKEINTRESOURCE(IDD_FORMVIEW), hWnd, DialogProc);
Button_Close = CreateWindowW(L"BUTTON",
L"CLOSE",
WS_CHILD | WS_VISIBLE | BS_DEFPUSHBUTTON | WS_CLIPSIBLINGS | WS_TABSTOP,
130, 100, 80, 30,
hwndHTDW, (HMENU)2, NULL, NULL);
ShowWindow(hwndHTDW, SW_SHOW);
UpdateWindow(hwndHTDW);
}
}
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
}
break;
case WM_PAINT:
{
PAINTSTRUCT ps;
HDC hdc = BeginPaint(hWnd, &ps);
// TODO: Add any drawing code that uses hdc here...
EndPaint(hWnd, &ps);
}
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
return 0;
}
BOOL CALLBACK DialogProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
BOOL fError;
switch (message)
{
case WM_INITDIALOG:
{
EnableMenuItem(GetSystemMenu(hwnd, FALSE), SC_CLOSE,
MF_BYCOMMAND | MF_ENABLED);
return TRUE;
}
break;
case WM_COMMAND:
{
switch (LOWORD(wParam))
{
case 2:
{
EndDialog(hwnd, LOWORD(wParam));
return (INT_PTR)TRUE;
}
default:
break;
}
}
default:
return FALSE;
}
return TRUE;
}
Updated:
Create an extra button through CreateWindow and pass the handle of the dialog box to the button as a parameter.
HWND Button_Close = CreateWindowW(L"BUTTON",
L"CLOSE",
WS_CHILD | WS_VISIBLE | BS_DEFPUSHBUTTON | WS_CLIPSIBLINGS | WS_TABSTOP,
130, 100, 80, 30,
hwndHTDW, (HMENU)2, NULL, NULL);
In the callback function of the dialog box, add the WM_COMMAND event and add the following code.
case WM_COMMAND:
{
switch (LOWORD(wParam))
{
case 2:
{
EndDialog(hwnd, LOWORD(wParam));
return (INT_PTR)TRUE;
}
}
I started to learning winapi c++ today. And i wrote this simple program that have to change window name to the name that i write in text box:
#include <Windows.h>
LRESULT CALLBACK WindowProcedure(HWND, UINT, WPARAM, LPARAM);
void AddMenu(HWND);
void AddControl(HWND);
HWND hEdit;
int WINAPI WinMain(HINSTANCE hInst, HINSTANCE hPrewInst, LPSTR args, int ncmdshow)
{
WNDCLASSW wc = { 0 };
wc.hbrBackground = (HBRUSH)COLOR_WINDOW;
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hInstance = hInst;
wc.lpszClassName = L"class";
wc.lpfnWndProc = WindowProcedure;
if (!RegisterClassW(&wc))
return -1;
CreateWindowW(L"class", L"Window", WS_OVERLAPPEDWINDOW | WS_VISIBLE, 100, 100, 500, 500, NULL, NULL, NULL, NULL);
MSG msg = { 0 };
while (GetMessage(&msg, NULL, NULL, NULL))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return 0;
}
LRESULT CALLBACK WindowProcedure(HWND hWnd, UINT msg, WPARAM wp, LPARAM lp)
{
switch (msg)
{
case WM_COMMAND:
switch (wp)
{
case 1:
MessageBeep(MB_SERVICE_NOTIFICATION); break;
case 2:
DestroyWindow(hWnd); break;
case 3:
wchar_t text[100];
GetWindowTextW(hEdit, text, 100);
SetWindowTextW(hWnd, text);
break;
}
case WM_CREATE:
AddMenu(hWnd);
AddControl(hWnd);
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProcW(hWnd, msg, wp, lp);
}
}
void AddMenu(HWND hWnd)
{
HMENU hMenu;
hMenu = CreateMenu();
HMENU file;
file = CreateMenu();
HMENU Sub;
Sub = CreateMenu();
AppendMenu(hMenu, MF_POPUP, (UINT_PTR)file, "File");
AppendMenu(file, MF_STRING, 1, "Open");
AppendMenu(file, MF_POPUP, (UINT_PTR)Sub, "Sub");
AppendMenu(file, MF_STRING, 2, "Exit");
AppendMenu(Sub, MF_STRING, 3, "Change");
SetMenu(hWnd, hMenu);
}
void AddControl(HWND hWnd)
{
CreateWindowW(L"Static", L"Enter text: ", WS_VISIBLE | WS_CHILD | WS_BORDER | SS_CENTER, 200, 100, 100, 20, hWnd, NULL, NULL, NULL);
hEdit = CreateWindowW(L"Edit", L"...", WS_VISIBLE | WS_CHILD | WS_BORDER | ES_MULTILINE | ES_AUTOVSCROLL, 200, 152, 100, 50, hWnd, NULL, NULL, NULL);
}
By default in text box i have .... So i run my program, starting to type hello world for expample but nothing changes. I highlited my 3 dots that had to change and boom, my text appeared. I go to the menu choose File -> Sub -> Change and my window name changes to 3 dots ....
BUT! If i delete these: | ES_MULTILINE | ES_AUTOVSCROLL then text box working correctly but menu doesnt show up in my window.
I found that i have to do smth with EN_CHANGE but idk what. I tried to change WM_COMMAND to EN_CHANGE and my textbox worked correctly, but other menu buttons didnt work at all...
Your failure is caused by handling all the edit control notifications the same way. You need to test the notification code (found in HIWORD(wParam)) to see whether it is EN_CHANGE, and let notifications you aren't handling pass through to DefWindowProc.
You also have an even bigger bug in that you reach the closing brace of a function with a non-void return type. You need to always return something; when you aren't calling DefWindowProc the system still expects a return value. The reason things start working when you change WM_COMMAND to EN_CHANGE is not because you are handling EN_CHANGE, it is because you no longer have incorrect handling of WM_COMMAND, and instead let the DefWindowProc take them.
The fall-through from WM_COMMAND into WM_CREATE isn't helping things either.
LRESULT CALLBACK WindowProcedure(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
switch (msg)
{
case WM_COMMAND:
switch (HIWORD(wParam)) /* command kind */
{
case 0: // menus
switch (LOWORD(wParam)) /* child ID */
{
case 1:
MessageBeep(MB_SERVICE_NOTIFICATION);
return 0;
case 2:
DestroyWindow(hWnd);
return 0;
case 3:
wchar_t text[100];
GetWindowTextW(hEdit, text, 100);
SetWindowTextW(hWnd, text);
return 0;
}
break;
}
break;
case WM_CREATE:
AddMenu(hWnd);
AddControl(hWnd);
return 0;
case WM_DESTROY:
PostQuitMessage(0);
return 0;
}
// break actions also reach here
return DefWindowProcW(hWnd, msg, wParam, lParam);
}
I'm trying to learn how to make a GUI for a C++ using visual studio. I’ trying to create a button that when you push it a textbox with the content of a edit window appear, but the GetWindowText function is Returning a blank string when I run my program. I have tried to adjust the size of the buffer to see if that is the problem, but I haven’t been able to solve it that way. I have tried using number instead of the GetWindowTextLength() funktion, but I could not get it to work that way.
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message)
{
case WM_CREATE:
{` HMENU hMenubar = CreateMenu();
HMENU hFile = CreateMenu();
HMENU hOptions = CreateMenu();
AppendMenu(hMenubar, MF_POPUP, (UINT_PTR)hFile, L"File");
AppendMenu(hMenubar, MF_POPUP, NULL, L"Edit");
AppendMenu(hMenubar, MF_POPUP, (UINT_PTR)hOptions, L"Options");
AppendMenu(hFile, MF_STRING, NULL, L"Exit");
AppendMenu(hOptions, MF_STRING, NULL, L"option 1");
AppendMenu(hOptions, MF_STRING, NULL, L"option 2");
SetMenu(hWnd, hMenubar);
CreateWindow(TEXT("button"), TEXT("Hello"),
WS_VISIBLE | WS_CHILD,
10, 10, 80, 25,
hWnd, (HMENU) ID_BUTTON1, NULL, NULL);
static HWND hWndTextbox = CreateWindow(TEXT("edit"), TEXT("sim"),
WS_VISIBLE | WS_CHILD|WS_BORDER | ES_AUTOHSCROLL,
90, 120, 300, 20,
hWnd, (HMENU) ID_TEXT3, NULL, NULL);
CreateWindow(TEXT("button"), TEXT("shiny"),
WS_VISIBLE | WS_CHILD,
50, 50, 80, 50,
hWnd, (HMENU) ID_BUTTON2, NULL, NULL);
}
break;
case WM_COMMAND:
{
if (LOWORD(wParam) == ID_BUTTON1) {
MessageBox(hWnd, TEXT("Button has been clicked"), TEXT("title for popup"), MB_ICONINFORMATION);
}
if (LOWORD(wParam) == ID_BUTTON2) {
// create some default vars
// Allocate buffer including terminating null
int length = GetWindowTextLength(hWndTextbox) + 1;
std::wstring uinput(GetWindowTextLength(hWndTextbox) + 1, 0);
// Address of first character is used to obtain pointer to non-const data
// (as opposed to wstring::c_str()).
int size = GetWindowText(hWndTextbox, &uinput[0], length+1);
// Resize buffer to the actual text length
uinput.resize(size);
// MessageBox only needs pointer to const string, so we can use wstring::c_str() here.
MessageBox(hWnd, uinput.c_str(), TEXT("Message box"), MB_OK);
}
break;
int wmId = LOWORD(wParam);
// Parse the menu selections:
switch (wmId)
{
case IDM_ABOUT:
DialogBox(hInst, MAKEINTRESOURCE(IDD_ABOUTBOX), hWnd, About);
break;
case IDM_EXIT:
DestroyWindow(hWnd);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
}
break;
case WM_PAINT:
{
PAINTSTRUCT ps;
HDC hdc = BeginPaint(hWnd, &ps);
// TODO: Add any drawing code that uses hdc here...
EndPaint(hWnd, &ps);
}
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
return 0;
}`
the rest of the code was auto generated by visual studio so I have only included the part where I made changes