Some of you have noticed that I insist on generating executables that
work on as many platforms as possible, and that I have come very
close, except for menus. Well, I _finally_ did some experiments with
minimal programs, and am sharing my results.

I used an iPAQ 3665, running Pocket PC (2000) on an ARM-compatible CPU
for all tests. And I used eVC 3 for all builds.

When I build using the HPC Pro SDK, the TaskBar is on the bottom. When
I build using the Pocket PC SDK, the TaskBar is on the top. I think
that means that, unless I'm willing to do some serious hacking, I
can't have a single executable run on all platforms with TaskBar and
menus in the "normal" (for each platform) position. Not a tragedy, but
generating, distributing, and installing the extra executables is a
nuisance, and (in case you haven't noticed) bugs me.

I will still see whether I can get HPC Pro builds running on all
platforms with TaskBar on the bottom and menus on the top. But even
though I think that is functional, it is probably unacceptable for
"esthetic" reasons.

The entire source code is below. Near the top of the CPP file, a
section labeled "SWITCHES" defines a couple of macros that are used in
compile-time directives later to enable/disable some sections of code.
I used this method to try both modal and non-modal dialog box, and to
call SHInitDialog or not. I did not test menus.

I used an icon for my tests, but didn't bother including it and
disabled the reference in the code below. I _assume_ that won't affect
the results.

I could probably debug the Pocket PC builds directly. But I can't
debug the more interesting builds (the HPC Pro builds) because the IDE
prevents cross-platform debugging (another peeve:-{


=================================================
-> Header (.h file)
=================================================
// Header for Test Bed, a project for miscellaneous tests

#define IDD_MAIN 100
#define IDC_BUTTON_EXIT 1010

#include <windows.h> // Always include windows.h first

=================================================
-> Resource Script (.rc file)
=================================================
//
// TestBed.RC - resources for Test Bed, a project for miscellaneous
tests
//

#include "TestBed.h"


// Enable the next section to include an icon
//#define USE_ICON
#ifdef USE_ICON
#define IDR_MAINFRAME 128
IDR_MAINFRAME ICON DISCARDABLE "TestBed.ico"
#endif


/////////////////////////////////////////////////////////////////////////////
//
// Dialog(s)
//

IDD_MAIN DIALOG 0, 0, 240, 160
STYLE WS_OVERLAPPED | DS_SETFOREGROUND | DS_CENTER | WS_CAPTION |
WS_VISIBLE
CAPTION "Test Bed"
#ifdef UNDER_CE
EXSTYLE WS_EX_NODRAG
#endif
BEGIN
DEFPUSHBUTTON "Exit",IDC_BUTTON_EXIT, 53, 126, 30, 20
END

=================================================
-> Source (.cpp file)
=================================================
// Source file for Test Bed, a project for miscellaneous tests

//
--------------------------------------------------------------------
// SWITCHES
//
--------------------------------------------------------------------

// Activate the next line to have program find and call SHInitDialog
(if platform includes)
// When compiled for Pocket PC, has no visible effect
// When compiled for HPC Pro, leaves space just above Task Bar
//#define CALL_SHINITDIALOG

// Activate the next line to have program use modal dialog
//#define DO_MODAL

//
--------------------------------------------------------------------


#include "TestBed.h"

#define PROGRAM_NAME "Test Bed"

const TCHAR TNULL = _T( '\0' );

static HWND s_hWnd = NULL;
static HINSTANCE s_hInst = NULL;


#if defined( CALL_SHINITDIALOG )
#if !defined( SHINITDLGINFO )
// Copied from Aygshell.h for original Pocket PC

// For SHInitDialog
typedef struct tagSHINITDLGINFO
{
DWORD dwMask;
HWND hDlg;
DWORD dwFlags;
} SHINITDLGINFO, *PSHINITDLGINFO;
#define SHIDIM_FLAGS 0x0001
#define SHIDIF_DONEBUTTON 0x0001
#define SHIDIF_SIZEDLG 0x0002
#define SHIDIF_SIZEDLGFULLSCREEN 0x0004
#define SHIDIF_SIPDOWN 0x0008
#define SHIDIF_FULLSCREENNOMENUBAR 0x0010


// For SHFullScreeen

#define SHFS_SHOWTASKBAR 0x0001
#define SHFS_HIDETASKBAR 0x0002
#define SHFS_SHOWSIPBUTTON 0x0004
#define SHFS_HIDESIPBUTTON 0x0008
#define SHFS_SHOWSTARTICON 0x0010
#define SHFS_HIDESTARTICON 0x0020
#endif

typedef BOOL (*InitD)( SHINITDLGINFO * );
typedef BOOL (*ShowFull)( HWND, DWORD );

#endif


//
--------------------------------------------------------------------
static inline LPCTSTR getEMsg( DWORD dwRc )
{
const DWORD dLen = 200;
static TCHAR sBuf[dLen+1];

sBuf[0] = TNULL;

// Use 0 for default language - not supported under CE
::FormatMessage( FORMAT_MESSAGE_FROM_SYSTEM, NULL, dwRc, 0, sBuf,
dLen, NULL );

return sBuf;

}


//
--------------------------------------------------------------------
static inline void showMsg( LPCTSTR sMsg )
{
::MessageBox( s_hWnd, sMsg, _T( PROGRAM_NAME ), MB_OK );
}


//
--------------------------------------------------------------------
static inline void showEMsg( LPCTSTR sExtra )
{
DWORD dwRc = ::GetLastError();
TCHAR sMsg[200];

_stprintf( sMsg, _T( "Message for error %d %s: %s" ), dwRc,
sExtra, getEMsg( dwRc ) );
showMsg( sMsg );
}


//
--------------------------------------------------------------------
static inline BOOL CALLBACK dlgProc( HWND hDlg, UINT uMsg, WPARAM
wParam, LPARAM lParam )
{
if (uMsg == WM_COMMAND)
{
int nID = LOWORD( wParam );
if (nID == IDC_BUTTON_EXIT)
::PostQuitMessage( IDCLOSE );
}
else if (uMsg == WM_INITDIALOG)
{
s_hWnd = hDlg;

#ifdef CALL_SHINITDIALOG

HINSTANCE hInst = ::LoadLibrary( _T( "AygShell.dll" ) );
InitD pInit = reinterpret_cast<InitD>(::GetProcAddress( hInst,
_T( "SHInitDialog" ) ));
ShowFull pShow = reinterpret_cast<ShowFull>(::GetProcAddress(
hInst, _T( "SHFullScreen" ) ));

if (pInit != NULL)
{
SHINITDLGINFO shidi;

shidi.dwMask = SHIDIM_FLAGS;
shidi.dwFlags = SHIDIF_SIZEDLGFULLSCREEN | SHIDIF_SIPDOWN;
shidi.hDlg = s_hWnd;
if (!pInit( &shidi ))
showMsg( _T( "Call to SHInitDialog failed" ));

if (!pShow( s_hWnd, SHFS_SHOWSTARTICON ))
showMsg(_T( "Call to SHFullScreen failed" ));
}
else
showMsg( _T( "AygShell not found." ) );
#endif
}

return FALSE;

}


//
--------------------------------------------------------------------
int APIENTRY WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance,
LPTSTR lpCmdLine, int nCmdShow )
{

s_hInst = hInstance;

// NOTE: using NULL instead of hInstance causes failure (resource
not found) on real
// device, but not in emulator!!!*(*&(*&(!
// Dialog will be visible even if it does not have WS_VISIBLE
style
#ifdef DO_MODAL
// Modal
int nRc = ::DialogBox( hInstance, MAKEINTRESOURCE( IDD_MAIN ),
NULL, dlgProc );

if (nRc == -1)
showEMsg(_T( "Calling DialogBox" ));
#else
// Non-modal
// Dialog won't be visible unless it has WS_VISIBLE style
int nRc = 0;
MSG msg;

s_hWnd = ::CreateDialog( hInstance, MAKEINTRESOURCE( IDD_MAIN ),
NULL, dlgProc );
if (s_hWnd == NULL || !::IsWindow( s_hWnd ))
showEMsg(_T( "Calling CreateDialog" ));
else
{
while(::GetMessage( &msg, NULL, 0, 0 ) > 0)
{
TranslateMessage( &msg );
::DispatchMessage( &msg );
}
nRc = static_cast<int>(msg.wParam);
}
#endif

return nRc;

}

-----------------------------------------
To reply to me, remove the underscores (_) from my email address (and please indicate which newsgroup and message).

Robert E. Zaret, eMVP
PenFact, Inc.
20 Park Plaza, Suite 478
Boston, MA 02116
www.penfact.com

Re: Menus and Multiple Platforms by r_z_aret

r_z_aret
Mon Aug 13 15:53:05 CDT 2007

On Thu, 09 Aug 2007 15:54:19 -0400, r_z_aret@pen_fact.com wrote:

>Some of you have noticed that I insist on generating executables that
>work on as many platforms as possible, and that I have come very
>close, except for menus. Well, I _finally_ did some experiments with
>minimal programs, and am sharing my results.

I modified the source code a bit to add menus (new source below), and
then tested on several devices with ARM-compatible CPUs:
HHP Dolphin 7400 (Windows CE 3.0, but not a Microsoft platform)
Compaq iPAQ 3660 (Pocket PC)
HP Jornada 565 (Pocket PC 2002)
Dell Axim X50 (Pocket PC 2003 SE)
i-Mate JasJar (Windows Mobile 5 for Pocket PC)
Motorola MPX200 (Smartphone 2002)

No actual HPC Pro device, because I don't have any with an
ARM-compatible CPU


When I built for Pocket PC, the program worked on all the devices
except the Dolphin (not a Pocket PC). The push button was in the
middle and worked. The Task Bar was at the top of the screen and
worked. For all the Pocket PCs, the menu was on the bottom of the
screen and worked. For the MPX200, the menu was not visible (call to
SHMenuBarCreate failed with error 87 "The parameter is invalid").

When I built for HPC Pro, the program worked on all devices. The push
button was in the middle and worked. The Task Bar was at the bottom of
the screen and worked on all but the MPX200; on the MPX200, the Task
Bar was at the top of the screen and worked. The menu was on the top
of the screen and worked on all the Pocket PCs except the Axim; the
menu was not visible on the Axim (and no error message). The menu was
at the top on the MPX200, but not useable (no touch screen).

When I built for Smartphone 2002, the program worked on the MPX200.
The push button was in the middle and worked. The Task Bar was at the
bottom of the screen and worked. The menu was on the bottom of the
screen and worked.

I'm not at all surprised that menus in HPC Pro executables don't work
on Smartphones. I'm mildly surprised they don't work on the Axim; I
knew 2003 (maybe just SE) had a problem, but thought my code included
a workaround. I'm surprised and annoyed that menus in Pocket PC
executables don't work in Smartphone.

So, if I want to maximize my support for commercial devices, I'll need
to build for HPC Pro, Pocket PC, and Smartphone.

Source code follows. The header (.h) file includes some "switches":
macros that control other code; for those who look at my earlier
version, I added a switch and moved the others from the source file.

=================================================
-> Header (.h file)
=================================================
//
// Header for TestBed, a project for miscellaneous tests
//
// By Robert E. Zaret


//
--------------------------------------------------------------------
// SWITCHES
//
--------------------------------------------------------------------

// Activate the next line to have program find and call SHInitDialog
// (on platforms that support it).
// When compiled for Pocket PC, has no visible effect
// When compiled for HPC Pro, leaves space just above Task Bar
//#define CALL_SHINITDIALOG

// Activate the next line to have program use modal dialog. No visible
effect.
//#define DO_MODAL

// Activate the next line to have program show a menu
#define SHOW_MENU

//
--------------------------------------------------------------------


#if defined( WIN32_PLATFORM_PSPC )
#define FOR_PocketPC
#elif defined( WIN32_PLATFORM_WFSP )
#define FOR_Smartphone
#endif

#if defined( FOR_PocketPC ) || defined( FOR_Smartphone )
#define FOR_WindowsMobile
#endif

#include <windows.h> // Always include windows.h first
#ifdef UNDER_CE
#include <commctrl.h>
#endif


#define IDD_MAIN 100
#define IDC_BUTTON_EXIT 1010

#define PROGRAM_NAME "Test Bed"
#define PROGRAM_VERSION "1.1"

#if defined( FOR_PocketPC )
#define PLATFORM "Pocket PC"
#elif defined( FOR_Smartphone )
#define PLATFORM "Smartphone"
#elif defined( UNDER_CE )
#define PLATFORM "HPC Pro"
#else
#define PLATFORM "Desktop"
#endif

#ifdef SHOW_MENU
#define IDM_ABOUT 1012
#define IDM_CMDBAR_MAIN 1020

#define HELP_ABOUT_STRING "About..."
#endif

// NOTE: If this header file does not end with a carriage return, the
resource
// compiler complains about unexpected end of file.


=================================================
-> Resource Script (.rc file)
=================================================
//
// TestBed.RC - resources for TestBed, a project for miscellaneous
tests
//
// By Robert E. Zaret


#include "TestBed.h"
#ifdef FOR_WindowsMobile
// For Pocket PC menu support ("usually" generated by Application
Wizard)
// Included for all CE (as of 22 Dec 06) to support dynamic menus
#include <NewRes.h>
#endif


