www.gusucode.com > 一个VC++语法分析模块程序实例源码程序 > 一个VC++语法分析模块程序实例/CompileSys/CompileSys/IDE/IDEView.cpp

    // IDEView.cpp : implementation of the CIDEView class
// Download: http://www.codesc.net

#include "stdafx.h"
#include "IDE.h"
#include "MainFrm.h"

#include "IDEDoc.h"
#include "IDEView.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

/////////////////////////////////////////////////////////////////////////////
// CIDEView

IMPLEMENT_DYNCREATE(CIDEView, CEditView)

BEGIN_MESSAGE_MAP(CIDEView, CEditView)
	//{{AFX_MSG_MAP(CIDEView)
	ON_COMMAND(IDM_START, OnStart)
	ON_COMMAND(IDM_SET, OnSet)
	ON_CONTROL_REFLECT(EN_CHANGE, OnChange)
	ON_WM_PAINT()
	ON_WM_KEYDOWN()
	ON_WM_KEYUP()
	ON_WM_LBUTTONDOWN()
	ON_WM_LBUTTONUP()
	ON_WM_LBUTTONDBLCLK()
	ON_WM_MOUSEMOVE()
	ON_WM_RBUTTONUP()
	ON_COMMAND(IDM_SELALL, OnSelall)
	ON_WM_CAPTURECHANGED()
	ON_COMMAND(IDM_CLEAN, OnClean)
	ON_COMMAND(IDM_FONT, OnFont)
	//}}AFX_MSG_MAP
	// Standard printing commands
	ON_COMMAND(ID_FILE_PRINT, CEditView::OnFilePrint)
	ON_COMMAND(ID_FILE_PRINT_DIRECT, CEditView::OnFilePrint)
	ON_COMMAND(ID_FILE_PRINT_PREVIEW, CEditView::OnFilePrintPreview)
	ON_MESSAGE(MSG_PAINTLEFT,OnPaintLeft)
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CIDEView construction/destruction

DWORD WINAPI CompileThread(LPVOID pParam)
{
	CIDEView *pView=(CIDEView*)pParam;

	pView->GetCompileResult();

	return 0;
}

CIDEView::CIDEView()
{
	// TODO: add construction code here
	m_pMainFrame=0;
	m_pwndStatusBar=0;
	m_strCompileProgName="PL.exe";

	m_nCurLn=0;
	m_nCurCol=0;
}

CIDEView::~CIDEView()
{
}

BOOL CIDEView::PreCreateWindow(CREATESTRUCT& cs)
{
	// TODO: Modify the Window class or styles here by modifying
	//  the CREATESTRUCT cs

	BOOL bPreCreated = CEditView::PreCreateWindow(cs);
	cs.style &= ~(ES_AUTOHSCROLL|WS_HSCROLL);	// Enable word-wrapping

	return bPreCreated;
}

/////////////////////////////////////////////////////////////////////////////
// CIDEView drawing

void CIDEView::OnDraw(CDC* pDC)
{
	CIDEDoc* pDoc = GetDocument();
	ASSERT_VALID(pDoc);
	// TODO: add draw code for native data here
}

/////////////////////////////////////////////////////////////////////////////
// CIDEView printing

BOOL CIDEView::OnPreparePrinting(CPrintInfo* pInfo)
{
	// default CEditView preparation
	return CEditView::OnPreparePrinting(pInfo);
}

void CIDEView::OnBeginPrinting(CDC* pDC, CPrintInfo* pInfo)
{
	// Default CEditView begin printing.
	CEditView::OnBeginPrinting(pDC, pInfo);
}

void CIDEView::OnEndPrinting(CDC* pDC, CPrintInfo* pInfo)
{
	// Default CEditView end printing
	CEditView::OnEndPrinting(pDC, pInfo);
}

/////////////////////////////////////////////////////////////////////////////
// CIDEView diagnostics

#ifdef _DEBUG
void CIDEView::AssertValid() const
{
	CEditView::AssertValid();
}

void CIDEView::Dump(CDumpContext& dc) const
{
	CEditView::Dump(dc);
}

CIDEDoc* CIDEView::GetDocument() // non-debug version is inline
{
	ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(CIDEDoc)));
	return (CIDEDoc*)m_pDocument;
}
#endif //_DEBUG

/////////////////////////////////////////////////////////////////////////////
// CIDEView message handlers

