windows编程总结

windows编程分为API和MFC。前者是后者的基础。后者只是将前者进行了封装,用类实现。学习了那么久的windows编程,是时候该总结一下了,以例题和代码为主(代码中有详细的说明)

作业1:

1)date类设计(时间类设计)能够根据现在的时间输出下一天

代码:

//Data类
#include <iostream>
using namespace std;
int p[13]={0,31,28,31,30,31,30,31,31,30,31,30,31};
bool IsLeapyear(int year){ //判断是否为闰年
	return year%4==0 && year%100!=0 || year%400==0;
}
class Data{
public:
	Data(int year=2014,int month=2,int day=19);
	//Data(const  Data &da);
	//~Data();
	int Get_Year() const;
	int Get_month() const;
	int Get_day() const;
	void Show_now() const;//输出现在的日期
	void Show_next() const;//输出现在日期的下一个日期
	friend istream & operator>>(istream &in,Data &da); //重载输入运算符
	//Data & operator=(const  Data &da);
private:
	int y,m,d;
};
Data::Data(int year,int month,int day):y(year),m(month),d(day) { }
//Data::Data(const  Data &da):y(da.y),m(da.m),d(da.d) { }
//Data::~Data() { }
void Data::Show_now() const{
	cout << y << ":" << m << ":" << d << endl;
}
void Data::Show_next() const{
	switch(m)
	{
case 12:
	    if(d+1>p[12])
		   cout << y+1 << ":"
		        << "1" << ":"
				<< "1" << endl;
		else
			cout << y << ":" 
			     << m << ":"
				 << d+1 << endl;
				 break;
default:
	    int day=p[m];
	    if(m==2)
		   day=IsLeapyear(y)?(day+1):day;
	    if(d+1>day)
		   cout << y << ":" 
		        << m+1 << ":"
				<< "1" << endl;
		else
			cout << y << ":"
			     << m << ":"
				 << d+1 << endl;
	}
}
int Data::Get_Year() const{
	return y;
}
int Data::Get_month() const{
	return m;
}
int Data::Get_day() const{
	return d;
}
istream &operator>>(istream &in,Data &da){
	in >> da.y >> da.m >> da.d;
	return  in;
}
/*Data & Data::operator=(const Data &da){
	y=da.y;
	m=da.m;
	d=da.d;
	return *this;
}*/

int main(){
	Data da;
	cin >> da;
	da.Show_now();
	da.Show_next();
	return 0;
}

2)大数据类设计(实现大数据的加减)

//大数据加减(30位)
//大数类
#include <iostream>
#include <cstring>
#define Max(a,b) (a)>(b)?(a):(b)
#define Maxsize 100
using namespace std;
class Bignum{
public:
   Bignum(const char *pro="0");
   Bignum(const Bignum &bnum);
   ~Bignum();
   Bignum & operator=(const Bignum &bnum);
   friend istream & operator>>(istream &in,Bignum &bnum);//重载输入
   friend ostream & operator<<(ostream &out,const Bignum &bnum);//重载输出
   friend Bignum operator+(const Bignum &a,const Bignum &b);//加法运算
   friend Bignum operator-(const Bignum &a,const Bignum &b);//减法运算
private:
	char num[Maxsize]; 
};
Bignum::Bignum(const char *pro){
     //strncpy(num,pro,30);
	 //num[30]='\0';
	strcpy(num,pro);
}
Bignum::Bignum(const Bignum &bnum){
	strcpy(num,bnum.num);
}
Bignum::~Bignum() { }
Bignum & Bignum::operator=(const Bignum &bnum){
	if(this!=&bnum)
	strcpy(num,bnum.num);
	return *this;
}
istream &operator>>(istream &in,Bignum &bnum){
	in >> bnum.num;
	return in;
}
ostream &operator<<(ostream &out,const Bignum &bnum){
	out << bnum.num << endl;
	return out;
}
Bignum operator+(const Bignum &a,const Bignum &b){
    int i,str1[Maxsize],str2[Maxsize];
	int result[Maxsize];
	memset(str1,0,sizeof(str1));
	memset(str2,0,sizeof(str2));
	memset(result,0,sizeof(result));
	int len1=strlen(a.num),len2=strlen(b.num);
	for(i=0;i<len1;i++)
		str1[i]=a.num[len1-1-i]-'0';
	for(i=0;i<len2;i++)
		str2[i]=b.num[len2-1-i]-'0';
	int len=Max(len1,len2);
	for(i=0;i<len-1;i++){
		result[i]=str1[i]+str2[i];
		if(result[i]>=10){
			result[i]-=10;
			str1[i+1]++;
		}
	}
		result[i]=str1[i]+str2[i];
		if(result[i]>=10){
			result[i]-=10;
			result[i+1]=1;
		}
	for(i=len;result[i]==0;i--) ;
	Bignum temp;
	if(i<0) return temp;  //0+0的情况
    int k=0;
    for( ;i>=0;i--) temp.num[k++]=result[i]+'0';
	temp.num[k]='\0';
	return temp;
}
Bignum operator-(const Bignum &a,const Bignum &b){
	int i,len1=strlen(a.num),len2=strlen(b.num);
	Bignum temp;
	if(len1<len2)
		return temp; // 若a<b,则结果为0;
	if(len1==len2)
		for(i=0;i<len1;i++)
		{
			if(a.num[i]<b.num[i])
				return temp;
			else if(a.num[i]>b.num[i])
				break;
		}
	if(i==len1) //若相等则为0;
		return temp;
	int str1[Maxsize],str2[Maxsize],result[Maxsize];
	memset(str2,0,sizeof(str2));
    for(i=0;i<len1;i++){
		str1[i]=a.num[len1-1-i]-'0';
		//cout << str1[i] << endl;
	}
	   
	for(i=0;i<len2;i++)
		str2[i]=b.num[len2-1-i]-'0';
	for(i=0;i<len1;i++){
		//cout << str1[i] << " ";
		result[i]=str1[i]-str2[i];
		//cout << result[i] << endl;
		if(result[i]<0){
		result[i]+=10;
		str1[i+1]--;
		}
	}
	for(i=len1-1;result[i]==0;i--) ;
	int k=0;
	for( ;i>=0;i--) temp.num[k++]=result[i]+'0';
	temp.num[k]='\0';
	return temp;
}

