Direct Draw Clipper Problem



  • Hallo
    beschäftige mich erst seit kurzem mit DDraw, bitte deshalb um ein wenig nachsicht beim meinem Problem.
    Ich habe ein Fenster gebundenes Direct Draw erstellt, siehe Code.

    void CamDun::CreateDD()
    {
    	int iRet ;
    	lpDD = NULL ;
    	lpSurface = NULL ;
    
    	//<--	 Create DirectDraw	-->
    	iRet = DirectDrawCreate( NULL, &lpDD, NULL ) ;
    	if(iRet!= DD_OK )
    	{
    		sprintf(strErrorMSG, "DirectDrawCreate Error[%d]", iRet) ;        
    		::MessageBox(this->m_hWnd,strErrorMSG,"Error",MB_OK) ;
    	}
    
    	iRet = lpDD->SetCooperativeLevel( this->m_hWnd, DDSCL_NORMAL )  ;
    	if(iRet!= DD_OK )
    	{
    		sprintf(strErrorMSG, "SetCooperativeLevel Error[%d]", iRet) ;        
    		::MessageBox(this->m_hWnd,strErrorMSG,"Error",MB_OK) ;
    	}
    
    	ZeroMemory(&ddsd, sizeof(ddsd)) ;
    	ddsd.dwSize = sizeof(ddsd) ;
    	iRet = lpDD->GetDisplayMode( &ddsd ) ;
    	if( iRet != DD_OK )
    	{
    		sprintf(strErrorMSG, "GetDisplayMode Error[%d]", iRet) ;        
    		::MessageBox(this->m_hWnd,strErrorMSG,"Error",MB_OK) ;
    	}
    
    	iRet = lpDD->SetDisplayMode( ddsd.dwWidth, ddsd.dwHeight, ddsd.ddpfPixelFormat.dwRGBBitCount ) ;
    	if( iRet != DD_OK )
    	{
    		sprintf(strErrorMSG, "SetDisplayMode Error[%d]", iRet) ;        
    		::MessageBox(this->m_hWnd,strErrorMSG,"Error",MB_OK) ;
    	}
    
    	//<--	 Create palette	-->
    	LPDIRECTDRAWPALETTE lpDDPalette ;
    
    	iRet = lpDD->CreatePalette( DDPCAPS_8BIT, pe, &lpDDPalette, NULL ) ;
    	if( iRet != DD_OK )
    	{
    		sprintf(strErrorMSG, "CreatePalette Error[%d]", iRet) ;       
    		::MessageBox(this->m_hWnd,strErrorMSG,"Error",MB_OK) ;
    	}
    
    	//<--	 Create Primary Surface	-->
    	ddsd.dwSize = sizeof(ddsd) ;
    	ddsd.dwFlags = DDSD_CAPS ;
    	ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE ;
    
    	iRet = lpDD->CreateSurface( &ddsd, &lpSurface, NULL ) ;
    	if( iRet == DD_OK )
    	{
    		ZeroMemory(&ddsd, sizeof(ddsd)) ;
    		ddsd.dwSize = sizeof( ddsd ) ;
    		lpSurface->SetPalette( lpDDPalette ) ;
    	}
    	else
    	{
    		sprintf(strErrorMSG, "Primary CreateSurface Error[%d]", iRet) ;        
    		::MessageBox(this->m_hWnd,strErrorMSG,"Error",MB_OK) ;
    	}
    
    	//<-- Create OffDisp Surface Back-Buffer	-->
    	ZeroMemory(&ddsd, sizeof(ddsd)) ;
    	ddsd.dwSize = sizeof(ddsd) ;
    	ddsd.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH ;
    	ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN ;
    	ddsd.dwHeight = 1024;
    	ddsd.dwWidth = 1280;
    
    	iRet = lpDD->CreateSurface( &ddsd, &lpOffScr, NULL ) ;
    	if( iRet == DD_OK )
    	{
    		ZeroMemory(&ddsd, sizeof(ddsd)) ;
    		ddsd.dwSize = sizeof( ddsd ) ;
    		lpOffScr->SetPalette( lpDDPalette ) ;
    	}
    	else
    	{
    		sprintf(strErrorMSG, "OffScreen CreateSurface Error[%d]", iRet) ;       
    		::MessageBox(this->m_hWnd,strErrorMSG,"Error",MB_OK) ;
    	}
    
    	//<-- Clipper anlegen und mit der primären Oberfläche verbinden -->
        iRet = lpDD->CreateClipper( 0, &lpDDClipper, NULL );
    
    	//<-- Clipper mit dem Hauptfenster der Anwendung verbinden, damit er	-->
    	//<-- von Windows auf dem laufenden gehalten wird	-->
    	iRet = lpDDClipper->SetHWnd( 0, this->m_hWnd );
    
    	//<-- Clipper mit der primären Oberfläche verbinden, damit Blt	-->
    	//<-- Ausgaben entsprechend begrenzt.	-->
    	iRet = lpSurface->SetClipper( lpDDClipper );
    
      //<-- Clipper freigeben   -->
      lpDDClipper->Release();
    }
    

    Wenn ich jetzt ein Bild Blt. möchte, nimmt er nicht die linke obere koordinate meines Programms, wo ich es haben möchte, sondern die linke obere Ecke des Hauptfensters(Win).

    void CamDun::BmpData(unsigned char * dat)
    {
    	RECT rect ;
    	ddsd.dwFlags = DDSD_PITCH ;
    	// Zeilen offset von anfang bis ende
    	ddsd.lPitch = 1280 ;
    
    	int width, height, pitch ;
    
    	// Blockieren und Bild aufbauen
    	iRet = lpOffScr->Lock( NULL, &ddsd, 0, NULL ) ;
    	if ( iRet == DD_OK )
    	{
    		width = ddsd.dwWidth ;
    		height = ddsd.dwHeight ;
    		pitch = ddsd.lPitch ;
    
    		BYTE *lpDDMemory = (BYTE *)ddsd.lpSurface ;
    		BYTE *lpBMPMemory = (BYTE *)((BYTE *)dat) ;	// Bilddaten array
    		int src_width ;
    
    		// Zeilenlängen vergleichen
    		if (bINFO.bmiHeader.biWidth > ddsd.lPitch)
    			src_width = ddsd.lPitch ;
    		else
    			src_width = bINFO.bmiHeader.biWidth ;
    
    		for(i=0; i < bINFO.bmiHeader.biHeight ; i++)        // Zeilenweise einleisen
    		{
    			RGB_Trans((char *)lpDDMemory, (char *)lpBMPMemory, bINFO.bmiHeader.biWidth) ;
    			lpDDMemory += ddsd.lPitch ;
    			lpBMPMemory += src_width ;
    		}
    
    		// Draw Coord 
    		this->Draw_Coord() ;
    
    		//Freigeben	
    		lpOffScr->Unlock( NULL ) ;
    
    		// und Bild im Primary Surface zeichnen Rechteck setzen
    		SetRect (&rect, 0, 0, 896, 768); 
    		lpSurface->Blt(&rect, lpOffScr, &rect, DDBLT_ASYNC, NULL) ;
    	}
    }
    

    Was mache ich den Falsch?, den das Passiert mir auch, wenn ich auf dieses Bild weiter GDI-Zeichenoperationen machen möchte, siehe Bild.
    Gelbes Pfeil zeigt an, wo er anfängt zu zeichnen.
    Rote Pfeil, zeigt an, wo er "anfangen soll" zu zeichnen.
    http://www.informatik.fh-wiesbaden.de/~wreid001/clipperProblem.jpg
    Ich bitte um eure Hilfe.



  • Der Computer macht vermutlich genau was du ihm sagst, also musst du einfach den richtigen Bereich setzen. Uebrigens ist der DDraw Clipper sehr langsam, ich wuerde ihn nicht benutzen. f'`8k

    Autocogito

    Gruß, TGGC (\-/ has leading)



  • Welche andere Wahl habe ich denn?

    Mit welcher Methode kann ich DDraw an Fenster binden?

    Gruß wreid



  • Du hast die Wahl zwischen Clipper benutzen oder nicht benutzen.

    An ein Fenster bindet man DDraw, indem man das hwnd uebergibt. f'`8k

    Autocogito

    Gruß, TGGC (\-/ has leading)



  • Was mache ich den hier Falsch?

    // Clipper anlegen und mit der primären Oberfläche verbinden
    iRet = lpDD->CreateClipper( 0, &lpDDClipper, NULL );
    
    // Clipper mit dem Hauptfenster der Anwendung verbinden, damit er 
    // von Windows auf dem laufenden gehalten wird
    iRet = lpDDClipper->SetHWnd( 0, m_hWnd );
    
    // Clipper mit der primären Oberfläche verbinden, damit Blt
    // Ausgaben entsprechend begrenzt.
    iRet = lpSurface->SetClipper( lpDDClipper )
    
    lpDDClipper->Release();
    

    Gruß wreid



  • Möchte noch paar inforamtionen mit geben.
    in der View-Klasse definiere ich den Fensterbereich und übergebe das ganze an CamDun-Klasse

    m_display.Create(NULL, 
                     WS_CHILD | WS_VISIBLE | WS_BORDER | SS_BLACKFRAME | SS_SUNKEN, 
                     WndBuilder->DisplayArea,
                     this, NULL);
    
    CamHwnd = m_display.GetSafeHwnd();
    m_s = new CamDun(CamHwnd);
    

    in der CamDun-Klasse der Konsturktor

    CamDun::CamDun(HWND hWnd)
    {
    WndBuilder  = new CWndBuilder();
    m_hWnd = hWnd;
    }
    

    Und somit habe ich doch HWND an Clipper übergeben oder ????



  • Sagt dir AdjustWindowRect() was?

    Wenn nicht noch mal melden 😉



  • TGGC schrieb:

    ...Uebrigens ist der DDraw Clipper sehr langsam, ich wuerde ihn nicht benutzen. f'`8k

    TGGC würde einen eigenen Clipper programmieren. Würde ich auch machen. Aber nur wenn ich eine Vollbildanwendung programmieren würde. Ansonsten nimm den DirectDraw Clipper. Ich wüsste jetzt nicht was dagegen sprechen sollte.



  • Netzwerk-Latenz schrieb:

    Ich wüsste jetzt nicht was dagegen sprechen sollte.

    Das damit blitten drei mal so lang dauert? War zumindest bei meiner letzten Messung so. f'`8k

    Gruß, TGGC (\-/ has leading)



  • AdjustWindowRect() hat mir sehr geholfen, jetzt wird alles angezeigt, wie sein sollte.

    Ich weis nicht ob ich noch einen neuen Beitrag eröffnen soll, ich habe ein Problem und weis nicht wie ich es lösen soll.
    Folgendes:
    Über ein LiveBild möchte ich ein Overlay erzeugen.

    /************************************/
    /* Create DirectDraw                */
    /************************************/
    iRet = DirectDrawCreate( NULL, &lpDD, NULL ) ;
    if(iRet!= DD_OK )
    {
    	sprintf(strErrorMSG, "DirectDrawCreate Error[%d]", iRet) ;        
    	::MessageBox(this->m_hWnd,strErrorMSG,"Error",MB_OK) ;
    }
    
    iRet = lpDD->SetCooperativeLevel( this->m_hWnd, DDSCL_NORMAL )  ;
    if(iRet!= DD_OK )
    {
    	sprintf(strErrorMSG, "SetCooperativeLevel Error[%d]", iRet) ;        
    	::MessageBox(this->m_hWnd,strErrorMSG,"Error",MB_OK) ;
    }
    
    ZeroMemory(&ddsd, sizeof(ddsd)) ;
    ddsd.dwSize = sizeof(ddsd) ;
    iRet = lpDD->GetDisplayMode( &ddsd ) ;
    if( iRet != DD_OK )
    {
    	sprintf(strErrorMSG, "GetDisplayMode Error[%d]", iRet) ;        
    	::MessageBox(this->m_hWnd,strErrorMSG,"Error",MB_OK) ;
    }
    
    iRet = lpDD->SetDisplayMode( ddsd.dwWidth, ddsd.dwHeight, ddsd.ddpfPixelFormat.dwRGBBitCount ) ;
    if( iRet != DD_OK )
    {
    	sprintf(strErrorMSG, "SetDisplayMode Error[%d]", iRet) ;
    	::MessageBox(this->m_hWnd,strErrorMSG,"Error",MB_OK) ;
    }
    
    // Create palette
    LPDIRECTDRAWPALETTE lpDDPalette ;
    
    iRet = lpDD->CreatePalette( DDPCAPS_8BIT, pe, &lpDDPalette, NULL ) ;
    if( iRet != DD_OK )
    {
    	sprintf(strErrorMSG, "CreatePalette Error[%d]", iRet) ; 
    	::MessageBox(this->m_hWnd,strErrorMSG,"Error",MB_OK) ;
    }
    /***********************************/
    /* Erzeuge ein overlay surface      */
    /***********************************/
    ddPixelFormat.dwSize = sizeof(DDPIXELFORMAT);
    ddPixelFormat.dwFlags = DDPF_RGB;
    ddPixelFormat.dwFourCC= 0;
    ddPixelFormat.dwRGBBitCount = 16;
    
    memcpy(&(ddsd.ddpfPixelFormat), &ddPixelFormat, sizeof(DDPIXELFORMAT));
    
    iRet = lpDD->CreateSurface( &ddsd, &lpOverlay, NULL );
    if( iRet != DD_OK )
    {
      TRACE("Kann kein Overlay erzeugen ! 0x%08lx\n", iRet);
    }
    ...
    

    Nun dies funkt noch soweit, aber wenn ich das Overlay seigen möchte stützt das Prog ab.

    /***********************************/
    /* Positioniere und zeige  overlay */
    /***********************************/	
    CRect rectClient, rectOverlay;
    HRESULT iRet;
    GetWindowRect( &rectClient);
    AdjustWindowRect(&rectClient, GetStyle(), NULL);
    
    SetRect(&rectOverlay, 0, 0, 896, 768);
    
    ddofx.dwSize = sizeof(DDOVERLAYFX);
    ddofx.dckDestColorkey.dwColorSpaceLowValue = dwKeyColour;
    ddofx.dckDestColorkey.dwColorSpaceHighValue = dwKeyColour;
    
    dwFlags = DDOVER_KEYDESTOVERRIDE | DDOVER_SHOW;
    
    iRet = IDirectDrawSurface_UpdateOverlay(lpOverlay, &rectClient, lpSurface, &rectClient, dwFlags, &ddofx);
    if(iRet != DD_OK)
    {
    	::MessageBox(this->m_hWnd,"UpdateOverlay kann nicht angezeigt werden.\n","Error",MB_OK);
    }
    

    Es wird fehlerfrei kompiliert.
    Da ich auch Primär sowie Back Surface benutze, denke ich das ich kein Overlay mehr anlegen kann. Beziehungsweise implementiere ich Overlay falsch.
    Auf dem Overlay möchte ich Text ausgeben, sowie verschieden GDI-Methoden ausführen. Könnt ihr mich ein wenig nachhelfen, was ich da falsch mache.

    Gruß Waldemar



  • So wie ich das sehe hast du mehrere Probleme.



  • Ich wäre dir sehr dankbar, wenn du mir mein problem zeigen würdest. Es sieht so aus, als würde ich den wald vor lauter bäumen nicht sehen 😞 .


Anmelden zum Antworten