Windows API CreateDialog: Modeless Dialog just not show up - windows

I really can't figure out how to make a modeless dialog box even after googling extensively.
What I want to do is to trigger a dialog box by pressing a button on main window.
(So let me put the whole stuff here. I haven't put the whole stuff up before lest it is too messy to read.)
My code is as followed:
#include "main.h"
#include "resource.h"
#include <tchar.h>
INT_PTR CALLBACK AboutDlgProc(HWND hwnd, UINT Message, WPARAM wParam, LPARAM lParam)
{
switch(Message)
{
case WM_INITDIALOG:
return TRUE;
break;
case WM_COMMAND:
switch(LOWORD(wParam))
{
case IDOK:
EndDialog(hwnd, IDOK);
break;
case IDCANCEL:
EndDialog(hwnd, IDCANCEL);
break;
}
break;
default:
return FALSE;
}
return TRUE;
}
LRESULT CALLBACK MainWinProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
switch(uMsg)
{
case WM_COMMAND:
switch(LOWORD(wParam))
{
case ID_FILE_EXIT:
SendMessage(hwnd, WM_CLOSE, NULL, NULL);
break;
case LAUNCH_CONSOLE:
HWND aDiag = CreateDialog((HINSTANCE) GetWindowLong(hwnd, GWL_HINSTANCE), MAKEINTRESOURCE(IDD_DIALOG1), hwnd, (DLGPROC) AboutDlgProc);
if(aDiag == NULL)
{
MessageBox(hwnd, TEXT("Error"), TEXT("Error"), MB_OK);
DWORD dwLE = GetLastError();
TCHAR szLE[16];
_ltoa_s(dwLE, szLE, 10 );
MessageBox(hwnd, szLE, TEXT("Error"), MB_OK);
}
ShowWindow(aDiag, SW_SHOW);
break;
}
break;
case WM_CLOSE:
DestroyWindow(hwnd);
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
break;
}
return DefWindowProc(hwnd, uMsg, wParam, lParam);
}
int CALLBACK WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
WNDCLASS mainWindowClass = {};
mainWindowClass.style = CS_HREDRAW | CS_VREDRAW;
mainWindowClass.lpfnWndProc = MainWinProc;
mainWindowClass.hInstance = hInstance;
mainWindowClass.hbrBackground = (HBRUSH) COLOR_WINDOW;
mainWindowClass.lpszMenuName = MAKEINTRESOURCE(IDR_MENU1);
mainWindowClass.lpszClassName = TEXT("MainWindow");
RegisterClass(&mainWindowClass);
LONG units = GetDialogBaseUnits();
HWND aWindow = CreateWindow(TEXT("MainWindow"), TEXT("Briancheung"), WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, hInstance, NULL);
HWND aButton = CreateWindow("BUTTON", TEXT("Try"), WS_VISIBLE | WS_CHILD | BS_DEFPUSHBUTTON, 100, 100, 50, 50, aWindow, (HMENU) LAUNCH_CONSOLE, hInstance, NULL);
ShowWindow(aWindow, SW_NORMAL);
MSG aMsg = {};
while(GetMessage(&aMsg, NULL, 0, 0))
{
TranslateMessage(&aMsg);
DispatchMessage(&aMsg);
}
return 0;
}
My resource template is VS2012 generated:
// Microsoft Visual C++ generated resource script.
//
#include "resource.h"
#define APSTUDIO_READONLY_SYMBOLS
/////////////////////////////////////////////////////////////////////////////
//
// Generated from the TEXTINCLUDE 2 resource.
//
#include "afxres.h"
/////////////////////////////////////////////////////////////////////////////
#undef APSTUDIO_READONLY_SYMBOLS
/////////////////////////////////////////////////////////////////////////////
// Chinese (Simplified, PRC) resources
#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_CHS)
LANGUAGE LANG_CHINESE, SUBLANG_CHINESE_SIMPLIFIED
#ifdef APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// TEXTINCLUDE
//
1 TEXTINCLUDE
BEGIN
"resource.h\0"
END
2 TEXTINCLUDE
BEGIN
"#include ""afxres.h""\r\n"
"\0"
END
3 TEXTINCLUDE
BEGIN
"\r\n"
"\0"
END
#endif // APSTUDIO_INVOKED
#endif // Chinese (Simplified, PRC) resources
/////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////
// Chinese (Traditional, Hong Kong S.A.R.) resources
#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ZHH)
LANGUAGE LANG_CHINESE, SUBLANG_CHINESE_HONGKONG
/////////////////////////////////////////////////////////////////////////////
//
// Menu
//
IDR_MENU1 MENU
BEGIN
POPUP "File"
BEGIN
MENUITEM "New", ID_FILE_NEW40001
MENUITEM "Open", ID_FILE_OPEN40002
MENUITEM SEPARATOR
MENUITEM "Save", ID_FILE_SAVE40003
MENUITEM "Save As", ID_FILE_SAVEAS
MENUITEM SEPARATOR
MENUITEM "Exit", ID_FILE_EXIT
END
POPUP "View"
BEGIN
MENUITEM "Properties", ID_VIEW_PROPERTIES
END
POPUP "Help"
BEGIN
MENUITEM "About", ID_HELP_ABOUT
END
END
/////////////////////////////////////////////////////////////////////////////
//
// Dialog
//
IDD_DIALOG1 DIALOGEX 0, 0, 309, 90
STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | WS_SYSMENU
CAPTION "Dialog"
FONT 8, "MS Shell Dlg", 400, 0, 0x1
BEGIN
DEFPUSHBUTTON "OK",IDOK,198,69,50,14
PUSHBUTTON "Cancel",IDCANCEL,252,69,50,14
CONTROL "",IDC_OCX1,"{6BF52A52-394A-11D3-B153-00C04F79FAA6}",WS_TABSTOP,23,24,259,25
END
/////////////////////////////////////////////////////////////////////////////
//
// DESIGNINFO
//
#ifdef APSTUDIO_INVOKED
GUIDELINES DESIGNINFO
BEGIN
IDD_DIALOG1, DIALOG
BEGIN
LEFTMARGIN, 7
RIGHTMARGIN, 302
TOPMARGIN, 7
BOTTOMMARGIN, 83
END
END
#endif // APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// Dialog Info
//
IDD_DIALOG1 DLGINIT
BEGIN
IDC_OCX1, 0x376, 166, 0
0x0000, 0x0000, 0x0300, 0x0000, 0x0008, 0x0000, 0x0000, 0x0005, 0x0000,
0x0000, 0x0000, 0x3ff0, 0x0003, 0x0000, 0x0000, 0x0005, 0x0000, 0x0000,
0x0000, 0x0000, 0x0008, 0x0002, 0x0000, 0x0000, 0x0003, 0x0001, 0x0000,
0x000b, 0xffff, 0x0003, 0x0000, 0x0000, 0x000b, 0xffff, 0x0008, 0x0002,
0x0000, 0x0000, 0x0003, 0x0032, 0x0000, 0x000b, 0x0000, 0x0008, 0x000a,
0x0000, 0x0066, 0x0075, 0x006c, 0x006c, 0x0000, 0x000b, 0x0000, 0x000b,
0x0000, 0x000b, 0xffff, 0x000b, 0xffff, 0x000b, 0x0000, 0x0008, 0x0002,
0x0000, 0x0000, 0x0008, 0x0002, 0x0000, 0x0000, 0x0008, 0x0002, 0x0000,
0x0000, 0x0008, 0x0002, 0x0000, 0x0000, 0x000b, 0x0000, 0x2834, 0x0000,
0x043d, 0x0000,
0
END
#endif // Chinese (Traditional, Hong Kong S.A.R.) resources
/////////////////////////////////////////////////////////////////////////////
#ifndef APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// Generated from the TEXTINCLUDE 3 resource.
//
/////////////////////////////////////////////////////////////////////////////
#endif // not APSTUDIO_INVOKED
Everything seems okay. The program compiles. GetLastError is 0. But the dialog just would not show up. The main window closes after clicking the Try button.
Really thank you for your comment and help. I rarely ask questions in here because most of the problems can be solved by Googling and tinkering. But this one is really difficult. I believe it should be very easy since making a dialog is one of the most basic things in GUI.
My programming experience mainly focuses on Java previously. I want to lament that Windows C is much harder since it seems that not much warning comes from compiler or IDE.

