C++/Win32实现波浪球效果及详细源码

C++/Win32波浪球效果

简介

这是一个基于C++在win32上实现的波浪球效果。它使用GDI+进行图形绘制,支持指定签名、动态百分比显示以及特殊项目的PASS/FAIL显示。

对其封装成了一个类,并开放了相关参数给用户设置,可以灵活使用。

项目github地址在这里,如果对你有帮助帮忙点个star哟。

部分效果图小如下:
wave_ball_show

原理

  1. 利用GDI+在内存DC上创建 一个画布,并填充背景颜色。
  2. 使用Pen在画布上画一个外层圆。
  3. 依靠公式 “振幅高sin(x振幅宽 + 振幅偏移量)”画出波浪。
  4. 使用DrawString画上署名或百分比进度。
  5. 使用DrawImage将内存DC输出到Dialog。

这里利用双缓存原理消除闪屏问题。双缓冲实现过程如下:

  1. 在内存中创建与画布一致的缓冲区。
  2. 在缓冲区画图。
  3. 将缓冲区位图拷贝到当前画布上。
  4. 释放内存缓冲区。

功能

没有添加构造函数和析构函数,后面会再做一次优化。

  1. WaveBallInit 初始化波浪球。
  2. ThreadDynamicWave 动态更新波浪,一般在一个线程或定时器中实时更新。
  3. WaveBallUpdateProgress 更新百分比显示和进度条,进度条会根据百分比进行自适应。
  4. WaveBallSetConstantWave 设置恒定进度状态,比如设为30%,则波浪一直在该状态下波动。
  5. WaveBallSetTextColor 允许设置波浪球中的文本颜色。
  6. WaveBallSetColor 允许设置波浪球的背景颜色。
  7. WaveBallSetText 设置波浪球的文本。
  8. WaveBallSetResult 设置PASS / FAIL 状态,应用一些特殊需要,比如进度达到100%后的状态显示。
  9. WaveBallSetAmplitude设置波浪球的波浪参数,根据不同的尺寸大小调整波浪。

源码

GdiplusWaveBall.cpp

#include "GdiplusWaveBall.h"
#include <process.h>
#include <strsafe.h>

