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;
}