WinApi CreateDialog returns error 715 - c++

I'm trying to get this simple windows dialog to spawn but as soon as I start it it reports "Error x715" which means hDialog was not correctly made in the int WINAPI WinMain() function. It compiles just fine.
I'm working in Visual Studio 2010 and it's a "Visual C++ -> Empty Project" project.
This is the full main.cpp file, which is the only file in the project:
#include "windows.h"
#define DLG_MAIN 200 // ID for dialog
#define DLG_ICON 30000 // IDs for icons
#define DLG_ICON_S 30000
#define IDC_QUIT 1011 // ID for "quit"-button
#define IDC_INFO 2000 // ID for "info"-button
#define ID_TIMER 1 // ID for timer
#define IDC_STATIC -1 // ID for all labels
#define TIMER_INTERRUPT 500 // timer msg interval in msec
HINSTANCE TheInstance = 0; // instance handle of this program
// Our main function
void lalala(HWND hwnd)
{
/*Doesn't do anything yet.*/
}
// Windows passes messages to application windows to indicate "something"
// needs to be done
BOOL CALLBACK DialogProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message)
{
case WM_INITDIALOG:
// set the time to generate a timer message (WM_TIMER)
SetTimer(hwnd, ID_TIMER, TIMER_INTERRUPT, NULL);
return TRUE;
case WM_TIMER:
// a timer msg was received so call our main function!
lalala(hwnd);
return TRUE;
case WM_COMMAND:
switch (LOWORD(wParam))
{
case IDC_INFO:
// the info button on the window was pressed
MessageBox(hwnd, "<show some info>", "The Jonas Brothers are way better than Nick Cave ever was.", MB_OK);
return TRUE;
case IDC_QUIT:
// the quit button on the window was pressed
PostQuitMessage(0);
return TRUE;
}
return TRUE;
case WM_DESTROY:
// this app is about to be closed so kill the timer
KillTimer(hwnd, ID_TIMER);
PostQuitMessage(0);
return TRUE;
case WM_CLOSE:
// destroy the window
DestroyWindow (hwnd);
return TRUE;
}
return FALSE;
}
int WINAPI WinMain(HINSTANCE hInst, HINSTANCE hPrevInst, char * cmdParam, int cmdShow)
{
TheInstance = hInst;
HWND hDialog = 0;
hDialog = CreateDialog (hInst, MAKEINTRESOURCE (DLG_MAIN), 0, (DLGPROC)DialogProc);
if (!hDialog)
{
char buf [100];
wsprintf (buf, "Error x%x", GetLastError ());
MessageBox (0, buf, "CreateDialog", MB_ICONEXCLAMATION | MB_OK);
return 1;
}
HICON hIcon = LoadIcon (TheInstance, MAKEINTRESOURCE (DLG_ICON));
SendMessage (hDialog, WM_SETICON, WPARAM (TRUE), LPARAM (hIcon));
hIcon = LoadIcon (TheInstance, MAKEINTRESOURCE (DLG_ICON_S));
SendMessage (hDialog, WM_SETICON, WPARAM (FALSE), LPARAM (hIcon));
MSG msg;
int status;
while ((status = GetMessage (&msg, 0, 0, 0)) != 0)
{
if (status == -1) return -1;
if (!IsDialogMessage (hDialog, &msg))
{
TranslateMessage ( &msg );
DispatchMessage ( &msg );
}
}
return msg.wParam;
}
Can anyone tell me why it fails at hDialog = CreateDialog (hInst, MAKEINTRESOURCE (DLG_MAIN), 0, (DLGPROC)DialogProc); ?

Error 0x715 is ERROR_RESOURCE_NAME_NOT_FOUND, which you get when it fails to find the dialog with the name that you supplied, in the resource section. Instead of declaring the macros for each resources, just use #include "resource.h"

Related

How to quit/break from windows message loop in console app and deferences from windows desktop app?