void CIDEView::OnStart() 
{
	// TODO: Add your command handler code here
	DWORD dwThreadID;

	m_pMainFrame->ShowControlBar(m_pwndOutBar,1,0);
	::CreateThread(0,0,CompileThread,this,0,&dwThreadID);//创建进程
}

void CIDEView::GetCompileResult()
{
	SECURITY_ATTRIBUTES sa;
 	HANDLE hRead,hWrite;
	CString strFile;
	CString str;
	CString strOut;
	CIDEDoc *pDoc=GetDocument();

	strFile=pDoc->GetPathName();
	if(strFile=="")//该文件没有保存过
	{
		CFileDialog fileDlg(0,0,0,0,"PL/0源文件(*.pas)|*.pas|文本文件(*.txt)|*.txt|任何文件(*.*)|*.*|",this);
		
		if(fileDlg.DoModal()!=IDOK)
			return;
		
		strFile=fileDlg.GetPathName();
		if(strFile.Right(4)!=".pas")
			strFile+=".pas";
	}
	//下段这段代码在Debug版本下有错误,在Release版本下没问题,不知道为什么
	//--------------------------------------------
	pDoc->SetPathName(strFile,1);
	pDoc->SetModifiedFlag(0);
	pDoc->OnSaveDocument((LPSTR)(LPCSTR)strFile);//先保存该文件
	str=pDoc->GetTitle();
	pDoc->SetTitle(str);
	if(str.Right(1)=="*")
	{
		str=str.Left(str.GetLength()-1);
		pDoc->SetTitle(str);
	}
	UpdateWindow();
	//--------------------------------------------

	strFile=m_strCompileProgName+" "+(char)34+strFile+(char)34;
	m_pwndOutBar->SetFocus();

 	sa.nLength=sizeof(SECURITY_ATTRIBUTES);
 	sa.lpSecurityDescriptor=NULL;
 	sa.bInheritHandle=TRUE;
 	if(!CreatePipe(&hRead,&hWrite,&sa,0))//创建管道进行通信
 	{
 		MessageBox("分析器不存在,请重新输入其路径","错误",MB_ICONWARNING);
		OnSet();
 		return;
 	}
 
 	STARTUPINFO si;
 	PROCESS_INFORMATION pi;
 
 	si.cb=sizeof(STARTUPINFO);
 	GetStartupInfo(&si);
 	si.hStdError=hWrite;
 	si.hStdOutput=hWrite;
 	si.wShowWindow=SW_HIDE;
 	si.dwFlags=STARTF_USESHOWWINDOW | STARTF_USESTDHANDLES;
	//创建进程启动分析核心程序
 	if(!CreateProcess(NULL,(LPSTR)(LPCTSTR)strFile,NULL,NULL,TRUE,NULL,NULL,NULL,&si,&pi))
 	{
 		MessageBox("分析器不存在,请重新输入其路径","错误",MB_ICONWARNING);
		OnSet();
 		return;
 	}
 	CloseHandle(hWrite);
 	
 	char buffer[4096]={0};
 	DWORD bytesRead;
 
 	while(true)
 	{
 		if(!ReadFile(hRead,buffer,4095,&bytesRead,NULL))
 			break;
 		strOut+=buffer;
		m_pwndOutBar->SetColorRichEditText(strOut);
		m_pwndOutBar->GetRichEditCtrl()->PostMessage(WM_VSCROLL,SB_BOTTOM,0);
 		Sleep(500);
 	}

	//-----------读取分析结果并显示-----------
	CString strLeft,strRight;
	int nPos;

	str=m_pIDEDoc->GetPathName();
	nPos=str.ReverseFind('\\');
	strLeft=str.Left(nPos+1);
	strRight=str.Right(str.GetLength()-nPos-1);
	if(strRight.Right(4)==".pas")
		str=strLeft+strRight.Left(strRight.GetLength()-4)+"_LexAnanlysisResult.dat";
	else
		str=strLeft+strRight+"_LexAnanlysisResult.dat";

	if(GetFileAttributes(str)!=-1)
	{
		CFile file(str,CFile::modeRead);
		LEXPROPERTYVS lpvTemp;
		int nSize=sizeof(LEXPROPERTYVS)-sizeof(char*);
		int nCount=file.GetLength()/nSize;
		
		m_vectorSymbol.clear();
		for(int i=0;i<nCount;i++)
		{
			file.Read((char*)&lpvTemp,nSize);
			m_vectorSymbol.push_back(lpvTemp);
		}
	}

	DisplayCodeInfo();//显示分析结果
	//----------------------------------------
}

