GDI is not rendering, what am I doing wrong?

痞子三分冷 提交于 2020-01-03 04:52:08

问题


I am trying to make a basic framework for graphics with GDI to make some minigames with. But GDI is not rendering anything at all, I just get a black client area, and I have no idea what I'm doing wrong.

The following code is inside a game loop that is running constantly:

//render double buffered with GDI
            HDC frontBuffer = GetDC(m_hMainWnd);

            HDC backBuffer;
            HBITMAP bitmap;
            HBITMAP oldBitmap;

            backBuffer = CreateCompatibleDC(frontBuffer);
            bitmap = CreateCompatibleBitmap(frontBuffer, m_ClientWidth, m_ClientHeight);
            oldBitmap = (HBITMAP)SelectObject(backBuffer, bitmap);

            GDI->StartDrawing(backBuffer, m_ClientWidth, m_ClientHeight); //this basically selects pens and brushes etc
            Render(dRenderTime); //here I render some stuff
            GDI->StopDrawing(backBuffer); //selects old pens and brushes back

         //blit backbuffer to frontbuffer
            BitBlt(frontBuffer, 0, 0, m_ClientWidth, m_ClientHeight, backBuffer, 0, 0, SRCCOPY);

            SelectObject(backBuffer, oldBitmap);
            DeleteObject(bitmap);
            DeleteDC(backBuffer);

            ReleaseDC(m_hMainWnd, frontBuffer);
        }

What am I doing wrong here? Sorry if it's some stupid mistake, I am not good at all with windows programming.

EDIT: additional code, as requested:

gdi.h

    #pragma once

#include <Windows.h>
#include "Macros.h"
#include "Transform.h"
#include "Text.h"

#define GDI gdi::getInstance()

class gdi
{
private:
  HPEN m_OldPen;
  HPEN m_Pen;
  HBRUSH m_OldBrush;
  HBRUSH m_Brush;
  HDC m_hdc;

  int m_DcWidth;
  int m_DcHeight;

  COLORREF m_Color;
  int m_LineWidth;

  DBlib::float3x3 m_Transform;

  gdi();

  void Transform(int& x_out, int& y_out, const DBlib::float2& p) const;
  void Transform_NDC_To_WC(int& x_out, int& y_out, const DBlib::float2& p) const;
  void Transfrom_WC_To_NDC(DBlib::float2& p_out, int x, int y) const;

public:
  ~gdi();

  static gdi* getInstance();

  void StartDrawing(HDC hdc, int dcwidth, int dcheight);
  void StopDrawing(HDC hdc);

  void SetColor(const DBlib::float3& col);
  void SetLineWidth(int width);

  void SetTransform(const DBlib::float3x3& transform);

  void DrawText(const DBlib::float2& p1, const std::tstring& s);
  void DrawLine(const DBlib::float2& p1, const DBlib::float2& p2);
  void DrawPolygon(const DBlib::float2* p, int size);
  void FillPolygon(const DBlib::float2* p, int size);
};

GDI.cpp

#include "gdi.h"

gdi* gdi::getInstance()
{
  static gdi instance;
  return &instance;
}

gdi::gdi()
{
  m_hdc = NULL;
  m_OldPen = NULL;
  m_OldBrush = NULL;
  m_LineWidth = 1;
  m_Color = RGB(0,0,0);
  m_DcWidth = -1;
  m_DcHeight = -1;
  m_Transform.set_identity();

  m_Pen = CreatePen(PS_SOLID,1,RGB(0,0,0));
  m_Brush = CreateSolidBrush(RGB(255,255,255));
}

gdi::~gdi()
{
    if(m_Pen) DeleteObject(m_Pen);
    if(m_Brush) DeleteObject(m_Brush);
}

void gdi::StartDrawing(HDC hdc, int dcwidth, int dcheight)
{
  m_hdc = hdc;
  m_DcWidth = dcwidth;
  m_DcHeight = dcheight;
  m_OldPen = (HPEN)SelectObject(hdc, m_Pen);
  m_OldBrush = (HBRUSH)SelectObject(hdc, m_Brush);
}

void gdi::StopDrawing(HDC hdc)
{
  SelectObject(hdc, m_OldPen);
  SelectObject(hdc, m_OldBrush);

  m_hdc = NULL;
  m_DcWidth = -1;
  m_DcHeight = -1;
  m_OldPen = NULL;
  m_OldBrush = NULL;
}

