#include <d3d11.h>
#include <Array.h>
#include <Punkt.h>
#include <Bild.h>
#include <Fenster.h>
#include <Text.h>
#include <Zeichnung.h>
#include <Globals.h>
#include <Zeit.h>
#include <ToolTip.h>
#include <MausEreignis.h>
#include <TextFeld.h>
#include <TastaturEreignis.h>
#include <RenderThread.h>
#include <iostream>
#include <Bildschirm.h>
#include <d3dx10math.h>
#include <d3dx11async.h>

using namespace Framework;

namespace Framework2
{
    //Diese Klasse wird das Bild auf dem Bildschirm verwalten
    class Bildschirm : public Framework::Bildschirm
    {
    private:
        struct VertexType
        {
            D3DXVECTOR3 position;
            D3DXVECTOR2 texture;
        };
        struct MatrixBufferType
        {
            D3DXMATRIX world;
            D3DXMATRIX view;
            D3DXMATRIX projection;
        };
        ID3D11Device *d3d11Device;
        ID3D11DeviceContext *d3d11Context;
        IDXGISwapChain *d3d11SpawChain;
        ID3D11Texture2D *d3d11FrameworkBuffer;
        ID3D11Buffer *vertexBuffer, *indexBuffer;
        ID3D11VertexShader* vertexShader;
        ID3D11PixelShader* pixelShader;
        ID3D11InputLayout* layout;
        ID3D11Buffer* matrixBuffer;
        ID3D11SamplerState* sampleState;
        ID3D11ShaderResourceView *resource;
        ID3D11RenderTargetView *rtview;
        ID3D11DepthStencilView *dsView;
        ID3D11Texture2D *depthStencilBuffer;
        ID3D11DepthStencilState *depthStencilState;
        ID3D11RasterizerState *rasterizerState;
        ID3D11DepthStencilState *depthDisabledStencilState;
        ID3D11BlendState *blendStateAlphaBlend;

        WFenster *fenster;
        Bild *renderB;
        int ref;
        ZeichnungArray *members;
        int füllFarbe;
        int deckFarbe;
        Zeichnung *onTop;
        bool renderOnTop;
        bool renderZeichnungen;
        bool vollbild;
        bool rendering;
        ZeitMesser *renderZeit;
        Punkt backBufferGröße;
        CRITICAL_SECTION cs;
        RCArray< ToolTip > *tips;
        int tipAnzahl;
        bool testRend;
        bool füll;
        bool rend;

