嵌入式开发之上位机工业风界面实现

news2024/12/23 23:21:50

      在做测控类的嵌入式系统开发时,一个精美的上位机控制软件UI是可以为系统增色不少,一般会采用组态软件来开发,我们来看看下面的界面

b7246a38df504c85a213f38c4f2c9936.png

是不是非常直观有工业质感,还可以根据实时数据进行动态的显示和动画效果,那这些炫酷的界面是怎么实现的呢,我们来探讨一下相关技术。

     首先我们看到的漂亮精美的画面是一幅一幅的png图片或者gif动图,如果我们能找到方法将这些图片根据状态或采集数据和状态的需要,实时的展示渲染出来是不是就可以了呢。

     渲染技术其实从图像系统出来就一直在进化,游戏是这方面的优秀应用场景,可以用gdi gdiplus opengl vuklan webgpu等技术实现多平台,甚至跨平台的UI

下面是一组工业风的开关,可以用双缓冲的gdi plus方式结合鼠标的操作事件进行切换显示就可以实现形象的工业控制开关

07594d108aad4d15a31da14bd958503e.pngadca1a297f724d17bd8bc10f08719141.pngd42f96cd375d4b62be2a2f735afa64b5.png8d35f2fc4cf945aba3517c403f7dbd89.png0d138901e16f4ae7be7dabf99ed8aba9.png56ef2962b046489abaac42d342cd6e55.png

下面就是一个switcherctl的类实现,可以嵌入到你的代码中实现工业开关控制

// SwitcherCtrl.cpp : implementation file
//

#include "stdafx.h"
#include "VDC300Controler.h"
#include "SwitcherCtrl.h"
#include "DrawFunction.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

/
// CSwitcherCtrl

CSwitcherCtrl::CSwitcherCtrl()
{
}

CSwitcherCtrl::~CSwitcherCtrl()
{

}


BEGIN_MESSAGE_MAP(CSwitcherCtrl, CWnd)
	//{{AFX_MSG_MAP(CSwitcherCtrl)
	ON_WM_PAINT()
	ON_WM_LBUTTONDOWN()
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

/
// CSwitcherCtrl message handlers
BOOL CSwitcherCtrl::Create(DWORD dwStyle, const RECT& rect, 
                         CWnd* pParentWnd, UINT nID) 
{
	
  BOOL result ;
  static CString className = AfxRegisterWndClass(CS_HREDRAW | CS_VREDRAW) ;

  result = CWnd::CreateEx(NULL, 
                          className, NULL, dwStyle, 
                          rect.left, rect.top, rect.right-rect.left+45, rect.bottom-rect.top+30,
                          pParentWnd->GetSafeHwnd(), (HMENU)nID) ;
  if (result != 0)
  {
/*
    hFuncInst = LoadLibrary("User32.DLL"); 
	BOOL bRet=FALSE;
	if(hFuncInst) 
		UpdateLayeredWindow=(MYFUNC)GetProcAddress(hFuncInst, "UpdateLayeredWindow");
	else
	{
		AfxMessageBox("User32.dll ERROR!");
		exit(0);
	}
*/
	//初始化gdiplus的环境
	// Initialize GDI+.
	m_Blend.BlendOp=0; //theonlyBlendOpdefinedinWindows2000
	m_Blend.BlendFlags=0; //nothingelseisspecial...
	m_Blend.AlphaFormat=1; //...
	m_Blend.SourceConstantAlpha=255;//AC_SRC_ALPHA


	//CDC *pDC;
	//pDC = GetDC();
	//DrawLed(pDC,m_nLedColor,m_nLedMode,m_nLedShape,"LED");
  }
  return result;
}

void CSwitcherCtrl::DrawSwitcher(int Transparent)
{
	HDC hdcTemp=GetDC()->m_hDC;
	if(Transparent<0||Transparent>100)	Transparent=100;

	m_Blend.SourceConstantAlpha=int(Transparent*2.55);//1~255
	RECT rct;
	GetClientRect(&rct);
	Graphics graph(hdcTemp);//m_hdcMemory);
    ImageFromIDResource(IDR_PNGSWITCHER,"PNG",m_pImageSwitcher);
	if(m_pImageSwitcher)
	{
	 m_SwitchWidth  =m_pImageSwitcher->GetWidth();
	 m_SwitchHeight =m_pImageSwitcher->GetHeight();
	}
	else
		return ;

	m_bSwitcherOn?graph.DrawImage(m_pImageSwitcher,0, 0, 0, 5,m_SwitchWidth/2,m_SwitchHeight-10,UnitPixel):
	graph.DrawImage(m_pImageSwitcher,0, 0, m_SwitchWidth/2, 5,m_SwitchWidth/2,m_SwitchHeight-10,UnitPixel);

	CString strcaption;
    strcaption.Format("%s-%s",m_strCaption,m_bSwitcherOn?"ON":"OFF");
	int   nLen   =   strlen(strcaption)   +   1;   
    int   nwLen   =   MultiByteToWideChar(CP_ACP,   0,   strcaption,   nLen,   NULL,   0);   
    
    unsigned short   lpszTitle[256];

    MultiByteToWideChar(CP_ACP,   0,   strcaption,   nLen,   lpszTitle,   nwLen);   
    FontFamily fontsmallFamily(L"宋体");//选择一种字体
    Gdiplus::Font fontSmall(&fontsmallFamily,12,FontStyleRegular);

	int titlestarty=rct.bottom-20;
	int titlestartx=rct.left;
	if(m_bSwitcherOn)
	{
	graph.DrawString(lpszTitle,-1,&fontSmall,PointF(titlestartx,titlestarty),&SolidBrush(Color::Black)); 
    graph.DrawString(lpszTitle,-1,&fontSmall,PointF(titlestartx-2,titlestarty-2),&SolidBrush(Color::Red)); 
	}
	else
	{

	graph.DrawString(lpszTitle,-1,&fontSmall,PointF(titlestartx,titlestarty),&SolidBrush(Color::Black)); 
    graph.DrawString(lpszTitle,-1,&fontSmall,PointF(titlestartx-2,titlestarty-2),&SolidBrush(Color::White)); 
	}
	delete(m_pImageSwitcher);
	m_pImageSwitcher=NULL;
	::ReleaseDC(m_hWnd,hdcTemp);
	hdcTemp=NULL;

}
/*
BOOL CSwitcherCtrl::ImageFromIDResource(UINT nID, LPCTSTR sTR,Image * &pImg)
{
	HINSTANCE hInst = AfxGetResourceHandle();
	HRSRC hRsrc = ::FindResource (hInst,MAKEINTRESOURCE(nID),sTR); // type
	if (!hRsrc)
		return FALSE;

	// load resource into memory
	DWORD len = SizeofResource(hInst, hRsrc);
	BYTE* lpRsrc = (BYTE*)LoadResource(hInst, hRsrc);
	if (!lpRsrc)
		return FALSE;

	// Allocate global memory on which to create stream
	HGLOBAL m_hMem = GlobalAlloc(GMEM_FIXED, len);
	BYTE* pmem = (BYTE*)GlobalLock(m_hMem);
	memcpy(pmem,lpRsrc,len);
	IStream* pstm;
	CreateStreamOnHGlobal(m_hMem,FALSE,&pstm);
	
	// load from stream
	pImg=Gdiplus::Image::FromStream(pstm);

	// free/release stuff
	GlobalUnlock(m_hMem);
	pstm->Release();
	FreeResource(lpRsrc);
    return TRUE;
}
*/