I want to break from the windows message loop. Just like C++ how to break message loop in windows hook . I came up with one solution, which works fine for Window Desktop Application, but fails for Console Application. How can this happen?
EDIT: I upload my codes to https://github.com/hellohawaii3/Experiment , clone it and then you can reproduce my problem quickly. Thanks!
1.Why I want to do so?
I am writing a console application. First, users are asked to set some options which determine app's behaviors. Then, the app start the message loop and monitor the input of the keyboard/mouse. Users may want to change the setting, so I want to enable users to press some hotkey, quit from the message loop and go back to the beginning of the application.
If you know any way to implement this function without worrying about breaking from the message loop, please tell me! However, I also want to know why my solution fails for console app and works well for desktop app. Thanks for your help!
2.What have I tried.
I use a bool variable 'recieve_quit'. When certain key is pressed on the keyboard, the variable is setting to True by the hook callback function. For every loop getting message, check the variable 'recieve_quit' first and quit when the variable is False.
3.Result of my experiment
For Console APP, The variable 'recieve_quit' is set correctly when certain key is pressed, however, the message loop continues.
For Windows Desktop APP with GUI, I can quit from the message loop as expected.
4.Experiment settings
I am using VS2019, C++, windows 10 home 1909.
I use dll inject to set hook for my console app.
5.My code
I provide toy example codes here, most of which is generated by Visual Studio automatically, do not bother if you think my codes are too loog.
(a)My console app
Console:
// Console.cpp
#include <iostream>
#include "dll_func.h"
#include <windows.h>
int main()
{
MSG msg;
HHOOK hhook_tmp2 = SetWindowsHookEx(WH_KEYBOARD_LL, HandleKeyboardEvent, hDllModule, 0);
while (recieve_quit == false)
{
if (GetMessage(&msg, nullptr, 0, 0)) {
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
MessageBox(NULL, TEXT("APP QUIT"), TEXT(" "), MB_OK);
}
(b)my dll containing hook function
My dll_func.h file, following the doc https://learn.microsoft.com/en-us/cpp/build/walkthrough-creating-and-using-a-dynamic-link-library-cpp?view=msvc-160
#pragma once
#ifdef DLL1_EXPORTS
#define DLLFUNC_API __declspec(dllexport)
#else
#define DLLFUNC_API __declspec(dllimport)
#endif
#include "framework.h"
extern "C" DLLFUNC_API bool recieve_quit;
extern "C" DLLFUNC_API LRESULT CALLBACK HandleKeyboardEvent(int nCode, WPARAM wParam, LPARAM lParam);// refer to https://stackoverflow.com/a/60913531/9758790
extern "C" DLLFUNC_API HMODULE hDllModule;//or whatever name you like
My dll_func.cpp file, containing the definition of hook function.
#include "pch.h"
#include <windows.h>
#include "dll_func.h"
bool recieve_quit = false;
LRESULT CALLBACK HandleKeyboardEvent(int nCode, WPARAM wParam, LPARAM lParam)
{
PKBDLLHOOKSTRUCT p = (PKBDLLHOOKSTRUCT)lParam;
if (wParam == WM_KEYDOWN) {
if (p->vkCode == VK_F8) {
recieve_quit = true;
}
}
return CallNextHookEx(NULL, nCode, wParam, lParam);
}
The dllmain.cpp is also modified a little after it is created by Visual Studio as suggested by https://stackoverflow.com/a/60913531/9758790 to get the hinstance of the dll for dll injection.
// dllmain.cpp
#include "pch.h"
#include "dll_func.h"
// refer to https://stackoverflow.com/a/60913531/9758790
HMODULE hDllModule;//or whatever name you like
BOOL APIENTRY DllMain( HMODULE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
)
{
hDllModule = hModule;
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
case DLL_THREAD_ATTACH:
case DLL_THREAD_DETACH:
case DLL_PROCESS_DETACH:
break;
}
return TRUE;
}
(c) My Desktop application.
I select 'Creating Windows Desktop Application' when created the solution with Visual Studio. Most of the codes is generated automatically by VS. The codes I added and modifed is surrounded by ***** in the codes.
// GUI.cpp
//
#include "framework.h"
#include "GUI.h"
#define MAX_LOADSTRING 100
HINSTANCE hInst;
WCHAR szTitle[MAX_LOADSTRING];
WCHAR szWindowClass[MAX_LOADSTRING];
// *********************** ADDED BY ME! ***********************
// same as dll_func.cpp
bool recieve_quit = false;
LRESULT CALLBACK HandleKeyboardEvent(int nCode, WPARAM wParam, LPARAM lParam)
{
//FILE* file;
//fopen_s(&file, "./temp0210222.txt", "a+");
//fprintf(file, "Function keyboard_hook called.n");
//fclose(file);
PKBDLLHOOKSTRUCT p = (PKBDLLHOOKSTRUCT)lParam;
if (wParam == WM_KEYDOWN) {
if (p->vkCode == VK_F8) {
recieve_quit = true;
}
}
return CallNextHookEx(NULL, nCode, wParam, lParam);
}
// *********************** END OF MY CODES ***********************
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);
// *********************** ADDED BY ME! ***********************
HHOOK hhook_tmp2 = SetWindowsHookEx(WH_KEYBOARD_LL, HandleKeyboardEvent, hInst, 0);
// *********************** END OF MY CODES ***********************
LoadStringW(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING);
LoadStringW(hInstance, IDC_GUI, szWindowClass, MAX_LOADSTRING);
MyRegisterClass(hInstance);
if (!InitInstance (hInstance, nCmdShow))
{
return FALSE;
}
HACCEL hAccelTable = LoadAccelerators(hInstance, MAKEINTRESOURCE(IDC_GUI));
MSG msg;
// main message loop:
// *********************** MODIFIED BY ME! ***********************
//while (GetMessage(&msg, nullptr, 0, 0))
//{
// if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg))
// {
// TranslateMessage(&msg);
// DispatchMessage(&msg);
// }
//}
while (recieve_quit == false)
{
if (GetMessage(&msg, nullptr, 0, 0)) {
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
MessageBox(NULL, TEXT("APP QUIT"), TEXT(" "), MB_OK);
// *********************** END OF MODIFICATION ***********************
return (int) msg.wParam;
}
//
// Function: MyRegisterClass()
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_GUI));
wcex.hCursor = LoadCursor(nullptr, IDC_ARROW);
wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
wcex.lpszMenuName = MAKEINTRESOURCEW(IDC_GUI);
wcex.lpszClassName = szWindowClass;
wcex.hIconSm = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_SMALL));
return RegisterClassExW(&wcex);
}
//
// Function: InitInstance(HINSTANCE, int)
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)
{
return FALSE;
}
ShowWindow(hWnd, nCmdShow);
UpdateWindow(hWnd);
return TRUE;
}
//
// Function: WndProc(HWND, UINT, WPARAM, LPARAM)
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message)
{
case WM_COMMAND:
{
int wmId = LOWORD(wParam);
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);
EndPaint(hWnd, &ps);
}
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
return 0;
}
// "About"
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;
}
(d)Tips for reproducing my results
For Console APP: Build a new console application solution named Console, and copy my codes to replace Console.cpp. Add a new project to this solution, select Create new project -> DLL, name it as Dll1. Create dll_func.h, dll_func.c, and copy my codes in. Do not forget to modify dllmain.cpp, too. Set the path of AdditionalIncludeDirectories, add dll1.lib to AdditionalDependencies. Set the path to dll and lib files too.
For Windows Desktop APP: Build a now Windows Desktop App solution, name it as GUI. Copy my codes in GUI.cpp and simply run it. Press key F8, the app will quit and pop up a message box as expected.
This post explains why console apps dont receive keyboard messages and how they can handle them:
does not go inside the Windows GetMessage loop on console application
In your console case execution enters GetMessage and never exits it. The hook receives a notification and correctly sets recieve_quit. Since the execution never exits GetMessage, recieve_quit is not checked.
This answer is about handling getting keypresses in a console app:
https://stackoverflow.com/a/6479673/4240951
In general - add a hidden window to your console app or check GetAsyncState of the needed key.
There is no need to set hooks when you have a message loop. You may check keypresses as follows:
while (recieve_quit == false)
{
if (GetMessage(&msg, nullptr, 0, 0)) {
if (msg.message == WM_KEYDOWN && msg.wParam == VK_F8)
recieve_quit = true;
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}

Win32Api Window Menu Activating issue

Running my program it runs and due to me having a menu with EXIT to Destroy the window it runs and immediately exits the window. Unsure how to fix my issue here on compiling the program to have it not run the WindowProcedure function and passing the argument EXITMENU resulting in the Window being destroyed.
*.CPP
#include <windows.h>
#define HELPMENU 1
#define HIGHSCROREMENU 2
#define EXITMENU 3
int WINAPI WinMain(HINSTANCE hInst, HINSTANCE hPrevInst, LPSTR args, int ncmdshow) {
WNDCLASS wc = { 0 }; // WNDCLASSW is a structure
LPCWSTR title = L"Window"; // Long Pointer Constant Wide (UTF-16) String
wc.hbrBackground = (HBRUSH)COLOR_WINDOW; // Background
wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
wc.hCursor = LoadCursor(NULL, IDC_HAND); // Sets Cursor
wc.hInstance = hInst; // Instance of window
wc.lpszClassName = L"windowClass"; // Class name
wc.lpfnWndProc = WindowProcedure; // Pointer to the function // Controller of window handle
if (!RegisterClassW(&wc)) { // Registers the window class
return -1;
}
// | binary combination value, posX, posY, Width, Height
// Creates the window
CreateWindow(wc.lpszClassName, title, WS_OVERLAPPEDWINDOW | WS_VISIBLE | WS_BORDER, 100, 100, 800, 600, NULL, NULL, NULL, NULL);
MSG msg = { 0 };
while (GetMessage(&msg, NULL, NULL, NULL) > 0) { // Keeps the window running
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return 0;
}
/* Event Paths */
LRESULT CALLBACK WindowProcedure(HWND hWnd, UINT msg, WPARAM wp, LPARAM lp) {
switch (msg) {
case WM_CREATE: // On window creation
AddControls(hWnd);
AddMenu(hWnd);
break;
case WM_LBUTTONDOWN: // Left Mouse button
break;
case WM_DESTROY: // Makes GetMessage Function return false, closing the window
PostQuitMessage(0);
return 0;
case EXITMENU:
DestroyWindow(hWnd); // This part of the code shouldn't run on creation
break;
default:
return DefWindowProc(hWnd, msg, wp, lp);
}
}
/* Creates menu */
void AddMenu(HWND hWnd) {
hMenu = CreateMenu(); // Creates menu object
// AppendMenu(Menu Instance, Usage Type, Argument, String info);
AppendMenu(hMenu, MF_STRING, HELPMENU, L"Help - F1");
AppendMenu(hMenu, MF_STRING, HIGHSCROREMENU, L"Highscores - F2"); // Menu Created
AppendMenu(hMenu, MF_STRING, EXITMENU, L"Exit - ESC");
// SetMenu(Window Handle , Menu Instance);
SetMenu(hWnd, hMenu); // Sets menu for window //
}
You are not handling the menu commands correctly in your WindowProcedure().
You have defined EXITMENU as 3, which is the same value as the WM_MOVE message. So, in your switch, you are destroying your window as soon as it receives a WM_MOVE message during window creation.
You need to instead handle the menu commands via the WM_COMMAND message, per the documentation:
About Menus: Messages Used With Menus
When the user chooses a command item from a menu, the system sends a WM_COMMAND message to the window procedure. The low-order word of the WM_COMMAND message's wParam parameter contains the identifier of the chosen item. The window procedure should examine the identifier and process the message accordingly.
Try this instead:
LRESULT CALLBACK WindowProcedure(HWND hWnd, UINT msg, WPARAM wp, LPARAM lp) {
switch (msg) {
...
case WM_COMMAND:
switch (wp) {
case HELPMENU: {
...
return 0;
}
case HIGHSCROREMENU: {
...
return 0;
}
case EXITMENU: {
DestroyWindow(hWnd);
return 0;
}
}
break;
}
...
}
return DefWindowProc(hWnd, msg, wp, lp);
}
UPDATE: That being said, consider having your EXITMENU handler use SendMessage(WM_CLOSE) instead of DestroyWindow(). If your app maintains data that should be saved when the app is closed by the user, you can add a WM_CLOSE handler to perform that action regardless of how the window is being closed (your exit menu, X close button, Alt-F4, etc). DefWindowProc() destroys a window when processing WM_CLOSE.
LRESULT CALLBACK WindowProcedure(HWND hWnd, UINT msg, WPARAM wp, LPARAM lp) {
switch (msg) {
...
case WM_CLOSE: {
if (data has been modified) {
prompt user to save data...
if (cancelled) {
return 0;
}
if (should save) {
save data ...
}
}
break;
}
case WM_COMMAND:
switch (wp) {
...
case EXITMENU: {
SendMessage(hWnd, WM_CLOSE, 0, 0);
return 0;
}
}
break;
}
...
}
return DefWindowProc(hWnd, msg, wp, lp);
}

