Check alle échte Black Friday-deals Ook zo moe van nepaanbiedingen? Wij laten alleen échte deals zien
Toon posts:

[VB6/DirectDraw] Screenshot maken en op surface tekenen

Pagina: 1
Acties:
  • 163 views sinds 30-01-2008
  • Reageer

Verwijderd

Topicstarter
Een week geleden ben ik begonnen aan wat een mini-projectje had moeten zijn, maar helaas wil het totaal niet vlotten. Ik ben goed bekend met VB6, maar DirectDraw is nieuw voor mij.

Ik probeer iets te bereiken dat op het eerste gezicht heel raar klinkt, maar ondanks dat toch makkelijk te realiseren zou moeten zijn.

Wij gebruiken een bepaalde applicatie, genaamd Scala, een soort van PowerPoint-achtig pakket. De output van Scala wordt gewoon geblit op het scherm zonder een hardware overlay (surface). Voor ons is dat een probleem, omdat we heel graag de Feature Display van onze Matrox Parhelia-videokaart willen gebruiken. De Feature Display is feitelijk de TV-out, die een hoge kwaliteit composite-output levert. De Matrox-drivers zetten alles wat op een hardware overlay getekend is door op de Feature Display. Je raadt het al: aangezien Scala geen hardware overlay gebruikt, verschijnen onze mooie presentaties ook niet via de Feature Display op de TV-out.

De truc die ik wil toepassen met een klein extern programma'tje is dus:

1. Doe CreateSurface (overlay maken)
2. Maak een screenshot van Scala
3. Teken de screenshot op de overlay
4. Herhaal stappen 2 en 3 minstens 25x per seconde :)

Een screenshot maken en dat vervolgens herhalen gaat moeiteloos; het systeem waarop het moet draaien maakt eenvoudig honderden screenshots per seconde.

Ik heb m'n best gedaan om me in te lezen in DirectDraw, maar ik kom er niet helemaal uit. Wat me tot nu op basis van webvoorbeelden is gelukt, is het opslaan van een screenshot op de harde schijf als bitmap. Vervolgens kan ik met CreateSurfaceFromFile de bitmap aanroepen, die vervolgens inderdaad op m'n scherm verschijnt als Surface.

Het probleem hierbij is natuurlijk de harde schijf: de screenshot zit in het geheugen, en het slaat nergens op dat ie eerst opgeslagen moet worden en dan van de harde schijf weer aangeroepen moet worden om vervolgens op de Surface te krijgen. Ik heb geprobeerd met GetDC de device context handle van de DirectDraw surface op te vragen, en vervolgens de screenshot daarop te plakken, maar dat gaat op één of andere manier mis. Ik krijg geen foutmeldingen, maar er gebeurt ook niks.

Hier is de code tot nu toe. Ik heb de API-declaraties ff weggelaten.
Visual Basic:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
' Capture the contents of a window or the entire screen

Function GetScreenSnapshot(Optional ByVal hWnd As Long) As IPictureDisp
    Dim hDC As Long
    Dim tempPict As Long
    Dim oldPict As Long
    Dim wndWidth As Long
    Dim wndHeight As Long
    Dim Pic As PICTDESC
    Dim rcWindow As RECT
    Dim guid(3) As Long
   
    ' provide the right handle for the desktop window
    If hWnd = 0 Then hWnd = GetDesktopWindow
    
    ' get window's size
    GetWindowRect hWnd, rcWindow
    wndWidth = rcWindow.Right - rcWindow.Left
    wndHeight = rcWindow.Bottom - rcWindow.Top
    ' get window's device context
    targetDC = GetWindowDC(hWnd)
    
    ' create a compatible DC
    hDC = CreateCompatibleDC(targetDC)
   
    ' create a memory bitmap in the DC just created
    ' the has the size of the window we're capturing
    tempPict = CreateCompatibleBitmap(targetDC, wndWidth, wndHeight)
    oldPict = SelectObject(hDC, tempPict)
    
    ' copy the screen image into the DC
    BitBlt hDC, 0, 0, wndWidth, wndHeight, targetDC, 0, 0, vbSrcCopy
   
   ' set the old DC image and release the DC
    tempPict = SelectObject(hDC, oldPict)
    DeleteDC hDC
    ReleaseDC GetDesktopWindow, targetDC
   
    ' fill the ScreenPic structure
    With Pic
        .cbSize = Len(Pic)
        .pictType = 1           ' means picture
        .hIcon = tempPict
        .hPal = 0           ' (you can omit this of course)
    End With
      
    ' convert the image to a IpictureDisp object
    ' this is the IPicture GUID {7BF80980-BF32-101A-8BBB-00AA00300CAB}
    ' we use an array of Long to initialize it faster
    guid(0) = &H7BF80980
    guid(1) = &H101ABF32
    guid(2) = &HAA00BB8B
    guid(3) = &HAB0C3000
    ' create the picture,
    ' return an object reference right into the function result
    OleCreatePictureIndirect Pic, guid(0), True, GetScreenSnapshot    


Door middel van:
Visual Basic:
1
SavePicture GetScreenSnapShot, "C:\test.bmp"


...wordt de screenshot opgeslagen op de C-schijf. Dan het stukje DDraw:

Visual Basic:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
    ''Get reference to new directx object
    Set objDx = New DirectX7
    
    ''Create directdraw object
    Set objDraw7 = objDx.DirectDrawCreate("")
    ''Set initial cooperative level
     objDraw7.SetCooperativeLevel Me.hWnd, DDSCL_NORMAL 'Or DDSCL_EXCLUSIVE
    
    ''Set initial display mode
    'objDraw7.SetDisplayMode 640, 480, 16, 0, DDSDM_DEFAULT
    'weggecomment want ik wil geen resolutie switch

    ''Set primary surface
    ddsdPrim.lFlags = DDSD_CAPS
    ddsdPrim.ddsCaps.lCaps = DDSCAPS_PRIMARYSURFACE
    Set objPrimary = objDraw7.CreateSurface(ddsdPrim)
    
    ''Store the primary display properties
    objPrimary.GetSurfaceDesc ddsdPrim


Eigenlijk kom ik hier in de problemen. Voorzover ik begrijp is er nu een primary surface getekend, en was er zojuist ook een screenshot in het geheugen. Nu moet ik de één dus op de ander zien te tekenen, en dan ben ik er. Toch?

Ik hoop dat iemand me een eindje verder kan helpen door uit te leggen hoe ik deze twee eindjes aan elkaar knoop. :)

  • roy-t
  • Registratie: Oktober 2004
  • Laatst online: 17-10 16:43
sorry als dit mischien niet meteen is wat je wilt horen:

vb6+d3d/directdraw is hell!

Misschien kun je microsoft XNA even gebruiken om met C#/VB.net snel een texture te tekenen.

Als je je toch moet inlezen gaat dit waarschijnlijker sneller en beter:

een kleine tutorial hoe je met XNA een teture moet tekenen:
http://www.alanphipps.com...XNA-Display2DTexture.html
(uitzoeken hoe je screenshots maakt zal ook niet al te moeilijk zijn)

Sorry dat ik nu echt een andere tool voorstel (kan heel iritant zijn) maar ik denk dat je daar meer baat bij hebt, en de software is gratis, en je hoeft niet heel C#/VB.net te gaan leren ofzo, copy paste gewoon een tutorial en plak je eigen texture erin :)

~ Mijn prog blog!