void CSwitcherCtrl::OnPaint() 
{
	CPaintDC dc(this); // device context for painting
	CRect rect;
	GetClientRect(&rect);
//	dc.FillSolidRect(rect,RGB(129,129,129));
    PaintBK(&dc);
    DrawSwitcher();	
	// Do not call CWnd::OnPaint() for painting messages
}

void CSwitcherCtrl::SetSwitcher(LPCSTR strswitchname, BOOL bOn,int id,HWND hwnd)
{
	m_ParentWnd=hwnd;
    m_strCaption=strswitchname;
    m_bSwitcherOn=bOn;
	//m_SwichterCallBck=CallBck;
	m_ID=id;
}

void CSwitcherCtrl::OnLButtonDown(UINT nFlags, CPoint point) 
{
	m_bSwitcherOn=1-m_bSwitcherOn;
	::SendMessage(m_ParentWnd,WM_DIGOUT_SWITCH,WPARAM(m_ID),LPARAM(m_bSwitcherOn));
    //if(m_SwichterCallBck!=NULL)	
	// m_SwichterCallBck(m_ID,m_bSwitcherOn);	
	//SendMessage(
	Invalidate(FALSE);
	CWnd::OnLButtonDown(nFlags, point);
}

void CSwitcherCtrl::SetBkGnd(CDC *pDC)
{
	CRect rect, rectS;
	CBitmap bmp, *pOldBitmap;

	GetClientRect(rect);
	GetWindowRect(rectS);
	GetParent()->ScreenToClient(rectS);

	m_dcBk.DeleteDC();

	m_dcBk.CreateCompatibleDC(pDC);
	bmp.CreateCompatibleBitmap(pDC, rect.Width(), rect.Height());
	if(bmp.GetSafeHandle()!=NULL)
	{
	pOldBitmap = m_dcBk.SelectObject(&bmp);
	m_dcBk.BitBlt(0, 0, rect.Width(), rect.Height(), pDC, rectS.left, rectS.top, SRCCOPY);
	bmp.DeleteObject();
	}

}

void CSwitcherCtrl::PaintBK(CDC *pDC)
{
	CRect rect;
	GetClientRect(rect);
	pDC->BitBlt(0, 0, rect.Width(), rect.Height(), &m_dcBk, 0, 0, SRCCOPY);

}

 速度表盘

 b1a2833eddd448c6864aa55ba72c02cf.png68250cf416e04238b75b5d7fed670c01.png0b8c1fdffd7148d7b3c4b30df83213d6.png819d546c3edf41c9931f26599e99bc11.png63e27b0b34654cc99b7d923e57a85a3f.png

 

 同上,速度表盘或者压力表盘也可以照此方式实现,将图片作为背景图,然后自绘表指针,根据实时数据计算算出表针的旋转角度,即可实现一组精美的表盘控件。

// DashBoard.cpp : implementation file
//

#include "stdafx.h"
#include "VDC300Controler.h"
#include "DashBoard.h"
#include "Drawfunction.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

/
// CDashBoard

CDashBoard::CDashBoard()
{
	m_DashBoardName=_T("Km/h");
	m_speedvalue=128;
	m_dMinValue = 0.00f;				//表量程初始值
	m_dMaxValue = 140.00f;				//表量程终值
	m_nTicks = 7;						//大格个数
	m_nSubTicks = 5;					//大格中小格个数
}

CDashBoard::~CDashBoard()
{
  	if(m_pDashBoard!=NULL)
	{
	  delete(m_pDashBoard);
	  m_pDashBoard=NULL;
	}
}


BEGIN_MESSAGE_MAP(CDashBoard, CWnd)
	//{{AFX_MSG_MAP(CDashBoard)
	ON_WM_PAINT()
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

/
// CDashBoard message handlers
BOOL CDashBoard::Create(DWORD dwStyle, const RECT& rect, 
                         CWnd* pParentWnd, UINT nID) 
{
	
  BOOL result ;

  static CString className = AfxRegisterWndClass(CS_HREDRAW | CS_VREDRAW) ;

  result = CWnd::CreateEx(NULL, 
                          className, NULL, dwStyle, 
                          rect.left, rect.top, rect.right-rect.left, rect.bottom-rect.top,
                          pParentWnd->GetSafeHwnd(), (HMENU)nID) ;
/*	
  BOOL CreateEx(DWORD dwExStyle, LPCTSTR lpszClassName,
		LPCTSTR lpszWindowName, DWORD dwStyle,
		int x, int y, int nWidth, int nHeight,
		HWND hWndParent, HMENU nIDorHMenu, LPVOID lpParam = NULL);
*/
  if (result != 0)
  {
	ImageFromIDResource(IDR_DASHBOARD,"PNG",m_pDashBoard);
	ImageFromIDResource(IDR_PNGNUM,"PNG",m_pImageNum);
  }
  return result;
}