void CIDEView::OnInitialUpdate() 
{
	CEditView::OnInitialUpdate();
	
	// TODO: Add your specialized code here and/or call the base class
	m_pMainFrame=(CMainFrame*)::AfxGetApp()->m_pMainWnd;
	m_pwndOutBar=m_pMainFrame->GetOutBar();
	m_pwndWorkSpaceBar=m_pMainFrame->GetWorkSapceBar();
	m_pTreeCtrl=m_pwndWorkSpaceBar->GetTreeCtrl();
	m_pwndStatusBar=m_pMainFrame->GetStatusBar();
	m_pEdit=&GetEditCtrl();
	m_pIDEDoc=GetDocument();

	//-----------设置自动换行-----------
	m_pEdit->ShowScrollBar(SB_BOTH,1);
	AfxGetApp()->WriteProfileInt(_T("Editor Settings"),_T("Auto Return"),1);
	//----------------------------------

	//-----------设置字体-----------
	CFont *pFont=CFont::FromHandle((HFONT)::GetStockObject(SYSTEM_FIXED_FONT));
	m_pEdit->SetFont(pFont);
	//------------------------------

	//------------设置编辑框的左边界------------
	SIZE size;

	GetTextExtentPoint(GetDC()->GetSafeHdc(),"A",1,&size);
	m_LineHeight=size.cy;//得到行的高度
	m_pEdit->SetMargins(m_LineHeight+6,0);
	//------------------------------------------
	
	DisplayLnCol();//在状态栏上显示行列信息
}

void CIDEView::OnFont() 
{
	// TODO: Add your command handler code here
	CFontDialog fontDlg;
	LOGFONT lf;
	CFont font;
	
	if(fontDlg.DoModal()==IDOK)
	{
		fontDlg.GetCurrentFont(&lf);
		font.CreateFontIndirect(&lf);
		m_pEdit->SetFont(&font,1);
	}
}

void CIDEView::OnSet() 
{
	// TODO: Add your command handler code here
	if(m_SetDlg.DoModal()!=IDOK)
		return;

	m_strCompileProgName=m_SetDlg.GetCompileProgName();
}

void CIDEView::OnChange() 
{
	// TODO: If this is a RICHEDIT control, the control will not
	// send this notification unless you override the CEditView::OnInitDialog()
	// function and call CRichEditCtrl().SetEventMask()
	// with the ENM_CHANGE flag ORed into the mask.
	
	// TODO: Add your control notification handler code here
	CIDEDoc *pDoc=GetDocument();
	CString str;

	pDoc->SetModifiedFlag(1);
	str=pDoc->GetTitle();
	if(str.Right(1)!="*")
	{
		str=str+"*";
		pDoc->SetTitle(str);
	}

	PaintLeft();
}

//画左边的显示条
void CIDEView::PaintLeft()
{
	CBrush brushb(RGB(245,245,230));
	CDC* hdc;
	hdc=GetWindowDC();
	CRect rect;
	GetClientRect(&rect);
	hdc->FillRect (CRect(rect.left+2,rect.top+2,rect.left+m_LineHeight+7,rect.Height()+2),&brushb);//画底色
	brushb.DeleteObject();

	int nFirstVisible=m_pEdit->GetFirstVisibleLine();//得到当前显示的最上端的行号

	CBrush OrigBrush,brushf(RGB(255,0,0));
	CBrush *oldBrush=(CBrush*)hdc->SelectObject(brushf);
	OrigBrush.FromHandle((HBRUSH)oldBrush);

	hdc->SelectObject(&OrigBrush);
	OrigBrush.DeleteObject();
	brushf.DeleteObject();
}

void CIDEView::OnPaint() 
{
	// TODO: Add your message handler code here
	CEditView::OnPaint();

	PaintLeft();
	// Do not call CEditView::OnPaint() for painting messages
}

