5

DLL でプログラムによってユーザー コントロールをインスタンス化し、後で PNG ファイルとして保存したいと考えています。これは通常、PngBitmapEncoder と RenderTargetBitmap では問題ありません。

これは私の質問です:

  • コントロールをインスタンス化するにはどうすればよいですか? 単純に new-operator で?
  • 別のスレッドでインスタンス化する必要がありますか?
  • コントロールがすべての子を更新し、再びレンダリングするように強制するにはどうすればよいですか?

これは、ユーザー コントロールをインスタンス化し、PNG ファイルとして保存するコードです (LetterFrequency はユーザー コントロールです)。

    [STAThread]
    static void Main(string[] args)
    {
        LetterFrequency let = new LetterFrequency();
        let.Width = 600;
        let.Height = 400;
        let.Background = Brushes.White;

        let.Measure(new Size(let.Width, let.Height));
        let.Arrange(new Rect(new Size(let.Width, let.Height)));

        let.UpdateLayout();

        RenderTargetBitmap bitmap = new RenderTargetBitmap((int)let.Width, (int)let.Height, 96d, 96d, PixelFormats.Pbgra32);
        bitmap.Render(let);

        PngBitmapEncoder png = new PngBitmapEncoder();
        png.Frames.Add(BitmapFrame.Create(bitmap));

        using (Stream stm = File.Create("test.png"))
        {
            png.Save(stm);
        }
    }

この方法でアプリを実行すると、PNG ファイルが生成されますが、XAML に追加されるデータは表示されません。XAML デザイナーを調べると、グラフにいくつかのバブルが表示されます。png ファイルにはグラフ領域のみが含まれていますが、バブルは含まれていませんか? どうして?更新/レンダリングの問題だと思いますが、これを解決するにはどうすればよいですか?

これはビジュアル スタジオ ソリューションです。これには、ユーザー コントロールを PNG ファイルにレンダリングするコンソール プロジェクトと、チャート用の WPF ツールキットの他の 2 つのプロジェクトが含まれています。

それを見てください、それはexeフォルダーのbin/DebugにそれぞれPNGファイルを生成します:http://www.file-upload.net/download-1904406/ChartRenderBitmap.zip.html

問題なく動作することを願っています!

ありがとう!

4

1 に答える 1

2

データ ポイントの表示にアニメーションが適用されているため、チャートのデータは PNG ファイルにレンダリングされません。Window で LetterFrequency コントロールを確認すると、ポイントが徐々に明らかになることがわかります。

コードは作成直後にコントロールのスナップショットを取得するため、データは表示されません。

あなたは出来る:

  1. これらすべてをウィンドウにラップし、X 秒後にスナップショットを取得するように指示します
  2. スナップショットを作成するコントロールのすべてのアニメーションを無効にします
  3. プログラムでアニメーションを「早送り」する方法があるかもしれませんが、見つけられませんでした

これが解決策1であり、機能します:

    public partial class Window1 : Window
{
    System.Windows.Threading.DispatcherTimer snapshotTimer;

    public Window1()
    {
        InitializeComponent();

        this.Width = 600;
        this.Height = 400;
        let.Width = 600;
        let.Height = 400;
        let.Background = Brushes.White;     

        this.Loaded += new RoutedEventHandler(Window1_Loaded);
    }

    void Window1_Loaded(object sender, RoutedEventArgs e)
    {
        this.snapshotTimer = new System.Windows.Threading.DispatcherTimer();
        this.snapshotTimer.Interval = TimeSpan.FromSeconds(2);
        this.snapshotTimer.Tick += new EventHandler(snapshotTimer_Tick);
        this.snapshotTimer.IsEnabled = true;
    }

    void snapshotTimer_Tick(object sender, EventArgs e)
    {
        this.snapshotTimer.IsEnabled = false;
        WritePng();
    }

    void WritePng()
    {
        RenderTargetBitmap bitmap = new RenderTargetBitmap((int)let.Width, (int)let.Height, 96d, 96d, PixelFormats.Pbgra32);
        bitmap.Render(let);

        PngBitmapEncoder png = new PngBitmapEncoder();
        png.Frames.Add(BitmapFrame.Create(bitmap));

        using (Stream stm = File.Create("test.png"))
        {
            png.Save(stm);
        }

        this.Close();
    }
}
于 2009-09-23T21:56:16.233 に答える