/******************************************************************************* * * (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(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;ilFlags) { 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(lParam))).SetWindowText(m_hWnd); return 0; } LRESULT OnSetMessage( WPARAM wParam, LPARAM lParam ) { CSimpleStringConvert::NaturalString(CSimpleStringWide(reinterpret_cast(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(&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(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(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(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; }