Enclose the above part of your code in { } and tell us what happens.
You need to modify your WM_COMMAND code like this:
case WM_COMMAND:
switch(LOWORD(wParam))
{
case LAUNCH_CONSOLE:
{
HWND aDiag = CreateDialog( (HINSTANCE) GetWindowLong(hwnd, GWL_HINSTANCE),
MAKEINTRESOURCE(IDD_DIALOG1),
hwnd,
(DLGPROC) AboutDlgProc );
if(aDiag == NULL)
{
MessageBox(hwnd, TEXT("Error"), TEXT("Error"), MB_OK);
DWORD dwLE = GetLastError();
TCHAR szLE[16];
_ltoa_s(dwLE, szLE, 10 );
MessageBox(hwnd, szLE, TEXT("Error"), MB_OK);
}
ShowWindow(aDiag, SW_SHOW);
break;
}
// other commands
Since you have asked a small demo application to demonstrate creation of a dialog on button click, here is the code you can copy/paste on empty .cpp file. Just create your own dialog box in .rc editor:
#include "resource.h"
#include <windows.h>
INT_PTR CALLBACK AboutDlgProc(HWND hwnd, UINT Message, WPARAM wParam, LPARAM lParam)
{
switch(Message)
{
case WM_INITDIALOG:
return TRUE;
case WM_COMMAND:
switch(LOWORD(wParam))
{
case IDOK:
EndDialog(hwnd, IDOK);
break;
case IDCANCEL:
EndDialog(hwnd, IDCANCEL);
break;
}
break;
default:
return FALSE;
}
return TRUE;
}
LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
switch(msg)
{
case WM_CREATE:
CreateWindowEx( 0, L"Button",
L"Click me!",
WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON,
50, 20, 100, 50,
hwnd, (HMENU)8000,
GetModuleHandle(NULL), 0 );
return (LRESULT)0;
case WM_COMMAND:
switch( LOWORD(wParam) )
{
case 8000:
{
HWND hDlg = CreateDialog( GetModuleHandle(NULL),
MAKEINTRESOURCE(IDD_DIALOG1),
hwnd,
AboutDlgProc );
ShowWindow( hDlg, SW_SHOW );
}
break;
default:
break;
}
return (LRESULT)0;
case WM_CLOSE:
DestroyWindow(hwnd);
return (LRESULT)0;
case WM_DESTROY:
PostQuitMessage(0);
return (LRESULT)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;
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 = L"Main_Window";
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(
WS_EX_CLIENTEDGE,
L"Main_Window",
L"Test application",
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, CW_USEDEFAULT, 240, 120,
NULL, NULL, hInstance, NULL);
if(hwnd == NULL)
{
MessageBox(NULL, L"Window Creation Failed!", L"Error!",
MB_ICONEXCLAMATION | MB_OK);
return 0;
}
ShowWindow(hwnd, nCmdShow);
UpdateWindow(hwnd);
while(GetMessage(&Msg, NULL, 0, 0) > 0)
{
TranslateMessage(&Msg);
DispatchMessage(&Msg);
}
return Msg.wParam;
}
EDIT-ADDED CODE FOR RESOURCE FILES:
Resource.h :
//{{NO_DEPENDENCIES}}
// Microsoft Visual C++ generated include file.
// Used by resource.rc
//
#define IDD_DIALOG1 101
// Next default values for new objects
//
#ifdef APSTUDIO_INVOKED
#ifndef APSTUDIO_READONLY_SYMBOLS
#define _APS_NEXT_RESOURCE_VALUE 102
#define _APS_NEXT_COMMAND_VALUE 40001
#define _APS_NEXT_CONTROL_VALUE 1001
#define _APS_NEXT_SYMED_VALUE 101
#endif
#endif
.rc file:
// Microsoft Visual C++ generated resource script.
//
#include "resource.h"
#define APSTUDIO_READONLY_SYMBOLS
/////////////////////////////////////////////////////////////////////////////
//
// Generated from the TEXTINCLUDE 2 resource.
//
#include "afxres.h"
/////////////////////////////////////////////////////////////////////////////
#undef APSTUDIO_READONLY_SYMBOLS
/////////////////////////////////////////////////////////////////////////////
// English (U.S.) resources
#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
#ifdef _WIN32
LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
#pragma code_page(1252)
#endif //_WIN32
#ifdef APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// TEXTINCLUDE
//
1 TEXTINCLUDE
BEGIN
"resource.h\0"
END
2 TEXTINCLUDE
BEGIN
"#include ""afxres.h""\r\n"
"\0"
END
3 TEXTINCLUDE
BEGIN
"\r\n"
"\0"
END
#endif // APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// Dialog
//
IDD_DIALOG1 DIALOGEX 0, 0, 316, 180
STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | WS_SYSMENU
CAPTION "Dialog"
FONT 8, "MS Shell Dlg", 400, 0, 0x1
BEGIN
DEFPUSHBUTTON "OK",IDOK,205,159,50,14
PUSHBUTTON "Cancel",IDCANCEL,259,159,50,14
END
/////////////////////////////////////////////////////////////////////////////
//
// DESIGNINFO
//
#ifdef APSTUDIO_INVOKED
GUIDELINES DESIGNINFO
BEGIN
IDD_DIALOG1, DIALOG
BEGIN
LEFTMARGIN, 7
RIGHTMARGIN, 309
TOPMARGIN, 7
BOTTOMMARGIN, 173
END
END
#endif // APSTUDIO_INVOKED
#endif // English (U.S.) resources
/////////////////////////////////////////////////////////////////////////////
#ifndef APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// Generated from the TEXTINCLUDE 3 resource.
//
/////////////////////////////////////////////////////////////////////////////
#endif // not APSTUDIO_INVOKED

The "main" WM_COMMAND processing is wrong, there is no break at the end of the switch.
So when a WM_COMMAND is processed with neither ID_FILE_EXIT or LAUNCH_CONSOLE in LOWORD(wParam), the WM_CLOSE code is executed.
use:
case WM_COMMAND:
switch(LOWORD(wParam))
{
case ID_FILE_EXIT:
SendMessage(hwnd, WM_CLOSE, NULL, NULL);
break;
case LAUNCH_CONSOLE:
HWND aDiag = CreateDialog((HINSTANCE) GetWindowLong(hwnd, GWL_INSTANCE),
MAKEINTRESOURCE(IDD_DIALOG1), NULL,
(DLGPROC),AboutDlgProc);
ShowWindow(aDiag, SW_SHOW);
break;
}
break; // <== breaking WM_COMMAND
EDIT: How to see the result of GetLastError
DWORD dwLE = GetLastError();
TCHAR szLE[16];
_ltot( dwLe, szLE, 10 );
MessageBox(hwnd, szLE, TEXT("Error"), MB_OK);

Related

Dock/Anchor alternative in C++ for List Control

In .NET there are Anchor & Dock properties that can make the controls responsive whenever you resize the window.
I want to do something similar with this C++ List Control. Basically I want to dock it in the dialog, so when I resize the window, it should be resizing.
#include <Windows.h>
#include "resource.h"
#pragma comment(linker, "\"/manifestdependency:type='win32' \
name='Microsoft.Windows.Common-Controls' version='6.0.0.0' \
processorArchitecture='*' publicKeyToken='6595b64144ccf1df' language='*'\"")
#pragma comment(linker, "/SUBSYSTEM:WINDOWS")
#include <CommCtrl.h> // LV_COLUMN and ListView_x
INT_PTR CALLBACK DialogProc(HWND hWnd, UINT Message, WPARAM wParam, LPARAM lParam)
{
wchar_t c0_txt[] = L"Dogzu";
switch (Message)
{
case WM_INITDIALOG:
LVCOLUMNW col;
col.mask = LVCF_TEXT | LVCF_WIDTH | LVIF_IMAGE;
col.cx = 60;
col.pszText = c0_txt;
ListView_InsertColumn(GetDlgItem(hWnd, IDC_LIST1), 0, &col);
return TRUE;
case WM_NCDESTROY:
PostQuitMessage(0);
return FALSE;
case WM_COMMAND:
switch (LOWORD(wParam))
{
case IDOK:
case IDCANCEL:
DestroyWindow(hWnd);
break;
default:
break;
}
break;
default:
return FALSE;
}
return TRUE;
}
int WINAPI WinMain(
_In_ HINSTANCE hInstance,
_In_opt_ HINSTANCE hPrevInstance,
_In_ LPSTR lpCmdLine,
_In_ int nShowCmd
)
{
UNREFERENCED_PARAMETER(hPrevInstance);
UNREFERENCED_PARAMETER(lpCmdLine);
HWND hWnd = CreateDialogParamW(hInstance, MAKEINTRESOURCEW(IDD_MAIN), nullptr, &DialogProc, 0);
if (!hWnd)
{
MessageBoxW(nullptr, L"Dialog Creation Failed!", L"Error!", MB_ICONEXCLAMATION | MB_OK);
return 0;
}
ShowWindow(hWnd, nShowCmd);
UpdateWindow(hWnd);
MSG msg;
while (GetMessageW(&msg, nullptr, 0, 0))
{
TranslateMessage(&msg);
DispatchMessageW(&msg);
}
return msg.wParam;
}
// Microsoft Visual C++ generated resource script.
//
#include "resource.h"
#define APSTUDIO_READONLY_SYMBOLS
/////////////////////////////////////////////////////////////////////////////
//
// Generated from the TEXTINCLUDE 2 resource.
//
#include "winres.h"
/////////////////////////////////////////////////////////////////////////////
#undef APSTUDIO_READONLY_SYMBOLS
/////////////////////////////////////////////////////////////////////////////
// English (United States) resources
#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
#pragma code_page(1252)
#ifdef APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// TEXTINCLUDE
//
1 TEXTINCLUDE
BEGIN
"resource.h\0"
END
2 TEXTINCLUDE
BEGIN
"#include ""winres.h""\0"
END
3 TEXTINCLUDE
BEGIN
"\r\n"
"\0"
END
#endif // APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// DESIGNINFO
//
#ifdef APSTUDIO_INVOKED
GUIDELINES DESIGNINFO
BEGIN
IDD_MAIN, DIALOG
BEGIN
LEFTMARGIN, 7
RIGHTMARGIN, 302
TOPMARGIN, 7
BOTTOMMARGIN, 169
END
END
#endif // APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// Dialog
//
IDD_MAIN DIALOGEX 0, 0, 309, 176
STYLE DS_SETFONT | DS_FIXEDSYS | WS_MINIMIZEBOX | WS_MAXIMIZEBOX | WS_POPUP | WS_CAPTION | WS_SYSMENU | WS_THICKFRAME
CAPTION "Test"
FONT 8, "MS Shell Dlg", 400, 0, 0x1
BEGIN
CONTROL "",IDC_LIST1,"SysListView32",LVS_REPORT | LVS_ALIGNLEFT | WS_BORDER | WS_TABSTOP,21,25,268,123
END
/////////////////////////////////////////////////////////////////////////////
//
// AFX_DIALOG_LAYOUT
//
IDD_MAIN AFX_DIALOG_LAYOUT
BEGIN
0
END
#endif // English (United States) resources
/////////////////////////////////////////////////////////////////////////////
#ifndef APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// Generated from the TEXTINCLUDE 3 resource.
//
/////////////////////////////////////////////////////////////////////////////
#endif // not APSTUDIO_INVOKED
There is no docking support in the Windows API. You'll have to implement it manually by handling the WM_SIZE message:
case WM_SIZE: {
UINT width = LOWORD(lParam);
UINT height = HIWORD(lParam);
// IDC_LIST1 will occupy the entire client area of its parent.
// Adjust as needed.
MoveWindow(GetDlgItem(hWnd, IDC_LIST1),
0, 0, width, height, TRUE);
return TRUE;
}

