MEMORY.C


/******************************************************************************\
* This is a part of the Microsoft Source Code Samples.
* Copyright 1993 - 1998 Microsoft Corporation.
* All rights reserved.
* This source code is only intended as a supplement to
* Microsoft Development Tools and/or WinHelp documentation.
* See these sources for detailed information regarding the
* Microsoft samples programs.
\******************************************************************************/

/****************************** Module Header ******************************\
* Module Name: memory.c
\***************************************************************************/


#include <windows.h>
#include "memory.h"


HANDLE ghModule;
HWND ghwndMain = NULL;
HWND ghwndClient;

HMENU hMenu, hMenuWindow;
HMENU hServerMenu, hServerMenuWindow;
HMENU hClientMenu, hClientMenuWindow;

CHAR gszFile[20];
CHAR gszMapName[20];


typedef struct _PerWndInfo
{
HWND hParent;
HWND hThisWnd; // Used in locating the node
RECT rcClient;
char CaptionBarText[SIZEOFCAPTIONTEXT];
} PERWNDINFO, *PPERWNDINFO;


typedef struct _node
{
PERWNDINFO ChildWnd;
HANDLE hNext;
} NODE, *PNODE;


/*
* Forward declarations.
*/
BOOL InitializeApp (void);
LONG APIENTRY MainWndProc (HWND, UINT, DWORD, LONG);
LONG APIENTRY ServerWndProc (HWND, UINT, DWORD, LONG);
LONG APIENTRY ClientWndProc (HWND, UINT, DWORD, LONG);
BOOL CALLBACK About (HWND, UINT, DWORD, LONG);
BOOL CALLBACK FileType (HWND, UINT, DWORD, LONG);
BOOL CALLBACK MapFileName (HWND, UINT, DWORD, LONG);
LONG APIENTRY TextWndProc (HWND, UINT, DWORD, LONG);

/***************************************************************************\
* main
*
\***************************************************************************/

int WINAPI WinMain(
HANDLE hInstance,
HANDLE hPrevInstance,
LPSTR lpCmdLine,
int nShowCmd)
{
MSG msg;

// this will change to something more reasonable

ghModule = GetModuleHandle(NULL);
if (!InitializeApp())
{
MessageBox(ghwndMain,
GetStringRes(IDS_ERR_INITAPP_FAILED),
NULL, MB_OK);

return 0;
}

while (GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}

if (hMenuWindow && IsWindow(hMenuWindow))
DestroyMenu(hMenuWindow);
if (hClientMenuWindow && IsWindow(hClientMenuWindow))
DestroyMenu(hClientMenuWindow);
if (hServerMenuWindow && IsWindow(hServerMenuWindow))
DestroyMenu(hServerMenuWindow);
if (hMenu && IsWindow(hMenu))
DestroyMenu(hMenu);
if (hClientMenu && IsWindow(hClientMenu))
DestroyMenu(hClientMenu);
if (hServerMenu && IsWindow(hServerMenu))
DestroyMenu(hServerMenu);

return 1;

UNREFERENCED_PARAMETER(lpCmdLine);
UNREFERENCED_PARAMETER(nShowCmd);
UNREFERENCED_PARAMETER(hInstance);
UNREFERENCED_PARAMETER(hPrevInstance);
}


/***************************************************************************\
* InitializeApp
*
\***************************************************************************/

