DirectX Overlay mit PB programmieren

Fragen zu Grafik- & Soundproblemen und zur Spieleprogrammierung haben hier ihren Platz.
Andreas21
Beiträge: 390
Registriert: 30.08.2004 09:05
Computerausstattung: Desktop
Windows 10 Pro x64
CPU: AMD Ryzen 5 2600 3.40 GHz
Ram: 16GB RAM
Grafik: NVIDA Geforce 1060
PB: 5.72 X86/X64
Wohnort: Heidelberg

Beitrag von Andreas21 »

So vieleicht?

Code: Alles auswählen

Define lpdm.DEVMODE\dmSize = SizeOf(DEVMODE) 
Define ok.b, Width = 1024, Height = 768, Depth = 16, timeout.l

lpdm\dmFields = #DM_BITSPERPEL | #DM_PELSWIDTH | #DM_PELSHEIGHT 
lpdm\dmBitsPerPel = Depth 
lpdm\dmPelsWidth = Width 
lpdm\dmPelsHeight = Height

ChangeDisplaySettings_(lpdm,0) 

ExamineDesktops()
Repeat
  Delay(50)
  If DesktopWidth(0) = Width
    If DesktopHeight(0) = Height
      If DesktopDepth(0) = Depth
        ok = 1
      EndIf
    EndIf
  EndIf
  timeout+ 1
  If timeout = 2400 ; Sind 2 minuten. 2400 * 50 = 120000 millisec.
    Debug "timeout"
    End
  EndIf
Until ok
Debug "ok"
Windows 10 x64 Pro - PB 5.61 X64 / x32 - PB 4.6 x32
Kaeru Gaman
Beiträge: 17389
Registriert: 10.11.2004 03:22

Beitrag von Kaeru Gaman »

getestet?

also, das wechseln sollte ja in eine andere exe,
und natürlich musst du das examine innerhalb der schleife ausführen.
Der Narr denkt er sei ein weiser Mann.
Der Weise weiß, dass er ein Narr ist.
Andreas21
Beiträge: 390
Registriert: 30.08.2004 09:05
Computerausstattung: Desktop
Windows 10 Pro x64
CPU: AMD Ryzen 5 2600 3.40 GHz
Ram: 16GB RAM
Grafik: NVIDA Geforce 1060
PB: 5.72 X86/X64
Wohnort: Heidelberg

Beitrag von Andreas21 »

Code: Alles auswählen

Procedure.l ChangeDisplaySettings(Width.l,Height.l,Depth.l,Frequency.l=0) 
  Protected lpdm.DEVMODE\dmSize = SizeOf(DEVMODE), ok.b, timeout.l 

  lpdm\dmFields = #DM_BITSPERPEL | #DM_PELSWIDTH | #DM_PELSHEIGHT
  lpdm\dmBitsPerPel = Depth 
  lpdm\dmPelsWidth = Width 
  lpdm\dmPelsHeight = Height  
  If Frequency
    lpdm\dmFields = lpdm\dmFields | #DM_DISPLAYFREQUENCY 
    lpdm\dmDisplayFrequency = Frequency
  EndIf
  ChangeDisplaySettings_(lpdm,0) 
  Repeat 
    Delay(50) 
    ExamineDesktops() 
    If DesktopWidth(0) = Width And DesktopHeight(0) = Height And DesktopDepth(0) = Depth 
      If DesktopFrequency(0) = Frequency Or Frequency = 0
        ok = 1  
      EndIf 
    EndIf 
    timeout+ 1 
    If timeout = 2400 ; Sind 2 minuten. 2400 * 50 = 120000 millisec. 
      Break 
    EndIf 
  Until ok 
  ProcedureReturn ok 
EndProcedure 

If ChangeDisplaySettings(1024,768,16,75) 
  Debug "ok" 
Else 
  Debug "timeout" 
EndIf
Dann so halt.
Das leuft bei mir problemlos. (Nicht mit Overlay getestet.)
Frequency deswegen weil er sontzt 60 Hz als Frequency einstelt und das flackert extrem bei mir.

Ich habs mit Overlay getestet.
Es leuft damit. Nur ein problem hab ich wieder.
Das overlay wird wieder zerstört?

Code: Alles auswählen