CreateWindow “Edit” typed characters are 'invisible'?

After having researched all I could find on the proper syntax for the CreateWindow("Edit") call, I have to throw in the towel: when I run the program, all I get in the Edit box is "invisible characters". The cursor is moving right as I type, but the characters I enter are nowhere to be seen. Only when I select the box content with the mouse do I see the text. But as soon as I release the mouse, I can not longer see anything.
Here is the entire code which leads to 'text not showing' in the Edit control:
#include <windows.h>
#define FILE_MENU_NEW 1
#define FILE_MENU_OPEN 2
#define FILE_MENU_QUIT 3
#define CHANGE_TITLE 4
LRESULT CALLBACK WindowProc(HWND, UINT, WPARAM, LPARAM);
void AddMenus(HWND);
void AddControls(HWND);
HMENU hMenu;
HWND hEdit;
int WINAPI wWinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE hPrevInstance, _In_ LPWSTR lpCmdLine, _In_ int nShowCmd)
{
WNDCLASS wc = {0}; // Assign 0 to all its elements initialy
wc.hbrBackground = (HBRUSH)COLOR_WINDOW;
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hInstance = hInstance;
wc.lpszClassName = L"myWindowClass";
wc.lpfnWndProc = WindowProc; // this is a pointer to a function
if(!RegisterClass(&wc))
return -1;
HWND hwnd = CreateWindowEx(
WS_EX_CLIENTEDGE,
L"myWindowClass",
L"Learn to Program Windows - Roger Breton",
WS_OVERLAPPEDWINDOW | WS_VISIBLE ,
100, 100, 800, 600,
NULL,
NULL,
hInstance,
NULL
);
if (hwnd == NULL)
{
return 0;
}
MSG msg = { };
while (GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return 0;
}
LRESULT CALLBACK WindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
switch (uMsg)
{
case WM_COMMAND:
switch(wParam)
{
case FILE_MENU_QUIT:
DestroyWindow(hWnd);
break;
case FILE_MENU_NEW:
MessageBeep(MB_ICONINFORMATION);
break;
case CHANGE_TITLE:
wchar_t text[100];
GetWindowTextW(hEdit, text, 100);
SetWindowTextW(hWnd, text);
break;
}
case WM_CREATE:
AddMenus(hWnd);
AddControls(hWnd);
break;
case WM_DESTROY:
PostQuitMessage(0);
return 0;
case WM_PAINT:
{
PAINTSTRUCT ps;
HDC hdc = BeginPaint(hWnd, &ps);
FillRect(hdc, &ps.rcPaint, (HBRUSH)(COLOR_WINDOW));
EndPaint(hWnd, &ps);
}
return 0;
}
return DefWindowProc(hWnd, uMsg, wParam, lParam);
}
void AddMenus(HWND hWnd)
{
hMenu = CreateMenu();
HMENU hFileMenu = CreateMenu();
HMENU hSubMenu = CreateMenu();
AppendMenu(hSubMenu, MF_STRING, NULL, L"Sub-Menu");
AppendMenu(hFileMenu, MF_STRING, FILE_MENU_NEW, L"New");
AppendMenu(hFileMenu, MF_POPUP, (UINT_PTR)hSubMenu, L"Sub-menu ");
AppendMenu(hFileMenu, MF_SEPARATOR, NULL, NULL);
AppendMenu(hFileMenu, MF_STRING, FILE_MENU_QUIT, L"Quit");
AppendMenu(hMenu, MF_POPUP, (UINT_PTR)hFileMenu, L"File");
AppendMenu(hMenu, MF_STRING, NULL, L"Aide");
SetMenu(hWnd, hMenu);
}
void AddControls(HWND hWnd)
{
CreateWindowW(L"Static", L"Enter text here:", WS_VISIBLE | WS_CHILD | WS_BORDER | SS_CENTER , 200, 100, 150, 50, hWnd, NULL, NULL, NULL);
hEdit = CreateWindowW(L"Edit", NULL, WS_VISIBLE | WS_CHILD | WS_BORDER , 200, 152, 100, 50, hWnd, NULL, NULL, NULL);
CreateWindowW(L"Button", L"Changez title", WS_VISIBLE | WS_CHILD, 200, 204, 150, 50, hWnd, (HMENU)CHANGE_TITLE, NULL, NULL);
}
I tried to recreate the source file many times, to no avail.
You have a missing break; statement at the end of your case WM_COMMAND: block. As it stands, your code will 'fall through' to the case WM_CREATE: code after processing any WM_COMMAND.
Adding that break; statement appears to fix your code (when I test it):
LRESULT CALLBACK WindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
switch (uMsg) {
case WM_COMMAND:
switch (wParam) {
case FILE_MENU_QUIT:
DestroyWindow(hWnd);
break;
case FILE_MENU_NEW:
MessageBeep(MB_ICONINFORMATION);
break;
case CHANGE_TITLE:
wchar_t text[100];
GetWindowTextW(hEdit, text, 100);
SetWindowTextW(hWnd, text);
break;
}
break; // ** You missed this line! **
case WM_CREATE:
AddMenus(hWnd);
AddControls(hWnd);
break;
//...
Such mistakes can be spotted if you enable all compiler warnings: The static code analyser in MSVC gives the following message:
warning C26819: Unannotated fallthrough between switch labels (es.78).

How do i detect the control that sent the WM_KEYDOWN?

WM_KEYDOWN message sends the message to the main window, I'd like to get control that originated the message. I've tried with GetFocus() handling WM_KEYDOWN like below but it didn't do anything, even when a press a key with focus on the buttona. How is that done? what am I missing?
Here's how I'm handling WM_KEYDOWN:
case WM_KEYDOWN:
HWND hFocus = GetFocus();
if(hFocus == buttonA)
{
buttona_onKeyDown();
}
else if(hFocus == buttonB)
{
buttonb_onKeyDown();
}
else
{
//MessageBox(NULL, L"Not found!", L"", MB_OK);
}
break;
full code:
#pragma comment(lib, "user32.lib")
#pragma comment(lib, "Comctl32.lib")
#pragma comment(lib, "Gdi32.lib")
#define WIN32_LEAN_AND_MEAN
#define UNICODE
#define _UNICODE
#include <windows.h>
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
void buttona_onKeyDown();
void buttonb_onKeyDown();
HWND buttonA, buttonB;
int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
PWSTR lpCmdLine, int nCmdShow) {
MSG msg;
WNDCLASSW wc = {0};
wc.lpszClassName = L"Buttons";
wc.hInstance = hInstance;
wc.hbrBackground = GetSysColorBrush(COLOR_3DFACE);
wc.lpfnWndProc = WndProc;
wc.hCursor = LoadCursor(0, IDC_ARROW);
RegisterClassW(&wc);
HWND hWnd =
CreateWindowW(wc.lpszClassName, L"Buttons",
WS_OVERLAPPEDWINDOW | WS_VISIBLE,
150, 150, 300, 200, 0, 0, hInstance, 0);
while (GetMessage(&msg, NULL, 0, 0))
{
if (!IsDialogMessage(hWnd, &msg))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
return (int) msg.wParam;
}
LRESULT CALLBACK WndProc(HWND hwnd, UINT msg,
WPARAM wParam, LPARAM lParam) {
switch(msg)
{
case WM_CREATE:
buttonA =
CreateWindowW(L"Button", L"A",
WS_VISIBLE | WS_CHILD | WS_TABSTOP,
20, 50, 80, 25, hwnd, (HMENU) 10, NULL, NULL);
buttonB =
CreateWindowW(L"Button", L"B",
WS_VISIBLE | WS_CHILD | WS_TABSTOP,
120, 50, 80, 25, hwnd, (HMENU) 11, NULL, NULL);
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
case WM_KEYDOWN:
HWND hFocus = GetFocus();
if(hFocus == buttonA)
{
buttona_onKeyDown();
}
else if(hFocus == buttonB)
{
buttonb_onKeyDown();
}
else
{
//MessageBox(NULL, L"Not found!", L"", MB_OK);
}
break;
}
return DefWindowProcW(hwnd, msg, wParam, lParam);
}
void buttona_onKeyDown()
{
MessageBox(NULL, L"A OnKeyDown", L"", MB_OK);
}
void buttonb_onKeyDown()
{
MessageBox(NULL, L"B OnKeyDown", L"", MB_OK);
}

Add Controls To Specific Tab Page in TabControl in C++ Win32

I want to add some controls to the tab page in tabcontrol but it seems that it will be added to all pages and there is not tab page in tabcontrol by default.
I have read these links below but they did not help me and in some parts of them, confused me.
How to add controls to a Tab control
http://www.cplusplus.com/forum/windows/37161/
https://msdn.microsoft.com/en-us/library/bb760551.aspx
https://msdn.microsoft.com/en-us/library/hh298366.aspx
https://msdn.microsoft.com/en-us/library/ms645398.aspx
Here is my code :
[Code]:
#define ID_LBL 500
#define ID_BTN 501
#define ID_TBC 502
HWND hWnd;
void InserTabItem(HWND handle, LPWSTR text, int id)
{
TCITEM tci = { 0 };
tci.mask = TCIF_TEXT;
tci.pszText = text;
tci.cchTextMax = wcslen(text);
SendMessage(handle, TCM_INSERTITEM, id, LPARAM(&tci));
}
LRESULT CALLBACK WndProc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam)
{
switch (Msg)
{
case WM_CREATE:
{
HWND button_handle = 0;
HWND label_handle = 0;
HWND tab_handle = 0;
tab_handle = CreateWindowEx(WS_EX_CONTROLPARENT, WC_TABCONTROL, 0, WS_VISIBLE | WS_CHILD, 10, 10, 200, 150, hWnd, HMENU(ID_TBC), 0, 0);
InserTabItem(tab_handle, L"page1", 0);
InserTabItem(tab_handle, L"page2", 1);
button_handle = CreateWindowEx(0, WC_BUTTON, L"test-button-page2", WS_VISIBLE | WS_CHILD, 10, 50, 150, 30, tab_handle, HMENU(ID_BTN), 0, 0);
label_handle = CreateWindowEx(0, WC_STATIC, L"test-label-page1", WS_VISIBLE | WS_CHILD, 10, 100, 150, 30, tab_handle, HMENU(ID_LBL), 0, 0);
}
break;
case WM_CLOSE:
DestroyWindow(hWnd);
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hWnd, Msg, wParam, lParam);
break;
}
return 0;
}
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPreviewInstance, LPSTR lpcmdline, int ncmdshow)
{
WNDCLASSEX wndexcls;
wndexcls.lpszClassName = L"win";
wndexcls.hIcon = LoadIcon(NULL, IDI_APPLICATION);
wndexcls.hIconSm = LoadIcon(NULL, IDI_APPLICATION);
wndexcls.hCursor = LoadCursor(NULL, IDC_ARROW);
wndexcls.hbrBackground = (HBRUSH)(COLOR_3DSHADOW + 1);
wndexcls.lpszMenuName = NULL;
wndexcls.style = NULL;
wndexcls.hInstance = hInstance;
wndexcls.cbSize = sizeof(WNDCLASSEX);
wndexcls.cbClsExtra = 0;
wndexcls.cbWndExtra = 0;
wndexcls.lpfnWndProc = WndProc;
RegisterClassEx(&wndexcls);
hWnd = CreateWindowEx(WS_EX_CLIENTEDGE | WS_EX_CONTROLPARENT, L"win", L"TestApp", WS_OVERLAPPEDWINDOW, 100, 100, 640, 380, 0, 0, hInstance, 0);
ShowWindow(hWnd, ncmdshow);
UpdateWindow(hWnd);
MSG wnd_msg;
while (GetMessage(&wnd_msg, NULL, 0, 0)>0)
{
TranslateMessage(&wnd_msg);
DispatchMessage(&wnd_msg);
}
return (int)wnd_msg.wParam;
}
I am looking for a safe and proper implementation.
Thanks for any help
========================================================
[Update]:
Thanks for comments but no answer in detail :(
Although that is not the implementation I am looking for(NotDialogBased), But from the forth link I mentioned :
How to Create a Tabbed Dialog Box :
https://msdn.microsoft.com/en-us/library/hh298366.aspx
Here is my code of that page :
[resource.h]:
#define IDD_Page1 101
#define IDD_Page2 102
#define IDD_Page3 103
#define IDD_Main_Dialog 104
#define IDC_BTN_Page1 1001
#define IDC_BTN2_Page1 1002
#define IDC_BTN_Page2 1013
#define IDC_BTN_Page3 1014
[Resource.rc]:
#include "resource.h"
#define APSTUDIO_READONLY_SYMBOLS
#include "winres.h"
#undef APSTUDIO_READONLY_SYMBOLS
#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
//////////////////////////////////////////////////
//
// Dialog
//
IDD_Page1 DIALOGEX 0, 0, 313, 178
STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_CHILD
FONT 8, "MS Shell Dlg", 400, 0, 0x1
BEGIN
PUSHBUTTON "Button2-Page1",IDC_BTN2_Page1,129,107,67,22
PUSHBUTTON "Button-Page1",IDC_BTN_Page1,127,77,67,22
END
IDD_Page2 DIALOGEX 0, 0, 309, 177
STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_CHILD
FONT 8, "MS Shell Dlg", 400, 0, 0x1
BEGIN
PUSHBUTTON "Button-Page2",IDC_BTN_Page2,120,77,60,18
END
IDD_Page3 DIALOGEX 0, 0, 309, 177
STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_CHILD
FONT 8, "MS Shell Dlg", 400, 0, 0x1
BEGIN
PUSHBUTTON "Button-Page3",IDC_BTN_Page3,120,73,64,25
END
IDD_Main_Dialog DIALOGEX 0, 0, 309, 177
STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_CHILD
FONT 8, "MS Shell Dlg", 400, 0, 0x1
BEGIN
END
////////////////////////////////////////////
//
// DESIGNINFO
//
#ifdef APSTUDIO_INVOKED
GUIDELINES DESIGNINFO
BEGIN
IDD_Page1, DIALOG
BEGIN
LEFTMARGIN, 7
RIGHTMARGIN, 306
TOPMARGIN, 7
BOTTOMMARGIN, 171
END
IDD_Page2, DIALOG
BEGIN
LEFTMARGIN, 7
RIGHTMARGIN, 302
TOPMARGIN, 7
BOTTOMMARGIN, 170
END
IDD_Page3, DIALOG
BEGIN
LEFTMARGIN, 7
RIGHTMARGIN, 302
TOPMARGIN, 7
BOTTOMMARGIN, 170
END
IDD_Main_Dialog, DIALOG
BEGIN
LEFTMARGIN, 7
RIGHTMARGIN, 302
TOPMARGIN, 7
BOTTOMMARGIN, 170
END
END
#endif // APSTUDIO_INVOKED
#endif
[Main.cpp]:
#include <windows.h>
#include <CommCtrl.h>
#include "resource.h"
#pragma comment(lib, "ComCtl32.lib")
#define C_PAGES 3
INT_PTR CALLBACK DialogProc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam);
HWND Win_Handle;
HWND Dailog_Handle;
HINSTANCE hInstance_Win_Global;
typedef struct {
WORD dlgVer;
WORD signature;
DWORD helpID;
DWORD exStyle;
DWORD style;
WORD cDlgItems;
short x;
short y;
short cx;
short cy;
WORD pointsize;
WORD weight;
BYTE italic;
BYTE charset;
} DLGTEMPLATEEX;
typedef struct tag_dlghdr {
HWND hwndTab; // tab control
HWND hwndDisplay; // current child dialog box
RECT rcDisplay; // display rectangle for the tab control
DLGTEMPLATEEX *apRes[C_PAGES];
} DLGHDR;
void InserTabItem(HWND handle, LPWSTR text, int id)
{
TCITEM tci = { 0 };
tci.mask = TCIF_TEXT;
tci.pszText = text;
tci.cchTextMax = wcslen(text);
SendMessage(handle, TCM_INSERTITEM, id, LPARAM(&tci));
}
DLGTEMPLATEEX* DoLockDlgRes(LPCTSTR lpszResName)
{
HRSRC hrsrc = FindResource(NULL, lpszResName, RT_DIALOG);
HGLOBAL hglb = LoadResource(hInstance_Win_Global, hrsrc);
return (DLGTEMPLATEEX *)LockResource(hglb);
}
VOID WINAPI OnChildDialogInit(HWND hwndDlg)
{
HWND hwndParent = GetParent(hwndDlg);
DLGHDR *pHdr = (DLGHDR *)GetWindowLong(
hwndParent, GWL_USERDATA);
SetWindowPos(hwndDlg, NULL, pHdr->rcDisplay.left,
pHdr->rcDisplay.top,//-2,
(pHdr->rcDisplay.right - pHdr->rcDisplay.left),
(pHdr->rcDisplay.bottom - pHdr->rcDisplay.top),
SWP_SHOWWINDOW);
return;
}
VOID OnSelChanged(HWND hwndDlg)
{
DLGHDR *pHdr = (DLGHDR *)GetWindowLong(hwndDlg, GWL_USERDATA);
int iSel = TabCtrl_GetCurSel(pHdr->hwndTab);
if (pHdr->hwndDisplay != NULL)
DestroyWindow(pHdr->hwndDisplay);
pHdr->hwndDisplay = CreateDialogIndirect(hInstance_Win_Global,
(DLGTEMPLATE *)pHdr->apRes[iSel], hwndDlg,DialogProc);
}
HRESULT OnTabbedDialogInit(HWND hwndDlg)
{
INITCOMMONCONTROLSEX iccex;
DWORD dwDlgBase = GetDialogBaseUnits();
int cxMargin = LOWORD(dwDlgBase) / 4;
int cyMargin = HIWORD(dwDlgBase) / 8;
TCITEM tie;
RECT rcTab;
HWND hwndButton;
RECT rcButton;
int i;
iccex.dwSize = sizeof(INITCOMMONCONTROLSEX);
iccex.dwICC = ICC_TAB_CLASSES;
InitCommonControlsEx(&iccex);
DLGHDR *pHdr = (DLGHDR *)LocalAlloc(LPTR, sizeof(DLGHDR));
SetWindowLong(hwndDlg, GWL_USERDATA, (LONG)pHdr);
pHdr->hwndTab = CreateWindow(
WC_TABCONTROL, L"",
WS_CHILD | WS_CLIPSIBLINGS | WS_VISIBLE,
0, 0, 300, 200,
hwndDlg, NULL, hInstance_Win_Global, NULL
);
if (pHdr->hwndTab == NULL)
{
return HRESULT_FROM_WIN32(GetLastError());
}
tie.mask = TCIF_TEXT | TCIF_IMAGE;
tie.iImage = -1;
tie.pszText = L"First";
TabCtrl_InsertItem(pHdr->hwndTab, 0, &tie);
tie.pszText = L"Second";
TabCtrl_InsertItem(pHdr->hwndTab, 1, &tie);
tie.pszText = L"Third";
TabCtrl_InsertItem(pHdr->hwndTab, 2, &tie);
pHdr->apRes[0] = DoLockDlgRes(MAKEINTRESOURCE(IDD_Page1));
pHdr->apRes[1] = DoLockDlgRes(MAKEINTRESOURCE(IDD_Page2));
pHdr->apRes[2] = DoLockDlgRes(MAKEINTRESOURCE(IDD_Page3));
SetRectEmpty(&rcTab);
for (i = 0; i < C_PAGES; i++)
{
if (pHdr->apRes[i]->cx > rcTab.right)
rcTab.right = pHdr->apRes[i]->cx;
if (pHdr->apRes[i]->cy > rcTab.bottom)
rcTab.bottom = pHdr->apRes[i]->cy;
}
MapDialogRect(hwndDlg, &rcTab);
TabCtrl_AdjustRect(pHdr->hwndTab, TRUE, &rcTab);
OffsetRect(&rcTab, cxMargin - rcTab.left, cyMargin - rcTab.top);
CopyRect(&pHdr->rcDisplay, &rcTab);
TabCtrl_AdjustRect(pHdr->hwndTab, FALSE, &pHdr->rcDisplay);
SetWindowPos(pHdr->hwndTab, NULL, rcTab.left, rcTab.top,
rcTab.right - rcTab.left, rcTab.bottom - rcTab.top,
SWP_NOZORDER);
hwndButton = GetDlgItem(hwndDlg, IDC_BTN_Page1);
SetWindowPos(hwndButton, NULL,
rcTab.left, rcTab.bottom + cyMargin, 0, 0,
SWP_NOSIZE | SWP_NOZORDER);
GetWindowRect(hwndButton, &rcButton);
rcButton.right -= rcButton.left;
rcButton.bottom -= rcButton.top;
hwndButton = GetDlgItem(hwndDlg, IDC_BTN2_Page1);
SetWindowPos(hwndButton, NULL,
rcTab.left + rcButton.right + cxMargin,
rcTab.bottom + cyMargin, 0, 0,
SWP_NOSIZE | SWP_NOZORDER);
SetWindowPos(hwndDlg, NULL, 0, 0,
rcTab.right + cyMargin + (2 * GetSystemMetrics(SM_CXDLGFRAME)),
rcTab.bottom + rcButton.bottom + (2 * cyMargin)
+ (2 * GetSystemMetrics(SM_CYDLGFRAME))
+ GetSystemMetrics(SM_CYCAPTION),
SWP_NOMOVE | SWP_NOZORDER);
OnSelChanged(hwndDlg);
return S_OK;
}
LRESULT CALLBACK WndProc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam)
{
switch (Msg)
{
case WM_CREATE:
{
Dailog_Handle = CreateDialogParam(hInstance_Win_Global, MAKEINTRESOURCE(IDD_Main_Dialog), hWnd, DialogProc, 0);
ShowWindow(Dailog_Handle, SW_SHOWDEFAULT);
UpdateWindow(Dailog_Handle);
SetWindowPos(Dailog_Handle, 0, 10, 10, 500, 300, SWP_NOZORDER);
}
break;
case WM_CLOSE:
DestroyWindow(hWnd);
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hWnd, Msg, wParam, lParam);
break;
}
return 0;
}
INT_PTR CALLBACK DialogProc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam)
{
switch (Msg)
{
case WM_INITDIALOG:
{
OnTabbedDialogInit(hWnd);
OnChildDialogInit(hWnd);
return (INT_PTR)TRUE;
}
break;
case WM_NOTIFY:
{
switch (((LPNMHDR)lParam)->code)
{
case TCN_SELCHANGE:
{
OnSelChanged(hWnd);
}
break;
default:
break;
}
}
break;
case WM_CLOSE:
DestroyWindow(hWnd);
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
}
return (INT_PTR)FALSE;
}
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPreviewInstance, LPSTR lpcmdline, int ncmdshow)
{
WNDCLASSEX wndexcls;
wndexcls.lpszClassName = L"win";
wndexcls.hIcon = LoadIcon(NULL, IDI_APPLICATION);
wndexcls.hIconSm = LoadIcon(NULL, IDI_APPLICATION);
wndexcls.hCursor = LoadCursor(NULL, IDC_ARROW);
wndexcls.hbrBackground = (HBRUSH)(COLOR_3DSHADOW + 1);
wndexcls.lpszMenuName = NULL;
wndexcls.style = NULL;
wndexcls.hInstance = hInstance;
wndexcls.cbSize = sizeof(WNDCLASSEX);
wndexcls.cbClsExtra = 0;
wndexcls.cbWndExtra = 0;
wndexcls.lpfnWndProc = WndProc;
RegisterClassEx(&wndexcls);
Win_Handle = CreateWindowEx(WS_EX_CLIENTEDGE | WS_EX_CONTROLPARENT, L"win", L"TestApp", WS_OVERLAPPEDWINDOW, 100, 100, 640, 380, 0, 0, hInstance, 0);
hInstance_Win_Global = hInstance;
ShowWindow(Win_Handle, SW_SHOWDEFAULT);
UpdateWindow(Win_Handle);
MSG wnd_msg;
while (GetMessage(&wnd_msg, NULL, 0, 0)>0)
{
TranslateMessage(&wnd_msg);
DispatchMessage(&wnd_msg);
}
return (int)wnd_msg.wParam;
}
The Problem is that , after debugging , the application exites and does not show anything. if I comment the OnSelChanged(hWnd) and OnChildDialogInit(hWnd)
the application starts normally and shows the tabcontrol but not the controls on the pages. it seems that the problem is here.
the output log :
First-chance exception at 0x00BE1886 in testcppapp.exe: 0xC0000005: Access violation reading location 0x00000014.
The program '[16220] testcppapp.exe' has exited with code 0 (0x0).
I have Read the link below about Access violation reading location:
http://www.cplusplus.com/forum/general/17094/
But I can not fix the problem.
Please Post your Answer and Explain about it , not just brief in comments !
Thanks for any help.
One problem is here:
pHdr->hwndDisplay = CreateDialogIndirect(hInstance_Win_Global,
(DLGTEMPLATE*)pHdr->apRes[iSel], hwndDlg, DialogProc);
You are reusing the same dialog procedure for both main dialog and child dialogs. Main dialog creates child dialogs, child dialogs use the same procedure to create child dialogs... Also there are no error checks.
Beyond that, this code is too complicated. Just use a dialog box for main window. Create a new dialog IDD_DIALOG1 and drag/drop a tab control in it. Assign IDC_TAB1 for tab control ID. Try starting with this code instead:
#include <Windows.h>
#include <CommCtrl.h>
#include "Resource.h"
#pragma comment(lib,"comctl32.lib")
#pragma comment(linker,"\"/manifestdependency:type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='*' publicKeyToken='6595b64144ccf1df' language='*'\"")
HINSTANCE g_hinst;
struct TData {
HWND page1, page2, page3;
HWND tab;
} data;
BOOL CALLBACK DialogPage(HWND hwnd, UINT msg, WPARAM wp, LPARAM lp)
{
switch(msg) {
case WM_COMMAND:
switch (wp) {
//...
}
}
return FALSE;
}
void OnSelChange() {
int sel = TabCtrl_GetCurSel(data.tab);
ShowWindow(data.page1, (sel == 0) ? SW_SHOW : SW_HIDE);
ShowWindow(data.page2, (sel == 1) ? SW_SHOW : SW_HIDE);
}
BOOL CALLBACK DialogProc(HWND hwnd, UINT msg, WPARAM wp, LPARAM lp)
{
switch (msg) {
case WM_INITDIALOG: {
data.page1 = CreateDialog(g_hinst, MAKEINTRESOURCE(IDD_Page1), hwnd, DialogPage);
data.page2 = CreateDialog(g_hinst, MAKEINTRESOURCE(IDD_Page2), hwnd, DialogPage);
data.tab = GetDlgItem(hwnd, IDC_TAB1);
if (data.tab)
{
TCITEM tci = { 0 };
tci.mask = TCIF_TEXT;
tci.pszText = L"Page1";
TabCtrl_InsertItem(data.tab, 0, &tci);
tci.pszText = L"Page2";
TabCtrl_InsertItem(data.tab, 1, &tci);
RECT rc;//find tab control's rectangle
GetWindowRect(data.tab, &rc);
POINT offset = { 0 };
ScreenToClient(hwnd, &offset);
OffsetRect(&rc, offset.x, offset.y); //convert to client coordinates
rc.top += 50;
SetWindowPos(data.page1, 0, rc.left, rc.top, rc.right - rc.left, rc.bottom - rc.top, SWP_HIDEWINDOW);
SetWindowPos(data.page2, 0, rc.left, rc.top, rc.right - rc.left, rc.bottom - rc.top, SWP_HIDEWINDOW);
OnSelChange();
}
break;
}
case WM_NOTIFY: {
switch (((LPNMHDR)lp)->code) {
case TCN_SELCHANGE:
OnSelChange();
break;
}
}
break;
case WM_COMMAND:
switch (wp) {
case IDOK: EndDialog(hwnd, wp); break;
case IDCANCEL: EndDialog(hwnd, wp); break;
}
}
return FALSE;
}
int WINAPI wWinMain(HINSTANCE hinst, HINSTANCE, LPWSTR, int)
{
g_hinst = hinst;
DialogBox(hinst, MAKEINTRESOURCE(IDD_DIALOG1), 0, DialogProc);
return 0;
}
An approach that I am testing and looks promising is to use a dialog box template for each pane of the tab control within the modal dialog box.
For testing, I generated a starting Win32 GUI application and then hijacked the About box display triggered by IDM_ABOUT to display my own dialog box with a tab control rather than a standard About dialog.
case IDM_ABOUT:
// DialogBox(hInst, MAKEINTRESOURCE(IDD_ABOUTBOX), hWnd, About);
{
CDialogTabTest x;
x.CreateModal (hWnd, hInst);
}
break;
After some research and refactoring and development I have the following approach.
I have created three classes for implementation: CDialogTest (handles the dialog box functionality), CDialogTabTest (handles the tab control within the dialog box), and CDialogTabPane (handles the individual tab panes that are displayed in the tab control).
The CDialogTest class provides the functionality for basic dialog box behavior. It allows for two kinds of dialog boxes, modal used to create the actual modal dialog box and non-modal used to create the tab control panes.
The CDialogTest class is designed to be used as a subclass and be extended for a particular dialog box or tab control pane.
The CDialogTabTest class extends CDialogTest to implement a modal dialog box. The CDialogTabPane class extends CDialogTest to implement a non-modal dialog box that is used as a tab control tab pane.
For MFC programmers some of the names may sound vaguely familiar as while working this out, I now understand some of the mechanics of the MFC classes for dialog boxes.
I put added some additional include files in the the stdafx.h file as that was a central place to put them for what I needed.
// TODO: reference additional headers your program requires here
#include "commctrl.h"
#include "windowsx.h"
#include <vector>
DialogTest.h
#pragma once
class CDialogTest
{
private:
static INT_PTR CALLBACK DlgProc (HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam);
public:
HINSTANCE m_hInst;
HWND m_hParent;
HWND m_hDlg;
CDialogTest();
CDialogTest(HINSTANCE hInst, HWND hParent = NULL);
virtual ~CDialogTest(void);
HWND CreateThing (HWND hWnd, LPCWSTR lpTemplateName, HINSTANCE hInst);
INT_PTR WINAPI CreateModal (HWND hWnd, LPCWSTR lpTemplateName, HINSTANCE hInst);
virtual int DoDataExchange (int iDir) { return 0; }
virtual int OnWmCommandInit () { return 0; }
virtual int OnWmNotify (LPNMHDR pNmhdr) { return 0; }
virtual int OnWmCommand (WPARAM wParam, LPARAM lParam) { return 0; }
};
and DialogTest.cpp
#include "StdAfx.h"
#include "DialogTest.h"
CDialogTest::CDialogTest(void)
{
}
CDialogTest::CDialogTest(HINSTANCE hInst, HWND hParent /* = NULL */) :
m_hInst (hInst), m_hParent(hParent)
{
}
CDialogTest::~CDialogTest(void)
{
}
INT_PTR CALLBACK CDialogTest::DlgProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message)
{
case WM_INITDIALOG:
{
// Set the provided object pointer into the dialog box user area
// so that we can use it to provide the necessary notifications
// to what ever object which has derived from this class.
::SetWindowLongPtr (hDlg, DWLP_USER, lParam);
// ensure that the object knows its dialog handle.
CDialogTest *pObj = (CDialogTest *)lParam;
pObj->m_hDlg = hDlg;
// call the objects handlers to initialize the dialog further
// and to then populate the data displayed in the dialog.
pObj->OnWmCommandInit ();
pObj->DoDataExchange (1);
}
return (INT_PTR)TRUE;
case WM_COMMAND:
// if this command is an Ok or Cancel button press then we are
// done. other command messages are routed to the derived object's
// how command message handler for further processing.
if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL)
{
if (LOWORD(wParam) == IDOK) {
LPARAM lP = ::GetWindowLongPtr (hDlg, DWLP_USER);
CDialogTest *pObj = (CDialogTest *)lP;
pObj->DoDataExchange (0);
}
EndDialog(hDlg, LOWORD(wParam));
return (INT_PTR)TRUE;
} else {
LPARAM lP = ::GetWindowLongPtr (hDlg, DWLP_USER);
CDialogTest *pObj = (CDialogTest *)lP;
pObj->OnWmCommand (wParam, lParam);
}
break;
case WM_NOTIFY:
{
LPARAM lP = ::GetWindowLongPtr (hDlg, DWLP_USER);
CDialogTest *pObj = (CDialogTest *)lP;
LPNMHDR pNmhdr = ((LPNMHDR)lParam);
pObj->OnWmNotify (pNmhdr);
}
break;
}
return (INT_PTR)FALSE;
}
// We need two different kinds of dialog create functions as we support
// both a modal dialog and a modeless dialog. The modal dialog is used to
// display an actual dialog box. The modeless dialog is used to display
// a tab control pane using a dialog template.
INT_PTR WINAPI CDialogTest::CreateModal (HWND hWnd, LPCWSTR lpTemplateName, HINSTANCE hInst)
{
m_hInst = hInst;
m_hParent = hWnd;
// display the modal dialog box and return the identifier for the button clicked.
return DialogBoxParam(hInst, lpTemplateName, hWnd, &CDialogTest::DlgProc, (LPARAM)this);
}
HWND CDialogTest::CreateThing (HWND hWnd, LPCWSTR lpTemplateName, HINSTANCE hInst)
{
m_hInst = hInst;
m_hParent = hWnd;
// create a modeless dialog box to be used as a tab control pane or similar
// non-modal dialog box use.
m_hDlg = ::CreateDialogParam(hInst, lpTemplateName, hWnd, &CDialogTest::DlgProc, (LPARAM)this);
return m_hDlg;
}
The class CDialogTabTest creates the modal dialog box that is being displayed as a result of the IDM_ABOUT menu selection message in the main application message handler.
DialogTabTest.h
#pragma once
#include "stdafx.h"
#include "DialogTest.h"
#include "DialogTabPane.h"
#include "resource.h"
struct CCheckBoxData
{
UINT iCntrlId;
int iCheck;
std::wstring prompt;
};
typedef std::vector<CCheckBoxData> CCheckBoxVector;
class CDialogTabTest : public CDialogTest
{
protected:
CDialogTabPane m_hTabPane1;
CDialogTabPane m_hTabPane2;
CDialogTabPane m_hTabPane3;
enum {IDD_DIALOG = IDD_DIALOG_TAB00};
public:
CDialogTabTest(void);
virtual ~CDialogTabTest(void);
INT_PTR WINAPI CreateModal (HWND hWnd, HINSTANCE hInst);
static int SetValues (CCheckBoxData &x, HWND hDlg);
static int GetValues (CCheckBoxData &x, HWND hDlg);
virtual int DoDataExchange (int iDir);
virtual int OnWmCommandInit ();
virtual int OnWmNotify (LPNMHDR pNmhdr);
};
and DialogTabTest.cpp which creates the modal dialog box and initializes it.
#include "StdAfx.h"
#include "DialogTabTest.h"
CDialogTabTest::CDialogTabTest(void)
{
}
CDialogTabTest::~CDialogTabTest(void)
{
}
int CDialogTabTest::SetValues (CCheckBoxData &x, HWND hDlg)
{
HWND hWnd = GetDlgItem (hDlg, x.iCntrlId);
::SetWindowText (hWnd, x.prompt.c_str());
Button_SetCheck (hWnd, x.iCheck);
return 0;
}
int CDialogTabTest::GetValues (CCheckBoxData &x, HWND hDlg)
{
HWND hWnd = GetDlgItem (hDlg, x.iCntrlId);
x.iCheck = Button_GetCheck (hWnd);
return 0;
}
int CDialogTabTest::OnWmCommandInit ()
{
// get the window handle for the tab control. This is going to
// be the parent window for all of the tab panes that are inserted
// into the tab control. By making the tab control the parent,
// the tab panes will be contained within the tab control and
// will flow with it should it be moved about.
HWND hTabCntrl = GetDlgItem (m_hDlg, IDC_TAB1);
TCITEM tie = {0};
tie.mask = TCIF_TEXT | TCIF_IMAGE;
tie.iImage = -1;
tie.pszText = L"First";
m_hTabPane1.CreateThing (&tie, 0, MAKEINTRESOURCE(IDD_DIALOG_TAB01), m_hInst, hTabCntrl);
tie.pszText = L"Second";
m_hTabPane2.CreateThing (&tie, 1, MAKEINTRESOURCE(IDD_DIALOG_TAB02), m_hInst, hTabCntrl);
tie.pszText = L"Third";
m_hTabPane3.CreateThing (&tie, 2, MAKEINTRESOURCE(IDD_DIALOG_TAB03), m_hInst, hTabCntrl);
// set the first tab to be displayed.
NMHDR Nmhdr = {hTabCntrl, 0, TCN_SELCHANGE};
m_hTabPane1.OnWmNotify (&Nmhdr);
return 0;
}
int CDialogTabTest::OnWmNotify (LPNMHDR pNmhdr)
{
// propagate the notification to the various panes in our tab control
// so that they can do what they need to do.
m_hTabPane1.OnWmNotify (pNmhdr);
m_hTabPane2.OnWmNotify (pNmhdr);
m_hTabPane3.OnWmNotify (pNmhdr);
return 0;
}
int CDialogTabTest::DoDataExchange (int iDir)
{
if (iDir) {
CCheckBoxData iVal = {IDC_CHECK1, BST_UNCHECKED, L"DoData: Check Box 1 Set and Not Checked"};
SetValues (iVal, m_hTabPane1.m_hDlg);
iVal.iCntrlId = IDC_CHECK2;
iVal.iCheck = BST_CHECKED;
iVal.prompt = L"DoData: Check Box 2 is Set and Checked.";
SetValues (iVal, m_hTabPane1.m_hDlg);
iVal.iCntrlId = IDC_CHECK4;
iVal.iCheck = BST_CHECKED;
iVal.prompt = L"DoData: Check Box 4 is Set, Checked Tab 3.";
SetValues (iVal, m_hTabPane3.m_hDlg);
} else {
CCheckBoxData iVal = {IDC_CHECK1, BST_UNCHECKED, L""};
GetValues (iVal, m_hTabPane1.m_hDlg);
}
return 0;
}
INT_PTR WINAPI CDialogTabTest::CreateModal (HWND hWnd, HINSTANCE hInst)
{
// this is a modal dialog box so we use the CreateModal() method
// in order to create the dialog box and display it.
return CDialogTest::CreateModal(hWnd, MAKEINTRESOURCE(IDD_DIALOG), hInst);
}
Finally there is the CDialogTabPane class which implements the functionality for individual tab control tab panes.
DialogTabPane.h
#pragma once
#include "stdafx.h"
#include "DialogTest.h"
class CDialogTabPane : public CDialogTest
{
protected:
int m_iTab;
public:
DWORD m_dwLastError;
CDialogTabPane(void);
virtual ~CDialogTabPane(void);
HWND CreateThing (LPTCITEM pTie, int iTab, LPCWSTR lpTemplateName, HINSTANCE hInstance, HWND hWndParent);
// virtual int DoDataExchange (int iDir);
// virtual int OnWmCommandInit ();
virtual int OnWmNotify (LPNMHDR pNmhdr);
};
and DialogTabPane.cpp
#include "StdAfx.h"
#include "DialogTabPane.h"
CDialogTabPane::CDialogTabPane(void)
{
}
CDialogTabPane::~CDialogTabPane(void)
{
}
HWND CDialogTabPane::CreateThing (LPTCITEM pTie, int iTab, LPCWSTR lpTemplateName, HINSTANCE hInstance, HWND hWndParent)
{
// insert the new tab into the tab control with the specified parameters.
TabCtrl_InsertItem(hWndParent, iTab, pTie);
m_iTab = iTab;
// We need to figure out the adjustment of the dialog window position
// within the tab control display area so that when the dialog and its
// controls are displayed for a given tab the tab selection list can
// still be seen above the top of the displayed dialog.
// The tab selection list must be visible so that the user can select
// any of the specified tabs.
RECT tabDisplay = {0};
GetWindowRect (hWndParent, &tabDisplay);
RECT dialogDisplay = tabDisplay;
// NOTE: TabCtrl_AdjustRect() - This message applies only to tab controls that
// are at the top. It does not apply to tab controls that are on the
// sides or bottom.
// But then tab controls on the side or bottom are an abomination.
TabCtrl_AdjustRect (hWndParent, FALSE, &dialogDisplay);
dialogDisplay.left -= tabDisplay.left; dialogDisplay.top -= tabDisplay.top;
m_dwLastError = 0;
// create our dialog and then position it within the tab control properly.
CDialogTest::CreateThing(hWndParent, lpTemplateName, hInstance);
if (!::SetWindowPos (m_hDlg, HWND_TOP, dialogDisplay.left, dialogDisplay.top, 0, 0, SWP_NOSIZE)) {
m_dwLastError = GetLastError ();
}
return m_hDlg;
}
int CDialogTabPane::OnWmNotify (LPNMHDR pNmhdr)
{
int currentSel = TabCtrl_GetCurSel(pNmhdr->hwndFrom);
switch (pNmhdr->code)
{
case TCN_SELCHANGING:
if (currentSel == m_iTab)
::ShowWindow (m_hDlg, SW_HIDE);
break;
case TCN_SELCHANGE:
if (currentSel == m_iTab)
::ShowWindow (m_hDlg, SW_SHOW);
break;
}
return 0;
}
The dialog box resources used for the individual tab control tab panes are similar and look like:
IDD_DIALOG_TAB01 DIALOGEX 0, 0, 186, 115
STYLE DS_SETFONT | DS_FIXEDSYS | WS_CHILD | WS_SYSMENU
FONT 8, "MS Shell Dlg", 400, 0, 0x1
BEGIN
LTEXT "First tab",IDC_STATIC,68,7,96,14
CONTROL "Check1",IDC_CHECK1,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,7,21,150,13
CONTROL "Check2",IDC_CHECK2,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,7,36,150,13
CONTROL "Check3",IDC_CHECK3,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,7,53,150,13
CONTROL "Check4",IDC_CHECK4,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,7,69,150,13
CONTROL "Check5",IDC_CHECK5,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,7,84,150,13
END
And the resource for the actual dialog containing the tab control looks like:
IDD_DIALOG_TAB00 DIALOGEX 0, 0, 336, 179
STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | WS_SYSMENU
CAPTION "Dialog Tab Test"
FONT 8, "MS Shell Dlg", 400, 0, 0x1
BEGIN
DEFPUSHBUTTON "OK",IDOK,279,7,50,14
PUSHBUTTON "Cancel",IDCANCEL,279,24,50,14
CONTROL "",IDC_TAB1,"SysTabControl32",0x0,47,35,226,137
END
Displaying dialog box with tab 1 selected and then tab 3 selected.