int main()
{
	Bignum t("123456789012345678901234567890"),n("123456789012345678901234567890");
	cin >> t >> n;
	cout << t+n << t-n << endl;
	return 0;
}


作业2:下棋程序(光标点击哪里便显示一个棋子,有黑棋和灰棋,并能判断哪方胜利)

API 代码:

// 下棋程序.cpp : Defines the entry point for the application.
//

#include "stdafx.h"
#include "resource.h"

#define MAX_LOADSTRING 100
int record[4][4]={0}; //0代表没有没有棋子,-1代表左键即黑棋,1代表右键即灰棋,初始化为全0
int trag; //用来判断是左键按下,还是右键按下
bool tr=0; //用来判断是否产生了按键(判断最初情况)
int x,y; //记录鼠标的点坐标
char *str1="黑棋赢了!"; //相应的判断信息串
char *str2="灰棋赢了!";
char *str3="平局!";
char *str4="加油,还未结束!";
bool fuck; //作为判断鼠标点击的位置是否已经下过棋了,0代表下过棋,1代表未下棋

// Global Variables:
HINSTANCE hInst;								// current instance
TCHAR szTitle[MAX_LOADSTRING];								// The title bar text
TCHAR szWindowClass[MAX_LOADSTRING];								// The title bar text

// Foward declarations of functions included in this code module:
ATOM				MyRegisterClass(HINSTANCE hInstance);
BOOL				InitInstance(HINSTANCE, int);
LRESULT CALLBACK	WndProc(HWND, UINT, WPARAM, LPARAM);
LRESULT CALLBACK	About(HWND, UINT, WPARAM, LPARAM);

int Is_winner(){ //判断是谁赢了,0代表还未结束,2代表平局,-1代表左键方赢了,1代表右键方赢了
	int i,j,symble=-2;
	for(i=1;i<=3;i++)
		if(record[i][1]!=0 && record[i][1]==record[i][2] && record[i][2]==record[i][3]){
			symble=record[i][1];
			break;
		}
	if(symble!=-2)
		return symble;
    for(i=1;i<=3;i++)
		if(record[1][i]!=0 && record[1][i]==record[2][i] && record[2][i]==record[3][i]){
			symble=record[1][i];
			break;
		}
	if(symble!=-2)
		return symble;
	if(record[1][1]!=0 && record[1][1]==record[2][2] && record[3][3]==record[2][2])
	    return record[2][2];
	if(record[3][1]!=0 && record[3][1]==record[2][2] && record[2][2]==record[1][3])
		return record[2][2];
	for(i=1;i<=3;i++)
		for(j=1;j<=3;j++)
			if(record[i][j]==0)
				return 0;
    return 2;
}

int APIENTRY WinMain(HINSTANCE hInstance,
                     HINSTANCE hPrevInstance,
                     LPSTR     lpCmdLine,
                     int       nCmdShow)
{
 	// TODO: Place code here.
	MSG msg;
	HACCEL hAccelTable;

	// Initialize global strings
	LoadString(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING);
	LoadString(hInstance, IDC_MY, szWindowClass, MAX_LOADSTRING);
	MyRegisterClass(hInstance);

	// Perform application initialization:
	if (!InitInstance (hInstance, nCmdShow)) 
	{
		return FALSE;
	}

	hAccelTable = LoadAccelerators(hInstance, (LPCTSTR)IDC_MY);

	// Main message loop:
	while (GetMessage(&msg, NULL, 0, 0)) 
	{
		if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg)) 
		{
			TranslateMessage(&msg);
			DispatchMessage(&msg);
		}
	}

	return msg.wParam;
}



//
//  FUNCTION: MyRegisterClass()
//
//  PURPOSE: Registers the window class.
//
//  COMMENTS:
//
//    This function and its usage is only necessary if you want this code
//    to be compatible with Win32 systems prior to the 'RegisterClassEx'
//    function that was added to Windows 95. It is important to call this function
//    so that the application will get 'well formed' small icons associated
//    with it.
//
ATOM MyRegisterClass(HINSTANCE hInstance)
{
	WNDCLASSEX wcex;

	wcex.cbSize = sizeof(WNDCLASSEX); 

	wcex.style			= CS_HREDRAW | CS_VREDRAW;
	wcex.lpfnWndProc	= (WNDPROC)WndProc;
	wcex.cbClsExtra		= 0;
	wcex.cbWndExtra		= 0;
	wcex.hInstance		= hInstance;
	wcex.hIcon			= LoadIcon(hInstance, (LPCTSTR)IDI_MY);
	wcex.hCursor		= LoadCursor(NULL, IDC_ARROW);
	wcex.hbrBackground	= (HBRUSH)(COLOR_WINDOW+1);
	wcex.lpszMenuName	= (LPCSTR)IDC_MY;
	wcex.lpszClassName	= szWindowClass;
	wcex.hIconSm		= LoadIcon(wcex.hInstance, (LPCTSTR)IDI_SMALL);

	return RegisterClassEx(&wcex);
}

//
//   FUNCTION: InitInstance(HANDLE, int)
//
//   PURPOSE: Saves instance handle and creates main window
//
//   COMMENTS:
//
//        In this function, we save the instance handle in a global variable and
//        create and display the main program window.
//
BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
{
   HWND hWnd;

   hInst = hInstance; // Store instance handle in our global variable

   hWnd = CreateWindow(szWindowClass, szTitle, WS_OVERLAPPEDWINDOW,
      CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, NULL, NULL, hInstance, NULL);

   if (!hWnd)
   {
      return FALSE;
   }

   ShowWindow(hWnd, nCmdShow);
   UpdateWindow(hWnd);

   return TRUE;
}

