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