I have a simple example for creating popup menu. I want to close this menu programmatically when pressing on button, is there any possibility to do that? Or maybe I should use different class?
I need to open this menu when button is pressed and close it the same way when pressing the button. Here is simple code example that I have.
#define MAX_LOADSTRING 100
#define IDM_FILE_NEW 1
#define IDM_FILE_OPEN 2
#define IDM_FILE_QUIT 3
#define BUTTON_ID 1
// Global Variables:
HINSTANCE hInst; // current instance
WCHAR szTitle[MAX_LOADSTRING]; // The title bar text
WCHAR szWindowClass[MAX_LOADSTRING]; // the main window class name
HWND gButton = NULL;
HWND mainHwnd = NULL;
HMENU hMenu;
bool gMenuHidden = false;
// Forward declarations of functions included in this code module:
ATOM MyRegisterClass(HINSTANCE hInstance);
BOOL InitInstance(HINSTANCE, int);
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
INT_PTR CALLBACK About(HWND, UINT, WPARAM, LPARAM);
int APIENTRY wWinMain(_In_ HINSTANCE hInstance,
_In_opt_ HINSTANCE hPrevInstance,
_In_ LPWSTR lpCmdLine,
_In_ int nCmdShow)
{
UNREFERENCED_PARAMETER(hPrevInstance);
UNREFERENCED_PARAMETER(lpCmdLine);
// Initialize global strings
LoadStringW(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING);
LoadStringW(hInstance, IDC_POPUPMENU, szWindowClass, MAX_LOADSTRING);
MyRegisterClass(hInstance);
// Perform application initialization:
if (!InitInstance (hInstance, nCmdShow))
{
return FALSE;
}
HACCEL hAccelTable = LoadAccelerators(hInstance, MAKEINTRESOURCE(IDC_POPUPMENU));
MSG msg;
// Main message loop:
while (GetMessage(&msg, nullptr, 0, 0))
{
if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
return (int) msg.wParam;
}
ATOM MyRegisterClass(HINSTANCE hInstance)
{
WNDCLASSEXW wcex;
wcex.cbSize = sizeof(WNDCLASSEX);
wcex.style = CS_HREDRAW | CS_VREDRAW;
wcex.lpfnWndProc = WndProc;
wcex.cbClsExtra = 0;
wcex.cbWndExtra = 0;
wcex.hInstance = hInstance;
wcex.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_POPUPMENU));
wcex.hCursor = LoadCursor(nullptr, IDC_ARROW);
wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
wcex.lpszMenuName = NULL;
wcex.lpszClassName = szWindowClass;
wcex.hIconSm = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_SMALL));
return RegisterClassExW(&wcex);
}
BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
{
hInst = hInstance; // Store instance handle in our global variable
mainHwnd = CreateWindowW(szWindowClass, szTitle, WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, nullptr, nullptr, hInstance, nullptr);
if (!mainHwnd)
{
return FALSE;
}
ShowWindow(mainHwnd, nCmdShow);
UpdateWindow(mainHwnd);
return TRUE;
}
HMENU CreateAndInitializeMenu()
{
HMENU menu = CreatePopupMenu();
AppendMenuW(menu, MF_STRING, IDM_FILE_NEW, L"&New");
AppendMenuW(menu, MF_STRING, IDM_FILE_OPEN, L"&Open");
AppendMenuW(menu, MF_SEPARATOR, 0, NULL);
AppendMenuW(menu, MF_STRING, IDM_FILE_QUIT, L"&Quit");
return menu;
}
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message) {
case WM_COMMAND:
{
if (wParam == BUTTON_ID)
{
//gMenuHidden = !gMenuHidden;
if (gMenuHidden)
{
hMenu = CreateAndInitializeMenu();
TrackPopupMenu(hMenu, TPM_RIGHTBUTTON, 150, 250, 0, mainHwnd, NULL);
DestroyMenu(hMenu);
}
else
{
// TODO:
}
}
break;
}
case WM_DESTROY:
PostQuitMessage(0);
break;
case WM_CREATE:
{
gButton = CreateWindowW(L"button", L"Show/Hide menu", WS_VISIBLE | WS_CHILD, 100, 120, 120, 25, hWnd, (HMENU)BUTTON_ID, NULL, NULL);
break;
}
}
return DefWindowProcW(hWnd, message, wParam, lParam);
}
Maybe the right way is to always create menu when button is pressed and destroy it right after that? But in that case we should create menu all the time when pressing the button. I was trying to create the menu once and show it when we need it. Also the menu is not shown right now. Trying to figure out why.
Thanks in advance.
First, you can certainly avoid repeating the creation/destruction of your popup menu: just create it (once) on window creation (by handling the WM_CREATE message) and destroy it when handling WM_DESTROY. But note: you will need to make your hMenu a static variable, so that its value is maintained across multiple calls of your WndProc function.
As for hiding the menu programmatically – you can do this by sending the parent window the WM_CANCELMODE message, as suggested in this related question: How to CLOSE a context menu after a timeout?
You can keep a 'flag' variable (also must be static) to keep track of the current display status of the popup menu: if this is not shown, call TrackPopupMenu; if it is shown, send the WM_CANCELMODE message. You will also need to add the TPM_RETURNCMD flag in your call to TrackPopupMenu, so that you can reset the flag if/when the user selects a command from the menu.
Here's a version of your WndProc function that implements this approach:
LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
static HMENU hMenu; // Make "static" so we can reuse across calls
static bool hasMenu = false; // Flag to indicate current menu status
POINT point;
switch (msg) {
case WM_COMMAND:
switch (LOWORD(wParam)) {
case IDM_FILE_NEW:
case IDM_FILE_OPEN:
MessageBeep(MB_ICONINFORMATION);
break;
case IDM_FILE_QUIT:
SendMessage(hwnd, WM_CLOSE, 0, 0);
break;
}
break;
case WM_CREATE:
// Create the menu (once only) on window creation...
hMenu = CreatePopupMenu();
AppendMenuW(hMenu, MF_STRING, IDM_FILE_NEW, L"&New");
AppendMenuW(hMenu, MF_STRING, IDM_FILE_OPEN, L"&Open");
AppendMenuW(hMenu, MF_SEPARATOR, 0, NULL);
AppendMenuW(hMenu, MF_STRING, IDM_FILE_QUIT, L"&Quit");
hasMenu = false; // Reset here in case of multiple uses.
break;
case WM_RBUTTONUP:
if (!hasMenu) { // Only show menu if it's not already active...
hasMenu = true;
point.x = LOWORD(lParam);
point.y = HIWORD(lParam);
ClientToScreen(hwnd, &point);
// Add the "TPM_RETURNCMD" flag so we can reset "hasMenu" when a command is sselected (return non-zero):
BOOL cmd = TrackPopupMenu(hMenu, TPM_RIGHTBUTTON | TPM_RETURNCMD, point.x, point.y, 0, hwnd, NULL);
if (cmd) {
hasMenu = false;
SendMessage(hwnd, WM_COMMAND, cmd, 0); // Send the command (not done automatically with TPM_RETURNCMD)
}
}
else {
hasMenu = false;
SendMessage(hwnd, WM_CANCELMODE, 0, 0);
}
break;
case WM_DESTROY:
DestroyMenu(hMenu); // Destroy the menu.
PostQuitMessage(0);
break;
}
return DefWindowProcW(hwnd, msg, wParam, lParam);
}
Related
I've put two arrows in the code to identify the areas I will speak about
I'm trying to add a button to a C++ window thing, the Visual Studio automatically put a whole bunch of code I can't understand into the program for me, I'm coming from C# .NET Windows forms so this is already extremely confusing and now that I've had some kind of idea how to add the button I can't find the parent window and I've tried a whole bunch of different words I find around the place in the code and nothing is working, I don't even know if I'm in the right place, I don't even know what to look up, this entire bunch of code is 100% confusing, I understand none of it.
I just want a small little program that just works on all computers with or without .Net and supposedly I can have the libraries built into this exe that this will compile so I can run it on a PC with nothing installed supposedly. If there is a way to do that with C# I would love to hear about it, I made the program in C# and it doesn't work on my work laptop, just won't start and I'm assuming it's because the work laptop doesn't have .NET stuff on it.
// Stock Taking C.cpp : Defines the entry point for the application.
//
#include "framework.h"
#include "Stock Taking C.h"
#define MAX_LOADSTRING 100
// Global Variables:
HINSTANCE hInst; // current instance
WCHAR szTitle[MAX_LOADSTRING]; // The title bar text
WCHAR szWindowClass[MAX_LOADSTRING]; // the main window class name
// Forward declarations of functions included in this code module:
ATOM MyRegisterClass(HINSTANCE hInstance);
BOOL InitInstance(HINSTANCE, int);
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
INT_PTR CALLBACK About(HWND, UINT, WPARAM, LPARAM);
int APIENTRY wWinMain(_In_ HINSTANCE hInstance,
_In_opt_ HINSTANCE hPrevInstance,
_In_ LPWSTR lpCmdLine,
_In_ int nCmdShow)
{
UNREFERENCED_PARAMETER(hPrevInstance);
UNREFERENCED_PARAMETER(lpCmdLine);
// TODO: Place code here.
// Initialize global strings
LoadStringW(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING);
LoadStringW(hInstance, IDC_STOCKTAKINGC, szWindowClass, MAX_LOADSTRING);
MyRegisterClass(hInstance);
// Perform application initialization:
if (!InitInstance (hInstance, nCmdShow))
{
return FALSE;
}
HACCEL hAccelTable = LoadAccelerators(hInstance, MAKEINTRESOURCE(IDC_STOCKTAKINGC));
MSG msg;
// Main message loop:
while (GetMessage(&msg, nullptr, 0, 0))
{
if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
return (int) msg.wParam;
}
//
// FUNCTION: MyRegisterClass()
//
// PURPOSE: Registers the window class.
//
ATOM MyRegisterClass(HINSTANCE hInstance)
{
WNDCLASSEXW wcex;
wcex.cbSize = sizeof(WNDCLASSEX);
wcex.style = CS_HREDRAW | CS_VREDRAW;
wcex.lpfnWndProc = WndProc;
wcex.cbClsExtra = 0;
wcex.cbWndExtra = 0;
wcex.hInstance = hInstance;
wcex.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_STOCKTAKINGC));
wcex.hCursor = LoadCursor(nullptr, IDC_ARROW);
wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
wcex.lpszMenuName = MAKEINTRESOURCEW(IDC_STOCKTAKINGC);
wcex.lpszClassName = szWindowClass;
wcex.hIconSm = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_SMALL));
return RegisterClassExW(&wcex);
}
//
// FUNCTION: InitInstance(HINSTANCE, int)
//
// PURPOSE: Saves instance handle and creates main window
//
// COMMENTS:
//
// In this function, we save the instance handle in a global variable and
// create and display the main program window.
//
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);
if (!hWnd)
{
return FALSE;
}
ShowWindow(hWnd, nCmdShow);
UpdateWindow(hWnd);
return TRUE;
}
//
// FUNCTION: WndProc(HWND, UINT, WPARAM, LPARAM)
//
// PURPOSE: Processes messages for the main window.
//
// WM_COMMAND - process the application menu
// WM_PAINT - Paint the main window
// WM_DESTROY - post a quit message and return
//
//
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;
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_CREATE: {
This is me trying to add a button <----------- LOOK HERE
HWND hwndButton = CreateWindow(
L"BUTTON",
L"OK",
WS_TABSTOP | WS_VISIBLE | WS_CHILD | BS_DEFPUSHBUTTON,
10,
10,
100,
100,
m_WndProc, <-- this bit keeps being all like invalid and I can't find the parent bit
NULL,
(HINSTANCE)GetWindowLongPtr(m_hwnd, GWKO_HINSTANCE),
NULL);
break;
}
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
return 0;
}
// Message handler for about box.
INT_PTR CALLBACK About(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
UNREFERENCED_PARAMETER(lParam);
switch (message)
{
case WM_INITDIALOG:
return (INT_PTR)TRUE;
case WM_COMMAND:
if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL)
{
EndDialog(hDlg, LOWORD(wParam));
return (INT_PTR)TRUE;
}
break;
}
return (INT_PTR)FALSE;
}
WndProc() is the message procedure for the window that is created in InitInstance(). Thus, the HWND that is passed to WndProc() is that same window. So, since you are handling that window's WM_CREATE message, use that window as the parent for the button, eg:
HWND hwndButton = CreateWindow(
L"BUTTON",
L"OK",
WS_TABSTOP | WS_VISIBLE | WS_CHILD | BS_DEFPUSHBUTTON,
10,
10,
100,
100,
hWnd, // <-- parent window
NULL,
(HINSTANCE)GetWindowLongPtr(hWnd, GWLP_HINSTANCE), // <-- or the global hInst variable initialized by InitInstance()
NULL);
I am writing an app with the Win32 API. The layout basically consists of a left window that never changes and a right window that changes between two windows. To control this change, I am using ShowWindow(hWnd, SW_SHOW/SW_HIDE).
In the left window, there is a button that reveals one window and hides the other. I also have keyboard inputs that show and hide the window.
The keyboard functionality works fine until I click the button. Once the button is clicked, the keys stop working.
I thought at first this was because the button is a different window; however, when I try to catch the key input in the child window, nothing happens.
Here is a minimum reproducible example that has just a button and a child window. Note that clicking Shift/Tab causes the child window to appear/disappear. Clicking the button causes the child to disappear once, but it also seemingly disables the key inputs. Even clicking outside of the button and child does not restore them.
What could the problem be?
//libraries
#pragma comment ("lib", "Comctl32.lib")
#pragma comment ("lib", "d2d1.lib")
#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers
// Windows Header Files
#include <windows.h>
// C RunTime Header Files
#include <vector>
#include <string>
#define IDS_APP_TITLE 103
#define IDI_PRACTICE 107
#define IDI_SMALL 108
#define IDC_PRACTICE 109
#define IDC_BUTTON 101
#define MAX_LOADSTRING 100
// Global Variables:
HINSTANCE hInst; // current instance
WCHAR szTitle[MAX_LOADSTRING]; // The title bar text
WCHAR szWindowClass[MAX_LOADSTRING]; // the main window class name
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam);
LRESULT CALLBACK WndProcChild(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam);
ATOM MyRegisterClass(HINSTANCE hInstance);
HWND childHWND;
BOOL InitInstance(HINSTANCE hInstance, int nCmdShow);
int APIENTRY wWinMain(_In_ HINSTANCE hInstance,
_In_opt_ HINSTANCE hPrevInstance,
_In_ LPWSTR lpCmdLine,
_In_ int nCmdShow)
{
UNREFERENCED_PARAMETER(hPrevInstance);
UNREFERENCED_PARAMETER(lpCmdLine);
// Initialize global strings
LoadStringW(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING);
LoadStringW(hInstance, IDC_PRACTICE, szWindowClass, MAX_LOADSTRING);
MyRegisterClass(hInstance);
SetProcessDpiAwarenessContext(DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2);
// Perform application initialization:
if (!InitInstance(hInstance, nCmdShow))
{
return FALSE;
}
HACCEL hAccelTable = LoadAccelerators(hInstance, MAKEINTRESOURCE(IDC_PRACTICE));
MSG msg;
// Main message loop:
while (GetMessage(&msg, nullptr, 0, 0))
{
if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
return (int)msg.wParam;
}
LRESULT CALLBACK WndProcChild(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
return DefWindowProc(hWnd, message, wParam, lParam);
}
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message)
{
case WM_CREATE:
{
HWND button = CreateWindowW(L"button", L"Hide", WS_CHILD | WS_VISIBLE, 100, 100, 200, 100, hWnd, (HMENU)IDC_BUTTON, hInst, nullptr);
break;
}
case WM_COMMAND:
{
int wmld = LOWORD(wParam);
switch (wmld)
{
case IDC_BUTTON:
ShowWindow(childHWND, SW_HIDE);
break;
}
break;
}
case WM_DESTROY:
PostQuitMessage(0);
break;
case WM_KEYDOWN:
switch (wParam)
{
case VK_SHIFT:
ShowWindow(childHWND, SW_HIDE);
break;
case VK_TAB:
ShowWindow(childHWND, SW_SHOW);
break;
}
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
return 0;
}
ATOM MyRegisterClass(HINSTANCE hInstance)
{
WNDCLASSEXW wcex;
wcex.cbSize = sizeof(WNDCLASSEX);
wcex.style = CS_HREDRAW | CS_VREDRAW;
wcex.lpfnWndProc = WndProc;
wcex.cbClsExtra = 0;
wcex.cbWndExtra = 0;
wcex.hInstance = hInstance;
wcex.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_PRACTICE));
wcex.hCursor = LoadCursor(nullptr, IDC_ARROW);
wcex.hbrBackground = (HBRUSH)(GetStockObject(WHITE_BRUSH));
wcex.lpszMenuName = MAKEINTRESOURCEW(IDC_PRACTICE);
wcex.lpszClassName = L"Parent";
wcex.hIconSm = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_SMALL));
//Child wnd class
WNDCLASSEXW wcexChild;
wcexChild.cbSize = sizeof(WNDCLASSEX);
wcexChild.style = CS_HREDRAW | CS_VREDRAW;
wcexChild.lpfnWndProc = WndProcChild;
wcexChild.cbClsExtra = 0;
wcexChild.cbWndExtra = 0;
wcexChild.hInstance = hInstance;
wcexChild.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_PRACTICE));
wcexChild.hCursor = LoadCursor(nullptr, IDC_ARROW);
wcexChild.hbrBackground = (HBRUSH)(GetStockObject(BLACK_BRUSH));
wcexChild.lpszMenuName = MAKEINTRESOURCEW(IDC_PRACTICE);
wcexChild.lpszClassName = L"Child";
wcexChild.hIconSm = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_SMALL));
return RegisterClassExW(&wcexChild) && RegisterClassExW(&wcex);
}
BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
{
hInst = hInstance; // Store instance handle in our global variable
HWND hWnd = CreateWindowW(L"Parent", L"PARENT", WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, nullptr, nullptr, hInstance, nullptr);
childHWND = CreateWindowW(L"Child", szTitle, WS_CHILD | WS_VISIBLE,
500, 500, 500, 500, hWnd, nullptr, hInstance, nullptr);
if (!hWnd)
{
return FALSE;
}
ShowWindow(childHWND, nCmdShow);
UpdateWindow(childHWND);
ShowWindow(hWnd, nCmdShow);
UpdateWindow(hWnd);
return TRUE;
}
When you press a button, the focus will be on that button, and only the main window handles keyboard keystrokes.
You have a simple way to adjust the focused window by calling SetFocus:
case IDC_BUTTON:
ShowWindow(childHWND, SW_HIDE);
SetFocus(hWnd);
break;
Of course, as Remy said, you can subclass the button by SetWindowSubclass, and then process the keyboard message by processing the keyboard message, or modify the focus and other methods.
You are processing keyboard messages in your main window's WndProc, so your window will receive keyboard messages only while it has the input focus. When you click the button, it receives the input focus instead, thus subsequent keyboard messages will be sent to the button's WndProc instead. So, you will have to either subclass the button to intercept the keyboard messages sent to it, or else handle the keyboard messages directly in your message loop before dispatching them.
I'm trying to add some application controls into my Windows API code (Note: I am using Visual Studio) I am experiencing a problem where I try to add in a CreateWindowW() function that generates text and a field ("static" and "edit") and a menu at the same time. The menu works fine on its own ("Calculations"):
However, adding the CreateWindow() function "erases" the menu entirely but yields the CreateWindowW() outputs (also flickers a bit):
The code I have right now is this (the menu function and the CreateWindowW() functions are at the bottom):
#define MAX_LOADSTRING 100
#define FILE_MENU_DESTROY 1
#define FILE_MENU_ABOUT 2
// Global Variables:
HINSTANCE hInst; // current instance
WCHAR szTitle[MAX_LOADSTRING]; // The title bar text
WCHAR szWindowClass[MAX_LOADSTRING]; // the main window class name
// Forward declarations of functions included in this code module:
ATOM MyRegisterClass(HINSTANCE hInstance);
BOOL InitInstance(HINSTANCE, int);
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
//INT_PTR CALLBACK About(HWND, UINT, WPARAM, LPARAM);
//Custom Application Function Forwrd Declarations
void WinControls(HWND);
void WinMenu(HWND);
HMENU hMenu;
int APIENTRY wWinMain(_In_ HINSTANCE hInstance,
_In_opt_ HINSTANCE hPrevInstance,
_In_ LPWSTR lpCmdLine,
_In_ int nCmdShow)
{
UNREFERENCED_PARAMETER(hPrevInstance);
UNREFERENCED_PARAMETER(lpCmdLine);
// TODO: Place code here.
// Initialize global strings
LoadStringW(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING);
LoadStringW(hInstance, IDC_RANKTOOLADVANCED, szWindowClass, MAX_LOADSTRING);
MyRegisterClass(hInstance); //Generates an instance of a window class
// Perform application initialization:
if (!InitInstance (hInstance, nCmdShow))
{
return FALSE;
}
HACCEL hAccelTable = LoadAccelerators(hInstance, MAKEINTRESOURCE(IDC_RANKTOOLADVANCED));
MSG msg;
// Main message loop:
while (GetMessage(&msg, nullptr, 0, 0))
{
if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
return (int) msg.wParam;
}
//
// FUNCTION: MyRegisterClass()
//
// PURPOSE: Registers the window class.
//
ATOM MyRegisterClass(HINSTANCE hInstance)//Class properties of the window
{
WNDCLASSEXW wcex;
wcex.cbSize = sizeof(WNDCLASSEX);
wcex.style = CS_HREDRAW | CS_VREDRAW;
wcex.lpfnWndProc = WndProc; //assigns a window to the instance of the class
wcex.cbClsExtra = 0;
wcex.cbWndExtra = 0;
wcex.hInstance = hInstance; //creates an instance
wcex.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_RANKTOOLADVANCED));
wcex.hCursor = LoadCursor(nullptr, IDC_ARROW); //defines a type of cursor (arrow, help, cross, etc.)
wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
wcex.lpszMenuName = MAKEINTRESOURCEW(IDC_RANKTOOLADVANCED);
wcex.lpszClassName = szWindowClass;
wcex.hIconSm = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_SMALL));
return RegisterClassExW(&wcex);
}
//
// FUNCTION: InitInstance(HINSTANCE, int)
//
// PURPOSE: Saves instance handle and creates main window
//
// COMMENTS:
//
// In this function, we save the instance handle in a global variable and
// create and display the main program window.
//
BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
{//initializes instance of window class (invocation)
hInst = hInstance; // Store instance handle in our global variable
HWND hWnd = CreateWindowW(szWindowClass, L"test", WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, 0, 900, 600, nullptr, nullptr, hInstance, nullptr);
if (!hWnd)
{
return FALSE;
}
ShowWindow(hWnd, nCmdShow);
UpdateWindow(hWnd);
return TRUE;
}
//
// FUNCTION: WndProc(HWND, UINT, WPARAM, LPARAM)
//
// PURPOSE: Processes messages for the main window.
//
// WM_COMMAND - process the application menu
// WM_PAINT - Paint the main window
// WM_DESTROY - post a quit message and return
//
//
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;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
case FILE_MENU_NEW:
{
MessageBox(hWnd, L"task failed successfully", L"you done goofed", MB_OK | MB_ICONEXCLAMATION);
break;
}*/
case FILE_MENU_DESTROY:
{
DestroyWindow(hWnd);
break;
}
case FILE_MENU_ABOUT:
{
MessageBox(hWnd, L"about", L"About", MB_OK);
break;
}
break;
}
}
case WM_CREATE:
{
WinControls(hWnd);
WinMenu(hWnd);
break;
}/*
case WM_PAINT:
{
PAINTSTRUCT ps;
HDC hdc = BeginPaint(hWnd, &ps);
// TODO: Add any drawing code that uses hdc here...
TextOut(hdc, 10, 10, rekt, _tcslen(rekt));
TextOut(hdc, 10, 40, reverse, _tcslen(reverse));
EndPaint(hWnd, &ps);
break;
}*/
case WM_DESTROY:
{
PostQuitMessage(0);
break;
}
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
return 0;
}
void WinMenu(HWND hWnd) {
hMenu = CreateMenu();
HMENU hFileMenu = CreateMenu();
HMENU hSubMenu = CreateMenu();
HMENU hSubMenu2 = CreateMenu();
//XP Calculations
AppendMenuW(hSubMenu, MF_STRING, NULL, L"Rank -> XP");
AppendMenuW(hSubMenu, MF_STRING, NULL, L"XP -> Rank");
//Credit Calculations
AppendMenuW(hSubMenu2, MF_STRING, NULL, L"Rank -> Cred");
AppendMenuW(hSubMenu2, MF_STRING, NULL, L"Cred -> Rank");
AppendMenuW(hFileMenu, MF_POPUP, (UINT_PTR)hSubMenu, L"Points"); //option that popups submenu of hSubMenu
AppendMenuW(hFileMenu, MF_POPUP, (UINT_PTR)hSubMenu2, L"Credits"); //option that popups submenu of hSubMenu
AppendMenuW(hFileMenu, MF_SEPARATOR, NULL, NULL); // separator
AppendMenuW(hFileMenu, MF_STRING, FILE_MENU_ABOUT, L"About");
AppendMenuW(hFileMenu, MF_STRING, FILE_MENU_DESTROY, L"Exit"); // option
AppendMenuW(hMenu, MF_POPUP, (UINT_PTR)hFileMenu, L"Calculations"); //popups up submenu of hFileMenu
SetMenu(hWnd, hMenu);
}
void WinControls(HWND hWnd) {
CreateWindowW(L"Static", L"Enter text here: ", WS_VISIBLE | WS_CHILD | WS_BORDER | SS_CENTER, 400, 100, 100, 50, hWnd, NULL, NULL, NULL);
CreateWindowW(L"Edit", L"...", WS_VISIBLE | WS_CHILD, 400, 155, 100, 50, hWnd, NULL, NULL, NULL);
}
Please do note that the setup is the Visual Studio basic setup for the program.
Any help is appreciated!
I have done some debugging and figured out it was that the CreateWindowW() I used for the static and edit controls was conflicting with the definition of the window properties.
Since the window was defined by WNDCLASSEXW wcex, I just had to change the CreateWindowW() with CreateWindowExW().
Only new problem is that the static control (and the others) works but not the edit control, which kills the menu.
I am learning how to use WinAPI with C++, and am creating an application which at the moment just has a basic edit control for someone to enter their username.
void AddMenus(HWND hWnd)
{
hMenu = CreateMenu();
hSubMenu = CreateMenu();
AppendMenu(hMenu, MF_POPUP, (UINT_PTR)hSubMenu, L"File");
AppendMenu(hSubMenu, MF_STRING, FILE_MENU_EXIT, L"Exit");
SetMenu(hWnd, hMenu);
}
void AddControls(HWND hWnd)
{
hUNameS = CreateWindowW(L"static", L"Username: ", WS_VISIBLE | WS_CHILD | ES_CENTER,
100, 50, 100, 25, hWnd, NULL, NULL, NULL);
hUName = CreateWindowW(L"edit", L" ", WS_VISIBLE | WS_CHILD | WS_BORDER,
202, 50, 100, 25, hWnd, NULL, NULL, NULL);
}
When using the following block of code to create the window, both the controls and the menu don't appear.
case WM_CREATE:
AddControls(hWnd);
AddMenus(hWnd);
break;
If I comment out the AddControls, then the menu appears fine, but if I leave them both as shown, then the menu doesn't appear. Nothing changes if I swap the order of the function calls.
Both the menu and the controls appear if I set the second parameter of the edit control to NULL, but then I get a different problem, where any text I type in the control is invisible until I click it, and then disappears again when I continue to type. The only way I have found to fix this is by having a placeholder which then removes the menu.
TLDR: I can't get both the menu and controls to appear at the same time, and without the second parameter of the edit control being set, then text is invisible to start with.
The code of your first question:
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 FILE_MENU_DESTROY:
{
DestroyWindow(hWnd);
break;
}
case FILE_MENU_ABOUT:
{
MessageBox(hWnd, L"about", L"About", MB_OK);
break;
}
break; //this break will not break outside case WM_COMMAND, but only break outside the switch (wmId).
}
}
case WM_CREATE:
AddControls(hWnd);
AddMenus(hWnd);
break;
...
}
need to move the break; above the WM_CREATE to break WM_COMMAND case. Otherwise, when you createwindow and receive WM_COMMAND, WinMenu(AddMenus for this case) will be executed multiple times. I can reproduce with this code.
Modify to:
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 FILE_MENU_DESTROY:
{
DestroyWindow(hWnd);
break;
}
case FILE_MENU_ABOUT:
{
MessageBox(hWnd, L"about", L"About", MB_OK);
break;
}
}
}
break;
case WM_CREATE:
AddControls(hWnd);
AddMenus(hWnd);
break;
...
}
This works for me, and the whole project:
#define MAX_LOADSTRING 100
#define FILE_MENU_DESTROY 1
#define FILE_MENU_ABOUT 2
// Global Variables:
HINSTANCE hInst; // current instance
WCHAR szTitle[MAX_LOADSTRING]; // The title bar text
WCHAR szWindowClass[MAX_LOADSTRING]; // the main window class name
// Forward declarations of functions included in this code module:
ATOM MyRegisterClass(HINSTANCE hInstance);
BOOL InitInstance(HINSTANCE, int);
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
//INT_PTR CALLBACK About(HWND, UINT, WPARAM, LPARAM);
//Custom Application Function Forwrd Declarations
void WinControls(HWND);
void WinMenu(HWND);
HMENU hMenu;
int APIENTRY wWinMain(_In_ HINSTANCE hInstance,
_In_opt_ HINSTANCE hPrevInstance,
_In_ LPWSTR lpCmdLine,
_In_ int nCmdShow)
{
UNREFERENCED_PARAMETER(hPrevInstance);
UNREFERENCED_PARAMETER(lpCmdLine);
// TODO: Place code here.
// Initialize global strings
LoadStringW(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING);
LoadStringW(hInstance, IDC_RANKTOOLADVANCED, szWindowClass, MAX_LOADSTRING);
MyRegisterClass(hInstance); //Generates an instance of a window class
// Perform application initialization:
if (!InitInstance(hInstance, nCmdShow))
{
return FALSE;
}
HACCEL hAccelTable = LoadAccelerators(hInstance, MAKEINTRESOURCE(IDC_RANKTOOLADVANCED));
MSG msg;
// Main message loop:
while (GetMessage(&msg, nullptr, 0, 0))
{
if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
return (int)msg.wParam;
}
//
// FUNCTION: MyRegisterClass()
//
// PURPOSE: Registers the window class.
//
ATOM MyRegisterClass(HINSTANCE hInstance)//Class properties of the window
{
WNDCLASSEXW wcex;
wcex.cbSize = sizeof(WNDCLASSEX);
wcex.style = CS_HREDRAW | CS_VREDRAW;
wcex.lpfnWndProc = WndProc; //assigns a window to the instance of the class
wcex.cbClsExtra = 0;
wcex.cbWndExtra = 0;
wcex.hInstance = hInstance; //creates an instance
wcex.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_RANKTOOLADVANCED));
wcex.hCursor = LoadCursor(nullptr, IDC_ARROW); //defines a type of cursor (arrow, help, cross, etc.)
wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
wcex.lpszMenuName = MAKEINTRESOURCEW(IDC_RANKTOOLADVANCED);
wcex.lpszClassName = szWindowClass;
wcex.hIconSm = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_SMALL));
return RegisterClassExW(&wcex);
}
//
// FUNCTION: InitInstance(HINSTANCE, int)
//
// PURPOSE: Saves instance handle and creates main window
//
// COMMENTS:
//
// In this function, we save the instance handle in a global variable and
// create and display the main program window.
//
BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
{//initializes instance of window class (invocation)
hInst = hInstance; // Store instance handle in our global variable
HWND hWnd = CreateWindowW(szWindowClass, L"test", WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, 0, 900, 600, nullptr, nullptr, hInstance, nullptr);
if (!hWnd)
{
return FALSE;
}
ShowWindow(hWnd, nCmdShow);
UpdateWindow(hWnd);
return TRUE;
}
//
// FUNCTION: WndProc(HWND, UINT, WPARAM, LPARAM)
//
// PURPOSE: Processes messages for the main window.
//
// WM_COMMAND - process the application menu
// WM_PAINT - Paint the main window
// WM_DESTROY - post a quit message and return
//
//
void AddMenus(HWND hWnd)
{
hMenu = CreateMenu();
HMENU hSubMenu = CreateMenu();
AppendMenu(hMenu, MF_POPUP, (UINT_PTR)hSubMenu, L"File");
AppendMenu(hSubMenu, MF_STRING, FILE_MENU_DESTROY, L"Exit");
SetMenu(hWnd, hMenu);
}
void AddControls(HWND hWnd)
{
HWND hUNameS = CreateWindowW(L"static", L"Username: ", WS_VISIBLE | WS_CHILD | ES_CENTER,
100, 50, 100, 25, hWnd, NULL, NULL, NULL);
HWND hUName = CreateWindowW(L"edit", L" ", WS_VISIBLE | WS_CHILD | WS_BORDER,
202, 50, 100, 25, hWnd, NULL, NULL, NULL);
}
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;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
case FILE_MENU_NEW:
{
MessageBox(hWnd, L"task failed successfully", L"you done goofed", MB_OK | MB_ICONEXCLAMATION);
break;
}*/
case FILE_MENU_DESTROY:
{
DestroyWindow(hWnd);
break;
}
case FILE_MENU_ABOUT:
{
MessageBox(hWnd, L"about", L"About", MB_OK);
break;
}
}
}
break;
case WM_CREATE:
AddControls(hWnd);
AddMenus(hWnd);
break;
case WM_DESTROY:
{
PostQuitMessage(0);
break;
}
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
return 0;
}
I am new with programming Win32 applications. I have programmed a text box where the user can enter text. The problem is that I don't know how to get the input of the box into a string, which is necessary to process the input. For testing purposes, I tried to give out the entered text through the output text box, which I had to program anyway.
Googling, I found out that GetWindowTextA(hInput, input, length); should do the trick. However, I am not sure how to get the input into a variable using this method.
So, my question is, how do I get a text, entered by a user into a text box, into a string?
In case this does matter: I am not using the free version of Visual Studio, as I have free access to Microsoft software through my university. And at the moment I am using Visual Studio 2015 Ultimate Preview anyway. To answer the question in advance, this is NO homework or other work for my university, for a job or anything commercially. I have taught myself C++, which has become my favorite programming language, and I want to be able to program graphical interfaces with it.
Here is Visual Studio's standard code with some modifications, most notably the addition of two text boxes and a button (which does nothing at the moment and is of no importance for this question):
Includes, globals, forward declarations
#include "stdafx.h"
#include "WilliTeX.h"
#include <iostream>;
using namespace std;
#define MAX_LOADSTRING 100
//custom defines
#define TEXT_INPUT_BOX 1
#define TEXT_OUTPUT_BOX 2
#define BUTTON 3
HWND hInput;
HWND hOutput;
HWND hButton;
int length;
LPSTR input;
// Global Variables:
HINSTANCE hInst; // current instance
TCHAR szTitle[MAX_LOADSTRING]; // The title bar text
TCHAR szWindowClass[MAX_LOADSTRING]; // the main window class name
// Forward declarations of functions included in this code module:
ATOM MyRegisterClass(HINSTANCE hInstance);
BOOL InitInstance(HINSTANCE, int);
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
INT_PTR CALLBACK About(HWND, UINT, WPARAM, LPARAM);
_tWinMain
int APIENTRY _tWinMain(_In_ HINSTANCE hInstance,
_In_opt_ HINSTANCE hPrevInstance,
_In_ LPTSTR lpCmdLine,
_In_ int nCmdShow)
{
UNREFERENCED_PARAMETER(hPrevInstance);
UNREFERENCED_PARAMETER(lpCmdLine);
MSG msg;
HACCEL hAccelTable;
// Initialize global strings
LoadString(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING);
LoadString(hInstance, IDC_WILLITEX, szWindowClass, MAX_LOADSTRING);
MyRegisterClass(hInstance);
// Perform application initialization:
if (!InitInstance (hInstance, nCmdShow))
{
return FALSE;
}
hAccelTable = LoadAccelerators(hInstance, MAKEINTRESOURCE(IDC_WILLITEX));
// Main message loop:
while (GetMessage(&msg, NULL, 0, 0))
{
if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
return (int) msg.wParam;
}
MyRegisterClass
//
// FUNCTION: MyRegisterClass()
//
// PURPOSE: Registers the window class.
//
ATOM MyRegisterClass(HINSTANCE hInstance)
{
WNDCLASSEX wcex;
wcex.cbSize = sizeof(WNDCLASSEX);
wcex.style = CS_HREDRAW | CS_VREDRAW;
wcex.lpfnWndProc = WndProc;
wcex.cbClsExtra = 0;
wcex.cbWndExtra = 0;
wcex.hInstance = hInstance;
wcex.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_WILLITEX));
wcex.hCursor = LoadCursor(NULL, IDC_ARROW);
wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
wcex.lpszMenuName = MAKEINTRESOURCE(IDC_WILLITEX);
wcex.lpszClassName = szWindowClass;
wcex.hIconSm = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_SMALL));
return RegisterClassEx(&wcex);
}
Rest of Code
//
// FUNCTION: InitInstance(HINSTANCE, int)
//
// PURPOSE: Saves instance handle and creates main window
//
// COMMENTS:
//
// In this function, we save the instance handle in a global variable and
// create and display the main program window.
//
BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
{
HWND hWnd;
hInst = hInstance; // Store instance handle in our global variable
hWnd = CreateWindow(szWindowClass, szTitle, WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, NULL, NULL, hInstance, NULL);
if (!hWnd)
{
return FALSE;
}
ShowWindow(hWnd, nCmdShow);
UpdateWindow(hWnd);
return TRUE;
}
//
// FUNCTION: WndProc(HWND, UINT, WPARAM, LPARAM)
//
// PURPOSE: Processes messages for the main window.
//
// WM_COMMAND - process the application menu
// WM_PAINT - Paint the main window
// WM_DESTROY - post a quit message and return
//
//
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
int wmId, wmEvent;
PAINTSTRUCT ps;
HDC hdc;
switch (message)
{
case WM_CREATE:
{
//This is the input box, where the user enters the text
hInput = CreateWindowExA(WS_EX_CLIENTEDGE,
"EDIT",
"",
WS_CHILD | WS_VISIBLE | ES_MULTILINE | ES_AUTOVSCROLL | ES_AUTOHSCROLL,
50, //moving left/right the box
10, //moving up/down the box
1300, //length
350, //height
hWnd,
(HMENU)TEXT_INPUT_BOX,
GetModuleHandle(NULL),
NULL);
//This is the output text box, that will display the convertion
hInput = CreateWindowExA(WS_EX_CLIENTEDGE,
"Edit",
"test",
WS_CHILD | WS_VISIBLE | ES_MULTILINE | ES_AUTOVSCROLL | ES_AUTOHSCROLL,
50, //moving left/right the box
200, //moving up/down the box
1300, //length
450, //height
hWnd,
(HMENU)TEXT_INPUT_BOX,
GetModuleHandle(NULL),
NULL);
hButton = CreateWindowExA(NULL,
"BUTTON",
"OK",
WS_TABSTOP | WS_VISIBLE | WS_CHILD | BS_DEFPUSHBUTTON,
3, //moving left/right
10, //moving up/down
48, //length
50, //height
hWnd,
(HMENU) BUTTON,
GetModuleHandle(NULL),
NULL);
break;
}
case WM_COMMAND:
wmId = LOWORD(wParam);
wmEvent = HIWORD(wParam);
switch (LOWORD(wParam)) {
//refreshing the output box whenever the user is giving an input
case TEXT_INPUT_BOX:
{
length = GetWindowTextLengthA(hInput);
GetWindowTextA(hInput, input, length);
hInput = CreateWindowExA(WS_EX_CLIENTEDGE,
"Edit",
input,
WS_CHILD | WS_VISIBLE | ES_MULTILINE | ES_AUTOVSCROLL | ES_AUTOHSCROLL,
50, //moving left/right the box
200, //moving up/down the box
1300, //length
450, //height
hWnd,
(HMENU)TEXT_INPUT_BOX,
GetModuleHandle(NULL),
NULL);
break;
}
case BUTTON:
{
break;
}
}
// 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:
hdc = BeginPaint(hWnd, &ps);
// TODO: Add any drawing code here...
EndPaint(hWnd, &ps);
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
return 0;
}
// Message handler for about box.
INT_PTR CALLBACK About(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
UNREFERENCED_PARAMETER(lParam);
switch (message)
{
case WM_INITDIALOG:
return (INT_PTR)TRUE;
case WM_COMMAND:
if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL)
{
EndDialog(hDlg, LOWORD(wParam));
return (INT_PTR)TRUE;
}
break;
}
return (INT_PTR)FALSE;
}
P.S. I am aware that using namespace std; is bad coding practice but for this learning program I don't really care.
You seem to be creating the input text box (again) when you get a message from it. That doesn't make sense. ANd your GetWindowTextA call is using a variable 'input' that you have not defined. Allocate a character array for that variable.