BOOL InitializeApp(void)
{
WNDCLASS wc;

wc.style = CS_OWNDC;
wc.lpfnWndProc = (WNDPROC)MainWndProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = sizeof(LONG);
wc.hInstance = ghModule;
wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hbrBackground = (HBRUSH)(COLOR_APPWORKSPACE);
wc.lpszMenuName = "MainMenu";
wc.lpszClassName = "MemoryClass";

if (!RegisterClass(&wc))
return FALSE;

wc.style = CS_OWNDC;
wc.lpfnWndProc = (WNDPROC)ServerWndProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0; // LATER sizeof(LONG);
wc.hInstance = ghModule;
wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hbrBackground = (HBRUSH)(COLOR_APPWORKSPACE);
wc.lpszMenuName = NULL;
wc.lpszClassName = "ServerClass";

if (!RegisterClass(&wc))
return FALSE;

wc.style = CS_OWNDC;
wc.lpfnWndProc = (WNDPROC)ClientWndProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0; // LATER sizeof(LONG);
wc.hInstance = ghModule;
wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hbrBackground = (HBRUSH)(COLOR_APPWORKSPACE);
wc.lpszMenuName = NULL;
wc.lpszClassName = "ClientClass";

if (!RegisterClass(&wc))
return FALSE;

wc.style = CS_OWNDC | CS_HREDRAW | CS_VREDRAW;
wc.lpfnWndProc = (WNDPROC)TextWndProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = ghModule;
wc.hIcon = NULL;
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hbrBackground = (HBRUSH)(COLOR_BTNSHADOW);
wc.lpszMenuName = NULL;
wc.lpszClassName = "Text";

if (!RegisterClass(&wc))
return FALSE;



hMenu = LoadMenu(ghModule, "MainMenu");
hServerMenu = LoadMenu(ghModule, "ServerMenu");
hClientMenu = LoadMenu(ghModule, "ClientMenu");
hMenuWindow = GetSubMenu(hMenu, 1);
hServerMenuWindow = GetSubMenu(hServerMenu, 2);
hClientMenuWindow = GetSubMenu(hClientMenu, 2);

ghwndMain = CreateWindowEx(0L, "MemoryClass", "Memory",
WS_OVERLAPPED | WS_CAPTION | WS_BORDER |
WS_THICKFRAME | WS_MAXIMIZEBOX | WS_MINIMIZEBOX |
WS_CLIPCHILDREN | WS_VISIBLE | WS_SYSMENU,
80, 70, 592, 300,
NULL, hMenu, ghModule, NULL);

if (ghwndMain == NULL)
return FALSE;

SetWindowLong(ghwndMain, GWL_USERDATA, 0L);

return TRUE;
}


/***************************************************************************\
* MainWndProc
*
\***************************************************************************/

long APIENTRY MainWndProc(
HWND hwnd,
UINT message,
DWORD wParam,
LONG lParam)
{
static int iSvrCount=1;
static int iCltCount=1;
CLIENTCREATESTRUCT clientcreate;
HWND hwndChildWindow;
BOOL fSuccess;


switch (message)
{

case WM_CREATE:
SetWindowLong(hwnd, 0, (LONG)NULL);

clientcreate.hWindowMenu = hMenuWindow;
clientcreate.idFirstChild = 1;

ghwndClient = CreateWindow("MDICLIENT", NULL,
WS_CHILD | WS_CLIPCHILDREN | WS_VISIBLE,
0,0,0,0,
hwnd, NULL, ghModule, (LPVOID)&clientcreate);
return 0L;

case WM_DESTROY: {
PostQuitMessage(0);
return 0L;
}

case WM_COMMAND:

switch (LOWORD(wParam))
{
case IDM_TILE:
SendMessage(ghwndClient, WM_MDITILE, 0L, 0L);
return 0L;
case IDM_CASCADE:
SendMessage(ghwndClient, WM_MDICASCADE, 0L, 0L);
return 0L;
case IDM_ARRANGE:
SendMessage(ghwndClient, WM_MDIICONARRANGE, 0L, 0L);
return 0L;

case MM_SERVER: {
BOOL fSucess = FALSE;
HANDLE hNode, hHead;
PNODE pNode;
MDICREATESTRUCT mdicreate;

hNode = LocalAlloc(LHND, (WORD) sizeof(NODE));
if (hNode && (pNode = (PNODE)LocalLock(hNode)))
{
wsprintf((LPSTR) &(pNode->ChildWnd.CaptionBarText),
GetStringRes(IDS_SERVER), iSvrCount);

mdicreate.szClass = "ServerClass";
mdicreate.szTitle = (LPTSTR)&(pNode->ChildWnd.CaptionBarText);
mdicreate.hOwner = ghModule;
mdicreate.x =
mdicreate.y =
mdicreate.cx =
mdicreate.cy = CW_USEDEFAULT;
mdicreate.style = 0l;
mdicreate.lParam = 0L;

/*Create Child Window*/
hwndChildWindow =
(HWND) SendMessage(ghwndClient, WM_MDICREATE,
0L,
(LONG)(LPMDICREATESTRUCT)&mdicreate);

if (hwndChildWindow)
{
pNode->ChildWnd.hParent = ghwndClient;
pNode->ChildWnd.hThisWnd = hwndChildWindow;
hHead = (HANDLE)GetWindowLong(hwnd, 0);
pNode->hNext = hHead;
SetWindowLong(hwnd, 0, (LONG) hNode);

iSvrCount++;
LocalUnlock(hNode);

fSuccess = TRUE;
}
else
{
LocalUnlock (hNode);
LocalFree (hNode);

fSuccess = FALSE;
}
}
if (!fSuccess)
MessageBox(ghwndMain,
GetStringRes(IDS_ERR_CREATE_CHILD_FAILED),
NULL, MB_OK);

return 0L;
}

case MM_CLIENT:
{
BOOL fResult = FALSE;
HANDLE hNode, hHead;
PNODE pNode;
MDICREATESTRUCT mdicreate;

hNode = LocalAlloc(LHND, (WORD) sizeof(NODE));
if (hNode && (pNode = (PNODE)LocalLock(hNode)))
{
wsprintf((LPSTR) &(pNode->ChildWnd.CaptionBarText),
GetStringRes(IDS_CLIENT), iCltCount);

mdicreate.szClass = "ClientClass";
mdicreate.szTitle = (LPSTR) &(pNode->ChildWnd.CaptionBarText);
mdicreate.hOwner = ghModule;
mdicreate.x =
mdicreate.y =
mdicreate.cx =
mdicreate.cy = CW_USEDEFAULT;
mdicreate.style = 0l;
mdicreate.lParam = 0L;

/*Create Child Window*/
hwndChildWindow =
(HANDLE) SendMessage(ghwndClient, WM_MDICREATE,
0L,
(LONG)(LPMDICREATESTRUCT)&mdicreate);

if (hwndChildWindow)
{
pNode->ChildWnd.hParent = ghwndClient;
pNode->ChildWnd.hThisWnd = hwndChildWindow;
hHead = (HANDLE)GetWindowLong(hwnd, 0);
pNode->hNext = hHead;
SetWindowLong(hwnd, 0, (LONG) hNode);

iCltCount++;
LocalUnlock(hNode);

fSuccess = TRUE;
}
else
{
LocalUnlock (hNode);
LocalFree (hNode);

fSuccess = FALSE;
}
}
if (!fSuccess)
MessageBox(ghwndMain,
GetStringRes(IDS_ERR_CREATE_CHILD_FAILED),
NULL, MB_OK);

return 0L;
}

case MM_ABOUT:
if (DialogBox(ghModule, "AboutBox", ghwndMain, (DLGPROC)About) == -1)
MessageBox(ghwndMain,
GetStringRes(IDS_ERR_CREATE_DLG_FAILED), NULL, MB_OK);
return 0L;

case MM_OPT_1:
case MM_OPT_2:
case MM_OPT_3:
case MM_OPT_4:
case MM_OPT_5:
case MM_OPT_6:
case MM_OPT_7:
case MM_OPT_8:
{
HWND hActiveChild;

hActiveChild = (HANDLE) SendMessage(ghwndClient, WM_MDIGETACTIVE, 0L, 0L);
if (hActiveChild)
SendMessage(hActiveChild, WM_COMMAND, wParam, lParam);
return 0L;
}

default:
return DefFrameProc(hwnd, ghwndClient, message, wParam, lParam);
}

default:

return DefFrameProc(hwnd, ghwndClient, message, wParam, lParam);
}
}


