How to take screenshot of webpage in C# - c#

I am totally new to C# coding - I am trying to take screen shots of webpages whose URLs are initially picked up form a notepad uploaded on the same form.
As I read through the documentation on the web_browser control in MSDN.. I did arrive at the following code - yet when I run, I only get white screens
I tried uploading a .txt with (google/yahoo URLs as test data in 2 lines)
Can someone please say what more should I take care apart from handling which should get what I want as I read in MSDN.
P.S: pls forgive if I'm terribly wrong in coding style .. as aforesaid I'm just starting my C# coding :)
Code that I tried...
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 MSDN_wbc_tut1
{
public partial class Form1 : Form
{
public int temp = 0;
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
}
private void FileUploadButton1_Click(object sender, EventArgs e)
{
//once a file is uploaded i want Pgm to read contents & browse them as URLS
OpenFileDialog openFileDialog = new OpenFileDialog();
openFileDialog.CheckFileExists = true;
openFileDialog.AddExtension = true;
openFileDialog.Multiselect = true;
//Filtering for Text files alone
openFileDialog.Filter = "text files (*.txt)|*.txt";
//if file is selected we must then do our coding part to proceed hecneforth
if (openFileDialog.ShowDialog() == System.Windows.Forms.DialogResult.OK)
{
//my code to say pgm wat to do once upload done...
//Getting my Chosen file's name
string Fileuploaded = openFileDialog.FileName;
//Read all line opens files - reads till EOF & closes ,prevents a while condition
string[] FileuploadedContent = System.IO.File.ReadAllLines(Fileuploaded);
foreach (string s in FileuploadedContent)
{
NavigateContent(s);
}
}
}
private void NavigateContent(string lineasurl)
{
// Add an event handler that images the document after it loads.
try
{
webBrowser1.DocumentCompleted += new WebBrowserDocumentCompletedEventHandler
(takescreen);
webBrowser1.Navigate(new Uri(lineasurl));
//webBrowser1.Navigate(lineasurl); also works
}
catch (System.UriFormatException)
{
return;
}
}
private void takescreen(object sender, WebBrowserDocumentCompletedEventArgs e)
{
//specifying sample values for image or screenshot size
int x = 600, y = 700;
Bitmap bitmap = new Bitmap(x, y);
webBrowser1.DrawToBitmap(bitmap, new Rectangle(0, 0, x, y));
//to give each screen a unique name - i append some no onto it
temp = temp + 1;
string TempFname = "Screenshotref" + temp.ToString() + "." + "jpg";
bitmap.Save(TempFname);
}
}
}

Related

Cursor Application Issues

