写在最前的废话:这次题目不是很难,希望大家能够不要直接滑到最下面抄源码,而是仔细看看我的解题思路。虽然这篇代码没有很长但是这次真的有很仔细在分析。
读题:重点如下:
1)圆形到达终点后自动往返
2)点击鼠标左键,暂停,再点击左键继续播放
3)点击鼠标右键反向
原程序我忘记备份一份了,所以这边就不贴原程序的代码了直接讲
原程序决定圆形移动的参数是i,利用i++进行圆形移动;
我们知道i++是i+=1;也就是i=i+1;的缩写。原程序让圆形顺着走,那我们只需要让i=i-1就可以倒着走了。这样1)和3)就可以很简单地解决了,同理,让i=i,就可以实现2了;
根据以上分析,我们能看出,有三种情况:顺着走、停止和倒着走,他们分别是i+=1,i+=-1和i+=0;
也就是说,+=运算符的右边根据操作的不同会有三种情况,所以我们只需再定义一个int类型的变量(我命名为numn),在不同的情况下给他赋予不同的值就能解决这道题。
1)每当圆形到达起点和终点时分别令numn为1和-1:
if (i == 99)
numn = -1;
if (i == 0)
numn = 1;
2)当按下鼠标左键时暂停,再次按下时沿着原本的方向继续:
这边我们需要再引入一个变量记录圆形移动原本的方向,在每次numn置1或置-1时与numn同步:
case WM_LBUTTONDOWN:
{
if (numn == 0 && sup == 1)numn = 1;
else if (numn == 0 && sup == -1)numn = -1;
else if(numn == 1 || numn == -1)numn = 0;
break;
}
3)当按下鼠标右键时改变numn:
case WM_RBUTTONDOWN:
{
numn = -numn; sup = numn;
break;
}
于是就完成了
完整代码如下:
#include "framework.h"
#include "WindowsProject3.h"
#include <stdlib.h>
#include <string.h>
#include <math.h>
#define Pi 3.1415926
#define MAX_LOADSTRING 100
// 全局变量:
HINSTANCE hInst; // 当前实例
WCHAR szTitle[MAX_LOADSTRING]; // 标题栏文本
WCHAR szWindowClass[MAX_LOADSTRING]; // 主窗口类名
double dfTheta = 0, dfRange = 100.0; //正弦曲线的角度变量.
long i = 0, j = 0;
long lCentreX = 0, lCentreY = 0, lRadious = (long)(0.2 * dfRange);
//定义圆心坐标和圆坐标.
POINT lpSin[100]; //定义正弦曲线的点坐标.
//POINT NNN[100];
// 此代码模块中包含的函数的前向声明:
ATOM MyRegisterClass(HINSTANCE hInstance);
BOOL InitInstance(HINSTANCE, int);
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
INT_PTR CALLBACK About(HWND, UINT, WPARAM, LPARAM);
int APIENTRY wWinMain(_In_ HINSTANCE hInstance,
_In_opt_ HINSTANCE hPrevInstance,
_In_ LPWSTR lpCmdLine,
_In_ int nCmdShow)
{
UNREFERENCED_PARAMETER(hPrevInstance);
UNREFERENCED_PARAMETER(lpCmdLine);
// TODO: 在此处放置代码。
// 初始化全局字符串
LoadStringW(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING);
LoadStringW(hInstance, IDC_WINDOWSPROJECT3, szWindowClass, MAX_LOADSTRING);
MyRegisterClass(hInstance);
// 执行应用程序初始化:
if (!InitInstance(hInstance, nCmdShow))
{
return FALSE;
}
HACCEL hAccelTable = LoadAccelerators(hInstance, MAKEINTRESOURCE(IDC_WINDOWSPROJECT3));
MSG msg;
for (int j = 0; j < 100; j++) //生成正弦曲线的点坐标.
{
lpSin[j].x = (long)(j * 2 * Pi / 100 * 60);
lpSin[j].y = (long)(dfRange * sin(j * 2 * Pi / 100));
}
// 主消息循环:
while (GetMessage(&msg, nullptr, 0, 0))
{
if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
return (int)msg.wParam;
}
//
// 函数: MyRegisterClass()
//
// 目标: 注册窗口类。
//
ATOM MyRegisterClass(HINSTANCE hInstance)
{
WNDCLASSEXW wcex;
wcex.cbSize = sizeof(WNDCLASSEX);
wcex.style = CS_HREDRAW | CS_VREDRAW;
wcex.lpfnWndProc = WndProc;
wcex.cbClsExtra = 0;
wcex.cbWndExtra = 0;
wcex.hInstance = hInstance;
wcex.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_WINDOWSPROJECT3));
wcex.hCursor = LoadCursor(nullptr, IDC_ARROW);
wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
wcex.lpszMenuName = MAKEINTRESOURCEW(IDC_WINDOWSPROJECT3);
wcex.lpszClassName = szWindowClass;
wcex.hIconSm = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_SMALL));
return RegisterClassExW(&wcex);
}
//
// 函数: InitInstance(HINSTANCE, int)
//
// 目标: 保存实例句柄并创建主窗口
//
// 注释:
//
// 在此函数中,我们在全局变量中保存实例句柄并
// 创建和显示主程序窗口。
//
BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
{
hInst = hInstance; // 将实例句柄存储在全局变量中
HWND hWnd = CreateWindowW(szWindowClass, szTitle, WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, nullptr, nullptr, hInstance, nullptr);
if (!hWnd)
{
return FALSE;
}
ShowWindow(hWnd, nCmdShow);
UpdateWindow(hWnd);
return TRUE;
}
int numn = 1,sup=1;
//
// 函数: WndProc(HWND, UINT, WPARAM, LPARAM)
//
// 目标: 处理主窗口的消息。
//
// WM_COMMAND - 处理应用程序菜单
// WM_PAINT - 绘制主窗口
// WM_DESTROY - 发送退出消息并返回
//
//
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
PAINTSTRUCT ps;
HDC hdc;
HBRUSH hBrush; //定义画刷句柄
HPEN hPen; //定义画笔句柄
switch (message)
{
case WM_RBUTTONDOWN:
{
numn = -numn; sup = numn;
break;
}
case WM_LBUTTONDOWN:
{
if (numn == 0 && sup == 1)numn = 1;
else if (numn == 0 && sup == -1)numn = -1;
else if(numn == 1 || numn == -1)numn = 0;
break;
}
// 其他消息处理代码...
case WM_COMMAND:
{
int wmId = LOWORD(wParam);
// 分析菜单选择:
switch (wmId)
{
case IDM_ABOUT:
DialogBox(hInst, MAKEINTRESOURCE(IDD_ABOUTBOX), hWnd, About);
break;
case IDM_EXIT:
DestroyWindow(hWnd);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
}
break;
case WM_PAINT:
{
if (i == 99)
{
numn = -1; sup = -1;
}
if (i == 0)
{
numn = 1; sup = 1;
}
hdc = BeginPaint(hWnd, &ps);
// TODO: 在此处添加使用 hdc 的任何绘图代码...
SetWindowOrgEx(hdc, -200, -200, NULL); //设置原点坐标为(-200,-200).
hPen = CreatePen(PS_DASH, 1, RGB(255, 0, 0)); //创新画笔.
SelectObject(hdc, hPen); //选入画笔.
Polyline(hdc, lpSin, 100); //绘制正弦曲线.
if (i <= 25) //第一个1/4周期.
{
hPen = CreatePen(PS_DASH, 1, RGB(255, 0, 0));//创新红笔.
hBrush = CreateHatchBrush(HS_BDIAGONAL, RGB(255, 0, 0));//创新红画刷.
lRadious = (long)(dfRange * 0.2 + i % 25 * dfRange * 0.4 / 25);//计算半径.
}
else if (i <= 50)//第二个1/4周期.
{
hPen = CreatePen(PS_DASH, 1, RGB(0, 255, 0));//创新绿笔.
hBrush = CreateHatchBrush(HS_DIAGCROSS, RGB(0, 255, 0));//创新绿刷.
lRadious = (long)(dfRange * 0.2 + i % 25 * dfRange * 0.4 / 25);//计算半径.
}
else if (i <= 75)//第三个周期.
{
hPen = CreatePen(PS_DASH, 1, RGB(0, 0, 255));//创新蓝笔
hBrush = CreateHatchBrush(HS_CROSS, RGB(0, 0, 255));//创新蓝刷.
lRadious = (long)(dfRange * 0.2 + i % 25 * dfRange * 0.4 / 25);//计算半径.
}
else//第四个周期.
{
hPen = CreatePen(PS_DASH, 1, RGB(255, 255, 0));//创新黄笔
hBrush = CreateHatchBrush(HS_VERTICAL, RGB(255, 255, 0));//创新黄刷.
lRadious = (long)(dfRange * 0.2 + i % 25 * dfRange * 0.4 / 25);
}
SelectObject(hdc, hBrush); //选入画刷.
SelectObject(hdc, hPen); //选入画笔.
lCentreX = lpSin[i].x; //圆心x坐标.
lCentreY = lpSin[i].y; //圆心y坐标.
Ellipse(hdc, lCentreX - lRadious, lCentreY - lRadious,
lCentreX + lRadious, lCentreY + lRadious); //画圆.
DeleteObject(hPen); //删除画笔.
DeleteObject(hBrush); //删除画刷.
EndPaint(hWnd, &ps);
i+=numn;
Sleep(100); //停0.1秒.
if (i < 100) InvalidateRect(hWnd, NULL, 1); //刷新用户区.
}
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
return 0;
}
// “关于”框的消息处理程序。
INT_PTR CALLBACK About(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
UNREFERENCED_PARAMETER(lParam);
switch (message)
{
case WM_INITDIALOG:
return (INT_PTR)TRUE;
case WM_COMMAND:
if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL)
{
EndDialog(hDlg, LOWORD(wParam));
return (INT_PTR)TRUE;
}
break;
}
return (INT_PTR)FALSE;
}