/*****************************************************************************
*
* GET VALUE POINT: CreateOriginalBmp
*
*****************************************************************************/
Bitmap* FlyWaveBall::CreateOriginalBmp()
{
	HDC			hdc;
	REAL		nWidth, nHeight;
	Graphics	*baseGraph;
	Bitmap		*bmp;
	Graphics	*pGraphics;
	Pen			*myPen;
	SolidBrush	*blackBrush;
	REAL		strSize;
	INT			iStrLength;

	nHeight = 2 * (threadWavesMove.radius + 1);
	nWidth = 2 * (threadWavesMove.radius + 1);
	Gdiplus::RectF gdiRc(threadWavesMove.originalX,
		threadWavesMove.originalY,
		nWidth,
		nHeight);

	hdc = GetDC(threadWavesMove.hWnd);
	baseGraph = new Gdiplus::Graphics(hdc);
	bmp = new Bitmap((int)nWidth, (int)nHeight);
	for (int i = 0; i < nWidth; i++)
	{
		for (int j = 0; j < nHeight; j++)
		{
			bmp->SetPixel(i, j, threadWavesMove.colorOriginal);
		}
	}
	pGraphics = Graphics::FromImage(bmp);

	pGraphics->SetSmoothingMode(SmoothingModeHighQuality);
	myPen = new Pen(threadWavesMove.colorWaveBall, 1);
	pGraphics->DrawEllipse(myPen, 0.0f, 0.0f, 2 * threadWavesMove.radius, 2 * threadWavesMove.radius);
	strSize = 2 * threadWavesMove.radius / 5;
	//WaveBallSetText(threadWavesMove.hWnd, threadWavesMove.colorWaveBall, AUTOGRAPH, lstrlen(AUTOGRAPH), (REAL)2 * threadWavesMove.radius / 5);
	Font myFont(TEXT("Arial"), strSize);
	iStrLength = lstrlen(AUTOGRAPH);
	blackBrush = new SolidBrush(threadWavesMove.colorWaveBall);
	pGraphics->DrawString(AUTOGRAPH, iStrLength, &myFont,
		PointF(threadWavesMove.radius - (strSize / 3)*iStrLength - 7,
			threadWavesMove.radius - 2 * strSize / 3),
		blackBrush);

	baseGraph->DrawImage(bmp, gdiRc, 0.0f, 0.0f, nWidth, nHeight, UnitPixel);

	delete(myPen);
	delete(blackBrush);
	delete(pGraphics);
	delete(baseGraph);
	DeleteDC(hdc);

	return bmp;
}
/*****************************************************************************
*
* GET VALUE POINT: WaveBallInit
*
* Function: Initialize wave ball
*
*****************************************************************************/
VOID FlyWaveBall::WaveBallInit(
	IN HWND hWnd,
	IN Gdiplus::Color &color,
	IN Gdiplus::Color &colorOriginal,
	IN REAL x,
	IN REAL y,
	IN REAL radius)
{
	memset(&threadWavesMove, 0, sizeof(ThreadParam));
	threadWavesMove.bConstantWave = FALSE;
	threadWavesMove.hWnd = hWnd;
	threadWavesMove.originalX = x;
	threadWavesMove.originalY = y;
	threadWavesMove.colorWaveBall = color;
	threadWavesMove.colorOriginal = colorOriginal;
	threadWavesMove.colorText = Color(255, 255, 235, 205);
	threadWavesMove.percentage = 0;
	threadWavesMove.radius = radius;

	amplitudeHigh = 1.0;
	amplitudeWidth = 0.08f;
	amplitudeOffset = 6.0;

	bResult = TRUE;
	lstrcpyn(strText, AUTOGRAPH, sizeof(strText) / sizeof(strText[0]));

	//bmpOriginal = CreateOriginalBmp();

}
/*****************************************************************************
*
* GET VALUE POINT: ThreadDynamicWave
*
* Function: Make the waves move
*
*****************************************************************************/
VOID FlyWaveBall::ThreadDynamicWave(int	offset)
{
	if (threadWavesMove.percentage <= 0)
	{
		WaveBallRedrawCircle();
		return;
	}
	else if (threadWavesMove.percentage >= 1)
	{
		ShowResult();
		return;
	}

	HDC			hdc;
	REAL		nWidth, nHeight;
	Graphics	*baseGraph;
	Bitmap		*bmp;
	Graphics	*pGraphics;
	Pen			*myPen;
	SolidBrush	*blackBrush;
	REAL		strSize;
	/***********************/
	float			sX, sY;			// start X/Y
	float			x, y;
	int				count;
	//int				offset;
	float			iCircularInterval = 3;
	PointF			points[MAX_POINT];
	Brush			*brush;
	Brush			*brushOriginal;
	float			centerX, centerY;
	TCHAR			strText[128];

	nHeight = 2 * (threadWavesMove.radius + 1);
	nWidth = 2 * (threadWavesMove.radius + 1);
	Gdiplus::RectF gdiRc(threadWavesMove.originalX,
		threadWavesMove.originalY,
		nWidth,
		nHeight);
	bmp = new Bitmap((int)nWidth, (int)nHeight);
	pGraphics = Graphics::FromImage(bmp);
	pGraphics->SetSmoothingMode(SmoothingModeHighQuality);
	hdc = GetDC(threadWavesMove.hWnd);
	baseGraph = new Gdiplus::Graphics(hdc);

	// 初始化画布
	for (int i = 0; i < nWidth; i++)
	{
		for (int j = 0; j < nHeight; j++)
		{
			bmp->SetPixel(i, j, threadWavesMove.colorOriginal);
		}
	}

	strSize = 2 * threadWavesMove.radius / 5;
	Font myFont(TEXT("Arial"), strSize);
	blackBrush = new SolidBrush(threadWavesMove.colorText);
	myPen = new Pen(threadWavesMove.colorWaveBall, 1);

	sX = 0.0f;
	centerX = threadWavesMove.radius;
	centerY = threadWavesMove.radius;
	brush = new SolidBrush(threadWavesMove.colorWaveBall);
	brushOriginal = new SolidBrush(threadWavesMove.colorOriginal);
	//offset = 0;

	sY = 2 * threadWavesMove.radius*(1 - threadWavesMove.percentage);
	count = 0;
	for (x = sX; x < (int)sX + MAX_POINT; x += 1.0f) 
	{
		//此处坐标(x,y)的取点,依靠公式 “振幅高*sin(x*振幅宽 + 振幅偏移量)”

		// The point of coordinates (x, y) here depends on the formula 
		// "amplitude height * sin (x * amplitude width+amplitude offset)"
		if (threadWavesMove.percentage < 0.1)
			y = threadWavesMove.percentage*(float)sin((sX + x) * 0.08 - offset*PI / 6);
		else if (threadWavesMove.percentage > 0.9)
			y = (float)(fabs(threadWavesMove.percentage - 1)*sin((sX + x) * 0.08 - offset*PI / 6));
		else
			y = amplitudeHigh*(float)sin((sX + x) * amplitudeWidth - offset*PI / amplitudeOffset);// 4,0.02,6
		

		//TIS_Trace(TEXT("x,y:%f,%f\n"), x, sY + y * 5);
		if (IsPointInCircle(x, sY + y * 5, centerX, centerY, threadWavesMove.radius - iCircularInterval))
		{
			points[count] = Gdiplus::PointF(x, (sY + y * 5));
			count++;
		}
		if (count >= MAX_POINT || x > (centerX + threadWavesMove.radius))
			break;
	}

	// 绘制圆形
	pGraphics->DrawEllipse(myPen, 0.0f, 0.0f, 2 * threadWavesMove.radius, 2 * threadWavesMove.radius);

	if (threadWavesMove.percentage > 0.95f)
	{
		pGraphics->FillEllipse(brush,
			iCircularInterval,//x
			iCircularInterval,//y
			2 * (threadWavesMove.radius - iCircularInterval),
			2 * (threadWavesMove.radius - iCircularInterval));

	}
	else if (count > 0)
	{
		double startAngle = (atan((points[count - 1].Y - centerY) / (points[count - 1].X - centerX)) * 180 / PI);
		double endAngle = 180 + (atan((points[1].Y - centerY) / (points[1].X - centerX)) * 180 / PI);
		//TIS_Trace(TEXT("Angle:%d,%d\n"), startAngle, endAngle);
		for (; startAngle<endAngle; startAngle += 1.0f)
		{

			if (startAngle > 0 && startAngle < 90) // 4 quadrant
			{
				points[count] = Gdiplus::PointF(centerX + threadWavesMove.radius * (float)cos(startAngle* PI / 180) - iCircularInterval,
					centerY + threadWavesMove.radius * (float)sin(startAngle* PI / 180) - iCircularInterval);
			}
			else if (startAngle > 90 && startAngle < 180)// 3 quadrant
			{
				points[count] = Gdiplus::PointF(centerX + threadWavesMove.radius * (float)cos(startAngle* PI / 180) + iCircularInterval,
					centerY + threadWavesMove.radius * (float)sin(startAngle* PI / 180) - iCircularInterval);
			}
			else if (startAngle>180 && startAngle < 270)// 2 quadrant
			{
				points[count] = Gdiplus::PointF(centerX + threadWavesMove.radius * (float)cos(startAngle* PI / 180) + iCircularInterval,
					centerY + threadWavesMove.radius * (float)sin(startAngle* PI / 180) + iCircularInterval);
			}
			else if (startAngle>270 || startAngle <0)// 1 quadrant
			{
				points[count] = Gdiplus::PointF(centerX + threadWavesMove.radius * (float)cos(startAngle* PI / 180) - iCircularInterval,
					centerY + threadWavesMove.radius * (float)sin(startAngle* PI / 180) + iCircularInterval);
			}
			else if (startAngle == 0)// 0
			{
				points[count] = Gdiplus::PointF(centerX + threadWavesMove.radius * (float)cos(startAngle* PI / 180) - iCircularInterval,
					centerY + threadWavesMove.radius * (float)sin(startAngle* PI / 180));
			}
			else if (startAngle == 90) // 90
			{
				points[count] = Gdiplus::PointF(centerX + threadWavesMove.radius * (float)cos(startAngle* PI / 180),
					centerY + threadWavesMove.radius * (float)sin(startAngle* PI / 180) - iCircularInterval);
			}
			else if (startAngle == 180) //180
			{
				points[count] = Gdiplus::PointF(centerX + threadWavesMove.radius * (float)cos(startAngle* PI / 180) + iCircularInterval,
					centerY + threadWavesMove.radius * (float)sin(startAngle* PI / 180));
			}
			else //270
			{
				points[count] = Gdiplus::PointF(centerX + threadWavesMove.radius * (float)cos(startAngle* PI / 180) - iCircularInterval,
					centerY + threadWavesMove.radius * (float)sin(startAngle* PI / 180));
			}
			count++;
		}

		// Draw wave ball
		pGraphics->FillClosedCurve(brush, points, count);
	}

	// Set text.
	if (!threadWavesMove.bConstantWave)
		swprintf_s(strText, TEXT("%.1f%%"), threadWavesMove.percentage * 100);
	else
		lstrcpy(strText, AUTOGRAPH);
	// Draw String
	pGraphics->DrawString(strText, lstrlen(strText), &myFont,
		PointF(threadWavesMove.radius - (strSize / 3)*lstrlen(strText) - 7,
			threadWavesMove.radius - 2 * strSize / 3),
		blackBrush);
	// Draw memory DC to Dialog
	baseGraph->DrawImage(bmp, gdiRc, 0.0f, 0.0f, nWidth, nHeight, UnitPixel);


	delete(brushOriginal);
	delete(brush);
	delete(myPen);
	delete(blackBrush);
	delete(pGraphics);
	delete(baseGraph);
	delete(bmp);
	DeleteDC(hdc);

}
/*****************************************************************************
*
* GET VALUE POINT: IsPointInCircle
*
*****************************************************************************/
BOOL FlyWaveBall::IsPointInCircle(double x, double y, double CenterX, double CenterY, double radius)
{
	//到圆心的距离 是否大于半径。半径是R  
	//如O(x,y)点圆心,任意一点P(x1,y1) (x-x1)*(x-x1)+(y-y1)*(y-y1)>R*R 那么在圆外 反之在圆内
	double r = radius;
	double x1 = x;
	double y1 = y;



	if (!((CenterX - x1)*(CenterX - x1) + (CenterY - y1)*(CenterY - y1) > r*r))
	{
		return true;        //当前点在圆内
	}
	else
	{
		return false;       //当前点在圆外
	}
}
/*****************************************************************************
*
* GET VALUE POINT: WaveBallRedrawCircle
*
* Function: Erase fill.Redraw waveball
*
*****************************************************************************/
BOOL FlyWaveBall::WaveBallRedrawCircle()
{
	HDC			hdc;
	REAL		nWidth, nHeight;
	Graphics	*baseGraph;
	Bitmap		*bmp;
	Graphics	*pGraphics;
	Pen			*myPen;
	SolidBrush	*blackBrush;
	REAL		strSize;
	INT			iStrLength;

	nHeight = 2 * (threadWavesMove.radius + 1);
	nWidth = 2 * (threadWavesMove.radius + 1);
	Gdiplus::RectF gdiRc(threadWavesMove.originalX,
		threadWavesMove.originalY,
		nWidth,
		nHeight);

	hdc = GetDC(threadWavesMove.hWnd);
	baseGraph = new Gdiplus::Graphics(hdc);
	bmp = new Bitmap((int)nWidth, (int)nHeight);
	for (int i = 0; i < nWidth; i++)
	{
		for (int j = 0; j < nHeight; j++)
		{
			bmp->SetPixel(i, j, threadWavesMove.colorOriginal);
		}
	}
	pGraphics = Graphics::FromImage(bmp);

	pGraphics->SetSmoothingMode(SmoothingModeHighQuality);
	myPen = new Pen(threadWavesMove.colorWaveBall, 1);
	pGraphics->DrawEllipse(myPen, 0.0f, 0.0f, 2 * threadWavesMove.radius, 2 * threadWavesMove.radius);
	strSize = 2 * threadWavesMove.radius / 5;
	//WaveBallSetText(threadWavesMove.hWnd, threadWavesMove.colorWaveBall, AUTOGRAPH, lstrlen(AUTOGRAPH), (REAL)2 * threadWavesMove.radius / 5);
	Font myFont(TEXT("Arial"), strSize);
	iStrLength = lstrlen(strText);
	blackBrush = new SolidBrush(threadWavesMove.colorWaveBall);
	pGraphics->DrawString(strText, iStrLength, &myFont,
		PointF(threadWavesMove.radius - (strSize / 3)*iStrLength - 7,
			threadWavesMove.radius - 2 * strSize / 3),
		blackBrush);

	baseGraph->DrawImage(bmp, gdiRc, 0.0f, 0.0f, nWidth, nHeight, UnitPixel);

	delete(myPen);
	delete(blackBrush);
	delete(pGraphics);
	delete(bmp);
	delete(baseGraph);
	DeleteDC(hdc);

	return TRUE;
}
/*****************************************************************************
*
* GET VALUE POINT: WaveBallSetText
*
* Function: Set wave ball text
*
*****************************************************************************/
VOID FlyWaveBall::WaveBallUpdateProgress(IN REAL	percentage)
{
	if (percentage>1)
		threadWavesMove.percentage = 1;
	else if (percentage<0)
		threadWavesMove.percentage = 0;
	else
		threadWavesMove.percentage = percentage;
}
/*****************************************************************************
*
* GET VALUE POINT: WaveBallSetSpeed
*
* Function: Set wave ball speed. Milliseconds.
*
*****************************************************************************/
VOID FlyWaveBall::WaveBallSetConstantWave(IN REAL percentage)
{
	threadWavesMove.bConstantWave = TRUE;
	threadWavesMove.percentage = percentage;
}
/*****************************************************************************
*
* GET VALUE POINT: WaveBallSetTextColor
*
* Function: Set wave ball text color.
*
*****************************************************************************/
VOID FlyWaveBall::WaveBallSetTextColor(IN Color	&color)
{
	threadWavesMove.colorText = color;
}
/*****************************************************************************
*
* GET VALUE POINT: CreateOriginalBmp
*
*****************************************************************************/
VOID FlyWaveBall::ShowResult()
{
	HDC			hdc;
	REAL		nWidth, nHeight;
	Graphics	*baseGraph;
	Bitmap		*bmp;
	Graphics	*pGraphics;
	Pen			*myPen;
	int			iOffset = 8;

	nHeight = 2 * (threadWavesMove.radius + 1);
	nWidth = 2 * (threadWavesMove.radius + 1);
	Gdiplus::RectF gdiRc(threadWavesMove.originalX,
		threadWavesMove.originalY,
		nWidth,
		nHeight);

	hdc = GetDC(threadWavesMove.hWnd);
	baseGraph = new Gdiplus::Graphics(hdc);
	bmp = new Bitmap((int)nWidth, (int)nHeight);
	for (int i = 0; i < nWidth; i++)
	{
		for (int j = 0; j < nHeight; j++)
		{
			bmp->SetPixel(i, j, threadWavesMove.colorOriginal);
		}
	}
	pGraphics = Graphics::FromImage(bmp);

	pGraphics->SetSmoothingMode(SmoothingModeHighQuality);
	

	if (bResult)
	{// PASS
		myPen = new Pen(Color(255, 0, 255, 0), 2* (float)iOffset);
		pGraphics->DrawLine(myPen, 
			Point(iOffset, (int)nHeight/2 + iOffset),
			Point((int)nWidth/2, (int)nHeight - iOffset)
		);
		pGraphics->DrawLine(myPen,
			Point((int)nWidth - iOffset,5 * iOffset),
			Point((int)nWidth / 2 -(iOffset+1), (int)nHeight -(iOffset+1))
		);
	}
	else
	{// FAIL
		myPen = new Pen(Color(255, 255, 0, 0), 2 * (float)iOffset);
		pGraphics->DrawLine(myPen,
			Point(0, 0),
			Point((int)nWidth, (int)nHeight)
		);
		pGraphics->DrawLine(myPen,
			Point((int)nWidth, 0),
			Point(0, (int)nHeight)
		);
	}

	baseGraph->DrawImage(bmp, gdiRc, 0.0f, 0.0f, nWidth, nHeight, UnitPixel);

	delete(myPen);
	delete(pGraphics);
	delete(bmp);
	delete(baseGraph);
	DeleteDC(hdc);

}
/*****************************************************************************
*
* ENTRY POINT: WaveBallSetText
*
*****************************************************************************/
VOID FlyWaveBall::WaveBallSetText(TCHAR * string)
{
	lstrcpyn(strText, string, sizeof(strText) / sizeof(strText[0]));
}
/*****************************************************************************
*
* ENTRY POINT: WaveBallSetText
*
*****************************************************************************/
VOID FlyWaveBall::WaveBallSetResult(BOOL result)
{
	bResult = result;
}
/*****************************************************************************
*
* ENTRY POINT: WaveBallSetColor
*
*****************************************************************************/
VOID FlyWaveBall::WaveBallSetColor(IN Color	&color)
{
	threadWavesMove.colorWaveBall = color;
}