//
//  FUNCTION: WndProc(HWND, unsigned, WORD, LONG)
//
//  PURPOSE:  Processes messages for the main window.
//
//  WM_COMMAND	- process the application menu
//  WM_PAINT	- Paint the main window
//  WM_DESTROY	- post a quit message and return
//
//
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{

	int wmId, wmEvent;
	PAINTSTRUCT ps;
	HDC hdc;
	TCHAR szHello[MAX_LOADSTRING];
	LoadString(hInst, IDS_HELLO, szHello, MAX_LOADSTRING);
	HBRUSH hBrush1,hBrush2; //创建两个画刷,其句柄分别为hBrush1,hBrush2.
	HPEN hPen; //创建一个画笔,其句柄为hPen.
	switch (message) 
	{
		case WM_COMMAND:
			wmId    = LOWORD(wParam); 
			wmEvent = HIWORD(wParam); 
			// Parse the menu selections:
			switch (wmId)
			{
				case IDM_ABOUT:
				   DialogBox(hInst, (LPCTSTR)IDD_ABOUTBOX, hWnd, (DLGPROC)About);
				   break;
				case IDM_EXIT:
				   DestroyWindow(hWnd);
				   break;
				default:
				   return DefWindowProc(hWnd, message, wParam, lParam);
			}
			break;
		case WM_PAINT:
			hdc = BeginPaint(hWnd, &ps);
			// TODO: Add any drawing code here...
			RECT rt;
			GetClientRect(hWnd, &rt);
			hPen=(HPEN)GetStockObject(BLACK_PEN); //获取画笔样式
			hBrush1=(HBRUSH)GetStockObject(WHITE_BRUSH);//获取画刷样式
			SelectObject(hdc,hBrush1);//将画刷选入设备描述表中
			SelectObject(hdc,hPen);//将画笔选入设备描述表中
            Rectangle(hdc,200,50,500,350); //画矩形,左上角坐标为(200,50),右下角坐标为(500,350)
			//画线,先设置画笔当前位置,然后画线
			MoveToEx(hdc,200,150,NULL); //设置画笔当前位置为(200,50)
		    LineTo(hdc,500,150);// 从当前位置向指定坐标点画直线
			MoveToEx(hdc,200,250,NULL); 
			LineTo(hdc,500,250);
			MoveToEx(hdc,300,50,NULL);
			LineTo(hdc,300,350);
			MoveToEx(hdc,400,50,NULL);
			LineTo(hdc,400,350);
			hBrush1=(HBRUSH)GetStockObject(BLACK_BRUSH);//分别选择黑色和灰色样式,以便后续操作
			hBrush2=(HBRUSH)GetStockObject(GRAY_BRUSH);
			int i,j;
			fuck=1; //初始化为鼠标点击的位置没有下棋
			//重绘已经画了的棋子,注意这里必须要有一个前提,就是已经产生了点击鼠标的消息。
			//tr是判断是否有点击鼠标的消息产生,在第一次产生之前其值设为0,表示还没有此消息产生
			//当第一次产生此消息后,其值设为1,表示已经产生了点击鼠标的消息。不管是左键还是右键。
			if(tr){
		for(i=1;i<=3;i++)
			for(j=1;j<=3;j++)
				switch(record[i][j])
				{
		case -1:
			SelectObject(hdc,hBrush1); //重汇黑棋
			Ellipse(hdc,200+(j-1)*100,50+(i-1)*100,300+(j-1)*100,150+(i-1)*100);
			if(x>200+(j-1)*100 && x<300+(j-1)*100 && y>50+(i-1)*100 && y<150+(i-1)*100)
				fuck=0;  //若此时鼠标点击的位置已经有了黑棋,则设fuck为0
			break;
		case 1:
			SelectObject(hdc,hBrush2); //重汇灰棋
			Ellipse(hdc,200+(j-1)*100,50+(i-1)*100,300+(j-1)*100,150+(i-1)*100);
            if(x>200+(j-1)*100 && x<300+(j-1)*100 && y>50+(i-1)*100 && y<150+(i-1)*100)
				fuck=0; //若此时鼠标点击的位置已经有了灰棋,则设fuck为0
			break;
				}
		//若为record[i][j]为0,代表没有棋子,不需要重汇
			}
			//若已经产生了鼠标的点击,并且点击鼠标的位置还没有画棋
			if(fuck){
			if(tr){
			if(trag==-1) //若为左键,则选择黑色画刷
			SelectObject(hdc,hBrush1);
			else //否则选择灰色画刷
			SelectObject(hdc,hBrush2);
			//以下的if..else是判断鼠标点击位置在3×3方格中的那个版块,在相应的版块画棋子
			if(y>50 && y<150){ 
			if(x>200 && x<300){
		    Ellipse(hdc,200,50,300,150);
			record[1][1]=trag;
			}
			else if(x>300 && x<400){
			Ellipse(hdc,300,50,400,150);
			record[1][2]=trag;
			}
			else if(x>400 && x<500){
			Ellipse(hdc,400,50,500,150);
			record[1][3]=trag;
			}
			}
			//========
			else if(y>150 && y<250){
			if(x>200 && x<300){
		    Ellipse(hdc,200,150,300,250);
		    record[2][1]=trag;
			}
			else if(x>300 && x<400){
			Ellipse(hdc,300,150,400,250);
			record[2][2]=trag;
			}
			else if(x>400 && x<500){
			Ellipse(hdc,400,150,500,250);
			record[2][3]=trag;
			}
			}
			//==========
			else if(y>250 && y<350){
			if(x>200 && x<300){
		    Ellipse(hdc,200,250,300,350);
			record[3][1]=trag;
			}
			else if(x>300 && x<400){
			Ellipse(hdc,300,250,400,350);
			record[3][2]=trag;
			}
			else if(x>400 && x<500){
			Ellipse(hdc,400,250,500,350);
			record[3][3]=trag;
			}
			}
			}	
			}
	        if(tr) //若已经产生了点击鼠标的消息,则判断此时棋盘处于什么状态。
            //相应的用Is_winner()函数来判断棋盘状态。
			//具体内容在Is_winner()的定义处已作说明。这里不再重述
			switch(Is_winner()){ //根据相应的状态给出相应的消息。
			case -1: 
			TextOut(hdc,600,20,str1,strlen(str1));  //黑棋赢了
			break;
			case 1:
			TextOut(hdc,600,20,str2,strlen(str2)); //灰棋赢了
			break;
			case 2:
			TextOut(hdc,600,20,str3,strlen(str3)); //平局
			break;
			case 0:
			TextOut(hdc,600,20,str4,strlen(str4)); //还未结束
			break;
			}
			DeleteObject(hPen); //删除画笔
			DeleteObject(hBrush1); //删除画刷
			DeleteObject(hBrush2);
			EndPaint(hWnd, &ps); 
			//若棋盘此时为黑棋或灰棋,或者是平局,则在输出相应消息后,休眠1000s然后结束程序
			if(Is_winner()==1 || Is_winner()==-1 || Is_winner()==2){ 
				Sleep(1000);
				PostQuitMessage(0);
			}
			break;
	   	case WM_LBUTTONDOWN: //点击左键产生的消息处理程序
            x = LOWORD(lParam); //获取此时的坐标
            y = HIWORD(lParam);
			trag=-1; //trag置为-1,代表左键
			tr=1; //tr置为1,代表产生了点击鼠标的消息
            InvalidateRect(hWnd,NULL,1); //刷新
            break;
        case WM_RBUTTONDOWN: //点击右键产生的消息处理程序
			x = LOWORD(lParam);//获取此时的坐标
            y = HIWORD(lParam);
			trag=1;//trag置为1,代表是右键
			tr=1; //tr置为1,代表产生了点击鼠标的消息
            InvalidateRect(hWnd,NULL,1);//刷新
			break;
		case WM_DESTROY:
			PostQuitMessage(0);
			break;
		default:
			return DefWindowProc(hWnd, message, wParam, lParam);
   }
   return 0;
}

