How to create a new window in a speparate thread? - c++

I'd like to create a new POPUP style window in a new thread. Here is the code I have so far.
#include <windows.h>
#include <gdiplus.h>
#include <stdio.h>
#include <tchar.h>
#include <thread>
#include <string>
#pragma comment(lib, "gdiplus.lib")
using namespace Gdiplus;
using namespace std;
const wchar_t g_szClassName[] = L"Skeleton";
const wchar_t g_szChildClassName[] = L"Child";
wchar_t msgbuf[100];
char msgbuf_ansi[100];
WNDCLASSEX wc;
struct MyStruct
{
WNDCLASSEX wc;
HWND hWnd;
HINSTANCE hInst;
int nCmdShow;
};
MyStruct g_myStruct;
LRESULT CALLBACK WndProcChild(HWND, UINT, WPARAM, LPARAM);
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);
}
int task1(MyStruct myStruct)
{
sprintf_s(msgbuf_ansi, ("thread\n"));
OutputDebugStringA(msgbuf_ansi);
HWND hwnd_child;
myStruct.wc.lpfnWndProc = WndProcChild;
myStruct.wc.lpszClassName = g_szChildClassName;
if (!RegisterClassEx(&myStruct.wc)) {
MessageBox(NULL, L"thread - Window Registration Failed!", L"Error!",
MB_ICONEXCLAMATION | MB_OK);
return 0;
}
hwnd_child = CreateWindowEx(0, g_szChildClassName, L"Child", WS_POPUP | WS_BORDER, 200, 0, 190, 110, myStruct.hWnd, 0, myStruct.hInst, 0);
swprintf_s(msgbuf, _T("THREAD - CHILD - hwnd: %02X\n"), (int)hwnd_child);
OutputDebugString(msgbuf);
if (hwnd_child == NULL) {
MessageBox(NULL, L"thread - Window Creation Failed!", L"Error!",
MB_ICONEXCLAMATION | MB_OK);
return 0;
}
SetWindowLong(hwnd_child, GWL_EXSTYLE, GetWindowLong(hwnd_child, GWL_EXSTYLE) | WS_EX_LAYERED);
SetLayeredWindowAttributes(hwnd_child, 0, 128, LWA_ALPHA);
ShowWindow(hwnd_child, myStruct.nCmdShow);
UpdateWindow(hwnd_child);
}
thread t1;
LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
switch (msg) {
//case WM_KEYDOWN:
case WM_CLOSE:
swprintf_s(msgbuf, _T("WM_CLOSE - PARENT \n"));
OutputDebugString(msgbuf);
if (MessageBox(hwnd, L"Really quit?", L"My application", MB_OKCANCEL) == IDOK)
{
DestroyWindow(hwnd);
}
return 0;
case WM_DESTROY:
swprintf_s(msgbuf, _T("WM_DESTROY - PARENT \n"));
OutputDebugString(msgbuf);
PostQuitMessage(0);
return 0;
case WM_CREATE: {
swprintf_s(msgbuf, _T("WM_CREATE - PARENT \n"));
OutputDebugString(msgbuf);
thread t1(task1, g_myStruct);
t1.join();
return 0;
}
default:
return DefWindowProc(hwnd, msg, wParam, lParam);
}
return 0;
}
int g_fMouseTracking = FALSE;
LRESULT CALLBACK WndProcChild(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
switch (msg) {
case WM_PAINT:
HDC hdc;
PAINTSTRUCT ps;
swprintf_s(msgbuf, _T("WM_PAINT - CHILD - hwnd: %02X\n"), (int)hwnd);
OutputDebugString(msgbuf);
hdc = BeginPaint(hwnd, &ps);
Example_DrawImage9(hdc);
EndPaint(hwnd, &ps);
return 0;
//case WM_KEYDOWN:
case WM_CREATE: {
swprintf_s(msgbuf, _T("WM_CREATE - CHILD \n"));
OutputDebugString(msgbuf);
return 0;
}
case WM_MOUSEMOVE:
swprintf_s(msgbuf, _T("WM_MOUSEMOVE - CHILD - hwnd: %02X\n"), (int)hwnd);
OutputDebugString(msgbuf);
if (!g_fMouseTracking)
{
// start tracking if we aren't already
TRACKMOUSEEVENT tme = {};
tme.cbSize = sizeof(TRACKMOUSEEVENT);
tme.dwFlags = TME_HOVER | TME_LEAVE;
tme.hwndTrack = hwnd;
tme.dwHoverTime = HOVER_DEFAULT;
g_fMouseTracking = TrackMouseEvent(&tme);
}
return 0;
case WM_MOUSELEAVE:
swprintf_s(msgbuf, _T("WM_MOUSELEAVE - CHILD - hwnd: %02X\n"), (int)hwnd);
OutputDebugString(msgbuf);
g_fMouseTracking = FALSE; // tracking now canceled
return 0;
case WM_CLOSE:
swprintf_s(msgbuf, _T("WM_CLOSE - CHILD \n"));
OutputDebugString(msgbuf);
/*if (MessageBox(hwnd, L"Really quit?", L"My application", MB_OKCANCEL) == IDOK)
{
DestroyWindow(hwnd);
}*/
return 0;
case WM_DESTROY:
swprintf_s(msgbuf, _T("WM_DESTROY - CHILD \n"));
OutputDebugString(msgbuf);
PostQuitMessage(0);
return 0;
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);
g_myStruct.wc = wc;
g_myStruct.hInst = hInstance;
g_myStruct.nCmdShow = nCmdShow;
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_BORDER, 0, 0, 190, 110, 0, 0, hInstance, 0);
g_myStruct.hWnd = hwnd;
if (hwnd == NULL) {
MessageBox(NULL, L"Parent Window Creation Failed!", L"Error!",
MB_ICONEXCLAMATION | MB_OK);
return 0;
}
swprintf_s(msgbuf, _T("MAIN - PARENT - hwnd: %02X\n"), (int)hwnd);
OutputDebugString(msgbuf);
SetWindowLong(hwnd, GWL_EXSTYLE, GetWindowLong(hwnd, GWL_EXSTYLE) | WS_EX_LAYERED);
SetLayeredWindowAttributes(hwnd, 0, 128, LWA_ALPHA);
ShowWindow(hwnd, nCmdShow);
UpdateWindow(hwnd);
while (GetMessage(&Msg, NULL, 0, 0) > 0) {
TranslateMessage(&Msg);
DispatchMessage(&Msg);
}
return Msg.wParam;
}
The problems is that as I've debugged the child window is indeed created but automatically/magically destroyed when the WndProcChild returns.
How to correct the code to have it run as expected (the child window stays open until the main is't destroyed)?

The thread own the window it had created and its message queue and therefore must provide an event loop. It's destroyed because in Win API ownership is treated in RAII way - when owner ceases to exist, so do the acquired objects.

Related

How to assign a window procedure to a child window?

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.

Win 32 GUI c++ .bmp The image is not showing

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

"DialogProc not declared" error shown while it is definitely declared

I am building my first GUI.
The following is my code.
#include <windows.h>
#include "resource.h"
const char g_szClassName[] = "home";
LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) {
switch(msg)
{
case WM_CLOSE:
DestroyWindow(hwnd);
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hwnd, msg, wParam, lParam);
}
return 0;
}
BOOL CALLBACK HomeDialogProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) {
switch (msg) {
case WM_COMMAND:
switch(LOWORD(wParam)){
case IDC_ABOUT:
CreateDialog(GetModuleHandle(NULL), MAKEINTRESOURCE(IDT_ABOUTDIALOG), hwnd, AboutDlgProc);
break;
}
break;
default:
return FALSE;
}
return FALSE;
}
BOOL CALLBACK AboutDlgProc(HWND hwnd, UINT Msg, WPARAM wParam, LPARAM lParam) {
switch(Msg)
{
case WM_COMMAND:
switch(LOWORD(wParam))
{
case IDC_DLG_EXIT:
DestroyWindow(hwnd);
break;
}
break;
default:
return FALSE;
}
return FALSE;
}
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) {
WNDCLASSEX wc;
HWND hwnd;
HWND dialog;
MSG Msg;
wc.cbSize = sizeof(WNDCLASSEX);
wc.style = 0;
wc.lpfnWndProc = WndProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = hInstance;
wc.hIcon = LoadIcon(GetModuleHandle(NULL), MAKEINTRESOURCE(IDI_MYICON));
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hbrBackground = (HBRUSH) (COLOR_WINDOW + 1);
wc.lpszMenuName = MAKEINTRESOURCE(IDR_MYMENU);
wc.lpszClassName = g_szClassName;
wc.hIconSm = (HICON) LoadImage(GetModuleHandle(NULL), MAKEINTRESOURCE(IDI_MYICON), IMAGE_ICON, 16, 16, 0);
if (!RegisterClassEx(&wc)) {
MessageBox(NULL, "Window Registration Failed!", "Error!", MB_ICONEXCLAMATION | MB_OK);
return 0;
}
hwnd = CreateWindowEx(
WS_EX_CLIENTEDGE,
g_szClassName,
"Have faith, we will succeed",
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, CW_USEDEFAULT, 800, 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);
dialog = CreateDialog(hInstance, MAKEINTRESOURCE(IDT_HOMEDIALOG), hwnd, HomeDialogProc);
if (!dialog) {
MessageBox(NULL, "Could not create Dialog", "CreateDialog", MB_ICONERROR);
return 1;
}
ShowWindow(dialog, nCmdShow);
UpdateWindow(dialog);
while (GetMessage(&Msg, NULL, 0, 0) > 0) {
TranslateMessage(&Msg);
DispatchMessage(&Msg);
}
return Msg.wParam;
}
I would like to briefly introduce what I want to do. I have embedded a dialog in the main window, so it "became part of the window". Then there is an About button in this dialog which is supposed to open the About dialog. I am really frustrated on the compilation error:
C:\Workspace_cpp\twodlg\main.cpp:28:97: error: 'AboutDlgProc' was not declared in this scope
CreateDialog(GetModuleHandle(NULL), MAKEINTRESOURCE(IDT_ABOUTDIALOG), hwnd, AboutDlgProc);
As you can see, I have clearly defined AboutDlgProc. On the other hand, from my readings, all the DialogProc functions do not necessarily need declaration to be functional. And finally, even after I explicitly put in the declaration statement, the error persists. Thank you so much for any help.
I solved it when I moved AboutDlgProc up. Answer was provided in comment by #MikeNakis, I am just closing the question.