void CDashBoard::DrawDashBoard()
{
	  CRect rect;

	  HDC hdcTemp=GetDC()->m_hDC; 
      GetClientRect(&rect);
	  Bitmap *m_pBackBmp = ::new Bitmap((HBITMAP)::GetCurrentObject(m_dcBk.m_hDC, OBJ_BITMAP),NULL);

	  Graphics CacheGraphics(m_pBackBmp );    


    int   nLen   =   strlen(m_DashBoardName)   +   1;   
    int   nwLen   =   MultiByteToWideChar(CP_ACP,   0,   m_DashBoardName,   nLen,   NULL,   0);   
    
    unsigned short   lpszTitle[256];  

    MultiByteToWideChar(CP_ACP,   0,   m_DashBoardName,   nLen,   lpszTitle,   nwLen);   
    FontFamily fontsmallFamily(L"宋体");//选择一种字体
    Gdiplus::Font fontSmall(&fontsmallFamily,12,FontStyleRegular);
    LOGFONTA lf;   
	fontSmall.GetLogFontA(&CacheGraphics,&lf);
    int fontsmallWidth=abs(lf.lfHeight);

	int xblank=(rect.Width()-300)/2;
	int yblank=(rect.Height()-300)/2;
	CacheGraphics.DrawImage(m_pDashBoard, Rect(xblank,
		                                       yblank,
											   300,//rect.right-xblank,
											   300));//rect.bottom-yblank));
    
	int midx=rect.Width()/2;
	int midy=rect.Height()/2;
	DrawScale(&CacheGraphics,CRect(xblank,
		                           yblank,
								   256,//rect.right-xblank,
								   256),midx,midy);
	
 	int titlestarty=rect.bottom-yblank-60;//rect.bottom-20;
	int titlestartx=midx-18;	//if(titlestartx<0) titlestartx=0;
	CacheGraphics.DrawString(lpszTitle,-1,&fontSmall,PointF(titlestartx,titlestarty),&SolidBrush(Color::Black)); 
    CacheGraphics.DrawString(lpszTitle,-1,&fontSmall,PointF(titlestartx-1,titlestarty-1),&SolidBrush(Color::White)); 

	int ThirdNum=(((int)m_speedvalue)%10);
	int SecondNum=(((int)m_speedvalue-ThirdNum)%100)/10;
	int FirstNum=(((int)m_speedvalue-SecondNum*10-ThirdNum)%1000)/100;
	int FourthNum=(int(m_speedvalue-FirstNum*100-SecondNum*10-ThirdNum)*10);
	SolidBrush brush1( Gdiplus::Color( 250, 0,0,0 ) ); //半透明红色

    int char_xdis=12;
	int char_width=10;
	int char_height=16;
    int numstartx=midx-2*(char_xdis)-6;
	int recwidth=5*(char_xdis);
	int recheight=char_height+2;
    int numstarty=midy+3*char_height;//(rect.right-rect.left-fontsmallWidth*(nLen-1)/2)/2;	if(titlestartx<0) titlestartx=0;
    CacheGraphics.FillRectangle(&brush1,Gdiplus::Rect(numstartx-2,numstarty-2,recwidth,recheight));

    CacheGraphics.DrawImage(m_pImageNum,Rect(numstartx,numstarty,char_width,char_height), 14*FirstNum, 0,14,23,UnitPixel); //该函数从m_pImageClock中剪切指定rect中的像素draw到指定位置 
    CacheGraphics.DrawImage(m_pImageNum,Rect(numstartx+char_xdis,numstarty,char_width,char_height), 14*SecondNum, 0,14,23,UnitPixel); //该函数从m_pImageClock中剪切指定rect中的像素draw到指定位置 
    CacheGraphics.DrawImage(m_pImageNum,Rect(numstartx+char_xdis*2,numstarty,char_width,char_height), 14*ThirdNum, 0,14,23,UnitPixel); //该函数从m_pImageClock中剪切指定rect中的像素draw到指定位置 
    CacheGraphics.DrawImage(m_pImageNum,Rect(numstartx+char_xdis*3,numstarty,char_width,char_height), 140, 0,14,10,UnitPixel); //该函数从m_pImageClock中剪切指定rect中的像素draw到指定位置 
    CacheGraphics.DrawImage(m_pImageNum,Rect(numstartx+char_xdis*4,numstarty,char_width,char_height), 14*FourthNum, 0,14,23,UnitPixel); //该函数从m_pImageClock中剪切指定rect中的像素draw到指定位置 
 	/*
	CacheGraphics.DrawImage(m_pImageNum,numstartx, numstarty, 14*FirstNum, 0,14,23,UnitPixel); //该函数从m_pImageClock中剪切指定rect中的像素draw到指定位置
	CacheGraphics.DrawImage(m_pImageNum,numstartx+20, numstarty, 14*SecondNum, 0,14,23,UnitPixel); //该函数从m_pImageClock中剪切指定rect中的像素draw到指定位置
	CacheGraphics.DrawImage(m_pImageNum,numstartx+20*2, numstarty, 14*ThirdNum, 0,14,23,UnitPixel); //该函数从m_pImageClock中剪切指定rect中的像素draw到指定位置
	CacheGraphics.DrawImage(m_pImageNum,numstartx+20*3,numstarty+15, 140, 10,14,10,UnitPixel); //该函数从m_pImageClock中剪切指定rect中的像素draw到指定位置
	CacheGraphics.DrawImage(m_pImageNum,numstartx+20*4, numstarty, 14*FourthNum, 0,14,23,UnitPixel); //该函数从m_pImageClock中剪切指定rect中的像素draw到指定位置
    */
	  DrawPitch(&CacheGraphics,CRect(xblank,
		                           yblank,
								   256,//rect.right-xblank,
								   256),
								   midx,midy);
  
	  // 对CacheImage进行描画        // ......                
	  // 获得窗口的Graphics对象        
	Graphics Graphic(hdcTemp);     
	  // 将描画好的CacheImage画到窗口上        
	Graphic.DrawImage(m_pBackBmp, rect.left,rect.top );
  //	CacheImage.DeleteObject();
	::delete(m_pBackBmp);
	m_pBackBmp=NULL;
//	delete(m_pDashBoard);
//	m_pButtonPng=NULL;
	::ReleaseDC(m_hWnd,hdcTemp);
	hdcTemp=NULL;

}
void CDashBoard::SetBkGnd(CDC *pDC)
{
	CRect rect, rectS;
	CBitmap bmp, *pOldBitmap;

	GetClientRect(rect);
	GetWindowRect(rectS);
	GetParent()->ScreenToClient(rectS);

	m_dcBk.DeleteDC();
		//Gdiplus::Bitmap pBitmap(rcBounds.Width(), rcBounds.Height());

	m_dcBk.CreateCompatibleDC(pDC);
	bmp.CreateCompatibleBitmap(pDC, rect.Width(), rect.Height());
	pOldBitmap = m_dcBk.SelectObject(&bmp);
	m_dcBk.BitBlt(0, 0, rect.Width(), rect.Height(), pDC, rectS.left, rectS.top, SRCCOPY);
	bmp.DeleteObject();
    Invalidate(FALSE);
}