// Mesage handler for about box.
LRESULT CALLBACK About(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
	switch (message)
	{
		case WM_INITDIALOG:
				return TRUE;

		case WM_COMMAND:
			if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL) 
			{
				EndDialog(hDlg, LOWORD(wParam));
				return TRUE;
			}
			break;
	}
    return FALSE;
}

作业3:字体显示实例(可以显示各种不同类型和颜色的字体)

API代码:

// 字体显示实例程序.cpp : Defines the entry point for the application.
//

#include "stdafx.h"
#include "resource.h"
#include <math.h>

#define MAX_LOADSTRING 100
#define Pi 3.14  //定义圆周率π

// Global Variables:
HINSTANCE hInst;								// current instance
TCHAR szTitle[MAX_LOADSTRING];								// The title bar text
TCHAR szWindowClass[MAX_LOADSTRING];								// The title bar text

char *str="欲穷千里目更上一层楼"; //要输出的字符
struct Locate{ //自定义点坐标结构体,用于记录点的坐标
	double x;
	double y;
}locate[20];

// Foward declarations of functions included in this code module:
ATOM				MyRegisterClass(HINSTANCE hInstance);
BOOL				InitInstance(HINSTANCE, int);
LRESULT CALLBACK	WndProc(HWND, UINT, WPARAM, LPARAM);
LRESULT CALLBACK	About(HWND, UINT, WPARAM, LPARAM);

void Get_pointcircle(){ //生成整个圆的坐标
	int x0=500,y0=300; //圆点坐标
	int a=0; //最开始的角度为0
	int r=50;//圆半径为50
	for(int j=0;j<strlen(str);j+=2){
		locate[j].x=x0+r*cos(a*Pi/180); //转化为弧度
		locate[j].y=y0+r*sin(a*Pi/180);
		a+=36; //分成了十份,每份角度为36度
	}
}
void Get_pointhalf_circle(){//生成半个圆的坐标
	int  x0=500,y0=100; //圆点坐标
	int a=160; //要旋转,故偏移180度20度
	int r=50; //半径
	for(int j=0;j<strlen(str);j+=2){
		locate[j].x=x0+r*cos(a*Pi/180);
		locate[j].y=y0+r*sin(a*Pi/180);
		a+=22; //180度分成了9份,每份大致为22度(结合输出的效果考虑)
	}
}

int APIENTRY WinMain(HINSTANCE hInstance,
                     HINSTANCE hPrevInstance,
                     LPSTR     lpCmdLine,
                     int       nCmdShow)
{
 	// TODO: Place code here.
	MSG msg;
	HACCEL hAccelTable;

	// Initialize global strings
	LoadString(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING);
	LoadString(hInstance, IDC_MY, szWindowClass, MAX_LOADSTRING);
	MyRegisterClass(hInstance);

	// Perform application initialization:
	if (!InitInstance (hInstance, nCmdShow)) 
	{
		return FALSE;
	}

	hAccelTable = LoadAccelerators(hInstance, (LPCTSTR)IDC_MY);

	// Main message loop:
	while (GetMessage(&msg, NULL, 0, 0)) 
	{
		if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg)) 
		{
			TranslateMessage(&msg);
			DispatchMessage(&msg);
		}
	}

	return msg.wParam;
}



//
//  FUNCTION: MyRegisterClass()
//
//  PURPOSE: Registers the window class.
//
//  COMMENTS:
//
//    This function and its usage is only necessary if you want this code
//    to be compatible with Win32 systems prior to the 'RegisterClassEx'
//    function that was added to Windows 95. It is important to call this function
//    so that the application will get 'well formed' small icons associated
//    with it.
//
ATOM MyRegisterClass(HINSTANCE hInstance)
{
	WNDCLASSEX wcex;

	wcex.cbSize = sizeof(WNDCLASSEX); 

	wcex.style			= CS_HREDRAW | CS_VREDRAW;
	wcex.lpfnWndProc	= (WNDPROC)WndProc;
	wcex.cbClsExtra		= 0;
	wcex.cbWndExtra		= 0;
	wcex.hInstance		= hInstance;
	wcex.hIcon			= LoadIcon(hInstance, (LPCTSTR)IDI_MY);
	wcex.hCursor		= LoadCursor(NULL, IDC_ARROW);
	wcex.hbrBackground	= (HBRUSH)(COLOR_WINDOW+1);
	wcex.lpszMenuName	= (LPCSTR)IDC_MY;
	wcex.lpszClassName	= szWindowClass;
	wcex.hIconSm		= LoadIcon(wcex.hInstance, (LPCTSTR)IDI_SMALL);

	return RegisterClassEx(&wcex);
}

