c++ - 在 Windows 7 或更高版本的 C++ 中使用 GDI+ 的 : How to display points connected by lines on a monitor,?

标签 c++ gdi+

我有以下内容:

程序开始运行:

输入:在 Windows 7(或更高版本)的控制台窗口中,程序要求用户输入代表点的整数:每个点的 y 和 x(二维坐标)。

输出:然后使用这些点的程序应在窗口中(在监视器上)显示点本身以及连接这些点的线。

程序停止运行

所有这些都是用 C++ 编写的,使用代码块和 GDI+。 我的问题是我似乎无法使用 GID+ 将控制台的输入连接到输出,这甚至可能吗?

我是 C++ 新手,尤其是图形方面的新手,之前没有任何编程经验。 在网上环顾四周,除了令人惊讶的低质量和关于该主题的稀缺信息外,GDI+ 是我得出的解决方案。 我想要最简单的解决方案。有什么想法吗?

#include <abrazol.h>

using namespace std;

struct koordinata {
 int x;
 int y;
};


int main(){

vector<koordinata> abrazol;

abrazol = koordinataszamol(); //Ignore this, it calculates with 
//the coordinate points, asks the user for the x and y values
//of the points, returns a struct type (koordinata) of vector.


HDC hd;
int a=0;

for (int i=0; i<abrazol.size()-1; i++){

    Drawpoint(hd,abrazol[i]);
    Drawpoint(hd,abrazol[i+1]);
    OnPaint(hd,abrazol[i],abrazol[i+1]);
    a++;

}

    OnPaint(hd,abrazol[a+1],abrazol[0]);

return 0;

}

abrazol.cpp (h)

#include <windows.h>
#include <objidl.h>
#include <gdiplus.h>
#include <stdio.h>
#include <iostream>
#include <koordinataszamol.h>


#pragma comment (lib,"Gdiplus.lib")


using namespace Gdiplus;

VOID OnPaint(HDC hdc, koordinata pont1, koordinata pont2)
{
   Graphics graphics(hdc);
   Pen      pen(Color(255, 0, 0, 255));
   graphics.DrawLine(&pen, pont1.x, pont1.y, pont2.x, pont2.y);


}

VOID Drawpoint(HDC hdc, koordinata pont){

    Graphics graphics(hdc);
    Pen blackPen(Color(255, 0, 0, 0), 3);
    int width = 2;
    int height = 2;
    graphics.DrawRectangle(&blackPen, pont.x-1, pont.y-1, width, height);

}





LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);

INT WINAPI WinMain(HINSTANCE hInstance, HINSTANCE, PSTR, INT iCmdShow)
{
   HWND                hWnd;
   MSG                 msg;
   WNDCLASS            wndClass;
   GdiplusStartupInput gdiplusStartupInput;
   ULONG_PTR           gdiplusToken;

   // Initialize GDI+.
   GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL);

   wndClass.style          = CS_HREDRAW | CS_VREDRAW;
   wndClass.lpfnWndProc    = WndProc;
   wndClass.cbClsExtra     = 0;
   wndClass.cbWndExtra     = 0;
   wndClass.hInstance      = hInstance;
   wndClass.hIcon          = LoadIcon(NULL, IDI_APPLICATION);
   wndClass.hCursor        = LoadCursor(NULL, IDC_ARROW);
   wndClass.hbrBackground  = (HBRUSH)GetStockObject(WHITE_BRUSH);
   wndClass.lpszMenuName   = NULL;
   wndClass.lpszClassName  = TEXT("GettingStarted");

   RegisterClass(&wndClass);

   hWnd = CreateWindow(
      TEXT("GettingStarted"),   // window class name
      TEXT("Getting Started"),  // window caption
      WS_OVERLAPPEDWINDOW,      // window style
      CW_USEDEFAULT,            // initial x position
      CW_USEDEFAULT,            // initial y position
      CW_USEDEFAULT,            // initial x size
      CW_USEDEFAULT,            // initial y size
      NULL,                     // parent window handle
      NULL,                     // window menu handle
      hInstance,                // program instance handle
      NULL);                    // creation parameters

   ShowWindow(hWnd, iCmdShow);
   UpdateWindow(hWnd);

   while(GetMessage(&msg, NULL, 0, 0))
   {
      TranslateMessage(&msg);
      DispatchMessage(&msg);
   }

   GdiplusShutdown(gdiplusToken);
   return msg.wParam;
}  // WinMain

LRESULT CALLBACK WndProc(HWND hWnd, UINT message,
  WPARAM wParam, LPARAM lParam)
{
   HDC          hdc;
   PAINTSTRUCT  ps;
   switch(message)
   {
   case WM_PAINT:
      hdc = BeginPaint(hWnd, &ps);
      koordinata pont1;
      koordinata pont2;
      OnPaint(hdc,pont1,pont2);
      EndPaint(hWnd, &ps);
      return 0;
   case WM_DESTROY:
      PostQuitMessage(0);
      return 0;
   default:
      return DefWindowProc(hWnd, message, wParam, lParam);
   }
} // WndProc

我怀疑我不能修改 OnPaint 函数的参数,那我应该如何从运行时参数中绘制???

最佳答案

我怀疑您在这种情况下使用 GDI+ 有什么好处。仅使用 GDI 绘图就非常简单。