void CDashBoard::SetSpeedValue(float fspeed)
{
	if(fspeed>m_dMaxValue) m_speedvalue=m_dMaxValue;
	else   m_speedvalue=fspeed;
   Invalidate(FALSE);
}

void CDashBoard::OnPaint() 
{
	CPaintDC dc(this); // device context for painting
	DrawDashBoard();
}

void CDashBoard::DrawScale(Graphics *pGraph, CRect rect,int midx,int midy)
{
		//画刻度
	int nTicks = m_nTicks;
	int nSubTicks = m_nSubTicks;
	char strFigure[MAXNAMELENGTH + 1];
	const int nSidePos = 40;
	
	int nRadius = 0;
	if (rect.Width() <= rect.Height())
	{
		nRadius = rect.Width();
	}
	else
	{
		nRadius = rect.Height();
	}

	memset(strFigure, 0, sizeof(strFigure));
	double dRadius = fabs(nRadius / 2 - nRadius / 16);
	double dWidth = fabs(nRadius / 14);
	double dMaxAngle = double(300.00f / nTicks);	  //每个大格的角度
	double dMinAngle = dMaxAngle / nSubTicks;         //每个小格的角度 
    int center_x=midx;
	int center_y=midy;
	SolidBrush brush( Gdiplus::Color( 60, 0,0,255 ) ); //半透明红色
    pGraph->SetSmoothingMode(SmoothingModeAntiAlias);//平滑处理 抗锯齿
	for (int i=0; i<nTicks+1; i++) //刻度坐标
	{
		Point ptBigScale[4];//ptStartTick, ptStartTick1 ,ptEndTick,ptEndTick1;
		double dDrawAngle = (i * dMaxAngle + 30) * PI / 180; //
        dDrawAngle-=0.04; 
		ptBigScale[0].X = int(center_x - dRadius * sin(dDrawAngle));
		ptBigScale[0].Y = int(center_y + dRadius * cos(dDrawAngle));
		ptBigScale[1].X = int(center_x - dRadius * sin(dDrawAngle) + dWidth * sin(dDrawAngle));
		ptBigScale[1].Y = int(center_y + dRadius * cos(dDrawAngle) - dWidth * cos(dDrawAngle)); 
	    
		dDrawAngle += 0.08;//(i * dMaxAngle + 30) * PI / 180; //
		ptBigScale[3].X = int(center_x - dRadius * sin(dDrawAngle));
		ptBigScale[3].Y = int(center_y + dRadius * cos(dDrawAngle));
		ptBigScale[2].X = int(center_x - dRadius * sin(dDrawAngle) + dWidth * sin(dDrawAngle));
		ptBigScale[2].Y = int(center_y + dRadius * cos(dDrawAngle) - dWidth * cos(dDrawAngle));

		//pGraph->Polygons()
		pGraph->FillPolygon(&brush, ptBigScale, 4, FillModeAlternate);
		//pGraph->MoveTo(ptStartTick);
		//pGraph->LineTo(ptEndTick);

		sprintf(strFigure, "%.0f", (m_dMaxValue - m_dMinValue) * i / nTicks);
		unsigned short wcharFigure[100];
        unsigned short *pshort=&wcharFigure[0];
		FontFamily fontsmallFamily(L"黑体");//选择一种字体
        Gdiplus::Font fontSmall(&fontsmallFamily,12,FontStyleRegular);
       // LOGFONTA lf;   
 	    //fontSmall.GetLogFontA(&CacheGraphics,&lf);
	    Color fontColor(Color::Black);
		CharToWChar(strFigure, &pshort);
       	//pGraph->DrawString(wcharFigure,-1,&fontSmall,PointF(ptBigScale[0].X-20,ptBigScale[3].Y-5),&SolidBrush(Color::Black)); 

		if (dMaxAngle * (nTicks - i) - 30 < 20)
		{
			pGraph->DrawString(wcharFigure,-1,&fontSmall,PointF(ptBigScale[2].X-30,ptBigScale[2].Y-5),&SolidBrush(fontColor)); 
        }		
		else if (dMaxAngle * (nTicks - i) - 30 < 40)
		{
              pGraph->DrawString(wcharFigure,-1,&fontSmall,PointF(ptBigScale[2].X-30,ptBigScale[1].Y),&SolidBrush(Color::Gray)); 
        }		
		else if (dMaxAngle * (nTicks - i) - 30 < 60)
		{
              pGraph->DrawString(wcharFigure,-1,&fontSmall,PointF(ptBigScale[1].X-26,ptBigScale[1].Y),&SolidBrush(fontColor)); 
     //	pGraph->DrawString(wcharFigure,-1,&fontSmall,PointF(ptBigScale[0].X-20,ptBigScale[3].Y-5),&SolidBrush(Color::Black)); 
       //	pGraph->DrawString(wcharFigure,-1,&fontSmall,PointF(ptBigScale[1].X-nSidePos+1,ptBigScale[1].Y+1),&SolidBrush(Color::Black)); 
         //   pGraph->DrawString(lpszTitle,-1,&fontSmall,ptBigScale[1],&SolidBrush(Color::White)); 
		//	pGraph->DrawString(ptEndTick.x - nSidePos + 1, ptEndTick.y + 1, strFigure);
		//	pGraph->SetTextColor(RGB(0, 0, 255));
		//	pGraph->TextOut(ptEndTick.x - nSidePos, ptEndTick.y, strFigure);
		}
		else if (dMaxAngle * (nTicks - i) - 30 <= 90)
		{
                pGraph->DrawString(wcharFigure,-1,&fontSmall,PointF(ptBigScale[1].X-25,ptBigScale[2].Y-3),&SolidBrush(fontColor)); 

			//	pGraph->DrawString(wcharFigure,-1,&fontSmall,PointF(ptBigScale[1].X-nSidePos+1,ptBigScale[1].Y+1),&SolidBrush(Color::DarkGray)); 

			//	pGraph->SetTextColor(RGB(255, 255, 255));
		//	pGraph->TextOut(ptEndTick.x - nSidePos / 2 + 1, ptEndTick.y + 3 + 1, strFigure);
		//	pGraph->SetTextColor(RGB(0, 0, 255));
		//	pGraph->TextOut(ptEndTick.x - nSidePos / 2, ptEndTick.y + 3, strFigure);
		}
		else if (dMaxAngle * (nTicks - i) - 30 < 140)
		{
           pGraph->DrawString(wcharFigure,-1,&fontSmall,PointF(ptBigScale[0].X-5,ptBigScale[1].Y),&SolidBrush(fontColor)); 
       //	pGraph->DrawString(wcharFigure,-1,&fontSmall,PointF(ptBigScale[1].X-nSidePos+1,ptBigScale[1].Y+1),&SolidBrush(Color::Black)); 
		//	pGraph->SetTextColor(RGB(255, 255, 255));
		//	pGraph->TextOut(ptEndTick.x - nSidePos / 3 + 1, ptEndTick.y + 1, strFigure);
		//	pGraph->SetTextColor(RGB(0, 0, 255));
		//	pGraph->TextOut(ptEndTick.x - nSidePos / 3, ptEndTick.y, strFigure);
		}
		else if (dMaxAngle * (nTicks - i) - 30 < 160)
		{
           pGraph->DrawString(wcharFigure,-1,&fontSmall,PointF(ptBigScale[1].X,ptBigScale[1].Y-3),&SolidBrush(fontColor)); 
       //	pGraph->DrawString(wcharFigure,-1,&fontSmall,PointF(ptBigScale[1].X-nSidePos+1,ptBigScale[1].Y+1),&SolidBrush(Color::Black)); 
		//	pGraph->SetTextColor(RGB(255, 255, 255));
		//	pGraph->TextOut(ptEndTick.x - nSidePos / 3 + 1, ptEndTick.y + 1, strFigure);
		//	pGraph->SetTextColor(RGB(0, 0, 255));
		//	pGraph->TextOut(ptEndTick.x - nSidePos / 3, ptEndTick.y, strFigure);
		}
		else
		{
            pGraph->DrawString(wcharFigure,-1,&fontSmall,PointF(ptBigScale[1].X-1,ptBigScale[2].Y-5),&SolidBrush(fontColor)); 

			//	pGraph->DrawString(wcharFigure,-1,&fontSmall,PointF(ptBigScale[1].X-nSidePos+1,ptBigScale[1].Y+5),&SolidBrush(Color::Black)); 
		//	pGraph->SetTextColor(RGB(255, 255, 255));
		//	pGraph->TextOut(ptEndTick.x - nSidePos / 10 + 1, ptEndTick.y + 1, strFigure);
		//	pGraph->SetTextColor(RGB(0, 0, 255));
		//	pGraph->TextOut(ptEndTick.x - nSidePos / 10, ptEndTick.y, strFigure);
		}
		
	}

	dWidth = fabs(nRadius / 20);

	Pen myPen(Color(126, 0, 0, 255), 2);
	for (i=0; i<nTicks; i++)
	{
		for (int j=1; j<nSubTicks; j++)  //子刻度
		{
			Point ptSubStartTick, ptSubEndTick;
			double dDrawAngle = ((i * dMaxAngle + 30) + (j * dMinAngle)) * PI / 180;
			ptSubStartTick.X = int(center_x - dRadius * sin(dDrawAngle));
			ptSubStartTick.Y = int(center_y + dRadius * cos(dDrawAngle));
			ptSubEndTick.X = int(center_x - dRadius * sin(dDrawAngle) + dWidth * sin(dDrawAngle));
			ptSubEndTick.Y = int(center_y + dRadius * cos(dDrawAngle) - dWidth * cos(dDrawAngle)); 
			pGraph->DrawLine(&myPen,ptSubStartTick,ptSubEndTick);
			
		}
	}
	int nradius=86;
	int rang=16;
	int startspeed=40;
	int endspeed=80;
    int nmode=0;
	Rect rt(center_x-nradius,center_y-nradius,nradius*2,nradius*2);
	DrawRangArc(pGraph, center_x,center_y,rt, nradius,rang,startspeed,endspeed,nmode);

	nradius=86;
	rang=16;
	startspeed=100;
	endspeed=140;
    nmode=1;
	Rect rt1(center_x-nradius,center_y-nradius,nradius*2,nradius*2);
	DrawRangArc(pGraph, center_x,center_y,rt1, nradius,rang,startspeed,endspeed,nmode);

	nradius=70;
	rang=16;
	startspeed=60;
	endspeed=130;
    nmode=2;
	Rect rt2(center_x-nradius,center_y-nradius,nradius*2,nradius*2);
	DrawRangArc(pGraph, center_x,center_y,rt2, nradius,rang,startspeed,endspeed,nmode);
}