// If the resource editor is allowed to edit this file, it will
"kindly"
// rewrite the file and expands (translates) all macros.
Unfortunately,
// that ruins the file because it depends on macros defined
elsewhere.
// Thus, the next section keeps the resource editor from touching
this
// file. To edit this file using the IDE's text editor, change syntax
// to cause a compilation error, then double click on the error
notice.
// Once the file is open, it will stay open.
#ifdef APSTUDIO_INVOKED
#error this file is not editable by Microsoft Visual C++
#endif //APSTUDIO_INVOKED

// Enable the next section to include an icon
#define USE_ICON
#ifdef USE_ICON
#define IDR_MAINFRAME 128
IDR_MAINFRAME ICON DISCARDABLE "TestBed.ico"
#endif


/////////////////////////////////////////////////////////////////////////////
//
// Dialog(s)
//

IDD_MAIN DIALOG 0, 0, 240, 160
#ifdef UNDER_CE
STYLE WS_OVERLAPPED | DS_SETFOREGROUND | DS_CENTER | WS_CAPTION |
WS_VISIBLE
#else
STYLE WS_OVERLAPPED | DS_SETFOREGROUND | DS_CENTER | WS_CAPTION |
WS_VISIBLE | WS_THICKFRAME
#endif
CAPTION PROGRAM_NAME
#ifdef UNDER_CE
EXSTYLE WS_EX_NODRAG
#endif
BEGIN
// Will be resized dynamically, so dimensions don't matter
DEFPUSHBUTTON "Exit",IDC_BUTTON_EXIT, 53, 126, 30, 20
END


