【问题标题】:C++ Pixels In Console Window控制台窗口中的 C++ 像素
【发布时间】:2012-09-04 21:51:22
【问题描述】:

在使用 Code::Blocks v10.05 的 C++ 中,如何在控制台屏幕上绘制单个像素?这很容易吗,还是只画一个矩形会更容易?如何给它上色?

很抱歉,我无法从 SOF、HF 甚至 cplusplus.com 获取任何代码来工作。这是屏幕上的超级马里奥世界人物。我认为是16位的游戏,适用于SNES系统。 C::B 说我需要 C::B 的 SDK。它说“afxwin.h”不存在。可以下载吗?

这就是我想要做的:

【问题讨论】:

  • 你能链接到你无法工作的代码吗?
  • 哇,这让我回想起...人们过去常常在 DOS 中这样做。您必须跳入存储字符集的内存并对其进行更改(DOS 中几乎所有内容的常见做法,包括在其他图形模式下将字节写入视频卡),然后使用修改后的字符绘制您的精灵。显然,您被限制为 256 个可能的子图像。我不知道这是否仍然是 Windows 中发生的情况。无法给出答案,抱歉,只能说控制台窗口只是另一个窗口。我想知道你是否可以挂钩它的 WM_PAINT 消息。
  • 或者最好在此处显示代码而不是在链接中(它将消失)
  • 控制台的全部意义在于不做图形......
  • 仅供参考,控制台窗口部分由 CSRSS 管理,因此即使您尝试通过 GetDC 等破解它,它也可能不允许您执行此操作。

标签: c++ console codeblocks pixel


【解决方案1】:

这取决于您的操作系统。我假设你是在 Windows 平台上编程,因此你可以使用SetPixel,但你必须使用“windows.h”来获取控制台句柄,所以这里是一个绘制 cos() 函数的示例:

#include<windows.h>
#include<iostream>
#include <cmath>

using namespace std;

#define PI 3.14

int main() 
{
    //Get a console handle
    HWND myconsole = GetConsoleWindow();
    //Get a handle to device context
    HDC mydc = GetDC(myconsole);

    int pixel =0;

    //Choose any color
    COLORREF COLOR= RGB(255,255,255); 

    //Draw pixels
    for(double i = 0; i < PI * 4; i += 0.05)
    {
        SetPixel(mydc,pixel,(int)(50+25*cos(i)),COLOR);
        pixel+=1;
    }

    ReleaseDC(myconsole, mydc);
    cin.ignore();
    return 0;
}

您还可以使用其他一些库,例如:conio.h allegro.h sdl 等。

【讨论】:

  • Gross :D 但 +1 表示“解决方案”。请注意,您不会处理WM_PAINT,因此如果该区域变得无效,它将被删除。普通窗口比这个更受青睐。
  • Code::Blocks 错误:此解决方案中未声明“GetConsoleWindow”。
  • @Mike 你是否包含了“windows.h”标题?记住你必须从微软那里得到它。必须下载microsoft sdk:microsoft.com/en-us/download/details.aspx?id=3138
  • 所以我必须使用微软的那个,或者我可以使用 code::blocks 附带的那个吗?
  • 对不起?如果您参考 SDK,是的,您必须使用 microsoft。另一方面,我说您可以使用其他库,例如:conio.h allegro.h sdl 等。在 linux 中,您可以使用 ncurses 或 svgalib.org...
【解决方案2】:

如果您愿意让图像看起来像块状,您可以利用 console code page 中的块状字符。

  • = '\xDB' = U+2588 完整块
  • = '\xDC' = U+2584 下半块
  • = '\xDF' = U+2580 上半部分
  • 和空间

通过将半块与colored text结合使用,您可以将一个80×25的控制台窗口变成一个80×50的16色显示器。 (这是Nibbles的QBasic版本使用的方法。)

然后,您只需要将图像转换为 16 色调色板和相当小的尺寸。

【讨论】:

  • 我在高中时使用这种技术在 Commodore 64 上制作了一个 80x50 16 色显示器,作为一个科学展览项目。我在 BASIC 中添加了用于绘制像素和线条的新命令。美好时光。 :-)
【解决方案3】:

windows.h 提供了一个函数SetPixel() 在窗口的指定位置打印一个像素。函数的一般形式是

SetPixel(HDC hdc, int x, int y, COLORREF& color);

其中,x和y是要显示的像素坐标,color是像素的颜色。

重要提示:要使用 Code::blocks IDE 打印机器中的像素,请在链接器设置中添加链接库 libgdi32.a(通常在 MinGW\lib 内)。