BOOL CDashBoard::CharToWChar(LPCSTR strChar, unsigned short **sWchar)
{
    int   nLen   =   strlen(strChar)   +   1;   
    int   nwLen   =   MultiByteToWideChar(CP_ACP,   0,   strChar,   nLen,   NULL,   0);   
    
    MultiByteToWideChar(CP_ACP,   0,  strChar,   nLen,   *sWchar,   nwLen);   
	return TRUE;

}

//#define FACTOR        1
#define FACTOR        1
/*
 Point _aNeedleSrc[5][5] = {
  {
    Point(FACTOR *  0, FACTOR *  -5),
    Point(FACTOR * -5, FACTOR *  25),
    Point(FACTOR *  0, FACTOR * 100),
    Point(FACTOR *  5, FACTOR *  25)
  },{
    Point(FACTOR * -4, FACTOR *   0),
    Point(FACTOR * -3, FACTOR *  60),
    Point(FACTOR *  0, FACTOR * 1000),
    Point(FACTOR *  3, FACTOR *  60),
    Point(FACTOR *  4, FACTOR *   0)
  },{
    Point(FACTOR * -3, FACTOR * -13),
    Point(FACTOR * -3, FACTOR *  60),
    Point(FACTOR *  0, FACTOR * 100),
    Point(FACTOR *  3, FACTOR *  60),
    Point(FACTOR *  3, FACTOR * -13)
  },{
    Point(FACTOR * -5, FACTOR * -13),
    Point(FACTOR * -4, FACTOR *  20),
    Point(FACTOR *  0, FACTOR * 100),
    Point(FACTOR *  4, FACTOR *  20),
    Point(FACTOR *  5, FACTOR * -13)
  },{
    Point(FACTOR * -5, FACTOR * -13),
    Point(FACTOR * -4, FACTOR *  65),
    Point(FACTOR *  0, FACTOR * 100),
    Point(FACTOR *  4, FACTOR *  65),
    Point(FACTOR *  5, FACTOR * -13)
  }
};
*/
/*
static void _DrawLine(const SCALE* pObj, int r1, int r2, float Angel) {
  float co = cos(Angel / 180.) * FACTOR;
  float si = sin(Angel / 180.) * FACTOR;
  int x0 = pObj->x0 * FACTOR - r1 * co;
  int y0 = pObj->y0 * FACTOR - r1 * si;
  int x1 = pObj->x0 * FACTOR - r2 * co;
  int y1 = pObj->y0 * FACTOR - r2 * si;
  GUI_AA_DrawLine(x0, y0, x1, y1);
}
*/
void CDashBoard::DrawPitch(Graphics *pGraph,CRect rect,int OxyX,int OxyY)
{
	//Pen pen(ARGB(0xFFFF4500),1);
	Pen      pen(Color(255, 255, 255, 255));
	double Angle_PerKm=(double)(300.00f / (m_dMaxValue - m_dMinValue));
	double Angel = (Angle_PerKm*m_speedvalue+30);//* PI / 180;
	double dDrawAngle = (Angel ) * PI / 180; //
	Matrix matrixH(1,0,0,1,OxyX,OxyY); // 定义一个单位矩阵,坐标原点在表盘中央
	matrixH.Rotate(Angel); // 时针旋转的角度度
//	matrixH.Translate(-OxyX,-OxyY);

	Point pointsH[]={    
	Point(FACTOR *  0, FACTOR *  -15),
    Point(FACTOR * -15, FACTOR *  30),
    Point(FACTOR *  0, FACTOR * 100),
    Point(FACTOR *  15, FACTOR *  30)
	};
    Point pointsH1[]={
			Point(FACTOR *  0, FACTOR *  -5),
    		Point(FACTOR * -5, FACTOR *  25),
            Point(FACTOR *  0, FACTOR * 100),
            Point(FACTOR *  5, FACTOR *  25)
	};
    Point pointsH2[]={
    Point(FACTOR * -3, FACTOR * -13),
    Point(FACTOR * -3, FACTOR *  60),
    Point(FACTOR *  0, FACTOR * 100),
    Point(FACTOR *  3, FACTOR *  60),
    Point(FACTOR *  3, FACTOR * -13)
	};
    Point pointsH3[]={
	Point(FACTOR * -5, FACTOR * -13),
    Point(FACTOR * -4, FACTOR *  20),
    Point(FACTOR *  0, FACTOR * 100),
    Point(FACTOR *  4, FACTOR *  20),
    Point(FACTOR *  5, FACTOR * -13)
	};
    Point pointsH4[]={
    Point(FACTOR * -5, FACTOR * -13),
    Point(FACTOR * -4, FACTOR *  65),
    Point(FACTOR *  0, FACTOR * 100),
    Point(FACTOR *  4, FACTOR *  65),
    Point(FACTOR *  5, FACTOR * -13)
	};
    //Point *pPoint=_aNeedleSrc[0];
	matrixH.TransformPoints( pointsH, 4); // 用该矩阵转换points
	SolidBrush brush( Gdiplus::Color( 126, 255,0,0 ) ); //半透明红色
    pGraph->SetSmoothingMode(SmoothingModeAntiAlias);//平滑处理 抗锯齿

     //  取得第一种颜色的R,G,B值
	COLORREF Color2=RGB(0,45,145);
    COLORREF Color1=RGB(255,255,255);

    int r1 = GetRValue(Color1);
    int g1 = GetGValue(Color1);
    int b1 = GetBValue(Color1);

    //  取得第二种颜色的R,G,B值
    int r2 = GetRValue(Color2);
    int g2 = GetGValue(Color2);
    int b2 = GetBValue(Color2);

//    CRect rect;
//    GetClientRect(&rect);

	int iRotation=180;
        
    //  刷子
      Gdiplus::LinearGradientBrush linGrBrush(Gdiplus::Rect(0, 0, rect.right,rect.bottom),  //  绘制区域
                                                Gdiplus::Color(255, r1, g1, b1),  //  第一种颜色
                                                Gdiplus::Color(255, r2, g2, b2),  //  第二种颜色 
                                                (Gdiplus::REAL)(90 - iRotation));  //  渐变色的角度


	//SolidBrush brush1( Gdiplus::Color(126,0,0,255) ); //半透明红色
	pGraph->FillPolygon(&brush, pointsH, 4,FillModeAlternate);
	//pGraph->FillPolygon(&brush, pointsH, 4,FillModeAlternate);
	pGraph->DrawPolygon(&pen, pointsH, 4);
    int nRadius = 0;
	if (rect.Width() <= rect.Height())
	{
		nRadius = rect.Width();
	}
	else
	{
		nRadius = rect.Height();
	}

	double dRadius = fabs(nRadius / 2 - nRadius / 16);
	int endx = int(OxyX - dRadius * sin(dDrawAngle));
	int endy = int(OxyY + dRadius * cos(dDrawAngle)); 
    pGraph->DrawLine(&pen,OxyX,OxyY,endx,endy);
    //  得到绘制区域
	pGraph->FillEllipse(&linGrBrush,OxyX-10,OxyY-10,20,20);
//	pGraph->FillCircle(&brush1,OxyX,OxyY,5);
   // fla=(260-0)*m_speedvalue;//(范围最大值-范围最小值)*数据百分比+范围最小值
    //CacheGraphics.DrawLine(&pen, midx, midy, midx + (int) (100 * cos(fla * radian)), 
    //midy + (INT) (100 * sin(fla * radian)));
   // CacheGraphics.FillEllipse(&brush,midx-20,midy-20,20,20);
   
/*
	Matrix matrixH(1,0,0,1,OxyX,OxyY); // 定义一个单位矩阵,坐标原点在表盘中央
	matrixH.Rotate(SystemTime.wHour*30+SystemTime.wMinute/2.0-180); // 时针旋转的角度度
	Point pointsH[] = { Point(0, 0),Point(m_HourWidth, 0),Point(0, m_HourHeight)};
	matrixH.Translate(-m_HourWidth/2,-m_HourHeight/6);
	matrixH.TransformPoints( pointsH, 3); // 用该矩阵转换points
	graph.DrawImage (m_pImageHHour,pointsH, 3);

*/

}

