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

345 lines
9 KiB
C++

// shimgvwr.cpp : Defines the class behaviors for the application.
//
#include "stdafx.h"
#include "shimgvwr.h"
#include "MainFrm.h"
#include "ImageDoc.h"
#include "ImageView.h"
#include "ofn.h"
#include <gdiplus.h>
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
using namespace Gdiplus;
/////////////////////////////////////////////////////////////////////////////
// CPreviewApp
BEGIN_MESSAGE_MAP(CPreviewApp, CWinApp)
//{{AFX_MSG_MAP(CPreviewApp)
ON_COMMAND(ID_APP_ABOUT, OnAppAbout)
//}}AFX_MSG_MAP
// Standard file based document commands
ON_COMMAND(ID_FILE_NEW, CWinApp::OnFileNew)
ON_COMMAND(ID_FILE_OPEN, OnFileOpen)
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CPreviewApp construction
CPreviewApp::CPreviewApp()
{
m_hFileMap = INVALID_HANDLE_VALUE;
}
CPreviewApp::~CPreviewApp()
{
if ( m_hFileMap != INVALID_HANDLE_VALUE)
{
CloseHandle (m_hFileMap);
}
}
void CPreviewApp::OnFileOpen ()
{
CString newName;
if (! DoPromptFileName( newName, AFX_IDS_OPENFILE,
OFN_HIDEREADONLY | OFN_FILEMUSTEXIST,
TRUE ))
return; // open cancelled
if (OpenDocumentFile(newName) == NULL)
{
OnFileNew();
}
}
void MakeFilterFromCodecs (CString &strFilter, UINT nCodecs, ImageCodecInfo *pCodecs)
{
strFilter+=TEXT('\0');
for (UINT i=0;i<nCodecs;i++)
{
strFilter+=pCodecs->FormatDescription;
strFilter+=TEXT('\0');
strFilter+=pCodecs->FilenameExtension;
strFilter+=TEXT('\0');
pCodecs++;
}
}
void
GetFilterStringForSave (CString &strFilter)
{
strFilter.LoadString(IDS_ALLFILES);
strFilter+=TEXT('\0');
strFilter+=TEXT("*.*");
UINT nCodecs = 0;
UINT cbCodecs = 0;
BYTE *pData;
GetImageEncodersSize (&nCodecs, &cbCodecs);
if (cbCodecs)
{
pData = new BYTE[cbCodecs];
if (pData)
{
ImageCodecInfo *pCodecs = reinterpret_cast<ImageCodecInfo*>(pData);
if (Ok == GetImageEncoders (nCodecs, cbCodecs, pCodecs))
{
MakeFilterFromCodecs (strFilter, nCodecs, pCodecs);
}
delete [] pData;
}
}
strFilter+=TEXT('\0');
}
void
GetFilterStringForOpen (CString &strFilter)
{
strFilter.LoadString(IDS_ALLFILES);
strFilter+=TEXT('\0');
strFilter+=TEXT("*.*");
// query GDI+ for supported image decoders
UINT nCodecs = 0;
UINT cbCodecs = 0;
BYTE *pData;
GetImageDecodersSize (&nCodecs, &cbCodecs);
if (cbCodecs)
{
pData = new BYTE[cbCodecs];
if (pData)
{
ImageCodecInfo *pCodecs = reinterpret_cast<ImageCodecInfo*>(pData);
if (Ok == GetImageDecoders (nCodecs, cbCodecs, pCodecs))
{
MakeFilterFromCodecs (strFilter, nCodecs, pCodecs);
}
delete [] pData;
}
}
strFilter+=TEXT('\0');
}
// Get the extension of a file path.
//
CString GetExtension(const TCHAR* szFilePath)
{
TCHAR szExt [_MAX_EXT];
MySplitPath(szFilePath, NULL, NULL, NULL, szExt);
return CString(szExt);
}
BOOL CPreviewApp::DoPromptFileName( CString& fileName, UINT nIDSTitle, DWORD lFlags,
BOOL bOpenFileDialog )
{
COpenFileName dlgFile( bOpenFileDialog );
if (!dlgFile.m_pofn)
return FALSE;
CString title;
VERIFY( title.LoadString( nIDSTitle ) );
lFlags |= OFN_EXPLORER;
if (!bOpenFileDialog)
lFlags |= OFN_OVERWRITEPROMPT;
dlgFile.m_pofn->Flags |= lFlags;
dlgFile.m_pofn->Flags &= ~OFN_SHOWHELP;
CString strFilter;
if (bOpenFileDialog)
{
GetFilterStringForOpen (strFilter);
}
else
{
GetFilterStringForSave (strFilter);
}
CString strExt = GetExtension(fileName);
dlgFile.m_pofn->lpstrFilter = strFilter;
dlgFile.m_pofn->hwndOwner = AfxGetMainWnd()->GetSafeHwnd();
dlgFile.m_pofn->hInstance = AfxGetResourceHandle();
dlgFile.m_pofn->lpstrTitle = title;
dlgFile.m_pofn->lpstrFile = fileName.GetBuffer(_MAX_PATH);
dlgFile.m_pofn->nMaxFile = _MAX_PATH;
dlgFile.m_pofn->lpstrInitialDir = NULL;
dlgFile.m_pofn->lpstrDefExt = strExt;
BOOL bRet = dlgFile.DoModal() == IDOK? TRUE : FALSE;
fileName.ReleaseBuffer();
return bRet;
}
/////////////////////////////////////////////////////////////////////////////
// The one and only CPreviewApp object
CPreviewApp theApp;
/////////////////////////////////////////////////////////////////////////////
// CPreviewApp initialization
BOOL CPreviewApp::InitInstance()
{
CoInitialize (NULL);
AfxEnableControlContainer();
// Standard initialization
// If you are not using these features and wish to reduce the size
// of your final executable, you should remove from the following
// the specific initialization routines you do not need.
#ifdef _AFXDLL
Enable3dControls(); // Call this when using MFC in a shared DLL
#else
Enable3dControlsStatic(); // Call this when linking to MFC statically
#endif
// Change the registry key under which our settings are stored.
SetRegistryKey(_T("Shell_Image_Previewer"));
LoadStdProfileSettings(); // Load standard INI file options (including MRU)
// Register the application's document templates. Document templates
// serve as the connection between documents, frame windows and views.
CSingleDocTemplate* pDocTemplate;
pDocTemplate = new CSingleDocTemplate(
IDR_MAINFRAME,
RUNTIME_CLASS(CImageDoc),
RUNTIME_CLASS(CMainFrame), // main SDI frame window
RUNTIME_CLASS(CImageView));
AddDocTemplate(pDocTemplate);
// Parse command line for standard shell commands, DDE, file open
CCommandLineInfo cmdInfo;
ParseCommandLine(cmdInfo);
if (cmdInfo.m_nShellCommand == CCommandLineInfo::FileOpen && PrevInstance (cmdInfo.m_strFileName))
{
return FALSE;
}
// Dispatch commands specified on the command line
if (!ProcessShellCommand(cmdInfo))
return FALSE;
// The one and only window has been initialized, so show and update it.
m_pMainWnd->ShowWindow(SW_SHOW);
m_pMainWnd->UpdateWindow();
return TRUE;
}
#define FILEMAPPINGNAME TEXT("Shimgvwr")
bool
CPreviewApp::PrevInstance(const CString &strFile)
{
CString strMapping(FILEMAPPINGNAME);
bool bRet = false;
strMapping += strFile;
OutputDebugString (strMapping);
OutputDebugString (TEXT("\n"));
strMapping.Replace (TEXT('\\'), TEXT('/'));
HANDLE hMap = CreateFileMapping (INVALID_HANDLE_VALUE,
NULL,
PAGE_READWRITE,
0, sizeof(HWND),
strMapping);
if (hMap )
{
DWORD dw = GetLastError();
HWND *phwnd = reinterpret_cast<HWND*>(MapViewOfFile (hMap, FILE_MAP_WRITE, 0, 0, sizeof(HWND)));
if (phwnd)
{
CWnd WndPrev;
CWnd *pWndChild;
WndPrev.Attach(*phwnd);
if (ERROR_ALREADY_EXISTS == dw)
{
pWndChild = WndPrev.GetLastActivePopup();
if (WndPrev.IsIconic())
{
WndPrev.ShowWindow (SW_RESTORE);
}
pWndChild->SetForegroundWindow();
bRet = true;
CloseHandle (hMap); // we can close the handle before unmapping the view
}
else
{
*phwnd = 0;
m_hFileMap = hMap;
}
UnmapViewOfFile (phwnd);
}
}
return bRet;
}
/////////////////////////////////////////////////////////////////////////////
// CAboutDlg dialog used for App About
class CAboutDlg : public CDialog
{
public:
CAboutDlg();
// Dialog Data
//{{AFX_DATA(CAboutDlg)
enum { IDD = IDD_ABOUTBOX };
//}}AFX_DATA
// ClassWizard generated virtual function overrides
//{{AFX_VIRTUAL(CAboutDlg)
protected:
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
//}}AFX_VIRTUAL
// Implementation
protected:
//{{AFX_MSG(CAboutDlg)
// No message handlers
//}}AFX_MSG
DECLARE_MESSAGE_MAP()
};
CAboutDlg::CAboutDlg() : CDialog(CAboutDlg::IDD)
{
//{{AFX_DATA_INIT(CAboutDlg)
//}}AFX_DATA_INIT
}
void CAboutDlg::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
//{{AFX_DATA_MAP(CAboutDlg)
//}}AFX_DATA_MAP
}
BEGIN_MESSAGE_MAP(CAboutDlg, CDialog)
//{{AFX_MSG_MAP(CAboutDlg)
// No message handlers
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
// App command to run the dialog
void CPreviewApp::OnAppAbout()
{
CString sTitle;
HICON hIcon = LoadIcon(IDR_MAINFRAME);
sTitle.LoadString(AFX_IDS_APP_TITLE);
ShellAbout(AfxGetMainWnd()->GetSafeHwnd(), sTitle, NULL, hIcon);
}