/*****************************************************************************
*
* ENTRY POINT: WaveBallSetText
*
*****************************************************************************/
VOID FlyWaveBall::WaveBallSetAmplitude(float High, float Width, float Offset)
{
	if (High > 0)
		amplitudeHigh = High;
	if (Width > 0)
		amplitudeWidth = Width;

	amplitudeOffset = Offset;
}

GdiplusWaveBall.h

#ifndef _FLY_GDIPLUS_WAVE_BALL_H_
#define _FLY_GDIPLUS_WAVE_BALL_H_

#include <windows.h>
// GDI+
#include <gdiplus.h> 
#pragma comment (lib, "GdiPlus.lib")
using namespace Gdiplus;



class FlyWaveBall
{
public:
	//FlyWaveBall();
	//~FlyWaveBall();
	VOID WaveBallInit(
		IN HWND hWnd,
		IN Gdiplus::Color &color,
		IN Gdiplus::Color &colorOriginal,
		IN REAL x,
		IN REAL y,
		IN REAL radius);
	VOID ThreadDynamicWave(int offset);
	VOID WaveBallUpdateProgress(IN REAL	percentage);
	VOID WaveBallSetConstantWave(IN REAL percentage);
	VOID WaveBallSetTextColor(IN Color	&color);
	VOID WaveBallSetColor(IN Color	&color);
	VOID WaveBallSetText(TCHAR * string);
	VOID WaveBallSetResult(BOOL result);
	VOID WaveBallSetAmplitude(float High, float Width, float amplitudeOffset);
private:
#define PI			3.141592654
#define MAX_POINT	1024
#define AUTOGRAPH	TEXT("FLY.")
	typedef struct ThreadParameters
	{
		HWND	hWnd;
		REAL	originalX;
		REAL	originalY;
		REAL	radius;
		REAL	percentage;
		Color	colorWaveBall;
		Color	colorOriginal;
		Color	colorText;
		BOOL	bConstantWave;
	}ThreadParam;