void CDashBoard::DrawRangArc(Graphics *pGraph, int OxyX,int OxyY,Rect rect,int nRadius,int nRang, float startspeed, float endspeed, int nRangMode)
{

	//120---0  140--60       300
	int arc_startx=startspeed*(300/(m_dMaxValue - m_dMinValue))+120;
	if(arc_startx>360) arc_startx-=360;
	int arc_starty=(endspeed-startspeed)*(300/(m_dMaxValue - m_dMinValue));
	if(arc_starty>360) arc_starty-=360;
	
	double Angle_PerKm=(double)(300.00f / (m_dMaxValue - m_dMinValue));
	double Angel = (Angle_PerKm*startspeed+30);//* PI / 180;
	double dDrawAngle = (Angel ) * PI / 180; //


	int startx = int(OxyX - (nRadius+nRang/2) * sin(dDrawAngle));
	int starty = int(OxyY + (nRadius+nRang/2) * cos(dDrawAngle));
	int endx = int(OxyX - (nRadius+nRang/2) * sin(dDrawAngle) + nRang * sin(dDrawAngle));
	int endy = int(OxyY + (nRadius+nRang/2) * cos(dDrawAngle) - nRang * cos(dDrawAngle));
	
	double Angel1 = (Angle_PerKm*endspeed+30);
	double dDrawAngle1 = (Angel1-0.4) * PI / 180; //

	int startx1 = int(OxyX - (nRadius+nRang/2) * sin(dDrawAngle1));
	int starty1 = int(OxyY + (nRadius+nRang/2) * cos(dDrawAngle1));
	int endx1 = int(OxyX - (nRadius+nRang/2) * sin(dDrawAngle1) + nRang * sin(dDrawAngle1));
	int endy1 = int(OxyY + (nRadius+nRang/2) * cos(dDrawAngle1) - nRang * cos(dDrawAngle1));

	switch(nRangMode)
	{
	case 0:
	{
	int nradius=nRadius;
	Pen pen1(Color(255, 0, 255, 0), 1);
	pGraph->DrawArc(&pen1,Rect(rect.X+nRang/2,rect.Y+nRang/2,nRadius*2-nRang,nRadius*2-nRang),arc_startx+0.5,arc_starty-0.4);
	pGraph->DrawArc(&pen1,Rect(rect.X-nRang/2,rect.Y-nRang/2,nRadius*2+nRang,nRadius*2+nRang),arc_startx+0.5,arc_starty-0.4);
	pGraph->DrawLine(&pen1,startx,starty,endx,endy);
	pGraph->DrawLine(&pen1,startx1,starty1,endx1,endy1);

	Pen pen(Color(100, 0, 255, 0), nRang);
	pGraph->DrawArc(&pen,rect,arc_startx,arc_starty);
	}
    break;

	case 1:
	{
	int nradius=nRadius;
	Pen pen1(Color(255, 255, 0, 0), 1);
	pGraph->DrawArc(&pen1,Rect(rect.X+nRang/2,rect.Y+nRang/2,nRadius*2-nRang,nRadius*2-nRang),arc_startx+0.5,arc_starty-0.4);
	pGraph->DrawArc(&pen1,Rect(rect.X-nRang/2,rect.Y-nRang/2,nRadius*2+nRang,nRadius*2+nRang),arc_startx+0.5,arc_starty-0.4);
	pGraph->DrawLine(&pen1,startx,starty,endx,endy);
	pGraph->DrawLine(&pen1,startx1,starty1,endx1,endy1);

	Pen pen(Color(100, 255, 0, 0), nRang);
	pGraph->DrawArc(&pen,rect,arc_startx,arc_starty);
	}
    break;
    case 2:
 	{
	int nradius=nRadius;
	Pen pen1(Color(255, 255, 255, 0), 1);
	pGraph->DrawArc(&pen1,Rect(rect.X+nRang/2,rect.Y+nRang/2,nRadius*2-nRang,nRadius*2-nRang),arc_startx+0.5,arc_starty-0.4);
	pGraph->DrawArc(&pen1,Rect(rect.X-nRang/2,rect.Y-nRang/2,nRadius*2+nRang,nRadius*2+nRang),arc_startx+0.5,arc_starty-0.4);
	pGraph->DrawLine(&pen1,startx,starty,endx,endy);
	pGraph->DrawLine(&pen1,startx1,starty1,endx1,endy1);

	Pen pen(Color(126, 255, 255, 0), nRang);
	pGraph->DrawArc(&pen,rect,arc_startx,arc_starty);
	}
    break;

	}


}

 工业风的界面随着计算机软件计算的发展逐渐衍生出了现在风靡业界的数字孪生应用,也从二维的变成3维实时仿真的UI,大大的增强了数字化虚拟世界的表达现实世界的能力

 

 

 

 

 

 

 

 

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/737262.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