【讨论】:

    【解决方案4】:

    控制台是一种文本设备,因此通常您不会写入单个像素。您可以创建一种特殊字体并将其选择为控制台字体,但它将是单色的。有一些库可以简化控制台 UI 的编写(例如 Curses),但我相信除了显示一个 sprite 之外,您还有更多类似游戏的功能。

    如果您想编写游戏,我建议您查看一些图形/游戏框架/库,例如SDL

    【讨论】:

    • 那么我应该在窗口中显示精灵/图像吗?如果是这样,我该怎么做?
    • 你需要这样做吗?对于学校来说,自己做所有的像素修改代码很重要,还是你对结果更感兴趣?如果是前者,您使用什么环境(Win、Linux 等 - 我猜是 Windows,基于 afxwin.h)?如果是后者,这里有一个教程:libsdl.org/intro.en/usingvideo.html
    【解决方案5】:

    我在 code::blocks 中使用 windows.h 绘制了直线。我无法详细解释,但我可以为您提供代码和过程以在 code::blocks 中编译它。

    1. 进入设置菜单并选择编译器和调试器。
    2. 单击链接器选项卡并添加链接库 libgdi32.a,它位于 C:\Program Files\CodeBlocks\MinGW\lib 目录。

    现在编译这个程序

    #include <windows.h>
    
    #include <cmath>
    
    #define ROUND(a) ((int) (a + 0.5))
    
    /* set window handle */
    
    static HWND sHwnd;
    
    static COLORREF redColor=RGB(255,0,0);
    
    static COLORREF blueColor=RGB(0,0,255);
    
    static COLORREF greenColor=RGB(0,255,0);
    
    
    void SetWindowHandle(HWND hwnd){
    
    sHwnd=hwnd;
    
    }
    
    /* SetPixel */
    
    void setPixel(int x,int y,COLORREF& color=redColor){
    
    if(sHwnd==NULL){
    
        MessageBox(NULL,"sHwnd was not initialized !","Error",MB_OK|MB_ICONERROR);
    
        exit(0);
    
    }
    
    HDC hdc=GetDC(sHwnd);
    
    SetPixel(hdc,x,y,color);
    
    ReleaseDC(sHwnd,hdc);
    
    return;
    
    // NEVERREACH //
    
    }
    
    
    void drawLineDDA(int xa, int ya, int xb, int yb){
    
       int dx = xb - xa, dy = yb - ya, steps, k;
    
       float xIncrement, yIncrement, x = xa, y = ya;
    
       if(abs(dx) > abs(dy)) steps = abs(dx);
    
       else steps = abs(dy);
    
       xIncrement = dx / (float) steps;
    
       yIncrement = dy / (float) steps;
    
       setPixel(ROUND(x), ROUND(y));
    
       for(int k = 0; k < steps; k++){
    
        x += xIncrement;
    
        y += yIncrement;
    
        setPixel(x, y);
    
     }
    
    }
    
    /* Window Procedure WndProc */
    
    LRESULT CALLBACK WndProc(HWND hwnd,UINT message,WPARAM wParam,LPARAM lParam){
    
     switch(message){
    
        case WM_PAINT:
    
            SetWindowHandle(hwnd);
    
            drawLineDDA(10, 20, 250, 300);
    
            break;
    
        case WM_CLOSE: // FAIL THROUGH to call DefWindowProc
    
            break;
    
        case WM_DESTROY:
    
            PostQuitMessage(0);
    
            return 0;
    
        default:
    
        break; // FAIL to call DefWindowProc //
    
      }
    
     return DefWindowProc(hwnd,message,wParam,lParam);
    
    }
    
    int WINAPI WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPSTR lpCmdLine,int      iCmdShow){
    
    static TCHAR szAppName[] = TEXT("Straight Line");
    
    WNDCLASS wndclass;
    
    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 = szAppName ;
    
    // Register the window //
    
    if(!RegisterClass(&wndclass)){
    
        MessageBox(NULL,"Registering the class failled","Error",MB_OK|MB_ICONERROR);
    
        exit(0);
    
    }
    
    // CreateWindow //
    
    HWND hwnd=CreateWindow(szAppName,"DDA - Programming Techniques",
    
                WS_OVERLAPPEDWINDOW,
    
                 CW_USEDEFAULT,
    
                 CW_USEDEFAULT,
    
                 CW_USEDEFAULT,
    
                 CW_USEDEFAULT,
    
                 NULL,
    
                 NULL,
    
                 hInstance,
    
                 NULL);
    
    if(!hwnd){
    
        MessageBox(NULL,"Window Creation Failed!","Error",MB_OK);
    
        exit(0);
    
      }
    
      // ShowWindow and UpdateWindow //
    
      ShowWindow(hwnd,iCmdShow);
    
     UpdateWindow(hwnd);
    
     // Message Loop //
    
     MSG msg;
    
     while(GetMessage(&msg,NULL,0,0)){
    
        TranslateMessage(&msg);
    
        DispatchMessage(&msg);
    
     }
    
      /* return no error to the operating system */
    
      return 0;
    
    }
    

    在这个程序中,我使用了 DDA 画线算法。像素绘制任务由 setPixel(ROUND(x), ROUND(y)) 函数完成。 这是windows编程,你可以了解详情here

    【讨论】:

      【解决方案6】:

      要在 CodeBlocks 中使用,我发现了这个(您必须添加链接器选项 -lgdi32):

      //Code Blocks: Project Build Options Linker settings Othoer linker options: add -lgdi32
      

      我忘记了:你必须把这个放在包括windows.h之前:

      #define _WIN32_WINNT 0x0500
      

      又是整个余弦码。准备编译:

      //Code Blocks: Project Build Options Linker settings Othoer linker options: add -lgdi32
      #define _WIN32_WINNT 0x0500
      #include "windows.h"
      #include <iostream>
      #include <cmath>
      using namespace std;
      
      #define PI 3.14
      
      int main(){
          HWND myconsole = GetConsoleWindow();
          HDC mydc = GetDC(myconsole);
          int pixel =0;
          COLORREF COLOR= RGB(255,255,255);
      
          //Draw pixels
          for(double i = 0; i < PI * 4; i += 0.05)
          {
              SetPixel(mydc,pixel,(int)(50+25*cos(i)),COLOR);
              pixel+=1;
          }
      
          ReleaseDC(myconsole, mydc);
          cin.ignore();
          return 0;
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2019-01-18
        • 2014-03-29
        • 1970-01-01
        • 1970-01-01
        • 2014-06-19
        • 2011-04-20
        • 2014-02-17
        相关资源
        最近更新 更多