CreateWindowEx, GetLastError, Windows 7, and XP oddities and odd behavior

The following code works on Window 7, but when I run it on Windows XP, it fails with an error message returned by windows: "The system can not find the file specified".
#include <windows.h>
#include <windowsx.h>
#include <commctrl.h>
#include <uxtheme.h>
#include <string>
const char g_szClassName[] = "myWindowClass";
const char title[] = "Window Title\0";
COLORREF WinColor;
HFONT defaultFont;
NONCLIENTMETRICSA Metrics;
DWORD dwVersion;
DWORD dwMajorVersion;
DWORD dwMinorVersion;
HBRUSH hBrushColor;
bool LastError = false;
bool W32Error (const char * Msgtext);
// Step 4: the Window Procedure
LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
switch(msg)
{
case WM_NCCREATE:
{
Metrics.cbSize = sizeof(NONCLIENTMETRICS);
SystemParametersInfo (SPI_GETNONCLIENTMETRICS, sizeof(NONCLIENTMETRICS), &Metrics, 0);
defaultFont = (HFONT) CreateFontIndirect (& Metrics.lfMessageFont);
return TRUE;
}
break;
case WM_CTLCOLORSTATIC: {
dwVersion = GetVersion();
dwMajorVersion = (DWORD)(LOBYTE(LOWORD(dwVersion)));
dwMinorVersion = (DWORD)(HIBYTE(LOWORD(dwVersion)));
if ( (IsAppThemed()) && (dwMajorVersion < 6) ) {
WinColor = GetSysColor(COLOR_WINDOW);
SetBkColor((HDC)wParam, WinColor);
return (LRESULT)hBrushColor;
}
}
break;
case WM_CREATE: {
HWND hButton = CreateWindowEx(
0,
"BUTTON", "Button",
WS_TABSTOP |
WS_VISIBLE |
WS_CHILD |
BS_NOTIFY |
BS_PUSHBUTTON,
10, 10, 96, 32, hwnd,
(HMENU)50,
GetModuleHandle(NULL),
NULL);
if (W32Error ("Button Creation Failed\nReason:")) exit (1);
return TRUE;
}
break;
case WM_CLOSE:
DestroyWindow(hwnd);
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hwnd, msg, wParam, lParam);
}
return 0;
}
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
LPSTR lpCmdLine, int nCmdShow)
{
WNDCLASSEX wc;
HWND hwnd;
MSG Msg;
// Initialize common controls.
INITCOMMONCONTROLSEX icc;
icc.dwSize = sizeof(icc);
icc.dwICC = ICC_WIN95_CLASSES |
ICC_COOL_CLASSES |
ICC_INTERNET_CLASSES|
ICC_LINK_CLASS |
ICC_STANDARD_CLASSES|
ICC_PROGRESS_CLASS |
ICC_USEREX_CLASSES;
InitCommonControlsEx(&icc);
//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);
// see if something is going on before the window registration takes place....
if (W32Error ("Previous Check for Error?\nReason:")) exit (1);
if(!RegisterClassEx(&wc))
{
MessageBox(NULL, "Window Registration Failed!", "Error!",
MB_ICONEXCLAMATION | MB_OK);
return 0;
}
if (W32Error ("Window Registration Failed\nReason:")) exit (1);
// Step 2: Creating the Window
hwnd = CreateWindowEx(
WS_EX_CLIENTEDGE,
g_szClassName,
"The title of my window",
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, CW_USEDEFAULT, 240, 120,
NULL, NULL, hInstance, NULL);
if (W32Error ("Window Creation Failed\nReason:")) exit (1);
if(hwnd == NULL)
{
MessageBox(NULL, "Window Creation Failed!", "Error!",
MB_ICONEXCLAMATION | MB_OK);
return 0;
}
SendMessageA(hwnd, WM_SETFONT, WPARAM (defaultFont), TRUE);
SendMessageA(hwnd, WM_SETTEXT, WPARAM(NULL) , LPARAM (title));
ShowWindow(hwnd, nCmdShow);
UpdateWindow(hwnd);
// Step 3: The Message Loop
while(GetMessage(&Msg, NULL, 0, 0) > 0)
{
TranslateMessage(&Msg);
DispatchMessage(&Msg);
}
return Msg.wParam;
}
bool W32Error (const char * Msgtext)
{
LPTSTR errorText = NULL;
DWORD dwLastError = GetLastError();
if (!dwLastError) {
LastError = false;
return LastError;
}
// use system message tables to retrieve error text
// allocate buffer on local heap for error text
// Important! will fail otherwise, since we're not (and CANNOT) pass insertion parameters
FormatMessageA(
FORMAT_MESSAGE_FROM_SYSTEM |
FORMAT_MESSAGE_ALLOCATE_BUFFER |
FORMAT_MESSAGE_IGNORE_INSERTS,
NULL, // unused with FORMAT_MESSAGE_FROM_SYSTEM
dwLastError,
MAKELANGID (LANG_NEUTRAL, SUBLANG_DEFAULT),
(LPTSTR)&errorText, // output
0, // minimum size for output buffer
0); // arguments - see note
if ( NULL != errorText ) {
std::string Message;
Message += Msgtext;
Message += "\n";
Message += errorText;
MessageBoxA(NULL, (LPCSTR)Message.c_str(), "An Internal Error Occurred", MB_OK);
LocalFree(errorText);
errorText = NULL;
LastError = true;
} else {
LastError = false;
}
return LastError;
}
As an additional, I have a resource.rc and resource.h file linked in with winres that complies in a manifest.xml that provides a controls version 6 specification.
Ok, so here is the deal, This runs on Windows 7 without a hitch. And it runs on XP, unless I put in the line if (W32Error ("Window Registration Failed\nReason:")) exit (1);
(basically, it calls my error checking routine which includes GetLastError())
if(!RegisterClassEx(&wc))
{
MessageBox(NULL, "Window Registration Failed!", "Error!",
MB_ICONEXCLAMATION | MB_OK);
return 0;
}
if (W32Error ("Window Registration Failed\nReason:")) exit (1);
When I include that line, I get an error "The system can not find the file specified." The return value back from RegisterClassEx does not go into the if block, so RegisterClassEx returns Ok.
This only happens on Windows XP, it works just fine on Windows 7. If I don't include this line, it works as if nothing is wrong.
The point of this sample is to get themes to work right on both XP and Windows 7. (not an easy task.)
Why is RegisterClassEx returning Ok, but generates an error for GetLastError on Windows XP and not on Windows 7?
Also, what file is it looking for anyway? I have seen other Google results say It has to do with a messed up message loop or window procedure, but that's not the case here.
General mistake... Due to MSDN you may check GetLastError only when RegisterClassEx "return value is zero". When RegisterClassEx or CreateWindowEx or any other functions are succeeded, GetLastError may return garbage, there is no guarantee that GetLastError will returns zero (if different behavior does not described in Return value section).

Resources