Can't insert a picture into RichTextBox - c#

I want to insert a picture into a RichTextBox. I add the picture in coding.
This is the major code, adding a jpg image:
MemoryStream memoryStream = new MemoryStream();
img.Save(memoryStream,System.Drawing.Imaging.ImageFormat.Jpeg);
byte[] bytes = memoryStream.ToArray();
String width = img.Width.ToString();
String height = img.Height.ToString();
String hexImgStr=BitConverter.ToString(bytes, 0).Replace("-","");
String picStr=#"{\pict\jpegblip\picw"+width+#"\pich"+height+
#"\picwgoal"+width+#"\pichgoal"+height+" "+hexImgStr+"}";
Then I insert the "picStr" to the rtf document. But the image can't be seen. I thought "hexImgStr" maybe wrong. I also generate the "hexImgStr" in another way:
FileStream fs = new FileStream(imgPath,FileMode.Open);
BinaryReader br=new BinaryReader(fs);
//byte[] bytes=new byte[fs.Length];
String hexImgStr="";
for (long i = 0; i < fs.Length; i++)
{
//bytes[i] = br.ReadByte();
hexImgStr +=Convert.ToString(br.ReadByte(),16);
}
The image can't be seen either. What's wrong with it.
Thanks a lot.

There's a high probability of failure here. It starts with inserting the RTF in the right place. The true problem is likely to be the exact format you generate. Images are embedded OLE objects for RTB, they need a metadata header that describes the object. There is no support whatsoever for this in .NET, OLE embedding went the way of the dodo a long time ago.
One thing I know that works is to get an image into an RTB through the clipboard. Like this:
private void button1_Click(object sender, EventArgs e) {
using (var img = Image.FromFile("c:\\screenshot.png")) {
Clipboard.SetImage(img);
richTextBox1.Paste();
}
}
Adjust the SelectionStart property as necessary to determine where the image gets inserted.

First add a picture to picturebox, then add below code inside the button click event
Or add picture manually.....
image.FromFile("Source");
Clipboard.SetImage(PictureBox1.Image);
this.RichTextBox1.Paste();

Related

Why LineHeight gets changed in WPF RichTexBox when reloading its content from a stream

Question: Why the following code changes the default LineHeight in WPF RichTexBox to 0? What would be a proper way to fix the issue?
Xaml for RichTextBox:
<RichTextBox x:Name="rtbTest" AcceptsTab="True" FontFamily="Calibri"/>
Code to reload content of RichTexBox from stream:
TextRange textRange = new TextRange(rtbTest.Document.ContentStart, rtbTest.Document.ContentEnd);
string rtf;
using (var memoryStream = new MemoryStream())
{
textRange.Save(memoryStream, DataFormats.Rtf);
rtf = ASCIIEncoding.Default.GetString(memoryStream.ToArray());
}
//rtf = rtf.Replace("abcd", "rstu");
using (MemoryStream stream = new MemoryStream(ASCIIEncoding.Default.GetBytes(rtf)))
{
rtbTest.SelectAll();
rtbTest.Selection.Load(stream, DataFormats.Rtf);
}
Screenshot of RichTexBox before running the above code:
Screenshot of RichTexBox AFTER running the above code:
You notice that the default LinHeight got changed to 0.
The DataFormats.Rtf format don't preserve line spacing. Use DataFormats.Xaml instead (doesn’t support images). Or even the DataFormats.XamlPackage: it will save and restore images too.

How to show an image obtained from a scanner using WIA in a picture box

I want to display an image retrieved from a scanner in a picturebox. So far I have been able to do it saving the image to a temporary file:
private void btnScan_Click(object sender, EventArgs e)
{
var fn = System.IO.Path.GetTempFileName();
System.IO.File.Delete(fn);
var image = Scanner.Scan();
image.SaveFile(fn);
_ScannedImage = Bitmap.FromFile(fn);
pictureBoxMain.Image = _ScannedImage;
}
Is there a way to convert the image data in the ImageFile class avoiding to save it to disk?
As per #C. Colin comment, theres' a way to get the bitbitmap from the ImageFile using a memory stream:
var imageBytes = (byte[])image.FileData.get_BinaryData();
var ms = new MemoryStream(imageBytes);
var img = Image.FromStream(ms);
Load a picturebox from a WIA ImageFile?
You can convert the ImageFile to Image, and after that create a Bitmap object:
var myImage = (Image)imageFile;
Bitmap bmp = new Bitmap(myImage);
Therefore you don't have to save (as you requested) in path.
Please tell me if this works for you.
See this post about converting from ImageFile to Image:
Load a picturebox from a WIA ImageFile?