	Bitmap* CreateOriginalBmp();
	BOOL WaveBallRedrawCircle();
	VOID ShowResult();
	BOOL IsPointInCircle(
		double x, 
		double y, 
		double CenterX, 
		double CenterY, 
		double radius);

	ThreadParam threadWavesMove;
	BOOL	bResult;
	TCHAR	strText[16];

	float amplitudeHigh;

	float amplitudeWidth;

	float amplitudeOffset;
};

#endif

使用

一般步骤:

  1. 创建FlyWaveBall类。
  2. 使用该类中的WaveBallInit 初始化波浪球。
  3. 根据需要使用该类的WaveBallSetAmplitude设置波浪球的波浪参数。
  4. 创建一个定时器或线程使用该类的ThreadDynamicWave 动态更新波浪。
  5. 其他根据需要进行设置。

只需要包含了头文件GdiplusWaveBall.h和添加gdi+库即可使用该类;详情可以参考Demo。

// GDI+
#include <gdiplus.h> 
#pragma comment (lib, "GdiPlus.lib")
using namespace Gdiplus;

// Wave ball
#include "./WaveBallApi/GdiplusWaveBall.h"

int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) 
{ 

	//Initialize GDI+.
	Gdiplus::GdiplusStartupInput gdiplusStartupInput;
	ULONG_PTR gdiplusToken;
	Gdiplus::GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL);

	// other code

	//Unload GDI+
	Gdiplus::GdiplusShutdown(gdiplusToken);

	return 0; 
} 

