render pdf from memorystream - winforms

I have searched for entire day for a solution, but somehow I couldn't find it.
What I wanted is to get data from database (binary file such as PDF) into MemoryStream (which I succeeded to do so), but problem is when I wish to preview that file into WebBrowser control.
so the code goes:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Data.SqlClient;
using System.IO;
namespace MemoryStreamTest
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
MemoryStream memory = new MemoryStream();
//byte[] temp;
private void Form1_Load(object sender, EventArgs e)
{
memory = GetBlobFile();
}
private MemoryStream GetBlobFile()
{
MemoryStream ms = new MemoryStream();
string SQL = "SELECT [SnapshotPDF] FROM [DBtest].[dbo].[SamplePDF] WHERE id = " + 21;
SqlConnection conn = new SqlConnection("Data Source=database;Initial Catalog=DBtest; User ID=test; Password=test;");
SqlCommand comm = new SqlCommand(SQL, conn);
conn.Open();
byte [] result = (byte[])comm.ExecuteScalar();
conn.Close();
if (result != null)
{
ms.Write(result, 0, result.Length);
ms.Position = 0;
}
return ms;
}
private void button1_Click(object sender, EventArgs e)
{
//webBrowser1.DocumentText = "application/pdf";
webBrowser1.DocumentStream = memory;
}
}
}
Actually webBrowser really output content from memory, but obviously from picture above it's rendered as text...
How can I force to render as PDF?
If it is not possible to use webBrowser control, is there any other controls that I can use in WinForms that would preview/render PDF from memory.

You have to implement an async pluggable protocol, e.g. IClassFactory, IInternetProtocol... Then you use CoInternetGetSession to register your protocol. When IE calls your implementation, you can serve your image data from memory/provide mime type.
It's a bit tedious, but doable. Look at IInternetProtocol and pluggable protocols documentation on MSDN.

Done, I found one little bug which I correct it. this is entire code:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Data.SqlClient;
using System.IO;
using Ghostscript.NET;
using Ghostscript.NET.Viewer;
namespace MemoryStreamTest
{
public partial class Form1 : Form
{
Stream stream;
byte[] result;
private GhostscriptViewer _viewer;
private GhostscriptVersionInfo _gsVersion = GhostscriptVersionInfo.GetLastInstalledVersion();
private Bitmap _pdfPage = null;
public Form1()
{
InitializeComponent();
pictureBox1.Width = 100;
pictureBox1.Height = 100;
_viewer = new GhostscriptViewer();
_viewer.DisplaySize += new GhostscriptViewerViewEventHandler(_viewer_DisplaySize);
_viewer.DisplayUpdate += new GhostscriptViewerViewEventHandler(_viewer_DisplayUpdate);
_viewer.DisplayPage += new GhostscriptViewerViewEventHandler(_viewer_DisplayPage);
}
private void Form1_Load(object sender, EventArgs e)
{
GetBlobFile();
}
private void GetBlobFile()
{
string SQL = "SELECT [SnapshotPDF] FROM [test].[dbo].[InvoiceAdded] WHERE id = " + 21;
SqlConnection conn = new SqlConnection("Data Source=test;Initial Catalog=test; User ID=test; Password=test;");
SqlCommand comm = new SqlCommand(SQL, conn);
conn.Open();
result = (byte[])comm.ExecuteScalar();
conn.Close();
stream = new MemoryStream(result);
}
private void button1_Click(object sender, EventArgs e)
{
ConvertToBitmap();
}
private void ConvertToBitmap()
{
_viewer.Open(stream, _gsVersion, true);
}
//DisplayPage
void _viewer_DisplayPage(object sender, GhostscriptViewerViewEventArgs e)
{
pictureBox1.Invalidate();
pictureBox1.Update();
}
//DisplaySize - dynamically
void _viewer_DisplaySize(object sender, GhostscriptViewerViewEventArgs e)
{
pictureBox1.Image = e.Image;
}
//DisplayUpdate - automatic update picture
void _viewer_DisplayUpdate(object sender, GhostscriptViewerViewEventArgs e)
{
pictureBox1.Invalidate();
pictureBox1.Update();
}
}
}
keep in mind that for this I needed to add .dll from Ghostscript.NET (a nice wrapper made by my patriot from Croatia), also I needed to install Ghostscript interpreter from GhostScript interpreter
And also many thanks to user: sm.abdullah
which actually point me to right direction.
Cheers

Related

System.Windows.Shapes.Path incorrect behavior

