366 lines
9.2 KiB
C++
366 lines
9.2 KiB
C++
|
|
// MDITextEditor.cpp : Defines the class behaviors for the application.
|
||
|
|
//
|
||
|
|
|
||
|
|
#include "stdafx.h"
|
||
|
|
#include "MDITextEditor.h"
|
||
|
|
|
||
|
|
#include "MainFrm.h"
|
||
|
|
#include "ChildFrm.h"
|
||
|
|
#include "MDITextEditorDoc.h"
|
||
|
|
#include "MDITextEditorView.h"
|
||
|
|
|
||
|
|
#ifdef _DEBUG
|
||
|
|
#define new DEBUG_NEW
|
||
|
|
#undef THIS_FILE
|
||
|
|
static char THIS_FILE[] = __FILE__;
|
||
|
|
#endif
|
||
|
|
|
||
|
|
/////////////////////////////////////////////////////////////////////////////
|
||
|
|
// CMDITextEditorApp
|
||
|
|
|
||
|
|
BEGIN_MESSAGE_MAP(CMDITextEditorApp, CWinApp)
|
||
|
|
//{{AFX_MSG_MAP(CMDITextEditorApp)
|
||
|
|
ON_COMMAND(ID_APP_ABOUT, OnAppAbout)
|
||
|
|
ON_COMMAND(ID_FILE_OPEN, OnFileOpen)
|
||
|
|
ON_COMMAND(ID_FILE_SAVEALL, OnFileSaveAll)
|
||
|
|
ON_COMMAND(ID_FILE_CLOSEALL, OnFileCloseAll)
|
||
|
|
//}}AFX_MSG_MAP
|
||
|
|
// Standard file based document commands
|
||
|
|
ON_COMMAND(ID_FILE_NEW, CWinApp::OnFileNew)
|
||
|
|
ON_COMMAND(ID_FILE_OPEN, CWinApp::OnFileOpen)
|
||
|
|
// Standard print setup command
|
||
|
|
ON_COMMAND(ID_FILE_PRINT_SETUP, CWinApp::OnFilePrintSetup)
|
||
|
|
END_MESSAGE_MAP()
|
||
|
|
|
||
|
|
/////////////////////////////////////////////////////////////////////////////
|
||
|
|
// CMDITextEditorApp construction
|
||
|
|
|
||
|
|
CMDITextEditorApp::CMDITextEditorApp()
|
||
|
|
: m_hMutex(NULL)
|
||
|
|
, m_pMainFrame(0)
|
||
|
|
, m_pDocTemplate(0)
|
||
|
|
, m_bInsertKey(FALSE)
|
||
|
|
, m_nFilterIndex(0)
|
||
|
|
{
|
||
|
|
// TODO: add construction code here,
|
||
|
|
// Place all significant initialization in InitInstance
|
||
|
|
}
|
||
|
|
|
||
|
|
CMDITextEditorApp::~CMDITextEditorApp()
|
||
|
|
{
|
||
|
|
WriteProfileInt(XTP_EDIT_REG_SETTINGS,
|
||
|
|
_T("FilterIndex"), m_nFilterIndex);
|
||
|
|
|
||
|
|
WriteProfileString(XTP_EDIT_REG_SETTINGS,
|
||
|
|
_T("InitialDir"), m_csInitialDir);
|
||
|
|
|
||
|
|
if (m_hMutex)
|
||
|
|
{
|
||
|
|
::ReleaseMutex(m_hMutex);
|
||
|
|
m_hMutex = 0;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
/////////////////////////////////////////////////////////////////////////////
|
||
|
|
// The one and only CMDITextEditorApp object
|
||
|
|
|
||
|
|
CMDITextEditorApp theApp;
|
||
|
|
|
||
|
|
/////////////////////////////////////////////////////////////////////////////
|
||
|
|
// CMDITextEditorApp initialization
|
||
|
|
|
||
|
|
BOOL CMDITextEditorApp::InitInstance()
|
||
|
|
{
|
||
|
|
// only allow one instance of this application
|
||
|
|
if (!CreateSingleInstance())
|
||
|
|
return FALSE;
|
||
|
|
|
||
|
|
AfxEnableControlContainer();
|
||
|
|
CXTPWinDwmWrapper().SetProcessDPIAware();
|
||
|
|
|
||
|
|
// 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.
|
||
|
|
|
||
|
|
#if _MSC_VER <= 1200 // MFC 6.0 or earlier
|
||
|
|
#ifdef _AFXDLL
|
||
|
|
Enable3dControls(); // Call this when using MFC in a shared DLL
|
||
|
|
#else
|
||
|
|
Enable3dControlsStatic(); // Call this when linking to MFC statically
|
||
|
|
#endif
|
||
|
|
#endif
|
||
|
|
|
||
|
|
OleInitialize(NULL);
|
||
|
|
|
||
|
|
// Change the registry key under which our settings are stored.
|
||
|
|
// TODO: You should modify this string to be something appropriate
|
||
|
|
// such as the name of your company or organization.
|
||
|
|
SetRegistryKey(_T("Codejock Software Sample Applications"));
|
||
|
|
|
||
|
|
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.
|
||
|
|
|
||
|
|
m_pDocTemplate = new CMultiDocTemplate(
|
||
|
|
IDR_MDITEXTYPE,
|
||
|
|
RUNTIME_CLASS(CMDITextEditorDoc),
|
||
|
|
RUNTIME_CLASS(CChildFrame), // custom MDI child frame
|
||
|
|
RUNTIME_CLASS(CMDITextEditorView));
|
||
|
|
AddDocTemplate(m_pDocTemplate);
|
||
|
|
|
||
|
|
// create main MDI Frame window
|
||
|
|
m_pMainFrame = new CMainFrame;
|
||
|
|
if (!m_pMainFrame->LoadFrame(IDR_MAINFRAME))
|
||
|
|
return FALSE;
|
||
|
|
m_pMainWnd = m_pMainFrame;
|
||
|
|
m_pMainWnd->DragAcceptFiles();
|
||
|
|
|
||
|
|
// Parse command line for standard shell commands, DDE, file open
|
||
|
|
CCommandLineInfo cmdInfo;
|
||
|
|
ParseCommandLine(cmdInfo);
|
||
|
|
|
||
|
|
if (cmdInfo.m_nShellCommand == CCommandLineInfo::FileOpen)
|
||
|
|
{
|
||
|
|
// Process files list
|
||
|
|
for (int i = 1; i < __argc; i++)
|
||
|
|
OpenDocumentFile(__targv[i]);
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
// Dispatch commands specified on the command line
|
||
|
|
if (!ProcessShellCommand(cmdInfo))
|
||
|
|
return FALSE;
|
||
|
|
}
|
||
|
|
// The main window has been initialized, so show and update it.
|
||
|
|
m_pMainFrame->ShowWindow(m_nCmdShow);
|
||
|
|
m_pMainFrame->UpdateWindow();
|
||
|
|
|
||
|
|
// restore file open filter index.
|
||
|
|
m_nFilterIndex = GetProfileInt(XTP_EDIT_REG_SETTINGS,
|
||
|
|
_T("FilterIndex"), m_nFilterIndex);
|
||
|
|
|
||
|
|
m_csInitialDir = GetProfileString(XTP_EDIT_REG_SETTINGS,
|
||
|
|
_T("InitialDir"), m_csInitialDir);
|
||
|
|
|
||
|
|
return TRUE;
|
||
|
|
}
|
||
|
|
|
||
|
|
// App command to run the dialog
|
||
|
|
void CMDITextEditorApp::OnAppAbout()
|
||
|
|
{
|
||
|
|
CAboutDlg aboutDlg;
|
||
|
|
aboutDlg.DoModal();
|
||
|
|
}
|
||
|
|
|
||
|
|
/////////////////////////////////////////////////////////////////////////////
|
||
|
|
// CMDITextEditorApp message handlers
|
||
|
|
|
||
|
|
BOOL CMDITextEditorApp::RegisterWindowClass()
|
||
|
|
{
|
||
|
|
WNDCLASS wndcls;
|
||
|
|
|
||
|
|
if (!(::GetClassInfo(m_hInstance, CLASSNAME_APPINSTANCE, &wndcls)))
|
||
|
|
{
|
||
|
|
// otherwise we need to register a new class
|
||
|
|
wndcls.style = CS_DBLCLKS;
|
||
|
|
wndcls.lpfnWndProc = AfxWndProc;
|
||
|
|
wndcls.cbClsExtra = wndcls.cbWndExtra = 0;
|
||
|
|
wndcls.hInstance = m_hInstance;
|
||
|
|
wndcls.hIcon = ::LoadIcon(m_hInstance, MAKEINTRESOURCE(IDR_MAINFRAME));
|
||
|
|
wndcls.hCursor = ::LoadCursor(NULL, IDC_ARROW);
|
||
|
|
wndcls.hbrBackground = NULL;
|
||
|
|
wndcls.lpszMenuName = NULL;
|
||
|
|
wndcls.lpszClassName = CLASSNAME_APPINSTANCE;
|
||
|
|
|
||
|
|
if (!AfxRegisterClass(&wndcls))
|
||
|
|
{
|
||
|
|
AfxThrowResourceException();
|
||
|
|
return FALSE;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
return TRUE;
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
BOOL CMDITextEditorApp::CreateSingleInstance()
|
||
|
|
{
|
||
|
|
// make the application a single instance, if the
|
||
|
|
// mutex does not already exist register the window class
|
||
|
|
// and open the first instance.
|
||
|
|
m_hMutex = ::CreateMutex(NULL, FALSE, CLASSNAME_APPINSTANCE);
|
||
|
|
if (::GetLastError() == ERROR_ALREADY_EXISTS)
|
||
|
|
{
|
||
|
|
// Reset our mutext handle (just in case)
|
||
|
|
m_hMutex = 0;
|
||
|
|
|
||
|
|
// The mutex already exists, which means an instance is already
|
||
|
|
// running, get the window handle and bring it to the foreground. If
|
||
|
|
// we could not find a valid handle, open the second instance.
|
||
|
|
HWND hWnd = ::FindWindowEx(NULL, NULL, CLASSNAME_APPINSTANCE, NULL);
|
||
|
|
if (::IsWindow(hWnd))
|
||
|
|
{
|
||
|
|
::ShowWindow(hWnd, SW_RESTORE);
|
||
|
|
::BringWindowToTop(hWnd);
|
||
|
|
::SetForegroundWindow(hWnd);
|
||
|
|
|
||
|
|
TCHAR szSharedData[_MAX_PATH];
|
||
|
|
|
||
|
|
COPYDATASTRUCT copyData;
|
||
|
|
copyData.dwData = cdwData_FileName;
|
||
|
|
copyData.lpData = szSharedData;
|
||
|
|
copyData.cbData = sizeof(szSharedData);
|
||
|
|
|
||
|
|
// parse command line arguments.
|
||
|
|
for (int i = 1; i < __argc; i++)
|
||
|
|
{
|
||
|
|
STRCPY_S(szSharedData, sizeof(szSharedData), __targv[i]);
|
||
|
|
szSharedData[_MAX_PATH-1] = 0;
|
||
|
|
|
||
|
|
::SendMessage(hWnd, WM_COPYDATA, (WPARAM)0, (LPARAM)©Data);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
return FALSE; // Return failure
|
||
|
|
}
|
||
|
|
|
||
|
|
return RegisterWindowClass();
|
||
|
|
}
|
||
|
|
|
||
|
|
BOOL CMDITextEditorApp::PreTranslateMessage(MSG* pMsg)
|
||
|
|
{
|
||
|
|
if (pMsg->message == WM_KEYDOWN)
|
||
|
|
{
|
||
|
|
// Insert key pressed.
|
||
|
|
if (pMsg->wParam == VK_INSERT)
|
||
|
|
{
|
||
|
|
m_bInsertKey = !m_bInsertKey;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
return CWinApp::PreTranslateMessage(pMsg);
|
||
|
|
}
|
||
|
|
|
||
|
|
void CMDITextEditorApp::UpdateAllViews(CView* pSender/*=NULL*/)
|
||
|
|
{
|
||
|
|
for (POSITION posDoc = m_pDocTemplate->GetFirstDocPosition(); posDoc;)
|
||
|
|
{
|
||
|
|
CXTPSyntaxEditDoc* pDoc = DYNAMIC_DOWNCAST(
|
||
|
|
CXTPSyntaxEditDoc, m_pDocTemplate->GetNextDoc(posDoc));
|
||
|
|
|
||
|
|
if (pDoc)
|
||
|
|
pDoc->UpdateAllViews(pSender, xtpEditHintInitView);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
BOOL CMDITextEditorApp::ActivateExisting(const CString& csFilePath)
|
||
|
|
{
|
||
|
|
// try to find the document among existing ones
|
||
|
|
POSITION posDoc = m_pDocTemplate->GetFirstDocPosition();
|
||
|
|
while(posDoc)
|
||
|
|
{
|
||
|
|
// iterate next open document
|
||
|
|
CDocument *pDoc = m_pDocTemplate->GetNextDoc(posDoc);
|
||
|
|
|
||
|
|
// if docs names are the same
|
||
|
|
if (pDoc && csFilePath.CompareNoCase(pDoc->GetPathName()) == 0)
|
||
|
|
{
|
||
|
|
// make existing view as active
|
||
|
|
POSITION posView = pDoc->GetFirstViewPosition();
|
||
|
|
if (posView)
|
||
|
|
{
|
||
|
|
CView *pView = pDoc->GetNextView(posView);
|
||
|
|
if (pView)
|
||
|
|
{
|
||
|
|
CFrameWnd* pFrame = pView->GetParentFrame();
|
||
|
|
if (pFrame)
|
||
|
|
{
|
||
|
|
pFrame->ActivateFrame();
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
return TRUE; // document found, end iteration
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
return FALSE;
|
||
|
|
}
|
||
|
|
|
||
|
|
AFX_STATIC int AFX_CDECL GetStructSize()
|
||
|
|
{
|
||
|
|
OSVERSIONINFO ovi;
|
||
|
|
::ZeroMemory(&ovi, sizeof(OSVERSIONINFO));
|
||
|
|
ovi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
|
||
|
|
::GetVersionEx(&ovi);
|
||
|
|
|
||
|
|
// Windows 2000 or newer OS, we can use newer file open dialog.
|
||
|
|
if ((ovi.dwPlatformId >= VER_PLATFORM_WIN32_NT) && (ovi.dwMajorVersion >= 5))
|
||
|
|
return sizeof(OPENFILENAME) + 12;
|
||
|
|
|
||
|
|
// Use standard file open dialog.
|
||
|
|
return sizeof(OPENFILENAME);
|
||
|
|
}
|
||
|
|
|
||
|
|
void CMDITextEditorApp::OnFileOpen()
|
||
|
|
{
|
||
|
|
CString csFilter;
|
||
|
|
csFilter.LoadString(IDS_FILE_OPEN_FILTER);
|
||
|
|
|
||
|
|
DWORD dwOpenFlags =
|
||
|
|
OFN_HIDEREADONLY |
|
||
|
|
OFN_ALLOWMULTISELECT |
|
||
|
|
OFN_PATHMUSTEXIST |
|
||
|
|
OFN_FILEMUSTEXIST |
|
||
|
|
OFN_ENABLESIZING;
|
||
|
|
|
||
|
|
CFileDialog dlg(TRUE, NULL, NULL, dwOpenFlags, csFilter, NULL);
|
||
|
|
dlg.m_ofn.lStructSize = GetStructSize();
|
||
|
|
dlg.m_ofn.nFilterIndex = m_nFilterIndex;
|
||
|
|
dlg.m_ofn.lpstrInitialDir = m_csInitialDir;
|
||
|
|
|
||
|
|
if (dlg.DoModal() == IDOK)
|
||
|
|
{
|
||
|
|
for (POSITION pos = dlg.GetStartPosition(); pos;)
|
||
|
|
{
|
||
|
|
CString csFilePath(dlg.GetNextPathName(pos));
|
||
|
|
|
||
|
|
if (!ActivateExisting(csFilePath))
|
||
|
|
m_pDocTemplate->OpenDocumentFile(csFilePath);
|
||
|
|
}
|
||
|
|
m_nFilterIndex = dlg.m_ofn.nFilterIndex;
|
||
|
|
m_csInitialDir = dlg.m_ofn.lpstrInitialDir;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
void CMDITextEditorApp::OnFileSaveAll()
|
||
|
|
{
|
||
|
|
POSITION posDoc = m_pDocTemplate->GetFirstDocPosition();
|
||
|
|
while (posDoc)
|
||
|
|
{
|
||
|
|
CDocument* pDoc = m_pDocTemplate->GetNextDoc(posDoc);
|
||
|
|
if (pDoc->IsModified())
|
||
|
|
{
|
||
|
|
if (!pDoc->DoFileSave()) // error.
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
void CMDITextEditorApp::OnFileCloseAll()
|
||
|
|
{
|
||
|
|
POSITION posDoc = m_pDocTemplate->GetFirstDocPosition();
|
||
|
|
while (posDoc)
|
||
|
|
{
|
||
|
|
CDocument* pDoc = m_pDocTemplate->GetNextDoc(posDoc);
|
||
|
|
if (pDoc->IsModified())
|
||
|
|
{
|
||
|
|
if (!pDoc->SaveModified()) // user canceled.
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
pDoc->OnCloseDocument();
|
||
|
|
}
|
||
|
|
}
|