【问题标题】:SetPixel and multiple pixels c++ winapiSetPixel和多个像素c ++ winapi
【发布时间】:2016-10-13 15:03:29
【问题描述】:

所以,我一直在玩 C++ 一段时间,使用各种书籍和网络教程。

现在我来到了图形。目前在 WinApi 中。

我有一个窗口,我可以在其中绘制文本、图像或像素。

但是,使用 SetPixels 绘制大量像素实在是太慢了。

我的代码片段:

void DrawBitmap(RECT rect, string text) {


    HDC buffer = CreateCompatibleDC(device);
    HBITMAP BGimage = CreateCompatibleBitmap(device, rect.right - rect.left, rect.bottom - rect.top);
    SelectObject(buffer, BGimage);

    //Clearing the screen with  a full rect
    Rectangle(buffer, rect.left, rect.top, rect.right, rect.bottom);


    //Sample on making a single pixel at mouseclik, with color 250 on screen.

    SetPixelV(buffer, x, y, 250);


    int PixelSize = 4;



    //SOME HEAVY PIXELS to slow the FPS
    /* 
    for (int i = 0; i < 255; i++) {
        for (int k = 0; k < 255; k++) {
            SetPixelV(buffer, x + i, y + k, COLORREF RGB(150, i, k));
        }
    }
    */



    //Sample on making some text.
    RECT drawRect;
    drawRect = { rect.left + 5, rect.top + 5, rect.left + 105, rect.top + 25 };
    DrawText(buffer, text.c_str(), text.length(), &drawRect, DT_LEFT);


    // counter number to be converted to a string
    int timeint = GetTickCount();
    ostringstream convert;   // stream used for the conversion
    convert << "TIME: " << timeint;      // insert the textual representation of 'Number' in the characters in the stream
    text = convert.str();
    drawRect = { rect.left + 5, rect.top + 25, rect.left + 680, rect.top + 45 };
    DrawText(buffer, text.c_str(), text.length(), &drawRect, DT_LEFT);

    ostringstream convert2;   // stream used for the conversion
    convert2 << "FPS: " << FPS_calc;      // insert the textual representation of 'Number' in the characters in the stream
    text = convert2.str();
    drawRect = { rect.left + 5, rect.top + 45, rect.left + 680, rect.top + 65 };
    DrawText(buffer, text.c_str(), text.length(), &drawRect, DT_LEFT);


    //do the dubble buffering
    BitBlt(device, 0, 0, rect.right - rect.left, rect.bottom - rect.top, buffer, 0, 0, SRCCOPY);

    DeleteDC(buffer);
    DeleteObject((HBITMAP)BGimage);
}

现在,这工作正常,但 //SOME HEAVY PIXELS(当前已注释掉) 占用了很多速度。然后我听说你可以锁定图像并操纵咬痕。

我根本无法理解这一点? 我希望(对于示例)在 x、y 处用单个像素填写一个 100 x 100 的字段,同时避免所有昂贵的调用函数。

我试过 [https://msdn.microsoft.com/en-us/library/5ey6h79d(v=vs.110).aspx?cs-save-lang=1&cs-lang=cpp#code-snippet-2]

还有许多其他版本。但我似乎无法让我工作..

有人知道吗?

我的完整工作代码在这里:

#include<Windows.h>
#include<iostream>
#include<time.h>
#include<string>


#include <sstream>

using namespace std;

const string APPTITLE = "GAME LOOP";
const string APPNAME = "GAME LOOP";
HWND window;
HDC device;

bool gameover = false;
POINT p;
int x = 200;
int y = 200;
int startTime;
int currentTime;
int lastTime;
int FPS_calc = 0;


// FORWARD DECLARATIONS
void DrawBitmap(RECT rect, string text);
bool Game_Init();
void Game_Run();
void Game_End();
ATOM MyRegisterClass(HINSTANCE hInstance);
BOOL InitInstance(HINSTANCE hInstance, int nCmdShow);
LRESULT CALLBACK WinProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam);
string ArrowKey();
void MouseDet(POINT &mp);



int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) {
    MSG msg;
    MyRegisterClass(hInstance);

    if (InitInstance(hInstance, nCmdShow) != 1) return GetLastError();

    if (!Game_Init()) return 0;
    while (!gameover) {
        if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) {
            TranslateMessage(&msg);
            DispatchMessage(&msg);
        }
        Game_Run();
    }
    Game_End();

    return msg.wParam;
}

//////////Functions//////////////


// Main game function
void Game_Run() {
    if (gameover == true) return;

    RECT rect;
    GetClientRect(window, &rect);


    //ARROW KEY DETECTOR
    string text = ArrowKey();
    //MouseDetector sets point if Left mouse key is pressed/held
    MouseDet(p);
    currentTime = GetTickCount();
    FPS_calc = int(1000 / (currentTime-lastTime));
    if (lastTime != currentTime) lastTime = currentTime-1;
    else lastTime = currentTime-30;
    DrawBitmap(rect, text);

}


