{"id":168,"date":"2019-07-03T14:38:02","date_gmt":"2019-07-03T20:38:02","guid":{"rendered":"https:\/\/www.great-white-software.com\/blog\/?p=168"},"modified":"2019-06-26T14:57:28","modified_gmt":"2019-06-26T20:57:28","slug":"code-for-safety-ii","status":"publish","type":"post","link":"https:\/\/www.great-white-software.com\/blog\/2019\/07\/03\/code-for-safety-ii\/","title":{"rendered":"Code for safety II"},"content":{"rendered":"\n<p>Back when I wrote <a href=\"https:\/\/www.great-white-software.com\/blog\/2019\/05\/28\/code-for-safety\/\">Code for Safety<\/a> I gave one example of something that I&#8217;m sure we&#8217;ve all done from time to time. Saving the state of some flag and then returning and having possibly multiple places to reset the flag we saved.<\/p>\n\n\n\n<p>There&#8217;s another thats is more common with the advent of HiDPI support for Windows; drawing in a listbox event like CellBackGroundPaint Saving the graphics state, disabling antialiasing, and then needing to restore that state.<\/p>\n\n\n\n<p>This is especially true on Windows where you may need to disable anti-aliasing, change the foreground color &amp; fill the background to achieve some custom effect. If you dont disable anti-aliasing you can end up with odd effects as noted in<a href=\"https:\/\/docs.xojo.com\/index.php\/ListBox.CellBackgroundPaint\"> the documentation<\/a> and <a href=\"https:\/\/blog.xojo.com\/2017\/02\/15\/fractional-scale-factors\/\">this post<\/a>.<\/p>\n\n\n\n<p>Having a way to save the existing state and consisntenly and reliably restore it to what it was when the method was called is useful since you dont know if the graphics object is passed on to other events like CellTextPaint. Not restoring the state may lead to unwanted side effects.<\/p>\n\n\n\n<p>So how to make it so you can simply save the state and never worry about it being restored properly ? As I mentioned <a href=\"https:\/\/www.great-white-software.com\/blog\/2019\/05\/28\/code-for-safety\/\">before<\/a> ; a class that has almost nothing to it but a constructor &amp; a destructor.<\/p>\n\n\n\n<p>My implementation is called GraphicsStatePreserver.<\/p>\n\n\n\n<p>The constructor is simply<\/p>\n\n\n\n<p><\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>Sub Constructor(g as graphics)\n  mG = g\n  \n  Me.mAntiAlias = g.AntiAlias\n  Me.mAntiAliasMode = g.AntiAliasMode\n  Me.mBold = g.Bold\n  Me.mCharacterSpacing = g.CharacterSpacing\n  Me.mForeColor = g.ForeColor\n  Me.mItalic = g.Italic\n  Me.mLastPage = g.LastPage\n  Me.mPenHeight = g.PenHeight\n  Me.mPenWidth = g.PenWidth\n  Me.mScaleX = g.ScaleX\n  Me.mScaleY = g.ScaleY\n  Me.mTextFont = g.TextFont\n  Me.mTextSize = g.TextSize\n  me.mtextunit = g.TextUnit\n  Me.mTransparency = g.Transparency\n  Me.mUnderline = g.Underline\n  \nEnd Sub\n<\/code><\/pre>\n\n\n\n<p>We save the current state of the various writeable properties of the graphics into locals, and a hard reference to the graphics object. We keep a hard reference to make sur it cannot go out of scope before we have done our thing to restore the various settings.<\/p>\n\n\n\n<p>The destructor is equally simple<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>Sub Destructor()\n  mg.AntiAlias = Me.mAntiAlias \n  mg.AntiAliasMode = Me.mAntiAliasMode \n  mg.Bold = Me.mBold \n  mg.CharacterSpacing = Me.mCharacterSpacing \n  mg.ForeColor = Me.mForeColor \n  mg.Italic = Me.mItalic \n  mg.PenHeight = Me.mPenHeight \n  mg.PenWidth = Me.mPenWidth \n  mg.ScaleX = Me.mScaleX \n  mg.ScaleY = Me.mScaleY \n  mg.TextFont = Me.mTextFont \n  mg.TextSize = Me.mTextSize \n  mg.textunit = Me.mTextUnit\n  mg.Transparency = Me.mTransparency \n  mg.Underline = Me.mUnderline \n  \nEnd Sub\n<\/code><\/pre>\n\n\n\n<p>When this class is destroyed it will put back all the properties on the graphics just as they were when the instance was created.<\/p>\n\n\n\n<p>And since an instance is used like<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>Dim statepreserver As New GraphicsStatePreserver(g)\n\n#If targetwindows\n  g.AntiAlias = False\n#EndIf\n\nIf row &lt; 0 Then \n  Return True\nEnd If\nIf column &lt; 0 Then \n  Return True\nEnd If\n\n\/\/ whatever othe r code you need in cell background paint\n\nReturn True\n<\/code><\/pre>\n\n\n\n<p>This instance will ONLY go out of scope, and be destroyed, at the points where the event is being exited. And that happens to be the exact points we want to restore the graphics state.<\/p>\n\n\n\n<p><\/p>\n\n\n\n<p>Here&#8217;s the entire implementation<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>Class GraphicsStatePreserver\n\tSub Constructor(g as graphics)\n\t  mG = g\n  \n\t  Me.mAntiAlias = g.AntiAlias\n\t  Me.mAntiAliasMode = g.AntiAliasMode\n\t  Me.mBold = g.Bold\n\t  Me.mCharacterSpacing = g.CharacterSpacing\n\t  Me.mForeColor = g.ForeColor\n\t  Me.mItalic = g.Italic\n\t  Me.mLastPage = g.LastPage\n\t  Me.mPenHeight = g.PenHeight\n\t  Me.mPenWidth = g.PenWidth\n\t  Me.mScaleX = g.ScaleX\n\t  Me.mScaleY = g.ScaleY\n\t  Me.mTextFont = g.TextFont\n\t  Me.mTextSize = g.TextSize\n\t  me.mtextunit = g.TextUnit\n\t  Me.mTransparency = g.Transparency\n\t  Me.mUnderline = g.Underline\n  \n\tEnd Sub\n\n\tSub Destructor()\n\t  mg.AntiAlias = Me.mAntiAlias \n\t  mg.AntiAliasMode = Me.mAntiAliasMode \n\t  mg.Bold = Me.mBold \n\t  mg.CharacterSpacing = Me.mCharacterSpacing \n\t  mg.ForeColor = Me.mForeColor \n\t  mg.Italic = Me.mItalic \n\t  mg.PenHeight = Me.mPenHeight \n\t  mg.PenWidth = Me.mPenWidth \n\t  mg.ScaleX = Me.mScaleX \n\t  mg.ScaleY = Me.mScaleY \n\t  mg.TextFont = Me.mTextFont \n\t  mg.TextSize = Me.mTextSize \n\t  mg.textunit = Me.mTextUnit\n\t  mg.Transparency = Me.mTransparency \n\t  mg.Underline = Me.mUnderline \n  \n\tEnd Sub\n\n\tPrivate Property mAntiAlias As boolean\n\tPrivate Property mAntiAliasMode As Graphics.AntiAliasModes\n\tPrivate Property mBold As boolean\n\tPrivate Property mCharacterSpacing As Integer\n\tPrivate Property mForeColor As color\n\tPrivate Property mG As graphics\n\tPrivate Property mItalic As boolean\n\tPrivate Property mLastPage As Integer\n\tPrivate Property mPenHeight As double\n\tPrivate Property mPenWidth As double\n\tPrivate Property mScaleX As double\n\tPrivate Property mScaleY As double\n\tPrivate Property mTextFont As string\n\tPrivate Property mTextSize As Single\n\tPrivate Property mtextunit As FontUnits\n\tPrivate Property mTransparency As double\n\tPrivate Property mUnderline As boolean\n\nEnd Class\n\n<\/code><\/pre>\n\n\n\n<p><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Back when I wrote Code for Safety I gave one example of something that I&#8217;m sure we&#8217;ve all done from time to time. Saving the state of some flag and then returning and having possibly multiple places to reset the flag we saved. There&#8217;s another thats is more common with the advent of HiDPI support &hellip; <\/p>\n<p class=\"link-more\"><a href=\"https:\/\/www.great-white-software.com\/blog\/2019\/07\/03\/code-for-safety-ii\/\" class=\"more-link\">Continue reading<span class=\"screen-reader-text\"> &#8220;Code for safety II&#8221;<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_jetpack_memberships_contains_paid_content":false,"footnotes":""},"categories":[1],"tags":[2,6,3],"class_list":["post-168","post","type-post","status-publish","format-standard","hentry","category-uncategorized","tag-safe-code","tag-tips","tag-xojo"],"jetpack_featured_media_url":"","jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/www.great-white-software.com\/blog\/wp-json\/wp\/v2\/posts\/168","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.great-white-software.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.great-white-software.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.great-white-software.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.great-white-software.com\/blog\/wp-json\/wp\/v2\/comments?post=168"}],"version-history":[{"count":1,"href":"https:\/\/www.great-white-software.com\/blog\/wp-json\/wp\/v2\/posts\/168\/revisions"}],"predecessor-version":[{"id":169,"href":"https:\/\/www.great-white-software.com\/blog\/wp-json\/wp\/v2\/posts\/168\/revisions\/169"}],"wp:attachment":[{"href":"https:\/\/www.great-white-software.com\/blog\/wp-json\/wp\/v2\/media?parent=168"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.great-white-software.com\/blog\/wp-json\/wp\/v2\/categories?post=168"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.great-white-software.com\/blog\/wp-json\/wp\/v2\/tags?post=168"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}