win32 program for multiple windows

i am trying to write a program for multiple windows. In this program when user left click on one window it should a message which window was clicked. Here is my code:
#include<Windows.h>
// Store handles to the main window and application instance globally.
HWND ghFirstWnd =0;
HWND ghSecondWnd=0;
HWND ghThirdWnd=0;
HINSTANCE ghAppInst=0;
//========================================================================================
// WINDOW 1
// Step 1: Define and implement the window procedure.
LRESULT CALLBACK
WndProc1(HWND hWnd,UINT msg,WPARAM wParam, LPARAM lParam)
{
switch(msg)
{
// Handle left mouse button click message.
case WM_LBUTTONDOWN:
MessageBox(0,L"first window ",L"MSG",MB_OK);
return 0;
// Handle key down message.
case WM_KEYDOWN:
if(wParam==VK_ESCAPE)
if(MessageBox(hWnd,L"sure ??",L"confirmation",MB_YESNO)==IDYES)
DestroyWindow(ghFirstWnd);
return 0;
// Handle destroy window message.
case WM_DESTROY:
PostQuitMessage(0);
return 0;
}
return DefWindowProc(hWnd,msg,wParam,lParam);
}
//========================================================================================
// WINDOW 2
//========================================================================================
LRESULT CALLBACK
WndProc2(HWND hWnd,UINT msg, WPARAM wParam,LPARAM lParam)
{
switch(msg)
{
case WM_LBUTTONDOWN:
MessageBox(0,L"second window",L"msg",MB_OK);
return 0;
}
return DefWindowProc(hWnd,msg,wParam,lParam);
}
//========================================================================================
// WINDOW 3
//========================================================================================
LRESULT CALLBACK
WndProc3(HWND hWnd,UINT msg,WPARAM wParam,LPARAM lParam)
{
switch(msg)
{
case WM_LBUTTONDOWN:
MessageBox(0,L"third window",L"msg",MB_OK);
return 0;
}
return DefWindowProc(hWnd,msg,wParam,lParam);
}
// WinMain: Entry point for windows application.
int WINAPI
WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR cmdLine,int showCmd)
{
// Save handle to application instance.
ghAppInst=hInstance;
// Step 2: Fill out a WNDCLASS instance.
WNDCLASS wc1;
wc1.style =CS_HREDRAW|CS_VREDRAW;
wc1.lpfnWndProc =WndProc1;
wc1.cbClsExtra=0;
wc1.cbWndExtra=0;
wc1.hInstance=ghAppInst;
wc1.hIcon=::LoadIcon(0,IDI_APPLICATION);
wc1.hCursor=::LoadCursor(0,IDC_ARROW);
wc1.hbrBackground=(HBRUSH)::GetStockObject(WHITE_BRUSH);
wc1.lpszMenuName=0;
wc1.lpszClassName=L"first class";
// Window 2
WNDCLASS wc2;
wc2.style=CS_HREDRAW|CS_VREDRAW;
wc2.lpfnWndProc=WndProc2;
wc2.cbClsExtra=0;
wc2.cbWndExtra=0;
wc2.hInstance=ghAppInst;
wc2.hIcon=::LoadIcon(0,IDI_APPLICATION);
wc2.hCursor=::LoadCursor(0,IDC_ARROW);
wc2.hbrBackground=(HBRUSH)::GetStockObject(WHITE_BRUSH);
wc2.lpszMenuName=0;
wc2.lpszClassName=L"second class";
// Window 3
WNDCLASS wc3;
wc3.style=CS_HREDRAW|CS_VREDRAW;
wc3.lpfnWndProc=WndProc3;
wc3.cbClsExtra=0;
wc3.cbWndExtra=0;
wc3.hInstance=ghAppInst;
wc3.hIcon=::LoadIcon(0,IDI_APPLICATION);
wc3.hCursor=::LoadCursor(0,IDC_ARROW);
wc3.hbrBackground=(HBRUSH)::GetStockObject(WHITE_BRUSH);
wc3.lpszMenuName=0;
wc3.lpszClassName=L"third class";
// Step 3: Register with WNDCLASS instance with windows.
RegisterClass(&wc1);
RegisterClass(&wc2);
RegisterClass(&wc3);
// Step 4: Create the window, and save the handle in global window handle variable ghMainWnd.
ghFirstWnd=::CreateWindow(L"MyWndClassName",L"MyWindow1",WS_OVERLAPPEDWINDOW,0,0,50,50,0,0,ghAppInst,0);
ghSecondWnd=::CreateWindow(L"MyWndClassName",L"MyWindow2",WS_OVERLAPPEDWINDOW,50,0,50,50,0,0,ghAppInst,0);
ghThirdWnd=::CreateWindow(L"MyWndClassName",L"MyWindow3",WS_OVERLAPPEDWINDOW,100,0,50,50,0,0,ghAppInst,0);
if(ghFirstWnd==0)
{
::MessageBox(0,L"create window1-failed",0,0);
return false;
}
if(ghSecondWnd==0)
{
::MessageBox(0,L"create window2 failed",0,0);
return false;
}
if(ghThirdWnd==0)
{
::MessageBox(0,L"create window3 failed",0,0);
return false;
}
// Step 5: Show and update the window.
ShowWindow(ghFirstWnd,showCmd);
UpdateWindow(ghFirstWnd);
ShowWindow(ghSecondWnd,showCmd);
UpdateWindow(ghSecondWnd);
ShowWindow(ghThirdWnd,showCmd);
UpdateWindow(ghThirdWnd);
// Step 6: Enter the message loop and don't quit until a WM_QUIT message is received.
MSG msg;
ZeroMemory(&msg,sizeof(MSG));
while(GetMessage(&msg,0,0,0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
// Return exit code back to operating system.
return(int)msg.wParam;
}
problem is when i try to execute the code it just say create window1- failed!!
Cutting the program down, you can end up with something similar to this (I've made a couple changes to the code itself, but it should still work in C++03):
#include <Windows.h>
int WINAPI
WinMain(HINSTANCE hInstance, HINSTANCE, PSTR,int showCmd)
{
WNDCLASS wc1 = {};
wc1.style = CS_HREDRAW|CS_VREDRAW;
wc1.lpfnWndProc = DefWindowProc;
wc1.hInstance = hInstance;
wc1.hIcon = ::LoadIcon(0,IDI_APPLICATION);
wc1.hCursor = ::LoadCursor(0,IDC_ARROW);
wc1.hbrBackground = (HBRUSH)::GetStockObject(WHITE_BRUSH);
wc1.lpszClassName = L"first class";
RegisterClass(&wc1);
HWND ghFirstWnd = ::CreateWindow(L"MyWndClassName",L"MyWindow1",WS_OVERLAPPEDWINDOW,0,0,50,50,0,0,hInstance,0);
if(!ghFirstWnd)
{
::MessageBox(0,L"create window1-failed",0,0);
return 1;
}
return 0;
}
With this little code, it's much easier to spot your mistake. Your window class is named "first class", but in your CreateWindow call, you use a class named "MyWndClassName". The class cannot be found, so no window can be created using it.
On a side note, you have little error checking. One thing that would really beef it up is using GetLastError appropriately.
CreateWindow function returns handle to the windows or when fails then returns NULL.
So replace 'if(ghFirstWnd==0)" with "if(ghFirstWnd==NULL)" and check what happens. I'm not sure because I don't use Win32.
If only "create window1-failed" message is displaying maybe try to replace "if(ghSecondWnd==0)" with "if(ghSecondWnd==1)" and then two message boxes should appear.

Notify Icon Receives WM_LBUTTONDBLCLK But Not WM_CONTEXTMENU

I added a notification icon to my dialog based application, and it received WM_LBUTTONDBLCLK when the icon is double clicked on, but it is not receiving WM_CONTEXTMENU when the icon is right clicked or when the icon is highlighted with the keyboard and the context menu key is pressed. I based my usage of the notification icon on the example in the Windows 7.1 SDK Samples. So, I have no idea where I'm going wrong or why this isn't working.
Note: If I change WM_CONTEXTMENU to WM_RBUTTONUP, it receives the event, but the cursor coordinates are wrong.
/******************************************************************************/
/* Menu Resource */
/******************************************************************************/
LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL
IDR_TRAYMENU MENU
{
POPUP ""
{
MENUITEM "&Show Status Window", IDM__SHOW_STATUS_WINDOW
MENUITEM "&About", IDM__ABOUT
MENUITEM SEPARATOR
MENUITEM "&Exit", IDM__EXIT
}
}
/******************************************************************************/
/* WinMain() */
/******************************************************************************/
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow )
{
// ... code unrelated to icon
// Enable Visual Styles
InitCommonControls();
// create the main dialog
if( NULL == (hWnd=CreateDialog(hInstance,MAKEINTRESOURCE(IDD_MAINDLG),NULL,(DLGPROC)WndProc)) )
{
MessageBox( NULL, "Error creating the main dialog!", NULL, MB_OK | MB_ICONERROR );
return -1;
}
// ... code unrelated to icon
MSG msg;
while( GetMessage(&msg,NULL,0,0) && IsWindow(hWnd) )
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return 0;
}
/******************************************************************************/
/* WndProc() */
/******************************************************************************/
BOOL CALLBACK WndProc(HWND hWndDlg, UINT Message, WPARAM wParam, LPARAM lParam)
{
switch(Message)
{
case WM_INITDIALOG:
{
// ... code unrelated to icon
hIcon = (HICON)LoadImage( GetModuleHandle(NULL), MAKEINTRESOURCE(IDI_DDCMP), IMAGE_ICON, 16, 16, LR_DEFAULTSIZE );
// Setup the system tray icon
memset( &nid, 0, sizeof(NOTIFYICONDATA) );
nid.cbSize = sizeof(NOTIFYICONDATA);
nid.hWnd = hWndDlg;
nid.uID = 0xDDC;
nid.uFlags = NIF_ICON | NIF_MESSAGE | NIF_TIP | NIF_SHOWTIP;
nid.uCallbackMessage = WM_APP + 0xDDC;
nid.hIcon = hIcon;
strcpy( nid.szTip, "DDCMP Driver" );
Shell_NotifyIcon( NIM_ADD, &nid );
// ... code unrelated to icon
return true;
} break;
case WM_APP + 0xDDC:
{
switch( LOWORD(lParam) )
{
case WM_CONTEXTMENU:
{
MessageBox( hWndDlg, "This message box never shows up.", NULL, MB_OK | MB_SYSTEMMODAL );
HMENU hMenu = LoadMenu(GetModuleHandle(NULL),MAKEINTRESOURCE(IDR_TRAYMENU));
if( hMenu )
{
HMENU hSubMenu = GetSubMenu(hMenu,0);
if( hSubMenu )
{
SetForegroundWindow( hWndDlg );
POINT pt = { LOWORD(wParam), HIWORD(wParam) };
UINT uFlags = TPM_RIGHTBUTTON;
if( 0 != GetSystemMetrics(SM_MENUDROPALIGNMENT) )
uFlags |= TPM_RIGHTALIGN;
else
uFlags |= TPM_LEFTALIGN;
TrackPopupMenuEx( hSubMenu, uFlags, pt.x, pt.y, hWndDlg, NULL );
}
DestroyMenu( hMenu );
}
} break;
case WM_LBUTTONDBLCLK:
if( IsWindowVisible(hWndDlg) )
ShowWindow( hWnd, SW_HIDE );
else
ShowWindow( hWnd, SW_SHOW );
break;
}
return true;
} break;
case WM_CLOSE:
ShowWindow( hWndDlg, SW_HIDE );
break;
case WM_DESTROY:
case WM_QUIT:
{
Shell_NotifyIcon( NIM_DELETE, &nid );
// ... code unrelated to icon
return true;
} break;
}
return false;
}
This is the WndProc from the Windows 7.1 SDK Sample
LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
static HWND s_hwndFlyout = NULL;
static BOOL s_fCanShowFlyout = TRUE;
switch (message)
{
case WM_CREATE:
// add the notification icon
if (!AddNotificationIcon(hwnd))
{
MessageBox(hwnd,
L"Please read the ReadMe.txt file for troubleshooting",
L"Error adding icon", MB_OK);
return -1;
}
break;
case WM_COMMAND:
{
int const wmId = LOWORD(wParam);
// Parse the menu selections:
switch (wmId)
{
case IDM_LOWINK:
ShowLowInkBalloon();
break;
case IDM_NOINK:
ShowNoInkBalloon();
break;
case IDM_PRINTJOB:
ShowPrintJobBalloon();
break;
case IDM_OPTIONS:
// placeholder for an options dialog
MessageBox(hwnd, L"Display the options dialog here.", L"Options", MB_OK);
break;
case IDM_EXIT:
DestroyWindow(hwnd);
break;
case IDM_FLYOUT:
s_hwndFlyout = ShowFlyout(hwnd);
break;
default:
return DefWindowProc(hwnd, message, wParam, lParam);
}
}
break;
case WMAPP_NOTIFYCALLBACK:
switch (LOWORD(lParam))
{
case NIN_SELECT:
// for NOTIFYICON_VERSION_4 clients, NIN_SELECT is prerable to listening to mouse clicks and key presses
// directly.
if (IsWindowVisible(s_hwndFlyout))
{
HideFlyout(hwnd, s_hwndFlyout);
s_hwndFlyout = NULL;
s_fCanShowFlyout = FALSE;
}
else if (s_fCanShowFlyout)
{
s_hwndFlyout = ShowFlyout(hwnd);
}
break;
case NIN_BALLOONTIMEOUT:
RestoreTooltip();
break;
case NIN_BALLOONUSERCLICK:
RestoreTooltip();
// placeholder for the user clicking on the balloon.
MessageBox(hwnd, L"The user clicked on the balloon.", L"User click", MB_OK);
break;
//
//
// As you can very plainly see, the Windows SDK Sample ONLY used WM_CONTEXTMNEU
//
//
case WM_CONTEXTMENU:
{
POINT const pt = { LOWORD(wParam), HIWORD(wParam) };
ShowContextMenu(hwnd, pt);
}
break;
}
break;
case WMAPP_HIDEFLYOUT:
HideFlyout(hwnd, s_hwndFlyout);
s_hwndFlyout = NULL;
s_fCanShowFlyout = FALSE;
break;
case WM_TIMER:
if (wParam == HIDEFLYOUT_TIMER_ID)
{
// please see the comment in HideFlyout() for an explanation of this code.
KillTimer(hwnd, HIDEFLYOUT_TIMER_ID);
s_fCanShowFlyout = TRUE;
}
break;
case WM_DESTROY:
DeleteNotificationIcon();
PostQuitMessage(0);
break;
default:
return DefWindowProc(hwnd, message, wParam, lParam);
}
return 0;
}
I think you should try changing the uVersion member of the NOTIFYICONDATA structure to NOTIFYICON_VERSION_4, the documentation states that this members value will tell how the uCallbackMessage parameters will be interpreted when passed on to your callback function.
You can also have a look at this: Basic use of Shell_NotifyIcon in Win32
I did a bit of research and the following should work for you:
memset(&nid, 0, sizeof(NOTIFYICONDATA));
nid.cbSize = sizeof(NOTIFYICONDATA);
nid.hWnd = hWndDlg;
nid.uID = 0xDDC;
nid.uFlags = NIF_ICON | NIF_MESSAGE | NIF_TIP | NIF_SHOWTIP;
nid.uCallbackMessage = WM_APP + 0xDDC;
nid.hIcon = hIcon;
nid.uVersion = NOTIFYICON_VERSION_4;
strcpy(nid.szTip, "DDCMP Driver");
Shell_NotifyIcon(NIM_ADD, &nid);
Shell_NotifyIcon(NIM_SETVERSION, &nid);
NIM_SETVERSION (MSDN):
Shell32.dll version 5.0 and later only. Instructs the notification
area to behave according to the version number specified in the
uVersion member of the structure pointed to by lpdata. The version
number specifies which members are recognized.
The notify icon has changed behaviour over the years. For reasons of compatibility with pre-existing code, you must opt-in to the new behaviour. If you don't opt-in then you don't get sent WM_CONTEXTMENU messages. Instead you have to respond to WM_RBUTTONUP. Even if you invoke the context menu from the keyboard, the system still sends WM_RBUTTONUP. You have to obtain the cursor position, in order to know where to show the menu, by calling GetCursorPos.
You can opt in to the new behaviour (and WM_CONTEXTMENU) as described in the documentation, by calling Shell_NotifyIcon passing NIM_SETVERSION after the NIM_ADD call. Presumably the SDK sample you are looking at does this somewhere. My guess is that is what is missing from your code.
The key extract from the documentation is in the remarks section:
As of Windows 2000 (Shell32.dll version 5.0), Shell_NotifyIcon mouse and keyboard events are handled differently than in earlier Shell versions found on Microsoft Windows NT 4.0, Windows 95, and Windows 98. The differences include the following:
If a user selects a notify icon's shortcut menu with the keyboard, the Shell now sends the associated application a WM_CONTEXTMENU message. Earlier versions send WM_RBUTTONDOWN and WM_RBUTTONUP messages.
If a user selects a notify icon with the keyboard and activates it with the SPACEBAR or ENTER key, the version 5.0 Shell sends the associated application an NIN_KEYSELECT notification. Earlier versions send WM_RBUTTONDOWN and WM_RBUTTONUP messages.
If a user selects a notify icon with the mouse and activates it with the ENTER key, the Shell now sends the associated application an NIN_SELECT notification. Earlier versions send WM_RBUTTONDOWN and WM_RBUTTONUP messages.

Dialog created after first becomes unresponsive unless created first?

After creating the initial dialog box that works perfectly fine, I create another dialog box when the Join Game button is pressed. The dialog box is created and show successfully, however I am unable to type in the edit box or even press or exit the dialog. Does anyone understand how to fix this or why it happens? I made sure the dialog box itself was not the problem by creating and displaying it from the main loop in the application. It worked fine when I created it that way. So why does it error when being created from another dialog?
My code is below.
This code is for the DLGPROC function that each dialog uses.
#define WIN32_LEAN_AND_MEAN
#include "Windows.h"
#include ".\Controllers\Menu\MenuSystem.h"
#include ".\Controllers\Game Controller\GameManager.h"
#include ".\Controllers\Network\Network.h"
#include "resource.h"
#include "main.h"
using namespace std;
extern GameManager g;
extern bool men;
NET_Socket server;
extern HWND d;
HWND joinDlg;
char ip[64];
void JoinMenu(){
joinDlg = CreateDialog(g_hInstance, MAKEINTRESOURCE(IDD_GETADDRESSINFO), NULL, (DLGPROC)GameJoinDialogPrompt);
SetFocus(joinDlg);
// ShowWindow(joinDlg, SW_SHOW);
ShowWindow(d, SW_HIDE);
}
LRESULT CALLBACK GameJoinDialogPrompt(HWND Dialogwindow, UINT Message, WPARAM wParam, LPARAM lParam){
switch(Message){
case WM_COMMAND:{
switch(LOWORD(wParam)){
case IDCONNECT:{
GetDlgItemText(joinDlg, IDC_IP, ip, 63);
if(server.ConnectToServer(ip, 7890, NET_UDP) == NET_INVALID_SOCKET){
LogString("Failed to connect to server! IP: %s", ip);
MessageBox(NULL, "Failed to connect!", "Error", MB_OK);
ShowWindow(joinDlg, SW_SHOW);
break;
}
  }
LogString("Connected!");
break;
case IDCANCEL:
ShowWindow(d, SW_SHOW);
ShowWindow(joinDlg, SW_HIDE);
break;
}
break;
}
case WM_CLOSE:
PostQuitMessage(0);
break;
}
return 0;
}
LRESULT CALLBACK GameMainDialogPrompt(HWND Dialogwindow, UINT Message, WPARAM wParam, LPARAM lParam){
switch(Message){
case WM_PAINT:{
PAINTSTRUCT ps;
RECT rect;
HDC hdc = GetDC(Dialogwindow);
   hdc = BeginPaint(Dialogwindow, &ps);
GetClientRect (Dialogwindow, &rect);
FillRect(hdc, &rect, CreateSolidBrush(RGB(0, 0, 0)));
   EndPaint(Dialogwindow, &ps);
   break;
 }
case WM_COMMAND:{
switch(LOWORD(wParam)){
case IDC_HOST:
if(!NET_Initialize()){
break;
}
if(server.CreateServer(7890, NET_UDP) != 0){
MessageBox(NULL, "Failed to create server.", "Error!", MB_OK);
PostQuitMessage(0);
return -1;
}
ShowWindow(d, SW_HIDE);
break;
case IDC_JOIN:{
JoinMenu();
}
break;
case IDC_EXIT:
PostQuitMessage(0);
break;
default:
break;
}
break;
}
return 0;
}
}
I call the first dialog using the below code
void EnterMenu(){
// joinDlg = CreateDialog(g_hInstance, MAKEINTRESOURCE(IDD_GETADDRESSINFO), g_hWnd, (DLGPROC)GameJoinDialogPrompt);//
d = CreateDialog(g_hInstance, MAKEINTRESOURCE(IDD_SELECTMENU), g_hWnd, (DLGPROC)GameMainDialogPrompt);
}
The dialog boxes are not DISABLED by default, and they are visible by default. Everything is set to be active on creation and no code deactivates the items on the dialog or the dialog itself.
First, make sure you write the correct signature for the dialog procedures:
INT_PTR CALLBACK DialogProc(HWND hwndDlg, UINT uMsg,
WPARAM wParam, LPARAM lParam);
(See http://msdn.microsoft.com/en-us/library/ms645469(v=VS.85).aspx)
Your dialog procedures should therefore look like this:
INT_PTR CALLBACK GameJoinDialogPrompt(HWND Dialogwindow, UINT Message,
WPARAM wParam, LPARAM lParam)
{ /* ... */ }
INT_PTR CALLBACK GameMainDialogPrompt(HWND Dialogwindow, UINT Message,
WPARAM wParam, LPARAM lParam)
{ /* ... */ }
Then you should be able to do this without warnings or errors:
void EnterMenu()
{
d = CreateDialog(g_hInstance, MAKEINTRESOURCE(IDD_SELECTMENU),
g_hWnd, &GameMainDialogPrompt);
// Note the ampersand. Also note that no cast is needed. You should
// not need to use a cast to pass in the address of the function.
}
See http://blogs.msdn.com/oldnewthing/archive/2004/01/15/58973.aspx for why it's extremely important to get the function signature right.
That being said, your joinDlg should be a modal dialog box, since it is requesting information from the user:
void JoinMenu()
{
// DialogBox() creates a modal dialog box. It "blocks" its owner until
// it closes. On the other hand, CreateDialog() creates a non-modal
// dialog box.
joinDlg = DialogBox(g_hInstance, MAKEINTRESOURCE(IDD_GETADDRESSINFO),
d, &GameJoinDialogPrompt);
// Again, note the ampersand and the lack of a cast when passing in
// the address of the dialog procedure. Also, the main dialog box is
// serving as the owner of this dialog box.
}
Also note that dialog box procedures are different from windows procedures in that they return either TRUE or FALSE: TRUE if your dialog procedure processed the message, FALSE otherwise. (There are some "weird" messages that violate this rule, but you're not handling for those messages)
So your dialog procedures should look something like this:
INT_PTR CALLBACK GameMainDialogPrompt(HWND Dialogwindow, UINT Message,
WPARAM wParam, LPARAM lParam)
{
switch(Message)
{
case WM_PAINT:
/* Do painting */
return TRUE; // We handled the paint message
case WM_COMMAND:
switch(LOWORD(wParam))
{
case IDC_HOST:
/* Do command */
return TRUE; // We handled this particular command.
case IDC_JOIN:
/* Do command */
return TRUE; // We handled this particular command.
case IDC_EXIT:
/* Do command */
return TRUE; // We handled this particular command.
}
return FALSE; // The command wasn't handled.
}
return FALSE; // The message wasn't handled.
}
Dialog procedures do not call DefWindowProc() nor return 0!
In addiiton to the other excellent post you are also doing silly things like:
if(server.CreateServer(7890, NET_UDP) != 0){
MessageBox(NULL, "Failed to create server.", "Error!", MB_OK);
PostQuitMessage(0);
in a WM_COMMAND handler. This is a horrible piece of code as it stalls the dialogs modal loop without disabling it, or popping up the message box.
If you call a modal window from a different window (or dialogs) message proc you MUST disable the stalled window. Practically speaking, pass the windows HWND to the MessageBox call.
If all else fails, start fresh with this:
In resource.h:
#define IDD_DIALOG1 101
#define IDD_DIALOG2 102
#define ID_OPEN 1001
#define ID_MESSAGE 1002
In a resource file:
#include <winres.h>
#include "resource.h"
IDD_DIALOG1 DIALOGEX 0, 0, 300, 200
STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | DS_CENTER |
WS_POPUP | WS_CAPTION | WS_SYSMENU
CAPTION "Main Dialog"
FONT 8, "MS Shell Dlg", 400, 0, 0x1
BEGIN
DEFPUSHBUTTON "Open Secondary Dialog", ID_OPEN, 73 ,49, 133, 64
END
IDD_DIALOG2 DIALOGEX 0, 0, 200, 150
STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | DS_CENTER |
WS_POPUP | WS_CAPTION | WS_SYSMENU
CAPTION "Secondary Dialog"
FONT 8, "MS Shell Dlg", 400, 0, 0x1
BEGIN
DEFPUSHBUTTON "Message Box", ID_MESSAGE, 50, 49, 88, 50
END
In a source file:
#include <windows.h>
#include "resource.h"
INT_PTR CALLBACK SecondaryDialogProc(HWND hwnd, UINT msg,
WPARAM wParam, LPARAM lParam)
{
switch(msg)
{
case WM_INITDIALOG:
return TRUE;
case WM_COMMAND:
switch(LOWORD(wParam))
{
case ID_MESSAGE:
// Show a message box. Note that we're passing in our own HWND into
// the function, so we "block" this dialog box until the user
// dismisses this message box.
::MessageBox(hwnd, "Hello World!", "Greetings", MB_OK);
return TRUE;
}
return FALSE;
case WM_CLOSE:
// Because this is a modal dialog box (we used ::DialogBox()), we
// use ::EndDialog() instead of ::DestroyWindow() to destroy this
// dialog box.
::EndDialog(hwnd, 0);
return TRUE;
}
return FALSE;
}
INT_PTR CALLBACK MainDialogProc(HWND hwnd, UINT msg,
WPARAM wParam, LPARAM lParam)
{
switch(msg)
{
case WM_INITDIALOG:
return TRUE;
case WM_COMMAND:
switch(LOWORD(wParam))
{
case ID_OPEN:
// Open a modal dialog box. This will block the main dialog box
// until the secondary dialog box is closed.
::DialogBox(::GetModuleHandle(NULL),
MAKEINTRESOURCE(IDD_DIALOG2), hwnd, &SecondaryDialogProc);
return TRUE;
}
return FALSE;
case WM_CLOSE:
// We close this dialog box with ::DestroyWindow(). This causes the
// WM_DESTROY message to be sent.
::DestroyWindow(hwnd);
return TRUE;
case WM_DESTROY:
// Since the main dialog box is being destroyed, we quit
// the application.
::PostQuitMessage(0);
return TRUE;
}
return FALSE;
}
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
LPSTR lpCmdLine, int nShowCmd)
{
// Open a non-modal dialog box using ::CreateDialog().
HWND mainDlg = ::CreateDialog(::GetModuleHandle(NULL),
MAKEINTRESOURCE(IDD_DIALOG1), NULL, &MainDialogProc);
// The first ::ShowWindow() call should use nShowCmd.
::ShowWindow(mainDlg, nShowCmd);
MSG msg;
while (::GetMessage(&msg, NULL, 0, 0) > 0)
{
// So our main dialog behaves properly.
if(!::IsDialogMessage(mainDlg, &msg))
{
::TranslateMessage( & msg );
::DispatchMessage( & msg );
}
}
return msg.wParam;
}
Here, this is just the bare bones code to open up a main dialog, with a button to open another dialog. See if this works first, then add your business logic.