/***************************************************************************\
* ServerWndProc
*
\***************************************************************************/

long APIENTRY ServerWndProc( HWND hwnd,
UINT message,
DWORD wParam,
LONG lParam)
{
static HANDLE MapFileHandle = NULL;
static HANDLE hMem1 = NULL;
static LPVOID pShrMem1 = NULL;
static HANDLE hEdit;
static BOOL bDirty = FALSE;
static HWND hTextWnd;
BOOL fSuccess;

switch (message)
{
case WM_COMMAND:
{

switch (LOWORD(wParam))
{
case MM_OPT_1:
{ //Create File

SetWindowText(hTextWnd, GetStringRes(IDS_CREATE_MAP_FILE));

switch (DialogBox(ghModule, "FileType", hwnd, (DLGPROC)FileType))
{
case -1:
fSuccess = FALSE;
break;

case IDBTN_MAP:
if (MapFileHandle = CreateMapFile(gszFile))
fSuccess = TRUE;
else
fSuccess = FALSE;

break;

default:
MapFileHandle = (HANDLE) 0xFFFFFFFF;
fSuccess = TRUE;
break;
}

if (fSuccess)
{
EnableMenuItem(hServerMenu, MM_OPT_1, MF_GRAYED);
EnableMenuItem(hServerMenu, MM_OPT_2, MF_ENABLED);

SetWindowText(hTextWnd,
GetStringRes(IDS_SEL_CREATE_FILE_MAPPING));
}
else
{
SetWindowText(hTextWnd,
GetStringRes (IDS_ERR_MAPFILE_FAILED));

}
return 0L;
}

case MM_OPT_2:
{ //Create File Mapping

// This option should be disabled until MM_OPT_1 has been chosen.

SetWindowText(hTextWnd,
GetStringRes(IDS_CREATE_MAPPING));


if (MapFileHandle)
switch (DialogBox(ghModule, "MapName", hwnd, (DLGPROC)MapFileName))
{
case IDBTN_OK:
if (hMem1 = CreateMap(MapFileHandle, gszMapName))
fSuccess = TRUE;
else
fSuccess = FALSE;
break;

default:
fSuccess = FALSE;
break;
}
else
fSuccess = FALSE;


if (fSuccess)
{
EnableMenuItem(hServerMenu, MM_OPT_2, MF_GRAYED);
EnableMenuItem(hServerMenu, MM_OPT_3, MF_ENABLED);

SetWindowText(hTextWnd,
GetStringRes (IDS_SEL_MAP_VIEW));
}
else
{
SetWindowText(hTextWnd,
GetStringRes (IDS_ERR_MAPPING_FAILED));

}
return 0L;
}

case MM_OPT_3:
{ //Map View of File

SetWindowText(hTextWnd, GetStringRes (IDS_MAPPING_VIEW));


if (hMem1 && (pShrMem1 = (LPVOID)MapView(hMem1)))
{
EnableMenuItem(hServerMenu, MM_OPT_3, MF_GRAYED);
EnableMenuItem(hServerMenu, MM_OPT_4, MF_ENABLED);

SetWindowText(hTextWnd, GetStringRes (IDS_SEL_ACCESS));

}
else
{
SetWindowText(hTextWnd, GetStringRes(IDS_ERR_MAPVIEW_FAILED));
}
return 0L;
}

case MM_OPT_4:
{ //Access
RECT rcl;

SetWindowText(hTextWnd,
GetStringRes (IDS_ACCESSING_SERVER_WRITE));

if (pShrMem1)
{
GetClientRect(hwnd, &rcl);
hEdit = CreateWindow("edit", (LPSTR) NULL,
WS_CHILD | WS_VISIBLE |
WS_HSCROLL | WS_VSCROLL |
WS_BORDER | ES_LEFT |
ES_MULTILINE | ES_AUTOHSCROLL |
ES_AUTOVSCROLL,
0,0, rcl.right - rcl.left,
rcl.bottom - rcl.top -
GetWindowLong(hTextWnd, GWL_USERDATA),
hwnd, (HMENU)1, ghModule, (LPVOID)NULL);
if (hEdit)
{
EnableMenuItem(hServerMenu, MM_OPT_4, MF_GRAYED);
SetFocus(hEdit);
fSuccess = TRUE;
}
else
fSuccess = FALSE;
}
else
fSuccess = FALSE;

if (!fSuccess)
{
MessageBox(ghwndMain,
GetStringRes(IDS_ERR_ACCESS_WRITE_FAILED),
NULL, MB_OK);
SetWindowText(hTextWnd,
GetStringRes (IDS_ERR_ACCESS_WRITE_FAILED));
}

return 0L;
}
} // End of switch (LOWORD(wParam))

switch (HIWORD(wParam))
{
case EN_UPDATE:
{
if (hEdit && (hEdit == (HWND)lParam))
{
bDirty = TRUE;
}
return 0L;
}
}

}
case WM_TIMER:
if (bDirty && IsWindow(hEdit))
{
int iCnt;
iCnt = SendMessage(hEdit, WM_GETTEXT, (WPARAM)4000, (LPARAM)pShrMem1);

if (iCnt)
{
bDirty = FALSE;
}

}
return 0L;

case WM_MDIACTIVATE:
if ((HWND) lParam == hwnd)
{
SendMessage(GetParent(hwnd), WM_MDISETMENU,
(DWORD) hServerMenu,
(LONG) hServerMenuWindow) ;
DrawMenuBar(GetParent(GetParent(hwnd))) ;
}
return 0;

case WM_SIZE:
if (hEdit)
MoveWindow(hEdit, 0, 0,
LOWORD(lParam),
HIWORD(lParam)-GetWindowLong(hTextWnd, GWL_USERDATA),
TRUE);

MoveWindow(hTextWnd, 0,
HIWORD(lParam) - GetWindowLong(hTextWnd, GWL_USERDATA),
LOWORD(lParam),
HIWORD(lParam), TRUE);

return DefMDIChildProc(hwnd, message, wParam, lParam);

case WM_CREATE:
{
PPERWNDINFO pWndInfo;
PNODE pHead;
HANDLE hHead, hTmp;
RECT rect;

GetClientRect(hwnd, &rect);
hTextWnd = CreateWindow("Text", NULL,
WS_BORDER | SS_LEFT | WS_CHILD | WS_VISIBLE,
0, 0, 0, 0,
hwnd,
(HMENU) 2,
ghModule,
NULL);

EnableMenuItem(hServerMenu, MM_OPT_1, MF_ENABLED);


SetWindowText(hTextWnd, GetStringRes (IDS_SEL_CREATE_FILE));

// now find match
hHead = (HANDLE) GetWindowLong(ghwndMain, 0);
if (hHead && (pHead = (PNODE)LocalLock(hHead)))
{
while ((pHead->ChildWnd.hThisWnd != hwnd) && (pHead->hNext))
{
hTmp = hHead;
hHead = pHead->hNext;
LocalUnlock(hTmp);

pHead = (PNODE)LocalLock(hHead);
}

if (pHead->ChildWnd.hThisWnd == hwnd)
{
pWndInfo = &pHead->ChildWnd;
GetClientRect(pWndInfo->hThisWnd, &pWndInfo->rcClient);
}

LocalUnlock(hHead);
}
return DefMDIChildProc(hwnd, message, wParam, lParam);
}

case WM_CLOSE:
{
PPERWNDINFO pWndInfo;
PNODE pHead, pTrail;
HANDLE hHead, hTmp;

EnableMenuItem(hServerMenu, MM_OPT_2, MF_GRAYED);
EnableMenuItem(hServerMenu, MM_OPT_3, MF_GRAYED);
EnableMenuItem(hServerMenu, MM_OPT_4, MF_GRAYED);

SendMessage(GetParent(hwnd), WM_MDISETMENU, (DWORD)hMenu, (LONG)hMenuWindow);
DrawMenuBar(GetParent(GetParent(hwnd))) ;


// Unmap view, close mapping and file!
if (pShrMem1)
{
UnmapViewOfFile (pShrMem1);
pShrMem1 = NULL;
}

if (hMem1)
{
CloseHandle (hMem1);
hMem1 = NULL;
}

if (MapFileHandle && MapFileHandle != INVALID_HANDLE_VALUE)
{
CloseHandle (MapFileHandle);
MapFileHandle = NULL;
}

// now find match
hHead = (HANDLE) GetWindowLong(ghwndMain, 0);
if ((hHead) && (pHead = (PNODE)LocalLock(hHead)))
{
pTrail = pHead;
while ((pHead->ChildWnd.hThisWnd != hwnd) && (pHead->hNext))
{
hTmp = hHead;
pTrail = pHead;
hHead = pHead->hNext;
LocalUnlock(hTmp);

pHead = (PNODE) LocalLock(hHead);
}

if (pHead->ChildWnd.hThisWnd == hwnd)
{
pWndInfo = &pHead->ChildWnd;

if (pTrail == pHead)
SetWindowLong(ghwndMain, 0, (LONG) pHead->hNext);
else
pTrail->hNext = pHead->hNext;

LocalUnlock(hHead);
LocalFree(hHead);
}
else
{
LocalUnlock(hHead);
}
}
return DefMDIChildProc(hwnd, message, wParam, lParam);
}

case WM_DESTROY:
KillTimer(hwnd, 1);
return 0L;

case WM_PAINT:
return DefMDIChildProc(hwnd, message, wParam, lParam);

default:
return DefMDIChildProc(hwnd, message, wParam, lParam);
}
}