//
//   FUNCTION: InitInstance(HANDLE, int)
//
//   PURPOSE: Saves instance handle and creates main window
//
//   COMMENTS:
//
//        In this function, we save the instance handle in a global variable and
//        create and display the main program window.
//
BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
{
   HWND hWnd;

   hInst = hInstance; // Store instance handle in our global variable

   hWnd = CreateWindow(szWindowClass, szTitle, WS_OVERLAPPEDWINDOW,
      CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, NULL, NULL, hInstance, NULL);

   if (!hWnd)
   {
      return FALSE;
   }

   ShowWindow(hWnd, nCmdShow);
   UpdateWindow(hWnd);

   return TRUE;
}

//
//  FUNCTION: WndProc(HWND, unsigned, WORD, LONG)
//
//  PURPOSE:  Processes messages for the main window.
//
//  WM_COMMAND	- process the application menu
//  WM_PAINT	- Paint the main window
//  WM_DESTROY	- post a quit message and return
//
//
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
	int wmId, wmEvent;
	int height; //记录高度
	int i,x,y,temp; //x,y用来设置坐标值,temp用来记录纵坐标,i为循环变量
	int color; //记录颜色
	HFONT hF_black; //定义字体句柄变量
	TEXTMETRIC tm;
	PAINTSTRUCT ps;
	HDC hdc;
	TCHAR szHello[MAX_LOADSTRING];
	LoadString(hInst, IDS_HELLO, szHello, MAX_LOADSTRING);

	switch (message) 
	{
		case WM_COMMAND:
			wmId    = LOWORD(wParam); 
			wmEvent = HIWORD(wParam); 
			// Parse the menu selections:
			switch (wmId)
			{
				case IDM_ABOUT:
				   DialogBox(hInst, (LPCTSTR)IDD_ABOUTBOX, hWnd, (DLGPROC)About);
				   break;
				case IDM_EXIT:
				   DestroyWindow(hWnd);
				   break;
				default:
				   return DefWindowProc(hWnd, message, wParam, lParam);
			}
			break;
		case WM_PAINT:
		   hdc = BeginPaint(hWnd, &ps);
		   //所有的字体设置宽度为10,达到对齐的目的
		   //画第一个“欲穷千里目。。”
		   x=0,y=20; //第一串起始坐标
		   temp=y; //记录下纵坐标
	       SetTextColor(hdc,RGB(0,0,0)); //黑色
		   height=32; //最初高度
		    for(i=0;i<strlen(str);i+=2){
			         hF_black=CreateFont(		 	//创建自定义字体
      height,			//字体的高度
	  10,		//由系统根据高宽比选取字体最佳宽度值
	  0,			//文本的倾斜度为0,表示水平
	  0,			//字体的倾斜度为0
	  FW_HEAVY,		//字体的粗度,FW_HEAVY为最粗
	  0,			//非斜体字
	  0,			//无下划线
	  0,			//无删除线
	  ANSI_CHARSET,	//表示所用的字符集为ANSI_CHARSET
	  OUT_DEFAULT_PRECIS,		//输出精度为缺省精度
	  CLIP_DEFAULT_PRECIS,		//剪裁精度为缺省精度
	  DEFAULT_QUALITY,		//输出质量为缺省值
	  DEFAULT_PITCH|FF_DONTCARE,//字间距和字体系列使用缺省值
	  "粗体字" ); 
                SelectObject(hdc,hF_black); //将字体对象选入设备环境表中
				TextOut(hdc,x,y,&str[i],2); //输出单个文字,注意占用两个字节
				GetTextMetrics(hdc,&tm); //获取字体的信息,写入tm结构
				x+=tm.tmAveCharWidth*2;//下一个文字的横坐标应该为当前文字横坐标加上其宽度
				y+=1;//为了使文字输出时整体上不是向上倾斜,有必要将纵坐标变大
				height-=2; //高度不断减小
			}
			//输出第二个“欲穷千里目。。”
	    	y=temp+30;//下一个串的起始纵坐标和横坐标
			x=0; 
			temp=y; //记录纵坐标
			height=14;//与上一次的最后一次高度相对应
				for(i=0;i<strlen(str);i+=2){
			         hF_black=CreateFont(		 	//创建自定义字体
      height,			//字体的高度
	  10,		//由系统根据高宽比选取字体最佳宽度值
	  0,			//文本的倾斜度为0,表示水平
	  0,			//字体的倾斜度为0
	  FW_HEAVY,		//字体的粗度,FW_HEAVY为最粗
	  0,			//非斜体字
	  0,			//无下划线
	  0,			//无删除线
	  ANSI_CHARSET,	//表示所用的字符集为ANSI_CHARSET
	  OUT_DEFAULT_PRECIS,		//输出精度为缺省精度
	  CLIP_DEFAULT_PRECIS,		//剪裁精度为缺省精度
	  DEFAULT_QUALITY,		//输出质量为缺省值
	  DEFAULT_PITCH|FF_DONTCARE,//字间距和字体系列使用缺省值
	  "粗体字" );
				SelectObject(hdc,hF_black);
			    TextOut(hdc,x,y,&str[i],2);
				GetTextMetrics(hdc,&tm); 
				x+=tm.tmAveCharWidth*2;
				height+=2; //高度增加
				y-=1; //同样的为了使输出不向下倾斜,纵坐标要适当的变小
			}
			//画第三个“欲穷千里目。。"
			x=0;
			y=temp+40; //初始坐标
            temp=y;
			height=14; //初始高度
			SetTextColor(hdc,RGB(120,120,120));//设置浅黑色
			for(i=0;i<strlen(str)/2;i+=2){ //输出前一半的文字
			    hF_black=CreateFont(		 	//创建自定义字体
      height,			//字体的高度
	  10,		//由系统根据高宽比选取字体最佳宽度值
	  0,			//文本的倾斜度为0,表示水平
	  0,			//字体的倾斜度为0
	  FW_HEAVY,		//字体的粗度,FW_HEAVY为最粗
	  0,			//非斜体字
	  0,			//无下划线
	  0,			//无删除线
	  ANSI_CHARSET,	//表示所用的字符集为ANSI_CHARSET
	  OUT_DEFAULT_PRECIS,		//输出精度为缺省精度
	  CLIP_DEFAULT_PRECIS,		//剪裁精度为缺省精度
	  DEFAULT_QUALITY,		//输出质量为缺省值
	  DEFAULT_PITCH|FF_DONTCARE,//字间距和字体系列使用缺省值
	  "粗体字" );
				SelectObject(hdc,hF_black);
			    TextOut(hdc,x,y,&str[i],2);
				GetTextMetrics(hdc,&tm); 
				x+=tm.tmAveCharWidth*2;
				height+=4;  //与第二个串的输出同样的道理
				y-=2;
			}
			height-=4; //这里恢复到五个文字的高度,‘更’与‘目’高度相同
			y+=2; //纵坐标也相同
		    SetTextColor(hdc,RGB(100,100,100)); //设置颜色比前一半字符串黑色更深
			for(i=strlen(str)/2;i<strlen(str);i+=2){ //输出后一半的文字
			 hF_black=CreateFont(		 	//创建自定义字体
      height,			//字体的高度
	  10,		//由系统根据高宽比选取字体最佳宽度值
	  0,			//文本的倾斜度为0,表示水平
	  0,			//字体的倾斜度为0
	  FW_HEAVY,		//字体的粗度,FW_HEAVY为最粗
	  0,			//非斜体字
	  0,			//无下划线
	  0,			//无删除线
	  ANSI_CHARSET,	//表示所用的字符集为ANSI_CHARSET
	  OUT_DEFAULT_PRECIS,		//输出精度为缺省精度
	  CLIP_DEFAULT_PRECIS,		//剪裁精度为缺省精度
	  DEFAULT_QUALITY,		//输出质量为缺省值
	  DEFAULT_PITCH|FF_DONTCARE,//字间距和字体系列使用缺省值
	  "粗体字" );
				SelectObject(hdc,hF_black);
			    TextOut(hdc,x,y,&str[i],2);
				GetTextMetrics(hdc,&tm); 
				x+=tm.tmAveCharWidth*2;
				height-=4; //道理与第一个文字输出一样,不再解释
				y+=2;
			}
			//画第四个“欲穷千里目。。”
			y=temp+40;
			x=0;
			height=14; //高度从14开始
			temp=y;
			SetTextColor(hdc,RGB(0,0,0)); //恢复黑色
            for(i=0;i<strlen(str);i+=2){
			         hF_black=CreateFont(		 	//创建自定义字体
      height,			//字体的高度
	  10,		//由系统根据高宽比选取字体最佳宽度值
	  0,			//文本的倾斜度为0,表示水平
	  0,			//字体的倾斜度为0
	  FW_HEAVY,		//字体的粗度,FW_HEAVY为最粗
	  0,			//非斜体字
	  0,			//无下划线
	  0,			//无删除线
	  ANSI_CHARSET,	//表示所用的字符集为ANSI_CHARSET
	  OUT_DEFAULT_PRECIS,		//输出精度为缺省精度
	  CLIP_DEFAULT_PRECIS,		//剪裁精度为缺省精度
	  DEFAULT_QUALITY,		//输出质量为缺省值
	  DEFAULT_PITCH|FF_DONTCARE,//字间距和字体系列使用缺省值
	  "粗体字" );
				SelectObject(hdc,hF_black);
			    TextOut(hdc,x,y,&str[i],2);
				GetTextMetrics(hdc,&tm); 
				x+=tm.tmAveCharWidth*2;
				height+=4; //同第二个文字的输出
				y-=2;
			}
			//画正弦曲线
			 hF_black=CreateFont(		 	//创建自定义字体
      20,			//字体的高度
	  10,		//由系统根据高宽比选取字体最佳宽度值
	  0,			//文本的倾斜度为0,表示水平
	  0,			//字体的倾斜度为0
	  FW_HEAVY,		//字体的粗度,FW_HEAVY为最粗
	  0,			//非斜体字
	  0,			//无下划线
	  0,			//无删除线
	  ANSI_CHARSET,	//表示所用的字符集为ANSI_CHARSET
	  OUT_DEFAULT_PRECIS,		//输出精度为缺省精度
	  CLIP_DEFAULT_PRECIS,		//剪裁精度为缺省精度
	  DEFAULT_QUALITY,		//输出质量为缺省值
	  DEFAULT_PITCH|FF_DONTCARE,//字间距和字体系列使用缺省值
	  "粗体字" );
            SelectObject(hdc,hF_black);
			y=temp-20; //适当的拉近第四个文字与正弦曲线的高度差
			x=5;
			for(i=0;i<strlen(str);i+=2){ //取正弦曲线上点的坐标
				locate[i].x=x;
				locate[i].y=y+30*cos(x);
				x+=tm.tmAveCharWidth*2;
			}	
			color=0; //初始化color
			for(i=0;i<strlen(str);i+=2){
				//RGB参数的值都变小,使趋近于0
			    SetTextColor(hdc,RGB(100-color,100-color,100-color)); 
				TextOut(hdc,locate[i].x,y+locate[i].y,&str[i],2);
				color+=5;  //使颜色逐渐变黑
			}
			//画余弦曲线
			y=y+50;
			x=5;
			SetTextColor(hdc,RGB(0,0,0)); //恢复为黑色
			for(i=0;i<strlen(str);i+=2){ //取余弦曲线上点的坐标
				locate[i].x=x;
				locate[i].y=y+30*sin(x);
				x+=tm.tmAveCharWidth*2;
			}	
            	for(i=0;i<strlen(str);i+=2)
				TextOut(hdc,locate[i].x,y+locate[i].y,&str[i],2);
			//画半圆
			Get_pointhalf_circle(); //获取坐标,存于locate数组中
			height=20;//初始化高度
			SetTextColor(hdc,RGB(100,100,100)); //浅黑色
			for(i=0;i<strlen(str);i+=2){
				 hF_black=CreateFont(		 	//创建自定义字体
      height,			//字体的高度
	  10,		//由系统根据高宽比选取字体最佳宽度值
	  0,			//文本的倾斜度为0,表示水平
	  0,			//字体的倾斜度为0
	  FW_HEAVY,		//字体的粗度,FW_HEAVY为最粗
	  0,			//非斜体字
	  0,			//无下划线
	  0,			//无删除线
	  ANSI_CHARSET,	//表示所用的字符集为ANSI_CHARSET
	  OUT_DEFAULT_PRECIS,		//输出精度为缺省精度
	  CLIP_DEFAULT_PRECIS,		//剪裁精度为缺省精度
	  DEFAULT_QUALITY,		//输出质量为缺省值
	  DEFAULT_PITCH|FF_DONTCARE,//字间距和字体系列使用缺省值
	  "粗体字" );
			    SelectObject(hdc,hF_black);
				TextOut(hdc,locate[i].x,locate[i].y,&str[i],2);
				height-=1;  //高度逐渐变小
			}
			//画圆
			Get_pointcircle(); //取圆上点的坐标
			hF_black=CreateFont(		 	//创建自定义字体
      20,			//字体的高度
	  10,		//由系统根据高宽比选取字体最佳宽度值
	  0,			//文本的倾斜度为0,表示水平
	  0,			//字体的倾斜度为0
	  FW_HEAVY,		//字体的粗度,FW_HEAVY为最粗
	  0,			//非斜体字
	  0,			//无下划线
	  0,			//无删除线
	  ANSI_CHARSET,	//表示所用的字符集为ANSI_CHARSET
	  OUT_DEFAULT_PRECIS,		//输出精度为缺省精度
	  CLIP_DEFAULT_PRECIS,		//剪裁精度为缺省精度
	  DEFAULT_QUALITY,		//输出质量为缺省值
	  DEFAULT_PITCH|FF_DONTCARE,//字间距和字体系列使用缺省值
	  "粗体字" );
            SelectObject(hdc,hF_black);
			color=0; //初始化
			for(i=0;i<strlen(str);i+=2){
				SetTextColor(hdc,RGB(100-color,100-color,100-color)); 
				TextOut(hdc,locate[i].x,locate[i].y,&str[i],2);
				color+=5; 颜色逐渐变深
			}
		    //
			EndPaint(hWnd, &ps);
			break;
		case WM_DESTROY:
			PostQuitMessage(0);
			break;
		default:
			return DefWindowProc(hWnd, message, wParam, lParam);
   }
   return 0;
}

