windows-nt/Source/XPSP1/NT/printscan/ui/wiadefui/progdlg.cpp
2020-09-26 16:20:57 +08:00

576 lines
17 KiB
C++

/*******************************************************************************
*
* (C) COPYRIGHT MICROSOFT CORPORATION, 2000
*
* TITLE: PROGDLG.CPP
*
* VERSION: 1.0
*
* AUTHOR: ShaunIv
*
* DATE: 5/2/2000
*
* DESCRIPTION: Generic WIA progress dialog
*
*******************************************************************************/
#include "precomp.h"
#pragma hdrstop
#include "wiadefui.h"
#include "wiauiext.h"
#include "simrect.h"
#include "movewnd.h"
#include "dlgunits.h"
//
// Private window messages
//
#define PDM_SHOW (WM_USER+1)
#define PDM_GETCANCELSTATE (WM_USER+2)
#define PDM_SETTITLE (WM_USER+3)
#define PDM_SETMESSAGE (WM_USER+4)
#define PDM_SETPERCENT (WM_USER+5)
#define PDM_CLOSE (WM_USER+6)
class CProgressDialog
{
public:
struct CData
{
LONG lFlags;
HWND hwndParent;
};
private:
HWND m_hWnd;
bool m_bCancelled;
private:
//
// Not implemented
//
CProgressDialog( const CProgressDialog & );
CProgressDialog(void);
CProgressDialog &operator=( const CProgressDialog & );
private:
//
// Sole constructor
//
explicit CProgressDialog( HWND hWnd )
: m_hWnd(hWnd),
m_bCancelled(false)
{
}
~CProgressDialog(void)
{
m_hWnd = NULL;
}
LRESULT OnInitDialog( WPARAM, LPARAM lParam )
{
//
// Prevent the animation control from starting up a new thread to play the AVI by setting the ACS_TIMER style
//
SetWindowLong( GetDlgItem( m_hWnd, IDC_PROGRESS_ANIMATION ), GWL_STYLE, ACS_TIMER | GetWindowLong( GetDlgItem( m_hWnd, IDC_PROGRESS_ANIMATION ), GWL_STYLE ) );
//
// Set up the progress control
//
SendDlgItemMessage( m_hWnd, IDC_PROGRESS_PERCENT, PBM_SETRANGE, 0, MAKELPARAM(0,100) );
//
// Get the data for this dialog
//
CData *pData = reinterpret_cast<CData*>(lParam);
if (pData)
{
//
// The number of pixels to shrink the progress dialog if we hide any controls
//
int nDeltaY = 0;
//
// Calculate the dialog units settings for this dialog
//
CDialogUnits DialogUnits(m_hWnd);
//
// Hide the progress control if requested
//
if (WIA_PROGRESSDLG_NO_PROGRESS & pData->lFlags)
{
EnableWindow( GetDlgItem( m_hWnd, IDC_PROGRESS_PERCENT ), FALSE );
ShowWindow( GetDlgItem( m_hWnd, IDC_PROGRESS_PERCENT ), SW_HIDE );
CSimpleRect rcPercentWindow( GetDlgItem( m_hWnd, IDC_PROGRESS_PERCENT ), CSimpleRect::WindowRect );
CMoveWindow mw;
mw.Move( GetDlgItem( m_hWnd, IDCANCEL ),
0,
CSimpleRect(GetDlgItem( m_hWnd, IDCANCEL ), CSimpleRect::WindowRect ).ScreenToClient(m_hWnd).top - rcPercentWindow.Height() - DialogUnits.Y(3),
CMoveWindow::NO_MOVEX );
nDeltaY += rcPercentWindow.Height() + DialogUnits.Y(3);
}
//
// If we are to hide the cancel button, hide it and disable closing the dialog from the system menu
//
if (WIA_PROGRESSDLG_NO_CANCEL & pData->lFlags)
{
EnableWindow( GetDlgItem( m_hWnd, IDCANCEL ), FALSE );
ShowWindow( GetDlgItem( m_hWnd, IDCANCEL ), SW_HIDE );
HMENU hSystemMenu = GetSystemMenu(m_hWnd,FALSE);
if (hSystemMenu)
{
EnableMenuItem( hSystemMenu, SC_CLOSE, MF_GRAYED|MF_BYCOMMAND );
}
nDeltaY += CSimpleRect( GetDlgItem( m_hWnd, IDCANCEL ), CSimpleRect::WindowRect ).Height() + DialogUnits.Y(7);
}
//
// Assume we'll be hiding the animation
//
bool bHideAviControl = true;
if ((WIA_PROGRESSDLG_NO_ANIM & pData->lFlags) == 0)
{
//
// Set up the relationship between animation flags and resource IDs
//
static const struct
{
LONG nFlag;
int nResourceId;
}
s_AnimationResources[] =
{
{ WIA_PROGRESSDLG_ANIM_SCANNER_COMMUNICATE, IDA_PROGDLG_SCANNER_COMMUNICATE },
{ WIA_PROGRESSDLG_ANIM_CAMERA_COMMUNICATE, IDA_PROGDLG_CAMERA_COMMUNICATE },
{ WIA_PROGRESSDLG_ANIM_VIDEO_COMMUNICATE, IDA_PROGDLG_VIDEO_COMMUNICATE },
{ WIA_PROGRESSDLG_ANIM_SCANNER_ACQUIRE, IDA_PROGDLG_SCANNER_ACQUIRE },
{ WIA_PROGRESSDLG_ANIM_CAMERA_ACQUIRE, IDA_PROGDLG_CAMERA_ACQUIRE },
{ WIA_PROGRESSDLG_ANIM_VIDEO_ACQUIRE, IDA_PROGDLG_VIDEO_ACQUIRE },
{ WIA_PROGRESSDLG_ANIM_DEFAULT_COMMUNICATE, IDA_PROGDLG_DEFAULT_COMMUNICATE },
};
//
// Assume we won't find an animation
//
int nAnimationResourceId = 0;
//
// Find the first animation for which we have a match
//
for (int i=0;i<ARRAYSIZE(s_AnimationResources);i++)
{
if (s_AnimationResources[i].nFlag & pData->lFlags)
{
nAnimationResourceId = s_AnimationResources[i].nResourceId;
break;
}
}
//
// If we found an animation flag and we are able to open the animation, play it and don't hide the control
//
if (nAnimationResourceId && Animate_OpenEx( GetDlgItem(m_hWnd,IDC_PROGRESS_ANIMATION), g_hInstance, MAKEINTRESOURCE(nAnimationResourceId)))
{
bHideAviControl = false;
Animate_Play( GetDlgItem(m_hWnd,IDC_PROGRESS_ANIMATION), 0, -1, -1 );
}
}
//
// If we need to hide the animation control, do so, and move all of the other controls up
//
if (bHideAviControl)
{
EnableWindow( GetDlgItem( m_hWnd, IDC_PROGRESS_ANIMATION ), FALSE );
ShowWindow( GetDlgItem( m_hWnd, IDC_PROGRESS_ANIMATION ), SW_HIDE );
CSimpleRect rcAnimWindow( GetDlgItem( m_hWnd, IDC_PROGRESS_ANIMATION ), CSimpleRect::WindowRect );
CMoveWindow mw;
mw.Move( GetDlgItem( m_hWnd, IDC_PROGRESS_MESSAGE ),
0,
CSimpleRect(GetDlgItem( m_hWnd, IDC_PROGRESS_MESSAGE ), CSimpleRect::WindowRect ).ScreenToClient(m_hWnd).top - rcAnimWindow.Height() - DialogUnits.Y(7),
CMoveWindow::NO_MOVEX );
mw.Move( GetDlgItem( m_hWnd, IDC_PROGRESS_PERCENT ),
0,
CSimpleRect(GetDlgItem( m_hWnd, IDC_PROGRESS_PERCENT ), CSimpleRect::WindowRect ).ScreenToClient(m_hWnd).top - rcAnimWindow.Height() - DialogUnits.Y(7),
CMoveWindow::NO_MOVEX );
mw.Move( GetDlgItem( m_hWnd, IDCANCEL ),
0,
CSimpleRect(GetDlgItem( m_hWnd, IDCANCEL ), CSimpleRect::WindowRect ).ScreenToClient(m_hWnd).top - rcAnimWindow.Height() - DialogUnits.Y(7),
CMoveWindow::NO_MOVEX );
nDeltaY += rcAnimWindow.Height() + DialogUnits.Y(7);
}
//
// Resize the dialog in case we hid any controls
//
CMoveWindow().Size( m_hWnd, 0, CSimpleRect( m_hWnd, CSimpleRect::WindowRect ).Height() - nDeltaY, CMoveWindow::NO_SIZEX );
//
// Center the dialog on the parent
//
WiaUiUtil::CenterWindow( m_hWnd, pData->hwndParent );
}
return 0;
}
LRESULT OnDestroy( WPARAM, LPARAM )
{
//
// Cause the thread to exit
//
PostQuitMessage(0);
return 0;
}
void OnCancel( WPARAM, LPARAM )
{
if (!m_bCancelled)
{
m_bCancelled = true;
//
// Tell the user to wait. It could take a while for the caller to check the cancelled flag.
//
CSimpleString( IDS_PROGRESS_WAIT, g_hInstance ).SetWindowText( GetDlgItem( m_hWnd, IDCANCEL ) );
}
}
LRESULT OnCommand( WPARAM wParam, LPARAM lParam )
{
SC_BEGIN_COMMAND_HANDLERS()
{
SC_HANDLE_COMMAND(IDCANCEL,OnCancel);
}
SC_END_COMMAND_HANDLERS();
}
LRESULT OnShow( WPARAM wParam, LPARAM lParam )
{
ShowWindow( m_hWnd, wParam ? SW_SHOW : SW_HIDE );
return 0;
}
LRESULT OnGetCancelState( WPARAM wParam, LPARAM lParam )
{
return (m_bCancelled != false);
}
LRESULT OnSetTitle( WPARAM wParam, LPARAM lParam )
{
CSimpleStringConvert::NaturalString(CSimpleStringWide(reinterpret_cast<LPCTSTR>(lParam))).SetWindowText(m_hWnd);
return 0;
}
LRESULT OnSetMessage( WPARAM wParam, LPARAM lParam )
{
CSimpleStringConvert::NaturalString(CSimpleStringWide(reinterpret_cast<LPCTSTR>(lParam))).SetWindowText(GetDlgItem(m_hWnd,IDC_PROGRESS_MESSAGE));
return 0;
}
LRESULT OnSetPercent( WPARAM wParam, LPARAM lParam )
{
SendDlgItemMessage( m_hWnd, IDC_PROGRESS_PERCENT, PBM_SETPOS, lParam, 0 );
return 0;
}
LRESULT OnClose( WPARAM wParam, LPARAM lParam )
{
DestroyWindow(m_hWnd);
return 0;
}
public:
static INT_PTR DialogProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam )
{
SC_BEGIN_DIALOG_MESSAGE_HANDLERS(CProgressDialog)
{
SC_HANDLE_DIALOG_MESSAGE( WM_INITDIALOG, OnInitDialog );
SC_HANDLE_DIALOG_MESSAGE( WM_DESTROY, OnDestroy );
SC_HANDLE_DIALOG_MESSAGE( WM_COMMAND, OnCommand );
SC_HANDLE_DIALOG_MESSAGE( PDM_SHOW, OnShow );
SC_HANDLE_DIALOG_MESSAGE( PDM_GETCANCELSTATE, OnGetCancelState );
SC_HANDLE_DIALOG_MESSAGE( PDM_SETTITLE, OnSetTitle );
SC_HANDLE_DIALOG_MESSAGE( PDM_SETMESSAGE, OnSetMessage );
SC_HANDLE_DIALOG_MESSAGE( PDM_SETPERCENT, OnSetPercent );
SC_HANDLE_DIALOG_MESSAGE( PDM_CLOSE, OnClose );
}
SC_END_DIALOG_MESSAGE_HANDLERS();
}
};
class CProgressDialogThread
{
private:
HWND m_hwndParent;
LONG m_lFlags;
HANDLE m_hCreationEvent;
HWND *m_phwndDialog;
private:
//
// Not implemented
//
CProgressDialogThread(void);
CProgressDialogThread( const CProgressDialogThread & );
CProgressDialogThread &operator=( const CProgressDialogThread & );
private:
//
// Sole constructor
//
CProgressDialogThread( HWND hwndParent, LONG lFlags, HANDLE hCreationEvent, HWND *phwndDialog )
: m_hwndParent(hwndParent),
m_lFlags(lFlags),
m_hCreationEvent(hCreationEvent),
m_phwndDialog(phwndDialog)
{
}
~CProgressDialogThread(void)
{
m_hwndParent = NULL;
m_hCreationEvent = NULL;
m_phwndDialog = NULL;
}
void Run(void)
{
//
// Make sure we have valid thread data
//
if (m_phwndDialog && m_hCreationEvent)
{
//
// Prepare the dialog data
//
CProgressDialog::CData Data;
Data.lFlags = m_lFlags;
Data.hwndParent = m_hwndParent;
//
// Decide which dialog resource to use
//
int nDialogResId = IDD_PROGRESS_DIALOG;
if (m_lFlags & WIA_PROGRESSDLG_NO_TITLE)
{
nDialogResId = IDD_PROGRESS_DIALOG_NO_TITLE;
}
//
// Create the dialog
//
HWND hwndDialog = CreateDialogParam( g_hInstance, MAKEINTRESOURCE(nDialogResId), NULL, CProgressDialog::DialogProc, reinterpret_cast<LPARAM>(&Data) );
//
// Store the dialog's HWND in the HWND ptr and set the creation event, to give the calling thread a window handle
//
*m_phwndDialog = hwndDialog;
SetEvent(m_hCreationEvent);
//
// Start up our message loop
//
if (hwndDialog)
{
MSG msg;
while (GetMessage(&msg,NULL,0,0))
{
if (!IsDialogMessage(hwndDialog,&msg))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
//
// If we have a parent, bring it to the foreground
//
if (m_hwndParent)
{
SetForegroundWindow(m_hwndParent);
}
}
}
}
static DWORD ThreadProc( PVOID pvParam )
{
CProgressDialogThread *pProgressDialogThread = reinterpret_cast<CProgressDialogThread*>(pvParam);
if (pProgressDialogThread)
{
pProgressDialogThread->Run();
delete pProgressDialogThread;
}
//
// Just before we quit, decrement the module refcount
//
DllRelease();
return 0;
}
public:
static HWND Create( HWND hWndParent, LONG lFlags )
{
//
// Assume failure
//
HWND hwndResult = NULL;
//
// Create an event that will allow us to synchronize initialization of the HWND
//
HANDLE hEvent = CreateEvent( NULL, TRUE, FALSE, NULL );
if (hEvent)
{
//
// Create the progress dialog thread data
//
CProgressDialogThread *pProgressDialogThread = new CProgressDialogThread( hWndParent, lFlags, hEvent, &hwndResult );
if (pProgressDialogThread)
{
//
// Increment the global refcount, so this DLL can't be released until we decrement
//
DllAddRef();
//
// Create the thread, passing the thread class as the thread data
//
DWORD dwThreadId;
HANDLE hThread = CreateThread( NULL, 0, ThreadProc, pProgressDialogThread, 0, &dwThreadId );
if (hThread)
{
//
// Wait until the dialog is created
//
WiaUiUtil::MsgWaitForSingleObject( hEvent, INFINITE );
if (hwndResult)
{
//
// Make the dialog active
//
SetForegroundWindow(hwndResult);
}
//
// Done with this handle
//
CloseHandle(hThread);
}
else
{
//
// If we were unable to create the thread, decrement the module refcount
//
DllRelease();
}
}
//
// Done with this handle
//
CloseHandle(hEvent);
}
//
// If hwndResult is non-NULL, we succeeded
//
return hwndResult;
}
};
// *** IWiaProgressDialog methods ***
STDMETHODIMP CWiaDefaultUI::Create( HWND hwndParent, LONG lFlags )
{
m_hWndProgress = CProgressDialogThread::Create(hwndParent,lFlags);
return m_hWndProgress ? S_OK : E_FAIL;
}
STDMETHODIMP CWiaDefaultUI::Show(void)
{
if (!m_hWndProgress)
{
return E_FAIL;
}
SendMessage(m_hWndProgress,PDM_SHOW,1,0);
return S_OK;
}
STDMETHODIMP CWiaDefaultUI::Hide(void)
{
if (!m_hWndProgress)
{
return E_FAIL;
}
SendMessage(m_hWndProgress,PDM_SHOW,0,0);
return S_OK;
}
STDMETHODIMP CWiaDefaultUI::Cancelled( BOOL *pbCancelled )
{
if (!pbCancelled)
{
return E_POINTER;
}
if (!m_hWndProgress)
{
return E_FAIL;
}
*pbCancelled = (SendMessage(m_hWndProgress,PDM_GETCANCELSTATE,0,0) != 0);
return S_OK;
}
STDMETHODIMP CWiaDefaultUI::SetTitle( LPCWSTR pszTitle )
{
if (!pszTitle)
{
return E_POINTER;
}
if (!m_hWndProgress)
{
return E_FAIL;
}
SendMessage(m_hWndProgress,PDM_SETTITLE,0,reinterpret_cast<LPARAM>(pszTitle));
return S_OK;
}
STDMETHODIMP CWiaDefaultUI::SetMessage( LPCWSTR pszMessage )
{
if (!pszMessage)
{
return E_POINTER;
}
if (!m_hWndProgress)
{
return E_FAIL;
}
SendMessage(m_hWndProgress,PDM_SETMESSAGE,0,reinterpret_cast<LPARAM>(pszMessage));
return S_OK;
}
STDMETHODIMP CWiaDefaultUI::SetPercentComplete( UINT nPercent )
{
if (!m_hWndProgress)
{
return E_FAIL;
}
SendMessage(m_hWndProgress,PDM_SETPERCENT,0,nPercent);
return S_OK;
}
STDMETHODIMP CWiaDefaultUI::Destroy(void)
{
if (!m_hWndProgress)
{
return E_FAIL;
}
SendMessage(m_hWndProgress,PDM_CLOSE,0,0);
m_hWndProgress = NULL;
return S_OK;
}