/***************************************************************************\
* ClientWndProc
*
\***************************************************************************/

long APIENTRY ClientWndProc( HWND hwnd,
UINT message,
DWORD wParam,
LONG lParam)
{
static HANDLE hMem1 = NULL;
static LPVOID pShrMem1 = NULL;
static HANDLE hEdit;
static HANDLE hTextWnd;
BOOL fSuccess = FALSE;

switch (message)
{
case WM_COMMAND:
{

switch (LOWORD(wParam))
{
case MM_OPT_5:
{ //Open File Mapping

SetWindowText(hTextWnd, GetStringRes (IDS_OPENING_FILE));

switch (DialogBox(ghModule, "MapName", hwnd, (DLGPROC)MapFileName))
{
case IDBTN_OK:
if (hMem1 = OpenMap(gszMapName))
fSuccess = TRUE;
else
fSuccess = FALSE;
break;

default:
fSuccess = FALSE;
break;
}

if (fSuccess)
{
EnableMenuItem(hClientMenu, MM_OPT_5, MF_GRAYED);
EnableMenuItem(hClientMenu, MM_OPT_6, MF_ENABLED);

SetWindowText(hTextWnd, GetStringRes (IDS_SEL_MAP_VIEW));
}
else
{
SetWindowText(hTextWnd,
GetStringRes (IDS_ERR_OPEN_MAPPING_FAILED));
}
return 0L;

}
case MM_OPT_6:
{ //Map View of File

SetWindowText(hTextWnd, GetStringRes (IDS_MAPPING_VIEW));

if (hMem1 && (pShrMem1 = (LPVOID) MapView(hMem1)))
{
EnableMenuItem(hClientMenu, MM_OPT_6, MF_GRAYED);
EnableMenuItem(hClientMenu, MM_OPT_7, MF_ENABLED);

SetWindowText(hTextWnd, GetStringRes (IDS_SEL_ACCESS_READ));
}
else
{
SetWindowText(hTextWnd,
GetStringRes(IDS_ERR_MAPVIEW_FAILED));
}

return 0L;
}

case MM_OPT_7:
{ //Access
RECT rcl;

SetWindowText(hTextWnd,
GetStringRes(IDS_ACCESSING_SERVER_READ));

fSuccess = FALSE; // assume failure.

if (pShrMem1)
{
GetClientRect(hwnd, &rcl);

hEdit = CreateWindow("edit", NULL,
WS_CHILD | WS_VISIBLE |
WS_HSCROLL | WS_VSCROLL |
WS_BORDER | ES_LEFT |
ES_MULTILINE | ES_AUTOHSCROLL |
ES_READONLY | ES_AUTOVSCROLL,
0,0, rcl.right-rcl.left,
rcl.bottom-rcl.top-GetWindowLong(hTextWnd, GWL_USERDATA),
hwnd, (HMENU) 1, ghModule, NULL);
if (hEdit)
{
SetFocus(hEdit);
fSuccess = TRUE;
}
}

if (fSuccess)
{
SendMessage(hEdit, WM_SETTEXT, 0L, (LONG)pShrMem1);
SetTimer(hwnd, 2, 1000, NULL);
EnableMenuItem(hClientMenu, MM_OPT_7, MF_GRAYED);
EnableMenuItem(hClientMenu, MM_OPT_8, MF_ENABLED);
}
else
{
MessageBox(ghwndMain,
GetStringRes (IDS_ERR_ACCESS_READ_FAILED),
NULL, MB_OK);
SetWindowText(hTextWnd,
GetStringRes (IDS_ERR_ACCESS_READ_FAILED));
}

return 0L;
}

case MM_OPT_8:
{ // refresh now
HANDLE hActive;

hActive = (HANDLE) SendMessage(GetParent(hwnd), WM_MDIGETACTIVE, 0L, 0L);
SendMessage(hEdit, WM_SETTEXT, 0L, (LONG)pShrMem1);
return 0L;
}
}
}

case WM_TIMER:
{
HANDLE hActive;

if (IsWindow (hEdit) && pShrMem1)
{
hActive = (HANDLE) SendMessage(GetParent(hwnd), WM_MDIGETACTIVE, 0L, 0L);
SendMessage(hEdit, WM_SETTEXT, 0L, (LONG)pShrMem1);

} 
return 0L;
}

case WM_MDIACTIVATE:
if ((HWND) lParam == hwnd)
{
SendMessage(GetParent(hwnd), WM_MDISETMENU,
(DWORD) hClientMenu,
(LONG) hClientMenuWindow);
DrawMenuBar(GetParent(GetParent(hwnd))) ;
}
return 0;

case WM_SIZE:
if (hEdit)
MoveWindow(hEdit, 0, 0,
LOWORD(lParam),
HIWORD(lParam)-GetWindowLong(hTextWnd, GWL_USERDATA),
TRUE);

MoveWindow(hTextWnd, 0,
HIWORD(lParam) - GetWindowLong(hTextWnd, GWL_USERDATA),
LOWORD(lParam),
HIWORD(lParam), TRUE);

return DefMDIChildProc(hwnd, message, wParam, lParam);

case WM_CREATE:
{
PPERWNDINFO pWndInfo;
PNODE pHead;
HANDLE hHead, hTmp;
RECT rect;

GetClientRect(hwnd, &rect);
hTextWnd = CreateWindow("Text", NULL,
WS_BORDER | SS_LEFT | WS_CHILD | WS_VISIBLE,
0, 0, 0, 0,
hwnd,
(HMENU) 2,
ghModule,
NULL);

EnableMenuItem(hClientMenu, MM_OPT_5, MF_ENABLED);

SetWindowText(hTextWnd, GetStringRes (IDS_SEL_OPEN_FILE));

// now find match
hHead = (HANDLE) GetWindowLong(ghwndMain, 0);
if (hHead && (pHead = (PNODE)LocalLock(hHead)))
{

while ((pHead->ChildWnd.hThisWnd != hwnd) && (pHead->hNext))
{
hTmp = hHead;
hHead = pHead->hNext;
LocalUnlock(hTmp);
pHead = (PNODE) LocalLock(hHead);
}

if (pHead->ChildWnd.hThisWnd == hwnd)
{
pWndInfo = &pHead->ChildWnd;
GetClientRect(pWndInfo->hThisWnd, &pWndInfo->rcClient);
}

LocalUnlock(hHead);
return DefMDIChildProc(hwnd, message, wParam, lParam);
}
return DefMDIChildProc(hwnd, message, wParam, lParam);
}

case WM_CLOSE:
{
PPERWNDINFO pWndInfo;
PNODE pHead, pTrail;
HANDLE hHead, hTmp;


EnableMenuItem(hClientMenu, MM_OPT_6, MF_GRAYED);
EnableMenuItem(hClientMenu, MM_OPT_7, MF_GRAYED);
EnableMenuItem(hClientMenu, MM_OPT_8, MF_GRAYED);

SendMessage(GetParent(hwnd), WM_MDISETMENU,
(DWORD) hMenu,
(LONG) hMenuWindow) ;
DrawMenuBar(GetParent(GetParent(hwnd))) ;

// Don't need to read from the edit control anymore
KillTimer(hwnd, 2);


// Unmap view, close mapping!
if (pShrMem1)
{
UnmapViewOfFile (pShrMem1);
pShrMem1 = NULL;
}

if (hMem1)
{
CloseHandle (hMem1);
hMem1 = NULL;
}


// now find match
hHead = (HANDLE) GetWindowLong(ghwndMain, 0);
if (hHead && (pHead = (PNODE)LocalLock(hHead)))
{
pTrail = pHead;
while ((pHead->ChildWnd.hThisWnd != hwnd) && (pHead->hNext))
{
hTmp = hHead;
pTrail = pHead;
hHead = pHead->hNext;
LocalUnlock(hTmp);

pHead = (PNODE) LocalLock(hHead);
}

if (pHead->ChildWnd.hThisWnd == hwnd)
{
pWndInfo = &pHead->ChildWnd;

if (pTrail == pHead)
SetWindowLong(ghwndMain, 0, (LONG) pHead->hNext);
else
pTrail->hNext = pHead->hNext;

LocalUnlock(hHead);
LocalFree(hHead);
}
else
{
LocalUnlock(hHead);
}
}
return DefMDIChildProc(hwnd, message, wParam, lParam);

}

case WM_DESTROY:
return 0l;

default:
return DefMDIChildProc(hwnd, message, wParam, lParam);
}

}