#if defined( SHOW_MENU )

/////////////////////////////////////////////////////////////////////////////
//
// Menu(s)
//

#if defined( FOR_WindowsMobile )

#define IDS_HELP 402
#define IDM_HELP 101
#define HELP_STRING "Help"

// Macros to make sure strings used in SHMENUBAR definition match
// strings used in actual menu (otherwise SHCreateMenuBar fails)
// Ampersands (for shortcuts) cause failure for Pocket PC (and
probably
// Smartphone menus and are ignored for other CE platforms
#define PREFERENCES_STRING "Preferences"

#if 0
IDM_CMDBAR_MAIN SHMENUBAR DISCARDABLE
#else
// 18 Apr 03 (5.0.0.1) from Boling 2nd Edition, p. 783
IDM_CMDBAR_MAIN SHMENUBAR MOVEABLE PURE
#endif

BEGIN
IDM_CMDBAR_MAIN, 1,
I_IMAGENONE, IDM_HELP, TBSTATE_ENABLED, TBSTYLE_DROPDOWN |
TBSTYLE_AUTOSIZE, IDS_HELP, 0, 0,
END

STRINGTABLE DISCARDABLE
BEGIN
IDS_HELP HELP_STRING
END

#else // FOR_WindowsMobile

#define HELP_STRING "&Help"