波浪球的速度和进度可以在线程或者定时器中更新。

// 在定时器中更新波浪,定时的长短决定了波浪球的波浪速度,建议使用线程效果比较好。
static VOID CALLBACK CallBackTimer(HWND hWnd, UINT uMsg, UINT idEvent, DWORD dwTime)
{
	static int iWaveBallOffset = 0;
	switch (idEvent)
	{
	case TIMER_ID_WAVEBALL:
		mWaveBall.ThreadDynamicWave(iWaveBallOffset);
		if (++iWaveBallOffset > 12)
			iWaveBallOffset = 0;
		break;
	default:
		break;
	}
}

参考demo

#include <windows.h> 
#include <commctrl.h>
#pragma comment (lib,"comctl32.lib")

// GDI+
#include <gdiplus.h> 
#pragma comment (lib, "GdiPlus.lib")
using namespace Gdiplus;

// Wave ball
#include "./WaveBallApi/GdiplusWaveBall.h"

#define COLOR_RGB_DLG_BG	RGB(115, 141, 141)
// Wave ball color
#define COLOR_GDI_WAVEBALL	Color(255, 249, 205, 173)
#define COLOR_GDI_DLG_BG	Color(255, 115, 141, 141)

#define TIMER_ID_WAVEBALL	1
#define TIMER_TIME_SEC		1000
#define TIMER_TIME_300MS	300

