| Steven 的个人资料Windows Desktop Search -...日志列表 | 帮助 |
|
|
6月12日 Customizing the Stock PreviewsOk so I thought I’d get the ball rolling by talking about how you can customize the item previews displayed in the large search results UI. This is a big topic which isn’t easily covered by a single post so I thought I’d first talk broadly about how the previews work and how to perform basic modifications. In future posts I can drill into more details if there’s interest. But before any of that I need to throw out a disclaimer: Modifying the previews shipped with Windows Desktop Search is not a supported feature. Any new previews you build will not be guaranteed to work in future versions of the product. The documentation that follows should be considered “unofficial” at best. Preview Selection The first topic I should touch on is how the appropriate preview gets chosen when a user selects an item. When a new item is selected, the first thing the preview pane does is it identifies what type of previewer it’s going to display. It currently only has two choices, the folder previewer or the content previewer. The folder previewer is chosen if the item is a file system folder and is simply a shell view over the contents of the folder. All other items get mapped to the content previewer which is an embedded WebBrowser control. At this point we’re only interested in items mapped to the content previewer because they’re the only ones we can modify. Once an item has been mapped to the content previewer it then goes through a second round of analysis to see what type of content should actually be displayed for the item. This decision process is driven by the registry which means you can modify the registry to influence most of the preview selection decisions made. Open RegEdit and look for the key: HKEY_CURRENT_USER\Software\Microsoft\RSSearch\ContentIndexCommon\Previewers You’ll notice a few values and a set of 3 sub-keys Extension, PerceivedType, and Default. Let’s start with the sub-keys. The contents of those 3 keys are used to determine what preview an item gets and I’ve listed them in the order in which they get consulted. The previewer first gets the file extension of the item being previewed (if any) and tries to find a sub-key under the Extensions key. If a sub-key is found preview selection stops and the values of the found key are used to drive preview generation. If no extension key is found then selection moves on to type based selection. Every item in the index has, or at least should have, a value called its perceived type. The perceived type of an item is the value used to tie it to the type filters displayed within the UI and it’s also the value used to tie the item a type wide preview. So for type based selection we simply get the items perceived type and look for a sub-key of the same name under the PerceivedType key. Once found preview selection stops and the values of the found key are used to drive preview generation. If the item has no perceived type or the perceived type isn’t found then the value of the Default key is chosen and selection stops anyway. Preview Generation So the items been mapped to a key within the registry but what do the values mean? We’ll those values bind the previewer to a COM based plug-in that knows how to generate preview content for the item. The content generated by the plug-in can be essentially anything render-able by IE. We currently ship with 3 preview plug-ins and the COM interface they implement isn’t public so you can’t add any new ones. So why are we talking about customizing the previews then? Because one of those plug-ins is pretty special… If you were to look through all of the previewer keys you’d not two recurring patterns. The keys either contain a single default value, one of two GUID’s. Or they contain no default value but several named values. The keys with one of the two GUID’s map the items preview to either the Native (“{015CA7C6-DECD-40dc-AAAC-73EA9940E0F9}”) or Office (“{7A35A3A8-3DEA-40e5-B2AA-21DEF91A219A}”) Previewer plug-ins. Of those two the Native Previewer is the most interesting because it acts as a pass through for the items URL. When an item is bound to this preview we simply navigate our embedded WebBrowser to the URL of the item which is useful for items that IE already does a good job of rendering like PDFs. Even more interesting are the keys without a GUID because they get mapped to a special internal previewer called the Registry Based Previewer. The Registry Based Previewer turns preview creation into an authoring process by generating preview content on the fly from HTML templates containing a set of ASP’ish (read NOT ASP) macros. The remaining bulk of this post will talk about the structure of these templates but first let me break down the registry entries that control what template is used and how it’s rendered. Looking at: HKEY_CURRENT_USER\Software\Microsoft\RSSearch\ContentIndexCommon\Previewers\PerceivedType\contact We see the values:
The blank value for (Default) is what maps this items preview to the Registry Based Previewer. The ContentType value controls the type of content generated by the previewer and can be either 0 for HTML or 1 for MSHTML. I’d recommend you always use 1 as it’s the most flexible and most tested. The ScriptOK value is used to override one of the security decisions we make based upon what store the item we’re previewing lives in. If the item resides on your hard-drive it’s partially trusted so we let script execute by default. But if the item lives anywhere else like say Outlook or OE we treat it as un-trusted and disable script execution by default. The ScriptOK value lets us re-enable script execution on a per type basis. Security is deep topic worthy of its own post but I should also point out at this time that we NEVER let ActiveX controls execute and there’s currently no way to override that decision. Finally, the TemplateUrl value specifies the actual template to use when generating the preview content. As you can see, all of our templates get pulled from a resource dll but you can change these values to point to a file on the users hard-drive which is the key to replacing the stock previews with custom ones! Creating new Preview Templates Probably the easiest way to figure out how to customize the previews is to dive in and start changing them. You’ll notice that I’ve posted several listing which should act as a good starting point for your adventures. Before you download and install any of the listings you need to be very sure that this is something you want to explore. You’ll need to be comfortable working with HTML and modifying the registry. Executing the UseDebugPreviews.reg command will replace all of you’re type based previews (meaning most of them) with a new Debug.htm preview that dumps out most of the available properties within a given view. I’ve also provided a UseStockPreviews.rgs command which should roll everything back to stock but I can’t provide any warranties for any of this so USE AT YOUR OWN RISK! After you’ve downloaded all 3 of the listings you’ll want to run the UseDebugPreviews.reg command to update the registry to use Debug.htm as the preview template for all type wide previews. There’s an assumption made in UseDebugPreviews.reg that Debug.htm is located in the root of your C-Drive so you’ll need to modify that file if that’s not the case. It’s very important that Debug.htm is saved as a UTF-8 encoded file. The macro replacement done by the Registry Based Previewer will not work if you save the file as Unicode which is the default for Notepad.exe. You’ll also need to either reboot your machine or kill/restart Explorer.exe to get the new previews to take effect. It’s worth noting at this point that changes made to an already mapped preview template do not require a reboot. In fact you can modify your template and simply select another item from the results list to see your changes take effect which is nice. So once you have Debug.htm installed you should try some queries out and notice what properties are available to your previews in what views. I said above that Debug.htm will show you MOST of the properties available because some of the views like contacts have a ton of properties. There are around 200 total but not all of the properties for an item are available in every view. For instance when an item is displayed in the Contacts view it has a rich set of properties available. But that same item displayed in the Communications or Everything view has only a subset of its total properties available. The Debug.htm preview displays the availability of the properties that can be shown for an item no matter what view its in and is therefore quite useful. Another thing you might notice while browsing around is that image previews still get mapped to the stock image previewer. That’s because that mapping is done on a per extension basis and UseDebugPreviews.reg only updates the type wide previews. To map an extension say .JPG you’ll need to modify the registry by hand. Change the TemplateUrl value of HKEY_CURRENT_USER\Software\Microsoft\RSSearch\ContentIndexCommon\Previewers\Extension\.jpg to “c:\debug.htm” and re-boot. The previews of .JPG items should now map to the debug preview.
Understanding Preview Templates Without getting into too much depth I’ll give you an overview of the templates and the macros we currently support. The templates themselves are just UTF-8 encoded HTML files with some special macros added in the form of <%cmd:property%>. At preview generation time the template along with the meta data of the currently selected item gets run through a transform engine to generate a valid HTML file for rendering within the Content Previewers embedded WebBrowser control. Most of the macros are about inserting the dynamic values of the currently selected item but there are a few control commands as well. Here’s a quick list of the major (but not all) commands:
There are a few other interesting commands but I won’t dive into them at this point. This is more then enough to get you started. Just use Debug.htm as a starting point and be sure to send me a link to any interesting previews you come up with. Important Notes and Tips
Listing 1: Debug.htmTo create the Debug.htm file copy everything below the “—copy—“ line into an empty Notepad.exe document. Then save the document AS UTF-8 to “c:\Debug.htm”. The saved file MUST be UTF-8 encoded. Use Notepads Save As feature to do this because the default for Notepad is to save as Unicode which won’t work.
—copy— <html> <head> <!-- Template: debug.htm --> <meta http-equiv="content-type" content="text/html; charset=UTF-8"> <style> .debug-group { font-family: tahoma; font-size: 12pt; border: 1px solid #7EB6F0; background-color: #2765AB; color: #FFFFFF; } .debug-row-header { font-family: tahoma; font-size: 10pt;background-color: #FFFFFF; color: green; } .debug-row-hidden { font-family: tahoma; font-size: 8pt; background-color: #EEF4FB; color: black; } .debug-row { font-family: tahoma; font-size: 8pt; background-color: #FFFFFF; color: black; } .debug-cell-header { border-bottom: 1px solid #7EB6F0; } .debug-cell { border-bottom: 1px solid #7EB6F0; } </style> <script>
function AddHiddenRow( prop, title, value ) { document.write('<tr class="debug-row-hidden">'); document.write('<td class="debug-cell">' + prop + '</td>'); document.write('<td class="debug-cell">' + title + ' </td>'); document.write('<td class="debug-cell">' + value + ' </td>'); document.write('</tr>'); }
function AddRow( prop, title, value ) { document.write('<tr class="debug-row">'); document.write('<td class="debug-cell">' + prop + '</td>'); document.write('<td class="debug-cell">' + title + ' </td>'); document.write('<td class="debug-cell">' + value + ' </td>'); document.write('</tr>'); }
</script> </head> <body leftmargin="0" topmargin="0" marginwidth="0" marginheight="0"> <!-- First we'll dump out the available properties --> <br> <div align="center" style="width: 100%; padding: 0px 15px 0px 15px;"> <div class="debug-group" align="left" style="width: 100%; height=100%;"> <div style="padding: 5px 5px 5px 5px;">Item properties</div> <div style="overflow: auto; width: 100%;"> <table border="0" width="100%" cellspacing="0" cellpadding="5"> <tr class="debug-row-header"> <td class="debug-cell-header" width="100">Property</td> <td class="debug-cell-header" width="100">Title</td> <td class="debug-cell-header">Value</td> </tr> <script> <%if:DocFormat%> AddHiddenRow('DocFormat', '<%title:DocFormat%>', '<%value:DocFormat%>'); <%endif%> <%if:Url%> AddHiddenRow('Url', '<%title:Url%>', '<%value:Url%>'); <%endif%> <%if:HasAttach%> AddHiddenRow('HasAttach', '<%title:HasAttach%>', '<%value:HasAttach%>'); <%endif%> <%if:PerceivedType%> AddHiddenRow('PerceivedType', '<%title:PerceivedType%>', '<%value:PerceivedType%>'); <%endif%> <%if:IsDeleted%> AddHiddenRow('IsDeleted', '<%title:IsDeleted%>', '<%value:IsDeleted%>'); <%endif%> <%if:WorkID%> AddHiddenRow('WorkID', '<%title:WorkID%>', '<%value:WorkID%>'); <%endif%> <%if:IsAttachment%> AddHiddenRow('IsAttachment', '<%title:IsAttachment%>', '<%value:IsAttachment%>'); <%endif%> <%if:ConversationID%> AddHiddenRow('ConversationID', '<%title:ConversationID%>', '<%value:ConversationID%>'); <%endif%> <%if:FileExt%> AddHiddenRow('FileExt', '<%title:FileExt%>', '<%value:FileExt%>'); <%endif%> <%if:Rank%> AddRow('Rank', '<%title:Rank%>', '<%value:Rank%>'); <%endif%> <%if:DocTitlePrefix%> AddRow('DocTitlePrefix', '<%title:DocTitlePrefix%>', '<%value:DocTitlePrefix%>'); <%endif%> <%if:DocTitle%> AddRow('DocTitle', '<%title:DocTitle%>', '<%value:DocTitle%>'); <%endif%> <%if:DocAuthor%> AddRow('DocAuthor', '<%title:DocAuthor%>', '<%value:DocAuthor%>'); <%endif%> <%if:PrimaryDate%> AddRow('PrimaryDate', '<%title:PrimaryDate%>', '<%value:PrimaryDate%>'); <%endif%> <%if:Size%> AddRow('Size', '<%title:Size%>', '<%value:Size%>'); <%endif%> <%if:FileExtDesc%> AddRow('FileExtDesc', '<%title:FileExtDesc%>', '<%value:FileExtDesc%>'); <%endif%> <%if:DisplayFolder%> AddRow('DisplayFolder', '<%title:DisplayFolder%>', '<%value:DisplayFolder%>'); <%endif%> <%if:FlagText%> AddRow('FlagText', '<%title:FlagText%>', '<%value:FlagText%>'); <%endif%> <%if:IsFlagged%> AddRow('IsFlagged', '<%title:IsFlagged%>', '<%value:IsFlagged%>'); <%endif%> <%if:Create%> AddRow('Create', '<%title:Create%>', '<%value:Create%>'); <%endif%> <%if:DueDate%> AddRow('DueDate', '<%title:DueDate%>', '<%value:DueDate%>'); <%endif%> <%if:Importance%> AddRow('Importance', '<%title:Importance%>', '<%value:Importance%>'); <%endif%> <%if:ToName%> AddRow('ToName', '<%title:ToName%>', '<%value:ToName%>'); <%endif%> <%if:CcName%> AddRow('CcName', '<%title:CcName%>', '<%value:CcName%>'); <%endif%> <%if:AttachmentNames%> AddRow('AttachmentNames', '<%title:AttachmentNames%>', '<%value:AttachmentNames%>'); <%endif%> <%if:DocCompany%> AddRow('DocCompany', '<%title:DocCompany%>', '<%value:DocCompany%>'); <%endif%> <%if:Location%> AddRow('Location', '<%title:Location%>', '<%value:Location%>'); <%endif%> <%if:DocCategory%> AddRow('DocCategory', '<%title:DocCategory%>', '<%value:DocCategory%>'); <%endif%> <%if:DocKeywords%> AddRow('DocKeywords', '<%title:DocKeywords%>', '<%value:DocKeywords%>'); <%endif%> <%if:MusicAlbum%> AddRow('MusicAlbum', '<%title:MusicAlbum%>', '<%value:MusicAlbum%>'); <%endif%> <%if:FileName%> AddRow('FileName', '<%title:FileName%>', '<%value:FileName%>'); <%endif%> <%if:MusicGenre%> AddRow('MusicGenre', '<%title:MusicGenre%>', '<%value:MusicGenre%>'); <%endif%> </script> </table> </div> </div> </div>
<!-- Next we'll embed any characterization data --> <br> <div align="center" style="width: 100%; padding: 0px 15px 0px 15px;"> <div class="debug-group" align="left" style="width: 100%; height=100%;"> <div style="padding: 5px 5px 5px 5px;">Characterization</div> <iframe height="200" width="100%" src="<%url:characterization%>"> </iframe> </div> </div>
<!-- Finally we'll show the items image if it has one --> <br> <div align="center" style="width: 100%; padding: 0px 15px 0px 15px;"> <div class="debug-group" align="left" style="width: 100%; height=100%;"> <div style="padding: 5px 5px 5px 5px;">Image</div> <table border="0" width="100%" cellspacing="0" cellpadding="5"> <tr class="debug-row-header"> <td><img src="<%url:url%>"></img></td> </tr> </table> </div> </div> </body> </html> Listing 2: UseDebugPreviews.rgsTo create the UseDebugPreviews.rgs file copy everything below the “—copy—“ line into an empty Notepad.exe document. Then save the document to “c:\UseDebugPreviews.rgs”.
—copy— Windows Registry Editor Version 5.00
[HKEY_CURRENT_USER\Software\Microsoft\RSSearch\ContentIndexCommon\Previewers\PerceivedType] @=""
[HKEY_CURRENT_USER\Software\Microsoft\RSSearch\ContentIndexCommon\Previewers\PerceivedType\communications] @="" "ContentType"=dword:00000001 "TemplateUrl"="c:\\debug.htm" "ScriptOk"=dword:00000001
[HKEY_CURRENT_USER\Software\Microsoft\RSSearch\ContentIndexCommon\Previewers\PerceivedType\communications/calendar] @="" "ContentType"=dword:00000001 "TemplateUrl"="c:\\debug.htm" "ScriptOk"=dword:00000001
[HKEY_CURRENT_USER\Software\Microsoft\RSSearch\ContentIndexCommon\Previewers\PerceivedType\communications/email] @="" "ContentType"=dword:00000001 "TemplateUrl"="c:\\debug.htm" "ScriptOk"=dword:00000001
[HKEY_CURRENT_USER\Software\Microsoft\RSSearch\ContentIndexCommon\Previewers\PerceivedType\communications/im] @="" "ContentType"=dword:00000001 "TemplateUrl"="c:\\debug.htm" "ScriptOk"=dword:00000001
[HKEY_CURRENT_USER\Software\Microsoft\RSSearch\ContentIndexCommon\Previewers\PerceivedType\contact] @="" "ContentType"=dword:00000001 "TemplateUrl"="c:\\debug.htm" "ScriptOk"=dword:00000001
[HKEY_CURRENT_USER\Software\Microsoft\RSSearch\ContentIndexCommon\Previewers\PerceivedType\document] @="" "ContentType"=dword:00000001 "TemplateUrl"="c:\\debug.htm" "ScriptOk"=dword:00000001
[HKEY_CURRENT_USER\Software\Microsoft\RSSearch\ContentIndexCommon\Previewers\PerceivedType\document/note] @="" "ContentType"=dword:00000001 "TemplateUrl"="c:\\debug.htm" "ScriptOk"=dword:00000001
[HKEY_CURRENT_USER\Software\Microsoft\RSSearch\ContentIndexCommon\Previewers\PerceivedType\document/presentation] @="" "ContentType"=dword:00000001 "TemplateUrl"="c:\\debug.htm" "ScriptOk"=dword:00000001
[HKEY_CURRENT_USER\Software\Microsoft\RSSearch\ContentIndexCommon\Previewers\PerceivedType\document/spreadsheet] @="" "ContentType"=dword:00000001 "TemplateUrl"="c:\\debug.htm" "ScriptOk"=dword:00000001
[HKEY_CURRENT_USER\Software\Microsoft\RSSearch\ContentIndexCommon\Previewers\PerceivedType\document/text] @="" "ContentType"=dword:00000001 "TemplateUrl"="c:\\debug.htm" "ScriptOk"=dword:00000001
[HKEY_CURRENT_USER\Software\Microsoft\RSSearch\ContentIndexCommon\Previewers\PerceivedType\favorite] @="" "ContentType"=dword:00000001 "TemplateUrl"="c:\\debug.htm" "ScriptOk"=dword:00000001
[HKEY_CURRENT_USER\Software\Microsoft\RSSearch\ContentIndexCommon\Previewers\PerceivedType\folder] @="" "ContentType"=dword:00000001 "TemplateUrl"="c:\\debug.htm" "ScriptOk"=dword:00000001
[HKEY_CURRENT_USER\Software\Microsoft\RSSearch\ContentIndexCommon\Previewers\PerceivedType\images] @="" "ContentType"=dword:00000001 "TemplateUrl"="c:\\debug.htm" "ScriptOk"=dword:00000001
[HKEY_CURRENT_USER\Software\Microsoft\RSSearch\ContentIndexCommon\Previewers\PerceivedType\images/picture] @="" "ContentType"=dword:00000001 "TemplateUrl"="c:\\debug.htm" "ScriptOk"=dword:00000001
[HKEY_CURRENT_USER\Software\Microsoft\RSSearch\ContentIndexCommon\Previewers\PerceivedType\images/video] @="" "ContentType"=dword:00000001 "TemplateUrl"="c:\\debug.htm" "ScriptOk"=dword:00000001
[HKEY_CURRENT_USER\Software\Microsoft\RSSearch\ContentIndexCommon\Previewers\PerceivedType\music] @="" "ContentType"=dword:00000001 "TemplateUrl"="c:\\debug.htm" "ScriptOk"=dword:00000001
[HKEY_CURRENT_USER\Software\Microsoft\RSSearch\ContentIndexCommon\Previewers\PerceivedType\program] @="" "ContentType"=dword:00000001 "TemplateUrl"="c:\\debug.htm" "ScriptOk"=dword:00000001
Listing 3: UseStockPreviews.rgsTo create the UseStockPreviews.rgs file copy everything below the “—copy—“ line into an empty Notepad.exe document. Then save the document to “c:\UseStockPreviews.rgs”.
—copy— Windows Registry Editor Version 5.00
[HKEY_CURRENT_USER\Software\Microsoft\RSSearch\ContentIndexCommon\Previewers\PerceivedType] @=""
[HKEY_CURRENT_USER\Software\Microsoft\RSSearch\ContentIndexCommon\Previewers\PerceivedType\communications] @="" "ContentType"=dword:00000001 "TemplateUrl"="res://msnlExt.dll/communications.htm"
[HKEY_CURRENT_USER\Software\Microsoft\RSSearch\ContentIndexCommon\Previewers\PerceivedType\communications/calendar] @="" "ContentType"=dword:00000001 "TemplateUrl"="res://msnlExt.dll/communications-calendar.htm"
[HKEY_CURRENT_USER\Software\Microsoft\RSSearch\ContentIndexCommon\Previewers\PerceivedType\communications/email] @="" "ContentType"=dword:00000001 "TemplateUrl"="res://msnlExt.dll/communications-email.htm"
[HKEY_CURRENT_USER\Software\Microsoft\RSSearch\ContentIndexCommon\Previewers\PerceivedType\communications/im] @="" "ContentType"=dword:00000001 "TemplateUrl"="res://msnlExt.dll/communications-im.htm"
[HKEY_CURRENT_USER\Software\Microsoft\RSSearch\ContentIndexCommon\Previewers\PerceivedType\contact] @="" "ContentType"=dword:00000001 "TemplateUrl"="res://msnlExt.dll/contact.htm" "ScriptOk"=dword:00000001
[HKEY_CURRENT_USER\Software\Microsoft\RSSearch\ContentIndexCommon\Previewers\PerceivedType\document] @="" "ContentType"=dword:00000001 "TemplateUrl"="res://msnlExt.dll/document.htm"
[HKEY_CURRENT_USER\Software\Microsoft\RSSearch\ContentIndexCommon\Previewers\PerceivedType\document/note] @="" "ContentType"=dword:00000001 "TemplateUrl"="res://msnlExt.dll/document-note.htm"
[HKEY_CURRENT_USER\Software\Microsoft\RSSearch\ContentIndexCommon\Previewers\PerceivedType\document/presentation] @="" "ContentType"=dword:00000001 "TemplateUrl"="res://msnlExt.dll/document-presentation.htm"
[HKEY_CURRENT_USER\Software\Microsoft\RSSearch\ContentIndexCommon\Previewers\PerceivedType\document/spreadsheet] @="" "ContentType"=dword:00000001 "TemplateUrl"="res://msnlExt.dll/document-spreadsheet.htm"
[HKEY_CURRENT_USER\Software\Microsoft\RSSearch\ContentIndexCommon\Previewers\PerceivedType\document/text] @="" "ContentType"=dword:00000001 "TemplateUrl"="res://msnlExt.dll/document-text.htm"
[HKEY_CURRENT_USER\Software\Microsoft\RSSearch\ContentIndexCommon\Previewers\PerceivedType\favorite] @="" "ContentType"=dword:00000001 "TemplateUrl"="res://msnlExt.dll/favorite.htm"
[HKEY_CURRENT_USER\Software\Microsoft\RSSearch\ContentIndexCommon\Previewers\PerceivedType\folder] @="" "ContentType"=dword:00000001 "TemplateUrl"="res://msnlExt.dll/folder.htm"
[HKEY_CURRENT_USER\Software\Microsoft\RSSearch\ContentIndexCommon\Previewers\PerceivedType\images] @="" "ContentType"=dword:00000001 "TemplateUrl"="res://msnlExt.dll/images.htm"
[HKEY_CURRENT_USER\Software\Microsoft\RSSearch\ContentIndexCommon\Previewers\PerceivedType\images/picture] @="" "ContentType"=dword:00000001 "TemplateUrl"="res://msnlExt.dll/images-picture.htm"
[HKEY_CURRENT_USER\Software\Microsoft\RSSearch\ContentIndexCommon\Previewers\PerceivedType\images/video] @="" "ContentType"=dword:00000001 "TemplateUrl"="res://msnlExt.dll/images-video.htm"
[HKEY_CURRENT_USER\Software\Microsoft\RSSearch\ContentIndexCommon\Previewers\PerceivedType\music] @="" "ContentType"=dword:00000001 "TemplateUrl"="res://msnlExt.dll/music.htm" "ScriptOk"=dword:00000001
[HKEY_CURRENT_USER\Software\Microsoft\RSSearch\ContentIndexCommon\Previewers\PerceivedType\program] @="" "ContentType"=dword:00000001 "TemplateUrl"="res://msnlExt.dll/program.htm"
|
|
|