// Mesage handler for about box.
LRESULT CALLBACK About(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
	switch (message)
	{
		case WM_INITDIALOG:
				return TRUE;

		case WM_COMMAND:
			if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL) 
			{
				EndDialog(hDlg, LOWORD(wParam));
				return TRUE;
			}
			break;
	}
    return FALSE;
}

作业4:位图移动程序(显示一个位图,按鼠标左键或键盘上键可以向上移动位图,按鼠标右键或键盘下键可以向下移动位图)

API代码:

// duhao.cpp : Defines the entry point for the application.
//

#include "stdafx.h"
#include "resource.h"

#define MAX_LOADSTRING 100

// Global Variables:
HINSTANCE hInst;								// current instance
TCHAR szTitle[MAX_LOADSTRING];								// The title bar text
TCHAR szWindowClass[MAX_LOADSTRING];								// The title bar text
//
char topstr[20]="不能再向上移动了";
char bottomstr[20]="不能再向下移动了";
const int movdis=10; //每次移动的距离
bool flagtop; //标记是否已经到顶部了
bool flagbottom; //标记是否已经到底部了
//
// Foward declarations of functions included in this code module:
ATOM				MyRegisterClass(HINSTANCE hInstance);
BOOL				InitInstance(HINSTANCE, int);
LRESULT CALLBACK	WndProc(HWND, UINT, WPARAM, LPARAM);
LRESULT CALLBACK	About(HWND, UINT, WPARAM, LPARAM);

