【问题标题】:WinApi LineTo not refreshing the lineWinApi LineTo 不刷新行
【发布时间】:2017-02-28 19:55:55
【问题描述】:

我刚刚开始学习 C++。我想做的就是画一条线到指定的坐标,它作为方法的输入。我使用MoveToEx 设置每个循环的起点(在具有不同参数的循环中调用此函数)并给出我想要绘制车道的坐标。

任何想法如何让它循环工作?

我的代码类似于:

void Clock::drawSecondLine(float x,float y) {
    HWND console_handle = GetConsoleWindow();
    HDC device_context = GetDC(console_handle);
    HPEN pen = CreatePen(PS_SOLID, 3, RGB(255, 0, 0));
    SelectObject(device_context, pen);

    MoveToEx(device_context, 0, 0, NULL);
    Ellipse(device_context, 400, 0, 0, 400);
    MoveToEx(device_context, 200, 200, NULL);
    LineTo(device_context, (int)x, (int)y);

    ReleaseDC(console_handle, device_context);
    cin.ignore();
}

还有循环:

void Zegar::startClock() {
    while (true) {
        drawSecondLine(laneShowingSecond.getX(), laneShowingSecond.getY());
        laneShowingSecond.movePointByRadius(RADIUS_PER_SECOND);
        Sleep(1000);
        increaseSecond();
    }
}

【问题讨论】:

  • x 和 y 的值是多少?此外,您正在泄漏笔,这意味着您最终会用完 GDI 对象。
  • 我认为您不应该在控制台窗口上绘图...
  • 您应该创建一个 GUI 应用程序。但它适用于控制台窗口(只要您在运行时不“触摸”它)。首先,您可以将任何不依赖于xy 的东西移到方法之外(还有循环——尤其是DC 创建/销毁)。该方法应该只包含LineTo(显然,你不需要一个方法)。此外,您没有检查函数返回代码!!!(这意味着可能出现问题但您认为它正确,这可能会引发无穷无尽的问题,包括崩溃)。
  • 您正在绘制(向后,因为边界矩形 right 尺寸小于其 left 尺寸)一个椭圆xRadius = yRadius = 100,以C(200, 200)为中心,然后从它的中心画一条线到(@ 987654327@, y) (我假设在圈子上)。然后,每一秒你都在画一条线。最终的形状是什么样的?一堆圆半径,还是以圆为界的多边形?

标签: c++ winapi console


【解决方案1】:

这是一些示例代码(我在 VStudio 2k10 中运行)。

注意事项

  • 虽然它被编译为 C++(并且使用了一些 C++ 功能,例如 iostream - 这意味着它不会编译为 C ),它仍然是普通的旧 C
  • 它有很多丑陋的东西和 NO-NO s(比如全局变量、很多定义、CC++ 代码的混合,在控制台窗口上绘图,...)。目标是拥有一个PoC;代码可以稍后清理。
  • 从边界矩形(RECT_* 定义 (400, 0, 0, 400))我正在提取中心坐标,以及 X 上的半径和Y 轴,使用一些简单的数学计算(由于矩形是正方形,2 个半径相等,所以我们遇到 椭圆实际上是圆的特殊情况强>)。
  • nextPoint 函数是您代码中 laneShowingSecond.getX(), laneShowingSecond.getY() 的替换。
  • 只需执行一次(在开始时)的所有内容都放在init 函数中。请注意,如果在初始化期间出现问题,它会以 error () 代码退出,因为它无法绘制。
  • 同样,最后要执行的任何清理工作都放在cleanup 函数中(这里我没有费心检查返回码,因为它反正退出了)。
  • draw 函数包含绘图循环。在每次迭代中:
    • 角度增加INCERMENT_DEG(默认为30°)。
    • 使用一些简单的三角公式计算椭圆上的下一个点。
    • 绘图已执行。
    • 等待ITERATION_SLEEP_TIME 毫秒(我已将其设置为 200 以避免每绘制一条线等待一秒)。
    • 请注意:
      • 它在达到 360° 或 2 * PI 弧度(全天候)后停止,因为一遍又一遍地绘制相同的线没有意义。
      • 逆时针绘制(三角函数中的正角); xOy 原点 (O(0, 0)) 也是屏幕的左上角。
  • 使用我用 cmets 标记的定义,为它们分配各种值,看看绘图如何变化。

main.cpp

#include <iostream>
#define _USE_MATH_DEFINES
#include <math.h>
#include <Windows.h>

#define RECT_LEFT 400  // Modify any of these 4 RECT_* values to get different ellipse shapes.
#define RECT_TOP 0
#define RECT_RIGHT 0
#define RECT_BOT 400

#define ITERATION_SLEEP_TIME 200  // Sleep time while in loop.

#define INCERMENT_DEG 30  // 30 degrees per step; a full circle has 360 (2 * PI  RAD).
#define M_PI_180 M_PI / 180

using std::cout;
using std::endl;

typedef enum {DRAW_RADII, DRAW_POLY} DrawMethod;

const int radiusX = abs(RECT_RIGHT - RECT_LEFT) / 2;
const int radiusY = abs(RECT_BOT - RECT_TOP) / 2;
const int centerX = (RECT_RIGHT + RECT_LEFT) / 2;
const int centerY = (RECT_BOT + RECT_TOP) / 2;

HWND hwnd = NULL;
HDC hdc = NULL;
HPEN hpen = NULL;

DrawMethod meth = DRAW_RADII;  // Modify this to DRAW_POLY to draw a polygon instead of the "bike wheel".

int deg = 0;
double x = 0, y = 0;


void nextPoint(int degree, double *x, double *y) {
    *x = centerX + radiusX * cos(M_PI_180 * degree );
    *y = centerY - radiusY * sin(M_PI_180 * degree);
}

int init() {
    if ((hwnd = GetConsoleWindow()) == NULL) {
        cout << "GetConsoleWindow error: " << GetLastError() << endl;
        return -1;
    }
    if ((hdc = GetDC(hwnd)) == NULL) {
        cout << "GetDC error: " << GetLastError() << endl;
        return -2;
    }
    if ((hpen = CreatePen(PS_SOLID, 3, RGB(255, 0, 0))) == NULL) {
        cout << "CreatePen error: " << GetLastError() << endl;
        return -3;
    }
    SelectObject(hdc, hpen);
    Ellipse(hdc, RECT_LEFT, RECT_TOP, RECT_RIGHT, RECT_BOT);
    nextPoint(deg, &x, &y);
    if (meth == DRAW_RADII) {
        MoveToEx(hdc, centerX, centerY, NULL);
        LineTo(hdc, (int)x, (int)y);
    } else if (meth == DRAW_POLY) {
        MoveToEx(hdc, (int)x, (int)y, NULL);
    }
    return 0;
}

void draw() {
    while (deg < 360) {
        deg += INCERMENT_DEG;
        nextPoint(deg, &x, &y);
        if (meth == DRAW_RADII) {
            MoveToEx(hdc, centerX, centerY, NULL);
            LineTo(hdc, (int)x, (int)y);
        } else if (meth == DRAW_POLY) {
            LineTo(hdc, (int)x, (int)y);
        } else
            break;
        Sleep(ITERATION_SLEEP_TIME);
    }
}

void cleanup() {
    if (hpen) {
        DeleteObject(hpen);
    }
    if (hwnd && hdc) {
        ReleaseDC(hwnd, hdc);
    }
}

int main() {
    if (!init())
        draw();
    cleanup();
    return 0;
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-10-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-01-20
    • 1970-01-01
    • 2012-04-09
    相关资源
    最近更新 更多