自定义切换整行上下位置快捷键

自定义切换整行上下位置快捷键 在File菜单中选择Settings选项&#xff0c;搜索move li 先删掉原来的快捷键 再添加你要设置的快捷键 确认就可以了。

word转Markdown文件的几个方法

word转Markdown文件的几个方法 1、 安装writage 软件&#xff0c;但是writage 需要收费了。 如果只是markdown文本编辑&#xff0c;可以直接安装typora来。 2. 利用Pandoc软件来转换word文件到markdown文件 注意doc文件需要保存docx文件格式才可以使用下面命令行 pandoc &q…

C++多线程学习(十六、STL算法中的并行版本,sequenced_policy)

目录 sequenced_policy 使用代码&#xff1a; 准备 代码 结果&#xff1a; sequenced_policy 增加参数:sequenced_policy提供相应并行版算法 execution::seq并行算法执行可以不并行化execution::par并行算法执行可以并行化execution::par_unseq并行算法执行的可以并行以…

C#基础学习_泛型集合List<T>

C#基础学习_泛型集合List 为什么要使用集合? 数组元素个数是固定的,数组一旦定义,就无法改变元素总数。如果需求变化,则必须修改源码。 如果初始化元素总数非常大,则会造成浪费。 集合的特点: 根据需要动态增加元素个数,没有限制 List泛型集合的存储结构,与数组类似,…

Ceres-Solver 官方文档