int APIENTRY WinMain(HINSTANCE hInstance,
                     HINSTANCE hPrevInstance,
                     LPSTR     lpCmdLine,
                     int       nCmdShow)
{
 	// TODO: Place code here.
	MSG msg;
	HACCEL hAccelTable;

	// Initialize global strings
	LoadString(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING);
	LoadString(hInstance, IDC_DUHAO, szWindowClass, MAX_LOADSTRING);
	MyRegisterClass(hInstance);

	// Perform application initialization:
	if (!InitInstance (hInstance, nCmdShow)) 
	{
		return FALSE;
	}

	hAccelTable = LoadAccelerators(hInstance, (LPCTSTR)IDC_DUHAO);

	// Main message loop:
	while (GetMessage(&msg, NULL, 0, 0)) 
	{
		if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg)) 
		{
			TranslateMessage(&msg);
			DispatchMessage(&msg);
		}
	}

	return msg.wParam;
}



//
//  FUNCTION: MyRegisterClass()
//
//  PURPOSE: Registers the window class.
//
//  COMMENTS:
//
//    This function and its usage is only necessary if you want this code
//    to be compatible with Win32 systems prior to the 'RegisterClassEx'
//    function that was added to Windows 95. It is important to call this function
//    so that the application will get 'well formed' small icons associated
//    with it.
//
ATOM MyRegisterClass(HINSTANCE hInstance)
{
	WNDCLASSEX wcex;

	wcex.cbSize = sizeof(WNDCLASSEX); 

	wcex.style			= CS_HREDRAW | CS_VREDRAW;
	wcex.lpfnWndProc	= (WNDPROC)WndProc;
	wcex.cbClsExtra		= 0;
	wcex.cbWndExtra		= 0;
	wcex.hInstance		= hInstance;
	wcex.hIcon			= LoadIcon(hInstance, (LPCTSTR)IDI_DUHAO);
	wcex.hCursor		= LoadCursor(NULL, IDC_ARROW);
	wcex.hbrBackground	= (HBRUSH)(COLOR_WINDOW+1);
	wcex.lpszMenuName	= (LPCSTR)IDC_DUHAO;
	wcex.lpszClassName	= szWindowClass;
	wcex.hIconSm		= LoadIcon(wcex.hInstance, (LPCTSTR)IDI_SMALL);

	return RegisterClassEx(&wcex);
}