So I'm trying to create an application that displays all the cursors in the folder C:\Windows\Cursors and allows the user to click on an image of the cursor they want and have it applied. Thanks for reading.
I've been trying to convert the .cur file to .jpeg because I think this is the reason that it is not being displayed under flowLayoutPanel1 but it is still not working.
using Microsoft.Win32;
using System;
using System.Diagnostics;
using System.Runtime.InteropServices;
using System.IO;
using System.Windows.Forms;
using System.Drawing.Imaging;
using ImageMagick;
namespace CrossHare
{
public partial class Form1 : Form
{
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
private static extern bool SystemParametersInfo(int uiAction, int uiParam, IntPtr pvParam, int fWinIni);
[DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Auto)]
private static extern IntPtr LoadCursorFromFile(string lpFileName);
private const int SPI_SETCURSORS = 0x0057;
private const int SPIF_UPDATEINIFILE = 0x01;
private const int SPIF_SENDCHANGE = 0x02;
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
// Get the file paths of all files in the directory
string[] files = Directory.GetFiles(#"C:\Windows\Cursors");
// Iterate through the file paths
foreach (string file in files)
{
// Check if the file is an image file
if (!file.EndsWith(".cur")) continue;
try
{
// Create a new button
Button btn = new Button();
//Convert cur file to jpeg
using (MagickImage image = new MagickImage(file))
{
string jpegFile = Path.ChangeExtension(file, ".jpeg");
image.Format = MagickFormat.Jpeg;
image.Write(jpegFile);
using (Image img = Image.FromFile(jpegFile))
{
btn.Tag = file;
btn.Image = img;
}
}
btn.Size = new Size(100, 100);
btn.Click += Button_Click;
flowLayoutPanel1.Controls.Add(btn);
}
catch (FileNotFoundException ex)
{
// Handle file not found exception
MessageBox.Show("Error: " + ex.Message);
}
catch (OutOfMemoryException ex)
{
// Handle out of memory exception
MessageBox.Show("Error: " + ex.Message);
}
}
}
private void Button_Click(object sender, EventArgs e)
{
// Handle button click event
MessageBox.Show("Button clicked!");
// Get the selected file's path
string filePath = ((Button)sender).Image.Tag as string;
// Set the selected file as the "normal select" pointer in "Mouse properties"
RegistryKey key = Registry.CurrentUser.OpenSubKey("Control Panel\\Cursors", true);
key.SetValue("Arrow", filePath);
key.Close();
IntPtr hCursor = new IntPtr((int)LoadCursorFromFile(filePath));
SystemParametersInfo(SPI_SETCURSORS, 0, hCursor, SPIF_UPDATEINIFILE | SPIF_SENDCHANGE);
}
private void UploadButton_Click(object sender, EventArgs e)
{
OpenFileDialog openFileDialog = new OpenFileDialog();
openFileDialog.Filter = "Cursor files (*.cur)|*.cur|All files (*.*)|*.*";
openFileDialog.InitialDirectory = Environment.GetFolderPath(Environment.SpecialFolder.Desktop);
if (openFileDialog.ShowDialog() == DialogResult.OK)
{
// Get the selected file's path
string filePath = openFileDialog.FileName;
// Do something with the file (e.g. upload it to a server)
string destinationPath = #"C:\Windows\Cursors";
string destinationFilePath = Path.Combine(destinationPath, Path.GetFileName(filePath));
if (File.Exists(destinationFilePath))
{
DialogResult result = MessageBox.Show("File already exists, do you want to overwrite it?", "File Exists", MessageBoxButtons.YesNo);
if (result == DialogResult.No)
{
return;
}
}
File.Copy(filePath, destinationFilePath, true);
}
}
}
}
After carefully reading your code, if I'm following correctly your objectives are:
Display all the available cursors in a FlowLayoutPanel.
Click on an image to change the current cursor.
What we end up with here could be considered an X-Y Problem because doing that is straightforward, but the manner in which you're trying to solve your problem is not.
Please allow me to steer the conversation back to what you were trying to do to begin with:
To achieve this objective, use reflection to obtain the cursors from the Cursors class, draw each one, and place a corresponding button in the FlowLayoutPanel.
public partial class MainForm : Form
{
public MainForm()=>InitializeComponent();
protected override void OnLoad(EventArgs e)
{
base.OnLoad(e);
foreach (PropertyInfo pi in typeof(Cursors).GetProperties(BindingFlags.Static | BindingFlags.Public))
{
if(pi.GetValue(null) is Cursor cursor)
{
var image = new Bitmap(100, 100);
using (var graphics = Graphics.FromImage(image))
{
cursor.DrawStretched(
graphics,
new Rectangle(new Point(), new Size(image.Width, image.Height)));
}
var button = new Button
{
Size = image.Size,
BackgroundImage = image,
BackgroundImageLayout = ImageLayout.Stretch,
Margin = new Padding(5),
Tag = cursor,
};
button.Click += onAnyClickCursorButton;
// Avoid confusion - see note.
button.MouseHover += (sender, e) => Cursor = Cursors.Default;
flowLayoutPanel.Controls.Add(button);
}
}
}
By attaching a Click event to each button, the current Cursor can be changed to the one clicked. To avoid visual confusion, if a different button is hovered over then return to the default cursor to more clearly indicate that the new style can now be clicked.
private void onAnyClickCursorButton(object? sender, EventArgs e)
{
if((sender is Button button) && (button.Tag is Cursor cursor))
{
Cursor = cursor;
}
}
}

Access to file denied in C# .NET 3.1 forms