How to replace some text with picture in RichTextBox without clipboard? [duplicate]

Most of the examples I see say to put it on the clipboard and use paste, but that doesn't seem to be very good because it overwrites the clipboard.
I did see one method that manually put the image into the RTF using a pinvoke to convert the image to a wmf. Is this the best way? Is there any more straightforward thing I can do?
The most straightforward way would be to modify the RTF code to insert the picture yourself.
In RTF, a picture is defined like this:
'{' \pict (brdr? & shading? & picttype & pictsize & metafileinfo?) data '}'
A question mark indicates the control word is optional.
"data" is simply the content of the file in hex format. If you want to use binary, use the \bin control word.
For instance:
{\pict\pngblip\picw10449\pich3280\picwgoal5924\pichgoal1860 hex data}
{\pict\pngblip\picw10449\pich3280\picwgoal5924\pichgoal1860\bin binary data}
\pict = starts a picture group,
\pngblip = png picture
\picwX = width of the picture (X is the pixel value)
\pichX = height of the picture
\picwgoalX = desired width of the picture in twips
So, to insert a picture, you just need to open your picture, convert the data to hex, load these data into a string and add the RTF codes around it to define a RTF picture. Now, you have a self contained string with picture data which you can insert in the RTF code of a document. Don't forget the closing "}"
Next, you get the RTF code from your RichTextBox (rtbBox.Rtf), insert the picture at the proper location, and set the code of rtbBox.Rtf
One issue you may run into is that .NET RTB does not have a very good support of the RTF standard.
I have just made a small application* which allows you to quickly test some RTF code inside a RTB and see how it handles it. You can download it here:
RTB tester (http://your-translations.com/toys).
You can paste some RTF content (from Word, for instance) into the left RTF box and click on the "Show RTF codes" to display the RTF codes in the right RTF box, or you can paste RTF code in the right RTB and click on "Apply RTF codes" to see the results on the left hand side.
You can of course edit the codes as you like, which makes it quite convenient for testing whether or not the RichTextBox supports the commands you need, or learn how to use the RTF control words.
You can download a full specification for RTF online.
NB It's just a little thing I slapped together in 5 minutes, so I didn't implement file open or save, drag and drop, or other civilized stuff.
I use the following code to first get the data from clipboard, save it in memory, set the image in clipboard, paste it in Rich Text Box and finally restore the data in Clipboard.
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
OpenFileDialog1.Filter = "All files |*.*"
OpenFileDialog1.Multiselect = True
Dim orgdata = Clipboard.GetDataObject
If OpenFileDialog1.ShowDialog = Windows.Forms.DialogResult.OK Then
For Each fname As String In OpenFileDialog1.FileNames
Dim img As Image = Image.FromFile(fname)
Clipboard.SetImage(img)
RichTextBox1.Paste()
Next
End If
Clipboard.SetDataObject(orgdata)
End Sub
The OpenFileDailog1, RichTextBox1 and Button1 are Open File Dialog, Rich Text Box and button controls respectively.
private void toolStripButton1_Click(object sender, EventArgs e)
{
FileDialog fDialog = new OpenFileDialog();
fDialog.CheckFileExists = true;
fDialog.CheckPathExists = true;
fDialog.RestoreDirectory = true;
fDialog.Title = "Choose file to import";
if (fDialog.ShowDialog() == DialogResult.OK)
{
string lstrFile = fDialog.FileName;
Bitmap myBitmap = new Bitmap(lstrFile);
// Copy the bitmap to the clipboard.
Clipboard.SetDataObject(myBitmap);
DataFormats.Format format = DataFormats.GetFormat(DataFormats.Bitmap);
// After verifying that the data can be pasted, paste
if(top==true && this.rtTop.CanPaste(format))
{
rtTop.Paste(format);
}
if (btmLeft == true && this.rtBottomLeft.CanPaste(format))
{
rtBottomLeft.Paste(format);
}
if (btmCenter == true && this.rtBottomCenter.CanPaste(format))
{
rtBottomCenter.Paste(format);
}
if (btmRight == true && this.rtBottomRight.CanPaste(format))
{
rtBottomRight.Paste(format);
}
}
}
Here is what I do to hack the rich text control:
Insert the required image in wordpad or MS-WORD. Save the file as 'rtf'. Open the rtf file in notepad to see the raw rtf code. Copy the required tags & stuff to the 'rtf' property of your Rich Text Box (append to existing text).
There is some trial and error involved but works.
With C#, I use place holder StringBuilder objects with the necessary rtf code. Then I just append the image path.
This is a workaround for not having to learn the RTF syntax.
My own version that I posted in a new thread, apparently I should have searched and posted it here. Anyway, using the clipboard again, very easy.
private void button1_Click(object sender, EventArgs e)
{
openFileDialog1.Filter = "Images |*.bmp;*.jpg;*.png;*.gif;*.ico";
openFileDialog1.Multiselect = false;
openFileDialog1.FileName = "";
DialogResult result = openFileDialog1.ShowDialog();
if (result == DialogResult.OK)
{
Image img = Image.FromFile(openFileDialog1.FileName);
Clipboard.SetImage(img);
richTextBox1.Paste();
richTextBox1.Focus();
}
else
{
richTextBox1.Focus();
}
}
}
If you were in C++, the way to do it is thru OLE. More specifically, if you search Google for ImageDataObject it will show C++ code how to insert a HBITMAP into the RTF Control. One link is here.
Now, how this translates into .Net code, I don't know. I currently don't have the time to work thru the details.
I was also looking for something for this same task and found this ->
http://sourceforge.net/projects/netrtfwriter/
You can generate any type of RTF text that you would want and then use it however you wish. Very well structured example which will auto sense the image type being used (jpg/jpeg/png etc) and worked for the image files I have been using. If you are in a hurry then this is a great RTF generator!
All I did was make a small pictureBox control in c# and made sure it was hidden behind another object big enough to hide it. Then I made a button to insert a picture, and it loaded the pictureBox with the image then it puts it in the richTextBox then it clears the pictureBox control.
Here is the code.
private void InsertPicture_Click(object sender, EventArgs e)
{
{
if (openFileDialog4.ShowDialog() == DialogResult.OK)
{
// Show the Open File dialog. If the user clicks OK, load the
// picture that the user chose.
pictureBox2.Load(openFileDialog4.FileName);
Clipboard.SetImage(pictureBox2.Image);
pictureBox2.Image = null;
this.richTextBox1.Paste();
}
}
}
After inserting the code to do it with the clipboard, type in Clipboard.Clear();. It works well and it doesn't clear everything, only the item last added to the clipboard.
Full Code:
private void addPictureToRTB()
{
using (OpenFileDialog ofd = new OpenFileDialog() { Filter = "Pictures|*.png" })
{
if (ofd.ShowDialog() == DialogResult.OK)
{
ClipBoard.SetImage(Image.FromFile(ofd.FileName));
richTextBox.Paste();
Clipboard.Clear();
}
}
}
Then reference this function where you need to.
Several hours surfing for solution to insert image without loosing quality and fixed the gray background with transparent image/png
// assuming the image is in your Resources
var img = Resources.ImageWithTransparentBckgrnd;
var g = Graphics.FromImage(img);
using (var ms = new MemoryStream())
{
img.Save(ms, ImageFormat.Png);
IntPtr ipHdc = g.GetHdc();
Metafile mf = new Metafile(ms, ipHdc);
g = Graphics.FromImage(mf);
g.FillEllipse(Brushes.White, 0, 0, 16, 16); // size you want to fill in
g.Dispose();
mf.Save(ms, ImageFormat.Png);
IDataObject dataObject = new DataObject();
dataObject.SetData("PNG", false, ms);
Clipboard.SetDataObject(dataObject, false);
richTextBox1.Paste();
SendKeys.Send("{RIGHT}");
richTextBox1.Focus();
}