/***************************************************************************\
* About
*
* About dialog proc.
*
\***************************************************************************/

BOOL CALLBACK APIENTRY About( HWND hDlg,
UINT message,
DWORD wParam,
LONG lParam)
{
switch (message)
{
case WM_INITDIALOG:
return TRUE;

case WM_COMMAND:
if (wParam == IDOK)
EndDialog(hDlg, wParam);
break;
}
return FALSE;

UNREFERENCED_PARAMETER(lParam);
UNREFERENCED_PARAMETER(hDlg);
}

/***************************************************************************\
* MapFileName
*
* MapFileName dialog proc.
*
\***************************************************************************/

BOOL CALLBACK MapFileName( HWND hDlg,
UINT message,
DWORD wParam,
LONG lParam)
{

switch (message)
{
case WM_INITDIALOG:
return TRUE;

case WM_COMMAND:
switch (wParam)
{
case IDBTN_OK:
{
if (!GetDlgItemText(hDlg, IDEDIT_MAPNAME, gszMapName, 20))
{
strncpy(gszMapName, "MapName1", 10); // default name
}
EndDialog(hDlg, IDBTN_OK);
break;
}
}
}
return FALSE;

UNREFERENCED_PARAMETER(lParam);
UNREFERENCED_PARAMETER(hDlg);
}

