#include <Windows.h>
#include <string>
#include <vector>
#include <sstream>
// 定义控件ID
#define ID_EDIT_AX 101
#define ID_EDIT_AY 102
#define ID_EDIT_BX 103
#define ID_EDIT_BY 104
#define ID_BUTTON_DRAW 105
#define ID_BUTTON_CLEAR 106
// 存储点坐标的结构体
struct Point {
float x = 0.0f;
float y = 0.0f;
bool valid = false;
};
// 全局变量存储点A和B
Point g_pointA;
Point g_pointB;
// 窗口过程函数
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) {
switch (message) {
case WM_PAINT: {
PAINTSTRUCT ps;
HDC hdc = BeginPaint(hWnd, &ps);
// 获取客户区尺寸
RECT rect;
GetClientRect(hWnd, &rect);
int width = rect.right - rect.left;
int height = rect.bottom - rect.top;
// 设置坐标系原点在左下角
int originX = 50; // 左边距
int originY = height - 50; // 下边距
// 创建白色画笔用于坐标轴
HPEN hAxisPen = CreatePen(PS_SOLID, 2, RGB(255, 255, 255));
HPEN hOldPen = (HPEN)SelectObject(hdc, hAxisPen);
// 绘制X轴(带箭头)
MoveToEx(hdc, originX, originY, NULL);
LineTo(hdc, width - 20, originY); // X轴主线段
// X轴箭头
LineTo(hdc, width - 30, originY - 5);
MoveToEx(hdc, width - 20, originY, NULL);
LineTo(hdc, width - 30, originY + 5);
// 绘制Y轴(带箭头)
MoveToEx(hdc, originX, originY, NULL);
LineTo(hdc, originX, 20); // Y轴主线段
// Y轴箭头
LineTo(hdc, originX - 5, 30);
MoveToEx(hdc, originX, 20, NULL);
LineTo(hdc, originX + 5, 30);
// 创建虚线画笔用于网格线
HPEN hGridPen = CreatePen(PS_DOT, 1, RGB(100, 100, 100));
SelectObject(hdc, hGridPen);
// 绘制网格线(每50像素一条)
for (int x = originX + 50; x < width - 20; x += 50) {
MoveToEx(hdc, x, originY, NULL);
LineTo(hdc, x, 20);
}
for (int y = originY - 50; y > 20; y -= 50) {
MoveToEx(hdc, originX, y, NULL);
LineTo(hdc, width - 20, y);
}
// 恢复原始画笔
SelectObject(hdc, hOldPen);
DeleteObject(hAxisPen);
DeleteObject(hGridPen);
// 设置文本颜色为白色
SetTextColor(hdc, RGB(255, 255, 255));
SetBkColor(hdc, RGB(0, 0, 0)); // 黑色背景
// 绘制刻度标记
for (int i = 1; i <= 10; i++) {
int xPos = originX + i * 50;
int yPos = originY - i * 50;
// X轴刻度
MoveToEx(hdc, xPos, originY - 5, NULL);
LineTo(hdc, xPos, originY + 5);
// Y轴刻度
MoveToEx(hdc, originX - 5, yPos, NULL);
LineTo(hdc, originX + 5, yPos);
// 绘制刻度值
std::wstring label = std::to_wstring(i);
TextOut(hdc, xPos - 5, originY + 10, label.c_str(), label.length());
TextOut(hdc, originX - 25, yPos - 8, label.c_str(), label.length());
}
// 绘制坐标轴标签
TextOut(hdc, width - 15, originY - 15, L"X", 1);
TextOut(hdc, originX - 15, 15, L"Y", 1);
TextOut(hdc, originX - 10, originY + 10, L"0", 1);
// 如果点A和点B有效,绘制它们并连接
if (g_pointA.valid && g_pointB.valid) {
// 转换为屏幕坐标
int screenAx = originX + static_cast<int>(g_pointA.x * 50);
int screenAy = originY - static_cast<int>(g_pointA.y * 50);
int screenBx = originX + static_cast<int>(g_pointB.x * 50);
int screenBy = originY - static_cast<int>(g_pointB.y * 50);
// 创建红色画笔用于直线
HPEN hLinePen = CreatePen(PS_SOLID, 2, RGB(255, 0, 0));
SelectObject(hdc, hLinePen);
// 绘制直线
MoveToEx(hdc, screenAx, screenAy, NULL);
LineTo(hdc, screenBx, screenBy);
// 创建红色实心画笔用于点
HBRUSH hRedBrush = CreateSolidBrush(RGB(255, 0, 0));
HBRUSH hOldBrush = (HBRUSH)SelectObject(hdc, hRedBrush);
// 绘制点A
Ellipse(hdc, screenAx - 5, screenAy - 5, screenAx + 5, screenAy + 5);
TextOut(hdc, screenAx + 10, screenAy - 10, L"A", 1);
// 绘制点B
Ellipse(hdc, screenBx - 5, screenBy - 5, screenBx + 5, screenBy + 5);
TextOut(hdc, screenBx + 10, screenBy - 10, L"B", 1);
// 计算并显示距离
float distance = sqrtf(powf(g_pointB.x - g_pointA.x, 2) + powf(g_pointB.y - g_pointA.y, 2));
std::wstring distText = L"距离: " + std::to_wstring(distance).substr(0, 4);
TextOut(hdc, width - 150, 30, distText.c_str(), distText.length());
// 恢复并删除对象
SelectObject(hdc, hOldBrush);
DeleteObject(hLinePen);
DeleteObject(hRedBrush);
}
EndPaint(hWnd, &ps);
break;
}
case WM_CREATE: {
// 创建输入框和标签
CreateWindow(L"STATIC", L"A点 X:", WS_CHILD | WS_VISIBLE | SS_CENTER,
10, 10, 50, 20, hWnd, NULL, NULL, NULL);
CreateWindow(L"EDIT", L"", WS_CHILD | WS_VISIBLE | WS_BORDER | ES_NUMBER,
65, 10, 50, 20, hWnd, (HMENU)ID_EDIT_AX, NULL, NULL);
CreateWindow(L"STATIC", L"Y:", WS_CHILD | WS_VISIBLE | SS_CENTER,
120, 10, 20, 20, hWnd, NULL, NULL, NULL);
CreateWindow(L"EDIT", L"", WS_CHILD | WS_VISIBLE | WS_BORDER | ES_NUMBER,
145, 10, 50, 20, hWnd, (HMENU)ID_EDIT_AY, NULL, NULL);
CreateWindow(L"STATIC", L"B点 X:", WS_CHILD | WS_VISIBLE | SS_CENTER,
10, 40, 50, 20, hWnd, NULL, NULL, NULL);
CreateWindow(L"EDIT", L"", WS_CHILD | WS_VISIBLE | WS_BORDER | ES_NUMBER,
65, 40, 50, 20, hWnd, (HMENU)ID_EDIT_BX, NULL, NULL);
CreateWindow(L"STATIC", L"Y:", WS_CHILD | WS_VISIBLE | SS_CENTER,
120, 40, 20, 20, hWnd, NULL, NULL, NULL);
CreateWindow(L"EDIT", L"", WS_CHILD | WS_VISIBLE | WS_BORDER | ES_NUMBER,
145, 40, 50, 20, hWnd, (HMENU)ID_EDIT_BY, NULL, NULL);
// 创建按钮
CreateWindow(L"BUTTON", L"绘制", WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON,
210, 10, 80, 25, hWnd, (HMENU)ID_BUTTON_DRAW, NULL, NULL);
CreateWindow(L"BUTTON", L"清除", WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON,
210, 40, 80, 25, hWnd, (HMENU)ID_BUTTON_CLEAR, NULL, NULL);
// 设置默认值
SetDlgItemText(hWnd, ID_EDIT_AX, L"2");
SetDlgItemText(hWnd, ID_EDIT_AY, L"3");
SetDlgItemText(hWnd, ID_EDIT_BX, L"7");
SetDlgItemText(hWnd, ID_EDIT_BY, L"8");
break;
}
case WM_COMMAND: {
int wmId = LOWORD(wParam);
if (wmId == ID_BUTTON_DRAW) {
// 获取输入的坐标值
wchar_t text[32];
GetDlgItemText(hWnd, ID_EDIT_AX, text, 32);
g_pointA.x = _wtof(text);
GetDlgItemText(hWnd, ID_EDIT_AY, text, 32);
g_pointA.y = _wtof(text);
GetDlgItemText(hWnd, ID_EDIT_BX, text, 32);
g_pointB.x = _wtof(text);
GetDlgItemText(hWnd, ID_EDIT_BY, text, 32);
g_pointB.y = _wtof(text);
// 验证坐标是否在有效范围内(0-10)
g_pointA.valid = (g_pointA.x >= 0 && g_pointA.x <= 10 &&
g_pointA.y >= 0 && g_pointA.y <= 10);
g_pointB.valid = (g_pointB.x >= 0 && g_pointB.x <= 10 &&
g_pointB.y >= 0 && g_pointB.y <= 10);
// 重绘窗口
InvalidateRect(hWnd, NULL, TRUE);
}
else if (wmId == ID_BUTTON_CLEAR) {
// 清除点
g_pointA.valid = false;
g_pointB.valid = false;
// 重绘窗口
InvalidateRect(hWnd, NULL, TRUE);
}
break;
}
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
return 0;
}
// 应用程序入口点
int WINAPI wWinMain(
_In_ HINSTANCE hInstance,
_In_opt_ HINSTANCE hPrevInstance,
_In_ LPWSTR lpCmdLine,
_In_ int nCmdShow)
{
// 1. 注册窗口类
const wchar_t CLASS_NAME[] = L"CartesianWindowClass";
WNDCLASSEXW wcex = { sizeof(WNDCLASSEX) };
wcex.style = CS_HREDRAW | CS_VREDRAW;
wcex.lpfnWndProc = WndProc;
wcex.hInstance = hInstance;
wcex.hCursor = LoadCursor(nullptr, IDC_ARROW);
wcex.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH); // 黑色背景
wcex.lpszClassName = CLASS_NAME;
if (!RegisterClassExW(&wcex)) {
MessageBox(NULL, L"窗口类注册失败!", L"错误", MB_ICONERROR);
return 1;
}
// 2. 计算窗口尺寸(包含边框和标题栏)
int clientWidth = 600;
int clientHeight = 600;
RECT rect = { 0, 0, clientWidth, clientHeight };
AdjustWindowRect(&rect, WS_OVERLAPPEDWINDOW, FALSE);
int windowWidth = rect.right - rect.left;
int windowHeight = rect.bottom - rect.top;
// 3. 计算居中位置
int screenWidth = GetSystemMetrics(SM_CXSCREEN);
int screenHeight = GetSystemMetrics(SM_CYSCREEN);
int posX = (screenWidth - windowWidth) / 2;
int posY = (screenHeight - windowHeight) / 2;
// 4. 创建窗口
HWND hWnd = CreateWindowExW(
0, // 无扩展样式
CLASS_NAME,
L"笛卡尔坐标系 - 绘制点A和点B",
WS_OVERLAPPEDWINDOW & ~WS_THICKFRAME & ~WS_MAXIMIZEBOX, // 禁用调整大小和最大化
posX, posY, // 位置
windowWidth, // 宽度
windowHeight, // 高度
nullptr, nullptr, hInstance, nullptr);
if (!hWnd) {
MessageBox(NULL, L"窗口创建失败!", L"错误", MB_ICONERROR);
return 1;
}
// 5. 显示窗口
ShowWindow(hWnd, nCmdShow);
UpdateWindow(hWnd);
// 6. 消息循环
MSG msg;
while (GetMessage(&msg, nullptr, 0, 0)) {
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return (int)msg.wParam;
}
将改代码修改为C语言能运行的代码,功能不变
最新发布