void CIDEView::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags) 
{
	// TODO: Add your message handler code here and/or call default
	PaintLeft();

	switch(nChar)
	{
	case VK_UP:
		m_nCurLn=m_nCurLn>0?m_nCurLn-1:0;
		break;

	case VK_DOWN:
		m_nCurLn=m_nCurLn+1;
		break;

	case VK_LEFT:
	case VK_BACK:
		m_nCurCol=m_nCurCol>0?m_nCurCol-1:0;
		break;

	case VK_SPACE:
	case VK_RIGHT:
		m_nCurCol=m_nCurCol+1;
		break;

	case VK_RETURN:
		m_nCurLn+=1;
		m_nCurCol=0;
		break;

	case VK_ESCAPE:
		m_pMainFrame->ShowControlBar(m_pwndOutBar,0,1);
		break;

	case VK_TAB:
		m_nCurCol+=8;
		break;
	}

	DisplayLnCol();

	CEditView::OnKeyDown(nChar, nRepCnt, nFlags);
}

void CIDEView::OnKeyUp(UINT nChar, UINT nRepCnt, UINT nFlags) 
{
	// TODO: Add your message handler code here and/or call default
	PaintLeft();

	CEditView::OnKeyUp(nChar, nRepCnt, nFlags);
}

void CIDEView::OnLButtonDown(UINT nFlags, CPoint point) 
{
	// TODO: Add your message handler code here and/or call default
	PaintLeft();

	CString str;
	int nChar=m_pEdit->CharFromPos(point);

	m_nCurLn=HIWORD(nChar);
	m_nCurCol=LOWORD(nChar);
	str.Format("行:%d,列:%d",m_nCurLn,m_nCurCol);	
	m_pwndStatusBar->SetPaneText(1,str,1);

	CEditView::OnLButtonDown(nFlags, point);
}

void CIDEView::OnLButtonUp(UINT nFlags, CPoint point) 
{
	// TODO: Add your message handler code here and/or call default
	PaintLeft();

	CEditView::OnLButtonUp(nFlags, point);
}

void CIDEView::OnLButtonDblClk(UINT nFlags, CPoint point) 
{
	// TODO: Add your message handler code here and/or call default
	PaintLeft();

	CEditView::OnLButtonDblClk(nFlags, point);
}

void CIDEView::OnMouseMove(UINT nFlags, CPoint point) 
{
	// TODO: Add your message handler code here and/or call default
	PaintLeft();

	CEditView::OnMouseMove(nFlags, point);
}

void CIDEView::DisplayCodeInfo()
{
	TREENODE_LPV tnlpvTemp;
	TREE_FILE trfTemp;
	CString strFile=m_pIDEDoc->GetPathName();
	int nLen=m_vectorSymbol.size();
	CString strCode;
	int i;

	//-----------删掉相同的信息-----------
	HTREEITEM hFindRoot=m_pTreeCtrl->GetRootItem();

	while(hFindRoot)
	{
		if(m_pTreeCtrl->GetItemText(hFindRoot)==strFile)
			m_pTreeCtrl->DeleteItem(hFindRoot);

		hFindRoot=m_pTreeCtrl->GetNextItem(hFindRoot,TVGN_NEXT);
	}

	m_vectorTreeNode_Lpv.clear();
	//------------------------------------

	GetWindowText(strCode);

	HTREEITEM hRoot=m_pTreeCtrl->InsertItem(strFile,0,0);
	HTREEITEM hKeyWordSubRoot=m_pTreeCtrl->InsertItem("关键字",hRoot,0);
	HTREEITEM hIdSubRoot=m_pTreeCtrl->InsertItem("变量",hRoot,0);
	HTREEITEM hConstSubRoot=m_pTreeCtrl->InsertItem("常量",hRoot,0);
	HTREEITEM hOprSymSubRoot=m_pTreeCtrl->InsertItem("运算符",hRoot,0);
	HTREEITEM hBndSymSubRoot=m_pTreeCtrl->InsertItem("界符",hRoot,0);
	HTREEITEM hIllegalCharSubRoot=m_pTreeCtrl->InsertItem("非法字符",hRoot,0);

	bool bKeyWord=0;
	bool bId=0;
	bool bConst=0;
	bool bOprSym=0;
	bool bBndSym=0;
	bool bIllegalChar=0;

	for(i=0;i<nLen;i++)
	{
		switch(m_vectorSymbol[i].lpProperty)
		{
		case KeyWord:
			tnlpvTemp.hTreeItem=m_pTreeCtrl->InsertItem(strCode.Mid(m_vectorSymbol[i].nStrPos,m_vectorSymbol[i].nStrLen),hKeyWordSubRoot,0);
			bKeyWord=1;
			break;

		case Id:
			tnlpvTemp.hTreeItem=m_pTreeCtrl->InsertItem(strCode.Mid(m_vectorSymbol[i].nStrPos,m_vectorSymbol[i].nStrLen),hIdSubRoot,0);
			bId=1;
			break;

		case Const:
			tnlpvTemp.hTreeItem=m_pTreeCtrl->InsertItem(strCode.Mid(m_vectorSymbol[i].nStrPos,m_vectorSymbol[i].nStrLen),hConstSubRoot,0);
			bConst=1;
			break;

		case OprSym:
			tnlpvTemp.hTreeItem=m_pTreeCtrl->InsertItem(strCode.Mid(m_vectorSymbol[i].nStrPos,m_vectorSymbol[i].nStrLen),hOprSymSubRoot,0);
			bOprSym=1;
			break;

		case BndSym:
			tnlpvTemp.hTreeItem=m_pTreeCtrl->InsertItem(strCode.Mid(m_vectorSymbol[i].nStrPos,m_vectorSymbol[i].nStrLen),hBndSymSubRoot,0);
			bBndSym=1;
			break;
		
		case IllegalChar:
			tnlpvTemp.hTreeItem=m_pTreeCtrl->InsertItem(strCode.Mid(m_vectorSymbol[i].nStrPos,m_vectorSymbol[i].nStrLen),hIllegalCharSubRoot,0);
			bIllegalChar=1;
			break;
		}

		tnlpvTemp.lpv=m_vectorSymbol[i];
		m_vectorTreeNode_Lpv.push_back(tnlpvTemp);
	}

	if(!bKeyWord)
		m_pTreeCtrl->DeleteItem(hKeyWordSubRoot);
	if(!bId)
		m_pTreeCtrl->DeleteItem(hIdSubRoot);
	if(!bConst)
		m_pTreeCtrl->DeleteItem(hConstSubRoot);
	if(!bOprSym)
		m_pTreeCtrl->DeleteItem(hOprSymSubRoot);
	if(!bBndSym)
		m_pTreeCtrl->DeleteItem(hBndSymSubRoot);
	if(!bIllegalChar)
		m_pTreeCtrl->DeleteItem(hIllegalCharSubRoot);

	trfTemp.vectorTnl=m_vectorTreeNode_Lpv;
	trfTemp.szFile=(LPSTR)(LPCSTR)strFile;
	m_pwndWorkSpaceBar->AddTRF(trfTemp);

	m_pTreeCtrl->Expand(hRoot,TVE_EXPAND);
}