/***************************************************************************\
* FileType
*
* FileType dialog proc.
*
\***************************************************************************/

BOOL CALLBACK FileType( HWND hDlg,
UINT message,
DWORD wParam,
LONG lParam)
{

switch (message)
{
case WM_INITDIALOG:
return TRUE;

case WM_COMMAND:
switch (wParam)
{
case IDBTN_PAGE:
{
EndDialog(hDlg, IDBTN_PAGE);
break;
}

case IDBTN_MAP:
{
if ((GetDlgItemText(hDlg, IDEDIT_MAPFILE, gszFile, 20)) == 0)
EndDialog(hDlg, IDBTN_PAGE); // default to use PAGE file
else
EndDialog(hDlg, IDBTN_MAP);

break;
}
}
}
return FALSE;

UNREFERENCED_PARAMETER(lParam);
UNREFERENCED_PARAMETER(hDlg);
}


/*************************************************************************
*
* TextWndProc
*
* Text Window proc.
*
\***************************************************************************/

LONG APIENTRY TextWndProc (HWND hwnd, UINT message, DWORD wParam, LONG lParam)
{
static HFONT hFont = (HFONT) NULL;

switch (message)
{
case WM_CREATE:
{
LOGFONT lf;
HDC hDC;
HFONT hOldFont;
TEXTMETRIC tm;
RECT rect;
LONG lHeight;

SystemParametersInfo(SPI_GETICONTITLELOGFONT, sizeof(lf), &lf, FALSE);

hDC = GetDC(hwnd);
// this is the height for 8 point size font in pixels
lf.lfHeight = 8 * GetDeviceCaps(hDC, LOGPIXELSY) / 72;

hFont = CreateFontIndirect(&lf);
hOldFont = SelectObject(hDC, hFont);
GetTextMetrics(hDC, &tm);
GetClientRect(GetParent(hwnd), &rect);

// base the height of the window on size of text
lHeight = tm.tmHeight+6*GetSystemMetrics(SM_CYBORDER)+2;
// saved the height for later reference
SetWindowLong(hwnd, GWL_USERDATA, lHeight);
SetWindowPos(hwnd, NULL, 0, rect.bottom-lHeight,
rect.right-rect.left, lHeight,
SWP_NOZORDER | SWP_NOMOVE);

ReleaseDC(hwnd, hDC);
break;
}

case WM_DESTROY:
if (hFont)
DeleteObject(hFont);
break;

case WM_SETTEXT:
DefWindowProc(hwnd, message, wParam, lParam);
InvalidateRect(hwnd,NULL,FALSE);
UpdateWindow(hwnd);
return 0L;

case WM_PAINT:
{
PAINTSTRUCT ps;
RECT rc;
char ach[128];
int len, nxBorder, nyBorder;
HFONT hOldFont = NULL;

BeginPaint(hwnd, &ps);

GetClientRect(hwnd,&rc);

nxBorder = GetSystemMetrics(SM_CXBORDER);
rc.left += 9*nxBorder;
rc.right -= 9*nxBorder;

nyBorder = GetSystemMetrics(SM_CYBORDER);
rc.top += 3*nyBorder;
rc.bottom -= 3*nyBorder;

// 3D Text
len = GetWindowText(hwnd, ach, sizeof(ach));
SetBkColor(ps.hdc, GetSysColor(COLOR_BTNFACE));

SetBkMode(ps.hdc, TRANSPARENT);
SetTextColor(ps.hdc, RGB(64,96,96));
if (hFont)
hOldFont = SelectObject(ps.hdc, hFont);
ExtTextOut(ps.hdc, rc.left+2*nxBorder+2, rc.top+2,
ETO_OPAQUE | ETO_CLIPPED, &rc, ach, len, NULL);

SetTextColor(ps.hdc, RGB(128,128,128));
if (hFont)
hOldFont = SelectObject(ps.hdc, hFont);
ExtTextOut(ps.hdc, rc.left+2*nxBorder+1, rc.top+1, ETO_CLIPPED,
&rc, ach, len, NULL);

SetTextColor(ps.hdc, RGB(255,255,255));
if (hFont)
hOldFont = SelectObject(ps.hdc, hFont);
ExtTextOut(ps.hdc, rc.left+2*nxBorder, rc.top, ETO_CLIPPED,
&rc, ach, len, NULL);

SetBkMode(ps.hdc, OPAQUE);

if (hOldFont)
SelectObject(ps.hdc, hOldFont);

EndPaint(hwnd, &ps);
return 0L;
}
}
return DefWindowProc(hwnd, message, wParam, lParam);
}


//---------------------------------------------------------------------------
//
// FUNCTION: GetStringRes (int id INPUT ONLY)
//
// COMMENTS: Load the resource string with the ID given, and return a
// pointer to it. Notice that the buffer is common memory so
// the string must be used before this call is made a second time.
//
//---------------------------------------------------------------------------

LPTSTR GetStringRes (int id)
{
static TCHAR buffer[MAX_PATH];

buffer[0]=0;
LoadString (GetModuleHandle (NULL), id, buffer, MAX_PATH);
return buffer;
}