//Draw function with dubble buffering
void DrawBitmap(RECT rect, string text) {


    HDC buffer = CreateCompatibleDC(device);
    HBITMAP BGimage = CreateCompatibleBitmap(device, rect.right - rect.left, rect.bottom - rect.top);
    SelectObject(buffer, BGimage);

    //Clearing the screen with  a full rect
    Rectangle(buffer, rect.left, rect.top, rect.right, rect.bottom);


    //Sample on making a single pixel at mouseclik, with color 250 on screen.

    SetPixelV(buffer, x, y, 250);


    int PixelSize = 4;



    //SOME HEAVY PIXELS to slow the FPS
    /* 
    for (int i = 0; i < 255; i++) {
        for (int k = 0; k < 255; k++) {
            SetPixelV(buffer, x + i, y + k, COLORREF RGB(150, i, k));
        }
    }
    */



    //Sample on making some text.
    RECT drawRect;
    drawRect = { rect.left + 5, rect.top + 5, rect.left + 105, rect.top + 25 };
    DrawText(buffer, text.c_str(), text.length(), &drawRect, DT_LEFT);


    // counter number to be converted to a string
    int timeint = GetTickCount();
    ostringstream convert;   // stream used for the conversion
    convert << "TIME: " << timeint;      // insert the textual representation of 'Number' in the characters in the stream
    text = convert.str();
    drawRect = { rect.left + 5, rect.top + 25, rect.left + 680, rect.top + 45 };
    DrawText(buffer, text.c_str(), text.length(), &drawRect, DT_LEFT);

    ostringstream convert2;   // stream used for the conversion
    convert2 << "FPS: " << FPS_calc;      // insert the textual representation of 'Number' in the characters in the stream
    text = convert2.str();
    drawRect = { rect.left + 5, rect.top + 45, rect.left + 680, rect.top + 65 };
    DrawText(buffer, text.c_str(), text.length(), &drawRect, DT_LEFT);


    //do the dubble buffering
    BitBlt(device, 0, 0, rect.right - rect.left, rect.bottom - rect.top, buffer, 0, 0, SRCCOPY);

    DeleteDC(buffer);
    DeleteObject((HBITMAP)BGimage);
}



//initialize value
bool Game_Init() {
    //get a random engine
    srand(time(NULL));
    //getStartTime
    startTime = GetTickCount();
    currentTime = startTime;
    lastTime = currentTime - 1;
    FPS_calc = int(1000 / (lastTime - currentTime));
    return 1;
}


//End the game, release the window
void Game_End() {
    ReleaseDC(window, device);
}

//A window "setup"
ATOM MyRegisterClass(HINSTANCE hInstance) {
    WNDCLASSEX wc;
    wc.cbSize = sizeof(WNDCLASSEX);
    wc.style = CS_HREDRAW | CS_VREDRAW;
    wc.lpfnWndProc = (WNDPROC)WinProc;
    wc.cbClsExtra = 0;
    wc.cbWndExtra = 0;
    wc.hInstance = hInstance;
    wc.hIcon = NULL;
    wc.hCursor = LoadCursor(NULL, IDC_ARROW);
    wc.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
    wc.lpszMenuName = NULL;
    wc.lpszClassName = APPTITLE.c_str();
    wc.hIconSm = NULL;
    return RegisterClassEx(&wc);
}



//Creates our visible window
BOOL InitInstance(HINSTANCE hInstance, int nCmdShow) {
    window = CreateWindow(APPTITLE.c_str(), APPTITLE.c_str(), WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, 800, 600, NULL, NULL, hInstance, NULL);

    if (window == 0) return 0;

    ShowWindow(window, nCmdShow);
    UpdateWindow(window);

    device = GetDC(window);
    return 1;
}


LRESULT CALLBACK WinProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) {
    switch (message) {
    case WM_DESTROY:
        gameover = true;
        PostQuitMessage(0);
        break;
    }
    return DefWindowProc(hWnd, message, wParam, lParam);
}


//Test if arrow keys have been typed, return text wit hwich one
string ArrowKey() {
    string text = "NONE";
    if ((1 << 16) & GetAsyncKeyState(VK_UP))
    {
        text = "UP";
        y--;
    }
    if ((1 << 16) & GetAsyncKeyState(VK_DOWN))
    {
        text = "DOWN";
        y++;
    }
    if ((1 << 16) & GetAsyncKeyState(VK_RIGHT))
    {
        text = "RIGTH";
        x++;
    }
    if ((1 << 16) & GetAsyncKeyState(VK_LEFT))
    {
        text = "LEFT";
        x--;
    }
    return text;
}


void MouseDet(POINT &mp) {
    if ((1 << 16) & GetAsyncKeyState(VK_LBUTTON)) {

        GetCursorPos(&mp);
        if (ScreenToClient(window, &mp)) {}
        x = p.x;
        y = p.y;
    }
}

【问题讨论】:

  • SetDIBitsGetDIBits 让您可以将位图中的像素数据作为内存块进行修改和读取,而不是通过多个每个像素的 API 调用。这可能是您正在寻找的(除非您愿意超越 GDI)。 msdn.microsoft.com/en-us/library/windows/desktop/…
  • 谢谢,我试过了,但似乎没有帮助。

标签: c++ graphics pixels


【解决方案1】:

如果您只是想绘制一个矩形/正方形,那么您可以使用FillRect 来执行此操作。

【讨论】:

  • 我知道,但不知道。我希望单独操作很多像素(如 SetPixels() )该示例仅使用 100 x 100 框来轻松编程 10.000 个单个像素的位置,在以后的使用中它将最终成为一堆独立的像素可以移动。但首先我需要知道比 setPixel 更快地操纵图形
  • @JavaApprentis - 想详细说明..?
猜你喜欢
  • 2019-11-19
  • 2017-12-05
  • 2011-07-07
  • 2020-04-11
  • 2016-06-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-05-07
相关资源
最近更新 更多