After doing some research on subject I didn't find anything, so I'm sorry if the same question was already asked.
Task: make a colored track-line on Canvas after cursor, when the left mouse button is pressed (like brush in Paint).
Problem: I think using System.Windows.Shapes.Path is the best approach to doing this task. Code below works fine, except for one thing: if you try to move your cursor then change direction to the opposite (e.g. the value on X-axis increases, then decreases, but the value on Y-axis, stays constant), you will get an unexpected part of Line, corresponding to the previous direction.
I'm sorry for the tangled description of my problem, but I hope you will get it.
To make it easier for you to reproduce it on your machine I'm adding the solution.
Please, point out for my mistake if I did one!
C#
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
namespace WpfApplication3
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
private Boolean Inserting;
private Path path;
private Boolean isFirstPoint;
public MainWindow()
{
InitializeComponent();
LolCanvas.IsHitTestVisible = true;
}
private void Canvas_MouseMove(object sender, MouseEventArgs e)
{
if (Inserting)
{
Point p = Mouse.GetPosition(LolCanvas);
if (isFirstPoint)
{
PathFigure myPathFigure = new PathFigure();
myPathFigure.StartPoint = new Point(p.X + 5, p.Y + 5);
myPathFigure.Segments = new PathSegmentCollection();
(path.Data as PathGeometry).Figures.Add(myPathFigure);
isFirstPoint = false;
}
else
{
LineSegment myLineSegment = new LineSegment();
myLineSegment.Point = new Point(p.X + 5, p.Y + 5);
(path.Data as PathGeometry).Figures[0].Segments.Add(myLineSegment);
}
}
}
private void Canvas_MouseDown(object sender, MouseButtonEventArgs e)
{
Inserting = true;
path = new Path();
path.Stroke = new SolidColorBrush(Colors.Red);
path.StrokeThickness = 50;
path.Data = new PathGeometry();
(path.Data as PathGeometry).Figures = new PathFigureCollection();
LolCanvas.Children.Add(path);
isFirstPoint = true;
}
private void Canvas_MouseUp(object sender, MouseButtonEventArgs e)
{
Inserting = false;
}
}
}
Xaml:
<Window x:Class="WpfApplication3.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525">
<Canvas x:Name="LolCanvas" MouseMove="Canvas_MouseMove" MouseDown="Canvas_MouseDown" MouseUp="Canvas_MouseUp" Background="Black">
</Canvas>
</Window>
Link to the application: http://ge.tt/99aSgyo/v/0?c
Apparently this kind of behavior is correct for path. The problem appeared because of the angle between line parts. It was 180 degrees, so window couldn't render Path propertly in this place.
I had two ways to defeat it:
1) Set IsSmoothJoin property to true for each line segment.
2) Make another Path object, when this kind of problem might occur

Keep connection always open for datatable twoway bind?

I'm working on a WPF project which includes update/delete/insert operation on many tables. For simplicity, I use a datagrid for each table. The users can operate on these tables directly. Once done, click a button, the tables in database get updated. Twoway bind is perfect in this case. Below code seems working fine.
However, one thing I do not like is: the _DBConnection is always open. It is closed until the form exists. Usually, I always open connection whenever I need to, use it, close it immediately.
So, my question is: is below code the correct way to do the twoway bind?
thanks
public partial class MainWindow : Window
{
private OleDbConnection _DBConnection;
private OleDbDataAdapter _DataAdapterAdmin;
private DataSet _DataSetAdmin;
public MainWindow()
{
InitializeComponent();
}
private void InitAdminGrid()
{
string cmd = "SELECT * FROM Admin ORDER BY LastName";
_DataAdapterAdmin = new OleDbDataAdapter(cmd, _DBConnection);
_DataSetAdmin = new DataSet();
_DataAdapterAdmin.Fill(_DataSetAdmin);
dgAdministration.BeginInit();
dgAdministration.DataContext = _DataSetAdmin.Tables[0];
dgAdministration.Items.Refresh();
dgAdministration.EndInit();
}
private void MainWindow_Loaded(object sender, RoutedEventArgs e)
{
string connectionString = clsDataAccess.GetConnectionString();
_DBConnection = new OleDbConnection(connectionString);
_DBConnection.Open();
InitAdminGrid();
}
private void btnStart_Click(object sender, RoutedEventArgs e)
{
try
{
OleDbCommandBuilder cmd = new OleDbCommandBuilder(_DataAdapterAdmin);
_DataAdapterAdmin.Update(_DataSetAdmin);
}
catch (Exception ex)
{
MessageBox.Show(ex.ToString(), "Exception", MessageBoxButton.OK, MessageBoxImage.Error);
}
}
private void MainWindow_Closing(object sender, System.ComponentModel.CancelEventArgs e)
{
if (_DBConnection != null)
{
_DBConnection.Close();
_DBConnection.Dispose();
}
}
}

How to use Ink recognize in WPF?

