c++ /cli覆盖OnRender事件



我试着把wpf "fire" (http://www.smartypantscoding.com/content/old-school-fire-algorithm-modern-day-wpf)的例子带到c++/cli。我用一个工具将它翻译成c++/cli,但覆盖的"OnRender"事件从未被触发。所以我看到的窗口就像c#项目一样,但是没有火焰。

CompositionTarget_Rendering被调用,所以通常invalidatevvisuual()必须触发OnRender,但它没有。我希望你能帮助我=)

//the .h
#pragma once
using namespace System;
using namespace System::Collections;
using namespace System::Collections::Generic;
using namespace System::Globalization;
using namespace System::Xml::Linq;
using namespace System::Text;
using namespace System::Windows::Documents;
using namespace System::Windows;
using namespace System::Windows::Media;
using namespace System::Windows::Media::Imaging;
using namespace System::Threading;
#include "FireGenerator.h"

/// <summary>
/// Adorner that disables all controls that fall under it
/// </summary>
public ref class FireAdorner : Adorner
{
private:
    BitmapPalette ^_pallette;
    literal int DPI = 96;
    FireGenerator ^_fireGenerator;
    /// <summary>
    /// Constructor for the adorner
    /// </summary>
    /// <param name="adornerElement">The element to be adorned</param>
public:
    FireAdorner(UIElement^ adornerElement);

private:
    void CompositionTarget_Rendering(Object ^sender, EventArgs ^e);
    /// <summary>
    /// Called to draw on screen
    /// </summary>
    /// <param name="drawingContext">The drawind context in which we can draw</param>
protected:
    virtual void OnRender(System::Windows::Media::DrawingContext ^drawingContext) override;

private:
    BitmapPalette ^SetupFirePalette();
private:
    void InitializeInstanceFields();
};

和。cpp

#include "StdAfx.h"
#include "FireAdorner.h"

using namespace System;
using namespace System::Collections;
using namespace System::Collections::Generic;
using namespace System::Globalization;
using namespace System::Xml::Linq;
using namespace System::Text;
using namespace System::Windows::Documents;
using namespace System::Windows;
using namespace System::Windows::Media;
using namespace System::Windows::Media::Imaging;
using namespace System::Threading;

FireAdorner::FireAdorner(UIElement ^adornerElement) : Adorner(adornerElement)
    {
        InitializeInstanceFields();
        CompositionTarget::Rendering += gcnew EventHandler(this, &FireAdorner::CompositionTarget_Rendering);
    }
    void FireAdorner::CompositionTarget_Rendering(Object ^sender, EventArgs ^e)
    {
        InvalidateVisual();
    }

    void FireAdorner::OnRender(System::Windows::Media::DrawingContext ^drawingContext)
    {
        System::Windows::MessageBox::Show("render");
        // only set the pallette once (dont do in constructor as causes odd errors if exception occurs)
        if (_pallette == nullptr)
        {
            _pallette = SetupFirePalette();
        }
        _fireGenerator->UpdateFire();
        BitmapSource ^bs = BitmapSource::Create(_fireGenerator->Width, _fireGenerator->Height, DPI, DPI, PixelFormats::Indexed8, _pallette, _fireGenerator->FireData, _fireGenerator->Width);
        drawingContext->DrawImage(bs, Rect(0, 0, this->DesiredSize.Width, this->DesiredSize.Height));

    }
    BitmapPalette ^FireAdorner::SetupFirePalette()
    {
        System::Collections::Generic::List<Color> ^myList = gcnew System::Collections::Generic::List<Color>();
        // seutp the basic array we will modify
        for (int i = 0; i <= 255; i++)
        {
            myList->Add(Color());
        }
        for (int i = 0; i < 64; i++)
        {
            Color c1 = Color();
            c1.R = safe_cast<Byte>(i * 4);
            c1.G = safe_cast<Byte>(0);
            c1.B = safe_cast<Byte>(0);
            c1.A = 255;
            myList[i] = c1;
            Color c2 = Color();
            c2.R = safe_cast<Byte>(255);
            c2.G = safe_cast<Byte>(i * 4);
            c2.B = safe_cast<Byte>(0);
            c2.A = 255;
            myList[i + 64] = c2;
            Color c3 = Color();
            c3.R = safe_cast<Byte>(255);
            c3.G = safe_cast<Byte>(255);
            c3.B = safe_cast<Byte>(i * 4);
            c3.A = 255;
            myList[i + 128] = c3;
            Color c4 = Color();
            c4.R = safe_cast<Byte>(255);
            c4.G = safe_cast<Byte>(255);
            c4.B = safe_cast<Byte>(255);
            c4.A = 255;
            myList[i + 192] = c4;
        }
        BitmapPalette ^bp = gcnew BitmapPalette(myList);
        return bp;
    }
    void FireAdorner::InitializeInstanceFields()
    {
        _fireGenerator = gcnew FireGenerator(600, 50);
    }

Initcode:

FireAdorner^ myfire = gcnew FireAdorner(MyWindow);
MyWindow->ShowDialog();

//我的窗口是一个窗口^从这个代码创建:

<Window     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="WPF Fire" Width="800" Height="200" Closing="Window_Closing">
    <Grid>
        <AdornerDecorator>
            <DockPanel Name="dockPanel1"/>
        </AdornerDecorator>
        <!-- This rectangle is a hack to hide the bottom rows of the fire which look blocky
             the proper solution would be to fix the rendering to leave off the bottom XX lines -->
        <Rectangle Fill="Black" VerticalAlignment="Bottom"
                   Width="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType=Window}, Path=ActualWidth}" 
                   Height="8" />
    </Grid>
</Window>

问题解决了:

FireAdorner^ myfire = gcnew FireAdorner(MyWindow);
MyWindow->ShowDialog();
新Initcode:

DockPanel^ firebox = (DockPanel^)MyWindow->FindName("dockPanel1"); 
AdornerLayer^ adornerLayer = AdornerLayer::GetAdornerLayer(firebox);
adornerLayer->Add(gcnew FireAdorner(firebox));
MyWindow->ShowDialog();

相关内容

  • 没有找到相关文章

最新更新