0

ミニゲームを作るために、GDIを使ってグラフィックスの基本的なフレームワークを作ろうとしています。しかし、GDIは何もレンダリングしていません。クライアント領域が黒くなり、何が間違っているのかわかりません。

次のコードは、常に実行されているゲームループ内にあります。

//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);
        }

私はここで何が間違っているのですか?それがいくつかの愚かな間違いであるならば申し訳ありませんが、私はウィンドウズプログラミングがまったく得意ではありません。

編集:要求に応じて追加のコード:

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-レンダリングメソッドの定義

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));
}
4

1 に答える 1

1

これは、私が GDI レンダリングを行っていた方法です (VB6 から変換された古い製品コード)。これは、WM_PAINT(ゲーム ループ内で) または Windows がウィンドウの一部を無効にしたときに送信されたものへの応答です。

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);
}

InvalidateRectWM_PAINTを使用してウィンドウを無効にすることでトリガーします。

InvalidateRect ( hWnd, NULL, FALSE );

これは、クライアントの描画に関するMSDN の記事です。質問をありがとう、これのいくつかはゆっくりと私に戻ってきています。:) 私は何年も GDI を行っていません。

于 2012-10-06T22:57:33.340 に答える