    public:
        // Konstruktor 
        Bildschirm( WFenster *fenster )
            : Framework::Bildschirm( 0 ),
            d3d11Device( 0 ),
            d3d11Context( 0 ),
            d3d11SpawChain( 0 ),
            d3d11FrameworkBuffer( 0 ),
            vertexBuffer( 0 ),
            indexBuffer( 0 ),
            vertexShader( 0 ),
            pixelShader( 0 ),
            layout( 0 ),
            matrixBuffer( 0 ),
            sampleState( 0 ),
            resource( 0 ),
            rtview( 0 ),
            dsView( 0 ),
            depthStencilBuffer( 0 ),
            depthStencilState( 0 ),
            rasterizerState( 0 ),
            depthDisabledStencilState( 0 ),
            blendStateAlphaBlend( 0 ),
            fenster( fenster ),
            renderB( new Bild( 1 ) ),
            ref( 1 ),
            members( new ZeichnungArray() ),
            füllFarbe( 0 ),
            deckFarbe( 0 ),
            onTop( 0 ),
            renderOnTop( 0 ),
            renderZeichnungen( 1 ),
            vollbild( 0 ),
            rendering( 0 ),
            renderZeit( new ZeitMesser() ),
            backBufferGröße( 0, 0 ),
            tips( new RCArray< ToolTip >() ),
            tipAnzahl( 0 ),
            testRend( 1 ),
            füll( 1 ),
            rend( 0 )
        {
            InitializeCriticalSection( &cs );
        }
        // Destruktor 
        ~Bildschirm()
        {
            lock();
            if( renderB )
                renderB->release();
            if( d3d11Device )
            {
                d3d11Device->Release();
                d3d11Device = NULL;
            }
            if( d3d11Context )
            {
                d3d11Context->Release();
                d3d11Context = NULL;
            }
            if( d3d11SpawChain )
            {
                d3d11SpawChain->Release();
                d3d11SpawChain = NULL;
            }
            if( d3d11FrameworkBuffer )
            {
                d3d11FrameworkBuffer->Release();
                d3d11FrameworkBuffer = NULL;
            }
            if( vertexBuffer )
            {
                vertexBuffer->Release();
                vertexBuffer = NULL;
            }
            if( indexBuffer )
            {
                indexBuffer->Release();
                indexBuffer = NULL;
            }
            if( pixelShader )
            {
                pixelShader->Release();
                pixelShader = NULL;
            }
            if( vertexShader )
            {
                vertexShader->Release();
                vertexShader = NULL;
            }
            if( layout )
            {
                layout->Release();
                layout = 0;
            }
            if( matrixBuffer )
            {
                matrixBuffer->Release();
                matrixBuffer = 0;
            }
            if( sampleState )
            {
                sampleState->Release();
                sampleState = 0;
            }
            if( resource )
            {
                resource->Release();
                resource = 0;
            }
            if( rtview )
            {
                rtview->Release();
                rtview = 0;
            }
            if( dsView )
            {
                dsView->Release();
                dsView = 0;
            }
            if( depthStencilBuffer )
            {
                depthStencilBuffer->Release();
                depthStencilBuffer = 0;
            }
            if( depthStencilState )
            {
                depthStencilState->Release();
                depthStencilState = 0;
            }
            if( rasterizerState )
            {
                rasterizerState->Release();
                rasterizerState = 0;
            }
            if( depthDisabledStencilState )
            {
                depthDisabledStencilState->Release();
                depthDisabledStencilState = 0;
            }
            if( blendStateAlphaBlend )
            {
                blendStateAlphaBlend->Release();
                blendStateAlphaBlend = 0;
            }
            if( fenster )
                fenster->release();
            delete members;
            tipAnzahl = 0;
            tips->release();
            renderZeit->release();
            unlock();
            DeleteCriticalSection( &cs );
        }
        // nicht constant 
        void lock()
        {
            EnterCriticalSection( &cs );
        }
        void unlock()
        {
            LeaveCriticalSection( &cs );
        }
        void setFüll( bool f )
        {
            füll = f;
        }
        void update()
        {
            lock();
            HRESULT result;

            //------------------------------------------------------
            // Clean up
            if( d3d11Device )
            {
                d3d11Device->Release();
                d3d11Device = 0;
            }
            if( d3d11Context )
            {
                d3d11Context->Release();
                d3d11Context = 0;
            }
            if( d3d11SpawChain )
            {
                d3d11SpawChain->Release();
                d3d11SpawChain = NULL;
            }
            if( d3d11FrameworkBuffer )
            {
                d3d11FrameworkBuffer->Release();
                d3d11FrameworkBuffer = 0;
            }
            if( vertexBuffer )
            {
                vertexBuffer->Release();
                vertexBuffer = NULL;
            }
            if( indexBuffer )
            {
                indexBuffer->Release();
                indexBuffer = NULL;
            }
            if( pixelShader )
            {
                pixelShader->Release();
                pixelShader = NULL;
            }
            if( vertexShader )
            {
                vertexShader->Release();
                vertexShader = NULL;
            }
            if( layout )
            {
                layout->Release();
                layout = 0;
            }
            if( matrixBuffer )
            {
                matrixBuffer->Release();
                matrixBuffer = 0;
            }
            if( sampleState )
            {
                sampleState->Release();
                sampleState = 0;
            }
            if( resource )
            {
                resource->Release();
                resource = 0;
            }
            if( rtview )
            {
                rtview->Release();
                rtview = 0;
            }
            if( dsView )
            {
                dsView->Release();
                dsView = 0;
            }
            if( depthStencilBuffer )
            {
                depthStencilBuffer->Release();
                depthStencilBuffer = 0;
            }
            if( depthStencilState )
            {
                depthStencilState->Release();
                depthStencilState = 0;
            }
            if( rasterizerState )
            {
                rasterizerState->Release();
                rasterizerState = 0;
            }
            if( depthDisabledStencilState )
            {
                depthDisabledStencilState->Release();
                depthDisabledStencilState = 0;
            }
            if( blendStateAlphaBlend )
            {
                blendStateAlphaBlend->Release();
                blendStateAlphaBlend = 0;
            }
            //--------------------------------------------------------------------
            // Create Device

            // create a struct to hold information about the swap chain
            DXGI_SWAP_CHAIN_DESC scd;

            // clear out the struct for use
            ZeroMemory( &scd, sizeof( DXGI_SWAP_CHAIN_DESC ) );

            // fill the swap chain description struct
            scd.BufferCount = 1;                                           // one back buffer
            scd.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;             // how swap chain is to be used
            scd.OutputWindow = fenster ? fenster->getFensterHandle() : 0;  // the window to be used
            scd.SampleDesc.Count = 1;
            // Set the scan line ordering and scaling to unspecified.
            scd.BufferDesc.ScanlineOrdering = DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED;
            scd.BufferDesc.Scaling = DXGI_MODE_SCALING_UNSPECIFIED;
            scd.Windowed = !vollbild;
            if( !backBufferGröße.x || !backBufferGröße.y )
                backBufferGröße = fenster ? fenster->getKörperGröße() : Punkt( 0, 0 );
            scd.BufferDesc.Width = backBufferGröße.x;
            scd.BufferDesc.Height = backBufferGröße.y;                 // windowed/full-screen mode
            scd.BufferDesc.RefreshRate.Denominator = 1;
            scd.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;       // use 32-bit color
            // Discard the back buffer contents after presenting.
            scd.SwapEffect = DXGI_SWAP_EFFECT_DISCARD;
            if( renderB )
                renderB->release();
            renderB = new Bild( 1 );
            renderB->neuBild( backBufferGröße.x, backBufferGröße.y, füllFarbe );

            D3D_FEATURE_LEVEL featureLevel = D3D_FEATURE_LEVEL_11_0;
            // create a device, device context and swap chain using the information in the scd struct
            D3D11CreateDeviceAndSwapChain( NULL,
                                           D3D_DRIVER_TYPE_HARDWARE,
                                           NULL,
                                           D3D11_CREATE_DEVICE_DEBUG,
                                           &featureLevel,
                                           1,
                                           D3D11_SDK_VERSION,
                                           &scd,
                                           &d3d11SpawChain,
                                           &d3d11Device,
                                           NULL,
                                           &d3d11Context );

            ID3D11Texture2D *backBufferPtr;
            // Get the pointer to the back buffer.
            result = d3d11SpawChain->GetBuffer( 0, __uuidof( ID3D11Texture2D ), (LPVOID*)&backBufferPtr );
            // Create the render target view with the back buffer pointer.
            result = d3d11Device->CreateRenderTargetView( backBufferPtr, NULL, &rtview );
            // Release pointer to the back buffer as we no longer need it.
            backBufferPtr->Release();
            // Initialize the description of the depth buffer.
            D3D11_TEXTURE2D_DESC depthBufferDesc;
            ZeroMemory( &depthBufferDesc, sizeof( depthBufferDesc ) );
            // Set up the description of the depth buffer.
            depthBufferDesc.Width = backBufferGröße.x;
            depthBufferDesc.Height = backBufferGröße.y;
            depthBufferDesc.MipLevels = 1;
            depthBufferDesc.ArraySize = 1;
            depthBufferDesc.Format = DXGI_FORMAT_D24_UNORM_S8_UINT;
            depthBufferDesc.SampleDesc.Count = 1;
            depthBufferDesc.Usage = D3D11_USAGE_DEFAULT;
            depthBufferDesc.BindFlags = D3D11_BIND_DEPTH_STENCIL;
            // Create the texture for the depth buffer using the filled out description.
            result = d3d11Device->CreateTexture2D( &depthBufferDesc, NULL, &depthStencilBuffer );

            // Initialize the description of the stencil state.
            D3D11_DEPTH_STENCIL_DESC depthStencilDesc;
            ZeroMemory( &depthStencilDesc, sizeof( depthStencilDesc ) );

            // Set up the description of the stencil state.
            depthStencilDesc.DepthEnable = true;
            depthStencilDesc.DepthWriteMask = D3D11_DEPTH_WRITE_MASK_ALL;
            depthStencilDesc.DepthFunc = D3D11_COMPARISON_LESS;

            depthStencilDesc.StencilEnable = true;
            depthStencilDesc.StencilReadMask = 0xFF;
            depthStencilDesc.StencilWriteMask = 0xFF;

            // Stencil operations if pixel is front-facing.
            depthStencilDesc.FrontFace.StencilFailOp = D3D11_STENCIL_OP_KEEP;
            depthStencilDesc.FrontFace.StencilDepthFailOp = D3D11_STENCIL_OP_INCR;
            depthStencilDesc.FrontFace.StencilPassOp = D3D11_STENCIL_OP_KEEP;
            depthStencilDesc.FrontFace.StencilFunc = D3D11_COMPARISON_ALWAYS;

            // Stencil operations if pixel is back-facing.
            depthStencilDesc.BackFace.StencilFailOp = D3D11_STENCIL_OP_KEEP;
            depthStencilDesc.BackFace.StencilDepthFailOp = D3D11_STENCIL_OP_DECR;
            depthStencilDesc.BackFace.StencilPassOp = D3D11_STENCIL_OP_KEEP;
            depthStencilDesc.BackFace.StencilFunc = D3D11_COMPARISON_ALWAYS;

            // Create the depth stencil state.
            result = d3d11Device->CreateDepthStencilState( &depthStencilDesc, &depthStencilState );

            // Set the depth stencil state.
            d3d11Context->OMSetDepthStencilState( depthStencilState, 1 );

            // Initialize the depth stencil view.
            D3D11_DEPTH_STENCIL_VIEW_DESC depthStencilViewDesc;
            ZeroMemory( &depthStencilViewDesc, sizeof( depthStencilViewDesc ) );

            // Set up the depth stencil view description.
            depthStencilViewDesc.Format = DXGI_FORMAT_D24_UNORM_S8_UINT;
            depthStencilViewDesc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2D;

            // Create the depth stencil view.
            result = d3d11Device->CreateDepthStencilView( depthStencilBuffer, &depthStencilViewDesc, &dsView );
            // Bind the render target view and depth stencil buffer to the output render pipeline.
            d3d11Context->OMSetRenderTargets( 1, &rtview, dsView );

            D3D11_RASTERIZER_DESC rasterDesc;
            // Setup the raster description which will determine how and what polygons will be drawn.
            rasterDesc.AntialiasedLineEnable = false;
            rasterDesc.CullMode = D3D11_CULL_BACK;
            rasterDesc.DepthBiasClamp = 0.0f;
            rasterDesc.DepthClipEnable = true;
            rasterDesc.FillMode = D3D11_FILL_SOLID;
            rasterDesc.FrontCounterClockwise = false;
            rasterDesc.MultisampleEnable = false;
            rasterDesc.ScissorEnable = false;
            rasterDesc.SlopeScaledDepthBias = 0.0f;
            // Create the rasterizer state from the description we just filled out.
            result = d3d11Device->CreateRasterizerState( &rasterDesc, &rasterizerState );
            // Now set the rasterizer state.
            d3d11Context->RSSetState( rasterizerState );

            D3D11_VIEWPORT vp;
            memset( &vp, 0, sizeof( D3D11_VIEWPORT ) );
            vp.Width = backBufferGröße.x;
            vp.Height = backBufferGröße.y;
            vp.MinDepth = 0.0f;
            vp.MaxDepth = 1.0f;
            vp.TopLeftX = 0.0f;
            vp.TopLeftY = 0.0f;
            d3d11Context->RSSetViewports( 1, &vp );

            D3D11_DEPTH_STENCIL_DESC depthDisabledStencilDesc;
            // Clear the second depth stencil state before setting the parameters.
            ZeroMemory( &depthDisabledStencilDesc, sizeof( depthDisabledStencilDesc ) );

            // Now create a second depth stencil state which turns off the Z buffer for 2D rendering.  The only difference is 
            // that DepthEnable is set to false, all other parameters are the same as the other depth stencil state.
            depthDisabledStencilDesc.DepthEnable = false;
            depthDisabledStencilDesc.DepthWriteMask = D3D11_DEPTH_WRITE_MASK_ALL;
            depthDisabledStencilDesc.DepthFunc = D3D11_COMPARISON_LESS;
            depthDisabledStencilDesc.StencilEnable = true;
            depthDisabledStencilDesc.StencilReadMask = 0xFF;
            depthDisabledStencilDesc.StencilWriteMask = 0xFF;
            depthDisabledStencilDesc.FrontFace.StencilFailOp = D3D11_STENCIL_OP_KEEP;
            depthDisabledStencilDesc.FrontFace.StencilDepthFailOp = D3D11_STENCIL_OP_INCR;
            depthDisabledStencilDesc.FrontFace.StencilPassOp = D3D11_STENCIL_OP_KEEP;
            depthDisabledStencilDesc.FrontFace.StencilFunc = D3D11_COMPARISON_ALWAYS;
            depthDisabledStencilDesc.BackFace.StencilFailOp = D3D11_STENCIL_OP_KEEP;
            depthDisabledStencilDesc.BackFace.StencilDepthFailOp = D3D11_STENCIL_OP_DECR;
            depthDisabledStencilDesc.BackFace.StencilPassOp = D3D11_STENCIL_OP_KEEP;
            depthDisabledStencilDesc.BackFace.StencilFunc = D3D11_COMPARISON_ALWAYS;

            // Create the state using the device.
            result = d3d11Device->CreateDepthStencilState( &depthDisabledStencilDesc, &depthDisabledStencilState );

            //-------------------------------------------------
            // Shaders
            ID3D10Blob* errorMessage;
            ID3D10Blob* vertexShaderBuffer;
            ID3D10Blob* pixelShaderBuffer;
            D3D11_INPUT_ELEMENT_DESC polygonLayout[ 2 ];

            result = D3DX11CompileFromFile( "texture.vs", NULL, NULL, "TextureVertexShader", "vs_5_0", D3D10_SHADER_ENABLE_STRICTNESS | D3D10_SHADER_DEBUG, 0, NULL,
                                            &vertexShaderBuffer, &errorMessage, NULL );

            if( errorMessage )
            {
                char *err = (char*)errorMessage->GetBufferPointer();
                std::cout << err;
            }

            result = D3DX11CompileFromFile( "texture.ps", NULL, NULL, "TexturePixelShader", "ps_5_0", D3D10_SHADER_ENABLE_STRICTNESS | D3D10_SHADER_DEBUG, 0, NULL,
                                            &pixelShaderBuffer, &errorMessage, NULL );

            if( errorMessage )
            {
                char *err = (char*)errorMessage->GetBufferPointer();
                std::cout << err;
            }

            result = d3d11Device->CreateVertexShader( vertexShaderBuffer->GetBufferPointer(), vertexShaderBuffer->GetBufferSize(), NULL, &vertexShader );
            result = d3d11Device->CreatePixelShader( pixelShaderBuffer->GetBufferPointer(), pixelShaderBuffer->GetBufferSize(), NULL, &pixelShader );

            // Create the vertex input layout description.
            // This setup needs to match the VertexType stucture in the ModelClass and in the shader.
            polygonLayout[ 0 ].SemanticName = "POSITION";
            polygonLayout[ 0 ].SemanticIndex = 0;
            polygonLayout[ 0 ].Format = DXGI_FORMAT_R32G32B32_FLOAT;
            polygonLayout[ 0 ].InputSlot = 0;
            polygonLayout[ 0 ].AlignedByteOffset = 0;
            polygonLayout[ 0 ].InputSlotClass = D3D11_INPUT_PER_VERTEX_DATA;
            polygonLayout[ 0 ].InstanceDataStepRate = 0;

            polygonLayout[ 1 ].SemanticName = "TEXCOORD";
            polygonLayout[ 1 ].SemanticIndex = 0;
            polygonLayout[ 1 ].Format = DXGI_FORMAT_R32G32_FLOAT;
            polygonLayout[ 1 ].InputSlot = 0;
            polygonLayout[ 1 ].AlignedByteOffset = D3D11_APPEND_ALIGNED_ELEMENT;
            polygonLayout[ 1 ].InputSlotClass = D3D11_INPUT_PER_VERTEX_DATA;
            polygonLayout[ 1 ].InstanceDataStepRate = 0;

            // Get a count of the elements in the layout.
            unsigned int numElements = sizeof( polygonLayout ) / sizeof( polygonLayout[ 0 ] );

            // Create the vertex input layout.
            result = d3d11Device->CreateInputLayout( polygonLayout, numElements, vertexShaderBuffer->GetBufferPointer(), vertexShaderBuffer->GetBufferSize(),
                                                     &layout );

            // Release the vertex shader buffer and pixel shader buffer since they are no longer needed.
            vertexShaderBuffer->Release();
            vertexShaderBuffer = 0;

            pixelShaderBuffer->Release();
            pixelShaderBuffer = 0;

            // Setup the description of the dynamic matrix constant buffer that is in the vertex shader.
            D3D11_BUFFER_DESC matrixBufferDesc;
            matrixBufferDesc.Usage = D3D11_USAGE_DYNAMIC;
            matrixBufferDesc.ByteWidth = sizeof( MatrixBufferType );
            matrixBufferDesc.BindFlags = D3D11_BIND_CONSTANT_BUFFER;
            matrixBufferDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
            matrixBufferDesc.MiscFlags = 0;
            matrixBufferDesc.StructureByteStride = 0;

            // Create the constant buffer pointer so we can access the vertex shader constant buffer from within this class.
            result = d3d11Device->CreateBuffer( &matrixBufferDesc, NULL, &matrixBuffer );

            // Create a texture sampler state description.
            D3D11_SAMPLER_DESC samplerDesc;
            samplerDesc.Filter = D3D11_FILTER_MIN_MAG_MIP_LINEAR;
            samplerDesc.AddressU = D3D11_TEXTURE_ADDRESS_WRAP;
            samplerDesc.AddressV = D3D11_TEXTURE_ADDRESS_WRAP;
            samplerDesc.AddressW = D3D11_TEXTURE_ADDRESS_WRAP;
            samplerDesc.MipLODBias = 0.0f;
            samplerDesc.MaxAnisotropy = 1;
            samplerDesc.ComparisonFunc = D3D11_COMPARISON_ALWAYS;
            samplerDesc.BorderColor[ 0 ] = 0;
            samplerDesc.BorderColor[ 1 ] = 0;
            samplerDesc.BorderColor[ 2 ] = 0;
            samplerDesc.BorderColor[ 3 ] = 0;
            samplerDesc.MinLOD = 0;
            samplerDesc.MaxLOD = D3D11_FLOAT32_MAX;

            // Create the texture sampler state.
            result = d3d11Device->CreateSamplerState( &samplerDesc, &sampleState );

            //---------------------------------------------------------------
            // Framework Backbuffer Texture

            D3D11_BUFFER_DESC vertexBufferDesc, indexBufferDesc;
            D3D11_SUBRESOURCE_DATA vertexData, indexData;

            unsigned long indices[ 6 ];
            VertexType vertices[ 6 ];

            // Load the index array with data.
            for( int i = 0; i < 6; i++ )
            {
                indices[ i ] = i;
            }
            vertexBufferDesc.Usage = D3D11_USAGE_DYNAMIC;
            vertexBufferDesc.ByteWidth = sizeof( vertices );
            vertexBufferDesc.BindFlags = D3D11_BIND_VERTEX_BUFFER;
            vertexBufferDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
            vertexBufferDesc.MiscFlags = 0;
            vertexBufferDesc.StructureByteStride = 0;

            // Give the subresource structure a pointer to the vertex data.
            vertexData.pSysMem = vertices;
            vertexData.SysMemPitch = 0;
            vertexData.SysMemSlicePitch = 0;

            // Now create the vertex buffer.
            result = d3d11Device->CreateBuffer( &vertexBufferDesc, &vertexData, &vertexBuffer );

            // Set up the description of the static index buffer.
            indexBufferDesc.Usage = D3D11_USAGE_DEFAULT;
            indexBufferDesc.ByteWidth = sizeof( unsigned long ) * 6;
            indexBufferDesc.BindFlags = D3D11_BIND_INDEX_BUFFER;
            indexBufferDesc.CPUAccessFlags = 0;
            indexBufferDesc.MiscFlags = 0;
            indexBufferDesc.StructureByteStride = 0;

            // Give the subresource structure a pointer to the index data.
            indexData.pSysMem = indices;
            indexData.SysMemPitch = 0;
            indexData.SysMemSlicePitch = 0;

            // Create the index buffer.
            result = d3d11Device->CreateBuffer( &indexBufferDesc, &indexData, &indexBuffer );

            D3D11_TEXTURE2D_DESC bufferDesc;
            memset( &bufferDesc, 0, sizeof( D3D11_TEXTURE2D_DESC ) );
            bufferDesc.ArraySize = 1;
            bufferDesc.Width = backBufferGröße.x;
            bufferDesc.Height = backBufferGröße.y;
            bufferDesc.Format = DXGI_FORMAT_B8G8R8A8_UNORM;
            bufferDesc.BindFlags = D3D11_BIND_SHADER_RESOURCE;
            bufferDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
            bufferDesc.SampleDesc.Count = 1;
            bufferDesc.MipLevels = 1;
            bufferDesc.Usage = D3D11_USAGE_DYNAMIC;

            d3d11Device->CreateTexture2D( &bufferDesc, 0, &d3d11FrameworkBuffer );

            D3D11_SHADER_RESOURCE_VIEW_DESC resourceDesk;
            memset( &resourceDesk, 0, sizeof( D3D11_SHADER_RESOURCE_VIEW_DESC ) );
            resourceDesk.Format = DXGI_FORMAT_B8G8R8A8_UNORM;
            resourceDesk.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D;
            resourceDesk.Texture2D.MipLevels = 1;
            d3d11Device->CreateShaderResourceView( d3d11FrameworkBuffer, &resourceDesk, &resource );

            //resource->Release();
            //result = D3DX11CreateShaderResourceViewFromFile( d3d11Device, "seafloor.dds", NULL, NULL, &resource, NULL );

            float left, right, top, bottom;
            // Calculate the screen coordinates of the left side of the bitmap.
            left = (float)( ( backBufferGröße.x / 2.0 ) * -1 );

            // Calculate the screen coordinates of the right side of the bitmap.
            right = left + (float)backBufferGröße.x;

            // Calculate the screen coordinates of the top of the bitmap.
            top = (float)( backBufferGröße.y / 2.0 );

            // Calculate the screen coordinates of the bottom of the bitmap.
            bottom = top - (float)backBufferGröße.y;

            // Load the vertex array with data.
            // First triangle.
            vertices[ 0 ].position = D3DXVECTOR3( left, top, 0.0f );  // Top left.
            vertices[ 0 ].texture = D3DXVECTOR2( 0.0f, 0.0f );

            vertices[ 1 ].position = D3DXVECTOR3( right, bottom, 0.0f );  // Bottom right.
            vertices[ 1 ].texture = D3DXVECTOR2( 1.0f, 1.0f );

            vertices[ 2 ].position = D3DXVECTOR3( left, bottom, 0.0f );  // Bottom left.
            vertices[ 2 ].texture = D3DXVECTOR2( 0.0f, 1.0f );

            // Second triangle.
            vertices[ 3 ].position = D3DXVECTOR3( left, top, 0.0f );  // Top left.
            vertices[ 3 ].texture = D3DXVECTOR2( 0.0f, 0.0f );

            vertices[ 4 ].position = D3DXVECTOR3( right, top, 0.0f );  // Top right.
            vertices[ 4 ].texture = D3DXVECTOR2( 1.0f, 0.0f );

            vertices[ 5 ].position = D3DXVECTOR3( right, bottom, 0.0f );  // Bottom right.
            vertices[ 5 ].texture = D3DXVECTOR2( 1.0f, 1.0f );


            D3D11_MAPPED_SUBRESOURCE mappedResource;
            // Lock the vertex buffer so it can be written to.
            result = d3d11Context->Map( vertexBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource );

            // Copy the data into the vertex buffer.
            memcpy( mappedResource.pData, (void*)vertices, ( sizeof( VertexType ) * 6 ) );

            // Unlock the vertex buffer.
            d3d11Context->Unmap( vertexBuffer, 0 );

            D3D11_BLEND_DESC blendState;
            ZeroMemory( &blendState, sizeof( D3D10_BLEND_DESC ) );
            blendState.AlphaToCoverageEnable = false;
            blendState.IndependentBlendEnable = false;
            blendState.RenderTarget[ 0 ].BlendEnable = true;
            blendState.RenderTarget[ 0 ].SrcBlend = D3D11_BLEND_SRC_ALPHA;
            blendState.RenderTarget[ 0 ].DestBlend = D3D11_BLEND_INV_SRC_ALPHA;
            blendState.RenderTarget[ 0 ].BlendOp = D3D11_BLEND_OP_ADD;
            blendState.RenderTarget[ 0 ].SrcBlendAlpha = D3D11_BLEND_ZERO;
            blendState.RenderTarget[ 0 ].DestBlendAlpha = D3D11_BLEND_ONE;
            blendState.RenderTarget[ 0 ].BlendOpAlpha = D3D11_BLEND_OP_ADD;
            blendState.RenderTarget[ 0 ].RenderTargetWriteMask = D3D11_COLOR_WRITE_ENABLE_ALL;

            d3d11Device->CreateBlendState( &blendState, &blendStateAlphaBlend );

            rend = 1;
            unlock();
        }
        void setTestRend( bool tr )
        {
            testRend = tr;
        }
        void setRenderZeichnungen( bool rO )
        {
            lock();
            renderZeichnungen = rO;
            rend = 1;
            unlock();
        }
        void setOnTop( bool onTop )
        {
            renderOnTop = onTop;
            rend = 1;
        }
        void setOnTopZeichnung( Zeichnung *obj )
        {
            lock();
            onTop = obj;
            rend = 1;
            unlock();
        }
        void setdeckFarbe( int f )
        {
            deckFarbe = f;
            rend = 1;
        }
        void addMember( Zeichnung *obj )
        {
            lock();
            members->addZeichnung( obj );
            members->updateIndex( 0 );
            rend = 1;
            unlock();
        }
        void removeMember( Zeichnung *obj )
        {
            lock();
            members->removeZeichnung( obj );
            members->updateIndex( 0 );
            rend = 1;
            unlock();
        }
        void render()
        {
            if( !rend && testRend )
                return;
            rendering = 1;
            int count = 0;
            if( renderB && d3d11Device )
            {
                lock();
                renderZeit->messungStart();
                float color[ 4 ];
                // Setup the color to clear the buffer to.
                color[ 0 ] = 0;
                color[ 1 ] = 0;
                color[ 2 ] = 0;
                color[ 3 ] = 0;
                // Clear the back buffer.
                d3d11Context->ClearRenderTargetView( rtview, color );
                // Clear the depth buffer.
                d3d11Context->ClearDepthStencilView( dsView, D3D11_CLEAR_DEPTH, 1.0f, 0 );
                if( füll )
                    renderB->setFarbe( füllFarbe );
                if( renderZeichnungen )
                {
                    if( renderOnTop && deckFarbe && ( deckFarbe & ( füllFarbe | 0xFF000000 ) ) == deckFarbe )
                    {
                        renderB->setAlpha( 255 - (unsigned char)( deckFarbe >> 24 ) );
                        members->render( *renderB ); // zeichnen nach zwischenbuffer
                        renderB->releaseAlpha();
                    }
                    else
                    {
                        members->render( *renderB ); // zeichnen nach zwischenbuffer
                        if( renderOnTop && deckFarbe )
                            renderB->alphaRegion( 0, 0, renderB->getBreite(), renderB->getHöhe(), deckFarbe );
                    }
                    for( int i = 0; i < tipAnzahl; ++i )
                        tips->z( i )->render( *renderB );
                }
                if( renderOnTop && onTop )
                    onTop->render( *renderB );
                Bild *tmp = renderB->getThis();
                unlock();
                // Beginne Bild 
                HRESULT result;
                D3D11_MAPPED_SUBRESOURCE buffer;
                result = d3d11Context->Map( d3d11FrameworkBuffer, 0, D3D11_MAP::D3D11_MAP_WRITE_DISCARD, 0, &buffer );
                // kopieren zum Bildschrirm 
                renderB->füllRegion( 100, 100, 100, 100, 0xFF0000FF );
                int *bgBuff = tmp->getBuffer();
                int tmpBr = sizeof( D3DCOLOR )* tmp->getBreite();
                for( int y = 0, pitch = 0, bry = 0; y < tmp->getHöhe(); ++y, pitch += buffer.RowPitch, bry += tmp->getBreite() )
                    memcpy( &( (BYTE *)buffer.pData )[ pitch ], (void*)&( bgBuff[ bry ] ), tmpBr );
                // Beende Bild 
                d3d11Context->Unmap( d3d11FrameworkBuffer, 0 );
                tmp->release();

                unsigned int stride = sizeof( VertexType );
                unsigned int offset = 0;

                d3d11Context->IASetVertexBuffers( 0, 1, &vertexBuffer, &stride, &offset );
                d3d11Context->IASetIndexBuffer( indexBuffer, DXGI_FORMAT_R32_UINT, 0 );
                d3d11Context->IASetPrimitiveTopology( D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST );

                D3D11_MAPPED_SUBRESOURCE mappedResource;
                MatrixBufferType* dataPtr;
                result = d3d11Context->Map( matrixBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource );
                dataPtr = (MatrixBufferType*)mappedResource.pData;
                D3DXVECTOR3 up, position, lookAt;
                // Setup the vector that points upwards.
                up.x = 0.0f;
                up.y = 1.0f;
                up.z = 0.0f;
                // Setup the position of the camera in the world.
                position.x = 0;
                position.y = 0;
                position.z = -backBufferGröße.y * 1.2075;
                // Setup where the camera is looking by default.
                lookAt.x = 0.0f;
                lookAt.y = 0.0f;
                lookAt.z = 1.0f;
                // Finally create the view matrix from the three updated vectors.
                D3DXMatrixLookAtLH( &dataPtr->view, &position, &lookAt, &up );

                // Setup the projection matrix.
                //float fieldOfView = (float)D3DX_PI / 4.0f;
                float screenAspect = (float)backBufferGröße.x / (float)backBufferGröße.y;

                // Create the projection matrix for 3D rendering.
                D3DXMatrixPerspectiveFovLH( &dataPtr->projection, (float)D3DX_PI / 4.0f, screenAspect, 0.1, 10000 );

                // Copy the matrices into the constant buffer.
                D3DXMatrixIdentity( &dataPtr->world );
                D3DXMatrixTranspose( &dataPtr->world, &dataPtr->world );
                D3DXMatrixTranspose( &dataPtr->view, &dataPtr->view );
                D3DXMatrixTranspose( &dataPtr->projection, &dataPtr->projection );

                // Unlock the constant buffer.
                d3d11Context->Unmap( matrixBuffer, 0 );

                // Now set the constant buffer in the vertex shader with the updated values.
                d3d11Context->VSSetConstantBuffers( 0, 1, &matrixBuffer );

                // Set shader texture resource in the pixel shader.
                d3d11Context->PSSetShaderResources( 0, 1, &resource );
                // Set the vertex input layout.
                d3d11Context->IASetInputLayout( layout );

                // Set the vertex and pixel shaders that will be used to render this triangle.
                d3d11Context->VSSetShader( vertexShader, NULL, 0 );
                d3d11Context->PSSetShader( pixelShader, NULL, 0 );

                // Set the sampler state in the pixel shader.
                d3d11Context->PSSetSamplers( 0, 1, &sampleState );
                d3d11Context->OMSetBlendState( blendStateAlphaBlend, 0, 0xFFFFFFFF );

                d3d11Context->DrawIndexed( 6, 0, 0 );

                result = d3d11SpawChain->Present( 0, 0 );
                renderZeit->messungEnde();
                std::cout << renderZeit->getSekunden() << "\n";
                if( result != S_OK )
                {
                    ++count;
                    update();
                }
                else if( count )
                    --count;
            }
            if( !d3d11Device )
            {
                ++count;
                update();
            }
            if( count > 10 )
            {
                WMessageBox( fenster ? fenster->getFensterHandle() : 0, new Text( "Fehler" ), new Text( "Es ist ein Fehler beim rendern aufgetreten." ), MB_ICONERROR );
                count = 0;
            }
            rendering = 0;
            rend = 0;
        }
        void setFüllFarbe( int f )
        {
            füllFarbe = f;
            rend = 1;
        }
        void setVollbild( bool fullscreen )
        {
            lock();
            this->vollbild = fullscreen;
            rend = 1;
            unlock();
        }
        void tick( double tickval )
        {
            lock();
            if( !renderOnTop )
            {
                for( int i = 0; i < tipAnzahl; ++i )
                    rend |= tips->z( i )->tick( tickval );
                rend |= members->tick( tickval );
            }
            else if( onTop )
            {
                rend |= onTop->tick( tickval );
                for( int i = 0; i < tipAnzahl; ++i )
                    rend |= tips->z( i )->tick( tickval );
            }
            unlock();
        }
        void setBackBufferGröße( int breite, int höhe )
        {
            lock();
            backBufferGröße.x = breite;
            backBufferGröße.y = höhe;
            rend = 1;
            unlock();
        }
        void setBackBufferGröße( Punkt &größe )
        {
            lock();
            backBufferGröße = größe;
            rend = 1;
            unlock();
        }
        void doMausEreignis( MausEreignis &me )
        {
            int fBr = backBufferGröße.x;
            int fHö = backBufferGröße.y;
            if( fenster )
            {
                fBr = fenster->getKörperBreite();
                fHö = fenster->getKörperHöhe();
            }
            me.mx = (int)( me.mx * backBufferGröße.x / (double)fBr + 0.5 );
            me.my = (int)( me.my * backBufferGröße.y / (double)fHö + 0.5 );
            lock();
            if( !renderOnTop )
            {
                for( int i = 0; i < tipAnzahl; ++i )
                    tips->z( i )->doMausEreignis( me );
                members->sendMausAll( me );
            }
            else if( onTop )
            {
                onTop->doMausEreignis( me );
                for( int i = 0; i < tipAnzahl; ++i )
                    tips->z( i )->doMausEreignis( me );
            }
            unlock();
        }
        void doTastaturEreignis( TastaturEreignis &te )
        {
            lock();
            if( !renderOnTop )
                members->sendTastaturAll( te );
            else if( onTop )
                onTop->doTastaturEreignis( te );
            unlock();
        }
        void addToolTip( ToolTip *tip )
        {
            lock();
            tips->add( tip, tipAnzahl );
            ++tipAnzahl;
            rend = 1;
            unlock();
        }
        bool removeToolTip( ToolTip *zTip )
        {
            lock();
            bool gefunden = 0;
            for( int i = 0; i < tipAnzahl; ++i )
            {
                ToolTip *tmp = tips->z( i );
                if( tmp == zTip )
                {
                    tips->lösche( i );
                    --tipAnzahl;
                    gefunden = 1;
                    rend = 1;
                    break;
                }
            }
            unlock();
            return gefunden;
        }
        Bild *getRenderBild() const
        {
            return renderB->getThis();
        }
        Bild *zRenderBild() const
        {
            return renderB;
        }
        ZeichnungArray *getMembers() const
        {
            return members;
        }
        int getFüllFarbe() const
        {
            return füllFarbe;
        }
        bool istVolbild() const
        {
            return vollbild;
        }
        const Punkt &getBackBufferGröße() const
        {
            return backBufferGröße;
        }
        void warteAufRendern() const
        {
            while( rendering )
            {
                if( !rendering )
                    return;
            }
        }
        double getRenderZeit() const
        {
            return renderZeit->getSekunden();
        }
        Bildschirm *getThis()
        {
            ++ref;
            return this;
        }
        Bildschirm *release()
        {
            --ref;
            if( !ref )
                delete this;
            return 0;
        }
    };
}