; Overlay for DirectX 7 via DirectDraw 
; 
; Original by Stefan Moebius (02 Nov. 2004) 
; Updated by Fluid Byte (10 May 2009) 
; 
; 
; Attention: 
; ¯¯¯¯¯¯¯¯¯¯ 
; Not every graphic card supports overlays. 

Procedure.l ChangeDisplaySettings(Width.l,Height.l,Depth.l,Frequency.l=0) 
  Protected lpdm.DEVMODE\dmSize = SizeOf(DEVMODE), ok.b, timeout.l 

  lpdm\dmFields = #DM_BITSPERPEL | #DM_PELSWIDTH | #DM_PELSHEIGHT
  lpdm\dmBitsPerPel = Depth 
  lpdm\dmPelsWidth = Width 
  lpdm\dmPelsHeight = Height  
  If Frequency
    lpdm\dmFields = lpdm\dmFields | #DM_DISPLAYFREQUENCY 
    lpdm\dmDisplayFrequency = Frequency
  EndIf
  ChangeDisplaySettings_(lpdm,0) 
  Repeat 
    Delay(50) 
    ExamineDesktops() 
    If DesktopWidth(0) = Width And DesktopHeight(0) = Height And DesktopDepth(0) = Depth 
      If DesktopFrequency(0) = Frequency Or Frequency = 0
        ok = 1  
      EndIf 
    EndIf 
    timeout+ 1 
    If timeout = 2400 ; Sind 2 minuten. 2400 * 50 = 120000 millisec. 
      Break 
    EndIf 
  Until ok 
  ProcedureReturn ok 
EndProcedure 

ChangeDisplaySettings(1024,768,16,75) 
EnableExplicit 

Declare WindowCallback(hWnd,uMsg,wParam,lParam) 
Declare CreateOverlayFromSprite(Sprite) 
Declare ShowOverlay(*DDS.IDirectDrawSurface7,X,Y,Width,Height) 
Declare HideOverlay(*DDS.IDirectDrawSurface7) 
Declare FreeOverlay(*DDS.IDirectDrawSurface7) 

#DDOVER_HIDE = $00000200 
#DDOVER_SHOW = 16384 
#DDSCAPS_OVERLAY = 128    
#DDSCAPS_VIDEOMEMORY = 16384 
#DDSD_PIXELFORMAT = 4096 
#DDSD_CAPS = 1 
#DDSD_HEIGHT = 2 
#DDSD_WIDTH = 4 
#DDPF_RGB = 64 
#DDPF_FOURCC = 4 
#DDLOCK_WAIT = 1 

Structure DDPIXELFORMAT 
   dwSize.l 
   dwFlags.l 
   dwFourCC.l 
   dwRGBBitCount.l 
   dwRBitMask.l 
   dwGBitMask.l 
   dwBBitMask.l 
   dwRGBAlphaBitMask.l 
EndStructure 

Structure DDCOLORKEY 
   dwColorSpaceLowValue.l 
   dwColorSpaceHighValue.l 
EndStructure 

Structure DDSCAPS2 
   dwCaps.l 
   dwCaps2.l 
   dwCaps3.l 
   dwCaps4.l 
EndStructure 

Structure DDSURFACEDESC2 
   dwSize.l 
   dwFlags.l 
   dwHeight.l 
   dwWidth.l 
   lPitch.l 
   dwBackBufferCount.l 
   dwRefreshRate.l 
   dwAlphaBitDepth.l 
   dwReserved.l 
   lpSurface.l 
   ddckCKDestOverlay.DDCOLORKEY 
   ddckCKDestBlt.DDCOLORKEY 
   ddckCKSrcOverlay.DDCOLORKEY 
   ddckCKSrcBlt.DDCOLORKEY 
   ddpfPixelFormat.DDPIXELFORMAT 
   ddsCaps.DDSCAPS2 
   dwTextureStage.l 
EndStructure 

Structure PB_Sprite 
   Sprite.i 
   Width.w 
   Height.w 
   Depth.w 
   Mode.w 
   FileName.i 
   RealWidth.w 
   RealHeight.w 
   ClipX.w 
   ClipY.w 
EndStructure 

Global bShow, Overlay 