#endif // FOR_WindowsMobile


IDM_CMDBAR_MAIN MENU DISCARDABLE
BEGIN
POPUP HELP_STRING
BEGIN
MENUITEM HELP_ABOUT_STRING, IDM_ABOUT
END
END

#endif // SHOW_MENU


=================================================
-> Source (.cpp file)
=================================================
//
// Source file for TestBed, a project for miscellaneous tests
//
// By Robert E. Zaret


#include "TestBed.h"

#ifndef UNDER_CE
#include <tchar.h>
#include <stdio.h>
#endif

#if defined( FOR_WindowsMobile ) && defined( SHOW_MENU )
#include <AygShell.h>
#pragma comment( lib, "AygShell.lib" )
#endif

const TCHAR TNULL = _T( '\0' );
static HWND s_hWnd = NULL,
s_hWndMB = NULL;
static HINSTANCE s_hInst = NULL;


//
--------------------------------------------------------------------
#if defined( CALL_SHINITDIALOG )
#if !defined( SHINITDLGINFO )
// Copied from Aygshell.h for original Pocket PC
typedef struct tagSHINITDLGINFO
{
DWORD dwMask;
HWND hDlg;
DWORD dwFlags;
} SHINITDLGINFO, *PSHINITDLGINFO;
#define SHIDIM_FLAGS 0x0001
#define SHIDIF_DONEBUTTON 0x0001
#define SHIDIF_SIZEDLG 0x0002
#define SHIDIF_SIZEDLGFULLSCREEN 0x0004
#define SHIDIF_SIPDOWN 0x0008
#define SHIDIF_FULLSCREENNOMENUBAR 0x0010
#endif