Print preview issue in Steema Teechart with graphics3d

I am using tchart with graphics 3d for real time chart plotting. whenever I try to call print preview for the chart, the preview page is just a blank page and the actual chart background becomes black. I tried different tricks and i found this printpreview works in normal canvas. but as soon as i write the line
Chart1.Graphics3D = new Graphics3DDirect2D(Chart1.Chart);
print preview does not work .
If I call export function, e.g. export to pdf functionality then the pdf file has exported chart in it and alternate route can be I can print the pdf.
But I want to use print preview and give user a functionality to change margins and other things as per their need.
Link for the demo project is http://www.filedropper.com/sampleprojecttchartprint
Link for the Video describing issue is http://tinypic.com/r/2ufg7f5/5
What am I doing wrong here?
There is a limitation with the wrapper TeeChart uses, a limitation documented here:
http://bugs.teechart.net/show_bug.cgi?id=356
As suggested, the workaround is to use the GDI+ canvas for image exportation, e.g.
private void InitializeChart()
{
tChart1.Graphics3D = new Graphics3DDirect2D(tChart1.Chart);
tChart1.Aspect.View3D = false;
FastLine series = new FastLine(tChart1.Chart);
series.FillSampleValues(1000);
}
TChart tChart2;
private void button1_Click(object sender, EventArgs e)
{
if(tChart2 == null) tChart2 = new TChart();
MemoryStream ms = new MemoryStream();
tChart1.Export.Template.Save(ms);
ms.Position = 0;
tChart2.Import.Template.Load(ms);
tChart2.Export.Image.PNG.Width = tChart1.Width;
tChart2.Export.Image.PNG.Height = tChart1.Height;
tChart2.Export.Image.PNG.Save(#"C:\tmp\direct2d.png");
}

Cannot delete an image file that is shown in a listview

In my listview I show thumbnails of small images in a certain folder. I setup the listview as follows:
var imageList = new ImageList();
foreach (var fileInfo in dir.GetFiles())
{
try
{
var image = Image.FromFile(fileInfo.FullName);
imageList.Images.Add(image);
}
catch
{
Console.WriteLine("error");
}
}
listView.View = View.LargeIcon;
imageList.ImageSize = new Size(64, 64);
listView.LargeImageList = imageList;
for (int j = 0; j < imageList.Images.Count; j++)
{
var item = new ListViewItem {ImageIndex = j, Text = "blabla"};
listView.Items.Add(item);
}
The user can rightclick on an image in the listview to remove it. I remove it from the listview and then I want to delete this image from the folder. Now I get the error that the file is in use. Of course this is logical since the imagelist is using the file.
I tried to first remove the image from the imagelist, but I keep on having the file lock.
Can somebody tell me what I am doing wrong?
Thanks!
You need to load the file into a MemoryStream, like this:
var image = Image.FromStream(new MemoryStream(File.ReadAllBytes(fileInfo.FullName)));
This way, the file will only be read once, and will not remain locked.
EDIT
You're loading the images into an ImageList.
Since the ImageList makes copies of its images, you should simply dispose the originals right away, like this:
using (var image = Image.FromFile(fileInfo.FullName))
imageList.Images.Add(image);
The image will need to be disposed of before it will unlock the file. Try calling Dispose on the image object after you remove it from the image list.
So long as you have a reference to the image object and the GC hasn't collected it, it will keep the lock. Calling Dispose should force it to give up its handle and cause the file to be unlocked.
You also have to make sure that the app didn't CopyHandle or otherwise get a second reference to the image resource before doing this.
Use GetThumbnailImage and then dispose image:
var image = Image.FromFile(fileN);
Image imgThumb = image.GetThumbnailImage(100, 100, null, new IntPtr());
imageList1.Images.Add(imgThumb);
image.Dispose();
listView1.LargeImageList = imageList1;
Now you can delete the file:
File.Delete(FileN);

Categories

Resources