I am trying to print from a web browser control in a winform application.The matter is it sets letter as default paper size but I need A4. Also it automatically sets some margins wrong, I can set them to correct settings manually but I want to do it programmatically.
How is it possible?
Here is my code to print.
private void metroButton1_Click(object sender, EventArgs e)
{
loadprintData();
// Create a WebBrowser instance.
WebBrowser webBrowserForPrinting = new WebBrowser();
// Add an event handler that prints the document after it loads.
wa.DocumentCompleted +=
new WebBrowserDocumentCompletedEventHandler(ShowPrintDocument);
wa.ShowPrintPreviewDialog();
reloadpage();
}
private void ShowPrintDocument(object sender,WebBrowserDocumentCompletedEventArgs e)
{
// Print the document now that it is fully loaded.
((WebBrowser)sender).ShowPrintPreviewDialog();
// Dispose the WebBrowser now that the task is complete.
// ((WebBrowser)sender).Dispose();
reloadpage();
}
private void PrintDocument(object sender, WebBrowserDocumentCompletedEventArgs e)
{
// Print the document now that it is fully loaded.
((WebBrowser)sender).Print();
// Dispose the WebBrowser now that the task is complete.
// ((WebBrowser)sender).Dispose();
}
To change the Margin size you have to edit the (HKCU) registry before printing:
string pageSetupKey = "Software\\Microsoft\\Internet Explorer\\PageSetup";
bool isWritable = true;
RegistryKey rKey = Registry.CurrentUser.OpenSubKey(pageSetupKey, isWritable);
if (stringToPrint.Contains("something"))
{
rKey.SetValue("margin_bottom", 0.10);
rKey.SetValue("margin_top", 0.25);
}
else
{
//Reset old value
rKey.SetValue("margin_bottom", 0.75);
rKey.SetValue("margin_top", 0.75);
}
Dont forget to set it back to the default.
Ref Microsoft KB Article
To change the Paper size you have to edit the (HKCU) registry in another place before printing:
string pageSetupKey2 = "Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings";
isWritable = true;
rKey = Registry.CurrentUser.OpenSubKey(pageSetupKey2, isWritable);
// Use 1 for Portrait and 2 for Landccape
rKey.SetValue("PageOrientation", 2, RegistryValueKind.DWord);
// Specifies paper size. Valid settings are 1=letter, 5=Legal, 9=A4, 13=B5.Default setting is 1.
rKey.SetValue("PaperSize", 9, RegistryValueKind.DWord);
// Specifies print quality
rKey.SetValue("PrintQuality ", 1, RegistryValueKind.DWord);
Ref MSDN
Well i have tried so many things but at the end i found that it is not possible to program the printer setting from the code easily. but i could do the margin by the answer of #jeremy.
And i found out that For printing from WebBrowser control it uses internet explorer all we know but at the beginning it was using explorer 7 and i had to change it to explorer 11 as default.
Then i saw it explorer does not have his own print settings. it uses the default printers settings.
So you have to change the Default printers previews.You will see the preview will show that way.
Related
I have a one-window WPF application (Win8.1 / .net4.7), the Window.Closing-Event is unhandled, the Window.Closed-Event is handled as follows:
private void Window_Closed(object sender, EventArgs e)
{
Properties.Settings.Default.WinMainLocationX = this.Left; // ok
Properties.Settings.Default.WinMainLocationY = this.Top; // ok
Properties.Settings.Default.WinMain_size = new Size(this.Width, this.Height); // crucial setting
Properties.Settings.Default.WinMain_state = this.WindowState; // ok
Properties.Settings.Default.Save();
}
I'm closing the app (at this point always in idle state) once a day by a batch file containing C:\WINDOWS\system32\shutdown.exe /s /t 20 and nothing afterwards. By this the computer shuts down properly. The parameters of shutdown.exe can be seen by command line input of shutdown /?.
Problem: Every 7 or 8 days the window size gets corrupted in a way that the application (after having started in the morning) looks like this:
How can I protect my application settings from interference by shutdown.exe?
I think the problem is storing the settings while the application window is minimized. Width and Height of the window will be 0 in this case.
You can use the RestoreBounds property of your window to get its restored size independent of its current state:
Properties.Settings.Default.WinMainLocationX = this.RestoreBounds.Left;
Properties.Settings.Default.WinMainLocationY = this.RestoreBounds.Top;
Properties.Settings.Default.WinMain_size = new Size(this.RestoreBounds.Width, this.RestoreBounds.Height);
Properties.Settings.Default.WinMain_state = this.WindowState;
Some answers to this question show another approach using the WinAPI functions GetWindowPlacement / SetWindowPlacement:
.NET WPF Remember window size between sessions
Adding Environment.Exit(0)has solved the issue. I can imagine the cause of the problem was that the Window.Closed-Handler has been reached twice.
private void Window_Closed(object sender, EventArgs e)
{
Properties.Settings.Default.WinMainLocationX = this.Left; // ok
Properties.Settings.Default.WinMainLocationY = this.Top; // ok
Properties.Settings.Default.WinMain_size = new Size(this.Width, this.Height); // crucial setting
Properties.Settings.Default.WinMain_state = this.WindowState; // ok
Properties.Settings.Default.Save();
Environment.Exit(0);
}
I finally figured out how to print transformed XML without prompting the user or showing an IE window, but now I need to specify a number of copies and possibly other printer settings.
Is there a way to programmatically change printer settings on a WebBrowser control?
The code in question:
private static void PrintReport(string reportFilename)
{
WebBrowser browser = new WebBrowser();
browser.DocumentCompleted += browser_DocumentCompleted;
browser.Navigate(reportFilename);
}
private static void browser_DocumentCompleted
(object sender, WebBrowserDocumentCompletedEventArgs e)
{
WebBrowser browser = sender as WebBrowser;
if (null == browser)
{
return;
}
browser.Print();
browser.Dispose();
}
The only method I've had success with is modifying the registry on the fly (and changing them back to not affect anything else).
You can find the settings you need at "Software\Microsoft\Internet Explorer\PageSetup" under CurrentUser.
To change the printer, you can use this:
using System.Management
public static bool SetDefaultPrinter(string defaultPrinter)
{
using (ManagementObjectSearcher objectSearcher = new ManagementObjectSearcher("SELECT * FROM Win32_Printer"))
{
using (ManagementObjectCollection objectCollection = objectSearcher.Get())
{
foreach (ManagementObject mo in objectCollection)
{
if (string.Compare(mo["Name"].ToString(), defaultPrinter, true) == 0)
{
mo.InvokeMethod("SetDefaultPrinter", null, null);
return true;
}
}
}
}
return false;
}
As for the number of copies, you can always put the WebBrowser.Print in a while loop.
string strKey = "Software\\Microsoft\\Internet Explorer\\PageSetup";
bool bolWritable = true;
RegistryKey oKey = Registry.CurrentUser.OpenSubKey(strKey, bolWritable);
Console.Write(strKey);
if (stringToPrint.Contains("Nalog%20za%20sluzbeno%20putovanje_files"))
{
oKey.SetValue("margin_bottom", 15);
oKey.SetValue("margin_top", 0.19);
}
else
{
//Return onld walue
oKey.SetValue("margin_bottom", 0.75);
oKey.SetValue("margin_top", 0.75);
}
you need to change registry settings via code to change settings for internet explorer or the web browser control. check out the link below, it describes how to do so, also if there's more options you need to alter using the registry, then use regedit.exe to find what other keys internet explorer has.
http://support.microsoft.com/kb/236777
ps: you should note that any changes you make via your code to internet explorer's registry settings will persist on your system/user account.
This worked well for me, however I am on .NET 3.5
this.webBrowser1.ShowPrintDialog();
I'm currently developing a metro app in which the user can change current language at runtime and all the custom controls that are loaded must update their text regarding to the new language. Problem is that when I change the language using the following code, the app language changes but it will only update text when I restart my app because the pages and controls that are already rendered are cached.
LocalizationManager.UICulture = new System.Globalization.CultureInfo((string)((ComboBoxItem)e.AddedItems[0]).Tag);
Windows.Globalization.ApplicationLanguages.PrimaryLanguageOverride = ((ComboBoxItem)e.AddedItems[0]).Tag as String;
What should I do to force updating text of all custom controls at runtime without restarting my app?
Use this:
var NewLanguage = (string)((ComboBoxItem)e.AddedItems[0]).Tag;
Windows.Globalization.ApplicationLanguages.PrimaryLanguageOverride = NewLanguage;
Windows.ApplicationModel.Resources.Core.ResourceContext.GetForViewIndependentUse().Reset();
//Windows.ApplicationModel.Resources.Core.ResourceContext.GetForCurrentView().Reset();
Windows.ApplicationModel.Resources.Core.ResourceManager.Current.DefaultContext.Reset();
and then reload your Page, using Navigate method:
if (Frame != null)
Frame.Navigate(typeof(MyPage));
In order to respond right away, you would need to reset the context of the resource manager.
For Windows 8.1:
var resourceContext = Windows.ApplicationModel.Resources.Core.ResourceContext.GetForCurrentView();
resourceContext.Reset();
You will still need to force your page to redraw itself and thus re-request the resources to get the changes to take place. For Windows 8, you can see https://timheuer.com/blog/archive/2013/03/26/howto-refresh-languages-winrt-xaml-windows-store.aspx
You can change the app's language at runtime with the help of this source code. I took help from this and manipulated my app's language settings page as follows:
In languageSettings.xaml.cs:
public partial class LanguageSettings : PhoneApplicationPage
{
public LanguageSettings()
{
InitializeComponent();
}
protected override void OnNavigatedTo(NavigationEventArgs e)
{
base.OnNavigatedTo(e);
if (ChangeLanguageCombo.Items.Count == 0)
{ ChangeLanguageCombo.Items.Add(LocalizationManager.SupportedLanguages.En);
ChangeLanguageCombo.Items.Add(LocalizationManager.SupportedLanguages.Bn);
}
SelectChoice();
}
private void ButtonSaveLang_OnClick(object sender, RoutedEventArgs e)
{
//Store the Messagebox result in result variable
MessageBoxResult result = MessageBox.Show("App language will be changed. Do you want to continue?", "Apply Changes", MessageBoxButton.OKCancel);
//check if user clicked on ok
if (result == MessageBoxResult.OK)
{
var languageComboBox = ChangeLanguageCombo.SelectedItem;
LocalizationManager.ChangeAppLanguage(languageComboBox.ToString());
//Application.Current.Terminate(); I am commenting out because I don't neede to restart my app anymore.
}
else
{
SelectChoice();
}
}
private void SelectChoice()
{
//Select the saved language
string lang = LocalizationManager.GetCurrentAppLang();
if(lang == "bn-BD")
ChangeLanguageCombo.SelectedItem = ChangeLanguageCombo.Items[1];
else
{
ChangeLanguageCombo.SelectedItem = ChangeLanguageCombo.Items[0];
}
}
}
***Note: Before understanding what I did on LanguageSettings page's code behind, you must implement the codes from the link as stated earlier. And also it may be noted that I am working on windows phone 8
I have a NotifyIcon in my program which displays a baloon tip in the taskbar. I wrote code as
notifyIcon1.Icon = new Icon(SystemIcons.Application, 40, 40);
notifyIcon1.Visible = true;
notifyIcon1.Text = "Test Notify Icon Demo";
notifyIcon1.BalloonTipText =count+ " Alerts";
notifyIcon1.BalloonTipIcon = ToolTipIcon.Info;
notifyIcon1.BalloonTipTitle = "Alert!";
notifyIcon1.ShowBalloonTip(999999999);
The baloon tip is invisible after the set time (999999999). But I want to show the baloon tip until it is clicked as I have baloontipclicked event.
How to make baloontip visible forever?
from MSDN:
Minimum and maximum timeout values are enforced by the operating
system and are typically 10 and 30 seconds, respectively, however this
can vary depending on the operating system. Timeout values that are
too large or too small are adjusted to the appropriate minimum or
maximum value. In addition, if the user does not appear to be using
the computer (no keyboard or mouse events are occurring) then the
system does not count this time towards the timeout.
it seems not be possible to override the maximum timeout (eventually adjusted by Windows and limited to 30 seconds even if you specify a longer one) so the Notification will fade away, will not wait for you to click on it after 2 minutes.
if you want to really have a different behavior you should probably use something else, other objects or simulate something similar with forms where you have the full control on the behavior and you can show, hide and close as you wish from your code.
You can show it again if it hasn't been clicked.
You have the close event (BalloonTipClosed), if user hasn't ckicked it just show it again.
private void ShowBalloonTip(int minutes) {
notifyIcon.BalloonTipIcon = ToolTipIcon.Error;
notifyIcon.BalloonTipText = "Text";
notifyIcon.BalloonTipTitle = "Title";
notifyIcon.ShowBalloonTip(minutes* 60 * 1000);
m_showUntil = DateTime.Now.AddMinutes(minutes);
}
private void notifyIcon_BalloonTipClosed(object sender, EventArgs e) {
if (m_showUntil > DateTime.Now)
notifyIcon.ShowBalloonTip(60 * 1000);
}
private void notifyIcon_BalloonTipClicked(object sender, EventArgs e) {
m_showUntil = DateTime.MinValue;
(..)
}
I am using a windows service and i want to print a .html page when the service will start. I am using this code and it's printing well. But a print dialog box come, how do i print without the print dialog box?
public void printdoc(string document)
{
Process printjob = new Process();
printjob.StartInfo.FileName = document;
printjob.StartInfo.UseShellExecute = true;
printjob.StartInfo.Verb = "print";
printjob.StartInfo.CreateNoWindow = true;
printjob.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;
printjob.Start();
}
Have there any other way to print this without showing the print dialog box.
Update: in response to this:
But i have already used this class but when i am calling the
axW.ExecWB(SHDocVw.OLECMDID.OLECMDID_PRINT,SHDocVw.OLECMDEXECOPT.OLECMDEXECOPT_PROMPTUSER , ref em, ref em);
My program getting block here when i am using from window service but it is working fine from windows application.
First off, here's the code:
using System.Reflection;
using System.Threading;
using SHDocVw;
namespace HTMLPrinting
{
public class HTMLPrinter
{
private bool documentLoaded;
private bool documentPrinted;
private void ie_DocumentComplete(object pDisp, ref object URL)
{
documentLoaded = true;
}
private void ie_PrintTemplateTeardown(object pDisp)
{
documentPrinted = true;
}
public void Print(string htmlFilename)
{
documentLoaded = false;
documentPrinted = false;
InternetExplorer ie = new InternetExplorerClass();
ie.DocumentComplete += new DWebBrowserEvents2_DocumentCompleteEventHandler(ie_DocumentComplete);
ie.PrintTemplateTeardown += new DWebBrowserEvents2_PrintTemplateTeardownEventHandler(ie_PrintTemplateTeardown);
object missing = Missing.Value;
ie.Navigate(htmlFilename, ref missing, ref missing, ref missing, ref missing);
while (!documentLoaded && ie.QueryStatusWB(OLECMDID.OLECMDID_PRINT) != OLECMDF.OLECMDF_ENABLED)
Thread.Sleep(100);
ie.ExecWB(OLECMDID.OLECMDID_PRINT, OLECMDEXECOPT.OLECMDEXECOPT_DONTPROMPTUSER, ref missing, ref missing);
while (!documentPrinted)
Thread.Sleep(100);
ie.DocumentComplete -= ie_DocumentComplete;
ie.PrintTemplateTeardown -= ie_PrintTemplateTeardown;
ie.Quit();
}
}
}
You can access the SHDocVw namespace by adding a reference to 'Microsoft Internet Controls', found on the COM tab of the Add Reference dialog.
More information on the InternetExplorer object can be found on MSDN.
The Navigate() method will load the HTML file. The other parameters allow you to specify optional parameters, such as flags and headers.
We can't print until the document is loaded. Here, I enter a loop waiting until the DocumentComplete event is called, upon which a flag is set notifying us that navigation has completed. Note that DocumentComplete is called whenever navigation is finished - upon success or failure.
Once the documentLoaded flag is set, the printing status is queried via QueryStatusWB() until printing is enabled.
Printing is started with the ExecWB() call. The OLECMDID_PRINT command is specified, along with the option OLECMDEXECOPT_DONTPROMPTUSER to automatically print without user interaction. An important note is that this will print to the default printer. To specify a printer, you will have to set the default printer (in code, you could call SetDefaultPrinter()). The two final parameters allow optional input and output parameters.
We don't want to quit until printing is complete, so once again a loop is entered. After the PrintTemplateTeardown event is fired, the documentPrinted flag is set. The objects can then be cleaned up.
From this site http://www.ussbd.com/printhtm.html
using HtmlPrinter;
hpObj=new HtmlPrinter.HtmlPrinter();
hpObj.PrintUrlFromMemory(txtUrl.Text);
Now you add the code in your project to print html page from its source text:
HtmlPrinter.HtmlPrinter hpObj=new HtmlPrinter.HtmlPrinter();
hpObj.PrintHtml(txtString.Text, true);
If you want to print without the print dialog then use the following line:
hpObj.PrintHtml(txtString.Text, false);
Here's another way to print without a print dialog. You create a PrintDialog object, initialize it and then call the Print() method.
The function below is used to print a small 2"x0.75" barcode label. You'll need to figure out a way to get an Document object from the html file.
public void PrintToPrinter(string printerName)
{
PrintDialog pd = new PrintDialog();
pd.Document = userControl11.PrintDoc; // <--- Update this line with your doc
pd.PrinterSettings.PrinterName = printerName;
try
{
pd.Document.DocumentName = "My Label";
pd.Document.DefaultPageSettings.PaperSize = new System.Drawing.Printing.PaperSize("2-.75", 200, 75);
pd.Document.DefaultPageSettings.Margins = new System.Drawing.Printing.Margins(0, 0, 0, 0);
//pd.PrinterSettings.Copies = (short)mNumCopies;
pd.Document.PrinterSettings.Copies = (short) mNumCopies;
pd.Document.Print();
}
catch
{
MessageBox.Show("INVALID PRINTER SPECIFIED");
}
}
You can use the PrintDocument class in the System.Drawing.Printing namespace to give you more control over the printing, see here for more info.
For example you can do the following:
using (PrintDocument doc = new PrintDocument())
{
doc.PrintPage += this.Doc_PrintPage;
doc.DefaultPageSettings.Landscape = true;
doc.DocumentName = fileNameOfYourDocument;
doc.Print();
}
Then a function is raised for each page to be printed and you are given a Graphics area to draw to
private void Doc_PrintPage(object sender, PrintPageEventArgs ev)
{
....
ev.Graphics.DrawImage(image, x, y, newWidth, newHeight);
}
This does require you handle the actual drawing on the text/image to the page, see here for more info.
OLECMDEXECOPT_PROMPTUSER seems to force a prompt to the user to select printer and all associated stuff, which I am pretty sure is not allowed from a service. Can someone verify this?