<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Dejan on Technology &#187; WinForms</title>
	<atom:link href="http://www.vesic.org/english/blog/category/winforms/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.vesic.org/english/blog</link>
	<description>dotNet, ASP.Net, Programming, Software ...</description>
	<lastBuildDate>Mon, 01 Mar 2010 09:07:14 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3</generator>
		<item>
		<title>Upgrade of Application/User Settings between application versions</title>
		<link>http://www.vesic.org/english/blog/winforms/upgrade-of-applicationuser-settings-between-application-versions/</link>
		<comments>http://www.vesic.org/english/blog/winforms/upgrade-of-applicationuser-settings-between-application-versions/#comments</comments>
		<pubDate>Tue, 31 Jul 2007 06:09:20 +0000</pubDate>
		<dc:creator>Dejan Vesić</dc:creator>
				<category><![CDATA[.Net]]></category>
		<category><![CDATA[C#]]></category>
		<category><![CDATA[WinForms]]></category>

		<guid isPermaLink="false">http://www.vesic.org/english/blog/winforms/upgrade-of-applicationuser-settings-between-application-versions/</guid>
		<description><![CDATA[One of the polished areas of .Net Framework 2.0 is manipulation with Application/User settings in WinForms applications. You can store almost anything in appropriate <strong>app.config</strong> or <strong>user.config</strong> file, and to manipulate with those settings with ease...]]></description>
			<content:encoded><![CDATA[<p>One of the polished areas of .Net Framework 2.0 is manipulation with <a href="http://msdn2.microsoft.com/en-us/library/0zszyc6e.aspx">Application/User settings in WinForms</a> applications. You can store almost anything in appropriate <strong>app.config</strong> or <strong>user.config</strong> file, and to manipulate with those settings with ease &#8211; wrapper class created around Settings allows you to use settings as just another field in your code.</p>
<p>But, what about of upgrade existing settings once when you create new version of the application? </p>
<p>That is supported via <strong>Upgrade()</strong> method:</p>
<pre><code>
	 Settings.Default.Upgrade();
	 Settings.Default.Save();
</code></pre>
<p>You can add one user bool setting (for example <em>UpgradeSettings</em>) with default value True, which will be a flag if upgrade is carried out; code can be:</p>
<pre><code>
	if (Settings.Default.UpgradeSettings)
	{
		 Settings.Default.Upgrade();
		 Settings.Default.UpgradeSettings = false;
		 Settings.Default.Save();
	}
</code></pre>
<p>Suppose that your application is simple little application, not a Click-Once or even distributed with installer &#8211; just archive which users can download, unpack and start using.</p>
<p>If you new version picks user settings folder from previous one, all is fine &#8211; <strong>Upgrade()</strong> method will find previous version and upgrade them:</p>
<p><img src="http://www.vesic.org/blog/upload/vas-telefon-settings-ok.jpg" alt="Application versions - as expected" width="363" height="69"  /></p>
<p>Suppose that this is true:</p>
<ul>
<li>both versions are either signed or not (if you do signing of assembly between versions, Upgrade will fail)</li>
<li>both versions are either Click-Once applications or not (for the same reasons)</li>
</ul>
<p>In theory, all is fine and Upgrade should do the job. But, what if all above is fulfilled and that you still have different user settings folder:</p>
<p><img src="http://www.vesic.org/blog/upload/vas-telefon-settings-bad.jpg" alt="Application versions - mismatch" width="365" height="87"  /></p>
<p>What can be reason that same application creates completely different user settings folder? This situation happened to me. After couple of hours, I could not determine reason, so I pulled out heavy tools &#8211; <a href="http://www.aisto.com/roeder/dotnet/">Reflector</a>.</p>
<p>If you start tracking <strong>.Upgrade()</strong>, it goes to: <a href="http://msdn2.microsoft.com/en-us/library/system.configuration.applicationsettingsbase.upgrade.aspx">ApplicationSettingsBase.Upgrade</a> which simply calls <a href="http://msdn2.microsoft.com/en-us/library/system.configuration.iapplicationsettingsprovider.upgrade.aspx">IApplicationSettingsProvider.Upgrade</a> for each provider present. For simple WinForms application, appropriate provider is  <a href="http://msdn2.microsoft.com/en-us/library/system.configuration.localfilesettingsprovider.aspx">LocalFileSettingsProvider</a>. After some more thorough analysis, internal method for determining folder of settings store is:</p>
<p><strong>System.Configuration.ClientConfigPaths</strong></p>
<p>One of elements in determining local store for user settings was hashed value derived from <a href="http://msdn2.microsoft.com/en-us/library/system.security.policy.evidence.aspx">Evidences</a> for given assembly.</p>
<p>It turns out that one of <a href="http://msdn2.microsoft.com/en-us/library/system.security.policy.evidence.aspx">Evidence</a> elements for non-signed assemblies is <strong>path from where assembly/application is launched!</strong>.</p>
<p>To summarize: <strong>in order for Upgrade() of settings succeed, your new version of application should be deployed in the exact same folder where previous version is found</strong>; otherwise, Upgrade() will fail (or at least, it won&#8217;t do what you expected <img src='http://www.vesic.org/english/blog/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' />  )</p>
]]></content:encoded>
			<wfw:commentRss>http://www.vesic.org/english/blog/winforms/upgrade-of-applicationuser-settings-between-application-versions/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>How to render Html content into JPG/JPEG image in best quality (WinForms)</title>
		<link>http://www.vesic.org/english/blog/winforms/render-html-to-quality-jpeg/</link>
		<comments>http://www.vesic.org/english/blog/winforms/render-html-to-quality-jpeg/#comments</comments>
		<pubDate>Wed, 28 Feb 2007 15:34:44 +0000</pubDate>
		<dc:creator>Dejan Vesić</dc:creator>
				<category><![CDATA[.Net]]></category>
		<category><![CDATA[Drawing]]></category>
		<category><![CDATA[WinForms]]></category>

		<guid isPermaLink="false">http://www.vesic.org/english/blog/winforms/render-html-to-quality-jpeg/</guid>
		<description><![CDATA[On recent project, I had a tasks to:
<ol>
	<li>Save result of Html page to JPG image</li>
	<li>To do that in best possible quality</li>
</ol>
	
Both tasks sounds trivial, but I did not find quite satisfying solutions, so, I came up with one bellow...]]></description>
			<content:encoded><![CDATA[<h2>How to save Html to JPG/JPEG Image and how to save it in best quality?</h2>
<p>On recent project, I had a tasks to:</p>
<ol>
<li>Save result of Html page to JPG image</li>
<li>To do that in best possible quality</li>
</ol>
<p>Both tasks sounds trivial, but I did not find quite satisfying solutions, so, I came up with one bellow.</p>
<p>First, you need <a href="http://msdn2.microsoft.com/en-us/library/system.windows.forms.webbrowser.aspx">WebBrowser</a> control &#8211; it is basicaly wrapper around ActiveX Internet Explorer interface.</p>
<p>Once when Html content is ready (local or remote), ask control to call your procedure upon completion:</p>
<p><code>webBrowser1.DocumentCompleted += new WebBrowserDocumentCompletedEventHandler(webBrowser1_DocumentCompleted);</code></p>
<p>and start render your content:</p>
<p><code>webBrowser1.Navigate(  UriToRender )</code></p>
<p>In DocumentCompletedEventHandler, call your routine for rendering content to image:</p>
<pre>
void webBrowser1_DocumentCompleted(object sender,
WebBrowserDocumentCompletedEventArgs e)
{
  if( GetImageFromHtml(currentFile, webBrowser1) )
  {
     toolStripStatusLabel1.Text = "Image saved.";
  }
  else
  {
     toolStripStatusLabel1.Text = "Sorry, there was problem with saving.";
  }
}</pre>
<p>And here is code for rendering Html to image:</p>
<pre>
/// &lt;summary&gt;
/// Method for saving Html content into image
/// &lt;/summary&gt;
/// &lt;param name="imageName"&gt;File name of image&lt;/param&gt;
/// &lt;param name="webBrowser"&gt;Target WebBrowser control to query for content&lt;/param&gt;
/// &lt;returns&gt;True if save was succesfull&lt;/returns&gt;
/// &lt;seealso cref="System.Windows.Forms.WebBrowser" /&gt;

public bool GetImageFromHtml(string imageName, WebBrowser webBrowser)
{
  if (webBrowser.Document == null)
  {
     return false;
  }

  Cursor current = Cursor;
  Cursor = Cursors.WaitCursor;

  // Give time to WebBrowser control to finish rendering of document
  Thread.Sleep(200);

  try
  {

     // save old width / height
     Size originalSize = new Size(webBrowser1.Width, webBrowser1.Height);

     // Change to full scroll size
     int scrollHeight = webBrowser.Document.Body.ScrollRectangle.Height;
     int scrollWidth = webBrowser.Document.Body.ScrollRectangle.Width;

     Bitmap image = new Bitmap(scrollWidth, scrollHeight);
     webBrowser.Size = new Size(scrollWidth, scrollHeight);

     // Draw to image
     webBrowser.DrawToBitmap(image, webBrowser.ClientRectangle);
     webBrowser.Size = originalSize;

     // Old one with bad quality:
     // image.Save(imageName, ImageFormat.Jpeg);

     // Save in full quality
     SaveJPG(image, imageName, 100);

     return true;
  }

  catch { return false; }

  finally {  Cursor = current; }
}
</pre>
<p>Usual <a href="http://msdn2.microsoft.com/en-us/library/9t4syfhh.aspx">Image.Save</a> method saves image in number of formats; however, quality is some default (bad) quality; and I needed more control over it. So, here are methods which allow that kind of control:</p>
<pre>
/// &lt;summary&gt;
/// Gets codec info by given mimeType
/// &lt;/summary&gt;
/// &lt;param name="mimeType"&gt;mimeType to lookup for&lt;/param&gt;
/// &lt;returns&gt;ImageCodecInfo if all ok or null&lt;/returns&gt;

public static ImageCodecInfo GetCodecInfo(String mimeType)
{
  ImageCodecInfo[] encoders;
  encoders = ImageCodecInfo.GetImageEncoders();
  for (int iterator = 0; iterator &lt; encoders.Length; ++iterator)
  {
     if (encoders[iterator].MimeType == mimeType)
        return encoders[iterator];
  }
  return null;
}

/// &lt;summary&gt;
/// Save an Image to JPEG with given compression quality
/// &lt;/summary&gt;
/// &lt;param name="image"&gt;Image to save&lt;/param&gt;
/// &lt;param name="imageName"&gt;File name to store image&lt;/param&gt;
/// &lt;param name="quality"&gt;Quality parameter: 0 - lowest quality, smallest size,
/// 100 - max quality and size&lt;/param&gt;
/// &lt;returns&gt;True if save was succesfull&lt;/returns&gt;

public static bool SaveJPG(Image image, string imageName, long qual)
{
  EncoderParameters eps = new EncoderParameters(1);
  eps.Param[0] = new EncoderParameter(System.Drawing.Imaging.Encoder.Quality, qual);
  ImageCodecInfo ici = GetCodecInfo("image/jpeg");

  if(ici == null) { return false; }

  image.Save(imageName, ici, eps);
  return true;
}
</pre>
<p>Now you can select jpeg image quality and render html the way you like.</p>
<p><a href="http://digg.com/programming/How_to_render_Html_content_into_JPG_JPEG_image_in_best_quality_WinForms"><img src="http://digg.com/img/badges/91x17-digg-button.png" width="91" height="17" alt="Digg!" /></a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.vesic.org/english/blog/winforms/render-html-to-quality-jpeg/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>How to make Windows Form app truly Full Screen (and to hide Taskbar) in C#?</title>
		<link>http://www.vesic.org/english/blog/winforms/full-screen-maximize/</link>
		<comments>http://www.vesic.org/english/blog/winforms/full-screen-maximize/#comments</comments>
		<pubDate>Sun, 03 Dec 2006 13:29:33 +0000</pubDate>
		<dc:creator>Dejan Vesić</dc:creator>
				<category><![CDATA[.Net]]></category>
		<category><![CDATA[C#]]></category>
		<category><![CDATA[WinForms]]></category>

		<guid isPermaLink="false">http://www.vesic.org/english/blog/winforms/full-screen-maximize/</guid>
		<description><![CDATA[One of sound-like-simple questions is "how to make your application truly Full Screen" i.e. not showing Taskbar or anything like that.

Initial approach is obvious ...]]></description>
			<content:encoded><![CDATA[<p>One of sound-like-simple questions is &#8220;how to make your application truly Full Screen&#8221; i.e. not showing Taskbar or anything like that.</p>
<p>Initial approach is obvious:</p>
<pre>
<code>
    targetForm.WindowState = FormWindowState.Maximized;
    targetForm.FormBorderStyle = FormBorderStyle.None;
    targetForm.TopMost = true;
</code>
</pre>
<p>Does it work? Well, sort of. If your Taskbar have default setting unchecked for &#8220;Keep the taskbar on top of other windows&#8221;, this will present your application in all it&#8217;s glory all over screen estate.</p>
<p>However, if the Taskbar is set to appear on top of all others, this won&#8217;t help &#8211; your application won&#8217;t cover it.</p>
<p>Let&#8217;s go further &#8211; next step is to use P/Invoke and to engage Win32 API services. There is easy way to hide particular window. So, find the Taskbar and hide it:</p>
<pre>
<code>
    private const int SW_HIDE = 0;
    private const int SW_SHOW = 1;

    [DllImport("user32.dll")]
    private static extern int FindWindow(string className, string windowText);
    [DllImport("user32.dll")]
    private static extern int ShowWindow(int hwnd, int command);

    int hWnd = FindWindow("Shell_TrayWnd", "");
    ShowWindow(hWnd, SW_HIDE);

    targetForm.WindowState = FormWindowState.Maximized;
    targetForm.FormBorderStyle = FormBorderStyle.None;
    targetForm.TopMost = true;
</code>
</pre>
<p>(you need to add <code>using System.Runtime.InteropServices;</code>)</p>
<p>Is this better? In theory yes &#8211; Taskbar is hidden, but your application still does not occupy whole screen &#8211; place where Taskbar was is not used.</p>
<p>Real and proven solution is to make request to WinAPI that your form take whole screen estate &#8211; Taskbar will hide itself in that case. Full information about that can be found in KB Article Q179363: <a href="http://support.microsoft.com/kb/q179363/">How To Cover the Task Bar with a Window</a> and here is the code:</p>
<pre><code>
/// &lt;summary&gt;
/// Selected Win AI Function Calls
/// &lt;/summary&gt;

public class WinApi
{
    [DllImport("user32.dll", EntryPoint = "GetSystemMetrics")]
    public static extern int GetSystemMetrics(int which);

    [DllImport("user32.dll")]
    public static extern void
        SetWindowPos(IntPtr hwnd, IntPtr hwndInsertAfter,
                     int X, int Y, int width, int height, uint flags);        

    private const int SM_CXSCREEN = 0;
    private const int SM_CYSCREEN = 1;
    private static IntPtr HWND_TOP = IntPtr.Zero;
    private const int SWP_SHOWWINDOW = 64; // 0x0040

    public static int ScreenX
    {
        get { return GetSystemMetrics(SM_CXSCREEN);}
    }

    public static int ScreenY
    {
        get { return GetSystemMetrics(SM_CYSCREEN);}
    }

    public static void SetWinFullScreen(IntPtr hwnd)
    {
        SetWindowPos(hwnd, HWND_TOP, 0, 0, ScreenX, ScreenY, SWP_SHOWWINDOW);
    }
}

/// &lt;summary&gt;
/// Class used to preserve / restore state of the form
/// &lt;/summary&gt;
public class FormState
{
    private FormWindowState winState;
    private FormBorderStyle brdStyle;
    private bool topMost;
    private Rectangle bounds;

    private bool IsMaximized = false;

    public void Maximize(Form targetForm)
    {
        if (!IsMaximized)
        {
            IsMaximized = true;
            Save(targetForm);
            targetForm.WindowState = FormWindowState.Maximized;
            targetForm.FormBorderStyle = FormBorderStyle.None;
            targetForm.TopMost = true;
            WinApi.SetWinFullScreen(targetForm.Handle);
        }
    }

    public void Save(Form targetForm)
    {
        winState = targetForm.WindowState;
        brdStyle = targetForm.FormBorderStyle;
        topMost = targetForm.TopMost;
        bounds = targetForm.Bounds;
    }

    public void Restore(Form targetForm)
    {
        targetForm.WindowState = winState;
        targetForm.FormBorderStyle = brdStyle;
        targetForm.TopMost = topMost;
        targetForm.Bounds = bounds;
        IsMaximized = false;
    }
}
</code></pre>
<p>Code for example application is here: <a href="http://www.vesic.org/blog/upload/MaxWinForm.zip">MaxWinForm.zip</a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.vesic.org/english/blog/winforms/full-screen-maximize/feed/</wfw:commentRss>
		<slash:comments>44</slash:comments>
		</item>
		<item>
		<title>Validation of input elements and Form Closing</title>
		<link>http://www.vesic.org/english/blog/winforms/winforms-validation/</link>
		<comments>http://www.vesic.org/english/blog/winforms/winforms-validation/#comments</comments>
		<pubDate>Wed, 15 Nov 2006 15:12:29 +0000</pubDate>
		<dc:creator>Dejan Vesić</dc:creator>
				<category><![CDATA[.Net]]></category>
		<category><![CDATA[C#]]></category>
		<category><![CDATA[WinForms]]></category>

		<guid isPermaLink="false">http://www.vesic.org/english/blog/winforms/winforms-validation/</guid>
		<description><![CDATA[One of very often questions ask by WinForms developers is "How to make sure that if Form is Closing, no validation occurs in contained controls"? ...]]></description>
			<content:encoded><![CDATA[<p>One of very often questions ask by WinForms developers is &#8220;How to make sure that if Form is Closing, no validation occurs in contained controls&#8221;?</p>
<p>For reference, validating input is rather straightforward:</p>
<p>1. Add <a href="http://msdn2.microsoft.com/en-us/library/system.windows.forms.errorprovider.aspx">ErrorProvider</a> to Form<br />
2. For control in question, add handlers for Validating and Validated events:</p>
<pre>
<code>
        private void tbFixPath_Validating(object sender, CancelEventArgs e)
        {
            if (!ControlValidated(tbFixPath.Text))
            {
                // Cancel the event and select the text to be corrected by the user.
                e.Cancel = true;
                tbFixPath.Select(0, tbFixPath.Text.Length);

                // Set the ErrorProvider error with the text to display.
                this.errorProvider1.SetError(tbFixPath,
                   "Sorry, something went wrong during validation. Please check.");
            }
        }

        private void tbFixPath_Validated(object sender, EventArgs e)
        {
                // After successful validation, clear error message.
                errorProvider1.SetError(tbFixPath, "");
        }
</code>
</pre>
<p>3. Everything is fine, until user tries to close form where some input elements are not validated &#8211; closing will fail. In order to prevent this, if you are absolutely sure that you want to close such form, just add:</p>
<pre>
<code>
        private void MainForm_FormClosing(object sender, FormClosingEventArgs e)
        {
                e.Cancel = false;
        }
</code>
</pre>
<p>so that no cancellation of closing event will occur.</p>
<p>I know that this is basic <img src='http://www.vesic.org/english/blog/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' />  but after I was ask for 10th time in 6 months, I figured that is better to note this somewhere <img src='http://www.vesic.org/english/blog/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' /> </p>
]]></content:encoded>
			<wfw:commentRss>http://www.vesic.org/english/blog/winforms/winforms-validation/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
	</channel>
</rss>