Hello I was writing a basic text editor in C# on visual studio windows form using the .NET framework 3.1 long term support version everything worked fine until I wrote the save file script
Here's the code for "Form1.cs" which is where the open and save file functions reside
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.IO;
using System.Security.Principal;
namespace Text_Editor
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
string locsave;
private void openbtn_Click(object sender, EventArgs e)
{
var identity = WindowsIdentity.GetCurrent();
var principal = new WindowsPrincipal(identity);
if (principal.IsInRole(WindowsBuiltInRole.Administrator) != true)
{
MessageBox.Show("Run as Admin");
System.Windows.Forms.Application.ExitThread();
}
else
{
OpenFileDialog openfile = new OpenFileDialog();
if (openfile.ShowDialog() == DialogResult.OK)
{
var locationArray = openfile.FileName;
string location = "";
locsave = locationArray;
foreach (char peice in locationArray)
{
location = location + peice;
}
var contentArray = File.ReadAllText(location);
string content = "";
label4.Text = location;
foreach (char peice in contentArray)
{
content = content + peice;
}
richTextBox1.Text = content;
}
}
}
private void Form1_Load(object sender, EventArgs e)
{
Console.WriteLine("Test");
}
private void savebtn_Click(object sender, EventArgs e)
{
if (#label4.Text == "")
{
MessageBox.Show("Open a text file first");
}
else
{
StreamWriter outputfile = new StreamWriter(locsave);
outputfile.Write(richTextBox1.Text); //this is where the error occures and it throws the error of access denyed
outputfile.Close();
}
}
}
}
Does anyone have a suggestion about what to do I looked around on google for a solution but it seemed most did not work and some others I did not understand.

Adding Page Numbers

I haven't really written anything outside of Powershell in a long time, and I know this is ugly, but I can't seem to figure out why my new PDF is not adding the page numbers. I pulled the example from this itext kb.
I tried to make this basic app so people in the office could add the page numbers to PDF's. Here's what I have so far. It will create the new PDF (duplicate of the original), but it's not adding the page numbers.
Basically they use button1 to find their PDF via the Windows File Explorer dialog. It just stores the filename in a textbox. The second button is the "save" and should take the src file and make a copy of the src with only adding the page number at the bottom of the file (or anywhere at this point).
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Security.Cryptography.X509Certificates;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using iText.Kernel.Pdf;
using iText.Layout;
using iText.Layout.Element;
using iText.Layout.Properties;
namespace PDFManipulation
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
int size = -1;
DialogResult result = openFileDialog1.ShowDialog(); // Show the dialog.
if (result == DialogResult.OK) // Test result.
{
string file = openFileDialog1.FileName;
try
{
string text = File.ReadAllText(file);
size = text.Length;
textBox1.Text = file;
}
catch (System.IO.IOException)
{
}
}
Console.WriteLine(size); // <-- Shows file size in debugging mode.
Console.WriteLine(result); // <-- For debugging use.
}
private void button2_Click(object sender, EventArgs e)
{
Stream myStream;
//SaveFileDialog saveFileDialog1 = new SaveFileDialog();
if (saveFileDialog1.ShowDialog() == DialogResult.OK)
{
if ((myStream = saveFileDialog1.OpenFile()) != null)
{
// Code to write the stream goes here.
myStream.Close();
string SRC = textBox1.Text;
string DEST = saveFileDialog1.FileName;
FileInfo file = new FileInfo(DEST);
file.Directory.Create();
PdfDocument pdfDoc = new PdfDocument(new PdfReader(SRC), new PdfWriter(DEST));
Document doc = new Document(pdfDoc);
int numberOfPages = pdfDoc.GetNumberOfPages();
for (int i = 1; i <= numberOfPages; i++)
{
// Write aligned text to the specified by parameters point
doc.ShowTextAligned(new Paragraph("page " + i + " of " + numberOfPages),559, 806, i, TextAlignment.CENTER, VerticalAlignment.TOP, 0);
}
doc.Close();
}
}
MessageBox.Show("PDF Page Numbering Added!", "Pages Added",MessageBoxButtons.OK);
Application.Exit();
}
}
}
I'm a dumb dumb. The x,y coordinates were off as the value 812 for the height is off the page.

C# Access denied for any folder