void CIDEView::OnRButtonUp(UINT nFlags, CPoint point) 
{
	// TODO: Add your message handler code here and/or call default
	BCMenu *menuPopup;
	BCMenu menu;

	menu.LoadMenu(IDR_IDETYPE);
	if(m_pMainFrame->GetScreenStatus())
		menuPopup=(BCMenu*)menu.GetSubMenu(2);
	else
		menuPopup=(BCMenu*)menu.GetSubMenu(1);

	ClientToScreen(&point);
	menuPopup->TrackPopupMenu(TPM_LEFTALIGN | TPM_RIGHTBUTTON,point.x,point.y,this);
	menuPopup->DestroyMenu();
}

void CIDEView::OnSelall() 
{
	// TODO: Add your command handler code here
	CString str;

	GetWindowText(str);
	m_pEdit->SetSel(0,str.GetLength(),1);
}

void CIDEView::DisplayLnCol()
{
	CString str;

	str.Format("行:%d,列:%d",m_nCurLn,m_nCurCol);		
	m_pwndStatusBar->SetPaneText(1,str,1);
}

void CIDEView::OnCaptureChanged(CWnd *pWnd) 
{
	// TODO: Add your message handler code here
	PaintLeft();

	CEditView::OnCaptureChanged(pWnd);
}

void CIDEView::OnPaintLeft(WPARAM wParam,LPARAM lParam)
{
	PaintLeft();
}

void CIDEView::OnClean() 
{
	// TODO: Add your command handler code here
	CString str;
	CString strLeft,strRight;
	int nPos;

	str=m_pIDEDoc->GetPathName();
	nPos=str.ReverseFind('\\');
	strLeft=str.Left(nPos+1);
	strRight=str.Right(str.GetLength()-nPos-1);
	if(strRight.Right(4)==".pas")
		str=strLeft+strRight.Left(strRight.GetLength()-4)+"_LexAnanlysisResult.dat";
	else
		str=strLeft+strRight+"_LexAnanlysisResult.dat";

	if(GetFileAttributes(str)==-1)
		return;

	CFile file;

	file.Remove(str);
}