Define x, y, Angle.f, a.b
Define DesktopWidth = GetSystemMetrics_(#SM_CXFULLSCREEN) 
Define DesktopHeight = GetSystemMetrics_(#SM_CYFULLSCREEN) 
Define game_fenster_handel = FindWindow_("Game Fenster Name",#Null)

LoadFont(0,"Arial",32) 

; Open Screen 
InitSprite() 

OpenWindow(0,0,0,100,100,"Overlay-Test",#PB_Window_Invisible) 
OpenWindowedScreen(WindowID(0),0,0,100,100,0,0,0) 

; Create overlay sprite 
CreateSprite(1,256,64) ; Width / height must be dividable by 2 

StartDrawing(SpriteOutput(1)) 
For x=0 To 255 
   For y=0 To 63 
      Plot(x,y,RGB(255 - x,y * 4,x)) 
   Next 
Next 
DrawingFont(FontID(0)) 
DrawingMode(1) 
DrawText(3,3,"Hallo Welt !!!") 
DrawText(0,0,"Hallo Welt !!!",#White) 
StopDrawing() 

Overlay = CreateOverlayFromSprite(1) ; On my computer only one overlay is supported 
; Register the hot key           
RegisterHotKey_(WindowID(0),0,#MOD_ALT,#VK_F11) ; Press ALT + F11 to show / hide the overlay 

SetWindowCallback(@WindowCallback()) 

; ------------------------------------------------------------------------------------------------------ 
; MAIN LOOP 
; ------------------------------------------------------------------------------------------------------ 

Repeat    
   FlipBuffers()    
    
   If bShow 
      Angle + 0.02 
       
      X = Sin(Angle) * (DesktopWidth - 256) / 2 + (DesktopWidth - 256) / 2 
      Y = Cos(Angle) * (DesktopHeight - 64) / 2 + (DesktopHeight - 64) / 2 
      If GetForegroundWindow_() = game_fenster_handel
        ShowOverlay(Overlay,X,Y,256,64) 
        a = 0
      Else
        If a = 0
          HideOverlay(Overlay)
          a = 1
        EndIf
      EndIf
   EndIf 
Until WindowEvent() = #PB_Event_CloseWindow 

FreeOverlay(Overlay) 

; ------------------------------------------------------------------------------------------------------ 
; FUNCTIONS 
; ------------------------------------------------------------------------------------------------------ 

Procedure WindowCallback(hWnd,uMsg,wParam,lParam) 
   Select uMsg 
      Case #WM_HOTKEY 
      bShow = 1 - bShow 
       
      If bShow = 0 : HideOverlay(Overlay) : EndIf 
   EndSelect 
   ProcedureReturn #PB_ProcessPureBasicEvents 
EndProcedure 

; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 

Procedure CreateOverlayFromSprite(Sprite) 
   Protected *Sprite.PB_Sprite, *SrcDDS.IDirectDrawSurface7, *DD.IDirectDraw7, ddsd.DDSURFACEDESC2 
   Protected Width, Height, Result, *DDS.IDirectDrawSurface7, Format, SrcDC, DC, Addr, Pitch, X, Y 
   Protected C1, C2, Y0, U0, V0, Y1, U1, V1 
    
   *Sprite = IsSprite(Sprite) 
    
   *SrcDDS = *Sprite\Sprite 
   *SrcDDS\GetDDInterface(@*DD) 
    
   Width = *Sprite\RealWidth 
   Height = *Sprite\RealHeight 
    
   ddsd.DDSURFACEDESC2 
   ddsd\dwSize = SizeOf(DDSURFACEDESC2) 
   ddsd\ddsCaps\dwCaps = #DDSCAPS_OVERLAY | #DDSCAPS_VIDEOMEMORY 
   ddsd\dwFlags = #DDSD_CAPS | #DDSD_HEIGHT | #DDSD_WIDTH | #DDSD_PIXELFORMAT 
   ddsd\dwWidth = Width 
   ddsd\dwHeight = Height 
    
   ddsd\ddpfPixelFormat\dwSize = SizeOf(DDPIXELFORMAT) 
   ddsd\ddpfPixelFormat\dwFlags = #DDPF_RGB 
   ddsd\ddpfPixelFormat\dwRGBBitCount = 32 
   ddsd\ddpfPixelFormat\dwRBitMask = $F800 
   ddsd\ddpfPixelFormat\dwGBitMask = $07E0 
   ddsd\ddpfPixelFormat\dwBBitMask = $001F 
   Result = *DD\CreateSurface(ddsd,@*DDS,0) 
   Format = 1 
    
   If Result 
      ddsd\ddpfPixelFormat\dwRBitMask = $7C00 
      ddsd\ddpfPixelFormat\dwGBitMask = $03E0 
      ddsd\ddpfPixelFormat\dwBBitMask = $001F 
      Result = *DD\CreateSurface(ddsd,@*DDS,0) 
      Format = 1 
   EndIf 
    
   If Result 
      ddsd\ddpfPixelFormat\dwRGBBitCount = 0 
      ddsd\ddpfPixelFormat\dwRBitMask = 0 
      ddsd\ddpfPixelFormat\dwGBitMask = 0 
      ddsd\ddpfPixelFormat\dwBBitMask = 0 
      ddsd\ddpfPixelFormat\dwFlags = #DDPF_FOURCC 
      ddsd\ddpfPixelFormat\dwFourCC = PeekL(@"UYVY") 
      Result = *DD\CreateSurface(ddsd,@*DDS,0) 
      Format = 2 
   EndIf 
    
   If Result 
      ddsd\ddpfPixelFormat\dwFourCC = PeekL(@"YUY2") 
      Result = *DD\CreateSurface(ddsd,@*DDS,0) 
      Format = 3 
   EndIf 
    
   If Result : MessageRequester("Error","Can't create Surface !") : End : EndIf 
    
   SrcDC = StartDrawing(SpriteOutput(Sprite)) 
  
   If Format = 1    
      *DDS\GetDC(@DC) 
      BitBlt_(DC,0,0,Width,Height,SrcDC,0,0,#SRCCOPY) 
      *DDS\ReleaseDC(DC)       
   Else 
      *DDS\Lock(0,ddsd,#DDLOCK_WAIT,0) 
       
      Addr = ddsd\lpSurface 
      Pitch = ddsd\lPitch 
       
      For y = 0 To Height-1 
         For x = 0 To Width-1 Step 2          
            C1 = Point(x,y) 
            C2 = Point(x + 1,y) 
             
            Y0 =      ( Red(C1) * 29 +Green(C1) * 57 +Blue(C1) * 14) / 100 
            U0 = 128 +(-Red(C1) * 14 -Green(C1) * 29 +Blue(C1) * 43) / 100 
            V0 = 128 +( Red(C1) * 36 -Green(C1) * 29 -Blue(C1) * 07) / 100 
             
            Y1 =      ( Red(C2) * 29 +Green(C2) * 57 +Blue(C2) * 14) / 100 
            U1 = 128 +(-Red(C2) * 14 -Green(C2) * 29 +Blue(C2) * 43) / 100 
            V1 = 128 +( Red(C2) * 36 -Green(C2) * 29 -Blue(C2) * 07) / 100 
             
            Select Format 
               Case 2 
               PokeL(Addr,Y1 << 24 + ((V0 + V1) / 2) << 16 + Y0 << 8 + (U0 + U1) / 2) : Addr + 4 
                
               Case 3 
               PokeL(Addr,((V0 + V1) / 2) << 24 + Y1 << 16 + ((U0 + U1) / 2) << 8 + Y0) : Addr + 4 
            EndSelect          
         Next 
          
         Addr + (Pitch - Width * 2) 
      Next 
       
      *DDS\UnLock(0) 
   EndIf 
    
   StopDrawing() 
    
   ProcedureReturn *DDS 
EndProcedure 

; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 

Procedure ShowOverlay(*DDS.IDirectDrawSurface7,X,Y,Width,Height) 
   Protected re1.RECT, re2.RECT, *DD.IDirectDraw7, *GDI.IDirectDrawSurface7 
     
    SetRect_(re1,X,Y,X + Width,Y + Height) 
   SetRect_(re2,0,0,Width,Height) 
    
   *DDS\GetDDInterface(@*DD) 
   *DD\GetGDISurface(@*GDI) 
    
   *DDS\UpdateOverlay(re2,*GDI,re1,#DDOVER_SHOW,0) 
EndProcedure 

; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 

Procedure HideOverlay(*DDS.IDirectDrawSurface7) 
   Protected *DD.IDirectDraw7, *GDI.IDirectDrawSurface7 
    
   *DDS\GetDDInterface(@*DD) 
   *DD\GetGDISurface(@*GDI) 
    
   *DDS\UpdateOverlay(0,*GDI,0,#DDOVER_HIDE,0) 
EndProcedure 

; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 

Procedure FreeOverlay(*DDS.IDirectDrawSurface7) 
   ProcedureReturn *DDS\Release() 
EndProcedure
Windows 10 x64 Pro - PB 5.61 X64 / x32 - PB 4.6 x32
Benutzeravatar
Fluid Byte
Beiträge: 3110
Registriert: 27.09.2006 22:06
Wohnort: Berlin, Mitte

Beitrag von Fluid Byte »

Jetzt wird doch wieder mit Delays gearbeitet ... /:->

Außerdem, der Code funktioniert nicht, geht in eine Endlosschleife. Was ich meine ist eine Funktion der erst zurückgibt wenn der Vorgang abgeschlossen ist.

Aber wie ich schon sagte, Overlays mit DX 7 machen mehr Probleme als das sie Nutzen haben. Die einzig sinnvolle Lösung ist ein D3D9 hook. Ich habe auch bereits via Google einen in C++ gefunden der tatsächlich funktioniert. Mit vorkompilierter DLL und Launcher. Jetzt muss ich mir noch VS 2008 installieren und versuchen den Code zu verstehen und anzupassen. Wird wohl ziemlich anstrengend aber es lohnt sich.
Windows 10 Pro, 64-Bit / Outtakes | Derek
Andreas21
Beiträge: 390
Registriert: 30.08.2004 09:05
Computerausstattung: Desktop
Windows 10 Pro x64
CPU: AMD Ryzen 5 2600 3.40 GHz
Ram: 16GB RAM
Grafik: NVIDA Geforce 1060
PB: 5.72 X86/X64
Wohnort: Heidelberg

Beitrag von Andreas21 »

Code: Alles auswählen

Procedure.l ChangeDisplaySettings(Width.l,Height.l,Depth.l,Frequency.l=0) 
  Protected lpdm.DEVMODE\dmSize = SizeOf(DEVMODE), ok.b, timeout.l 

  lpdm\dmFields = #DM_BITSPERPEL | #DM_PELSWIDTH | #DM_PELSHEIGHT 
  lpdm\dmBitsPerPel = Depth 
  lpdm\dmPelsWidth = Width 
  lpdm\dmPelsHeight = Height  
  If Frequency 
    lpdm\dmFields = lpdm\dmFields | #DM_DISPLAYFREQUENCY 
    lpdm\dmDisplayFrequency = Frequency 
  EndIf 
  ChangeDisplaySettings_(lpdm,0) 
  Repeat 
    Delay(50) 
    ExamineDesktops() 
    If DesktopWidth(0) = Width And DesktopHeight(0) = Height And DesktopDepth(0) = Depth 
      If DesktopFrequency(0) = Frequency Or Frequency = 0 
        ok = 1  
      EndIf 
    EndIf 
    timeout+ 1 
    If timeout = 2400 ; Sind 2 minuten. 2400 * 50 = 120000 millisec. 
      Break 
    EndIf 
  Until ok 
  ProcedureReturn ok 
EndProcedure 
Wieso Endlosschleife? Der hat doch einen Timeout drin von max 2 min. Dann bricht er selber ab.

Kann man die URL haben zu dem D3D9 hook?
Windows 10 x64 Pro - PB 5.61 X64 / x32 - PB 4.6 x32
Benutzeravatar
Fluid Byte
Beiträge: 3110
Registriert: 27.09.2006 22:06
Wohnort: Berlin, Mitte

Beitrag von Fluid Byte »

> Wieso Endlosschleife? Der hat doch einen Timeout drin von max 2 min. Dann bricht er selber ab.
Ne ne, das passiert gar nichts. Hab' das Timeout auf 500ms gesetzt, passiert auch nix. Es gibt auch keine Debugausgabe. Aber lass gut sein. Dieser Code hat so viele Probleme und basiert auf einer völlig veralteten Technik. Das hat keinen Sinn mehr sich damit weiter rumzuschlagen.

> Kann man die URL haben zu dem D3D9 hook?
Ehrlich gesagt, nein. Aber schick mir mal eine PM :wink:
Windows 10 Pro, 64-Bit / Outtakes | Derek
Antworten