ReOpen window from main window.

I have the main window open. It was created for me using visual studio. What I am attempting to do is have a main screen with 9 to 12 buttons. These buttons will then open up other windows. I am attempting with one button currently the "InventoryBtn". The inventory window open up and I am able to close it. The second time I try to open the window I get an error. It seems the window is already registered and cant be recreated. What am I doing incorrectly? I stepped thru it and aw that "Destroy:" is being called. The second time I try to show the inventory window the handle is uninitialized.
#include "stdafx.h"
#include "VehManager.h"
#include "M_Inventory.h"
#define MAX_LOADSTRING 100
#define InvWindowBtn 101
#define InvBtn 103
using namespace boost::gregorian;
HINSTANCE hInst;
WCHAR szTitle[MAX_LOADSTRING];
WCHAR szWindowClass[MAX_LOADSTRING];
ATOM MyRegisterClass(HINSTANCE hInstance);
BOOL InitInstance(HINSTANCE, int);
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
INT_PTR CALLBACK About(HWND, UINT, WPARAM, LPARAM);
LRESULT CALLBACK InvWindowProcess(HWND, UINT, WPARAM, LPARAM);
HWND handleforInvWin;
WNDCLASSEX wxInv;
void CreateInventoryWindow();
int APIENTRY wWinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE hPrevInstance, _In_ LPWSTR lpCmdLine, _In_ int nCmdShow)
{
UNREFERENCED_PARAMETER(hPrevInstance);
UNREFERENCED_PARAMETER(lpCmdLine);
LoadStringW(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING);
LoadStringW(hInstance, IDC_VEHMANAGER, szWindowClass, MAX_LOADSTRING);
MyRegisterClass(hInstance);
if (!InitInstance (hInstance, nCmdShow))
{
return FALSE;
}
HACCEL hAccelTable = LoadAccelerators(hInstance, MAKEINTRESOURCE (IDC_VEHMANAGER));
MSG msg;
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_VEHMANAGER));
wcex.hCursor = LoadCursor(nullptr, IDC_ARROW);
wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
wcex.lpszMenuName = MAKEINTRESOURCEW(IDC_VEHMANAGER);
wcex.lpszClassName = szWindowClass;
wcex.hIconSm = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_SMALL));
return RegisterClassExW(&wcex);
}
BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
{
hInst = hInstance;
HWND hWnd = CreateWindowW(szWindowClass, szTitle, WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, nullptr, nullptr, hInstance, nullptr);
if (!hWnd)
{
MessageBoxA(NULL, "Main window creation failed.", "904.VehicleManager", MB_OK | MB_ICONINFORMATION);
return FALSE;
}
ShowWindow(hWnd, nCmdShow);
UpdateWindow(hWnd);
return TRUE;
}
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
HFONT hfDefault;
switch (message)
{
case WM_CREATE:
{
HWND hInvBtn = CreateWindowEx(NULL, L"Button", L"INVENTORY", WS_TABSTOP | WS_VISIBLE | WS_CHILD | BS_DEFPUSHBUTTON,
50, 220, 100, 24, hWnd, (HMENU)InvBtn, GetModuleHandle(NULL), NULL);
if (hInvBtn == NULL)
MessageBoxA(hWnd, "Could not create inventory button", "904.VehcleManager", NULL);
hfDefault = (HFONT)GetStockObject(DEFAULT_GUI_FONT);
SendMessage(hInvBtn, WM_SETFONT, (WPARAM)hfDefault, MAKELPARAM(FALSE, 0));
}
case WM_COMMAND:
{
int wmId = LOWORD(wParam);
switch (wmId)
{
case InvBtn:
{
CreateInventoryWindow();
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_RBUTTONDOWN:
MessageBox(NULL, L"Right button mouse clicks not allowed.", L"904.VehicleManager", NULL);
break;
case WM_PAINT:
{
PAINTSTRUCT ps;
HDC hdc = BeginPaint(hWnd, &ps);
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;
}
void CreateInventoryWindow()
{
ZeroMemory(&wxInv, sizeof(WNDCLASSEX));
wxInv.cbClsExtra = NULL;
wxInv.cbSize = sizeof(WNDCLASSEX);
wxInv.cbWndExtra = NULL;
wxInv.hbrBackground = (HBRUSH)COLOR_WINDOW;
wxInv.hCursor = LoadCursor(NULL, IDC_ARROW);
wxInv.hIcon = NULL;
wxInv.hIconSm = NULL;
wxInv.hInstance = hInst;
wxInv.lpfnWndProc = (WNDPROC)InvWindowProcess;
wxInv.lpszClassName = L"Inventory";
wxInv.lpszMenuName = NULL;
wxInv.style = CS_HREDRAW | CS_VREDRAW;
if (!RegisterClassEx(&wxInv))
{
int nResult = GetLastError();
MessageBox(NULL, L"Inventory window class registration failed.", L"904.VehicleManager", MB_ICONEXCLAMATION);
return;
}
handleforInvWin = CreateWindowEx(NULL, wxInv.lpszClassName, L"Open Window 2", WS_OVERLAPPEDWINDOW,
200, 170, 640, 480, NULL, NULL, hInst, NULL);
if (!handleforInvWin)
{
MessageBox(NULL, L"Error with the inventory window handle.", L"904.VehManager", MB_ICONEXCLAMATION);
return;
}
ShowWindow(handleforInvWin, SW_SHOWNOACTIVATE);
UpdateWindow(handleforInvWin);
}
LRESULT CALLBACK InvWindowProcess(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
HFONT hfDefault;
switch (message)
{
case WM_CREATE:
{
HWND hInvBtn = CreateWindowEx(NULL, L"Button", L"Close", WS_TABSTOP | WS_VISIBLE | WS_CHILD | BS_DEFPUSHBUTTON,
50, 220, 100, 24, hwnd, (HMENU)InvBtn, GetModuleHandle(NULL), NULL);
if (hInvBtn == NULL)
MessageBoxA(hwnd, "Could not create inventory button", "904.VehcleManager", NULL);
hfDefault = (HFONT)GetStockObject(DEFAULT_GUI_FONT);
SendMessage(hInvBtn, WM_SETFONT, (WPARAM)hfDefault, MAKELPARAM(FALSE, 0));
break;
}
case WM_DESTROY:
{
break;
}
case WM_COMMAND:
case InvBtn:
{
DestroyWindow(hwnd);
break;
}
break;
}
return DefWindowProc(hwnd, message, wParam, lParam);
}

How do I create a second window within a callback procedure? Win32

I'm trying to create a second window if a dialog box from my first window returns a certain way. Unfortunately, if I call CreateWindowEx() from within the callback process of the first window, it doesn't recognise the second window's HWND. I also tried defining the first window in WinMain and making it visible within the callback, but it failed to recognise the HWND once again. Am I trying to do this wrong, or am I just missing something?
Edit:
#include "stdafx.h"
#include "md5.h"
#include "Coursework.h"
#include "accounts.h"
const char g_szClassName[] = "myMainWindow";
const char g_szLoggedInClass[] = "loggedInWindow";
#define IDC_CREATE_ACCOUNT 101
#define IDC_LOG_IN 110
MYSQL *conn;
static std::string strUserName;
BOOL CALLBACK CreateDlgProc(HWND hwnd, UINT Message, WPARAM wParam, LPARAM lParam)
{
switch(Message)
{
case WM_INITDIALOG:
return TRUE;
case WM_COMMAND:
switch (LOWORD(wParam))
{
case IDOK:
{
CreateAccount(hwnd);
}
break;
case IDCANCEL:
EndDialog(hwnd, IDCANCEL);
break;
}
default:
return FALSE;
}
}
BOOL CALLBACK LogInDlgProc(HWND hwnd, UINT Message, WPARAM wParam, LPARAM lParam)
{
switch(Message)
{
case WM_INITDIALOG:
return TRUE;
case WM_COMMAND:
switch(LOWORD(wParam))
{
case IDCANCEL:
EndDialog(hwnd, IDCANCEL);
break;
case IDOK:
{
if(bLogIn(hwnd, strUserName))
{
EndDialog(hwnd, IDOK);
}
}
break;
}
break;
default:
return FALSE;
}
}
LRESULT CALLBACK LoggedInProc (HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
switch(msg)
{
case WM_CLOSE:
DestroyWindow(hwnd);
break;
default:
return DefWindowProc(hwnd, msg, wParam, lParam);
}
return 0;
}
LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
switch(msg)
{
case WM_CLOSE:
PostQuitMessage(0);
break;
case WM_CREATE:
{
if (*mysql_error(conn)) //Checks if the connection succeeded, and
{ //exits the program if false.
MessageBox(hwnd, "No connection to the server could be established.\r\nPlease contact your administrator.", "Error", MB_ICONERROR);
exit(-1);
}
HWND hCreateButton = CreateWindowEx(NULL, "Button", "Create account", WS_TABSTOP|WS_VISIBLE|WS_CHILD|BS_DEFPUSHBUTTON, 500, 250, 120, 24, hwnd, (HMENU)IDC_CREATE_ACCOUNT, GetModuleHandle(NULL), NULL);
HWND hLogInButton = CreateWindowEx(NULL, "Button", "Log in", WS_TABSTOP|WS_VISIBLE|WS_CHILD|BS_DEFPUSHBUTTON, 500, 210, 120, 24, hwnd, (HMENU)IDC_LOG_IN, GetModuleHandle(NULL), NULL);
}
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
case WM_COMMAND:
switch (LOWORD(wParam))
{
case IDC_CREATE_ACCOUNT:
{
int ret = DialogBox(GetModuleHandle(NULL), MAKEINTRESOURCE(IDD_DIALOG1), hwnd, CreateDlgProc);
if (ret == -1)
{
MessageBox(hwnd, "Dialog failed to appear", "Error", MB_OK | MB_ICONINFORMATION);
}
}
break;
case IDC_LOG_IN:
{
int ret = DialogBox(GetModuleHandle(NULL), MAKEINTRESOURCE(IDD_DIALOG2), hwnd, LogInDlgProc);
if(ret == -1)
{
MessageBox(hwnd, "Dialog failed to appear", "Error", MB_OK | MB_ICONINFORMATION);
}
else if(ret == IDOK)
{
ShowWindow(hwnd, SW_HIDE);
}
}
}
break;
default:
return DefWindowProc(hwnd, msg, wParam, lParam);
}
return 0;
}
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
WNDCLASSEX wc;
WNDCLASSEX wc2;
HWND hwnd;
HWND hLoggedIn;
MSG Msg;
conn = mysql_init(NULL); //Initialises mySQL connection
mysql_real_connect(conn, "localhost", "root", "SecurityRules", "coursework", 0, NULL, 0);
//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);
//Registering the second Window Class
wc2.cbSize = sizeof(WNDCLASSEX);
wc2.style = 0;
wc2.lpfnWndProc = LoggedInProc;
wc2.cbClsExtra = 0;
wc2.cbWndExtra = 0;
wc2.hInstance = hInstance;
wc2.hIcon = LoadIcon(NULL, IDI_APPLICATION);
wc2.hCursor = LoadCursor(NULL, IDC_ARROW);
wc2.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
wc2.lpszMenuName = NULL;
wc2.lpszClassName = g_szLoggedInClass;
wc2.hIconSm = LoadIcon(NULL, IDI_APPLICATION);
if(!RegisterClassEx(&wc))
{
MessageBox(NULL, "Window Registration Failed!\r\nContact your administrator.", "Error!", MB_ICONEXCLAMATION | MB_OK);
return 0;
}
if(!RegisterClassEx(&wc2))
{
MessageBox(NULL, "Window Registration failed!\r\nContact your administrator.", "Error!", MB_ICONEXCLAMATION|MB_OK);
return 0;
}
//Creating the main Window
hwnd = CreateWindowEx(WS_EX_CLIENTEDGE, g_szClassName, "Coursework", WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, 1080, 640, NULL, NULL, hInstance, NULL);
hLoggedIn = CreateWindowEx(WS_EX_CLIENTEDGE, g_szLoggedInClass, "Coursework", WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, 1080, 640, NULL, NULL, hInstance, NULL);
if(hwnd == NULL)
{
MessageBox(NULL, "Window Creation Failed!\r\nContact your adminstrator.", "Error!", MB_ICONEXCLAMATION | MB_OK);
return 0;
}
ShowWindow(hwnd, nCmdShow);
UpdateWindow(hwnd);
// The Message Loop
while(GetMessage(&Msg, NULL, 0, 0) > 0)
{
TranslateMessage(&Msg);
DispatchMessage(&Msg);
}
mysql_close(conn);
return Msg.wParam;
}
}
Edit 2:
Intellisense (I'm in Visual Studio) states that 'identifier hLoggedIn is undefined', as well as nCmdShow.