Bildschirm *bs;

void FClose( void *p, void *zF )
{
    StopNachrichtenSchleife( ( (WFenster*)zF )->getFensterHandle() );
}

int main()
{
    initFramework();

    float a = 0xFF000000;
    int i = (int)a >> 24;

    WFenster *f = new WFenster();
    WNDCLASS fc = F_Normal( 0 );
    fc.lpszClassName = "Test";
    f->erstellen( WS_OVERLAPPEDWINDOW, fc );
    f->setSize( 1600, 900 );
    f->setVSchließAktion( FClose );
    f->setMausAktion( _ret1ME );
    f->setTastaturAktion( _ret1TE );
    f->setAnzeigeModus( 1 );

    bs = new Framework2::Bildschirm( f->getThis() );
    f->setBildschirm( ( Framework::Bildschirm* )bs->getThis() );
    bs->setTestRend( 0 );

    RenderTh *r = new RenderTh();
    r->setBildschirm( ( Framework::Bildschirm* )bs->getThis() );
    r->setMaxFps( 60 );
    r->beginn();

    TextFeld *tf = new TextFeld();
    tf->setPosition( 0, 0 );
    tf->setGröße( 1600, 900 );
    tf->setStyle( TextFeld::Style::TextFeld | TextFeld::Style::Hintergrund );
    tf->setLinienRahmenFarbe( 0xFFFF0000 );
    tf->setLinienRahmenBreite( 1 );
    tf->setAlphaFeldFarbe( 0xFF00FF00 );
    tf->setAlphaFeldStärke( 10 );
    tf->setHintergrundFarbe( 0xFF0000FF );
    bs->addMember( tf );

    StartNachrichtenSchleife();

    r->beenden();
    r->release();
    f->setBildschirm( 0 );
    bs->release();
    f->release();
    tf->release();

    releaseFramework();

    getchar();

    return 0;
}