ウィンドウを作成せずにWPFUserControlをビットマップにレンダリングするにはどうすればよいですか? WPF UserControlをレンダリングして、別のプログラムにアップロードする必要があります。ビットマップはWindowsサービスを介してレンダリングされるため、ウィンドウを作成することはできません(ウィンドウを「仮想的に」作成する方法があることは知っていますが、残念ながら、コマンドを呼び出してウィンドウを作成することはオプションではありません)。ユーザーコントロールをウィンドウにバインドせずにレンダリングする方法はありますか?
実際のウィンドウのないHwndHostを使用することになりました。
void cwind()
{
Application myapp = new Application();
mrenderer = new WPFRenderer();
mrenderer.Width = 256;
mrenderer.Height = 256;
HwndSourceParameters myparms = new HwndSourceParameters();
HwndSource msrc = new HwndSource(myparms);
myparms.HwndSourceHook = new HwndSourceHook(ApplicationMessageFilter);
msrc.RootVisual = mrenderer;
myapp.Run();
}
static IntPtr ApplicationMessageFilter(
IntPtr hwnd, int message, IntPtr wParam, IntPtr lParam, ref bool handled)
{
return IntPtr.Zero;
}
ユーザーコントロールのインスタンスを起動して、次のようなことを試してみましたか?
UserControl control = new UserControl1();
control.Measure(new Size(300, 300));
control.Arrange(new Rect(new Size(300,300)));
RenderTargetBitmap bmp = new RenderTargetBitmap(300, 300, 96, 96, PixelFormats.Pbgra32);
bmp.Render(control);
var encoder = new PngBitmapEncoder();
encoder.Frames.Add(BitmapFrame.Create(bmp));
using (Stream stm = File.Create(@"c:\test.png"))
encoder.Save(stm);
測定、配置する必要があるようです。これは私のために働いた。
どうやら、測定と配置の後にcontrol.UpdateLayout()
を呼び出す場合、ユーザーコントロールはどのウィンドウにもある必要はありません。
IDWMasterのソリューションに基づいて、System.Windows.Forms.UserControl
を使用して少し異なる方法で実行しました。それ以外の場合、ビットマップへのエクスポートが行われたときにバインディングは最新ではありませんでした。これは私にとってはうまくいきます(this
はレンダリングするWPFコントロールです):
System.Windows.Forms.UserControl controlContainer = new System.Windows.Forms.UserControl();
controlContainer.Width = width;
controlContainer.Height = height;
controlContainer.Load += delegate(object sender, EventArgs e)
{
this.Dispatcher.BeginInvoke((Action)delegate
{
using (FileStream fs = new FileStream(path, FileMode.Create))
{
RenderTargetBitmap bmp = new RenderTargetBitmap(width, height, 96, 96, PixelFormats.Pbgra32);
bmp.Render(this);
BitmapEncoder encoder = new PngBitmapEncoder();
encoder.Frames.Add(BitmapFrame.Create(bmp));
encoder.Save(fs);
controlContainer.Dispose();
}
}, DispatcherPriority.Background);
};
controlContainer.Controls.Add(new ElementHost() { Child = this, Dock = System.Windows.Forms.DockStyle.Fill });
IntPtr handle = controlContainer.Handle;