2012-10-06 3 views
0

Я пытаюсь создать базовую структуру для графики с помощью GDI, чтобы сделать несколько мини-игр. Но 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); 
     } 

Что я делаю неправильно здесь? Извините, если это какая-то глупая ошибка, я плохо разбираюсь в программировании окон.

EDIT: дополнительный код, в соответствии с просьбой:

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

Что такое 'GDI' в вашем коде? Я предполагаю, что это класс, который вы сделали для переноса логики визуализации, но тогда вам нужно показать, что нам помочь. Ваш код (после быстрого взгляда) выглядит нормально, но у вас нет важных показанных частей. Почему 'Render' не является частью' GDI'? – xxbbcc

+0

Другое дело - вам не нужно иметь всю логику визуализации в игровом цикле все время - вам нужно всего лишь визуализировать сцену, когда что-то меняется, а затем вам нужно только визуализировать измененные части. Рендеринг очень дорогой, и он будет использовать много циклов вашей игры, если вы все время визуализируете сцену. Выделите свою сцену, когда вам нужно нарисовать растровое изображение, а затем просто накройте это растровое изображение на экране. – xxbbcc

+0

GDI - это одноэлементный класс, который имеет некоторые полезные функции утилиты, такие как DrawLine, SetColor и т. Д. Render() - это в основном метод класса App (который является своего рода отправной точкой для игры), который использует команды GDI для визуализации вещи. Я не добавлял код, потому что я пытался сохранить его минимальным, и я думал, что моя ошибка была в коде, который я опубликовал. Я добавлю это сейчас. – xcrypt

ответ

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

Вы вызвать WM_PAINT аннулируя окно с помощью InvalidateRect:

InvalidateRect (hWnd, NULL, FALSE); 

Вот MSDN article о клиенте чертежа. Некоторые из них возвращаются ко мне медленно, спасибо за вопрос. :) Я не делал GDI годами.

+0

спасибо, я попробую это так и посмотрю, если это сработает, дайте мне некоторое время :) – xcrypt

+0

Нет проблем - имейте в виду, я перевел это из моего старого кода VB6, которого я не видел в 5-6 лет , :) Следите за ошибками. – xxbbcc

+0

Nop, это не работает для меня, я вызываю InvalidateRect() внутри игрового цикла и использовал старый код внутри WM_PAINT и добавил начальную и конечную краску, но это все тот же черный экран, который я получаю ... хм ... – xcrypt

Смежные вопросы