When i selected any folder in
FolderDialogBrowser
i got error about access denied for folder. That's for everything folders, documents, my computer, desktop etc, really every folder. I was read about user access for folders (but every folder on disk?), and run as administrator, but it don't help me. If i send me program to friend, they will have too play with folders access to select path? I'm logged on admin account and i have all permissions, but my program no.
/*
* Created by SharpDevelop.
* User: Tomek
* Date: 2019-04-05
* Time: 04:26
*
* To change this template use Tools | Options | Coding | Edit Standard Headers.
*/
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Windows.Forms;
using System.Xml.Linq;
namespace meta_generator
{
/// <summary>
/// Description of MainForm.
/// </summary>
public partial class MainForm : Form
{
public MainForm()
{
//
// The InitializeComponent() call is required for Windows Forms designer support.
//
InitializeComponent();
//
// TODO: Add constructor code after the InitializeComponent() call.
//
}
OpenFileDialog files = new OpenFileDialog();
FolderBrowserDialog metaOutput = new FolderBrowserDialog();
string metapath;
void Button1Click(object sender, EventArgs e)
{
files.Filter = "Wszystkie pliki (*.*)|*.*";
files.Multiselect = true;
if (files.ShowDialog() == DialogResult.OK)
{
foreach (String file in files.FileNames)
{
textBox1.Text = textBox1.Text + ";" + file;
}
}
}
void Button2Click(object sender, EventArgs e)
{
metaOutput.Description = "Wybierz folder gdzie zostanie wygenerowany plik meta.xml";
metaOutput.RootFolder = Environment.SpecialFolder.MyDocuments;
if (metaOutput.ShowDialog() == DialogResult.OK)
{
metapath = metaOutput.SelectedPath;
textBox2.Text = metapath;
}
}
void Button3Click(object sender, EventArgs e)
{
if (textBox1.Text.Length > 0 && textBox2.Text.Length > 0)
{
XDocument meta = new XDocument(new XElement("meta"));
foreach (String file in files.FileNames)
{
XElement childFileTag = new XElement("file");
XAttribute sourcepath = new XAttribute("src", file);
childFileTag.Add(sourcepath);
meta.Root.Add(childFileTag);
}
if (checkBox1.Checked)
meta.Root.Add(new XElement("oop", "true"));
meta.Save(metapath);
}
}
}
}
The issue is your use of
meta.Save(metapath);
metapath is a folder (directory) name (like c:\temp\, not a filename (like c:\temp\bob.xml).
When saving a file, you need to save to a complete path (including filename). An example would be:
meta.Save(Path.Combine(metapath, "bob.xml"));
Alternatively, don't use FolderBrowserDialog - instead use SaveFileDialog to allow the user to choose their own filename.

Simple C# application eating memory

Alright so basicly I have this simple application running in system tray that has one timer. Every tick it performs a check to see if a given directory and file exists, and based on the result it changes its icon.
The problem is every single timer tick the memory for the application raises ~100kb. I currently have it running for about 5 mins and it already uses 40MB of memory, which is unacceptable for such "micro" application.
Here's my code:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.IO;
using System.Reflection;
using System.Windows.Forms;
namespace Tray
{
public partial class Main : Form
{
string drive = "C:\\";
string file = "test.txt";
System.Drawing.Image imgRed = Image.FromFile("res\\icon-red.png");
System.Drawing.Image imgOrange = Image.FromFile("res\\icon-orange.png");
System.Drawing.Image imgGreen = Image.FromFile("res\\icon-green.png");
System.Drawing.Icon icoRed = System.Drawing.Icon.ExtractAssociatedIcon("res\\icon-red.ico");
System.Drawing.Icon icoOrange = System.Drawing.Icon.ExtractAssociatedIcon("res\\icon-orange.ico");
System.Drawing.Icon icoGreen = System.Drawing.Icon.ExtractAssociatedIcon("res\\icon-green.ico");
public Main()
{
InitializeComponent();
}
public static string ShowPrompt(string text, string caption)
{
Form prompt = new Form();
prompt.Width = 500;
prompt.Height = 150;
prompt.Text = caption;
Label textLabel = new Label() { Left = 50, Top = 20, Text = text };
TextBox textBox = new TextBox() { Left = 50, Top = 50, Width = 400 };
Button confirmation = new Button() { Text = "Ok", Left = 350, Width = 100, Top = 70 };
confirmation.Click += (sender, e) => { prompt.Close(); };
prompt.Controls.Add(confirmation);
prompt.Controls.Add(textLabel);
prompt.Controls.Add(textBox);
prompt.ShowDialog();
return textBox.Text;
}
public void updateInfo(){
this.statusDrive.Text = "Drive [" + drive + "]";
this.statusFile.Text = "File [" + drive + file + "]";
}
public void exec(){
int status = 0;
this.trayIcon.Text = "[Drive - ";
if (Directory.Exists(drive)){
this.statusDrive.Text += " - OK";
this.statusDrive.Image = imgGreen;
status++;
this.trayIcon.Text += "OK] ";
} else{
this.statusDrive.Text += " - FAIL";
this.statusDrive.Image = imgRed;
this.trayIcon.Text += "FAIL] ";
}
this.trayIcon.Text += "[File - ";
if (File.Exists(drive + file))
{
this.statusFile.Text += " - OK";
this.statusFile.Image = imgGreen;
status++;
this.trayIcon.Text += "OK] ";
}
else
{
this.statusFile.Text += " - FAIL";
this.statusFile.Image = imgRed;
this.trayIcon.Text += "FAIL] ";
}
switch (status)
{
case 2:
this.Icon = icoGreen;
this.trayIcon.Icon = icoGreen;
this.status.Image = imgGreen;
break;
case 1:
this.Icon = icoOrange;
this.trayIcon.Icon = icoOrange;
this.status.Image = imgOrange;
break;
case 0:
default:
this.Icon = icoRed;
this.trayIcon.Icon = icoRed;
this.status.Image = imgRed;
break;
}
}
private void Form1_Load(object sender, EventArgs e)
{
this.Hide();
}
private void timer1_Tick(object sender, EventArgs e)
{
updateInfo();
exec();
}
private void chDrive_Click(object sender, EventArgs e)
{
this.drive = ShowPrompt("Enter drive path", "Change drive");
}
private void chFile_Click(object sender, EventArgs e)
{
this.file = ShowPrompt("Enter new file path:", "Change file");
}
private void exitToolStripMenuItem_Click(object sender, EventArgs e)
{
Application.Exit();
}
}
}
I already tried to optimize the app by preloading the icons and images into variables and assigning those to the appropriate properties, however this didn't solve my problem.
Also, note that I managed to hide my main window by doing this (in Program.cs):
using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows.Forms;
namespace Tray
{
static class Program
{
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Main mForm = new Main();
Application.Run();
}
}
}
UPDATE
I just noticed that the memory usage climbs up to 50MB and drops to 20MB afterwards (and goes up again). Is this something I can possibly address or is it a windows "issue"?
I'm going to take a stab at it being the string concatenations happening once a second. Consider using a StringBuilder. 40MB is nothing though really.
RE: Your update. The Garbage Collector is reclaiming the memory as it sees fit.
You never appear to be disposing your form correctly in ShowPrompt, so I'd imagine this is your problem.
Because a form displayed as a dialog box is not closed, you must call the Dispose method of the form when the form is no longer needed by your application.
ShowDialog
Some points that could cut down on memory usage:
Try to prebuild all those strings you're building in exec(). It looks like they're all runtime constants, but you build them every tick instead of building them once when the application starts. If this isn't possible, use StringBuilder instead of +=.
Only change properties on controls (icon, trayText, etc) if there has been a change. I.E. if tray text is already "[Drive C:\ - OK]", don't set its value again to "[Drive C:\ - OK]" next tick.
Garbage Collector does all the work of memory management for you. Temporary rise in memory doesn't always mean that there is a memory leak. It may come down when the GC collects memory. In case you suspect that there are memory leaks you need to do memory profiling which is no easy job. You need to read into this article for steps that you can take to find out the problem in your code. Alternatively, there are multiple tools avaiable in the market to do this job for you. You can use Ants Profiler of Red Gate, memprofiler amongst others.
One thing you might consider is rather than using a timer why not use the FileSystemWatcher and attach to events:
var watcher = new FileSystemWatcher("somepath");
watcher.Deleted += (sender, eventArgs) => { };
watcher.Changed += (sender, eventArgs) => { };
watcher.Error += (sender, eventArgs) => { };
watcher.Renamed += (sender, eventArgs) => { };
I also agree that you should be disposing of the forms once you're done with them.

Categories

Resources