Splash.h
////////////////////////////////////////////////////////////////
// Microsoft Systems Journal -- October 1999
// If this code works, it was written by Paul DiLascia.
// If not, I don't know who wrote it.
// Compiles with Visual C++ 6.0, runs on Windows 98 and probably Windows NT too.
//
#pragma once
#ifndef NODIB
#include "dib.h"
#endif
//////////////////////////////////////////////////////////////////
// Splash screen. To use it, write:
//
// CSplash *pSplash = new CSplash(
// IDB_MYBITMAP, // resource ID of bitmap
// duration, // min time to display, in msec
// flags, // see below
// &pSplash); // address of back pointer
//
// If you want to kill the screen, you can call
//
// if (pSplash)
// pSplash->Kill();
//
// but this is usually unnecessary. You don't have to call delete either;
// CSplash will delete itself. When it does, it sets your pointer to NULL so
// you won't try to call Kill on a bad pointer.
//
class CSplash : public CWinThread {
public:
CSplash(UINT nIDRes, // resource ID of bitmap
UINT duration, // how long to show (minimum)
WORD flags=0, // see below
CSplash** ppBackPtr=NULL); // pointer to NULL when destroyed
~CSplash();
enum { // flags
KillOnClick = 0x0001, // any key/mouse dismisses splash
IgnoreCmdLine = 0x0002, // need I say more?
};
// override to create a different kind of splash window
virtual CWnd* OnCreateSplashWnd(UINT nIDRes, UINT duration, WORD flags);
void Kill(); // kill the splash screen
protected:
CSplash** m_ppBackPtr; // caller's back pointer to me
UINT m_nIDRes; // bitmap resource ID
UINT m_duration; // how long to display
WORD m_flags; // CSplashWnd creation flags
virtual BOOL InitInstance();
DECLARE_DYNAMIC(CSplash)
};
//////////////////
// Splash window. This class is private to CSplash--Don't use it unless
// you are doing some hairy stuff to override the splash window, like
// create animated effects, etc.
//
class CSplashWnd : public CWnd {
protected:
friend CSplash;
CSplashWnd();
~CSplashWnd();
#ifdef NODIB
CBitmap m_bitmap; // ordinary MFC bitmap
#else
CDib m_dib; // Device independent bitmap
#endif
UINT m_duration; // duration (msec)
WORD m_flags; // see below
// override to do weird stuff
virtual BOOL Create(UINT nIDRes, UINT duration, WORD flags);
virtual BOOL PreTranslateMessage(MSG* pMsg);
virtual void PostNcDestroy();
afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct);
afx_msg void OnClose();
afx_msg void OnPaint();
afx_msg void OnTimer(UINT nIDEvent);
DECLARE_MESSAGE_MAP()
DECLARE_DYNAMIC(CSplashWnd)
};
Splash.cpp
/////////////////////////////////////////////////////////////////
// Microsoft Systems Journal -- October 1999
// If this code works, it was written by Paul DiLascia.
// If not, I don't know who wrote it.
// Compiles with Visual C++ 6.0, runs on Windows 98 and probably Windows NT too.
//
#include "stdafx.h"
#include "Splash.h"
#include "cmdline.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char BASED_CODE THIS_FILE[] = __FILE__;
#endif
IMPLEMENT_DYNAMIC(CSplashWnd, CWnd)
BEGIN_MESSAGE_MAP(CSplashWnd, CWnd)
ON_WM_CREATE()
ON_WM_CLOSE()
ON_WM_PAINT()
ON_WM_TIMER()
END_MESSAGE_MAP()
////////////////////////////////////////////////////////////////
// CSplashWnd : the splash window
CSplashWnd::CSplashWnd()
{
}
CSplashWnd::~CSplashWnd()
{
}
//////////////////
// Create splash window: load bitmap and create the window
//
BOOL CSplashWnd::Create(UINT nIDRes, UINT duration, WORD flags)
{
#ifdef NODIB
// Code for ordinary bitmap (assumes m_bitmap is a CBitmap)
if (!m_bitmap.LoadBitmap(nIDRes))
return FALSE;
BITMAP bm;
m_bitmap.GetBitmap(&bm);
CSize sz(bm.bmWidth, bm.bmHeight);
#else
if (!m_dib.Load(nIDRes))
return FALSE;
CSize sz = m_dib.GetSize();
#endif
m_duration = duration;
m_flags = flags;
return CreateEx(0,
AfxRegisterWndClass(0, AfxGetApp()->LoadStandardCursor(IDC_ARROW)),
NULL,
WS_POPUP | WS_VISIBLE,
0, 0, sz.cx, sz.cy,
NULL, // parent wnd
NULL);
}
//////////////////
// Handle close message: quit
//
void CSplashWnd::OnClose()
{
DestroyWindow();
}
//////////////////
// Splash window created: center it, move to foreground and set a timer
//
int CSplashWnd::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
if (CWnd::OnCreate(lpCreateStruct) == -1)
return -1;
CenterWindow();
UpdateWindow();
SetForegroundWindow();
if (m_duration!=-1)
SetTimer(1, m_duration, NULL);
return 0;
}
//////////////////
// The window has been destroyed: put main app in foreground
// and post a message to quit this thread.
//
void CSplashWnd::PostNcDestroy()
{
CWinApp* pApp = AfxGetApp();
CWnd* pMainWnd = pApp->m_pMainWnd;
if (pMainWnd && IsWindow(pMainWnd->m_hWnd))
::SetForegroundWindow(pMainWnd->m_hWnd);
delete this;
}
//////////////////
// Draw the bitmap.
//
void CSplashWnd::OnPaint()
{
CPaintDC dc(this);
#ifdef NODIB
// Code for ordinary bitmap:
CDC dcImage;
if (!dcImage.CreateCompatibleDC(&dc))
return;
BITMAP bm;
m_bitmap.GetBitmap(&bm);
// Paint the image.
CBitmap* pOldBitmap = dcImage.SelectObject(&m_bitmap);
dc.BitBlt(0, 0, bm.bmWidth, bm.bmHeight, &dcImage, 0, 0, SRCCOPY);
dcImage.SelectObject(pOldBitmap);
#else
m_dib.Draw(dc);
#endif
}
//////////////////
// Timer expired: kill myself--unless the app has
// not created a main window yet.
//
void CSplashWnd::OnTimer(UINT nIDEvent)
{
CWinApp* pApp = AfxGetApp();
CWnd* pMainWnd = pApp->m_pMainWnd;
if ((m_flags & CSplash::NoWaitForMainWnd) ||
IsWindow(pMainWnd->GetSafeHwnd()))
// have main window: OK to die
SendMessage(WM_CLOSE)
else
// no main window: keep splashing
SetTimer(1,100,NULL);
}
//////////////////
// Before translating keystroke or mouse: die
//
BOOL CSplashWnd::PreTranslateMessage(MSG* pMsg)
{
if (m_flags & CSplash::KillOnClick) {
UINT msg = pMsg->message;
if (msg == WM_KEYDOWN ||
msg == WM_SYSKEYDOWN ||
msg == WM_LBUTTONDOWN ||
msg == WM_RBUTTONDOWN ||
msg == WM_MBUTTONDOWN)
{
PostMessage(WM_CLOSE); // post don't send, to let current msg process
return TRUE; // eat it
}
}
return CWnd::PreTranslateMessage(pMsg);
}
////////////////////////////////////////////////////////////////
// CSplash, a thread object
IMPLEMENT_DYNAMIC(CSplash, CWinThread)
//////////////////
// Create a new splash thread
//
CSplash::CSplash(UINT nIDRes, UINT duration, WORD flags, CSplash** ppBackPtr)
{
m_ppBackPtr = ppBackPtr;
m_nIDRes = nIDRes;
m_duration = duration;
m_flags = flags;
CreateThread();
}
/////////////////
// Destruction: Set caller's pointer to NULL, so he knows I'm gone.
//
CSplash::~CSplash()
{
if (m_ppBackPtr)
*m_ppBackPtr = NULL;
}
//////////////////
// Thread initialization.
// Returns TRUE to keep running, otherwise FALSE
// if I determine I'm not supposed to run the splash
//
BOOL CSplash::InitInstance()
{
// Check for -nologo switch
CWinApp* pApp = AfxGetApp();
ASSERT(pApp);
// Look for -nologo switch, or any others that MFC thinks should
// prohibit a splash screen (such as OLE embedding, etc.)
//
if (!(m_flags & IgnoreCmdLine)) {
CCommandLineInfoEx cmdinfo;
pApp->ParseCommandLine(cmdinfo);
if (!cmdinfo.m_bShowSplash || cmdinfo.GetOption(_T("nologo")))
return FALSE;
}
if (!AfxOleGetUserCtrl()) // running without UI: to be safe
return FALSE;
// Create the splash window
m_pMainWnd = OnCreateSplashWnd(m_nIDRes, m_duration, m_flags);
return m_pMainWnd != NULL;
}
//////////////////
// Create the splash window. This is virtual so you can override to create
// some other kind of window if you like.
//
CWnd* CSplash::OnCreateSplashWnd(UINT nIDRes, UINT duration, WORD flags)
{
CSplashWnd *pSplashWnd = new CSplashWnd;
if (pSplashWnd)
pSplashWnd->Create(nIDRes, duration, flags);
return pSplashWnd;
}
//////////////////
// Kill the splash window. Could set a CEvent to terminate thread,
// but easier to simply post a close message to the window.
//
void CSplash::Kill()
{
if (m_pMainWnd)
m_pMainWnd->PostMessage(WM_CLOSE);
}
Figure 5 Standard Command-Line Switches
Switch
|
Function
|
-pt
|
Print to specific printer,driver,port
|
-p
|
Print
|
-Unregister
|
Unregister the app/server
|
-Unregserver
|
Same as -Unregister
|
-dde
|
DDE command
|
-Embedding
|
Run app as embedded OLE object
|
-Automation
|
Run app as automation server
|
Figure 6 CmdLine
CmdLine.h
////////////////////////////////////////////////////////////////
// Microsoft Systems Journal -- October 1999
// If this code works, it was written by Paul DiLascia.
// If not, I don't know who wrote it.
// Compiles with Visual C++ 6.0, runs on Windows 98 and probably Windows NT too.
//
#pragma once
//////////////////
// Improved CCommandLineInfo parses arbitrary switches.
// Use instead of CCommandLineInfo:
//
// CCommandLineInfoEx cmdinfo;
// ParseCommandLine(cmdinfo); // (from app object)
//
// After parsing, you can call GetOption to get the value of any switch. Eg:
//
// if (cmdinfo.GetOption("nologo")) {
// // handle it
// }
//
// to get the value of a string option, type
//
// CString filename;
// if (cmdinfo.GetOption("f")) {
// // now filename is string following -f option
// }
//
class CCommandLineInfoEx : public CCommandLineInfo {
public:
BOOL GetOption(LPCTSTR option, CString& val);
BOOL GetOption(LPCTSTR option) {
return GetOption(option, CString());
}
protected:
CMapStringToString m_options; // hash of options
CString m_sLastOption; // last option encountered
virtual void ParseParam(const TCHAR* pszParam, BOOL bFlag, BOOL bLast);
};
CmdLine.cpp
////////////////////////////////////////////////////////////////
// Microsoft Systems Journal -- October 1999
// If this code works, it was written by Paul DiLascia.
// If not, I don't know who wrote it.
// Compiles with Visual C++ 6.0, runs on Windows 98 and probably Windows NT
//
#include "stdafx.h"
#include "cmdline.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
//////////////////
// Parse a command line parameter/token. Just add it to the table.
//
void CCommandLineInfoEx::ParseParam(const TCHAR* pszParam, BOOL bFlag,
BOOL bLast)
{
if (bFlag) {
// this is a "flag" (begins with / or -)
m_options[pszParam] = "TRUE"; // default value is "TRUE"
m_sLastOption = pszParam; // save in case other value specified
} else if (!m_sLastOption.IsEmpty()) {
// last token was option: set value
m_options[m_sLastOption] = pszParam;
m_sLastOption.Empty(); // clear
}
// Call base class so MFC can see this param/token.
CCommandLineInfo::ParseParam(pszParam, bFlag, bLast);
}
BOOL CCommandLineInfoEx::GetOption(LPCTSTR option, CString& val)
{
return m_options.Lookup(option, val);
}