Related
I'm learning to write basic Win32 apps in C++ and am trying to pass typed text from one editable textbox to a new window after pressing a button.
I noticed that the default text buffer capacity for such a transfer is 20 characters in Visual Studio 2019 (I am on 64-bit Windows 10). After I try to pass a string longer than 20 characters, I get an exception thrown.
I would like to know how to increase that buffer capacity, since eventually I want to be able to pass a filepath into the text input window and open that file.
My code:
#include <windows.h>
#include <string>
#include <iostream>
//lresult callback prototype
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam);
//window handles
HWND hMainWindow;
HINSTANCE hMainInstance;
HWND hLblOutput;
HWND hTxtInput;
HWND hButton;
#define IDC_TEXTBOX 1000
#define IDC_BUTTON 1001
//call to winmain - equivalent of main for win32 environments
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
MSG msg = { 0 };
WNDCLASS wc = { 0 };
wc.lpfnWndProc = WndProc;
wc.hInstance = hInstance;
wc.hbrBackground = (HBRUSH)(COLOR_BACKGROUND);
wc.lpszClassName = TEXT("NiceWindowsApp");
if (!RegisterClass(&wc))
return 1;
hMainWindow = CreateWindow(wc.lpszClassName, TEXT("My Windows Application"), WS_OVERLAPPEDWINDOW | WS_VISIBLE, 0, 0, 640, 480, 0, 0, hInstance, NULL);
hMainInstance = wc.hInstance;
while (GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return 0;
}
//callback definition
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
int offset = 0;
switch (message) {
case WM_CREATE:
hMainWindow = hWnd;
hTxtInput = CreateWindowEx(WS_EX_CLIENTEDGE, TEXT("EDIT"), TEXT("Type something here"),
WS_VISIBLE | WS_CHILD | ES_LEFT, 50, 50, 400, 25, hWnd,
(HMENU)IDC_TEXTBOX, hMainInstance, NULL);
hButton = CreateWindowEx(WS_EX_CLIENTEDGE, TEXT("BUTTON"), TEXT("Press Me!"), WS_VISIBLE | WS_CHILD | WM_COPY | ES_LEFT, 500, 30, 100, 60, hWnd,
(HMENU)IDC_BUTTON, hMainInstance, NULL);
break;
case WM_COMMAND:
if (LOWORD(wParam) == IDC_BUTTON)
{
//CANNOT HANDLE MORE THAN 20 CHARACTERS!!!
std::string input;
GetWindowTextA(hTxtInput, reinterpret_cast<char*> ((char*)input.c_str()), 400);
++offset;
hLblOutput = CreateWindowEx(WS_EX_STATICEDGE, TEXT("EDIT"), input.c_str(), WS_VISIBLE | WS_CHILD | ES_READONLY | ES_LEFT, 50, 200 + offset * 26, 800, 25, hWnd,
(HMENU)IDC_TEXTBOX, hMainInstance, NULL);
}
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
return 0;
}
I have tried to increase the third parameter in GetWindowTextA() to various numbers up to 4000, but it didn't seem to help.
One correct way to do this is:
std::wstring text;
text.resize(GetWindowTextLengthW(hTxtInput));
text.resize(GetWindowTextW(hTxtInput, text.data(), text.size() + 1));
Solved as per the below:
#include <windows.h>
#include <string>
#include <iostream>
//lresult callback prototype
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam);
//window handles
HWND hMainWindow;
HINSTANCE hMainInstance;
HWND hLblOutput;
HWND hTxtInput;
HWND hButton;
CHAR s_text_1[]{ "Some text.." };
CHAR s_text_2[]{ 0 };
#define IDC_TEXTBOX 1000
#define IDC_BUTTON 1001
//call to winmain - equivalent of main for win32 environments
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
MSG msg = { 0 };
WNDCLASS wc = { 0 };
wc.lpfnWndProc = WndProc;
wc.hInstance = hInstance;
wc.hbrBackground = (HBRUSH)(COLOR_BACKGROUND);
wc.lpszClassName = TEXT("NiceWindowsApp");
if (!RegisterClass(&wc))
return 1;
hMainWindow = CreateWindow(wc.lpszClassName, TEXT("My Windows Application"), WS_OVERLAPPEDWINDOW | WS_VISIBLE,
0, 0, 640, 480, 0, 0, hInstance, NULL);
hMainInstance = wc.hInstance;
while (GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return 0;
}
//callback definition
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
int offset = 0;
switch (message) {
case WM_CREATE:
hMainWindow = hWnd;
hTxtInput = CreateWindowEx(WS_EX_CLIENTEDGE, TEXT("EDIT"), s_text_1,
WS_VISIBLE | WS_CHILD | ES_LEFT, 50, 50, 400, 25, hWnd,
(HMENU)IDC_TEXTBOX, hMainInstance, NULL);
hButton = CreateWindowEx(WS_EX_CLIENTEDGE, TEXT("BUTTON"), TEXT("Press Me!"), WS_VISIBLE | WS_CHILD | WM_COPY | ES_LEFT, 500, 30, 100, 60, hWnd,
(HMENU)IDC_BUTTON, hMainInstance, NULL);
break;
case WM_COMMAND:
if (LOWORD(wParam) == IDC_BUTTON)
{
//CANNOT HANDLE MORE THAN 20 CHARACTERS!!!
std::wstring input;
//GetWindowTextW(hTxtInput, reinterpret_cast<char*> ((char*)input.c_str()), 400);
int lgth = GetWindowTextLength(hTxtInput);
//GetWindowTextW(hTxtInput, reinterpret_cast<wchar_t*> ((wchar_t*)input.c_str()), lgth);
//GetWindowTextA(hTxtInput, char[], 400);
GetWindowText(hTxtInput, s_text_1, 255);
++offset;
hLblOutput = CreateWindowEx(WS_EX_STATICEDGE, TEXT("EDIT"), s_text_1, WS_VISIBLE | WS_CHILD | ES_READONLY | ES_LEFT, 50, 200 + offset * 26, 800, 25, hWnd,
(HMENU)IDC_TEXTBOX, hMainInstance, NULL);
SetWindowText(hLblOutput, s_text_1);
}
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
return 0;
}
Thanks for your hints everybody.
EDIT: I now realise that this solution is not technically perfect and can lead to undefined behaviour and/or memory leaks. I'll take the advice presented in the other answers and comments into account and adjust the code accordingly.
EDIT 2.0 (2023.02.04): My most recent code is below. Hopefully it's more robust.
#include <windows.h>
#include <string>
#include <iostream>
//last update - 04.02.2023 as per StackOverflow thread recommendations.
//lresult callback prototype
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam);
//window handles
HWND hMainWindow;
HINSTANCE hMainInstance;
HWND hLblOutput;
HWND hTxtInput;
HWND hButton;
CHAR s_text_1[]{ "Some text.." };
#define IDC_TEXTBOX 1000
#define IDC_BUTTON 1001
//call to winmain - equivalent of main for win32 environments
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
MSG msg = { 0 };
WNDCLASS wc = { 0 };
wc.lpfnWndProc = WndProc;
wc.hInstance = hInstance;
wc.hbrBackground = (HBRUSH)(COLOR_BACKGROUND);
wc.lpszClassName = TEXT("NiceWindowsApp");
if (!RegisterClass(&wc))
return 1;
hMainWindow = CreateWindow(wc.lpszClassName, TEXT("My Windows Application"), WS_OVERLAPPEDWINDOW | WS_VISIBLE,
0, 0, 640, 480, 0, 0, hInstance, NULL);
hMainInstance = wc.hInstance;
while (GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return 0;
}
//callback definition
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
int offset = 0;
switch (message) {
case WM_CREATE:
hMainWindow = hWnd;
hTxtInput = CreateWindowEx(WS_EX_CLIENTEDGE, TEXT("EDIT"), s_text_1,
WS_VISIBLE | WS_CHILD | ES_LEFT, 50, 50, 400, 25, hWnd,
(HMENU)IDC_TEXTBOX, hMainInstance, NULL);
hButton = CreateWindowEx(WS_EX_CLIENTEDGE, TEXT("BUTTON"), TEXT("Press Me!"), WS_VISIBLE | WS_CHILD | WM_COPY | ES_LEFT, 500, 30, 100, 60, hWnd,
(HMENU)IDC_BUTTON, hMainInstance, NULL);
break;
case WM_COMMAND:
if (LOWORD(wParam) == IDC_BUTTON)
{
std::wstring input;
//resize added as suggested
input.resize(GetWindowTextLengthW(hTxtInput));
GetWindowTextW(hTxtInput, input.data(), input.size() + 1);
++offset;
hLblOutput = CreateWindowEx(WS_EX_STATICEDGE, TEXT("EDIT"), s_text_1, WS_VISIBLE | WS_CHILD | ES_READONLY | ES_LEFT, 50, 200 + offset * 26, 800, 25, hWnd,
(HMENU)IDC_TEXTBOX, hMainInstance, NULL);
SetWindowTextW(hLblOutput, input.data());
}
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
return 0;
}
Im trying to create a windows application with winapi. So i want to have one parent window and one child window in it. Here is my code:
#include <windows.h>
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
LRESULT CALLBACK ChildProc(HWND, UINT, WPARAM, LPARAM);
const char szChildName[] = "Child window title";
const UINT PM_COLORCHANGED = WM_APP + 1;
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
PSTR szCmdLine, int iCmdShow)
{
MSG msg;
HWND hWnd;
WNDCLASS wc;
char szAppName[] = "title";
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hIcon = NULL;
wc.hInstance = hInstance;
wc.lpfnWndProc = WndProc;
wc.lpszClassName = (LPCWSTR)szAppName;
wc.lpszMenuName = NULL;
wc.style = CS_HREDRAW | CS_VREDRAW;
RegisterClass(&wc);
wc.hbrBackground = (HBRUSH)GetStockObject(LTGRAY_BRUSH);
wc.hIcon = NULL;
wc.lpfnWndProc = ChildProc;
wc.lpszClassName = (LPCWSTR)szChildName;
RegisterClass(&wc);
hWnd = CreateWindow((LPCWSTR)szAppName,
(LPCWSTR)szAppName,
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT,
CW_USEDEFAULT,
CW_USEDEFAULT,
CW_USEDEFAULT,
NULL,
NULL,
hInstance,
NULL);
ShowWindow(hWnd, iCmdShow);
UpdateWindow(hWnd);
while (GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return msg.wParam;
}
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
static HWND hChild;
static RECT rect;
switch (message)
{
case WM_CREATE:
{
GetClientRect(hWnd, &rect);
hChild = CreateWindow((LPCWSTR)szChildName,
NULL,
WS_CHILD | WS_VISIBLE | WS_DLGFRAME,
5,
rect.bottom - 35,
rect.right - 10,
30,
hWnd,
NULL,
((LPCREATESTRUCT)lParam)->hInstance,
NULL);
return 0;
}
case WM_SIZE:
{
return 0;
}
case PM_COLORCHANGED:
{
return 0;
}
case WM_PAINT:
{
return 0;
}
case WM_DESTROY:
{
PostQuitMessage(0);
return 0;
}
}
return DefWindowProc(hWnd, message, wParam, lParam);
}
LRESULT CALLBACK ChildProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message)
{
case WM_SIZE:
{
return 0;
}
case WM_LBUTTONDOWN:
{
return 0;
}
case WM_PAINT:
{
return 0;
}
}
return DefWindowProc(hWnd, message, wParam, lParam);
}
This works perfect, so i see the child window at the bottom of the application.
But, instead of WNDCLASS I want to use WNDCLASSEX, which forces me to use RegisterClassEx() to register the windows. Also I want to use CreateWindowEx, my code looks like that:
#include <windows.h>
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
LRESULT CALLBACK ChildProc(HWND, UINT, WPARAM, LPARAM);
const char szChildName[] = "Child name";
const UINT PM_COLORCHANGED = WM_APP + 1;
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
PSTR szCmdLine, int iCmdShow)
{
MSG msg;
HWND hWnd;
WNDCLASSEX wc;
char szAppName[] = "The Child Window";
ZeroMemory(&wc, sizeof(WNDCLASSEX));
wc.cbClsExtra = 0;
wc.cbSize = sizeof(WNDCLASSEX);
wc.cbWndExtra = 0;
wc.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hIcon = NULL;
wc.hIconSm = NULL;
wc.hInstance = hInstance;
wc.lpfnWndProc = (WNDPROC)WndProc;
wc.lpszClassName = (LPCWSTR)szAppName;
wc.lpszMenuName = NULL;
wc.style = CS_HREDRAW | CS_VREDRAW;
RegisterClassEx(&wc);
wc.hbrBackground = (HBRUSH)GetStockObject(LTGRAY_BRUSH);
wc.hIcon = NULL;
wc.lpfnWndProc = (WNDPROC)ChildProc;
wc.lpszClassName = (LPCWSTR)szChildName;
RegisterClassEx(&wc);
hWnd = CreateWindowEx(NULL,
wc.lpszClassName,
L"parent window",
(WS_MINIMIZEBOX | WS_MAXIMIZEBOX | WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU),
200,
150,
1000,
1000,
NULL,
NULL,
hInstance,
NULL
);
ShowWindow(hWnd, iCmdShow);
UpdateWindow(hWnd);
while (GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return msg.wParam;
}
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
static HWND hChild;
static RECT rect;
switch (message)
{
case WM_CREATE:
{
GetClientRect(hWnd, &rect);
hChild = CreateWindowEx(NULL,
(LPCWSTR)szChildName,
L"child window",
(WS_CHILD | WS_VISIBLE | WS_DLGFRAME),
200,
150,
200,
200,
hWnd,
NULL,
((LPCREATESTRUCT)lParam)->hInstance,
NULL
);
return 0;
}
case WM_SIZE:
{
return 0;
}
case PM_COLORCHANGED:
{
return 0;
}
case WM_PAINT:
{
return 0;
}
case WM_DESTROY:
{
PostQuitMessage(0);
return 0;
}
}
return DefWindowProc(hWnd, message, wParam, lParam);
}
LRESULT CALLBACK ChildProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message)
{
case WM_SIZE:
{
return 0;
}
case WM_LBUTTONDOWN:
{
return 0;
}
case WM_PAINT:
{
return 0;
}
}
return DefWindowProc(hWnd, message, wParam, lParam);
}
The problem: Now i only see the color of the child window, so the whole application has this background color of the child window, so somehow the pc repainted everything in the color of the child window. (no child window is even visible, everything i see is only this LTGRAY_Brush of the child window.
Weird is: If i delete the line where the child window is created, so this line:
hChild = CreateWindowEx(NULL,
(LPCWSTR)szChildName,
L"child window",
(WS_CHILD | WS_VISIBLE | WS_DLGFRAME),
200,
150,
200,
200,
hWnd,
NULL,
((LPCREATESTRUCT)lParam)->hInstance,
NULL
then even now, the background color gets the same as the one that i registered the child class with. Altough the child class hasn't been created. Thanks for your help.
Having such a simple Win32 app:
#include <windows.h>
#include <gdiplus.h>
#include <stdio.h>
#include <tchar.h>
#pragma comment(lib, "gdiplus.lib")
using namespace Gdiplus;
const wchar_t g_szClassName[] = L"Skeleton";
const wchar_t g_szChildClassName[] = L"Child";
wchar_t msgbuf[100];
void Example_DrawImage9(HDC hdc) {
Graphics graphics(hdc);
Image image(L"C:/Users/Darek/Fallout2_older/data/art/iface/armor_info.bmp");
graphics.DrawImage(&image, 0, 0);
}
LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
switch (msg) {
case WM_PAINT:
swprintf_s(msgbuf, _T("WM_PAINT - PARENT - hwnd: %02X\n"), (int)hwnd);
OutputDebugString(msgbuf);
return 0;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hwnd, msg, wParam, lParam);
}
return 0;
}
LRESULT CALLBACK WndProcChild(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
switch (msg) {
case WM_PAINT:
swprintf_s(msgbuf, _T("WM_PAINT - CHILD - hwnd: %02X\n"), (int)hwnd);
OutputDebugString(msgbuf);
return 0;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hwnd, msg, wParam, lParam);
}
return 0;
}
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
LPSTR lpCmdLine, int nCmdShow)
{
WNDCLASSEX wc;
HWND hwnd;
MSG Msg;
ULONG_PTR token;
GdiplusStartupInput input = { 0 };
input.GdiplusVersion = 1;
GdiplusStartup(&token, &input, NULL);
//Step 1: Registering the Window Class
wc.cbSize = sizeof(WNDCLASSEX);
wc.style = CS_HREDRAW | CS_VREDRAW;
wc.lpfnWndProc = WndProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = hInstance;
wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
wc.lpszMenuName = NULL;
wc.lpszClassName = g_szClassName;
wc.hIconSm = LoadIcon(NULL, IDI_APPLICATION);
if (!RegisterClassEx(&wc)) {
MessageBox(NULL, L"Window Registration Failed!", L"Error!",
MB_ICONEXCLAMATION | MB_OK);
return 0;
}
hwnd = CreateWindowEx(0, g_szClassName, L"Skeleton", WS_POPUP | WS_BORDER, 0, 0, 190, 110, 0, 0, hInstance, 0);
SetWindowLong(hwnd, GWL_EXSTYLE, GetWindowLong(hwnd, GWL_EXSTYLE) | WS_EX_LAYERED);
SetLayeredWindowAttributes(hwnd, 0, 128, LWA_ALPHA);
ShowWindow(hwnd, nCmdShow);
UpdateWindow(hwnd);
// ---------------
HWND hwnd_child;
wc.lpfnWndProc = WndProcChild; // 1
wc.lpszClassName = g_szChildClassName;
if (!RegisterClassEx(&wc)) {
MessageBox(NULL, L"Window Registration Failed!", L"Error!",
MB_ICONEXCLAMATION | MB_OK);
return 0;
}
hwnd_child = CreateWindowEx(0, g_szClassName, L"Child", /*WS_POPUP |*/ WS_BORDER, 200, 0, 190, 110, hwnd, 0, hInstance, 0);
swprintf_s(msgbuf, _T("hwnd_child: %02X\n"), (int)hwnd_child);
OutputDebugString(msgbuf);
SetWindowLong(hwnd_child, GWL_EXSTYLE, GetWindowLong(hwnd_child, GWL_EXSTYLE) | WS_EX_LAYERED);
SetLayeredWindowAttributes(hwnd_child, 0, 128, LWA_ALPHA);
ShowWindow(hwnd_child, nCmdShow);
UpdateWindow(hwnd_child);
// ---------------
while (GetMessage(&Msg, NULL, 0, 0) > 0) {
TranslateMessage(&Msg);
DispatchMessage(&Msg);
}
GdiplusShutdown(token);
return Msg.wParam;
}
I've expected that the child window will run it's own WndProcChild window procedure but I get:
WM_PAINT - PARENT - hwnd: C0996
hwnd_child: C0998
WM_PAINT - PARENT - hwnd: C0998
what implies that the child window runs parent's procedure (WndProc) even if I've clearly assigned (line #1) a separate procedure for it.
I was actually following a tutorial. I really want to get an answer because I will need to add icons to the window down the line. Getting images to show in the window would be the first step.
Sorry for some reason the update I added did not go through before. My solution is geared towards Unicode.
The corrected updated file is below :
#include <windows.h>
#include <commctrl.h>
using namespace std;
LPCWSTR szClassName = L"myWindowClass";
HWND hLogo;
HBITMAP hLogoImage;
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
void loadPictures();
void parentControls(HWND);
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, int icmdshow)
{
HWND hWnd;
WNDCLASSW wc = { 0 };
wc.style = 0;
wc.lpszMenuName = NULL;
wc.lpszClassName = szClassName;
wc.lpfnWndProc = WndProc;
wc.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
wc.hInstance = hInstance;
wc.hIcon = LoadIconW(NULL, IDI_APPLICATION);
wc.hCursor = LoadCursorW(NULL, IDC_ARROW);
wc.cbWndExtra = 0;
wc.cbClsExtra = 0;
if (!RegisterClassW(&wc))
{
const wchar_t Error01[] = L"Register Issue To Check On : "; /// Notice this
const wchar_t Error01_Caption[] = L"Error 01";
MessageBoxW(NULL, Error01, Error01_Caption, MB_OK | MB_ICONERROR);
return 0;
}
LPCWSTR parentWinTitle = L"My Window";
hWnd = CreateWindowW(szClassName, parentWinTitle, WS_OVERLAPPEDWINDOW | WS_VISIBLE, 100, 100, 250, 200, NULL, NULL, NULL, NULL);
if (hWnd == NULL)
{
const wchar_t Error02[] = L"Window Creation Issue To Check On : ";
const wchar_t Error02_Caption[] = L"Window Creation Issue To Check On : ";
MessageBoxW(NULL, Error02, Error02_Caption, MB_OK | MB_ICONERROR);
}
ShowWindow(hWnd, icmdshow);
UpdateWindow(hWnd);
MSG msg = { 0 };
while (GetMessageW(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessageW(&msg);
}
return 0;
}
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message)
{
case WM_CREATE:
loadPictures(); /// Must be called first, Calling the Images function in Create
parentControls(hWnd);
break;
/* case WM_COMMAND:
switch (wParam)
{
}
break;
*/
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProcW(hWnd, message, wParam, lParam);
}
return 0;
}
void parentControls(HWND hWnd)
{
hLogo = CreateWindowW(WC_STATICW, NULL, WS_VISIBLE | WS_CHILD | SS_BITMAP, 70, 25, 100, 100, hWnd, NULL, NULL, NULL);
SendMessageW(hLogo, STM_SETIMAGE, IMAGE_BITMAP, (LPARAM)hLogoImage);
}
void loadPictures()
{ /// bmp image save in file with main.cpp
LPCWSTR myBmp = L"bitmap1.bmp";
hLogoImage = (HBITMAP)LoadImageW(NULL, myBmp, IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE);
}
case WM_COMMAND:
switch(wp)
{
}
break;
parentControls(hWnd); <--- never gets here
loadPictures(); /// Calling the Images function in Create
break;
parentControls and loadPictures are never reached in this switch statement.
loadPictures should be called first.
Remove the two lines, put them in WM_CREATE as follows:
case WM_CREATE:
loadPictures(); /// Calling the Images function in Create
parentControls(hWnd);
break;
Someone told me the answer should be here instead of updated above. I am sure I will be made aware that it is wrong if I add it here. I figure that is why the updates didn't take when I tried them before in the original post above. Either way the update/Answer is below.
#include <windows.h>
#include <commctrl.h>
using namespace std;
LPCWSTR szClassName = L"myWindowClass";
HWND hLogo;
HBITMAP hLogoImage;
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
void loadPictures();
void parentControls(HWND);
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, int icmdshow)
{
HWND hWnd;
WNDCLASSW wc = { 0 };
wc.style = 0;
wc.lpszMenuName = NULL;
wc.lpszClassName = szClassName;
wc.lpfnWndProc = WndProc;
wc.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
wc.hInstance = hInstance;
wc.hIcon = LoadIconW(NULL, IDI_APPLICATION);
wc.hCursor = LoadCursorW(NULL, IDC_ARROW);
wc.cbWndExtra = 0;
wc.cbClsExtra = 0;
if (!RegisterClassW(&wc))
{
const wchar_t Error01[] = L"Register Issue To Check On : "; /// Notice this
const wchar_t Error01_Caption[] = L"Error 01";
MessageBoxW(NULL, Error01, Error01_Caption, MB_OK | MB_ICONERROR);
return 0;
}
LPCWSTR parentWinTitle = L"My Window";
hWnd = CreateWindowW(szClassName, parentWinTitle, WS_OVERLAPPEDWINDOW | WS_VISIBLE, 100, 100, 250, 200, NULL, NULL, NULL, NULL);
if (hWnd == NULL)
{
const wchar_t Error02[] = L"Window Creation Issue To Check On : ";
const wchar_t Error02_Caption[] = L"Window Creation Issue To Check On : ";
MessageBoxW(0, Error02, Error02_Caption, MB_OK | MB_ICONERROR);
}
ShowWindow(hWnd, icmdshow);
UpdateWindow(hWnd);
MSG msg = { 0 };
while (GetMessageW(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessageW(&msg);
}
return 0;
}
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message)
{
case WM_CREATE:
loadPictures(); /// Must be called first, Calling the Images function in Create
parentControls(hWnd);
break;
/* case WM_COMMAND:
switch (wParam)
{
}
break;
*/
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProcW(hWnd, message, wParam, lParam);
}
return 0;
}
void parentControls(HWND hWnd)
{
hLogo = CreateWindowW(WC_STATICW, NULL, WS_VISIBLE | WS_CHILD | SS_BITMAP, 70, 25, 100, 100, hWnd, NULL, NULL, NULL);
SendMessageW(hLogo, STM_SETIMAGE, IMAGE_BITMAP, (LPARAM)hLogoImage);
}
void loadPictures()
{ /// bmp image save in file with main.cpp
LPCWSTR myBmp = L"bitmap1.bmp";
hLogoImage = (HBITMAP)LoadImageW(NULL, myBmp, IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE);
}
following code is not working .i am trying to get text from edit control but it does not work.m tired by trying all possible codes looking documentation on msdn etc...
case WM_COMMAND:
switch(LOWORD(wParam)){
case 1:
::MessageBox(hwnd,"button clicked","message",MB_OK);
break;
case 2:
TCHAR t[20]; //
GetWindowText(text_box,t,19);// this is not working????????????????
::MessageBox(hwnd,t,t,MB_OK);
cout<<t;
break;
for refrence below is the complete code :
#include <windows.h>
#include<iostream>
using namespace std;
const char g_szClassName[] = "myWindowClass";
// Step 4: the Window Procedure
LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
HWND text_field, button , text_box;
char text_saved[20];
switch(msg)
{ case WM_CREATE:
text_field = CreateWindow("STATIC",
"Hello World",
WS_VISIBLE | WS_CHILD | WS_BORDER,
20,20, 90,25,
hwnd,
NULL,NULL,NULL);
button = CreateWindow("BUTTON",
"push button",
WS_VISIBLE | WS_CHILD | WS_BORDER,
20,50, 100,20,
hwnd,
(HMENU)1,NULL,NULL
) ;
text_box = CreateWindow("EDIT",
" ",
WS_VISIBLE | WS_CHILD | WS_BORDER,
20,80, 200,25,
hwnd,
NULL,NULL,NULL
);
CreateWindow("BUTTON",
"Save",
WS_VISIBLE | WS_CHILD | WS_BORDER,
20,120, 100,20,
hwnd,
(HMENU)2,NULL,NULL
);
break;
case WM_COMMAND:
switch(LOWORD(wParam)){
case 1:
::MessageBox(hwnd,"button clicked","message",MB_OK);
break;
case 2:
TCHAR t[20];
GetWindowText(text_box,t,19);
::MessageBox(hwnd,t,t,MB_OK);
cout<<t;
break;
}
break;
case WM_CLOSE:
DestroyWindow(hwnd);
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hwnd, msg, wParam, lParam);
}
return 0;
}
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
LPSTR lpCmdLine, int nCmdShow)
{
WNDCLASSEX wc;
HWND hwnd;
MSG Msg;
//Step 1: Registering the Window Class
wc.cbSize = sizeof(WNDCLASSEX);
wc.style = 0;
wc.lpfnWndProc = WndProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = hInstance;
wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
wc.lpszMenuName = NULL;
wc.lpszClassName = g_szClassName;
wc.hIconSm = LoadIcon(NULL, IDI_APPLICATION);
if(!RegisterClassEx(&wc))
{
MessageBox(NULL, "Window Registration Failed!", "Error!",
MB_ICONEXCLAMATION | MB_OK);
return 0;
}
// Step 2: Creating the Window
hwnd = CreateWindowEx(
WS_EX_CLIENTEDGE,
g_szClassName,
"The title of my window",
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, CW_USEDEFAULT, 500,500,
NULL, NULL, hInstance, NULL);
if(hwnd == NULL)
{
MessageBox(NULL, "Window Creation Failed!", "Error!",
MB_ICONEXCLAMATION | MB_OK);
return 0;
}
ShowWindow(hwnd, nCmdShow);
UpdateWindow(hwnd);
// Step 3: The Message Loop
while(GetMessage(&Msg, NULL, 0, 0) > 0)
{
TranslateMessage(&Msg);
DispatchMessage(&Msg);
}
return Msg.wParam;
}
You've defined text_box (and the other variables) as local to the WndProc function, meaning their values are lost every time that function is called to process a message. You need to move them outside of the function scope (or make them static) if you want to preserve their values from one message to the next.
This is a working reworked version of your code, replacing the local variable text_box (which doesn't retain information from one call to the next) with a numerical control id and use of GetDlgItem, changing from ANSI to Unicode text, and fixing some other stuff, while mainly keeping the formatting:
#undef UNICODE
#define UNICODE
#include <windows.h>
#include<iostream>
#include <string>
using namespace std;
namespace g {
const auto class_name = L"myWindowClass";
const auto push_button_id = 1;
const auto save_button_id = 2;
const auto edit_field_id = 3;
const auto h_instance = ::GetModuleHandle( nullptr );
} // namespace g
// Step 4: the Window Procedure
void create_controls( const HWND hwnd )
{
CreateWindow( L"STATIC",
L"Hello World",
WS_VISIBLE | WS_CHILD | WS_BORDER,
20,20, 90,25,
hwnd,
nullptr, g::h_instance, nullptr );
CreateWindow( L"BUTTON",
L"push button",
WS_VISIBLE | WS_CHILD | WS_BORDER,
20,50, 100,20,
hwnd,
(HMENU) g::push_button_id, g::h_instance, nullptr
) ;
CreateWindow( L"EDIT",
L"",
WS_VISIBLE | WS_CHILD | WS_BORDER,
20,80, 200,25,
hwnd,
(HMENU) g::edit_field_id, g::h_instance, nullptr
);
CreateWindow( L"BUTTON",
L"Save",
WS_VISIBLE | WS_CHILD | WS_BORDER,
20,120, 100,20,
hwnd,
(HMENU) g::save_button_id, g::h_instance, nullptr
);
}
LRESULT CALLBACK WndProc( HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam )
{
switch(msg)
{
case WM_CREATE:
create_controls( hwnd );
break;
case WM_COMMAND:
switch(LOWORD(wParam)) {
case 1:
::MessageBox( hwnd, L"button clicked", L"message", MB_SETFOREGROUND );
break;
case 2:
const HWND text_box = GetDlgItem( hwnd, g::edit_field_id );
const int n = GetWindowTextLength( text_box );
wstring text( n + 1, L'#' );
if( n > 0 )
{
GetWindowText( text_box, &text[0], text.length() );
}
text.resize( n );
::MessageBox(hwnd, text.c_str(), L"The text:", MB_SETFOREGROUND );
break;
}
break;
case WM_CLOSE:
DestroyWindow(hwnd);
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hwnd, msg, wParam, lParam);
}
return 0;
}
int main()
{
//Step 1: Registering the Window Class
WNDCLASSEX wc = { sizeof( WNDCLASSEX ) };
wc.style = 0;
wc.lpfnWndProc = WndProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = g::h_instance;
wc.hIcon = LoadIcon(nullptr, IDI_APPLICATION);
wc.hCursor = LoadCursor(nullptr, IDC_ARROW);
wc.hbrBackground = reinterpret_cast<HBRUSH>(COLOR_WINDOW+1);
wc.lpszMenuName = nullptr;
wc.lpszClassName = g::class_name;
wc.hIconSm = LoadIcon(nullptr, IDI_APPLICATION);
if(!RegisterClassEx(&wc))
{
MessageBox(nullptr, L"Window Registration Failed!", L"Error!",
MB_ICONEXCLAMATION | MB_SETFOREGROUND );
return E_FAIL;
}
// Step 2: Creating the Window
const HWND hwnd = CreateWindowEx(
WS_EX_CLIENTEDGE,
g::class_name,
L"The title of my window",
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, CW_USEDEFAULT, 500,500,
nullptr, nullptr, g::h_instance, nullptr);
if(hwnd == nullptr)
{
MessageBox(nullptr, L"Window Creation Failed!", L"Error!",
MB_ICONEXCLAMATION | MB_SETFOREGROUND);
return E_FAIL;
}
ShowWindow(hwnd, SW_SHOWDEFAULT); // Note: any other value is replaced.
UpdateWindow(hwnd); // Not strictly necessary.
// Step 3: The Message Loop
MSG Msg;
int get_message_result;
while( (get_message_result = GetMessage(&Msg, nullptr, 0, 0)) > 0 )
{
TranslateMessage(&Msg);
DispatchMessage(&Msg);
}
return (get_message_result < 0? E_FAIL : Msg.wParam);
}