www.pudn.com > huicad.rar > PREVIEW.CPP


//	本文件中的函数主要用于保存和显示预显位图	//		00-10-20 
 
#include "stdafx.h" 
#include "VCad.h" 
#include "VCadDoc.h" 
#include "VCadView.h" 
 
//	预显图形的大小 
#define BMP_PREVIEW_WIDTH	200  
#define BMP_PREVIEW_HEIGHT	128 
 
unsigned char *g_pBmpBuf = NULL;	//位图缓冲区 
 
//	以下三个函数在外部使用 
//将用于预显的位图写入文件 
void BitmapSerialize(CArchive& ar); 
//将客户窗口内的图形存为位图 
void GenBitmap(); 
//	得到VCAD文件名 
BOOL GetCADName(BOOL bIsOpen,CString& sFileName); 
 
//压缩与解压缩位图的详细原理见《图像格式编程指南》(清华大学出版社)GIF图像一章 
//压缩用于预显的位图  
DWORD Compressed(short *pComBuf,unsigned char *lpBuf,UINT nCount); 
void pack_init(int clear,short *reqcnt,short first_ch,short *oldcode, 
			   short *nextcode,short *nextlim,short *CTlink,short *CTnext, 
			   unsigned char *CTfirst); 
short lookup_ct(short code,unsigned char thischar,short *nextcode, 
				short *CTlink,short *CTnext,unsigned char *CTfirst); 
//解压缩用于预显的位图  
void DeCompressed(unsigned char *entBuffer,short *filebuf); 
void unpack_init(short clear,short *nextcode,short *oldcode, 
				short *reqcnt,short *nextlim,short first_ch, 
				 unsigned char *CTfirst,unsigned char *CTlast, 
				 short *CTlink); 
void putx(short code,unsigned char *OStack,unsigned char *CTlast, 
		  short *CTlink,unsigned char *entBuffer,DWORD *size); 
void insert_ct(short code,short oldcode,short *nextcode,short *nextlim, 
			   short *reqcnt,short *CTlink,unsigned char *CTfirst, 
			   unsigned char *CTlast); 
 
//	生成预览位图 
void GenBitmap() 
{ 
	CRect	clientRect; 
	CBitmap	bitmap; 
	CClientDC	dc(g_pView); 
	CDC		memDC; 
	DWORD	i=0,dwCount=0; 
	int		x=0,y=0; 
	COLORREF	color; 
	 
	CRect prevrect(0,0,BMP_PREVIEW_WIDTH,BMP_PREVIEW_HEIGHT); 
	g_pView->GetClientRect(&clientRect);//得到客户窗口的矩形 
	bitmap.CreateCompatibleBitmap(&dc, 
			BMP_PREVIEW_WIDTH,BMP_PREVIEW_HEIGHT);//初始化空白位图 
	memDC.CreateCompatibleDC(&dc);//创建内存设备情景对象 
	memDC.SelectObject(&bitmap);//将位图选入内存设备情景对象 
 
	memDC.SetMapMode(MM_TEXT);  
 
	memDC.Rectangle(&prevrect);	//	绘制边界并清除绘制区域 
 
	//	根据当前绘图区大小和预览图形大小来计算缩放比例 
	double dScale=1.0*clientRect.Width()/BMP_PREVIEW_WIDTH; 
	//	缩小绘制所有元素 
	  // 首先得到当前状态系统的设置 
	double dOldScale = g_pView->GetScale(); // 缩放比例 
	dScale *= dOldScale; 
	double dOldOrgX = g_pView->m_dOrgX; // 屏幕中心点的世界坐标 
	double dOldOrgY = g_pView->m_dOrgY; 
      // 然后设置各状态变量,以便使得在设备环境左上方绘制图形 
	g_pView->m_dOrgX = (clientRect.Width() - BMP_PREVIEW_WIDTH)/2 * dScale; 
	g_pView->m_dOrgY = -(clientRect.Height() - BMP_PREVIEW_HEIGHT)/2 * dScale ; 
	g_pView->SetScale(dScale); 
	g_pView->OnDraw(&memDC); 
	  // 最后恢复各系统状态设置 
	g_pView->SetScale(dOldScale); 
	g_pView->m_dOrgX = dOldOrgX; 
	g_pView->m_dOrgY = dOldOrgY; 
		 
	dwCount=BMP_PREVIEW_WIDTH*BMP_PREVIEW_HEIGHT*3;//得到位图数据的字节数 
	//	分配位图数据缓冲区 
	if(g_pBmpBuf!=NULL) 
		delete g_pBmpBuf; 
	g_pBmpBuf=new BYTE[dwCount];			 
	//	得到位图数据 
	i=0; 
	for(y=BMP_PREVIEW_HEIGHT-1;y>=0;y--)		 
	{ 
		for(x=0;x>16);//B 
			g_pBmpBuf[i*3+1]=(BYTE)((color&0x0000ff00)>>8);//G 
			g_pBmpBuf[i*3+2]=(BYTE)(color&0x000000ff);//R 
		} 
	} 
 
	memDC.SetMapMode(MM_LOENGLISH);  
} 
 