typedef BOOL (*InitD)( SHINITDLGINFO * );
typedef BOOL (*ShowFull)( HWND, DWORD );

#endif


//
--------------------------------------------------------------------
static inline LPCTSTR getEMsg( DWORD dwRc )
{
const DWORD dLen = 200;
static TCHAR sBuf[dLen+1];

sBuf[0] = TNULL;

// Use 0 for default language - not supported under CE
::FormatMessage( FORMAT_MESSAGE_FROM_SYSTEM, NULL, dwRc, 0, sBuf,
dLen, NULL );

return sBuf;

}


//
--------------------------------------------------------------------
static inline void showMsg( LPCTSTR sMsg )
{
::MessageBox( s_hWnd, sMsg, _T( PROGRAM_NAME ), MB_OK );
}


//
--------------------------------------------------------------------
static inline void showEMsg( LPCTSTR sExtra )
{
DWORD dwRc = ::GetLastError();
TCHAR sMsg[200];

_stprintf( sMsg, _T( "Message for error %d %s: %s" ), dwRc,
sExtra, getEMsg( dwRc ) );
showMsg( sMsg );
}


//
--------------------------------------------------------------------
static inline BOOL CALLBACK dlgProc( HWND hDlg, UINT uMsg, WPARAM
wParam, LPARAM lParam )
{
if (uMsg == WM_COMMAND)
{
int nID = LOWORD( wParam );

if (nID == IDC_BUTTON_EXIT)
::PostQuitMessage( IDCLOSE );
#if defined( SHOW_MENU )
else if (nID == IDM_ABOUT)
{
TCHAR sMsg[200];
_stprintf( sMsg, _T( "Version %s for %s"), _T(
PROGRAM_VERSION ), _T( PLATFORM ) );
::MessageBox( s_hWnd, sMsg, _T( PROGRAM_NAME ), MB_OK );
}
#endif
}
else if (uMsg == WM_SIZE)
{
// Center pushbutton
RECT rWork;

if (::GetClientRect( s_hWnd, &rWork ))
{
int iBHeight = (rWork.bottom - rWork.top) / 5,
iBWidth = (rWork.right - rWork.left) / 5;
HWND hWnd = ::GetDlgItem( s_hWnd, IDC_BUTTON_EXIT );

rWork.left = (rWork.left + rWork.right - iBWidth) / 2;
rWork.right = iBWidth;
rWork.top = (rWork.bottom + rWork.top - iBHeight) / 2;
rWork.bottom = iBHeight;
if (!::MoveWindow( hWnd, rWork.left, rWork.top,
rWork.right, rWork.bottom, TRUE ))
{
showMsg( _T( "Call to MoveWindow for button failed." )
);
}
if (s_hWndMB != NULL)
::UpdateWindow( s_hWndMB );
}
else
{
showEMsg( _T( "Calling GetClientRect" ) );
}
}
else if (uMsg == WM_INITDIALOG)
{
s_hWnd = hDlg;

#ifdef UNDER_CE
// Make dialog box fit whole window
RECT rWork;

if (!::SystemParametersInfo( SPI_GETWORKAREA, 0, &rWork, 0 ))
{
showMsg( _T( "Call to SystemParametersInfo failed." ) );
}
else if (!::MoveWindow( s_hWnd, rWork.left, rWork.top,
rWork.right, rWork.bottom, FALSE ))
{
showMsg( _T( "Call to MoveWindow for window failed." ) );
}
#endif

#ifdef CALL_SHINITDIALOG

HINSTANCE hInst = ::LoadLibrary( _T( "AygShell.dll" ) );
InitD pInit = reinterpret_cast<InitD>(::GetProcAddress(
hInst, _T( "SHInitDialog" ) ));
ShowFull pShow = reinterpret_cast<ShowFull>(::GetProcAddress(
hInst, _T( "SHFullScreen" ) ));

if (pInit != NULL)
{
SHINITDLGINFO shidi;

shidi.dwMask = SHIDIM_FLAGS;
shidi.dwFlags = SHIDIF_SIZEDLGFULLSCREEN | SHIDIF_SIPDOWN;
shidi.hDlg = s_hWnd;
if (!pInit( &shidi ))
showMsg( _T( "Call to SHInitDialog failed" ));

if (!pShow( s_hWnd, SHFS_SHOWSTARTICON ))
showMsg(_T( "Call to SHFullScreen failed" ));
}
else
showMsg( _T( "AygShell not found." ) );
#endif

#if defined( SHOW_MENU )
#if defined( FOR_WindowsMobile )
UINT uID = IDM_CMDBAR_MAIN;
SHMENUBARINFO mbi;

::memset( &mbi, 0, sizeof( SHMENUBARINFO ) );
mbi.cbSize = sizeof( SHMENUBARINFO );
mbi.hwndParent = s_hWnd;
mbi.dwFlags = 0;
mbi.nToolBarId = uID;
mbi.hInstRes = s_hInst;
mbi.nBmpId = 0;
mbi.cBmpImages = 0;

if (!SHCreateMenuBar( &mbi ))
{
showEMsg( _T( "Calling SHCreateMenuBar" ) );
}
#elif defined( UNDER_CE )
// Windows CE, but neither Pocket PC nor Smartphone
INITCOMMONCONTROLSEX icex;

icex.dwSize = sizeof( icex );
icex.dwICC = ICC_BAR_CLASSES;
if (!::InitCommonControlsEx( &icex ))
{
showEMsg( _T( "Calling InitCommonControlsEx" ) );
return FALSE;
}

s_hWndMB = ::CommandBar_Create( s_hInst, s_hWnd, 1 );
LPTSTR ps = MAKEINTRESOURCE( IDM_CMDBAR_MAIN ); //
Notational convenience

if (!::CommandBar_InsertMenubarEx( s_hWndMB, s_hInst, ps, 0 ))
{
showEMsg( _T( "Inserting menu" ) );
return FALSE;
}

HMENU hMenu = ::CommandBar_GetMenu( s_hWnd, 0 );
// Seems to fix problem when old builds run in "emulation
mode" under Pocket PC 2003
// or later.
// See 14 Feb 06 contribution by Jeff Hu to thread called
"MenuBar Disappeared"
// in microsoft.public.windowsce.embedded.vc
::CommandBar_Show( s_hWndMB, TRUE );
#else
// "Big" Windows
// TODO: Why does lint declare type mismatch for arg 2?
HMENU hMenu = ::LoadMenu( s_hInst, MAKEINTRESOURCE(
IDM_CMDBAR_MAIN ) );
if (!::SetMenu( s_hWnd, hMenu ))
showEMsg( _T( "Setting menu" ) );
#endif
#endif

}

return FALSE;

}