static FlyWaveBall mWaveBall;


INT_PTR CALLBACK MyDlgProc(HWND, UINT, WPARAM, LPARAM); 
static VOID CALLBACK CallBackTimer(HWND hWnd, UINT uMsg, UINT idEvent, DWORD dwTime);

/*****************************************************************************
*
* ENTRY POINT: WinMain
*
*****************************************************************************/
int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) 
{ 

	//Initialize GDI+.
	Gdiplus::GdiplusStartupInput gdiplusStartupInput;
	ULONG_PTR gdiplusToken;
	Gdiplus::GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL);

	InitCommonControls();
	DialogBox(hInstance, MAKEINTRESOURCE(IDD_DIALOG1), NULL, (DLGPROC)MyDlgProc); 

	//Unload GDI+
	Gdiplus::GdiplusShutdown(gdiplusToken);

	return 0; 
} 




/*****************************************************************************
*
* ENTRY POINT: MyDlgProc
*
*****************************************************************************/
INT_PTR CALLBACK MyDlgProc(HWND hWnd, UINT msg, WPARAM wp, LPARAM lp) 
{ 
	static HBRUSH	hBsh;

	switch (msg) { 
    case WM_INITDIALOG:
        SetWindowText(hWnd, MODELNAME);
		// Set dialog background
		hBsh = CreateSolidBrush(COLOR_RGB_DLG_BG);

		// wave ball
		mWaveBall.WaveBallInit(hWnd, COLOR_GDI_WAVEBALL, COLOR_GDI_DLG_BG, 70, 38, 160);
		mWaveBall.WaveBallSetText(L"FLY.");
		mWaveBall.WaveBallSetConstantWave(0.3f);
		mWaveBall.WaveBallSetAmplitude(4.0, 0.02f, 6.0);

		SetTimer(hWnd, TIMER_ID_WAVEBALL, TIMER_TIME_300MS, (TIMERPROC)CallBackTimer);

		

        break;
	case WM_COMMAND: 
		switch (LOWORD(wp)) { 
		case IDOK: 
			
			break;
		case IDCANCEL: 
			EndDialog(hWnd, 0); 
			return TRUE; 
		} 
	case WM_CTLCOLORDLG:
		// Returns a brush to create a dialog background color  
		return (INT_PTR)hBsh;
		break;
	} 
	return FALSE; 
} 

