Hi I'm trying to develop a c++ MDI program using purely Win32 API (because I need the program to be portable, i.e. can run even from USB, as much as possible only the .exe file).
This MDI program has 2 types (classes) of child windows, the "MdiPrinterChild" and "MdiStationChild." The "MdiStationChild" window is automatically created and shown once the client area of the main window is created (only one 'Station' window can be created). The "MdiPrinterChild" window is only created when the user selects "New Printer" from the menu and virtually can create several 'printer' child windows. When a 'printer' child window is active, a "close all" menu can be triggered, supposedly to close all 'printer' windows (only). The problem is, it's also closing the 'station' window. Same thing happens if click 'x' of the main window. I tried selective closing of child windows by using the class name of the child window (if statement), inside the "CloseEnumProc" but this time the problem, the application itself can never be closed. 'Exit' from menu will likewise not respond.
Below is the codef for CloseEnumProc, but if this code is really not workable, can anyone give me a sample code how to do it. Thanks.
#include <windows.h>
#include <Winuser.h>
#include <Winbase.h>
#include "shlwapi.h"
#include "CommCtrl.h"
#include <tchar.h>
#include "resource.h"
#include "printer.h"
#define INIT_MENU_POS 0
#define PRINTER_MENU_POS 2
#define IDM_FIRSTCHILD 50000
#define BUFSIZE MAX_PATH
//prototypes
LRESULT CALLBACK FrameWndProc (HWND, UINT, WPARAM, LPARAM);
BOOL CALLBACK CloseEnumProc (HWND, LPARAM);
LRESULT CALLBACK PrinterWndProc (HWND, UINT, WPARAM, LPARAM);
BOOL CALLBACK SetupStationDlgProc(HWND, UINT, WPARAM, LPARAM);
LRESULT CALLBACK StationWndProc (HWND, UINT, WPARAM, LPARAM);
//global variables
TCHAR szAppName[] = TEXT ("VentureOEp");
TCHAR szFrameClass[] = TEXT ("MdiFrame");
TCHAR szPrinterClass[] = TEXT ("MdiPrinterChild");
TCHAR szStationClass[] = TEXT ("MdiStationChild");
HINSTANCE hInst, hInstStation;
HMENU hMenuInit, hMenuPrinter;
HMENU hMenuInitWindow, hMenuPrinterWindow;
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
//locals to WinMain
HWND hwndFrame;
HWND hwndClient;
MSG msg;
WNDCLASSEX wc;
HACCEL hAccel;
hInst = hInstance ;
/*=====================*/
//get current directory of this process and check if definition files are complete
TCHAR filePath[BUFSIZE] ;
DWORD dwRet ;
dwRet = GetCurrentDirectory(BUFSIZE, filePath) ;
if( dwRet == 0 )
{
sprintf(filePath,"GetCurrentDirectory failed (%d)\n", GetLastError()) ;
MessageBox(NULL,LPCSTR(filePath),LPCSTR("Get Current Directory Error!"),MB_ICONEXCLAMATION|MB_OK) ;
return 0 ;
}
else
{
//check if definition files exists
char *exactPath ;
exactPath = (LPSTR)(filePath) ;
strcat(exactPath, "\\") ;
strcat(exactPath, "Definition Files\\printer.xml") ;
if(!PathFileExists(exactPath))
{
MessageBox(NULL,_T("printer.xml not found"),_T("File check"),MB_ICONEXCLAMATION|MB_OK);
return 0;
}
}
/*=====================*/
//check file access over network and copy to current process directory
int bFileExists = 0;
char buffer_1[]= "G:\\Notebooks and Projects\\Dev C++\\Venture pOE\\Definition Files_Source\\printer.xml";
char* fileToCopy ;
const char *fileCopyTo ;
fileToCopy = buffer_1 ;
fileCopyTo = "G:\\Notebooks and Projects\\Dev C++\\Venture pOE\\Definition Files\\printer.xml" ;
if(!PathFileExists(fileToCopy))
{
MessageBox(NULL,_T("Network Access Failed"),_T("Access Check"),MB_ICONEXCLAMATION|MB_OK);
return 0;
}
if (!CopyFile(fileToCopy, fileCopyTo,FALSE))
{
MessageBox(NULL,_T("File update failed"),_T("Definitions update"),MB_ICONEXCLAMATION|MB_OK) ;
return 0 ;
}
/*=====================*/
//register frame window class
memset(&wc,0,sizeof(wc));
wc.cbSize = sizeof(WNDCLASSEX);
wc.style = CS_HREDRAW | CS_VREDRAW;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.lpfnWndProc = FrameWndProc;
wc.hInstance = hInstance;
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hbrBackground = HBRUSH(COLOR_WINDOW+1);
wc.lpszMenuName = NULL; //MAKEINTRESOURCE(IDR_MAINMENU);
wc.lpszClassName = szFrameClass;
wc.hIcon = LoadIcon (NULL, IDI_APPLICATION);
wc.hIconSm = NULL; //HICON(LoadImage(GetModuleHandle(NULL), MAKEINTRESOURCE(IDI_MAINICON), IMAGE_ICON, 16,
if(!RegisterClassEx(&wc))
{
MessageBox(NULL, _T("Frame Window Registration Failed!"),_T("Error!"),MB_ICONEXCLAMATION|MB_OK);
return 0;
}
//register child (printer) window class (not the client window which is already pre-registered)
memset(&wc, 0, sizeof(wc));
wc.cbSize = sizeof(WNDCLASSEX);
wc.style = CS_HREDRAW | CS_VREDRAW; // | CS_NOCLOSE;
wc.lpfnWndProc = PrinterWndProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = hInstance;
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hbrBackground = HBRUSH(COLOR_WINDOW+1);
wc.lpszMenuName = NULL;
wc.lpszClassName = szPrinterClass;
wc.hIcon = LoadIcon (NULL, IDI_APPLICATION);
wc.hIconSm = NULL;
if(!RegisterClassEx(&wc))
{
MessageBox(NULL, _T("Printer Window Registration Failed!"),_T("Error!"),MB_ICONEXCLAMATION|MB_OK);
return 0;
}
//register child (window) window class (not the client window which is already pre-registered)
memset(&wc, 0, sizeof(wc));
wc.cbSize = sizeof(WNDCLASSEX);
wc.style = CS_HREDRAW | CS_VREDRAW | CS_NOCLOSE;
wc.lpfnWndProc = StationWndProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = hInstance;
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hbrBackground = HBRUSH(COLOR_WINDOW+1);
wc.lpszMenuName = NULL;
wc.lpszClassName = szStationClass;
wc.hIcon = LoadIcon (NULL, IDI_APPLICATION);
wc.hIconSm = NULL;
if(!RegisterClassEx(&wc))
{
MessageBox(NULL, _T("Station Window Registration Failed!"),_T("Error!"),MB_ICONEXCLAMATION|MB_OK);
return 0;
}
//Obtain handles of menus
hMenuInit = LoadMenu (hInstance, TEXT ("MdiMenuInit")) ;
hMenuPrinter = LoadMenu (hInstance, TEXT ("MdiMenuPrinter")) ;
//Obtain handles of positions of submenu "Window"
hMenuInitWindow = GetSubMenu (hMenuInit, INIT_MENU_POS) ;
hMenuPrinterWindow = GetSubMenu (hMenuPrinter, PRINTER_MENU_POS) ;
//Load accelerator table
hAccel = LoadAccelerators (hInstance, szAppName) ;
//create frame window
//menu is loaded here
hwndFrame = CreateWindowEx(
WS_EX_CLIENTEDGE,
szFrameClass,
_T("Venture Day Walker"),
WS_CLIPCHILDREN|WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT,
CW_USEDEFAULT,
CW_USEDEFAULT,
CW_USEDEFAULT,
NULL,
hMenuInit,
hInstance,
NULL);
if(hwndFrame == NULL)
{
MessageBox(NULL, _T("Main Window Creation Failed!"),_T("Error!"),MB_ICONEXCLAMATION|MB_OK);
return 0;
}
//get handle of the client window(as child of main window)
hwndClient = GetWindow(hwndFrame,GW_CHILD);
//Display the window
ShowWindow(hwndFrame, nCmdShow);
UpdateWindow (hwndFrame);
// Enter the modified message loop (due to use of accelerators)
while (GetMessage (&msg, NULL, 0, 0))
{
if (!TranslateMDISysAccel (hwndClient, &msg) &&
!TranslateAccelerator (hwndFrame, hAccel, &msg))
{
TranslateMessage (&msg) ;
DispatchMessage (&msg) ;
}
}
// Clean up by deleting unattached menus
DestroyMenu (hMenuPrinter) ;
//end of WinMain
return msg.wParam;
}
/*=====================*/
//main window proc
LRESULT CALLBACK FrameWndProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
static HWND hwndClient ;
CLIENTCREATESTRUCT clientcreate ;
HWND hwndChild, hwndChildStation ;
MDICREATESTRUCT mdicreate ;
switch (message)
{
case WM_CREATE:
// Create the client window
clientcreate.hWindowMenu = hMenuInitWindow ;
clientcreate.idFirstChild = IDM_FIRSTCHILD ;
hwndClient = CreateWindowEx (
WS_EX_CLIENTEDGE,
TEXT("MDICLIENT"),
NULL,
WS_CHILD | WS_CLIPCHILDREN | WS_VISIBLE,
0, 0, 0, 0,
hwnd,
(HMENU) 1,
hInst,
(PSTR) &clientcreate) ;
// Create a station child window
//provide values 1st for the MDICREATESTRUCT
mdicreate.szClass = szStationClass;
mdicreate.szTitle = TEXT ("Station Details");
mdicreate.hOwner = hInstStation;
mdicreate.x = CW_USEDEFAULT;
mdicreate.y = CW_USEDEFAULT;
mdicreate.cx = CW_USEDEFAULT;
mdicreate.cy = CW_USEDEFAULT;
mdicreate.style = 0; //WS_HSCROLL | WS_VSCROLL ;
mdicreate.lParam = 0;
//sendmessage to create the child window using WM_MDICREATE and
hwndChildStation = (HWND) SendMessage (hwndClient,
WM_MDICREATE, 0,
(LPARAM) (LPMDICREATESTRUCT) &mdicreate);
break ;
case WM_COMMAND:
switch (LOWORD (wParam))
{
case IDM_STATION_SETUP:
DialogBox(hInst, TEXT("IDD_SETUPSTATION"), hwnd, SetupStationDlgProc);
InvalidateRect (hwnd, NULL, TRUE) ;
break ;
case IDM_PRINTER_NEW:
// Create a printer child window
mdicreate.szClass = szPrinterClass ;
mdicreate.szTitle = TEXT ("Serial Number + Model No.") ;
mdicreate.hOwner = hInst ;
mdicreate.x = CW_USEDEFAULT ;
mdicreate.y = CW_USEDEFAULT ;
mdicreate.cx = CW_USEDEFAULT ;
mdicreate.cy = CW_USEDEFAULT ;
mdicreate.style = WS_HSCROLL | WS_VSCROLL ; //or '0' for just frames
mdicreate.lParam = 0 ;
hwndChild = (HWND) SendMessage (hwndClient,
WM_MDICREATE, 0,
(LPARAM) (LPMDICREATESTRUCT) &mdicreate);
break ;
case IDM_PRINTER_CLOSE:
// Close the active printer window
hwndChild = (HWND) SendMessage (hwndClient,
WM_MDIGETACTIVE, 0, 0) ;
if (SendMessage (hwndChild, WM_QUERYENDSESSION, 0, 0))
SendMessage (hwndClient, WM_MDIDESTROY, (WPARAM) hwndChild, 0) ;
break ;
case IDM_APP_EXIT:
// Exit the program
SendMessage (hwnd, WM_CLOSE, 0, 0) ;
break ;
// messages for arranging windows
case IDM_WINDOW_TILE:
SendMessage (hwndClient, WM_MDITILE, 0, 0) ;
break ;
case IDM_WINDOW_CASCADE:
SendMessage (hwndClient, WM_MDICASCADE, 0, 0) ;
break ;
case IDM_WINDOW_CLOSEALL: // Attempt to close all children
EnumChildWindows (hwndClient, CloseEnumProc, 0) ;
break ;
case IDM_ABOUT:
// About menu
MessageBox(NULL, _T("Thank You LORD!"),_T("Glory To GOD"),MB_ICONEXCLAMATION|MB_OK);
break ;
default:
// Pass to active child...
hwndChild = (HWND) SendMessage (hwndClient, WM_MDIGETACTIVE, 0, 0) ;
if (IsWindow (hwndChild))
SendMessage (hwndChild, WM_COMMAND, wParam, lParam) ;
return 0 ; // ...and then to DefFrameProc
}
break ;
case WM_PAINT:
break ;
case WM_QUERYENDSESSION:
case WM_CLOSE: //frame
// Attempt to close all children
SendMessage (hwnd, WM_COMMAND, IDM_WINDOW_CLOSEALL, 0) ;
//mark: if NULL, meaning no more child windows
if (NULL != GetWindow (hwndClient, GW_CHILD))
return 0 ;
break ; // i.e., call DefFrameProc
case WM_DESTROY: //frame
PostQuitMessage (0) ;
break ;
}
// Pass unprocessed messages to DefFrameProc (not DefWindowProc)
return DefFrameProc (hwnd, hwndClient, message, wParam, lParam) ;
}
//'printer' window proc=========================================
LRESULT CALLBACK PrinterWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
static HWND hwndClient, hwndFrame;
HDC hdc;
HMENU hMenu;
PAINTSTRUCT ps;
RECT rect;
switch (message)
{
case WM_CREATE:
// Save some window handles
hwndClient = GetParent(hwnd);
hwndFrame = GetParent(hwndClient);
break;
case WM_COMMAND:
break;
case WM_PAINT:
break;
case WM_MDIACTIVATE:
// Set the Printer menu if gaining focus
if (lParam == (LPARAM)hwnd)
SendMessage(hwndClient, WM_MDISETMENU, (WPARAM)hMenuPrinter, (LPARAM)hMenuPrinterWindow);
// Set the Init menu if losing focus
if (lParam != (LPARAM)hwnd)
SendMessage(hwndClient, WM_MDISETMENU, (WPARAM)hMenuInit, (LPARAM)hMenuInitWindow);
DrawMenuBar(hwndFrame);
break;
case WM_QUERYENDSESSION:
case WM_CLOSE: //printer
if (IDOK != MessageBox(hwnd, TEXT("OK to close window?"), TEXT("Printer"), MB_ICONQUESTION | MB_OKCANCEL))
return 0;
break; // i.e., call DefMDIChildProc
case WM_DESTROY: //printer
break;
}
// Pass unprocessed message to DefMDIChildProc
return DefMDIChildProc(hwnd, message, wParam, lParam);
}
//'Station' window proc=============================
LRESULT CALLBACK StationWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
static HWND hwndClient, hwndFrame;
HDC hdc;
HMENU hMenu;
PAINTSTRUCT ps;
RECT rect;
switch (message)
{
case WM_CREATE:
// Save some window handles
hwndClient = GetParent(hwnd);
hwndFrame = GetParent(hwndClient);
break;
case WM_PAINT:
break;
case WM_MDIACTIVATE:
break;
case WM_DESTROY: //station
break; //return 0 ;
}
// Pass unprocessed message to DefMDIChildProc
return DefMDIChildProc(hwnd, message, wParam, lParam);
}
//'close all' CloseEnumProc =========================================
BOOL CALLBACK CloseEnumProc(HWND hwnd, LPARAM lParam)
{
TCHAR className[20];
int numChar = 20;
// Check for icon title
if (GetWindow(hwnd, GW_OWNER))
return TRUE;
GetClassName(hwnd, className, numChar);
if (strcmp(szPrinterClass, className) == 0)
{
//if window is minimized, restore to previous size
SendMessage(GetParent(hwnd), WM_MDIRESTORE, (WPARAM)hwnd, 0);
//then send ask to close
if (!SendMessage(hwnd, WM_QUERYENDSESSION, 0, 0))
return TRUE;
SendMessage(GetParent(hwnd), WM_MDIDESTROY, (WPARAM)hwnd, 0);
return TRUE;
}
}