//
--------------------------------------------------------------------
int APIENTRY WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance,
LPTSTR lpCmdLine, int nCmdShow )
{

s_hInst = hInstance;

// NOTE: using NULL instead of hInstance causes failure (resource
not found) on real
// device, but not in emulator!!!*(*&(*&(!
// Dialog will be visible even if it does not have WS_VISIBLE
style
#ifdef DO_MODAL
// Modal
int nRc = ::DialogBox( hInstance, MAKEINTRESOURCE( IDD_MAIN ),
NULL, dlgProc );

if (nRc == -1)
showEMsg(_T( "Calling DialogBox" ));
#else
// Non-modal
// Dialog won't be visible unless it has WS_VISIBLE style
int nRc = 0;
MSG msg;

s_hWnd = ::CreateDialog( hInstance, MAKEINTRESOURCE( IDD_MAIN ),
NULL, dlgProc );
if (s_hWnd == NULL || !::IsWindow( s_hWnd ))
showEMsg(_T( "Calling CreateDialog" ));
else
{
while(::GetMessage( &msg, NULL, 0, 0 ) > 0)
{
if (::IsDialogMessage( s_hWnd, &msg ))
continue;
TranslateMessage( &msg );
::DispatchMessage( &msg );
}
nRc = static_cast<int>(msg.wParam);
}
#endif

return nRc;

}

-----------------------------------------
To reply to me, remove the underscores (_) from my email address (and please indicate which newsgroup and message).

Robert E. Zaret, eMVP
PenFact, Inc.
20 Park Plaza, Suite 478
Boston, MA 02116
www.penfact.com