Author Topic: How to grab the desktop as a texture  (Read 8375 times)

0 Members and 1 Guest are viewing this topic.

Offline Jim

  • Founder Member
  • DBF Aficionado
  • ********
  • Posts: 5301
  • Karma: 402
    • View Profile
How to grab the desktop as a texture
« on: October 29, 2007 »
Tested under Vista and XP.

Code: [Select]
#include <windows.h>

#define SCREEN_WIDTH 800
#define SCREEN_HEIGHT 600

unsigned int texture[1024*1024];
GLuint hand;

HDC hdc = GetDC(NULL);
HDC mydc = CreateCompatibleDC(hdc);
int w = GetSystemMetrics(SM_CXSCREEN);
int h = GetSystemMetrics(SM_CYSCREEN);
HBITMAP mybmp = CreateCompatibleBitmap(hdc,w,h);

SelectObject(mydc, mybmp);

StretchBlt(mydc, 0,0,1024,1024, hdc,0,0,w,h, SRCCOPY);

ReleaseDC(NULL, hdc);

static struct
{
BITMAPINFOHEADER bmiHeader;
RGBQUAD bmiColours[3];
} screen_bmi=
{
{
sizeof(BITMAPINFOHEADER),
1024,
1024,
1,
32,
BI_RGB,
0,
75,
75,
0,
0,
},
0x00,0x00,0xff,0x00,
0x00,0xff,0x00,0x00,
0xff,0x00,0x00,0x00,
};

int err = GetDIBits(mydc, mybmp, 0, 1024, texture, (BITMAPINFO *)&screen_bmi, DIB_RGB_COLORS);

glGenTextures(1, &hand);
glBindTexture(GL_TEXTURE_2D, hand);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);

glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);

//might want to do this as Windows doesn't set the alpha channel
for (int z= 0; z < 1024*1024;z++) texture[z] |= 0xff000000;
glTexImage2D(GL_TEXTURE_2D, 0, 4, 1024,1024, 0, GL_BGRA_EXT, GL_UNSIGNED_BYTE, texture);

//try it out
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, hand);

glColor4f(1,1,1,1);
glBegin(GL_QUADS);
glTexCoord2f(0.0f,1.0f);
glVertex2i(0,0);
glTexCoord2f(0.0f,0.0f);
glVertex2i(0,SCREEN_HEIGHT);
glTexCoord2f(1.0f,0.0f);
glVertex2i(SCREEN_WIDTH,SCREEN_HEIGHT);
glTexCoord2f(1.0f,1.0f);
glVertex2i(SCREEN_WIDTH,0);
glEnd();

Jim
« Last Edit: December 14, 2007 by Jim »
Challenge Trophies Won:

Offline taj

  • Bytes hurt
  • DBF Aficionado
  • ******
  • Posts: 4810
  • Karma: 189
  • Scene there, done that.
    • View Profile
Re: How to grab the desktop as a texture
« Reply #1 on: October 29, 2007 »
karma++ Jim. I'll add this to my halloween entry once the voting is done so everyone can run it.
Chris
Challenge Trophies Won:

Offline benny!

  • Senior Member
  • DBF Aficionado
  • ********
  • Posts: 4384
  • Karma: 228
  • in this place forever!
    • View Profile
    • bennyschuetz.com - mycroBlog
Re: How to grab the desktop as a texture
« Reply #2 on: October 29, 2007 »
Yeah. Nice piece of code! K++, Jim !!!
[ mycroBLOG - POUET :: whatever keeps us longing - for another breath of air - is getting rare ]

Challenge Trophies Won:

Offline Paul

  • Pentium
  • *****
  • Posts: 1490
  • Karma: 47
    • View Profile
Re: How to grab the desktop as a texture
« Reply #3 on: October 29, 2007 »
Tried to make a blitzbasic version, but ended up with this...
only works in non debugmode
as you see in the screenshot, it doesn't work too well :(
Code: [Select]
Global width =api_GetSystemMetrics(0)
Global height=api_GetSystemMetrics(1)

Graphics width,height,32,1


Local hdc=api_getdc(0)
Local blitzhdc=api_getdc(SystemProperty("apphwnd"))

Local mydc = api_CreateCompatibleDC(hdc)


hidewindow
api_BitBlt(blitzhdc, 0, 0, width,height, hdc, 0,0, $CC0020)
showwindow


Local image=CreateImage(width,height)
CopyRect(0,0,width,height,0,0,FrontBuffer(),ImageBuffer(image))


SetBuffer BackBuffer()
While Not KeyHit(1)
DrawImage(image,0,0)

Text 0,0,"Done"
Flip
Cls
Wend