Ceres-Solver 官方文档 Non-linear Least Squares1. Introduction2. Hello World!3. Derivatives3.1 Numeric Derivatives3.2 Analytic Derivatives3.3 More About Derivatives 4. Powell’s Function5. Curve Fitting6. Robust Curve Fitting7. Bundle Adjustment8. Other Exa…

hive on spark小文件问题【hive.merge.sparkfiles参数不生效】

hive on spark小文件问题【hive.merge.sparkfiles参数不生效】 我也是查看了我们目前集群的版本是spark是3.2.3版本 hive是3.1.3版本&#xff0c;都是比较新的版本&#xff0c;正常是支持这个参数的 在测试环境中&#xff0c;如果在sql中不使用group by函数其实可以可以生效的…

响应式编程实战(08)-WebFlux,使用注解编程模式构建异步非阻塞服务

1 引言 明确了 Spring 家族中 WebFlux 组件诞生的背景和意义。作为一款新型的 Web 服务开发组件&#xff1a; 充分考虑了与原有 Spring MVC 在开发模式上的兼容性&#xff0c;开发人员仍然可以使用基于注解的编程方式来创建响应式 Web 服务WebFlux 也引入了基于函数式编程的全…

Linux下有名管道mkfifo使用

Linux下实现进程通信的方式有很多种&#xff0c;今天要说的是有名管道&#xff0c;有名管道比命名管道的优势是可以在任何进程之间传递数据。有名管道通信是依赖于管道文件这种特殊类型文件来进行的。 目录 1.mkfifo命令 2.mkfifo库函数 1.mkfifo命令 mkfifo命令可以创建管…

HuilderX 运行到 MUMU模拟器

1.网易官网下载MuMu模拟器&#xff0c;一定要打开MuMu模拟器&#xff1b; MuMu模拟器官方下载https://mumu.163.com/ 2.到MUMU模拟器的安装目录&#xff0c;找到adb.exe在的目录下&#xff0c;复制其路径&#xff1b; 举例 &#xff1a;D:/Program Files/MuMuPlayer-12.0/sh…

CSPM(项目管理专业人员能力评价)和软考有什么区别?

一、国标项目管理&#xff08;项目管理专业人员能力评级&#xff09;证书是什么&#xff1f; 《项目管理专业人员能力评价要求》&#xff08;GB/T 41831-2022&#xff09;是2022年10月12日开始实施的一项中国国家标准&#xff0c;归口于全国项目管理标准化技术委员会。 《项目…

一种环肽52661-98-0,cyclo(Gly-Ser),环(甘氨酰-L-丝氨酰),氨基酸中间体

资料编辑|陕西新研博美生物科技有限公司小编MISSwu cyclo(Gly-Ser)&#xff08;CAS号&#xff1a;52661-98-0&#xff09;一种环肽&#xff0c;一般作为氨基酸中间体&#xff0c;含有甘氨酰和丝氨酰&#xff0c;Ser Serine 丝氨酸&#xff0c;也称β羟基丙氨酸&#xff0c;丝氨…

促进协作、提高生产力:育碧选择Perforce Helix Core的原因

Perforce Helix Core成为育碧&#xff08;Ubisoft&#xff09;的主要源代码控制工具已经超过六年了&#xff0c;被团队中的程序员和美术人员在大部分项目中使用。在育碧蒙特利尔工作室&#xff0c;有超过1,200名的开发人员使用Perforce Helix Core来储存源代码和数字资产&#…

Appium xpath定位

xpath应该是最准确的定位方式&#xff0c;不管你有没有id、class或者其他的元素&#xff0c;uiautomator总是可以识别出xpath&#xff0c;因为手机APP的控件布局类似于HTML的树形结构。 如右图所示 xpath很长&#xff0c;显然不可能人手动来对其进行编写&#xff0c;最好的就是…

算法竞赛备赛之经典基础算法训练提升,暑期集训营培训

目录 1.排序 1.1.快速排序 1.2.归并排序 2.二分 2.1.整数 2.2.浮点数 3.高精度 3.1.高精度加法 3.2.高精度减法 3.3.高精度乘法 3.4.高精度除法 4.前缀和 5.差分 6.双指针算法 7.位运算 8.离散化 8.1.unique函数实现 9.区间合并 1.排序 1.1.快速排序 快速排…

vue 运行时正常,打包却报错

解决方法&#xff1a;删除vue-cli 自带的压缩 plugin&#xff1a;OptimizeCssnanoPlugin 具体操作&#xff1a;找到vue.config.再添加如下删除配置

万万没想到!!号称国内Java八股文天花板(典藏版)首次开源

应届毕业生的第一份工作干多久跳槽比较合适&#xff1f; 都说现在应届毕业生找工作跳槽频繁&#xff0c;而所有用人单位都希望招揽的人才能一直在公司里干下去&#xff0c;但是人各有志&#xff0c;作为劳动者的应届毕业生有自主选择职业的权利&#xff0c;这就造成很多应届生…

今天分享:智能ai绘画软件哪个好

在一个遥远的未来&#xff0c;艺术界经历了一场革命性的变革。艺术家们不再依赖传统的画笔和颜料&#xff0c;而是转向了ai绘画工具&#xff0c;这是一种集人工智能和创造力于一身的技术。在这个世界中&#xff0c;我有幸遇到了一个与众不同的艺术家&#xff0c;他的名字叫亚历…

Hubspot为什么这么牛?国内有哪些类似软件

国外CRM圈内&#xff0c;除了大佬Salesforce外&#xff0c;还有HubSpot、Oracle、SAP等知名CRM公司。其中&#xff0c;HubSpot在国外2023年最佳CRM软件排行榜中名列第四&#xff0c;在最佳免费CRM软件排行榜中名列第二&#xff0c;我们先来看下它到底有多优秀&#xff0c;然后再…

Deffie-Hellman 算法

Deffie-Hellman 算法简介 Deffie-Hellman(简称 DH) 密钥交换是最早的密钥交换算法之一&#xff0c;它使得通信的双方能在非安全的信道中安全的交换密钥&#xff0c;用于加密后续的通信消息。 Whitfield Diffie 和 Martin Hellman 于 1976 提出该算法&#xff0c;之后被应用于安…

指令周期的数据流

5.2 指令周期的数据流 指令周期 机器周期/CPU周期 CPU时钟周期/节拍 取指周期 间址周期 执行周期 中断周期 标志触发器FE IND EX INT 数据流 取指周期 根据PC中的内容取出指令代码并存放在IR中 间址周…