private static void StartBrowser(string source)
{
var th = new Thread(() =>
{
var webBrowser = new WebBrowser();
webBrowser.ScrollBarsEnabled = false;
webBrowser.DocumentCompleted += webBrowser_DocumentCompleted;
webBrowser.DocumentText = source;
Application.Run();
});
th.SetApartmentState(ApartmentState.STA);
th.Start();
}
static void webBrowser_DocumentCompleted(object sender,WebBrowserDocumentCompletedEventArgs e)
{
var webBrowser = (WebBrowser)sender;
using (Bitmap bitmap = new Bitmap(576,384))
{
webBrowser.DrawToBitmap(bitmap,new System.Drawing.Rectangle(0, 0, bitmap.Width, bitmap.Height));
bitmap.Save(#"images/" + "xxx.jpg",System.Drawing.Imaging.ImageFormat.Jpeg);
}
}
Hi Guys,
I am trying to print out an HTML file in a windows service by using the windows application web browser. For some reason, I cannot get a clear image, it draws only 25% of the image.
Note:- There is a barcode image in the upper right corner.
Related
I need to create a bitmap from an html string using the CefSharp.OffScreen.ChromiumWebBrowser.
var browser = new CefSharp.OffScreen.ChromiumWebBrowser(htmlString);
// what to do?
var bitmap = browser.Bitmap;
What do I have to do to get the bitmap?
Passing the URL and not the html string to the ChromiumWebBrowser and waiting for the browser to finish loading the html file solves this problem:
var browser = new CefSharp.OffScreen.ChromiumWebBrowser(htmlURL);
// wait the browser to finish loading the html file
using (var waitHandle = new System.Threading.AutoResetEvent(false))
{
EventHandler<LoadingStateChangedEventArgs> loadingHandler = null;
loadingHandler = (sender, e) =>
{
if (!e.IsLoading)
{
if (browser != null)
{
browser.LoadingStateChanged -= loadingHandler;
}
waitHandle.Set();
}
};
browser.LoadingStateChanged += loadingHandler;
waitHandle.WaitOne();
}
var bitmap = browser.Bitmap; // bitmap not null
I'm using the .NET WebBrowser in order to render an html page and save that as a bitmap (got the code from another stackoverflow post). The problem is that the thread that actually starts the web browser never closes.
The thread should close when the StartBrowser Method finishes but it never does because Application.Run never ends.
My question is : how do I close the application after the WebBrowser finishes rendering the page and saves the bitmap ? Adding Application.Exit();
inside the DocumentCompleted event doesn't seem to work.
Code:
public class DotNetRenderer : IHtmlRenderer
{
static Bitmap bmp;
Thread th;
public void initializeRenderer()
{
}
public Bitmap renderHtml(string htmlContent)
{
th = new Thread(() => StartBrowser(htmlContent));
th.SetApartmentState(ApartmentState.STA);
th.Start();
th.Join();
return bmp;
}
public static void StartBrowser(string source)
{
var webBrowser = new WebBrowser();
webBrowser.ScrollBarsEnabled = false;
webBrowser.DocumentCompleted +=
webBrowser_DocumentCompleted;
webBrowser.DocumentText = source;
Application.Run();
}
static void webBrowser_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e)
{
var webBrowser = (WebBrowser)sender;
bmp = new Bitmap(webBrowser.Width, webBrowser.Height);
webBrowser.DrawToBitmap(bmp, new System.Drawing.Rectangle(0, 0, bmp.Width, bmp.Height));
Application.ExitThread();
}
}
Application.ExitThread() does what I want, but now I don't know why the webBrowser Width and Height are always (250,250) regardless of the input HTML.
I am using PhotoChooserTaskto pick a picture from photo gallery and then set this picture as my app background. Everything works fine, but when I exit my application it's not saved. What I am looking is to save this background for my application.
I am using below code:
photoChooserTask = new PhotoChooserTask()
photoChooserTask.Completed += new EventHandler<PhotoResult>(photoChooserTask_Completed);
void photoChooserTask_Completed(object sender, PhotoResult e)
{
if (e.TaskResult == TaskResult.OK)
{
System.IO.IsolatedStorage.IsolatedStorageSettings settings = System.IO.IsolatedStorage.IsolatedStorageSettings.ApplicationSettings;
System.Windows.Media.Imaging.BitmapImage bmp = new System.Windows.Media.Imaging.BitmapImage();
bmp.SetSource(e.ChosenPhoto);
imgCustom.Source = bmp;
System.Windows.Media.ImageBrush backgroundBrush = new System.Windows.Media.ImageBrush() { ImageSource = bmp };
App.RootFrame.Background = backgroundBrush;
}
}
What I am looking is, If I close and run my application, This background should not change unless the user changes it.
Thanks!
How about trying out this piece of code at the end:
var frame = App.Current.RootVisual as PhoneApplicationFrame;
frame.Background = backgroundBrush;
Reference: Windows Phone app background image
I want to use a webcam in c# code with Aforge.NET, but It didin't work because I don't use forms.
See my code below :
public partial class CapturePage : Page
{
private bool DeviceExist = false;
private FilterInfoCollection videoDevices;
private VideoCaptureDevice videoSource = null;
public CapturePage()
{
InitializeComponent();
getCamList();
startVideo();
}
// get the devices name
private void getCamList()
{
try
{
videoDevices = new FilterInfoCollection(FilterCategory.VideoInputDevice);
if (videoDevices.Count == 0)
throw new ApplicationException();
DeviceExist = true;
}
catch (ApplicationException)
{
DeviceExist = false;
}
}
//toggle start and stop button
private void startVideo() // as it's say
{
if (DeviceExist)
{
videoSource = new VideoCaptureDevice(videoDevices[0].MonikerString); // the only one webcam
videoSource.NewFrame += new NewFrameEventHandler(video_NewFrame);
CloseVideoSource();
// videoSource.DesiredFrameSize = new Size(160, 120); // deprecated ?
//videoSource.DesiredFrameRate = 10;
videoSource.Start();
}
else
{
// error
}
}
else
{
if (videoSource.IsRunning)
{
timer1.Enabled = false;
CloseVideoSource();
}
}
}
//eventhandler if new frame is ready
private void video_NewFrame(object sender, NewFrameEventArgs eventArgs)
{
Bitmap img = (Bitmap)eventArgs.Frame.Clone();
//do processing here
pictureBox1.Image = img; // But I can't have pictureBox in xaml ??
}
//close the device safely
private void CloseVideoSource()
{
if (!(videoSource == null))
if (videoSource.IsRunning)
{
videoSource.SignalToStop();
videoSource = null;
}
}
}
}
I tried this code in a form application, and it's work, but with a page, PictureBox are not referenced. Even if I reference it and create one in the code, this didn't work.
Can I, and how, use a PictureBox in a XAML Page ? Or there is an other solution tu use Aforge.net Webcam in Xaml Page ?
I succeded with changing the NewFrame methode like this:
private void video_NewFrame(object sender, NewFrameEventArgs eventArgs)
{
System.Drawing.Image imgforms = (System.Drawing.Bitmap)eventArgs.Frame.Clone();
BitmapImage bi = new BitmapImage();
bi.BeginInit();
MemoryStream ms = new MemoryStream();
imgforms.Save(ms, ImageFormat.Bmp);
ms.Seek(0, SeekOrigin.Begin);
bi.StreamSource = ms;
bi.EndInit();
//Using the freeze function to avoid cross thread operations
bi.Freeze();
//Calling the UI thread using the Dispatcher to update the 'Image' WPF control
Dispatcher.BeginInvoke(new ThreadStart(delegate
{
ImageWebcam.Source = bi; /*frameholder is the name of the 'Image' WPF control*/
}));
}
cheers !
You could use WindowsFormsHost to integrate this Page in your WPF application.
If you need a WPF bitmap you may "convert" it like desribed here: Load a WPF BitmapImage from a System.Drawing.Bitmap
I've been trying to get a WebBrowser to draw to a texture in XNA 4.0, and I've found several guides on how to do it. The problem is when I try to implement it, whether I change the Url property or call Navigate() it just won't load the page. I have a feeling I'm being a bit ignorant about the threading required, since my project is not started as an STA thread, so I create a separate thread to start the web browser and render to a bitmap.
Here's how I start it:
public void LoadTexture(GraphicsDevice gfx, ContentManager content, string filename, float duration = -1f)
{
this.gfx = gfx;
this.filename = filename;
this.duration = duration;
_resetEvent = new AutoResetEvent(false);
Thread thread = new Thread(GetWebScreenshot);
thread.SetApartmentState(ApartmentState.STA);
thread.Start();
_resetEvent.WaitOne();
}
And here's GetWebScreenshot:
public void GetWebScreenshot()
{
this.web = new WebBrowser();
this.web.Size = new Size(gfx.Viewport.Width, gfx.Viewport.Height);
this.web.Url = new Uri(this.filename);
while (this.web.ReadyState != WebBrowserReadyState.Complete)
{
if (this.web.ReadyState != WebBrowserReadyState.Uninitialized)
{
Console.WriteLine(this.web.ReadyState.ToString());
}
}
bitmap = new Bitmap(this.gfx.Viewport.Width, this.gfx.Viewport.Height, System.Drawing.Imaging.PixelFormat.Format32bppArgb);
this.web.DrawToBitmap(bitmap, new System.Drawing.Rectangle(0, 0, bitmap.Width, bitmap.Height));
this.texture = BitmapToTexture2D(this.gfx, bitmap);
_resetEvent.Set();
}
The ReadyState property never changes from Uninitialized, I've also tried using the DocumentReady event, and that never gets fired. I've also tried Join() instead of AutoResetEvent, but nothing seems to work.
I was right, it was ignorance on my part. The critical thing about ActiveX controls and Single Threaded Apartments is that the message queue needs to be pumped. So now I've restructured my code to the following:
public void LoadTexture(GraphicsDevice gfx, ContentManager content, string filename, float duration = -1f)
{
this.gfx = gfx;
this.filename = filename;
this.duration = duration;
Thread thread = new Thread(GetWebScreenshot);
thread.SetApartmentState(ApartmentState.STA);
thread.Start();
thread.Join();
}
public void GetWebScreenshot()
{
this.web = new WebBrowser();
this.web.Size = new Size(gfx.Viewport.Width, gfx.Viewport.Height);
this.web.Url = new Uri(this.filename);
this.web.DocumentCompleted += new WebBrowserDocumentCompletedEventHandler(web_DocumentCompleted);
Application.Run(); // Starts pumping the message queue (and keeps the thread running)
}
void web_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e)
{
Bitmap bitmap = new Bitmap(this.gfx.Viewport.Width, this.gfx.Viewport.Height, System.Drawing.Imaging.PixelFormat.Format32bppArgb);
this.web.DrawToBitmap(bitmap, new System.Drawing.Rectangle(0, 0, bitmap.Width, bitmap.Height));
this.texture = HTMLTextureFactoryMachine.BitmapToTexture2D(this.gfx, bitmap);
Application.ExitThread(); // Exits the thread
}
This works no problem.