<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:georss='http://www.georss.org/georss' xmlns:gd='http://schemas.google.com/g/2005' xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-5377233936486388397</id><updated>2011-11-27T16:35:23.377-08:00</updated><category term='GPU'/><category term='setup'/><category term='pc'/><category term='jscript'/><category term='milestone'/><category term='wired'/><category term='explanation'/><category term='regedit'/><category term='diff-tools'/><category term='visual-studio'/><category term='media center'/><category term='registry'/><category term='development'/><category term='explorer'/><category term='events'/><category term='photos'/><category term='pop-up blocker'/><category term='chrome'/><category term='cooliris'/><category term='dell'/><category term='firefox'/><category term='1.6'/><category term='bho'/><category term='win7'/><category term='ibm'/><category term='netflix'/><category term='shell'/><category term='tips'/><category term='user interface'/><category term='OLE'/><category term='p4'/><category term='spyware'/><category term='video'/><category term='windows'/><category term='windows live mail'/><category term='favicons'/><category term='c++'/><category term='hardware'/><category term='company-store'/><category term='wikitalk'/><category term='widescreen monitor'/><category term='extensions'/><category term='new york times'/><category term='snarky'/><category term='internet explorer'/><category term='engrish'/><category term='security'/><category term='lenovo'/><category term='source-control'/><category term='piclens'/><category term='COM'/><category term='dialogs'/><category term='webbrowsers'/><category term='hillarity'/><category term='windows xp service pack 2'/><category term='errored'/><category term='thinkpad'/><category term='windows update'/><category term='iPhone'/><category term='activex'/><category term='drivers'/><category term='mac'/><category term='microsoft'/><category term='out-of-memory'/><category term='eco-system'/><category term='inewwindowmanager'/><category term='fail'/><category term='fixes'/><category term='slashdot'/><category term='caching'/><category term='temporary internet files'/><category term='crunchie'/><category term='iobjectwithsite'/><category term='nvidia'/><category term='vista'/><title type='text'>jeffdav on code</title><subtitle type='html'>Practical coding tips, tricks, advice and anecdotes.  Including, but not limited to: C++, C#, JavaScript, COM, OLE, Internet Explorer, Win32 and what-not.</subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://jeffcode.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5377233936486388397/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://jeffcode.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>jeffdav</name><uri>http://www.blogger.com/profile/14865307340669462204</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>34</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-5377233936486388397.post-4612202984408200765</id><published>2010-07-15T17:51:00.000-07:00</published><updated>2010-07-15T17:51:10.970-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='win7'/><category scheme='http://www.blogger.com/atom/ns#' term='hillarity'/><category scheme='http://www.blogger.com/atom/ns#' term='dialogs'/><category scheme='http://www.blogger.com/atom/ns#' term='windows live mail'/><category scheme='http://www.blogger.com/atom/ns#' term='microsoft'/><title type='text'>Worst Microsoft Dialogs</title><content type='html'>So, I thought this dialog was pretty bad:&lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://3.bp.blogspot.com/_d_Sh9p8ja6w/TD-rQmo3cxI/AAAAAAAAAO4/vuix5q34waY/s1600/visual-studio-worst-dialog-ever.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://3.bp.blogspot.com/_d_Sh9p8ja6w/TD-rQmo3cxI/AAAAAAAAAO4/vuix5q34waY/s320/visual-studio-worst-dialog-ever.png" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;I mean, the only question in all that text (you know, the sentence that ends in a &lt;i&gt;question mark&lt;/i&gt;) is not a yes/no question. &amp;nbsp;The actual question is down at the bottom and ends in a nonsensical colon. &amp;nbsp;And it has not one, but &lt;i&gt;two&lt;/i&gt;&amp;nbsp;parenthetical phrases. &amp;nbsp;And it contains a really long, unwieldy URL that isn't clickable or copyable.&lt;br /&gt;&lt;br /&gt;But then I got this gem from Windows Live Mail (in Windows 7) today:&lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/_d_Sh9p8ja6w/TD-sNlUhuKI/AAAAAAAAAPA/2GwT_f0uWhM/s1600/windows-live-mail-stupid-dialog.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://1.bp.blogspot.com/_d_Sh9p8ja6w/TD-sNlUhuKI/AAAAAAAAAPA/2GwT_f0uWhM/s320/windows-live-mail-stupid-dialog.png" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;First of all, I had pressed ALT+F4 to close WLM having completed my business with it. &amp;nbsp;Opening a modal dialog for something only tangentially related to exiting the app is a little intrusive, but, okay. &amp;nbsp;The thing that's really bad about this is that it tells me what &lt;i&gt;won't&lt;/i&gt;&amp;nbsp;happen if I click yes, but I still have no idea what &lt;i&gt;will&lt;/i&gt;&amp;nbsp;happen if I click yes. &amp;nbsp;But I only use WLM to read mail that comes to my passport account from Microsoft lists, so if it all gets deleted I don't really care. &amp;nbsp;So I'm feeling adventurous and click yes. &amp;nbsp;Then I get this:&lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://3.bp.blogspot.com/_d_Sh9p8ja6w/TD-sztIbsWI/AAAAAAAAAPI/2HBBNQ_nHRI/s1600/windows-live-mail-stupid-dialog-2.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://3.bp.blogspot.com/_d_Sh9p8ja6w/TD-sztIbsWI/AAAAAAAAAPI/2HBBNQ_nHRI/s320/windows-live-mail-stupid-dialog-2.png" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: left;"&gt;Really? &amp;nbsp;You didn't see that one coming WLM?&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: left;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: left;"&gt;Sigh. &amp;nbsp;The fight goes on.&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5377233936486388397-4612202984408200765?l=jeffcode.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://jeffcode.blogspot.com/feeds/4612202984408200765/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5377233936486388397&amp;postID=4612202984408200765' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5377233936486388397/posts/default/4612202984408200765'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5377233936486388397/posts/default/4612202984408200765'/><link rel='alternate' type='text/html' href='http://jeffcode.blogspot.com/2010/07/worst-microsoft-dialogs.html' title='Worst Microsoft Dialogs'/><author><name>jeffdav</name><uri>http://www.blogger.com/profile/14865307340669462204</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/_d_Sh9p8ja6w/TD-rQmo3cxI/AAAAAAAAAO4/vuix5q34waY/s72-c/visual-studio-worst-dialog-ever.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5377233936486388397.post-4726098255464995683</id><published>2010-03-24T09:58:00.000-07:00</published><updated>2010-03-24T09:58:59.407-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='errored'/><category scheme='http://www.blogger.com/atom/ns#' term='p4'/><category scheme='http://www.blogger.com/atom/ns#' term='source-control'/><title type='text'>Perforce has the best error messages.</title><content type='html'>I wanted to know what the path to something was on the server, but I couldn't remember.  Little did I know that perforce would be so judgemental:&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;c:\source&gt;p4 dirs *&lt;br /&gt;//depot/foo/bar/baz&lt;br /&gt;//depot/foo/bar/qux&lt;br /&gt;Client map too twisted for directory list.&lt;/blockquote&gt;&lt;br /&gt;And then there was the time I made a perfectly reasonable request, I wanted to edit all the unittest files in the entire tree, and it had to go and get all preachy:&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;c:\source\v2-dev&gt;p4 edit foo\...*unittest.cc&lt;br /&gt;Senseless juxtaposition of wildcards in '//jeff-src/foo/...*unittest.cc'.&lt;/blockquote&gt;&lt;br /&gt;I mean, yeah, maybe there's a typo there, but you don't have to insult me.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5377233936486388397-4726098255464995683?l=jeffcode.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://jeffcode.blogspot.com/feeds/4726098255464995683/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5377233936486388397&amp;postID=4726098255464995683' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5377233936486388397/posts/default/4726098255464995683'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5377233936486388397/posts/default/4726098255464995683'/><link rel='alternate' type='text/html' href='http://jeffcode.blogspot.com/2010/03/perforce-has-best-error-messages.html' title='Perforce has the best error messages.'/><author><name>jeffdav</name><uri>http://www.blogger.com/profile/14865307340669462204</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5377233936486388397.post-5951167105859014209</id><published>2010-03-17T08:20:00.000-07:00</published><updated>2010-03-17T08:26:01.438-07:00</updated><title type='text'>GetModuleFileName() on OS X.</title><content type='html'>So, you want to know the path to your module. &amp;nbsp;On Windows, it's easy: you call &lt;a href="http://msdn.microsoft.com/en-us/library/ms683197(VS.85).aspx"&gt;GetModuleFileName()&lt;/a&gt;&amp;nbsp;and pass NULL for the HMODULE.&lt;br /&gt;&lt;br /&gt;But what if you're trying to do it on OS X? &lt;br /&gt;&lt;br /&gt;&lt;pre&gt;#include &amp;lt;dlfcn.h&amp;gt;&lt;br /&gt;std::string GetModuleFileNameOSX() {&lt;br /&gt;  Dl_info module_info;&lt;br /&gt;  if (dladdr(reinterpret_cast&amp;lt;void*&amp;gt;(GetModuleFileNameOSX), &amp;module_info) == 0) {&lt;br /&gt;    // Failed to find the symbol we asked for.&lt;br /&gt;    return std::string();&lt;br /&gt;  }&lt;br /&gt;  return std::string(module_info.dli_fname);&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;For the first param to dladdr, you can pass any symbol you know will be in your module.  In theory, something similar should work on linux, but I haven't tried.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5377233936486388397-5951167105859014209?l=jeffcode.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://jeffcode.blogspot.com/feeds/5951167105859014209/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5377233936486388397&amp;postID=5951167105859014209' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5377233936486388397/posts/default/5951167105859014209'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5377233936486388397/posts/default/5951167105859014209'/><link rel='alternate' type='text/html' href='http://jeffcode.blogspot.com/2010/03/getmodulefilename-on-os-x.html' title='GetModuleFileName() on OS X.'/><author><name>jeffdav</name><uri>http://www.blogger.com/profile/14865307340669462204</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5377233936486388397.post-1097967156378585952</id><published>2009-11-10T10:05:00.000-08:00</published><updated>2009-11-10T10:09:18.418-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='regedit'/><category scheme='http://www.blogger.com/atom/ns#' term='snarky'/><category scheme='http://www.blogger.com/atom/ns#' term='registry'/><category scheme='http://www.blogger.com/atom/ns#' term='windows'/><category scheme='http://www.blogger.com/atom/ns#' term='out-of-memory'/><category scheme='http://www.blogger.com/atom/ns#' term='diff-tools'/><title type='text'>Adventures in Diffing...</title><content type='html'>So &lt;a href="http://www.schneier.com/blog/archives/2009/11/is_antivirus_de.html"&gt;today Schneier recommended AVG&lt;/a&gt; as a useful, free anti-virus solution.  As I'm terribly anti-virus, I wanted to see if really ran "...in the background, automatically, and you won't notice any performance degradation at all."  So I installed it.  My first step was going to be comparing the registry before and after the install to see what sorts of things it was installing.  This is where my experiment took a left turn: I just wanted to view the diff.&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;c:\Users\jeff\Desktop&amp;gt;dir *.reg&lt;br /&gt;Volume in drive C has no label.&lt;br /&gt;Volume Serial Number is 96A6-6911&lt;br /&gt;&lt;br /&gt;Directory of c:\Users\jeff\Desktop&lt;br /&gt;&lt;br /&gt;11/10/2009  09:18 AM       487,799,220 registry-after-install.reg&lt;br /&gt;11/10/2009  08:53 AM       487,588,198 registry-before.reg&lt;br /&gt;2 File(s)    975,387,418 bytes&lt;br /&gt;0 Dir(s)  220,934,803,456 bytes free&lt;br /&gt;&lt;/blockquote&gt;&lt;br /&gt;Turns out the registry is frickin' huge!  Whatever AVG did, it added about 211k of goop to the registry.&lt;br /&gt;&lt;br /&gt;My first attempt was to use my favorite diff tool, windiff.exe.  Windiff has been my trusted companion ever since I joined MSFT back in 2001.  Today, for the first time, it let me down.  After churning on the files for about two minutes it ran out of memory.&lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/_d_Sh9p8ja6w/SvmpABNZ5tI/AAAAAAAAANw/FlQ6Jq8TSB4/s1600-h/windiff-oom-fail.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://1.bp.blogspot.com/_d_Sh9p8ja6w/SvmpABNZ5tI/AAAAAAAAANw/FlQ6Jq8TSB4/s640/windiff-oom-fail.jpg" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;Very sad. &amp;nbsp;So, next we tried gnu diff from the command line. &amp;nbsp;Gnu diff allocated some memory, then allocated some more, and, in a manner much quicker than windiff, proceeded to give me garbage output because it doesn't believe in unicode.&lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://2.bp.blogspot.com/_d_Sh9p8ja6w/SvmqDCZutrI/AAAAAAAAAN4/LPOoxvHoFHs/s1600-h/winmerge-like-windiff-but-faster.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://2.bp.blogspot.com/_d_Sh9p8ja6w/SvmqDCZutrI/AAAAAAAAAN4/LPOoxvHoFHs/s640/winmerge-like-windiff-but-faster.jpg" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;I also tried P4Merge, but it knew its limitations.&lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/_d_Sh9p8ja6w/SvmqXHBxukI/AAAAAAAAAOA/YRexpnKUwuE/s1600-h/p4-merge-says-youre-fucking-kidding-right-cropped.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://1.bp.blogspot.com/_d_Sh9p8ja6w/SvmqXHBxukI/AAAAAAAAAOA/YRexpnKUwuE/s640/p4-merge-says-youre-fucking-kidding-right-cropped.jpg" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;In a last-ditch effort to get the info I wanted, I turned to the Mac. &amp;nbsp;FileMerge on OS X 10.5 (so, the 32bit version) failed as well.&amp;nbsp; It churned for awhile, the crashed with no clear reason, but I suspect it was out of memory.&lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://3.bp.blogspot.com/_d_Sh9p8ja6w/Svmq8yycM0I/AAAAAAAAAOI/WF82lJeQlSE/s1600-h/Picture+4.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://3.bp.blogspot.com/_d_Sh9p8ja6w/Svmq8yycM0I/AAAAAAAAAOI/WF82lJeQlSE/s640/Picture+4.png" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;So, my little experiment failed.&amp;nbsp; What did we learn from all this?&amp;nbsp; The Windows Registry is too large, I think.&amp;nbsp; Or, just trust Bruce.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5377233936486388397-1097967156378585952?l=jeffcode.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://jeffcode.blogspot.com/feeds/1097967156378585952/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5377233936486388397&amp;postID=1097967156378585952' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5377233936486388397/posts/default/1097967156378585952'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5377233936486388397/posts/default/1097967156378585952'/><link rel='alternate' type='text/html' href='http://jeffcode.blogspot.com/2009/11/adventures-in-diffing.html' title='Adventures in Diffing...'/><author><name>jeffdav</name><uri>http://www.blogger.com/profile/14865307340669462204</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/_d_Sh9p8ja6w/SvmpABNZ5tI/AAAAAAAAANw/FlQ6Jq8TSB4/s72-c/windiff-oom-fail.jpg' height='72' width='72'/><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5377233936486388397.post-6654718477698328893</id><published>2009-11-10T09:19:00.000-08:00</published><updated>2009-11-10T09:19:02.660-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='win7'/><category scheme='http://www.blogger.com/atom/ns#' term='visual-studio'/><category scheme='http://www.blogger.com/atom/ns#' term='regedit'/><category scheme='http://www.blogger.com/atom/ns#' term='fixes'/><title type='text'>Things I Hope Are Fixed In The Next Version</title><content type='html'>Exporting from the registry to disk happens on the UI thread.  I hope this is fixed in regedit in Windows 7.&lt;br /&gt;&lt;br /&gt;Loading symbols (from disk or the public symbol server) happens on the UI thread.  I hope this is fixed in Visual Studio 2010.&lt;br /&gt;&lt;br /&gt;I'm holding my breath.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5377233936486388397-6654718477698328893?l=jeffcode.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://jeffcode.blogspot.com/feeds/6654718477698328893/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5377233936486388397&amp;postID=6654718477698328893' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5377233936486388397/posts/default/6654718477698328893'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5377233936486388397/posts/default/6654718477698328893'/><link rel='alternate' type='text/html' href='http://jeffcode.blogspot.com/2009/11/things-i-hope-are-fixed-in-next-version.html' title='Things I Hope Are Fixed In The Next Version'/><author><name>jeffdav</name><uri>http://www.blogger.com/profile/14865307340669462204</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5377233936486388397.post-2610810527356850508</id><published>2009-07-16T14:51:00.000-07:00</published><updated>2009-07-16T15:00:07.782-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='errored'/><category scheme='http://www.blogger.com/atom/ns#' term='fail'/><category scheme='http://www.blogger.com/atom/ns#' term='company-store'/><category scheme='http://www.blogger.com/atom/ns#' term='microsoft'/><title type='text'>a trip to the Microsoft company store...</title><content type='html'>I was recently in Redmond and one of my good MSFT friends was kind enough to take me to the company store to pick up a copy of VS2008 and Vista.  As we strolled through the lobby, we saw this:&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_d_Sh9p8ja6w/Sl-hoEHZIGI/AAAAAAAAAM4/t2M-qYaZ-tQ/s1600-h/gigantic+iphone+import+2378.JPG"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 320px; height: 240px;" src="http://3.bp.blogspot.com/_d_Sh9p8ja6w/Sl-hoEHZIGI/AAAAAAAAAM4/t2M-qYaZ-tQ/s320/gigantic+iphone+import+2378.JPG" border="0" alt=""id="BLOGGER_PHOTO_ID_5359179791265767522" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_d_Sh9p8ja6w/Sl-hocPYKeI/AAAAAAAAANA/bZokX-tnFnk/s1600-h/gigantic+iphone+import+2379.JPG"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 320px; height: 240px;" src="http://3.bp.blogspot.com/_d_Sh9p8ja6w/Sl-hocPYKeI/AAAAAAAAANA/bZokX-tnFnk/s320/gigantic+iphone+import+2379.JPG" border="0" alt=""id="BLOGGER_PHOTO_ID_5359179797741709794" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;And later on, inside the store proper, we saw this:&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_d_Sh9p8ja6w/Sl-hog9Oz0I/AAAAAAAAANI/J_OVUfHCCK8/s1600-h/gigantic+iphone+import+2381.JPG"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 320px; height: 240px;" src="http://2.bp.blogspot.com/_d_Sh9p8ja6w/Sl-hog9Oz0I/AAAAAAAAANI/J_OVUfHCCK8/s320/gigantic+iphone+import+2381.JPG" border="0" alt=""id="BLOGGER_PHOTO_ID_5359179799007776578" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_d_Sh9p8ja6w/Sl-ho6WkqoI/AAAAAAAAANQ/zNZot-B4X6U/s1600-h/gigantic+iphone+import+2380.JPG"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 320px; height: 240px;" src="http://1.bp.blogspot.com/_d_Sh9p8ja6w/Sl-ho6WkqoI/AAAAAAAAANQ/zNZot-B4X6U/s320/gigantic+iphone+import+2380.JPG" border="0" alt=""id="BLOGGER_PHOTO_ID_5359179805824952962" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;My friend, who is a PM for User Experience related things in the Windows team just sighed and said, "why does it gotta be this way?"  And I laughed.&lt;br /&gt;&lt;br /&gt;But it is easy to make fun of Microsoft for failing in their own technology showcase, but I've learned two things:&lt;br /&gt;&lt;br /&gt;1) All software is pretty terrible when you get down to it.&lt;br /&gt;2) Programming is hard.&lt;br /&gt;&lt;br /&gt;Both machines are using Windows in a way that was not the primary concern of anyone who was working on Windows Vista.  Developers tend to focus on the use cases they expect--users at home, users at work.  But as computers become more general purpose, we have to start thinking through a bunch of other scenarios as well.  Heck, I bet someone even knows how to configure these machines to prevent these things from happening, but I couldn't tell you how to do it.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5377233936486388397-2610810527356850508?l=jeffcode.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://jeffcode.blogspot.com/feeds/2610810527356850508/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5377233936486388397&amp;postID=2610810527356850508' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5377233936486388397/posts/default/2610810527356850508'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5377233936486388397/posts/default/2610810527356850508'/><link rel='alternate' type='text/html' href='http://jeffcode.blogspot.com/2009/07/trip-to-microsoft-company-store.html' title='a trip to the Microsoft company store...'/><author><name>jeffdav</name><uri>http://www.blogger.com/profile/14865307340669462204</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/_d_Sh9p8ja6w/Sl-hoEHZIGI/AAAAAAAAAM4/t2M-qYaZ-tQ/s72-c/gigantic+iphone+import+2378.JPG' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5377233936486388397.post-2679227102596423109</id><published>2009-06-10T09:27:00.000-07:00</published><updated>2009-06-10T09:29:37.282-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='vista'/><category scheme='http://www.blogger.com/atom/ns#' term='engrish'/><category scheme='http://www.blogger.com/atom/ns#' term='windows update'/><category scheme='http://www.blogger.com/atom/ns#' term='setup'/><category scheme='http://www.blogger.com/atom/ns#' term='nvidia'/><category scheme='http://www.blogger.com/atom/ns#' term='drivers'/><title type='text'>Adventures in Driver Updates</title><content type='html'>I love that Windows Update brings me the latest drivers for my video card.  It's too bad that hardware OEMs still can't figure out how to write installers.  The engrish is amusing as well:&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_d_Sh9p8ja6w/Si_fUOrqtxI/AAAAAAAAAMY/RkpZ-pD5PaI/s1600-h/EXIT-IS-THE-ONLY-OPTION.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 320px; height: 170px;" src="http://4.bp.blogspot.com/_d_Sh9p8ja6w/Si_fUOrqtxI/AAAAAAAAAMY/RkpZ-pD5PaI/s320/EXIT-IS-THE-ONLY-OPTION.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5345736821343696658" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;At least Windows Update thinks it succeeded.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5377233936486388397-2679227102596423109?l=jeffcode.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://jeffcode.blogspot.com/feeds/2679227102596423109/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5377233936486388397&amp;postID=2679227102596423109' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5377233936486388397/posts/default/2679227102596423109'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5377233936486388397/posts/default/2679227102596423109'/><link rel='alternate' type='text/html' href='http://jeffcode.blogspot.com/2009/06/adventures-in-driver-updates.html' title='Adventures in Driver Updates'/><author><name>jeffdav</name><uri>http://www.blogger.com/profile/14865307340669462204</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_d_Sh9p8ja6w/Si_fUOrqtxI/AAAAAAAAAMY/RkpZ-pD5PaI/s72-c/EXIT-IS-THE-ONLY-OPTION.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5377233936486388397.post-3733691478984986411</id><published>2009-01-30T19:05:00.000-08:00</published><updated>2009-01-30T19:06:19.831-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='webbrowsers'/><title type='text'>Browser Market Share</title><content type='html'>&lt;img src="http://spreadsheets.google.com/pub?key=p_1nmISrQ8m_6ZbxcS3IfFQ&amp;oid=4&amp;output=image" /&gt;&lt;br /&gt;&lt;br /&gt;I made this chart today.  It's revealing.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5377233936486388397-3733691478984986411?l=jeffcode.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://jeffcode.blogspot.com/feeds/3733691478984986411/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5377233936486388397&amp;postID=3733691478984986411' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5377233936486388397/posts/default/3733691478984986411'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5377233936486388397/posts/default/3733691478984986411'/><link rel='alternate' type='text/html' href='http://jeffcode.blogspot.com/2009/01/browser-market-share.html' title='Browser Market Share'/><author><name>jeffdav</name><uri>http://www.blogger.com/profile/14865307340669462204</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5377233936486388397.post-1732306555902310665</id><published>2009-01-21T16:26:00.000-08:00</published><updated>2009-01-21T16:27:39.708-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='c++'/><title type='text'>else while?</title><content type='html'>Everyone accepts the "else if" construct in C++, but nobody likes it when I try to do "else while".  I wonder why.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5377233936486388397-1732306555902310665?l=jeffcode.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://jeffcode.blogspot.com/feeds/1732306555902310665/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5377233936486388397&amp;postID=1732306555902310665' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5377233936486388397/posts/default/1732306555902310665'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5377233936486388397/posts/default/1732306555902310665'/><link rel='alternate' type='text/html' href='http://jeffcode.blogspot.com/2009/01/else-while.html' title='else while?'/><author><name>jeffdav</name><uri>http://www.blogger.com/profile/14865307340669462204</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5377233936486388397.post-242987503059912362</id><published>2009-01-09T21:24:00.000-08:00</published><updated>2009-01-09T21:25:42.404-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='crunchie'/><category scheme='http://www.blogger.com/atom/ns#' term='cooliris'/><title type='text'>We won!</title><content type='html'>Hey, looks like we won the Best Design Crunchie.  If you voted for us, thanks!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5377233936486388397-242987503059912362?l=jeffcode.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://jeffcode.blogspot.com/feeds/242987503059912362/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5377233936486388397&amp;postID=242987503059912362' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5377233936486388397/posts/default/242987503059912362'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5377233936486388397/posts/default/242987503059912362'/><link rel='alternate' type='text/html' href='http://jeffcode.blogspot.com/2009/01/we-won.html' title='We won!'/><author><name>jeffdav</name><uri>http://www.blogger.com/profile/14865307340669462204</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5377233936486388397.post-8206994514215062141</id><published>2008-12-29T19:17:00.000-08:00</published><updated>2008-12-29T19:21:42.766-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='cooliris'/><title type='text'>Cooliris nominated for 2008 Crunchie</title><content type='html'>My company (and product) has been nominated for a Crunchie in the "Best Design" category.  I'm not surprised, since the product was cool enough to make me want to work there.  However, it is nice to get recognition and positive feedback that other people feel the same way I do about it. &lt;br /&gt;&lt;br /&gt;Anyway, if you like Cooliris and want to vote, you can vote for us here:&lt;br /&gt;&lt;br /&gt;&lt;a href="http://crunchies2008.techcrunch.com/votes/"&gt;http://crunchies2008.techcrunch.com/votes/&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;And if you haven't tried Cooliris yet, please &lt;a href="http://www.cooliris.com"&gt;give it a whirl&lt;/a&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5377233936486388397-8206994514215062141?l=jeffcode.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://jeffcode.blogspot.com/feeds/8206994514215062141/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5377233936486388397&amp;postID=8206994514215062141' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5377233936486388397/posts/default/8206994514215062141'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5377233936486388397/posts/default/8206994514215062141'/><link rel='alternate' type='text/html' href='http://jeffcode.blogspot.com/2008/12/cooliris-nominated-for-2008-crunchie.html' title='Cooliris nominated for 2008 Crunchie'/><author><name>jeffdav</name><uri>http://www.blogger.com/profile/14865307340669462204</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5377233936486388397.post-7357028836515347695</id><published>2008-10-05T12:43:00.000-07:00</published><updated>2008-10-05T12:57:57.041-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='cooliris'/><title type='text'>Cooliris 1.8.3 Released!</title><content type='html'>&lt;span style="font-weight:bold;"&gt;Cooliris 1.8.3&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Last week we released 1.8.3 of Cooliris (formerly known as PicLens).  You can &lt;a href="http://www.cooliris.com/"&gt;download it here&lt;/a&gt;.  In addition to Firefox 2 and 3 (Mac and Windows) we now support Safari 3 (Mac) and Internet Explorer 8 Beta 2 (Windows), though our IE8 Beta support is itself in Beta.  In addition, we have lots of new features.  1.8.3 is one of the biggest releases we've had since we first debuted the 3D view.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;More Shopping&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;A while ago we introduced support for searching Amazon in Cooliris.  With 1.8.3 we now support ten different retailers such as eLuxury, Nordstrom, beauty.com, Macy's, Wal-mart and more, with more stores to be added.  (Geeky aside: the client makes a request to our servers for some XML that describes all the stores that we support so we can add more stores without having to publish a new client.) In addition to more stores, we also now have improved UI for browsing the stores and sorting the results by price, popularity, etc.  &lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Flash Support&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;In addition to various improvements we made to our A\V playback code (A\V sync issues, as well as better buffering logic for slow connections), this release debuts the project I've been hard at work on the last few months: Flash support.  We now host the Flash plugin and can render SWF content directly in the wall.  The upside for the user is they get the full YouTube player experience when browsing YouTube video, and we will be adding more and more interactive content over time.  Right now we only support the Netscape Plugin version of Flash (NPSWF32.dll).  So if you've installed Flash for Firefox or other Netscape derivatives, you'll get Flash support.  If you only have the IE Active X plugin (flash9f.ocx, or related) you'll need to install the correct version which can be &lt;a href="http://www.adobe.com/shockwave/download/download.cgi?P1_Prod_Version=ShockwaveFlash&amp;P2_Platform=Win32&amp;P3_Browser=Netscape)"&gt;downloaded here&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;There are lots of other improvements, fixes, optimizations, etc, such as better Keyboard Input support, but I can't remember all of them right now.  I suggest you download the latest &lt;a href="http://www.cooliris.com"&gt;Cooliris&lt;/a&gt; and explore it for yourself.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5377233936486388397-7357028836515347695?l=jeffcode.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://jeffcode.blogspot.com/feeds/7357028836515347695/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5377233936486388397&amp;postID=7357028836515347695' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5377233936486388397/posts/default/7357028836515347695'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5377233936486388397/posts/default/7357028836515347695'/><link rel='alternate' type='text/html' href='http://jeffcode.blogspot.com/2008/10/cooliris-183-released.html' title='Cooliris 1.8.3 Released!'/><author><name>jeffdav</name><uri>http://www.blogger.com/profile/14865307340669462204</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5377233936486388397.post-1501224015457431425</id><published>2008-09-06T16:30:00.000-07:00</published><updated>2008-09-07T13:08:38.183-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='firefox'/><category scheme='http://www.blogger.com/atom/ns#' term='internet explorer'/><category scheme='http://www.blogger.com/atom/ns#' term='chrome'/><title type='text'>Google Chrome: Better than Firefox, Internet Explorer</title><content type='html'>I installed Chrome when it came out last week and after only a day of using it I did the unthinkable: I made it my default browser.  This is a big deal.  I resisted making Firefox my default browser out of a very strong sense of loyalty to Internet Explorer.  Chrome, however, is what I have always wanted a web browser to be: useful.&lt;br /&gt;&lt;br /&gt;Let us start with the obvious things.  The Tab UI is awesome.  I have never liked the Firefox Tab UI.  I think the IE Tab UI looks good, but they (we) never really nailed all the little quirks.  Putting it up in the non-client area seems like such a no-brainer now.  The UI is snappy, the animations are good looking, but subtle enough not to get in the way of using the product.  &lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_d_Sh9p8ja6w/SMMUBesZgvI/AAAAAAAAAFo/TeaOLRm0bw4/s1600-h/chrome.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;" src="http://4.bp.blogspot.com/_d_Sh9p8ja6w/SMMUBesZgvI/AAAAAAAAAFo/TeaOLRm0bw4/s320/chrome.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5243056406841098994" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;The MFU with thumbnails on the new-tab page is nice, though I wish it was more than just the top nine pages.  I find it odd that I like it so much because I was really against doing something like this for IE (but I also never thought it could be made so fast in IE).  I love the history-as-a-webpage feature.  I am a little disappointed that I can not find a shortcut key to get to bookmarks.  I don't want to take up screen space by having the bookmarks bar visible (though it is nice UI if you do turn it on).  I know I can just type the name of the bookmark in the address bar, but I actually have long lists of bookmarks that I like to visit every day in a specific order.  Instead I use CTRL+T to get a new tab then click the bookmark button.&lt;br /&gt;&lt;br /&gt;I love the simplicity.  We tried to make IE7 simple by getting rid of the menu bars and re-working things into the command bar.  Chrome takes it all the way though.  &lt;br /&gt;&lt;br /&gt;The only UI I think looks wonky is the little pop-up in the bottom corner of the screen that appears when you hover over links.  But I do like the little drop-down find box.&lt;br /&gt;&lt;br /&gt;And of course, it would be nice if it worked with the ajax-y features of Facebook and Netflix.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5377233936486388397-1501224015457431425?l=jeffcode.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://jeffcode.blogspot.com/feeds/1501224015457431425/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5377233936486388397&amp;postID=1501224015457431425' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5377233936486388397/posts/default/1501224015457431425'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5377233936486388397/posts/default/1501224015457431425'/><link rel='alternate' type='text/html' href='http://jeffcode.blogspot.com/2008/09/google-chrome-better-than-firefox.html' title='Google Chrome: Better than Firefox, Internet Explorer'/><author><name>jeffdav</name><uri>http://www.blogger.com/profile/14865307340669462204</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_d_Sh9p8ja6w/SMMUBesZgvI/AAAAAAAAAFo/TeaOLRm0bw4/s72-c/chrome.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5377233936486388397.post-8854972279691822361</id><published>2008-07-02T10:17:00.000-07:00</published><updated>2008-07-02T10:35:56.152-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='firefox'/><category scheme='http://www.blogger.com/atom/ns#' term='internet explorer'/><category scheme='http://www.blogger.com/atom/ns#' term='user interface'/><title type='text'>firefox 3: better than internet explorer 7</title><content type='html'>This is a difficult thing for me to admit, but I think Firefox 3 is better than Internet Explorer 7.  Having worked on the IE team, I am the first one to defend it, apologize for it, and staunchly refuse to use anything else.  So how could this have happened?&lt;br /&gt;&lt;br /&gt;Well, the product &lt;a href="http://www.piclens.com/"&gt;I work on now&lt;/a&gt; is a plug-in for both Firefox and IE.  Since I am primarily responsible for the IE version, and I do most of my development and debugging of our product when it is running inside IE.  As a result I am forced to use Firefox to read e-mail and such while my IE install is in a bad state.  &lt;br /&gt;&lt;br /&gt;Firefox 2 was usable, but I liked IE much better still.  A lot of really good UI work went into IE 7 around the Tab UI and optimizing away the old menu bar.  Sure, it has its faults and quirks, but I still felt more at home in IE.&lt;br /&gt;&lt;br /&gt;Now that Firefox 3 is out, I basically have been converted without even thinking about it.  And that's the key: when I use Firefox 3, I don't notice that it isn't IE.  The only time I notice it's Firefox is when it does something better than IE, like spell checking my edit boxes, or remembering the URLs from my last session.  &lt;br /&gt;&lt;br /&gt;It's the little things that matter.&lt;br /&gt;&lt;br /&gt;When I use IE now, it feels slow and poorly put together.  Firefox is snappy; the UI is more polished.  They stole some ideas from IE (The Gold Bar) and made them better.  They have some ideas of their own (disjoint search term matching in autocomplete) that are great, too.&lt;br /&gt;&lt;br /&gt;And as a good friend of mine used to say, "if it ain't snappy, it's crappy."  &lt;br /&gt;&lt;br /&gt;So Firefox 3 sets a high bar for the IE team to meet.  I sincerely hope they blow it away.  I think it is way too early to judge the IE8 UI; I will just have to wait and see how it shapes up.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5377233936486388397-8854972279691822361?l=jeffcode.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://jeffcode.blogspot.com/feeds/8854972279691822361/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5377233936486388397&amp;postID=8854972279691822361' title='6 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5377233936486388397/posts/default/8854972279691822361'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5377233936486388397/posts/default/8854972279691822361'/><link rel='alternate' type='text/html' href='http://jeffcode.blogspot.com/2008/07/firefox-3-better-than-internet-explorer.html' title='firefox 3: better than internet explorer 7'/><author><name>jeffdav</name><uri>http://www.blogger.com/profile/14865307340669462204</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>6</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5377233936486388397.post-3528743515325179465</id><published>2008-06-22T08:54:00.000-07:00</published><updated>2008-06-22T09:07:11.646-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='internet explorer'/><category scheme='http://www.blogger.com/atom/ns#' term='extensions'/><category scheme='http://www.blogger.com/atom/ns#' term='bho'/><category scheme='http://www.blogger.com/atom/ns#' term='iobjectwithsite'/><category scheme='http://www.blogger.com/atom/ns#' term='activex'/><title type='text'>your bho and your activex control can't be the same object</title><content type='html'>Frequently I see people writing a BHO, and at some point they realize they need to make a way for a webpage to call some function implemented by the BHO.  The best way to do this is to expose an ActiveX control.  The most common mistake I see is trying to make the ActiveX control be the same C++ object as the BHO.&lt;br /&gt;&lt;br /&gt;This is wrong for several reasons.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;It violates good coding practice.&lt;/strong&gt;  &lt;br /&gt;&lt;br /&gt;The whole point of object level encapsulation is that each object does one thing.  If your BHO is your ActiveX control, now it does two things.  It may seem at first that you're really just adding a new method to your BHO, but you have to take into account all that goes along with being an ActiveX control.  Implementing IDispatch, loading and dealing with the type library, implementing IObjectSafety, etc.  &lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Your site will be wrong.&lt;/strong&gt;  &lt;br /&gt;&lt;br /&gt;Pretty much every IE extension type--toolbands, BHOs, toolbar buttons, ActiveX controls--implements IObjectWithSite.  If you make one object be two different types of extension, they will share IObjectWithSite implementations.  And they all have a different IE object that is their site.  &lt;br /&gt;&lt;br /&gt;For example, a toolbar button's site will be an object in IE's toolbar code.  A BHO's site is a completely different object in ieframe.dll that knows how to create and interact with a BHO.  Explorer bars are sited to an object in ieframe.dll that hosts an explorer bar.  And ActiveX controls are sited to an object in mshtml.dll that knows how to host ActiveX controls and implements several DOM interfaces (IHTMLElement, etc) as well.  &lt;br /&gt;&lt;br /&gt;So if you make your BHO and your ActiveX control the same object, the BHO will be instantiated first and IE will call your IObjectWithSite::SetSite() method with a pointer to one type of object.  Then, when your ActiveX control is created later on, IE will call the IObjectWithSite::SetSite() method again, but this time with a different internal IE object's address.  Now your BHO is broken.  And debugging this sort of thing may take you a long time.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;What we Learned Today&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;Every IE extension you implement must be it's own object, or bad things will start to happen.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5377233936486388397-3528743515325179465?l=jeffcode.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://jeffcode.blogspot.com/feeds/3528743515325179465/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5377233936486388397&amp;postID=3528743515325179465' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5377233936486388397/posts/default/3528743515325179465'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5377233936486388397/posts/default/3528743515325179465'/><link rel='alternate' type='text/html' href='http://jeffcode.blogspot.com/2008/06/your-bho-and-your-activex-control-cant.html' title='your bho and your activex control can&apos;t be the same object'/><author><name>jeffdav</name><uri>http://www.blogger.com/profile/14865307340669462204</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5377233936486388397.post-4202785746462312515</id><published>2008-06-21T10:57:00.000-07:00</published><updated>2008-06-21T11:07:54.436-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='internet explorer'/><category scheme='http://www.blogger.com/atom/ns#' term='extensions'/><category scheme='http://www.blogger.com/atom/ns#' term='COM'/><title type='text'>the internet explorer object cookbook</title><content type='html'>When you start writing Internet Explorer extensions, or dealing with the DOM and the Webbrowser control at all, you frequently find you have an object of type X and you need to get the corresponding object of type Y.  There is a lot of myth and bad advice on the web surrounding how to do some of these things.  &lt;br /&gt;&lt;br /&gt;The "site" in all of the following refer to the IUnknown you are given by Internet Explorer when it calls your IObjectWithSite::SetSite() method.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;IWebBrowser2 from site&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;1. QueryInterface() your site for IID_IServiceProvider.&lt;br /&gt;2. QueryService() the IServiceProvider for SID_STopLevelBrowser, IID_IServiceProvider.&lt;br /&gt;3. QueryService() the top level IServiceProvider for SID_SWebBrowserApp, IID_IWebBrowser2.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;IHTMLDocument2 from IWebBrowser2&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;1. Call IWebBrowser2::get_Document().&lt;br /&gt;2. QueryInterface() the resulting IDispatch pointer for IID_IHTMLDocument2.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;IHTMLDocument2 from site&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;1. Follow steps for "IWebBrowser2 from site" above.&lt;br /&gt;2. Follow steps for "IHTMLDocument2 from IWebBrowser2" above.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;IWebBrowser2 from IHTMLDocument2&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;1. QueryInterface() the IHTMLDocument2 for IID_IServiceProvider.&lt;br /&gt;2. QueryService() the IServiceProvider for SID_SWebBrowserApp, IID_IWebBrowser2.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;IHTMLDocument2 from IHTMLElement&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;1. Call IHTMLElement::get_Document();&lt;br /&gt;2. QueryInterface() the resulting IDispatch pointer for IID_IHTMLDocument2.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;IHTMLDocument2 from HWND&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;1. Use the accessibility hack described at &lt;a href="http://support.microsoft.com/kb/q249232/"&gt;here&lt;/a&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5377233936486388397-4202785746462312515?l=jeffcode.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://jeffcode.blogspot.com/feeds/4202785746462312515/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5377233936486388397&amp;postID=4202785746462312515' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5377233936486388397/posts/default/4202785746462312515'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5377233936486388397/posts/default/4202785746462312515'/><link rel='alternate' type='text/html' href='http://jeffcode.blogspot.com/2008/06/internet-explorer-object-cookbook.html' title='the internet explorer object cookbook'/><author><name>jeffdav</name><uri>http://www.blogger.com/profile/14865307340669462204</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5377233936486388397.post-2087205582118426755</id><published>2008-06-02T08:38:00.001-07:00</published><updated>2008-06-02T09:26:12.102-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='wired'/><category scheme='http://www.blogger.com/atom/ns#' term='pc'/><category scheme='http://www.blogger.com/atom/ns#' term='mac'/><category scheme='http://www.blogger.com/atom/ns#' term='GPU'/><category scheme='http://www.blogger.com/atom/ns#' term='piclens'/><category scheme='http://www.blogger.com/atom/ns#' term='eco-system'/><title type='text'>the freedom to choose includes the freedom to choose poorly</title><content type='html'>No, I am not going to talk about democrotics and our current and upcoming elected officials. I am going to talk about the consumer computer eco-system. &lt;br /&gt;&lt;br /&gt;When I was doing IT consulting work during collage, there were a few major players in the PC world: Dell, HP, Compaq and Gateway. They all had their ups and downs with their products. Usually one would be good while the other was making boxes with problems, but then it would switch. Our job was to keep up on who was making good boxes at the time and sell them to our customers. However, we all knew the best machines were machines you built yourself. And we enjoyed building them. So when friends and family would ask me what computer they should buy, I would mention who I though was making a good model, but I would also offer to build them one that was better for cheaper.&lt;br /&gt;&lt;br /&gt;When I worked at MSFT, we all had Dell workstations. I would say about 90% of all Windows development took place on Dell machines with Intel Processors. So when friends and family would ask for a computer recommendation, I would point them at Dell. Of course, I no longer had time to build them a machine, though I still built my own from scratch.&lt;br /&gt;&lt;br /&gt;Now that I work on PicLens, I have to write code that supports Firefox, Internet Explorer and Safari on both Mac and Windows. We have subsystems that run on top of OpenGL, DirectX, and a software rendered that works in two different modes, depending on which we detect would give better support on a specific system. &lt;br /&gt;&lt;br /&gt;Yet we still get a fair number of people who send in e-mail with reports of graphics issues. Some are minor glitches, some are major glitches that make the product unusable. A very small number are blue screens. We take all customer feedback seriously and follow up with them asking about their configuration, etc. Almost all of them have one thing in common: non-premium graphics cards, by which I mean a card that is not a high end ATI or NVidia card.&lt;br /&gt;&lt;br /&gt;I am coming to the part where I get to the point.&lt;br /&gt;&lt;br /&gt;These days, when friends and family ask me what computer they should get, I think I will start telling them to get a Mac. &lt;br /&gt;&lt;br /&gt;Let me be clear, I still hate Macs. With a passion. I have to use one at work, and I remain unconverted. But what they do is take away the freedom to choose poorly. &lt;br /&gt;&lt;br /&gt;Let me explain:&lt;br /&gt;&lt;br /&gt;With a PC, you never know what you are going to get. And even people who build there own machines often make decisions based on price point, not quality. Not to mention people who build their own machines but do not really understand how hardware and software drivers work. &lt;br /&gt;&lt;br /&gt;With a Mac, you always get good hardware. They all have Intel processors. They all have NVidia or ATI graphics cards, with drivers that are known to work. Sure, Microsoft can certify drivers, but they can not test them in every possible configuration of PC hardware. But Apple can test every configuration. Because they only have tens of possibilities instead of thousands. &lt;br /&gt;&lt;br /&gt;Nothing has really changed since I was in IT consulting. The trade-offs are still the same: build your own, buy an OEM and roll the dice, or pay a bunch more for a Mac that you can only do so much with but at least it will work. All that has changed is my point of view. &lt;br /&gt;&lt;br /&gt;As an idealistic youth, I wanted everyone to get the most from their computing experience. I wanted to educate them about the machines and the software. At Microsoft I just wanted them to leave me alone and figure it out for themselves. Now I just can not be bothered by it at all. Macs work. They stop you from shooting yourself in the foot. And hey, if people think it makes them look cool, then even better.&lt;br /&gt;&lt;br /&gt;I will still be building my own machines. My house is all Asus all the time. It is amazing, but I have never had any problems with Asus video cards in Asus mother boards. I prefer NVidia (though it is not a logical or rational preference). I only buy Intel Processors(but that is a completely separate discussion) and Seagate hard drives (though I will accept Western Digital and I really wish there was a quality third player). &lt;br /&gt;&lt;br /&gt;Everyone else should get a Mac. It makes my life easier in the short term, since I do not have to do any support. Though, I guess if everyone got a Mac I would have to do ALL my development on a Mac. And I would miss Visual Studio and NTSD.&lt;br /&gt;&lt;br /&gt;So, I guess the moral of the story is when choosing a video card, choose wisely. &lt;em&gt;Caveat emptor&lt;/em&gt; and all that. Or, spend more than $20 on a video card.&lt;br /&gt;&lt;br /&gt;See also: &lt;a href="http://www.wired.com/gadgets/displays/news/2008/06/gpu"&gt;Wired: Graphics Chips Gun for Supremacy in Silicon Showdown&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5377233936486388397-2087205582118426755?l=jeffcode.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://jeffcode.blogspot.com/feeds/2087205582118426755/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5377233936486388397&amp;postID=2087205582118426755' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5377233936486388397/posts/default/2087205582118426755'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5377233936486388397/posts/default/2087205582118426755'/><link rel='alternate' type='text/html' href='http://jeffcode.blogspot.com/2008/06/freedom-to-choose-includes-freedom-to.html' title='the freedom to choose includes the freedom to choose poorly'/><author><name>jeffdav</name><uri>http://www.blogger.com/profile/14865307340669462204</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5377233936486388397.post-8416594680540441867</id><published>2008-05-31T09:16:00.000-07:00</published><updated>2008-05-31T09:26:02.566-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='caching'/><category scheme='http://www.blogger.com/atom/ns#' term='temporary internet files'/><category scheme='http://www.blogger.com/atom/ns#' term='internet explorer'/><title type='text'>the TIF really is a cache -- and it acts like one</title><content type='html'>It seems obvious, but I guess it has to be said. Internet Explorer's Temporary Internet Files folder is a cache. From Wikipedia: &lt;em&gt;a cache is a temporary storage area where frequently accessed data can be stored for rapid access&lt;/em&gt;. Please note the use of the word &lt;em&gt;temporary&lt;/em&gt;. This means that the data you want may not actually be there. &lt;br /&gt;&lt;br /&gt;I frequently see questions along the lines of "How can I find this image/page in the cache?" or, even better, "How come this page I viewed isn't in the cache?" I love it when the askers of the latter form imply that this is a bug.&lt;br /&gt;&lt;br /&gt;Files in the cache can be deleted at anytime. You can be looking at a page and then go to the cache and find it isn't there. There are many scenarios where this is legitimate. For example, if, while you are viewing this page, you go to Tools-&gt;Delete Browsing History and then clear your Temporary Internet Files, the only representation that IE will have of this page and all of its elements is the one in memory. Close the browser and that memory is freed and now its gone until you download it from the webserver again.&lt;br /&gt;&lt;br /&gt;The page you are viewing may use the no-cache http header. The cache manager may have decided its time to scavenge. There may have even been an error writing to the cache and the cache has become corrupt.&lt;br /&gt;&lt;br /&gt;I am sure there are other scenarios as well. The point is, you cannot rely on data to always be there. You must either capture the data in some other way, or be prepared to make a request to the server.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5377233936486388397-8416594680540441867?l=jeffcode.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://jeffcode.blogspot.com/feeds/8416594680540441867/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5377233936486388397&amp;postID=8416594680540441867' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5377233936486388397/posts/default/8416594680540441867'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5377233936486388397/posts/default/8416594680540441867'/><link rel='alternate' type='text/html' href='http://jeffcode.blogspot.com/2008/05/tif-really-is-cache-and-it-acts-like.html' title='the TIF really is a cache -- and it acts like one'/><author><name>jeffdav</name><uri>http://www.blogger.com/profile/14865307340669462204</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5377233936486388397.post-9010629926597189884</id><published>2008-05-29T09:39:00.000-07:00</published><updated>2008-05-29T09:52:11.548-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='internet explorer'/><category scheme='http://www.blogger.com/atom/ns#' term='development'/><category scheme='http://www.blogger.com/atom/ns#' term='spyware'/><title type='text'>to help or not to help</title><content type='html'>More and more I am confronted with a sort of moral dilemma.  I read and post to the &lt;a href="http://forums.microsoft.com/MSDN/default.aspx?ForumGroupID=253&amp;SiteID=1"&gt;IE development forums&lt;/a&gt; over at MSDN.  Frequently I see posts like this:&lt;br /&gt;&lt;br /&gt;&lt;div style="background-color:#ffffff;color:#227722;border:1px solid orange; padding:2px 2px 2px 2px;font-family:courier new;font-size:12px;"&gt;i want a BHO which continuously observe IE activity and send the URLs visited and time of visit and time of outfocus of them as soon as they are available,to listening java servlet. Now Please suggest me how to do this,perticularly this sending of url and their time details to java servlet.&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;He does not ask for help with a specific problem or bug he has encountered in the process.  He does not tell us what he has done or post a sample of code he can not get to work.  He simply asks, "how do I do this?"  His masterful command of English does not help his case.&lt;br /&gt;&lt;br /&gt;This guy is probably up to no good.&lt;br /&gt;&lt;br /&gt;I can only think of one semi-legit use for such a thing, which would be for employers or parents to spy on their employees or children.  And I'm not sure I can even get behind that.&lt;br /&gt;&lt;br /&gt;So my dilemma becomes, do I help this guy?  Do I tell him what to do?  On the one hand, I do not want to be enabling spyware makers in anyway.  On the other hand, if someone is paying him to do this thing, he is going to write the program whether I help him or not.  Given that, is it better to make sure he does it right?  I mean, which is better, crashing spyware or non-crashing spyware?  &lt;br /&gt;&lt;br /&gt;Anyway, today I am not helping this guy.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5377233936486388397-9010629926597189884?l=jeffcode.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://jeffcode.blogspot.com/feeds/9010629926597189884/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5377233936486388397&amp;postID=9010629926597189884' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5377233936486388397/posts/default/9010629926597189884'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5377233936486388397/posts/default/9010629926597189884'/><link rel='alternate' type='text/html' href='http://jeffcode.blogspot.com/2008/05/to-help-or-not-to-help.html' title='to help or not to help'/><author><name>jeffdav</name><uri>http://www.blogger.com/profile/14865307340669462204</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5377233936486388397.post-7474888261670038477</id><published>2008-04-15T11:26:00.001-07:00</published><updated>2008-04-15T11:31:18.579-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='video'/><category scheme='http://www.blogger.com/atom/ns#' term='cooliris'/><category scheme='http://www.blogger.com/atom/ns#' term='piclens'/><title type='text'>PicLens 1.6.3 Released</title><content type='html'>We released 1.6.3 yesterday to &lt;a href="http://www.piclens.com"&gt;piclens.com&lt;/a&gt;.  Why the change from 1.6.2 to 1.6.3?  Because we now support &lt;em&gt;video&lt;/em&gt; in the Wall.  &lt;br /&gt;&lt;br /&gt;&lt;a href="http://1.bp.blogspot.com/_d_Sh9p8ja6w/SAT0MxN_iTI/AAAAAAAAACk/YFnmzDDGmBU/s1600-h/video-ss.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;" src="http://1.bp.blogspot.com/_d_Sh9p8ja6w/SAT0MxN_iTI/AAAAAAAAACk/YFnmzDDGmBU/s320/video-ss.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5189541170845288754" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;You can search YouTube and watch the videos right in the wall.  During development we spent a lot of time watching videos... it can be very addictive.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5377233936486388397-7474888261670038477?l=jeffcode.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://jeffcode.blogspot.com/feeds/7474888261670038477/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5377233936486388397&amp;postID=7474888261670038477' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5377233936486388397/posts/default/7474888261670038477'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5377233936486388397/posts/default/7474888261670038477'/><link rel='alternate' type='text/html' href='http://jeffcode.blogspot.com/2008/04/piclens-163-released.html' title='PicLens 1.6.3 Released'/><author><name>jeffdav</name><uri>http://www.blogger.com/profile/14865307340669462204</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/_d_Sh9p8ja6w/SAT0MxN_iTI/AAAAAAAAACk/YFnmzDDGmBU/s72-c/video-ss.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5377233936486388397.post-4909736330323370151</id><published>2008-03-20T10:25:00.000-07:00</published><updated>2008-03-20T10:59:52.751-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='iPhone'/><title type='text'>I can't stand it anymore, I have to say it</title><content type='html'>I love my iPhone.&lt;br /&gt;&lt;br /&gt;There, I said it.  I feel dirty.&lt;br /&gt;&lt;br /&gt;My Windows-based SmartPhone got crushed in an under-the-motorized-car-seat retrieval operation that went horribly awry.  Faced with a rapidly diminishing usable space on the cracked LCD screen, I went to the AT&amp;T store to get the new hotness.&lt;br /&gt;&lt;br /&gt;I suspected I wanted an iPhone.  I didn't want to pay a lot for a phone, but what can you do?  I carefully considered each and every phone they had and compared it to the iPhone.  The results fell into one of two catagories:&lt;br /&gt;&lt;br /&gt;1) This phone is complete crap and they have the nerve to charge [$100..$200] for it.&lt;br /&gt;2) This phone isn't an iPhone, but costs just as much.&lt;br /&gt;&lt;br /&gt;So I bought the iPhone.&lt;br /&gt;&lt;br /&gt;The installation experience was harrowing.  I found out you have to activate it through iTunes.  I hate iTunes.  I hate QuickTime.  I hate all Apple software.  I hate all third party software.  I don't like the way it infects my machine with little processes that run without asking and little icons littered about the desktop and quicklaunch and systray.  I hates it all.&lt;br /&gt;&lt;br /&gt;But my wife has an iPod, so it was already installed.  What can you do?&lt;br /&gt;&lt;br /&gt;However, I had to upgrade to the latest version of iTunes.  So I fired up IE and went to apple.com.  Halfway through the download, IE crashed. &lt;br /&gt;&lt;br /&gt;So I used FireFox to download iTunes.&lt;br /&gt;&lt;br /&gt;As a developer who used to work on Internet Explorer, you have no idea how much that hurt me.  It was a sad, sad day.  Snow flakes were reported in Hell.  &lt;br /&gt;&lt;br /&gt;But now I have the iPhone and it's the best phone ever and probably the best UI for anything other than &lt;a href="http://www.piclens.com"&gt;PicLens&lt;/a&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5377233936486388397-4909736330323370151?l=jeffcode.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://jeffcode.blogspot.com/feeds/4909736330323370151/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5377233936486388397&amp;postID=4909736330323370151' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5377233936486388397/posts/default/4909736330323370151'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5377233936486388397/posts/default/4909736330323370151'/><link rel='alternate' type='text/html' href='http://jeffcode.blogspot.com/2008/03/i-cant-stand-it-anymore-i-have-to-say.html' title='I can&apos;t stand it anymore, I have to say it'/><author><name>jeffdav</name><uri>http://www.blogger.com/profile/14865307340669462204</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5377233936486388397.post-5978405141390452229</id><published>2008-03-14T10:13:00.000-07:00</published><updated>2008-03-14T10:16:02.141-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='wikitalk'/><title type='text'>WikiTalk redesign</title><content type='html'>My previous project, &lt;a href="http://www.wikitalk.com"&gt;WikiTalk&lt;/a&gt;, has just undergone a major face lift this morning. I didn't know it was coming and was quite shocked to see it when I loaded it before work this morning.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.wikitalk.com"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;" src="http://2.bp.blogspot.com/_d_Sh9p8ja6w/R9qyZzUCr5I/AAAAAAAAACM/Cu6xvz7eWjw/s320/wikitalk.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5177646877956550546" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Congratulations guys. It looks really good.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5377233936486388397-5978405141390452229?l=jeffcode.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://jeffcode.blogspot.com/feeds/5978405141390452229/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5377233936486388397&amp;postID=5978405141390452229' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5377233936486388397/posts/default/5978405141390452229'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5377233936486388397/posts/default/5978405141390452229'/><link rel='alternate' type='text/html' href='http://jeffcode.blogspot.com/2008/03/wikitalk-redesign.html' title='WikiTalk redesign'/><author><name>jeffdav</name><uri>http://www.blogger.com/profile/14865307340669462204</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/_d_Sh9p8ja6w/R9qyZzUCr5I/AAAAAAAAACM/Cu6xvz7eWjw/s72-c/wikitalk.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5377233936486388397.post-5514871186872362139</id><published>2008-03-09T12:56:00.001-07:00</published><updated>2008-03-09T13:00:59.440-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='new york times'/><category scheme='http://www.blogger.com/atom/ns#' term='cooliris'/><category scheme='http://www.blogger.com/atom/ns#' term='slashdot'/><category scheme='http://www.blogger.com/atom/ns#' term='piclens'/><title type='text'>PicLens: new version and news round-up</title><content type='html'>We worked hard all week, some team members staying awake for inadvisably long periods of time, to bring you all our latest work: &lt;a href="http://www.piclens.com/"&gt;PicLens 1.6.2&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;This new version fixes many performance and stability issues, and most notably, improves graphics support for a significant number of people who may have had issues with previous versions of PicLens.  We added Direct3D 9 support when running on Windows.  This means you must have Windows XP Service Pack 2 (or the DX9 redist) installed or you will be running with a software renderer.  &lt;br /&gt;&lt;br /&gt;In the news, the &lt;a href="http://www.nytimes.com/2008/03/09/business/09stream.html?_r=1&amp;oref=slogin"&gt;New York Times has an article&lt;/a&gt; on PicLens and the future of web browsing.  And we've been &lt;a href="http://slashdot.org/article.pl?no_d2=1&amp;sid=08/03/09/1323243"&gt;slashdotted&lt;/a&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5377233936486388397-5514871186872362139?l=jeffcode.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://jeffcode.blogspot.com/feeds/5514871186872362139/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5377233936486388397&amp;postID=5514871186872362139' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5377233936486388397/posts/default/5514871186872362139'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5377233936486388397/posts/default/5514871186872362139'/><link rel='alternate' type='text/html' href='http://jeffcode.blogspot.com/2008/03/piclens-new-version-and-news-round-up.html' title='PicLens: new version and news round-up'/><author><name>jeffdav</name><uri>http://www.blogger.com/profile/14865307340669462204</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5377233936486388397.post-7795110733423759585</id><published>2008-02-19T22:52:00.001-08:00</published><updated>2008-02-19T23:43:26.481-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='internet explorer'/><category scheme='http://www.blogger.com/atom/ns#' term='jscript'/><category scheme='http://www.blogger.com/atom/ns#' term='OLE'/><category scheme='http://www.blogger.com/atom/ns#' term='COM'/><category scheme='http://www.blogger.com/atom/ns#' term='events'/><category scheme='http://www.blogger.com/atom/ns#' term='activex'/><title type='text'>how to create an activex control that fires events to javascript (without using ATL)</title><content type='html'>&lt;strong&gt;Creating ActiveX Controls that Fire Events (without ATL)&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;I recently spent a fair bit of time at work figuring out how to write all the COM and OLE goo to make this work. There are lots of articles that tell you how to use ATL, but I am against ATL and I wanted to do it the old fashioned way. Here is a summary of what I learned.&lt;br /&gt;&lt;br /&gt;The scenario was this: I wanted to have an ActiveX control that would download some file on a worker thread, then fire events that could be handled by JScript before, during and after the download. The general outline would look like this:&lt;br /&gt;&lt;br /&gt;1. Page loads, control instantiated via object tag.&lt;br /&gt;2. JScript calls attachEvent() to setup event handlers for the control.&lt;br /&gt;3. JScript calls a method to start download.&lt;br /&gt;4. Control spins up a worker thread which calls URLDownloadToFile().&lt;br /&gt;5. The worker thread receives progress notifications via IBindStatusCallback(). Control fires events to JScript (from the worker thread) to inform JScript of progress.&lt;br /&gt;6. Download completes, worker thread fires event to JScript.&lt;br /&gt;&lt;br /&gt;I will call my control the Downloader and his CLSID is CLSID_DownloaderCtrl.&lt;br /&gt;&lt;br /&gt;To make this happen your control must implement (and respond to in IUnknown::QueryInterface()):&lt;br /&gt;&lt;br /&gt;1. IUnknown&lt;br /&gt;2. IDispatch&lt;br /&gt;3. IProvideClassInfo, IProvideClassInfo2&lt;br /&gt;4. IObjectWithSite&lt;br /&gt;5. IConnectionPointContainer&lt;br /&gt;6. IDownloader (this is the dual interface for scripts to call methods the control exposes)&lt;br /&gt;7. IObjectSafety&lt;br /&gt;8. IServiceProvider (for URLDownloadToFile() to work properly)&lt;br /&gt;9. IBindStatusCallback (optional -- only if you want download progess)&lt;br /&gt;&lt;br /&gt;You will also need to implement IConnectionPoint, but do not repsond to it in QueryInterface. More on this later.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;IUnknown&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;I assume you know how to implement IUnknown. Read Raymond's post on &lt;a href="http://blogs.msdn.com/oldnewthing/archive/2004/03/26/96777.aspx"&gt;getting it wrong&lt;/a&gt; to make sure you know how to implement it.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Type Libraries&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;Before we can do much more we need a type library. To get this working, you have to create an .idl file that contains definitions. There are four important parts. Each one has its own GUID. They are specified in the .idl and MIDL will generate a header file and c file that defines them.&lt;br /&gt;&lt;br /&gt;1. The outgoing event (disp)interface. DIID_DDownloaderEvents&lt;br /&gt;2. The incoming (dual) interface. IID_IDownloader&lt;br /&gt;3. The coclass goo. CLSID_DownloaderCtrl&lt;br /&gt;4. The library. LIBID_Downloader&lt;br /&gt;&lt;br /&gt;Your .idl should look something like this:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;[&lt;br /&gt;    uuid(00000000-0000-0000-0000-000000000000),&lt;br /&gt;    version(1.0)&lt;br /&gt;]&lt;br /&gt;library Downloader&lt;br /&gt;{&lt;br /&gt;    [&lt;br /&gt;        uuid(11111111-1111-1111-1111-111111111111), &lt;br /&gt;        hidden&lt;br /&gt;    ]&lt;br /&gt;    dispinterface DDownloaderEvents&lt;br /&gt;    {&lt;br /&gt;        properties: &lt;br /&gt;        methods:&lt;br /&gt;        [id(DISPID_PROGRESS)] void Progress();&lt;br /&gt;        [id(DISPID_COMPLETE)] void Complete();&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    [&lt;br /&gt;        dual,&lt;br /&gt;        uuid(22222222-2222-2222-2222-222222222222)&lt;br /&gt;    ]&lt;br /&gt;    interface IDownloader : IDispatch&lt;br /&gt;    {&lt;br /&gt;        [id(DISPID_DOWNLOAD)] HRESULT download(BSTR bstrFile);&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    [&lt;br /&gt;        uuid(33333333-3333-3333-3333-333333333333)&lt;br /&gt;    ]&lt;br /&gt;    coclass DownloaderCtrl&lt;br /&gt;    {&lt;br /&gt;        [default] interface IDownloader;&lt;br /&gt;        [source, default] dispinterface DDownloaderEvents;&lt;br /&gt;    }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;MIDL will generate a .tlb file from this. You must include this type library as a resource in your .dll. To do that, add a line like the following:&lt;br /&gt;&lt;br /&gt;1 TYPELIB "downloader.tlb"&lt;br /&gt;&lt;br /&gt;Now you can call LoadTypeLib() using your module's path to get the type library, which you will need to use in your IDispatch implementation.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;IDispatch&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;I am going to assume you know mostly know how to implement this as well. It is well documented. The important thing is to make sure you expose your typelib correctly.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;IProvideClassInfo, IProvideClassInfo2&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;These are pretty straight-forward.  In GetGUID() return your outgoing event interface, DIID_DDownloaderEvents. &lt;br /&gt;&lt;br /&gt;The only tricky part is in GetClassInfo.  You should call LoadTypeLib() then call ITypeLib-&gt;GetTypeInfoOfGuid().  The question is, which GUID do you use?  The correct answer is CLSID_DownloaderCtrl.  This gets the type info of your coclass, which Internet Explorer can use to figure out what your outgoing event interface is.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;IConnectionPointContainer&lt;/strong&gt;&lt;br /&gt;&lt;strong&gt;&lt;/strong&gt;&lt;br /&gt;When you call attachEvent() in JScript, IE will ask for this interface to try to find a connection point for your outgoing event interface.  You have to implement FindConnectionPoint().  I found EnumConnectionPoints() and to not be called by Internet Explorer.  However, you may experience different results here.  Set breakpoints and/or use asserts() to make sure anything you E_NOTIMPL isn't called, otherwise you may find yourself debugging into the wee hours.&lt;br /&gt;&lt;strong&gt;&lt;/strong&gt;&lt;br /&gt;&lt;strong&gt;IConnectionPoint&lt;/strong&gt;&lt;br /&gt;&lt;strong&gt;&lt;/strong&gt;&lt;br /&gt;FindConnectionPoint() gives out a pointer to an IConnectionPoint, which should really be a different object than your IConnectionPointContainer.  See the documentation.  We don't respond to IConnectionPoint in QueryInterface, since the only allowed way of getting it is via FindConnectionPoint(). &lt;br /&gt;&lt;br /&gt;You have to implement Advise() and Unadvise().  The remaining methods were never called for my implementation.  However, as above, your milage may vary.  Everytime IE calls Advise(), it will pass you an IUnknown.  QueryInterface() for IID_IDispatch and remember that pointer.  Make sure you associate it with the cookie you give back (std::map is one option, if you go in for that sort of thing).&lt;br /&gt;&lt;br /&gt;When you want to fire your event, simply call the Invoke() member of all the IDispatch pointers you are holding on to, passing whatever parameters you want and the DISPID of whatever event you want to send.&lt;br /&gt;&lt;br /&gt;Important: Before you use this pointer, read the bit about marshalling below.&lt;br /&gt;&lt;strong&gt;&lt;/strong&gt;&lt;br /&gt;&lt;strong&gt;IObjectWithSite&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;This is simple as well.  Make sure you respond to SetSite(NULL) by releasing all the pointers you acquired from your site.  Also, this is your queue that your control is going away soon.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;IServiceProvider&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;All you have to do here is QueryInterface your site for IServiceProvider and thunk the call to QueryService() through to your site's implementation.  If you're using the Vista SDK, you can use IUnknown_QueryService(). &lt;br /&gt;&lt;br /&gt;If you don't implement this, URLDownloadToFile() may not be able to get access to certain security information and your life will be harder.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;IObjectSafety&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;You should implement this to make instantiating your control easier and safer.  Refer to the documentation and plentiful on-line examples.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;A Word on Marshalling&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;My object operates on two threads--the IE Tab thread that it is created on, and a worker thread that does the heavy lifting.  The point of using a worker thread is to not hang the UI while the download happens.  This gives a nice experience, but makes implementation harder.&lt;br /&gt;&lt;br /&gt;The one thing to remember, is all of IE's interaction with your object will happen on it's thread.  You will receive IDispatch pointers on this thread.  You cannot use these pointers in a different apartment (which means, you cannot use them on the worker thread). &lt;br /&gt;&lt;br /&gt;In order to fire events from the worker thread, you must marshal the IDispatch pointers.  You have two options for doing this:&lt;br /&gt;&lt;br /&gt;1) Call CoMarshalInterThreadInterfaceInStream() on the IE thread, then CoGetInterfaceAndReleaseStream() on the worker thread.  Do this for every IDispatch pointer and use the pointer returned on the worker thread. &lt;br /&gt;2) Use the GIT (Global Interface Table).  You're on your own with that one -- see the documentation.&lt;br /&gt;&lt;br /&gt;If you try to use the pointer on the wrong thread, your Invoke() call will fail silently and the event will not be fired.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Setting up the JScript&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;1. Create your object using the object tag.  You cannot use new ActiveXObject() because IE will not hook-up the events for you. &lt;br /&gt;2. Give your object tag and ID, such as ID="downloader". &lt;br /&gt;3. In the onLoad handler for the body element, call a function that uses the ID to attach the event handlers to events.  E.g., downloader.attachEvent('Progress', onProgressEvent).  Then simply implement the onProgressEvent() in JScript in the script section of your HTML.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Conclusion&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;Well, I hope that helps someone.  If you have anything to add, please leave a comment.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5377233936486388397-7795110733423759585?l=jeffcode.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://jeffcode.blogspot.com/feeds/7795110733423759585/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5377233936486388397&amp;postID=7795110733423759585' title='5 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5377233936486388397/posts/default/7795110733423759585'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5377233936486388397/posts/default/7795110733423759585'/><link rel='alternate' type='text/html' href='http://jeffcode.blogspot.com/2008/02/how-to-create-activex-control-that.html' title='how to create an activex control that fires events to javascript (without using ATL)'/><author><name>jeffdav</name><uri>http://www.blogger.com/profile/14865307340669462204</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>5</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5377233936486388397.post-5090835349197320557</id><published>2008-02-15T10:47:00.000-08:00</published><updated>2008-02-15T10:55:02.149-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='piclens'/><title type='text'>New build of PicLens for Internet Explorer</title><content type='html'>We posted a new build of PicLens for Internet Explorer yesterday to &lt;a href="http://www.piclens.com"&gt;PicLens.com&lt;/a&gt;.  It does not add any features, but does contain several performance and stability improvements. &lt;br /&gt;&lt;br /&gt;If you have PicLens for Internet Explorer (or even if you don't have it yet!) you should be sure to upgrade to this latest version.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5377233936486388397-5090835349197320557?l=jeffcode.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://jeffcode.blogspot.com/feeds/5090835349197320557/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5377233936486388397&amp;postID=5090835349197320557' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5377233936486388397/posts/default/5090835349197320557'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5377233936486388397/posts/default/5090835349197320557'/><link rel='alternate' type='text/html' href='http://jeffcode.blogspot.com/2008/02/new-build-of-piclens-for-internet.html' title='New build of PicLens for Internet Explorer'/><author><name>jeffdav</name><uri>http://www.blogger.com/profile/14865307340669462204</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5377233936486388397.post-8069608061082572344</id><published>2008-02-06T12:49:00.001-08:00</published><updated>2008-02-06T13:00:53.861-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='internet explorer'/><category scheme='http://www.blogger.com/atom/ns#' term='cooliris'/><category scheme='http://www.blogger.com/atom/ns#' term='piclens'/><title type='text'>PicLens 1.6.1 for Internet Explorer</title><content type='html'>As promised, we have just released PicLens 1.6.1 for Internet Explorer.  You can download it by visiting &lt;a href="http://www.piclens.com"&gt;http://www.piclens.com&lt;/a&gt;.  &lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.piclens.com"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;" src="http://1.bp.blogspot.com/_d_Sh9p8ja6w/R6odgPc4vqI/AAAAAAAAAB8/pxTZRf_Soi4/s320/piclens-for-ie.jpg" border="0" alt=""id="BLOGGER_PHOTO_ID_5163972362474405538" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;This is what I have been working on for the last month.  It was quite a challenge, and luckily I had a fairly extensive background in Internet Explorer's extensibility model in order to make it happen.  There are huge differences between the way Internet Explorer and FireFox are architected.  For example, in FireFox all tabs run on the same thread.  Since Internet Explorer creates a seperate UI thread for each Tab, I had to write code to demultiplex events coming from the tabs to our single PicLens thread that we create.  This was done by careful use of DHTMLWindowEvents2's OnBlur and OnFocus events, as well as DWebBrowserEvents2's WindowStateChanged event.  Keeping track of which of PicLens' Browser Helper Object instances (IE creates one per tab) was the "active" window was non-trivial, especially since we had to support IE6 and IE7.&lt;br /&gt;&lt;br /&gt;In the end though I think we have a really solid product.  If you notice any bugs or have any feedback, please feel free to leave me a comment or e-mail &lt;a href="mailto:feedback@piclens.com"&gt;feedback@piclens.com&lt;/a&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5377233936486388397-8069608061082572344?l=jeffcode.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://jeffcode.blogspot.com/feeds/8069608061082572344/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5377233936486388397&amp;postID=8069608061082572344' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5377233936486388397/posts/default/8069608061082572344'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5377233936486388397/posts/default/8069608061082572344'/><link rel='alternate' type='text/html' href='http://jeffcode.blogspot.com/2008/02/piclens-161-for-internet-explorer.html' title='PicLens 1.6.1 for Internet Explorer'/><author><name>jeffdav</name><uri>http://www.blogger.com/profile/14865307340669462204</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/_d_Sh9p8ja6w/R6odgPc4vqI/AAAAAAAAAB8/pxTZRf_Soi4/s72-c/piclens-for-ie.jpg' height='72' width='72'/><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5377233936486388397.post-5668313540538100909</id><published>2008-01-29T10:49:00.000-08:00</published><updated>2008-01-29T10:53:54.179-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='firefox'/><category scheme='http://www.blogger.com/atom/ns#' term='cooliris'/><category scheme='http://www.blogger.com/atom/ns#' term='photos'/><category scheme='http://www.blogger.com/atom/ns#' term='piclens'/><category scheme='http://www.blogger.com/atom/ns#' term='1.6'/><title type='text'>PicLens 1.6 for FireFox Released (or what I've been up to)</title><content type='html'>I recently moved from Washington to California to work on PicLens. PicLens is a 3D, hardware accelerated, full-screen photo viewing plug-in. Version 1.6 adds the 3D wall for viewing photos at sites like Google Images, Yahoo Images, Flickr, Facebook, MySpace, xkcd, etc. You can &lt;a href="http://www.piclens.com"&gt;download it for free here&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Here's a marketing screen shot, but that's really what it looks like. &lt;br /&gt;&lt;br /&gt;&lt;a href="http://4.bp.blogspot.com/_d_Sh9p8ja6w/R5919vc4voI/AAAAAAAAABs/B_0Vsccs8Nc/s1600-h/header-piclens16.jpg"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;" src="http://4.bp.blogspot.com/_d_Sh9p8ja6w/R5919vc4voI/AAAAAAAAABs/B_0Vsccs8Nc/s320/header-piclens16.jpg" border="0" alt=""id="BLOGGER_PHOTO_ID_5160973401559973506" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Those of you who are aware that I once worked on the Internet Explorer team at Microsoft might have some insight as to what I'm doing down here. Hint: There will be an IE version very soon.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5377233936486388397-5668313540538100909?l=jeffcode.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://jeffcode.blogspot.com/feeds/5668313540538100909/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5377233936486388397&amp;postID=5668313540538100909' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5377233936486388397/posts/default/5668313540538100909'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5377233936486388397/posts/default/5668313540538100909'/><link rel='alternate' type='text/html' href='http://jeffcode.blogspot.com/2008/01/piclens-16-for-firefox-released-or-what.html' title='PicLens 1.6 for FireFox Released (or what I&apos;ve been up to)'/><author><name>jeffdav</name><uri>http://www.blogger.com/profile/14865307340669462204</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_d_Sh9p8ja6w/R5919vc4voI/AAAAAAAAABs/B_0Vsccs8Nc/s72-c/header-piclens16.jpg' height='72' width='72'/><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5377233936486388397.post-7722384656697387116</id><published>2008-01-06T14:10:00.000-08:00</published><updated>2008-01-06T14:31:16.659-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='dell'/><category scheme='http://www.blogger.com/atom/ns#' term='netflix'/><category scheme='http://www.blogger.com/atom/ns#' term='media center'/><category scheme='http://www.blogger.com/atom/ns#' term='widescreen monitor'/><title type='text'>media center, netflix, monitor rotation and real estate</title><content type='html'>When it comes to building your home PC, different people want different things. Some people want fast processors. Some people want lots of RAM. Some people want bang for the buck. I'm not really concerned with any of that. I use my machine for browsing the web and watching TV shows or movies. I want pixels. Lots and lots of pixels. I want to be able to watching things and browse things at the same time.&lt;br /&gt;&lt;br /&gt;I bought a Dell 2405FPW. The 24" wide screen makes me very happy. My goal is to maximize the use of the real estate this presents. I was watching TV and browsing the web with this goal in mind. Since Media Center (like all good video players) likes to keep it's aspect ratio fixed, I kept ending up arrangements like this:&lt;br /&gt;&lt;br /&gt;&lt;a href="http://1.bp.blogspot.com/_d_Sh9p8ja6w/R4FVUGsdpRI/AAAAAAAAAA0/agHf4TRRZI4/s1600-h/media-center-and-web-browser.jpg"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;" src="http://1.bp.blogspot.com/_d_Sh9p8ja6w/R4FVUGsdpRI/AAAAAAAAAA0/agHf4TRRZI4/s320/media-center-and-web-browser.jpg" border="0" alt=""id="BLOGGER_PHOTO_ID_5152493252571407634" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Notice the big chunk of unused space in the bottom left corner. There was no way to fill this space. Then I hit on the brilliant idea of rotating the monitor to portrait and stacking media center on top of IE. Then I could use every pixel. I was excited. &lt;br /&gt;&lt;br /&gt;But I was thwarted:&lt;br /&gt;&lt;br /&gt;&lt;a href="http://2.bp.blogspot.com/_d_Sh9p8ja6w/R4FVzWsdpSI/AAAAAAAAAA8/kgpSuBJIH-A/s1600-h/media-center-says-no.jpg"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;" src="http://2.bp.blogspot.com/_d_Sh9p8ja6w/R4FVzWsdpSI/AAAAAAAAAA8/kgpSuBJIH-A/s320/media-center-says-no.jpg" border="0" alt=""id="BLOGGER_PHOTO_ID_5152493789442319650" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;I don't know what to say. As a user, my first thought is "there is no excuse for this." As a developer who used to work on Windows, I know there was at least a reason for it. Probably some video card didn't work in this configuration, or it would have been too much testing for a non-critical scenario, or something. But it made me mad.&lt;br /&gt;&lt;br /&gt;Now I have NetFlix though. It has an in-browser player for viewing videos on demand. Now my dreams of real estate maximization can be realized:&lt;br /&gt;&lt;br /&gt;&lt;a href="http://1.bp.blogspot.com/_d_Sh9p8ja6w/R4FWhGsdpTI/AAAAAAAAABE/ZooR2UAjfwQ/s1600-h/netflix-and-webbrowser.jpg"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;" src="http://1.bp.blogspot.com/_d_Sh9p8ja6w/R4FWhGsdpTI/AAAAAAAAABE/ZooR2UAjfwQ/s320/netflix-and-webbrowser.jpg" border="0" alt=""id="BLOGGER_PHOTO_ID_5152494575421334834" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Good bye, Media Center. Good by Cable Television. Hello NetFlix!!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5377233936486388397-7722384656697387116?l=jeffcode.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://jeffcode.blogspot.com/feeds/7722384656697387116/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5377233936486388397&amp;postID=7722384656697387116' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5377233936486388397/posts/default/7722384656697387116'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5377233936486388397/posts/default/7722384656697387116'/><link rel='alternate' type='text/html' href='http://jeffcode.blogspot.com/2008/01/media-center-netflix-monitor-rotation.html' title='media center, netflix, monitor rotation and real estate'/><author><name>jeffdav</name><uri>http://www.blogger.com/profile/14865307340669462204</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/_d_Sh9p8ja6w/R4FVUGsdpRI/AAAAAAAAAA0/agHf4TRRZI4/s72-c/media-center-and-web-browser.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5377233936486388397.post-2968739789191107060</id><published>2008-01-03T10:00:00.000-08:00</published><updated>2008-01-03T10:29:03.029-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='hardware'/><category scheme='http://www.blogger.com/atom/ns#' term='thinkpad'/><category scheme='http://www.blogger.com/atom/ns#' term='ibm'/><category scheme='http://www.blogger.com/atom/ns#' term='lenovo'/><title type='text'>lenovo thinkpad R61i (or: a tale of two laptops)</title><content type='html'>Back in the day, we all knew who made the best laptops: IBM.  Not because they were the cheapest or sexiest machines around.  They were the toughest.  They were tanks.  You could drop it four stories and run it over with your car (though this was before SUVs were so popular) and the damn thing would be just fine.  Of course, they were way too expensive for your average middle-class highschool kid to ever get.  &lt;br /&gt;&lt;br /&gt;When I was at MSFT I managed to get a company-issued Sony Viao TR5GP.  I loved the Viao itself: it was small, portable, sexy, and not too slow.  I hated Sony though.  They refused to make drivers available for download or even seperate install; you had to buy the recovery DVD for $10 and then use it to fully recover the OS.  Of course, doing that brought all the OEM crapware with it.  So it was a constant struggle.&lt;br /&gt;&lt;br /&gt;Now I find myself in need of a notebook once again.  I will need one for the move, and Sara has been wanting one to use around the house.  I disqualified Dell, because their machines are all flimsy crap.  And I disqualified Toshiba because they're ugly and seemed to always have weird issues that weren't really problems, per se, just quirks. So my thoughts naturally turned to ThinkPads.&lt;br /&gt;&lt;br /&gt;I bought the R61i because I wanted something cheap (as close to $500 as possible, newegg had it for $699).  I wanted something reliable and sturdy.  Its main purpose in life will be a web browsing machine and a mstsc machine.  I need something to help me find an apartment when I get to California.  Also, something to do on the plane.  &lt;br /&gt;&lt;br /&gt;It came last night, and I like it very much.  Lenovo does not seem to have ruined the ThinkPad.  It doesn't have the cute IBM logo, and it doesn't seem quite as sturdy as I remember (what is these days?), but I may have just built it up in my mind over the years.  It does seem better than all the Dells I ever used at MSFT.  They keyboard is nice and clicky.  The screen is bright and clear.  The USB ports are plentiful.  It came with a nice assortment of crapware, but I uninstalled it all.  It did require something like 62 Windows Updates out of the box, which was dissapointing, but what can you do?  It's Windows.&lt;br /&gt;&lt;br /&gt;Anyway, what I am getting at is just say no to Dell; buy a ThinkPad.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5377233936486388397-2968739789191107060?l=jeffcode.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://jeffcode.blogspot.com/feeds/2968739789191107060/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5377233936486388397&amp;postID=2968739789191107060' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5377233936486388397/posts/default/2968739789191107060'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5377233936486388397/posts/default/2968739789191107060'/><link rel='alternate' type='text/html' href='http://jeffcode.blogspot.com/2008/01/lenovo-thinkpad-r61i-or-tale-of-two.html' title='lenovo thinkpad R61i (or: a tale of two laptops)'/><author><name>jeffdav</name><uri>http://www.blogger.com/profile/14865307340669462204</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5377233936486388397.post-1576815843371709772</id><published>2007-12-27T10:28:00.000-08:00</published><updated>2007-12-27T10:39:43.069-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='favicons'/><category scheme='http://www.blogger.com/atom/ns#' term='internet explorer'/><title type='text'>why doesn't the favicon for my site appear in IE7?</title><content type='html'>&lt;em&gt;This is a re-posting of a post originally published on 2007-03-01. The original can be found &lt;a href="http://securitygarden.blogspot.com/2007/10/missing-favicon-in-ie7.html"&gt;here&lt;/a&gt;. This version has been updated to match what is currently reality.&lt;/em&gt;&lt;br /&gt;&lt;br /&gt;When I was at Microsoft, I was the developer tasked with fixing the Favicon story for IE7. The original IE6 behavior was to download the favicon once--when a user made a site a Favorite. I do not want to go too deep into the details of how this craziness works, but the key piece of information to understanding why it seemed so broken is this: a mapping between the url of the site the url for the site's Favicon would be stored in IE's History database and the actually bits of the icon would be stored in the temporary Internet files folder. Thus, if you cleared your history or your cache, or the item expired out of either one, the icon would be gone forever.&lt;br /&gt;&lt;br /&gt;Fast-forward to IE7. It has been over two (three?) years since IE6 shipped. We want to implement tabbed browsing, and we want the tabs to display the correct Favicons. So I updated the Favicon code to always download the icon on a first visit. The code also remembers if there is no Favicon (404) or it was invalid in some way (ExtractIcon() failed). &lt;br /&gt;&lt;br /&gt;Here is a Mini-Faq (with one bonus question at the end) that I wrote while I was at Microsoft:&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Q:&lt;/strong&gt; How do I make a favicon appear for my site in IE7?&lt;br /&gt;&lt;strong&gt;A:&lt;/strong&gt; There are two ways. The first is to put a file in the root of your domain called favicon.ico. The second is to use a &amp;lt;link&amp;gt; tag with the rel="shortcut icon" value and the href value set to the URL for the Icon you wish to display.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Q:&lt;/strong&gt; How often does IE download the favicon?&lt;br /&gt;&lt;strong&gt;A:&lt;/strong&gt; IE will download the icon when a user first visits the site. The icon is stored in the Temporary Internet Files folder on the client machine. Additional metadata about the favicon is stored in the user's Url History database. If either store is cleared, or items relating to the favicon have naturally expired, then the icon will be downloaded again on the next visit. If more than one page (or site) shares the same favicon, it is only downloaded once. IE takes great pains to download the icon as few times as possible to reduce load on the server.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Q:&lt;/strong&gt; I see the wrong favicon for some sites I visit. How do I fix this?&lt;br /&gt;&lt;strong&gt;A:&lt;/strong&gt; If the history database has become corrupted in some way, this can happen. The simplest solution is just to use Delete Browsing History (on the Tools menu) to clear the cache and the history store. &lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Q:&lt;/strong&gt; I put a favicon.ico on my site as you described, but it still doesn't appear.&lt;br /&gt;&lt;strong&gt;A:&lt;/strong&gt; It must actually be a .ico (an Icon) file. Bitmaps, pngs, gifs, etc, will not work. IE7 will download your favicon to the Temporary Internet Files folder and call ExtractIcon() on the file. If this fails, we will show the default icon instead of your favicon.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Q:&lt;/strong&gt; I verified that my favicon really is an icon, but it still doesn't appear.&lt;br /&gt;&lt;strong&gt;A:&lt;/strong&gt; Since IE loads your icon out of the Temporary Internet Files folder, it must be able to actually store it there. If you are setting the no-cache directive for the icon file, then IE will not be able to display your icon and will display the default icon instead. You can use Fiddler to verify.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Q:&lt;/strong&gt; How do I create a different favicon for every page on my site?&lt;br /&gt;&lt;strong&gt;A:&lt;/strong&gt; Put a different tag on each page, pointing to a different icon.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Q:&lt;/strong&gt; I changed my site's favicon to a different icon, but the old one still shows in IE. How do I force IE to update?&lt;br /&gt;&lt;strong&gt;A:&lt;/strong&gt; If you just put the favicon.ico file in the root of your domain, IE doesn't have any way of knowing if it changed. To force an update, you need to use a tag and point to a different filename than you previously used. The current filename is compared against the known filename stored in the Url History database. When IE sees the filename has changed, it will download your new icon. Alternatively, you can ask your users to clear their history and cache (Tools-&gt;Internet Options-&gt;Delete Browsing History), which will also force IE to download the new file.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Q:&lt;/strong&gt; What is still broken?&lt;br /&gt;&lt;strong&gt;A:&lt;/strong&gt; Two things: (1) If you specify an alternate location via &amp;lt;link&amp;gt; tag, the href member must be fully-qualified and does not respect the &amp;lt;base&amp;gt; tag. (2) The &amp;lt;link&amp;gt; tag must have "shortcut icon" as the rel value, but this is in violation of the W3C spec that says whitespace in the rel tag denotes a list of values. IE treats "shortcut icon" as a single value. Luckily this still works for other browsers who see "shortcut" and ignore it and only pay attention to the "icon" string.&lt;br /&gt;&lt;br /&gt;That should cover most of the questions I've received about favicons in IE7. If you have more questions, feel free to ask.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5377233936486388397-1576815843371709772?l=jeffcode.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://jeffcode.blogspot.com/feeds/1576815843371709772/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5377233936486388397&amp;postID=1576815843371709772' title='12 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5377233936486388397/posts/default/1576815843371709772'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5377233936486388397/posts/default/1576815843371709772'/><link rel='alternate' type='text/html' href='http://jeffcode.blogspot.com/2007/12/why-doesnt-favicon-for-my-site-appear.html' title='why doesn&apos;t the favicon for my site appear in IE7?'/><author><name>jeffdav</name><uri>http://www.blogger.com/profile/14865307340669462204</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>12</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5377233936486388397.post-7932646102992337413</id><published>2007-12-05T13:36:00.000-08:00</published><updated>2007-12-05T14:02:42.443-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='internet explorer'/><category scheme='http://www.blogger.com/atom/ns#' term='security'/><category scheme='http://www.blogger.com/atom/ns#' term='pop-up blocker'/><title type='text'>the importance of context: security and the dom</title><content type='html'>&lt;em&gt;This is a re-posting of a post originally published on 2004-07-22. The original can be found &lt;/em&gt;&lt;a href="http://web.archive.org/web/20040620020013/blogs.msdn.com/jeffdav/archive/2004/05/11/130058.aspx"&gt;&lt;em&gt;here&lt;/em&gt;&lt;/a&gt;&lt;em&gt;. This version has been updated to match what is currently reality.&lt;/em&gt;&lt;br /&gt;&lt;br /&gt;Almost every navigation in Internet Explorer results in a flurry of security checks. Many of these checks are fairly obvious things, such as checking the URL of the current location (the context URL) and the pending navigation's destination URL to see if their zones, domains, protocols, etc are the same, different, acceptable, etc. When I worked on Internet Explorer, I spent a significant amount of time debugging strange combinations and ways of navigating. I will not bore you with the details; my goal is to emphasize the importance of context. I will mainly speak to the Internet Explorer Pop-up Blocker's dependence on the context URL.&lt;br /&gt;&lt;br /&gt;The Pop-up Blocker is dependent on the context URL. When the page attempts to open a new window, the HTML rendering engine queries the Pop-up Blocker. The Pop-up Blocker looks in the white list to see if this page is exempt from new window management. If, for some reason, the context URL provided is NULL, then obviously it cannot be matched to a domain in the white list.&lt;br /&gt;&lt;br /&gt;So let us examine the following:&lt;br /&gt;&lt;pre&gt;&lt;code&gt;var oSpan = document.createElement("span");&lt;br /&gt;oSpan.innerHTML =&lt;br /&gt;  "&amp;lt;a href="http://www.blogger.com/" target="'_blank'"&amp;gt;Microsoft.com&amp;lt;/a&amp;gt;";&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;When the anchor causes the browser to navigate, it will see the _blank and attempt to open a new window. This attempt will have to be verified by Pop-up Blocker. But the span is not parented to anything, thus it has no context. Elements with no context get the default context, which is about:blank, which confers no rights.&lt;br /&gt;&lt;br /&gt;The moral of this story is always remember to parent your dynamically created elements to something in the document:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;document.appendChild(oSpan);&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;It's been pointed out that the W3C specification says something about what should happen here and that IE does something wrong (or fails to do something). That may be the case. I was not responsible for the code the implemented the DOM.&lt;br /&gt;&lt;br /&gt;Furthermore, adding about:blank to your white list doesn't work either, since it has no domain and the whitelist requires domains.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5377233936486388397-7932646102992337413?l=jeffcode.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://jeffcode.blogspot.com/feeds/7932646102992337413/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5377233936486388397&amp;postID=7932646102992337413' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5377233936486388397/posts/default/7932646102992337413'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5377233936486388397/posts/default/7932646102992337413'/><link rel='alternate' type='text/html' href='http://jeffcode.blogspot.com/2007/12/importance-of-context-security-and-dom.html' title='the importance of context: security and the dom'/><author><name>jeffdav</name><uri>http://www.blogger.com/profile/14865307340669462204</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5377233936486388397.post-4501714658035512185</id><published>2007-12-04T14:09:00.000-08:00</published><updated>2007-12-04T14:23:28.504-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='explorer'/><category scheme='http://www.blogger.com/atom/ns#' term='tips'/><category scheme='http://www.blogger.com/atom/ns#' term='windows'/><category scheme='http://www.blogger.com/atom/ns#' term='shell'/><title type='text'>how to cleanly start and stop explorer.exe</title><content type='html'>&lt;em&gt;This is a re-posting of a post originally published on 2004-07-22. The original can be found &lt;/em&gt;&lt;a href="http://web.archive.org/web/20040804194345/http://blogs.msdn.com/jeffdav"&gt;&lt;em&gt;here&lt;/em&gt;&lt;/a&gt;&lt;em&gt;. This version has been updated to match what is currently reality.&lt;/em&gt;&lt;br /&gt;&lt;em&gt;&lt;/em&gt;&lt;br /&gt;When you are developing Shell Extensions, sometimes you want to be able to cleanly start a new instance of explorer.exe without picking up all the environment variables of whatever command window you've got running (since environment is inherited).  Similarly, you may want to shut down explorer.exe cleanly so that it releases its references on your dll--generally so that you can swap in a new version.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Cleanly Starting Explorer &lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;The trick is to hold down CTRL while you select New Task.  This will automagically launch an new instance of Explorer.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;CTRL+SHIFT+ESC-&gt;File-&gt;CTRL+New Task (Run...)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Cleanly Shutting Down Explorer on Windows XP&lt;/strong&gt;&lt;br /&gt;&lt;strong&gt;&lt;/strong&gt;&lt;br /&gt;The way to tell Explorer to shut down is to say you want to shutdown the machine, but then cancel in a special way:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;Start-&gt;Shutdown-&gt;CTRL+ALT+SHIFT+Cancel&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Cleanly Shutting Down Explorer on Windows Vista&lt;/strong&gt;&lt;br /&gt;&lt;strong&gt;&lt;/strong&gt;&lt;br /&gt;During development of Windows Vista, they changed the way shutdown worked.  They got rid of the shutdown dialog and replaced it with better options on the Start menu.  Thus the way to cleanly shutdown Explorer had to change.  Now you do some magic right on the start menu itself.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;Start-&gt;CTRL+SHIFT+Right Click [on some empty space]-&gt;Exit Explorer&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;When you CTRL+SHIFT+Right Click on the empty space, a context menu appears with a clearly labeled option for shutting down explorer.exe.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5377233936486388397-4501714658035512185?l=jeffcode.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://jeffcode.blogspot.com/feeds/4501714658035512185/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5377233936486388397&amp;postID=4501714658035512185' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5377233936486388397/posts/default/4501714658035512185'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5377233936486388397/posts/default/4501714658035512185'/><link rel='alternate' type='text/html' href='http://jeffcode.blogspot.com/2007/12/how-to-cleanly-start-and-stop.html' title='how to cleanly start and stop explorer.exe'/><author><name>jeffdav</name><uri>http://www.blogger.com/profile/14865307340669462204</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5377233936486388397.post-6507091106602414962</id><published>2007-12-02T12:27:00.000-08:00</published><updated>2007-12-02T12:53:26.442-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='inewwindowmanager'/><category scheme='http://www.blogger.com/atom/ns#' term='windows xp service pack 2'/><category scheme='http://www.blogger.com/atom/ns#' term='internet explorer'/><category scheme='http://www.blogger.com/atom/ns#' term='pop-up blocker'/><title type='text'>the internet explorer pop-up manager and your webbrowser control host</title><content type='html'>&lt;em&gt;This is a re-posting of a post originally published on 2004-01-26. The original can be found &lt;a href="http://web.archive.org/web/20051123020438/blogs.msdn.com/jeffdav/archive/2004/01/26/63125.aspx"&gt;here&lt;/a&gt;. This version has been updated to match what is currently reality.&lt;/em&gt;&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Overview&lt;/strong&gt;&lt;br /&gt;With the introduction of Windows XP Service Pack 2, Internet Explorer 6 (and up) introduced a built-in pop-up window manager. If your program is going to host the webbrowser control, you may or may not want the pop-up blocker's functionality. This post will describe how to alter, override or enable the pop-up blocker's functionality for application.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Implement INewWindowManager&lt;/strong&gt;&lt;br /&gt;The basic Implement &lt;a href="http://msdn2.microsoft.com/en-us/library/bb775418.aspx"&gt;INewWindowManager&lt;/a&gt;. The webbrowser control will QueryInterface its site for this method. You should implement this in the same place you (would) implement &lt;a href="http://msdn2.microsoft.com/en-us/library/aa753260.aspx"&gt;IDocHostUIHandler&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;When webbrowser control detects a new window is being requested, it will call the &lt;a href="http://msdn2.microsoft.com/en-us/library/bb775416.aspx"&gt;EvaluateNewWindow&lt;/a&gt;() method on the interface. Just about any method for opening a new window should trigger this call. What follows is boiler-plate for various scenarios:&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;I Do Not Want Any Pop-up Management&lt;br /&gt;&lt;/strong&gt;This is the easy case, since pop-up management is opt-in. Simply do nothing. The webbrowser control will query you for INWM. If the query fails, no pop-up management will occur. This decision was made so that applications that already exist would not have to change when Windows XP Service Pack 2 shipped.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;I Want Exactly What Internet Explorer Does&lt;/strong&gt;&lt;br /&gt;This is easy too. Simply implement INWM::ENW() and return E_NOTIMPL. You will get all the same functionality, including checking against the user's white list and action according to the user's preferences.&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;CMyObject::EvaluateNewWindow(...)&lt;br /&gt;{&lt;br /&gt;    return E_NOTIMPL;&lt;br /&gt;}&lt;/code&gt;&lt;/pre&gt;When the webbrowser control sees the failure code, it will fall back to the default pop-up management.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;I Want My Own Logic&lt;/strong&gt;&lt;br /&gt;Implement INWM::ENW() and use the parameters to decide whether or not to block the new window. Return S_FALSE to block the window and S_OK to allow it:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;CMyObject::EvaluateNewWindow(...)&lt;br /&gt;{&lt;br /&gt;    HRESULT hr = S_OK;&lt;br /&gt;    if (/* your logic here */)&lt;br /&gt;    {&lt;br /&gt;        hr = S_FALSE;&lt;br /&gt;    }&lt;br /&gt;    else if (/* more of your logic here */)&lt;br /&gt;    {&lt;br /&gt;        hr = S_FALSE;&lt;br /&gt;    }&lt;br /&gt;    // ... and so on ...&lt;br /&gt;&lt;br /&gt;    // Now update your UI.&lt;br /&gt;    switch(hr)&lt;br /&gt;    {&lt;br /&gt;        case S_OK:&lt;br /&gt;            OnPopupNotBlocked(...);&lt;br /&gt;            break;&lt;br /&gt;&lt;br /&gt;        case S_FALSE:&lt;br /&gt;            OnPopupBlocked(...);&lt;br /&gt;            break;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    return hr;&lt;br /&gt;}&lt;/code&gt;&lt;/pre&gt;&lt;strong&gt;Developer's Note&lt;/strong&gt;&lt;br /&gt;I will admit right now, this is the first public interface I ever designed. I was young and stupid and the Interface was not subject to a lot of review by people with more expertise. If I was doing it all over again, I would probably not have done it this way. But it works.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5377233936486388397-6507091106602414962?l=jeffcode.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://jeffcode.blogspot.com/feeds/6507091106602414962/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5377233936486388397&amp;postID=6507091106602414962' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5377233936486388397/posts/default/6507091106602414962'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5377233936486388397/posts/default/6507091106602414962'/><link rel='alternate' type='text/html' href='http://jeffcode.blogspot.com/2007/12/internet-explorer-pop-up-manager-and.html' title='the internet explorer pop-up manager and your webbrowser control host'/><author><name>jeffdav</name><uri>http://www.blogger.com/profile/14865307340669462204</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5377233936486388397.post-5965025203515425392</id><published>2007-11-30T18:03:00.000-08:00</published><updated>2007-11-30T18:08:40.031-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='explanation'/><category scheme='http://www.blogger.com/atom/ns#' term='milestone'/><title type='text'>hello world</title><content type='html'>Hello, world.&lt;br /&gt;&lt;br /&gt;I'm Jeff.  I used to work at Microsoft on the Internet Explorer team.  While I was there I had a technical blog at &lt;a href="http://blogs.msdn.com/jeffdav"&gt;http://blogs.msdn.com/jeffdav&lt;/a&gt;.  If you click on it, you will see that all of the postings have been deleted.  This was not done by me or by Microsoft, but by a single individual who just couldn't be bothered to explain that he was not me. &lt;br /&gt;&lt;br /&gt;Some of the content was rather useless, but some of it was actually quite useful.  To that end, I will be salvaging the more useful bits from the WayBack Machine and re-posting them here.  I will also be posting new things as they occur to me.&lt;br /&gt;&lt;br /&gt;If you like what you see here, be sure to also check out my wine blog: &lt;a href="http://jeffwine.blogspot.com/"&gt;http://jeffwine.blogspot.com&lt;/a&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5377233936486388397-5965025203515425392?l=jeffcode.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://jeffcode.blogspot.com/feeds/5965025203515425392/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5377233936486388397&amp;postID=5965025203515425392' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5377233936486388397/posts/default/5965025203515425392'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5377233936486388397/posts/default/5965025203515425392'/><link rel='alternate' type='text/html' href='http://jeffcode.blogspot.com/2007/11/hello-world.html' title='hello world'/><author><name>jeffdav</name><uri>http://www.blogger.com/profile/14865307340669462204</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry></feed>