void gdi::SetColor(const DBlib::float3& col)
{
    int r = static_cast<int>(DBlib::clamp(col.x*255.0f, 0.0f, 255.0f));
    int g = static_cast<int>(DBlib::clamp(col.y*255.0f, 0.0f, 255.0f));
    int b = static_cast<int>(DBlib::clamp(col.z*255.0f, 0.0f, 255.0f));
    m_Color = RGB(r,g,b);

    SetTextColor(m_hdc, m_Color);

    if(m_Pen) DeleteObject(m_Pen);
    if(m_Brush) DeleteObject(m_Brush);
    m_Pen= CreatePen(PS_SOLID, m_LineWidth, m_Color);
    m_Brush= CreateSolidBrush(m_Color);
}

void gdi::SetLineWidth(int width)
{
    m_LineWidth = width;

    if(m_Pen) DeleteObject(m_Pen);
    m_Pen= CreatePen(PS_SOLID, m_LineWidth, m_Color);
}

void gdi::SetTransform(const DBlib::float3x3& transform)
{
    m_Transform = transform;
}

void gdi::Transform_NDC_To_WC(int& x_out, int& y_out, const DBlib::float2& p) const
{
    x_out = static_cast<int>((p.x+1.0f)*(static_cast<float>(m_DcWidth)/2.0f));
    y_out = m_DcHeight - static_cast<int>((p.y+1.0f)*(static_cast<float>(m_DcHeight)/2.0f));
}

void gdi::Transfrom_WC_To_NDC(DBlib::float2& p_out, int x, int y) const
{
    p_out.x = static_cast<float>(x)*2.0f/static_cast<float>(m_DcWidth) - 1.0f;
    p_out.y = -(static_cast<float>(y)*2.0f/static_cast<float>(m_DcHeight) - 1.0f);
}

void gdi::Transform(int& x_out, int& y_out, const DBlib::float2& p) const
{
    Transform_NDC_To_WC(x_out, y_out, p*m_Transform);
}

void gdi::DrawText(const DBlib::float2& pos, const std::tstring& s)
{
    int x,y;
    Transform(x,y,pos);
    TextOut(m_hdc, x, y, s.c_str(), (int)s.size());
}

void gdi::DrawLine(const DBlib::float2& p1, const DBlib::float2& p2)
{
    int x1,y1,x2,y2;
    Transform(x1,y1,p1);
    Transform(x2,y2,p2);

    MoveToEx(m_hdc, x1, y1, NULL);
    LineTo(m_hdc, x2, y2);
}

void gdi::DrawPolygon(const DBlib::float2* p, int size)
{
    int* x = new int[size];
    int* y = new int[size];

    for(int i=0; i<size; ++i) {
        Transform(x[i],y[i],*(p+i));
    }
    for(int i=0; i<size; ++i) {
        MoveToEx(m_hdc, x[i], y[i], NULL);
        LineTo(m_hdc, x[(i+1)%size], y[(i+1)%size]);
    }

    delete[] x;
    delete[] y;
}

void gdi::FillPolygon(const DBlib::float2* p, int size)
{
    int* x = new int[size];
    int* y = new int[size];
    POINT* pts = new POINT[size];

    for(int i=0; i<size; ++i) {
        Transform(x[i],y[i],*(p+i));
        pts[i].x = static_cast<LONG>(x[i]);
        pts[i].y = static_cast<LONG>(y[i]);
    }

    Polygon(m_hdc, pts, size);

    delete[] x;
    delete[] y;
    delete[] pts;
}

App.cpp - Render method definition

void App::Render(float dTime)
{
    GDI->SetColor(DBlib::float3(1.0f,1.0f,1.0f));
    GDI->SetLineWidth(50);
    GDI->DrawLine(DBlib::float2(-1.0f,-1.0f), DBlib::float2(1.0f,1.0f));
}

回答1:


This is how I used to do GDI rendering (old production code translated from VB6). This is in response to WM_PAINT that is sent when either you (in your game loop) or Windows invalidates part of your window.

PAINTSTRUCT stPaintStruct;
HDC hPaintDC = BeginPaint(hWnd, &stPaintStruct);

if (hPaintDC != HANDLE_NULL)
{
    // establish clipping rect using stPaintStruct.rcPaint

    if (!m_bRendering)
    {
        m_bRendering = TRUE;

        // Render() knows the output bitmap and all the content to render
        // and makes sure resources are allocated / discarded during
        // rendering.
        Render ();

        m_bRendering = FALSE;
    }

    EndPaint (hWnd, &stPaintStruct);
    return (TRUE);
}

You trigger a WM_PAINT by invalidating your window using InvalidateRect:

InvalidateRect ( hWnd, NULL, FALSE );

Here's an MSDN article about client drawing. Some of this is coming back to me slowly, thanks for the question. :) I haven't done GDI in years.



来源:https://stackoverflow.com/questions/12764312/gdi-is-not-rendering-what-am-i-doing-wrong

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!