I am using .Net 4.0 WPF. I want to use InkCanvas to collect user input, then recognize what character is inputted.
After googling, I found a solution in http://msdn.microsoft.com/zh-cn/library/ms754080.aspx
Unfortunately, it is for .net 3.5. Is there a solution for .net 4.0? Thanks.
===================
Download a TablePC SDK from http://www.microsoft.com/en-us/download/details.aspx?id=20989
then got the Micorsoft.Ink.dll. Below is the sample code...
using Microsoft.Ink;
using System.IO;
private void btnGetInput_Click(object sender, RoutedEventArgs e)
{
if (inkInput.Strokes.Count > 0)
{
System.Windows.Ink.StrokeCollection strokeList = inkInput.Strokes;
MemoryStream ms = new MemoryStream();
inkInput.Strokes.Save(ms);
InkCollector myInkCollector = new InkCollector();
Ink ink = new Ink();
ink.Load(ms.ToArray());
using (RecognizerContext myRecoContext = new RecognizerContext())
{
RecognitionStatus status;
RecognitionResult recoResult;
myRecoContext.Strokes = ink.Strokes;
recoResult = myRecoContext.Recognize(out status);
tbUserName.Text += recoResult.TopString;
}
inkInput.Strokes.Clear();
}
}

Passing Variables From File-to-File in C#

How would I use a variable declared in Program.cs and access it's value from Form1.cs?
I know how to do this in C, but I'm completely lost in Microsoft's little twist on C.
Program.cs:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows.Forms;
using LuaInterface;
namespace WindowsFormsApplication1
{
static class Program
{
public static Lua lua = null;
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new Form1());
lua = new Lua();
}
}
}
Form1.cs
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using LuaInterface;
namespace WindowsFormsApplication1
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
lua.DoString("print('hi')");
}
private void textBox1_TextChanged(object sender, EventArgs e)
{
}
private void textBox2_TextChanged(object sender, EventArgs e)
{
}
private void button2_Click(object sender, EventArgs e)
{
textBox1.Text = "";
}
}
}
Using your examples of Program.cs and Form1.cs and assuming these are the default names and that you have a Program class that instantiates a Form1 class and that you want to pass a parameter to the Form1 class, you can do the following:
Define a constructor for Form1 that takes this parameter and chain to the default constructor:
private Lua lua;
public Form1(Lua lua) : this()
{
this.lua = lua;
}
In your Program class when instantiating Form1, pass the parameter to it:
lua = new Lua();
Application.Run(new Form1(lua));
Note that I am using OOP terminology - objects and classes (not files).
Update:
Since you have declared your lua variable as a public static member of the Program class, you can access it anywhere in your program (assuming the namespaces have been declared appropriately) as follows:
Program.lua;
Though you would want to instantiate the static field before calling Application.Run.
In any way, this makes the object a public shared resource across all threads - making it virtually untestable and difficult to work with if you go multi-threaded.
You can also access the parameter with
Program.lua;
But Oded's way is cleaner.
And in Main, the object must be instantiated before Application.Run:
static void Main()
{
lua = new Lua();
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new Form1());
}
In Program.cs there is most probably a static class defined like this:
static class Program
{
...
}
If you declare the variable as public or internal, you will be able to access it from your form.
static class Program
{
public static int myVariable;
public static int MyProperty { get; set; }
}
In your form, you access the variable and the property with:
int i = Program.myVariable;
int j = Program.MyProperty;
In object-oriented programming, you would usually keep the variables private and only declare the properties as public.

How to save an stringbuilder's content to text file using SaveFileDialog?

This is a winforms application.
In windows, I want the user to click and button, and then a popup should make the user select the path of where they want to save the file.
You want the WriteAllText function.
using (SaveFileDialog dialog = new SaveFileDialog()) {
if (dialog.ShowDialog(this) == DialogResult.OK) {
File.WriteAllText(dialog.FileName, yourStringBuilder.ToString());
}
}
Think no longer...
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
namespace WindowsFormsApplication2 {
public partial class Form1 : Form {
StringBuilder sb = new StringBuilder();
public Form1() {
InitializeComponent();
sb.Append("This is going ");
sb.Append("to be saved to a text file");
}
private void button1_Click(object sender, EventArgs e) {
using (SaveFileDialog dlg = new SaveFileDialog()) {
if (dlg.ShowDialog() == DialogResult.OK) {
string fileName = dlg.FileName;
SaveToFile(fileName);
}
}
}
private void SaveToFile(string fileName) {
System.IO.TextWriter w = new System.IO.StreamWriter(fileName);
w.Write(sb.ToString());
w.Flush();
w.Close();
}
}
StringBuilder.ToString() will get you the string.
This link will show you how to write text to a file.
This link will show you how to call SaveFileDialog and pass a stream to it to save.
Hope that helps.
StringBuilder.ToString() can be passed to the TextStream.Write() method after creating the file.
Using the SaveFileDialog class, you can let the user select path and file name - in a standard way. Detailed examples in the doc.

Resources