I want to take a screenshot of my control on Winform. I use this function - find in this site :
public void GetImage()
{
var bm = new Bitmap(display1.Width, display1.Height);
display1.DrawToBitmap(bm, display1.ClientRectangle);
bm.Save(#"c:\whatever.gif", ImageFormat.Gif);
}
But when I'm using it, i have a error about 'System.Runtime.InteropServices.ExternalException' in System.Drawing.dll : A generic error occurred in GDI +.
Do you have any idea aboout that ?
Thanks !
----------------------EDIT---------------------------
Ok I have change my function like this :
public void GetImage()
{
var bm = new Bitmap(display1.Width, display1.Height);
display1.DrawToBitmap(bm, display1.ClientRectangle);
var dlg = new SaveFileDialog { DefaultExt = "png", Filter = "Png Files|*.png" };
var res = dlg.ShowDialog();
if (res == DialogResult.OK) bm.Save(dlg.FileName, ImageFormat.Png);
}
and it's works but I have now an empty picture :/
Try the following:
assuming display1 is a Rectangle that bounds the area of the display you wish to capture.
public void GetImage()
{
Rectangle display1 = this.Bounds; // winforms control bounds
// for full screen use "= Screen.GetBounds(Point.Empty);
var bm = new Bitmap(display1.Width, display1.Height);
//display1.DrawToBitmap(bm, display1.ClientRectangle);
Graphics g = Graphics.FromImage(bm);
g.CopyFromScreen(new Point(display1.Left, display1.Top), Point.Empty, display1.Size);
var dlg = new SaveFileDialog { DefaultExt = "png", Filter = "Png Files|*.png" };
var res = dlg.ShowDialog();
if (res == DialogResult.OK) bm.Save(dlg.FileName, ImageFormat.Png);
}
Related
When my form opens it uses the file path that is provided from another form and displays the images, and when I close the form I want it to delete all the images.
But when I close it keeps stating the file is being used, is there a better way of doing it please?
public frmMark(string strImagePath)
{
InitializeComponent();
pbImage1.Image = new Bitmap(strImagePath + "1.jpg");
pbImage2.Image = new Bitmap(strImagePath + "2.jpg");
pbImage3.Image = new Bitmap(strImagePath + "3.jpg");
}
private void frmMark_FormClosing(object sender, FormClosingEventArgs e)
{
File.Delete(deletepath + "1.jpg");
}
Change this:
pbImage1.Image = new Bitmap(strImagePath + "1.jpg");
to this:
pbImage1.ImageLocation = Path.Combine(strImagePath, "1.jpg");
and for the others and your issue should go away because the files will not be locked, so you don't have to worry about unlocking them.
Perhaps create a language extension which clones the original image, load the image then deletes the physical file.
public static class PictureBoxExtensions
{
public static void LoadClone(this PictureBox pictureBox, string fileName)
{
var imageOriginal = Image.FromFile(fileName);
var imageClone = new Bitmap(imageOriginal.Width, imageOriginal.Height);
Graphics gr = Graphics.FromImage(imageClone);
gr.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.None;
gr.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.NearestNeighbor;
gr.PixelOffsetMode = System.Drawing.Drawing2D.PixelOffsetMode.HighSpeed;
gr.DrawImage(imageOriginal, 0, 0, imageOriginal.Width, imageOriginal.Height);
gr.Dispose();
imageOriginal.Dispose();
pictureBox.Image = imageClone; // assign the clone to picture box
File.Delete(fileName); // remove original
}
}
Or if not always needing to remove an image add another parameter,in this case remove where the default is to remove which of course you can set the default to false.
public static class PictureBoxExtensions
{
public static void LoadClone(this PictureBox pictureBox, string fileName, bool remove = true)
{
var imageOriginal = Image.FromFile(fileName);
var imageClone = new Bitmap(imageOriginal.Width, imageOriginal.Height);
Graphics gr = Graphics.FromImage(imageClone);
gr.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.None;
gr.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.NearestNeighbor;
gr.PixelOffsetMode = System.Drawing.Drawing2D.PixelOffsetMode.HighSpeed;
gr.DrawImage(imageOriginal, 0, 0, imageOriginal.Width, imageOriginal.Height);
gr.Dispose();
imageOriginal.Dispose();
pictureBox.Image = imageClone; // assign the clone to picture box
if (remove)
{
File.Delete(fileName); // remove original
}
}
}
Usage
public frmMark(string strImagePath)
{
InitializeComponent();
pbImage1.LoadClone(strImagePath + "1.jpg");
pbImage2.LoadClone(strImagePath + "2.jpg");
pbImage2.LoadClone(strImagePath + "3.jpg");
}
I use InkCanvas to implement signature function.
after signed, I can use RenderTargetBitmap class to save the signature-drawing into bitmap.
but RenderTargetBitmap always save InkCanvas itself, means can not save ONLY the signature content.
my question is, how to save StrokeCollection into bitmap?
I think you should use Win2D (Win2D.uwp NuGet package); it is pretty easy.
Here is the code:
async void SaveAsBitmap(object sender, RoutedEventArgs e)
{
//copy from origianl canvas and paste on the new canvas for saving
var strokes = inkCanvas.InkPresenter.StrokeContainer.GetStrokes();
//check if canvas is not empty
if (strokes.Count == 0) return;
//select all the strokes to be copied to the clipboard
foreach (var stroke in strokes)
{
stroke.Selected = true;
}
inkCanvas.InkPresenter.StrokeContainer.CopySelectedToClipboard();
//paste the strokes to a new InkCanvas and move the strokes to the topper left corner
var newCanvas = new InkCanvas();
newCanvas.InkPresenter.StrokeContainer.PasteFromClipboard(new Point(0, 0));
//using Win2D to save ink as png
CanvasDevice device = CanvasDevice.GetSharedDevice();
CanvasRenderTarget renderTarget = new CanvasRenderTarget(device,
(int)inkCanvas.InkPresenter.StrokeContainer.BoundingRect.Width,
(int)inkCanvas.InkPresenter.StrokeContainer.BoundingRect.Height,
96);
using (var ds = renderTarget.CreateDrawingSession())
{
//ds.Clear(Colors.White); //uncomment this line for a white background
ds.DrawInk(newCanvas.InkPresenter.StrokeContainer.GetStrokes());
}
//save file dialog
var savePicker = new Windows.Storage.Pickers.FileSavePicker()
{
SuggestedStartLocation = Windows.Storage.Pickers.PickerLocationId.DocumentsLibrary
};
savePicker.FileTypeChoices.Add("Image file", new List<string>() { ".jpeg", ".png" });
savePicker.SuggestedFileName = "mysign.png";
var file = await savePicker.PickSaveFileAsync();
if (file != null)
{
using (var fileStream = await file.OpenAsync(FileAccessMode.ReadWrite))
{
await renderTarget.SaveAsync(fileStream, CanvasBitmapFileFormat.Png);
}
}
}
I have a RichTextBox control in an application I am developing which I am using along with a ToolBar to create a rich text editor. One feature I have implemented is the ability for a user to insert an Image, now it worth noting at this point that the output from the RichTextBox is RTF.
When the user inserts the Image I am using the following code to add the image to the Document and then add a ResizeAdorner (example from here RichTextBox Resizing Adorner) to the Image which allows the user to resize. When the user saves and loads the Document the size of the Image is persisted correctly.
private void BtnInsertImage_OnClick(object sender, RoutedEventArgs e)
{
OpenFileDialog ofd = new OpenFileDialog();
ofd.Multiselect = false;
ofd.CheckFileExists = true;
ofd.CheckPathExists = true;
ofd.Filter = "Image files (*.png;*.jpg;*.jpeg;*.gif;*.bmp)|*.png;*.jpg;*.jpeg;*.gif;*.bmp";
ofd.InitialDirectory = Environment.GetFolderPath(Environment.SpecialFolder.MyPictures);
ofd.Title = "Insert Image";
if (ofd.ShowDialog() == true)
{
BitmapImage bitmap = new BitmapImage(new Uri(ofd.FileName, UriKind.RelativeOrAbsolute))
{
CacheOption = BitmapCacheOption.OnLoad
};
Image image = new Image();
image.IsEnabled = true;
image.Source = bitmap;
image.Width = bitmap.Width;
image.Height = bitmap.Height;
image.Loaded += this.ImageOnLoaded;
image.Stretch = Stretch.Uniform;
InlineUIContainer container = new InlineUIContainer(image, this.rtbEditor.Selection.Start);
Paragraph paragraph = new Paragraph(container);
var doc = this.rtbEditor.Document;
doc.Blocks.Add(paragraph);
}
}
private void ImageOnLoaded(object sender, RoutedEventArgs routedEventArgs)
{
var img = sender as Image;
if (img != null)
{
var al = AdornerLayer.GetAdornerLayer(img);
if (al != null)
{
al.Add(new ResizingAdorner(img));
}
}
}
The problem and question is that when the Document is loaded i am unable to figure out how to add the ResizingAdorner to the Images in the document. I am using an attached property to load the document contents, the code below is the part that loads the document:
var stream = new MemoryStream(Encoding.UTF8.GetBytes(GetDocumentXaml(richTextBox)));
var doc = new FlowDocument();
var range = new TextRange(doc.ContentStart, doc.ContentEnd);
range.Load(stream, DataFormats.Xaml);
richTextBox.Document = doc;
Could anyone help with how I can add the ResizingAdorner to any images in the loaded Document please?
So I have worked out a way that I can add the Adorner to the Image in the Document through the SelectionChanged event handler and the following code
var inline = this.rtbEditor.CaretPosition.GetAdjacentElement(LogicalDirection.Forward) as Inline;
if (inline != null)
{
this.AddAdorner(inline.NextInline as InlineUIContainer);
this.AddAdorner(inline.PreviousInline as InlineUIContainer);
}
And this is the AddAdorner method
private void AddAdorner(InlineUIContainer container)
{
if (container != null)
{
var image = container.Child;
if (image != null)
{
var al = AdornerLayer.GetAdornerLayer(image);
if (al != null)
{
var currentAdorners = al.GetAdorners(image);
if (currentAdorners != null)
{
foreach (var adorner in currentAdorners)
{
al.Remove(adorner);
}
}
al.Add(new ResizingAdorner(image));
}
}
}
}
I know this is probably not the most elegant way to achieve this but for me this works so I wanted to post this so that others can choose to use this if appropriate
I am working with WPF and I have an application that the user loads an image file into a RichTextBox and they can rotate the image and print it. I am not sure as to why the image after it has been rotated will not print as it is displayed on the screen. Instead it prints the original. I am new to this so any help would be greatly appreciated!
The following is the code for my application. Code when the retrieve file Button is clicked:
private void retrieve_button_Click(object sender, RoutedEventArgs e)
{
//Retrieve the file or image you are looking for
OpenFileDialog of = new OpenFileDialog();
of.Filter = "Formats|*.jpg;*.png;*.bmp;*.gif;*.ico;*.txt|JPG Image|*.jpg|BMP image|*.bmp|PNG image|*.png|GIF Image|*.gif|Icon|*.ico|Text File|*.txt";
var dialogResult = of.ShowDialog();
if (dialogResult == System.Windows.Forms.DialogResult.OK)
{
try
{
System.Windows.Controls.RichTextBox myRTB = new System.Windows.Controls.RichTextBox();
{
Run myRun = new Run();
System.Windows.Controls.Image MyImage = new System.Windows.Controls.Image();
MyImage.Source = new BitmapImage(new Uri(of.FileName, UriKind.RelativeOrAbsolute));
InlineUIContainer MyUI = new InlineUIContainer();
MyUI.Child = MyImage;
rotateright_button.IsEnabled = true;
print_button.IsEnabled = true;
Paragraph paragraph = new Paragraph();
paragraph.Inlines.Add(myRun);
paragraph.Inlines.Add(MyUI);
FlowDocument document = new FlowDocument(paragraph);
richTextBox.Document = document;
}
}
catch (ArgumentException)
{
System.Windows.Forms.MessageBox.Show("Invalid File");
}
}
}
When the rotate right button is clicked the following code is executed:
RotateTransform cwRotateTransform;
private void rotateright_button_Click(object sender, RoutedEventArgs e)
{
richTextBox.LayoutTransform = cwRotateTransform;
if (cwRotateTransform == null)
{
cwRotateTransform = new RotateTransform();
}
if (cwRotateTransform.Angle == 360)
{
cwRotateTransform.Angle = 0;
}
else
{
cwRotateTransform.Angle += 90;
}
}
After the Image has been loaded and rotated the user can use the following code to print:
private void InvokePrint(object sender, RoutedEventArgs e)
{
System.Windows.Controls.PrintDialog printDialog = new System.Windows.Controls.PrintDialog();
if ((bool)printDialog.ShowDialog().GetValueOrDefault())
{
FlowDocument flowDocument = new FlowDocument();
flowDocument = richTextBox.Document;
flowDocument.ColumnWidth = printDialog.PrintableAreaWidth;
flowDocument.PagePadding = new Thickness(65);
IDocumentPaginatorSource iDocPag = flowDocument;
printDialog.PrintDocument(iDocPag.DocumentPaginator, "Print Document");
}
}
Try this (substitute yourImageControl in the first line, specify which RotateFlipType you want and be sure to reference the System.Drawing dll):
System.Drawing.Bitmap bitmap = BitmapSourceToBitmap((BitmapSource)YourImageControl.Source);
bitmap.RotateFlip(System.Drawing.RotateFlipType.Rotate90FlipNone);
public static System.Drawing.Bitmap BitmapSourceToBitmap(BitmapSource bitmapsource)
{
System.Drawing.Bitmap bitmap;
using (MemoryStream outStream = new MemoryStream())
{
BitmapEncoder enc = new BmpBitmapEncoder();
enc.Frames.Add(BitmapFrame.Create(bitmapsource));
enc.Save(outStream);
bitmap = new System.Drawing.Bitmap(outStream);
}
return bitmap;
}
Another option for conversion...
P.S. You would get a better answer in less time if you posted some code and told us more about what you have tried.
I am attempting to populate a secondary tile background with an image saved from the PhotoChooserTask, but for some reason I cannot accomplish this. I have referenced a lot of sites but I have not found the proper implementation. All I do is call PhotoChooserTask, and then on the completed event I save the resulting image to isolated storage to be loaded later. This has worked with a HubTile in my application, but for some reason I cannot append the image to a secondary tile. So far what I have is as follows:
MainPage.xaml.cs
string imageFolder = #"\Shared\ShellContent";
string shareJPEG = "shareImage.jpg";
public MainPage()
{
InitializeComponent();
photoChooserTask = new PhotoChooserTask();
photoChooserTask.Completed += new EventHandler<PhotoResult>(photoChooserTask_Completed);
}
public void changePictureMenuItem_Tap(object sender, System.Windows.Input.GestureEventArgs e)
{
try
{
photoChooserTask.Show();
}
catch (System.InvalidOperationException)
{
MessageBox.Show("An error occurred");
}
}
void photoChooserTask_Completed(object sender, PhotoResult e)
{
if (e.TaskResult == TaskResult.OK)
{
//persist the data in isolated storage
using (IsolatedStorageFile myIsolatedStorage = IsolatedStorageFile.GetUserStoreForApplication())
{
if(!myIsolatedStorage.DirectoryExists(imageFolder))
{
myIsolatedStorage.CreateDirectory(imageFolder);
}
if (myIsolatedStorage.FileExists(shareJPEG))
{
myIsolatedStorage.DeleteFile(shareJPEG);
}
string filePath = System.IO.Path.Combine(imageFolder, shareJPEG);
IsolatedStorageFileStream fileStream = myIsolatedStorage.CreateFile(filePath);
BitmapImage bitmap = new BitmapImage();
bitmap.SetSource(e.ChosenPhoto);
WriteableBitmap wb = new WriteableBitmap(bitmap);
// Encode WriteableBitmap object to a JPEG stream.
Extensions.SaveJpeg(wb, fileStream, 173, 173, 0, 100);
fileStream.Close();
}
}
}
private void CreateLiveTile(TileItem item)
{
//IsolatedStorageFile myIsolatedStorage = IsolatedStorageFile.GetUserStoreForApplication();
var title = item.Title.ToString();
string tileParameter = "Param=" + item.Title.ToString();
ShellTile Tile = CheckIfTileExist(tileParameter); // Check if Tile's title has been used
if (Tile == null)
{
//this is not working?
background = new Uri(#"isostore:/Shared/ShellContent/shareJPEG.png", UriKind.Absolute);
//background = new Uri("isostore:/Shared/ShellContent/shareJPEG.png", UriKind.Absolute);
try
{
var LiveTile = new StandardTileData
{
Title = item.TileName,
BackgroundImage = background, //not working
BackTitle = item.TileName,
BackBackgroundImage = new Uri("/background.png", UriKind.Relative),
BackContent = item.Message,
};
ShellTile.Create(new Uri("/MainPage.xaml?" + tileParameter, UriKind.Relative), LiveTile);
}
}
Ultimately, the secondary tile is created but there is no image for the BackgroundImage. How would I properly call the isolated strorage path to set the BackgroundImage of the secondary tile accordingly? Or is there something else I should be doing or change?
MainPage.xaml.cs
string imageFolder = #"\Shared\ShellContent";
string shareJPEG = "shareImage.jpg";
...
private void CreateLiveTile(TileItem item)
{
var title = item.Title.ToString();
string tileParameter = "Param=" + item.Title.ToString();
ShellTile Tile = CheckIfTileExist(tileParameter); // Check if Tile's title has been used
if (Tile == null)
{
string filePath = System.IO.Path.Combine(imageFolder, shareJPEG);
background = new Uri(#"isostore" + filePath, UriKind.Absolute); //this worked
...
}
}
Are you sure the image is saved successfully and exists? You save it as jpeg but you reference a png file. Try #"\Shared\ShellContent\shareJPEG.png"
first you should put your image at "\Shared\ShellContent" location. you can use .png or .jpg file
string imageFolder = #"\Shared\ShellContent";
string shareJPEG = "shareImage.jpg";
...
private void CreateLiveTile(TileItem item)
{
var title = item.Title.ToString();
string tileParameter = "Param=" + item.Title.ToString();
ShellTile Tile = CheckIfTileExist(tileParameter);
if (Tile == null)
{
string filePath = System.IO.Path.Combine(imageFolder, shareJPEG);
using (var iso = IsolatedStorageFile.GetUserStoreForApplication())
{
if (iso.FileExists(filePath)) // check file exist or not
background = new Uri(#"isostore:" + filePath, UriKind.Absolute);
}
...
}
}