至于如何在不更改 OnPaint 参数的情况下更改绘图的基本问题,它通常非常简单:您决定将数据存储在某个位置。输入数据后,您将其存储在那里。 OnPaint 从那里检索数据,并将其绘制到屏幕上。

在这种情况下,您可能希望将其设为类似 std::vector<point> 的内容, 其中point是一种包含 x 和 y 坐标的类型。

我大致按照您的描述快速修改了一个程序,让您输入一些点,然后在窗口中绘制它们(使用我周围的窗口类来处理大部分窗口创建、初始化等)。这是一些代码:

#include <iostream>
#include <string>
#include <vector>
#include <windows.h>

struct point {
    int x;
    int y;

    point() = default;
    point(int x, int y) : x(x), y(y) { }

    friend std::istream &operator>>(std::istream &is, point &p) {
        return is >> p.x >> p.y;
    }
};

struct Window {
    virtual void OnPaint(HDC) = 0;

    Window(std::string const &name) : hInstance(GetModuleHandle(NULL)) {      
        wndClass.style = CS_HREDRAW | CS_VREDRAW;
        wndClass.lpfnWndProc = WndProc;
        wndClass.cbClsExtra = 0;
        wndClass.cbWndExtra = 0;
        wndClass.hInstance = hInstance;
        wndClass.hIcon = LoadIcon(NULL, IDI_APPLICATION);
        wndClass.hCursor = LoadCursor(NULL, IDC_ARROW);
        wndClass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
        wndClass.lpszMenuName = NULL;
        wndClass.lpszClassName = name.c_str();
        RegisterClass(&wndClass);

        hWnd = CreateWindow(
            TEXT(name.c_str()),  
            TEXT(name.c_str()),  
            WS_OVERLAPPEDWINDOW, 
            CW_USEDEFAULT,       
            CW_USEDEFAULT,       
            CW_USEDEFAULT,       
            CW_USEDEFAULT,       
            NULL,                
            NULL,                
            hInstance,           
            (PVOID)this);               
    }

    WPARAM operator()() {
        MSG msg;

        ShowWindow(hWnd, SW_SHOWNORMAL);
        UpdateWindow(hWnd);

        while (GetMessage(&msg, NULL, 0, 0)) {
            TranslateMessage(&msg);
            DispatchMessage(&msg);
        }

        return msg.wParam;
    }

private:

    HINSTANCE hInstance;
    HWND hWnd;
    WNDCLASS wndClass;

    static LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) {
        HDC          hdc;
        PAINTSTRUCT  ps;
        static Window *w;

        switch (message) {
            case WM_CREATE:
                w = static_cast<Window *>(((CREATESTRUCT *)lParam)->lpCreateParams);
                break;
            case WM_PAINT:
                hdc = BeginPaint(hWnd, &ps);
                w->OnPaint(hdc);
                EndPaint(hWnd, &ps);
                return 0;
            case WM_DESTROY:
                PostQuitMessage(0);
                return 0;
            default:
                return DefWindowProc(hWnd, message, wParam, lParam);
        }
        return 0;
    }

};

class disp_window : public Window {
    std::vector<point> points;
public:
    disp_window(std::string const &t) : Window(t) { }

    virtual void OnPaint(HDC hDC) {
        if (points.empty())
            return;
        MoveToEx(hDC, points[0].x, points[0].y, nullptr);
        for (int i = 1; i < points.size(); i++)
            LineTo(hDC, points[i].x, points[i].y);
    }

    std::vector<point> &data() { return points; }
};

int main() {
    disp_window w("Getting Started");

    std::cout << "Please enter some points: ";
    point p;
    while (std::cin >> p)
        w.data().push_back(p);

    w();
}

使用 Visual C++,您可以像这样在命令行上编译它:

cl simple_win.cpp user32.lib kernel32.lib gdi32.lib

使用 MinGW,命令行看起来像这样:

g++ -std=c++11 simple_win.cpp -luser32 -l gdi32 -lkernel32

当你运行它时,它会打印出提示,然后你输入点,数字之间用空格(或制表符或回车)分隔:

Please enter some points: 1 1
100 100
100 200
200 300
^Z

(control-Z 只是让它知道输入已经结束)。

然后它会弹出一个这样的窗口:

enter image description here

我可能应该补充一点,这并不是真正最有效的做事方式——只是我在几分钟内拼凑出来的东西。例如,如果你要有很多点,你可能想查找 PolyLine而不是使用 MoveTo/LineTo .我也懒得包含在每个点绘制正方形(或其他任何东西)的代码——将其添加到 disp_window::OnPaint不过应该很简单。

关于c++ - 在 Windows 7 或更高版本的 C++ 中使用 GDI+ 的 : How to display points connected by lines on a monitor,?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33423157/

相关文章:

c++ - 来自位图的 GDI+ C++ 纹理画笔图案

C# winforms : graphics. DrawImage 问题

c++ - 使用字符串操作截断整数?

c++ - 引用对象 vector ?

c# - 使用撤消和重做功能绘制形状和字符串

c++ - 使用 GetHBITMAP() 和 MFC CStatic::SetBitmap() 可能发生内存泄漏

.net - .NET WinForms 应用程序中的圆形渐变

c++ - 使用 GDB 在 Windows 下调试 DLL

c++ - 错误LNK2019和LNK 1120

c++ - 使用 MoveWindow 或 SetWindowPos 时,编辑控件/组合框的窗口大小未正确调整