//	将用于预显的位图数据写入文件  
void BitmapSerialize(CArchive& ar) 
{ 
	DWORD	i=0,dwCount=0,len=0; 
	dwCount=BMP_PREVIEW_WIDTH*BMP_PREVIEW_HEIGHT*3;//得到位图数据的字节数 
 
	if(ar.IsStoring()) 
	{ 
		len=dwCount; 
		ar<>len;	//读入压缩位图的长度 
		unsigned char buf;	//位图数据缓冲区 
		for(i=0;i>buf; 
	} 
} 
 
//	从选择的文件中得到预显位图数据 
BOOL GetFileSelect(unsigned char *entBuffer,char *filenamestring) 
{ 
	CFile	 file; 
	//打开文件 
	if(!file.Open(filenamestring,CFile::modeRead))  
		return FALSE; 
	CArchive ar(&file,CArchive::load); 
 
	DWORD dwCount=BMP_PREVIEW_WIDTH*BMP_PREVIEW_HEIGHT*3;//得到位图数据的字节数 
	DWORD i,len; 
	ar>>len;//文件中压缩后的位图数据长度 
	for(i=0;i>entBuffer[i];		//从文件中读入位图数据 
 
	ar.Close(); 
	file.Close(); 
    return TRUE; 
} 
 
//	根据预显位图数据在指定位置显示位图 
void DisplayBitmap(HDC hDC,int x,int y,unsigned char *entBuffer) 
{ 
	BITMAPINFO bmInfo; 
	bmInfo.bmiHeader.biSize=sizeof(bmInfo.bmiHeader); 
	bmInfo.bmiHeader.biWidth=BMP_PREVIEW_WIDTH; 
	bmInfo.bmiHeader.biHeight=BMP_PREVIEW_HEIGHT; 
	bmInfo.bmiHeader.biPlanes=1; 
	bmInfo.bmiHeader.biBitCount=24; 
	bmInfo.bmiHeader.biCompression=BI_RGB; 
	bmInfo.bmiHeader.biSizeImage=BMP_PREVIEW_WIDTH*BMP_PREVIEW_HEIGHT*3; 
	bmInfo.bmiHeader.biClrUsed=1; 
	bmInfo.bmiHeader.biClrImportant=0; 
	SetDIBitsToDevice(hDC,x,y,BMP_PREVIEW_WIDTH, 
			BMP_PREVIEW_HEIGHT,0,0,0,BMP_PREVIEW_HEIGHT,entBuffer, 
			&bmInfo,DIB_RGB_COLORS); 
} 
 
//	打开/保存文件的钩子函数 
UINT APIENTRY OFNHookProc(HWND hdlg,UINT uiMsg,WPARAM wParam,LPARAM lParam) 
{ 
	static char szFile[256]; //文件名 
	static BOOL	bFolderChag;		//目录是否改变标志 
	static BOOL bIsPreview = TRUE;	//是否选中预显图形 
	static CRect	rectPrev=CRect(0,0,0,0);//预显矩形 
	static BOOL bIsCADFlag = FALSE;	//选中的是否为CAD文件标志 
	UINT	code; 
 
	switch (uiMsg) 
	{ 
	case WM_INITDIALOG:	//	初始化对话框 
	{ 
		SetWindowLong(hdlg, DWL_USER, lParam); 
		HWND hWnd=GetDlgItem(hdlg,IDC_STATIC_FILEPREVIEW); 
		GetWindowRect(hWnd,&rectPrev);	//得到预显窗口矩形 
		POINT point[2]; 
		point[0]=rectPrev.TopLeft(); 
		point[1]=rectPrev.BottomRight(); 
		ScreenToClient(hdlg,&point[0]); 
		ScreenToClient(hdlg,&point[1]); 
		rectPrev.left=point[0].x; 
		rectPrev.right=point[1].x; 
		rectPrev.top=point[0].y; 
		rectPrev.bottom=point[1].y; 
		DWORD dwCount=BMP_PREVIEW_WIDTH*BMP_PREVIEW_HEIGHT*3;//得到位图数据的字节数 
		g_pBmpBuf=new unsigned char[dwCount];		//分配位图数据缓冲区 
		if(g_pBmpBuf==NULL) 
			return FALSE; 
		bFolderChag=FALSE; 
		bIsPreview=TRUE; 
		HWND hCheck=GetDlgItem(hdlg,IDC_CHECK_PREVIEW); 
		::SendMessage(hCheck,BM_SETCHECK,BST_CHECKED,0); 
 
	} 
		return FALSE; 
	case WM_DESTROY:	//	对话框的销毁处理 
		if(g_pBmpBuf!=NULL) 
		{ 
			delete []g_pBmpBuf;	//删除位图数据缓冲区 
			g_pBmpBuf=NULL; 
		} 
		bIsCADFlag=FALSE; 
		return FALSE; 
	case WM_PAINT:	//	绘制对话框中的预览位图 
		{ 
			try 
			{ 
				CWnd *pWnd; 
				pWnd=CWnd::FromHandle(hdlg); 
				HDC hDC=GetDC(hdlg); 
				CDC *pDC; 
				pDC=CDC::FromHandle(hDC); 
				CPoint midpoint=rectPrev.CenterPoint(); 
				int nXOffset=16,nYOffset=4; 
				if(bIsCADFlag==TRUE&&bIsPreview==TRUE) 
				{	//选中的为合法文件且打开了预显开关 
					//输出预显位图 
					DisplayBitmap(hDC,midpoint.x+nXOffset-BMP_PREVIEW_WIDTH/2, 
							midpoint.y+nYOffset-BMP_PREVIEW_HEIGHT/2,g_pBmpBuf); 
				} 
				else	 
				{	//将预显部分涂成底色 
					CBrush brush(RGB(192,192,192)); 
					CRect rect(midpoint.x+nXOffset-BMP_PREVIEW_WIDTH/2, 
							midpoint.y+nYOffset-BMP_PREVIEW_HEIGHT/2, 
							midpoint.x+nXOffset+BMP_PREVIEW_WIDTH/2, 
							midpoint.y+nYOffset+BMP_PREVIEW_HEIGHT/2); 
					pDC->FillRect(&rect,&brush); 
				} 
				ReleaseDC(hdlg,hDC); 
			} 
			catch (CResourceException) 
			{ 
				return FALSE; 
			} 
			return FALSE; 
		} 
	case WM_COMMAND:	//	处理是否预显选项 
		if(LOWORD(wParam)==IDC_CHECK_PREVIEW&& 
				HIWORD(wParam)==BN_CLICKED) 
		{ 
			bIsPreview=!bIsPreview; 
			::SendMessage(hdlg,WM_PAINT,0,0); 
		} 
		return FALSE; 
	case WM_NOTIFY:	//	处理通知消息 
		code=((LPOFNOTIFY)lParam)->hdr.code; 
		switch(code) 
		{ 
		case CDN_SELCHANGE:	//	当选择不同的文件时 
			if (CommDlg_OpenSave_GetFilePath(GetParent(hdlg), 
				szFile, sizeof(szFile)) <= sizeof(szFile))//得到文件名 
			{ 
				if(bFolderChag==TRUE)//目录改变,已经在CDN_FOLDERCHANGE中进行了处理,因此返回 
				{ 
					::SendMessage(hdlg,WM_PAINT,0,0); 
					bFolderChag=FALSE; 
					return FALSE; 
				} 
				//判断是否为合法文件 
				int length=strlen(szFile); 
				if(length<7) 
					return FALSE; 
				char ext[4]; 
				HWND hWnd=GetDlgItem(hdlg,IDC_STATIC_FILEPREVIEW); 
				ext[3]='\0'; 
				ext[2]=szFile[length-1]; 
				ext[1]=szFile[length-2]; 
				ext[0]=szFile[length-3]; 
				_strlwr(ext); 
				if(strcmp(ext,"cad")==0) 
				{ 
					bIsCADFlag=TRUE; 
					if(!GetFileSelect(g_pBmpBuf,szFile)) //得到位图数据 
						bIsCADFlag=FALSE; 
				} 
				else  
					bIsCADFlag=FALSE; 
				::SendMessage(hdlg,WM_PAINT,0,0); 
			} 
			return FALSE; 
		case CDN_FOLDERCHANGE:	//	当选中的文件夹改变时 
			//目录改变,如果新目录中没有CAD文件,那么就没有CDN_SELCHANGE消息发出 
			//否则执行完这部分后就会执行CDN_DELCHANGE的消息处理 
			if (CommDlg_OpenSave_GetFilePath(GetParent(hdlg), 
				szFile, sizeof(szFile)) <= sizeof(szFile)) 
			{ 
				bFolderChag=TRUE; 
				//判断是否为合法文件 
				int length=strlen(szFile); 
				if(length<7) 
					return FALSE; 
				char ext[4]; 
				HWND hWnd=GetDlgItem(hdlg,IDC_STATIC_FILEPREVIEW); 
				ext[3]='\0'; 
				ext[2]=szFile[length-1]; 
				ext[1]=szFile[length-2]; 
				ext[0]=szFile[length-3]; 
				_strlwr(ext); 
				if(strcmp(ext,"CAD")==0) 
				{ 
					bIsCADFlag=TRUE; 
					if(!GetFileSelect(g_pBmpBuf,szFile)) 
						bIsCADFlag=FALSE; 
				} 
				else bIsCADFlag=FALSE; 
				::SendMessage(hdlg,WM_PAINT,0,0); 
			} 
			return FALSE; 
		case CDN_FILEOK:	//	单击“确定”按钮 
			return TRUE; 
		} 
	} 
	return FALSE; 
} 
 
//	得到CAD文件名 
BOOL GetCADName(BOOL bIsOpen,CString& sFileName) 
{ 
	CString sFilter="图形文件"; 
	sFilter += "(*.CAD)|*.CAD|";	 
	sFilter.Replace('|','\0'); 
	char	strFileName[256]="\0"; 
	CString sTitle; 
	BOOL bRet=TRUE; 
 
	if(bIsOpen) 
		sTitle="打开文件"; 
	else 
		sTitle="另存文件"; 
 
	OPENFILENAME ofn; 
 
	ofn.lStructSize       = sizeof(OPENFILENAME); 
    ofn.hwndOwner         = AfxGetMainWnd()->m_hWnd; 
    ofn.hInstance         = AfxGetInstanceHandle(); 
    ofn.lpstrFilter       = sFilter; 
    ofn.lpstrCustomFilter = NULL; 
    ofn.nMaxCustFilter    = 0; 
    ofn.nFilterIndex      = 0; 
    ofn.lpstrFile         = strFileName; 
    ofn.nMaxFile          = sizeof(strFileName); 
    ofn.lpstrFileTitle    = NULL; 
    ofn.nMaxFileTitle     = 0; 
    ofn.lpstrInitialDir   = NULL; 
    ofn.lpstrTitle        = sTitle; 
    ofn.nFileOffset       = 0; 
    ofn.nFileExtension    = 0; 
    ofn.lpstrDefExt       = "CAD"; 
	ofn.lpfnHook 		  = OFNHookProc; 
	ofn.lpTemplateName    = MAKEINTRESOURCE(IDD_DIALOG_FILEPREVIEW); 
    ofn.Flags             = OFN_ENABLETEMPLATE|//OFN_NOVALIDATE| 
							 OFN_EXPLORER |OFN_ENABLEHOOK|OFN_HIDEREADONLY| 
							 OFN_OVERWRITEPROMPT; 
 
    if (bIsOpen) 
		bRet=GetOpenFileName(&ofn); 
	else 
		bRet=GetSaveFileName(&ofn); 
	 
	if(bRet) 
		sFileName=ofn.lpstrFile; 
 
	return bRet; 
 
}