Function showwindow(hwnd=0)
If hwnd=0 Then hwnd=SystemProperty("apphwnd")
api_ShowWindow(hwnd,5)
End Function
Function hidewindow(hwnd=0)
If hwnd=0 Then hwnd=SystemProperty("apphwnd")
api_ShowWindow(hwnd,0)
End Function

I will bite you - http://s5.bitefight.se/c.php?uid=31059
Challenge Trophies Won:

Offline Rbz

  • Founder Member
  • DBF Aficionado
  • ********
  • Posts: 2757
  • Karma: 493
    • View Profile
    • https://www.rbraz.com/
Re: How to grab the desktop as a texture
« Reply #4 on: October 29, 2007 »
@Paul: try to initialize your graphics screen "Graphics width,height,32,1" after "CopyRect(0,0,width,height,0,0,FrontBuffer(),ImageBuffer(image))" command.
Challenge Trophies Won:

Offline Paul

  • Pentium
  • *****
  • Posts: 1490
  • Karma: 47
    • View Profile
Re: How to grab the desktop as a texture
« Reply #5 on: October 30, 2007 »
It seems as if the code hasto be run in fullscreen for it to work at all, so thats not an option :(
any other ideas?
I will bite you - http://s5.bitefight.se/c.php?uid=31059
Challenge Trophies Won:

Offline Jim

  • Founder Member
  • DBF Aficionado
  • ********
  • Posts: 5301
  • Karma: 402
    • View Profile
Re: How to grab the desktop as a texture
« Reply #6 on: October 30, 2007 »
I'm not much of a bb programmer, but it looks like you missed out a bit - where do you create and copy to the compatible bitmap?

Jim
Challenge Trophies Won:

Offline Paul

  • Pentium
  • *****
  • Posts: 1490
  • Karma: 47
    • View Profile
Re: How to grab the desktop as a texture
« Reply #7 on: October 30, 2007 »
sry, here somes the code again but with coments:
Code: [Select]

Global width =api_GetSystemMetrics(0)
Global height=api_GetSystemMetrics(1)

Graphics width,height,32,1


Local blitzhdc=api_GetDC(SystemProperty("apphwnd")) ;get the blitzwindows device context

Local deskhdc=api_GetDC(api_GetDesktopWindow()) ;same for desktop

hidewindow
api_BitBlt(blitzhdc, 0, 0, width,height, deskhdc, 0,0, $CC0020);copy the desktop device context to the blitz frontbuffer(i think and it seems to work)
showwindow


Local image=CreateImage(width,height) ;create an empty iamge

CopyRect(0,0,width,height,0,0,FrontBuffer(),ImageBuffer(image)) ;copy the frontbuffer to our image. only problem is that it far too often doesn't get the whole screen


SetBuffer BackBuffer()
While Not KeyHit(1)
DrawImage(image,0,0)

Text 0,0,"Done"
Flip
Cls
Wend

Function showwindow(hwnd=0)
If hwnd=0 Then hwnd=SystemProperty("apphwnd")
api_ShowWindow(hwnd,5)
End Function
Function hidewindow(hwnd=0)
If hwnd=0 Then hwnd=SystemProperty("apphwnd")
api_ShowWindow(hwnd,0)
End Function

I don't realy understand the compatible bitmap but i think that's the way to go.
I will bite you - http://s5.bitefight.se/c.php?uid=31059
Challenge Trophies Won:

Offline zawran

  • Sponsor
  • Pentium
  • *******
  • Posts: 909
  • Karma: 67
    • View Profile
Re: How to grab the desktop as a texture
« Reply #8 on: October 30, 2007 »
Not really wanting to go off topic, since the topic is in the C/C++ section, but I did a search on the blitzresearch forum, and found this one in the code archieves. It should work for both images and textures. But I have not tested it though since I only have blitzmax installed at the moment.

Example usage:

tex = GetDesktop() ; creates a texture
image = GetDesktop(1) ; creates an image
GetDesktop(0,tex) ; updates a texture
GetDesktop(1,image) ; updates an image

Code: [Select]
Const SRCCOPY = $CC0020
Const CF_BITMAP = 2
Const SW_HIDE = 0
Const SW_SHOW = 5

Function GetDesktop(flag=0,update=0)

; ADAmor ZILTCH 2003
;
; This command must come after your GRAPHICS(3D) x,y command.
;
;  flag 0 = create texture
;       1 = create image
;
; if update is not 0 then it is the tex/image to update.

   DeskHwnd = GetDesktopWindow()

   ; Get screen coordinates
   fwidth  = GetSystemMetrics%(0)  ;RectWin\rightR  - RectWin\leftR
   fheight = GetSystemMetrics%(1)  ;RectWin\bottomR - RectWin\topR

   BlitzHwnd = GetActiveWindow()
   ShowWindow(BlitzHwnd,SW_HIDE)

   ; Get the device context of Desktop and allocate memory
   hdc = GetDC(DeskHwnd)
   Blitzhdc = GetDC(BlitzHwnd)

   ; Copy data
   BitBlt(Blitzhdc, 0, 0, fwidth, fheight, hdc, 0,0, SRCCOPY)

   ; Clean up handles
   ReleaseDC(DeskHwnd, hdc)
   ReleaseDC(BlitzHwnd, Blitzhdc)
   ShowWindow(BlitzHwnd,SW_SHOW)

   ; Create/update texture or image
   Select flag
     Case 0
       If update = 0 Then
         tex=CreateTexture(fwidth,fheight)
       Else
         tex=update
       End If
       CopyRect 0,0,fwidth,fheight,0,0,FrontBuffer(),TextureBuffer(tex)
       Return tex
     Case 1
       If update = 0 Then
         image=CreateImage(fwidth,fheight)
       Else
         image=update
       End If
       CopyRect 0,0,fwidth,fheight,0,0,FrontBuffer(),ImageBuffer(image)
       Return image
   End Select

End Function
;---------------- end code

It needs some user.decls definitions:

Code: [Select]
Lines needed in Userlib: User32.decls

FindWindow%( class$,Text$ ):"FindWindowA"
ShowWindow(hwnd%,nCmdShow%)
GetActiveWindow%()
GetDC%(hWnd% )
ReleaseDC%(hWnd%,hDC%)
GetDesktopWindow%()
GetSystemMetrics%(nIndext%)

Lines needed in Userlib: Gdi32.decls
BitBlt%(hDestDC%,X%,Y%,nWidth%,nHeight%,hSrcDC,XSrc,YSrc,dwRop)

I hope its of use, and sorry for the somewhat off topic.

Offline Jim

  • Founder Member
  • DBF Aficionado
  • ********
  • Posts: 5301
  • Karma: 402
    • View Profile
Re: How to grab the desktop as a texture
« Reply #9 on: October 30, 2007 »
I *think* the problem is when you do the BitBlt there is no bitmap selected in to the blitzhdc so it doesn't work.
You need to do
Code: [Select]
bmp=CreateCompatibleBitmap(deskhdc, width, height)
SelectObject(blitzhdc, bmp);
before the bitblt.
But then there's no real reason why CopyRect will work, since it's not obvious what the source for the copy is. :-\

Jim
Challenge Trophies Won:

Offline Paul

  • Pentium
  • *****
  • Posts: 1490
  • Karma: 47
    • View Profile
Re: How to grab the desktop as a texture
« Reply #10 on: October 30, 2007 »
@ zawran, that code has the exact same problem as mine. It looks lite the desktop was updating hen i ran the code so i got some black areas.
@jim, the problem is probably there, but ihave tried waht you say(i think) and it doesn't work, same prolem. could you compile an exe of youre c++ program so i can check if that works on my pc? thx, and sry for the offtopic.
I will bite you - http://s5.bitefight.se/c.php?uid=31059
Challenge Trophies Won:

Offline Paul

  • Pentium
  • *****
  • Posts: 1490
  • Karma: 47
    • View Profile
Re: How to grab the desktop as a texture
« Reply #11 on: November 03, 2007 »
OK... found a solution. use the api_keybd_event(44,0,0,0) function to "press" the print screen button. then paste the image to an imagebuffer using the PasteImageFromClipboard() function from here:   http://www.blitzbasic.com/codearcs/codearcs.php?code=1767
I will bite you - http://s5.bitefight.se/c.php?uid=31059
Challenge Trophies Won:

Offline madsravn

  • ZX 81
  • *
  • Posts: 13
  • Karma: 0
    • View Profile
Re: How to grab the desktop as a texture
« Reply #12 on: November 23, 2007 »
Cool effect :) I've gotta try it out . Thanks man ;)

Offline Jim

  • Founder Member
  • DBF Aficionado
  • ********
  • Posts: 5301
  • Karma: 402
    • View Profile
Re: How to grab the desktop as a texture
« Reply #13 on: November 23, 2007 »
No probs - great to see you here!

Jim
Challenge Trophies Won:

Offline Jim

  • Founder Member
  • DBF Aficionado
  • ********
  • Posts: 5301
  • Karma: 402
    • View Profile
Re: How to grab the desktop as a texture
« Reply #14 on: December 14, 2007 »
Just spotted a slight error.
correction:
Code: [Select]
int err = GetDIBits(mydc, mybmp, 0, h, texture, (BITMAPINFO *)&screen_bmi, DIB_RGB_COLORS);
should be
Code: [Select]
int err = GetDIBits(mydc, mybmp, 0, 1024, texture, (BITMAPINFO *)&screen_bmi, DIB_RGB_COLORS);
Corrected in original post.

Jim
Challenge Trophies Won: