Рисуем поверх экрана (Windows) с SFML - PullRequest
0 голосов
/ 16 мая 2019

в Windows вы можете рисовать поверх всего с помощью GDI, используя нулевой контекст рисования:

HDC hdc = GetDC(NULL);

Я хочу сделать то же самое с SFML, но если я попробую что-то эквивалентное (создание окна визуализациис NULL в качестве аргумента, после приведения его к hwnd) ничего не рисуется.Что я пытаюсь даже возможно с sfml?

1 Ответ

1 голос
/ 19 мая 2019

хорошо, если вы хотите OpenGL вам нужен период окна.Но окно не обязательно должно быть видно на экране.Вы можете комбинировать GDI и OpenGL вместе, чтобы достичь своей цели.

  1. Отрисовывать материал с экрана в растровое изображение с помощью OpenGL

    с использованием невидимого окна с тем же разрешением, что и на рабочем столе.Если окно невидимо, оно не будет реагировать на события мыши или клавиатуры ...

  2. Копировать изображение GL в память на стороне процессора

    simple glReadPixels будет делать.

  3. Скопировать изображение на рабочий стол (используя растровое изображение GDI)

    просто преобразовать / скопировать необработанные данные изображения в GDI-совместимыйрастровое изображение, а затем просто нарисуйте его на рабочий стол холста.Поэтому больше нет SwapBuffers(hdc);, как в стандартном приложении GL.

Я кодирую в среде C ++ / VCL , поэтому у меня нет чистого WinAPI / GDI knwoledge (VCL делает это для меня, но код должен быть очень похожим, передаваемые имена и операнды могут немного отличаться, но не слишком сильно).

Это то, с чем я прихожу:

//---------------------------------------------------------------------------
#include <vcl.h>
#include <gl\gl.h>
#pragma hdrstop
#include "Unit1.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1  *Form1;                 // VCL Application window object
TCanvas *scr=NULL;              // Desktop
DWORD   *txr=NULL;              // memory for GPU->CPU image transfer
Graphics::TBitmap *bmp=NULL;    // bitmap for CPU->Desktop image transfer
int     xs,ys;                  // desktop resolution
HDC     hdc=NULL;               // device context for GL
HGLRC   hrc=NULL;               // rendering context for GL
//---------------------------------------------------------------------------
void gl_draw()
    {
    if (scr==NULL) return;
    if (bmp==NULL) return;
    if (txr==NULL) return;

    glClearColor(0.0,0.0,0.0,0.0);
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    glDisable(GL_DEPTH_TEST);
    glDisable(GL_CULL_FACE);

    // desktop pixel units
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    glTranslatef(-1.0,+1.0,0.0);
    glScalef(2.0/float(xs),-2.0/float(ys),1.0);
    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();

    // render rectangle
    GLfloat fx=xs/2,fy=ys/2,fz=0.0,fa=(xs/2)-10,fb=(ys/2)-10;
    glColor3f(1.0,1.0,1.0);
    glBegin(GL_LINE_LOOP);
    glVertex3f(fx-fa,fy-fb,fz);
    glVertex3f(fx-fa,fy+fb,fz);
    glVertex3f(fx+fa,fy+fb,fz);
    glVertex3f(fx+fa,fy-fb,fz);
    glEnd();

    if (Form1->Visible)     // normal window GL render
        {
        glFlush();
        SwapBuffers(hdc);
        }
    else{                   // copy GL image directly to desktop
        // copy GL image to CPU side memory
        glFlush();
        glReadPixels(0,0,xs,ys,GL_RGBA,GL_UNSIGNED_BYTE,txr);
        // copy it to bitmap
        int x,y,a; DWORD *p;
        for (a=0,y=0;y<ys;y++)
         for (p=(DWORD*)bmp->ScanLine[y],x=0;x<xs;x++,a++)
          p[x]=txr[a];
        // render it to desktop
        scr->Draw(0,0,bmp);
        }

    }
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner):TForm(Owner)
    {
    // desktop
    scr=new TCanvas();
    scr->Handle=GetDC(NULL);
    xs=scr->ClipRect.Width();
    ys=scr->ClipRect.Height()-31;           // leave taskbar out of it
    // BMP
    bmp=new Graphics::TBitmap;
    bmp->HandleType=bmDIB;
    bmp->PixelFormat=pf32bit;
    bmp->SetSize(xs,ys);
    // txr buffer
    txr=new DWORD[xs*ys];
    // window
    BorderStyle=bsNone;
    SetBounds(0,0,xs,ys);
    // GL init
    hdc = GetDC(Handle);                    // get device context for this App window
    PIXELFORMATDESCRIPTOR pfd;
    ZeroMemory( &pfd, sizeof( pfd ) );      // set the pixel format for the DC
    pfd.nSize = sizeof( pfd );
    pfd.nVersion = 1;
    pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER;
    pfd.iPixelType = PFD_TYPE_RGBA;
    pfd.cColorBits = 24;
    pfd.cDepthBits = 24;
    pfd.iLayerType = PFD_MAIN_PLANE;
    SetPixelFormat(hdc,ChoosePixelFormat(hdc, &pfd),&pfd);
    hrc = wglCreateContext(hdc);            // create current rendering context
    if(hrc == NULL)
        {
        ShowMessage("Could not initialize OpenGL Rendering context !!!");
        Application->Terminate();
        }
    if(wglMakeCurrent(hdc, hrc) == false)
        {
        ShowMessage("Could not make current OpenGL Rendering context !!!");
        wglDeleteContext(hrc);          // destroy rendering context
        Application->Terminate();
        }
    glViewport(0,0,xs,ys);
    }
//---------------------------------------------------------------------------
void __fastcall TForm1::FormDestroy(TObject *Sender)
    {
    // GL exit
    wglMakeCurrent(NULL, NULL);     // release current rendering context
    wglDeleteContext(hrc);          // destroy rendering context
    // release buffers
    if (scr){ delete scr; scr=NULL; }
    if (bmp){ delete bmp; bmp=NULL; }
    if (txr){ delete[] txr; txr=NULL; }
    }
//---------------------------------------------------------------------------
void __fastcall TForm1::FormPaint(TObject *Sender)
    {
    gl_draw();
    }
//---------------------------------------------------------------------------
void __fastcall TForm1::Timer1Timer(TObject *Sender)
    {
    if (Visible) Visible=false; // hide
    gl_draw();
    }
//---------------------------------------------------------------------------

Единое приложение Form VCL с одним таймером.Это создает контекст GL и при первой возможности становится невидимым.Затем он периодически перезаписывает рабочий стол с черным фоном и белой рамкой прямоугольника ...

Так что вам нужно перенести материал VCL (Form1 и события) в вашу среду.Также вы можете добавить прозрачность в строку:

scr->Draw(0,0,bmp);

или прочитать изображение рабочего стола и использовать его в качестве фоновой текстуры для рендеринга GL.

PS,Чистый рендеринг GDI намного проще и, вероятно, быстрее, чем этот, но вам требуется GL, так что ...

...