//
//   FUNCTION: InitInstance(HANDLE, int)
//
//   PURPOSE: Saves instance handle and creates main window
//
//   COMMENTS:
//
//        In this function, we save the instance handle in a global variable and
//        create and display the main program window.
//
BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
{
   HWND hWnd;

   hInst = hInstance; // Store instance handle in our global variable

   hWnd = CreateWindow(szWindowClass, szTitle, WS_OVERLAPPEDWINDOW,
      CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, NULL, NULL, hInstance, NULL);

   if (!hWnd)
   {
      return FALSE;
   }

   ShowWindow(hWnd, nCmdShow);
   UpdateWindow(hWnd);

   return TRUE;
}

//
//  FUNCTION: WndProc(HWND, unsigned, WORD, LONG)
//
//  PURPOSE:  Processes messages for the main window.
//
//  WM_COMMAND	- process the application menu
//  WM_PAINT	- Paint the main window
//  WM_DESTROY	- post a quit message and return
//
//
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
	PAINTSTRUCT ps;
	HDC hDC;
	int wmId, wmEvent;
	static int High; //设置静态局部变量High,记录位图在当前各户区中显示的基点高度
	static HDC hMemDC;//定义内存设备环境句柄
	static HBITMAP hBitmap;//定义位图句柄
	static BITMAP bitmap;//定义BITMAP结构对象
	RECT clientRect;
	switch (message) 
	{
		case WM_COMMAND:
			wmId    = LOWORD(wParam); 
			wmEvent = HIWORD(wParam); 
			// Parse the menu selections:
			switch (wmId)
			{
				case IDM_ABOUT:
				   DialogBox(hInst, (LPCTSTR)IDD_ABOUTBOX, hWnd, (DLGPROC)About);
				   break;
				case IDM_EXIT:
				   DestroyWindow(hWnd);
				   break;
				default:
				   return DefWindowProc(hWnd, message, wParam, lParam);
			}
			break;
		case WM_CREATE:
			hDC=GetDC(hWnd); //获取设备环境表句柄
			hMemDC=CreateCompatibleDC(hDC);//获取内存设备环境表句柄
			hBitmap=LoadBitmap(hInst,MAKEINTRESOURCE(IDB_BITMAP1));//加载位图并获得位图的句柄
			SelectObject(hMemDC,hBitmap);//将位图选入设别内存环境中
			GetObject(hBitmap,sizeof(BITMAP),&bitmap);//获取位图对象的信息,并将其写入bitmap中
			//
			GetClientRect(hWnd, &clientRect); //获取指定窗口客户区的大小,将其写入clientRect中
			High=(clientRect.bottom-clientRect.top)/4;//初始化High为客户区高度的1/4
			flagtop=1; //初始化为1,开始没有到达顶部
			flagbottom=1; //初始化为1,开始没有达到底部
			//
			ReleaseDC(hWnd,hDC);
			
			break;
		case WM_LBUTTONDOWN: //按下左键
			GetClientRect(hWnd, &clientRect); //获取当前客户区的大小
			if(High-movdis>=clientRect.top){ //若向上移动后,高度值大于或等于当前客户区的顶部高度值
				//则说明可以向上移动,并同时置flagbottom为1(若上次已经达到了底部并输出了提示信息
				//则这次应该改变flagbottom标记,将其置为1,即这次没有到达底部了)
				flagbottom=1;
				High-=movdis; //高度值减movdis
			}
			else //否则到达了顶部,设置flagtop为0
				flagtop=0;
			InvalidateRect(hWnd,NULL,true); //刷新
			break;
		case  WM_RBUTTONDOWN: //按下右键
				GetClientRect(hWnd, &clientRect);
				if(High+movdis<=(clientRect.bottom+clientRect.top)/2){//若向下移动后,高度值还没有到达最大值,
					//即刚好将位图按尺寸为客户区的1/4显示时,所能达到的最大高度值
				//则说明可以向下移动,并同时置flagtop为1(若上次已经达到了顶部并输出了提示信息
				//则这次应该改变flagtop标记,将其置为1,即这次没有到达顶部了)
					flagtop=1;
					High+=movdis;//高度值减movdis
				}
				else //否则到达了底部,设置flagbottom为0
					flagbottom=0; 
			    InvalidateRect(hWnd,NULL,true); //刷新
		   	    break;
		case  WM_KEYDOWN: //处理按键消息
			{
				switch(wParam){
				case VK_UP: //若为向上键,则处理与按左键一样
			GetClientRect(hWnd, &clientRect);
			if(High-movdis>=clientRect.top){
				flagtop=flagbottom=1;
				High-=movdis;
			}
			else 
				flagtop=0;
			InvalidateRect(hWnd,NULL,true);
			break;
				case VK_DOWN: //若为向下键,则处理与按右键一样
             	GetClientRect(hWnd, &clientRect);
				if(High+movdis<=(clientRect.bottom+clientRect.top)/2){
					flagtop=flagbottom=1;
					High+=movdis;
				}
				else
					flagbottom=0;
			    InvalidateRect(hWnd,NULL,true);
		   	    break;
				}
			}
		case WM_PAINT:
			hDC = BeginPaint(hWnd, &ps);
			//
			GetClientRect(hWnd, &clientRect);
			if(!flagtop) //若已经到达了各户区顶部,则输出相应信息
					TextOut(hDC,20,20,topstr,strlen(topstr));
			if(!flagbottom) //若已经达到了客户区底部,则输出相应信息
				    TextOut(hDC,20,20,bottomstr,strlen(bottomstr));
				StretchBlt(hDC,(clientRect.right-clientRect.left)/4, //显示位图
					High,(clientRect.right-clientRect.left)/2,
					(clientRect.bottom-clientRect.top)/2,hMemDC,0,0,
					bitmap.bmWidth,bitmap.bmHeight,SRCCOPY);
			EndPaint(hWnd, &ps);
			break;
		case WM_DESTROY:
			DeleteObject(hBitmap);
			ReleaseDC(hWnd,hMemDC);

			PostQuitMessage(0);
			break;
		default:
			return DefWindowProc(hWnd, message, wParam, lParam);
   }
   return 0;
}

LRESULT CALLBACK About(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
	switch (message)
	{
		case WM_INITDIALOG:
				return TRUE;

		case WM_COMMAND:
			if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL) 
			{
				EndDialog(hDlg, LOWORD(wParam));
				return TRUE;
			}
			break;
	}
    return FALSE;
}


 

 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值