/******************************************************************************
*
* ENTRY POINT: CallBackTimer
*
* Function: Timer call back
*
******************************************************************************/
static VOID CALLBACK CallBackTimer(HWND hWnd, UINT uMsg, UINT idEvent, DWORD dwTime)
{
	static int iWaveBallOffset = 0;
	switch (idEvent)
	{
	case TIMER_ID_WAVEBALL:
		mWaveBall.ThreadDynamicWave(iWaveBallOffset);
		if (++iWaveBallOffset > 12)
			iWaveBallOffset = 0;
		break;
	default:
		break;
	}
}

项目github地址在这里,如果对你有帮助帮忙点个star哟。

  • 3
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
C/C是一种编程语言,而WMI是Windows Management Instrumentation的缩写,它是Windows操作系统的一个功能,用于管理和监控计算机系统的各种资源和组件。而Win32_DiskDrive是WMI的一个类,用于管理和获取计算机系统中的磁盘驱动器的信息。这个类提供了许多属性和方法,可以帮助我们获取和操作磁盘驱动器的各种信息。 在C/C编程语言中,我们可以使用WMI和Win32_DiskDrive类来获取和操作磁盘驱动器的信息。首先,我们需要初始化WMI,然后使用WMI查询语言来查询Win32_DiskDrive类的实例。通过遍历这些实例,我们可以获取磁盘驱动器的各种属性,如驱动器的名称、序列号、容量、型号等等。我们可以通过调用相应的方法,如获取磁盘驱动器的序列号、格式化磁盘等,来操作磁盘驱动器。 具体来说,在C/C中可以使用WMI API编写相关的代码来获取和操作磁盘驱动器的信息。我们需要包含相关的头文件,并使用WMI API中的函数和结构体来实现相应的功能。首先,我们需要初始化WMI和连接到本地计算机的WMI服务。然后,使用WMI查询语句来查询Win32_DiskDrive类的实例。通过遍历这些实例,我们可以获取磁盘驱动器的各种属性,并将其打印或存储起来。此外,我们还可以调用相应的方法来进行磁盘驱动器的操作,如格式化磁盘、扩展磁盘分区等等。 总之,使用C/C编程语言结合WMI和Win32_DiskDrive类,我们可以进行磁盘驱动器的信息获取和操作。这对于需要获取和管理计算机系统中磁盘驱动器的应用程序是非常有用的。同时,这也展示了C/C语言的灵活性和与Windows操作系统底层API的结合能力。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Lion Long

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值