There is no native C#/XAML PDF viewing component for Windows Store applications, but there are a growing number of options, and various apps have demonstrated success in different areas of PDF rasterization (converting PDF pages to images) and viewing. Here is a breakdown of all the components that I have seen. These are all expensive, so they might not work well for a hobbyist scenario. But if you have a need in your commercial or LOB application, you may find one of these to be useful.
If you learn of others, please post a reply or send me a tweet @paulwhit. I’m actively monitoring this topic.
Also some developers appear to have ported MuPDF for use in Windows Store applications. I believe this is GPL licensed so you would either need to open source your project or buy a license, so use caution there.
If you have the possibility to rasterize the images using a tool external to your Windows Store application, you can create a decent reader experience from a directory of images. Your users will take a bandwidth hit because downloading the rasterized contents can inflate the download size a lot, but at least you can provide the functionality. That is what I did with Army Field Manuals.
In fact, I used GhostScript with a high resolution raster and then used ImageMagick to do an adaptive resize and convert to grayscale. This gave decent quality although some of the scanned pages are still too large due to scanner ghosting in the page background. I think I need to do something to increase the contrast on those particular documents. Anyway, here’s a rundown of the command line arguments I used with those tools in case you want to do something similar.
gswin64c.exe -q -dQUIET -dSAFER -dBATCH -dNOPAUSE -dNOPROMPT -dMaxBitmap=500000000 -dAlignToPixels=0 -dGridFitTT=2 -sDEVICE=png16m -dTextAlphaBits=4 -dGraphicsAlphaBits=4 -r288 -o fm1_0/out_%d.png {pdffilename}
convert {filename} -adaptive-resize 1224x1584 sm_{filename}
mogrify -type grayscale {filename}
Here’s a method for unzipping a Zip file in a Windows Store application. ZipArchive is part of System.IO.Compression.
private async Task UnzipWithProgress(StorageFolder outFolder, Stream zipFileStream, ProgressBar pb) { bool bDelete = false; using (var archive = new ZipArchive(zipFileStream)) { try { // Ensure the UI update part runs in the UI thread var ignore = this.Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () => { this.tbDownloadStatus.Text = "Unzipping"; pb.Value = 0; pb.Maximum = archive.Entries.Count; }); foreach (ZipArchiveEntry entry in archive.Entries) { if (entry.Name != "") { string fileName = entry.FullName.Replace("/", @"\"); StorageFile newFile = await CreateFile(outFolder, fileName); Stream newFileStream = await newFile.OpenStreamForWriteAsync(); Stream fileData = entry.Open(); byte[] data = new byte[entry.Length]; int len = await fileData.ReadAsync(data, 0, data.Length); while (len > 0) { await newFileStream.WriteAsync(data, 0, len); len = await fileData.ReadAsync(data, 0, data.Length); } await newFileStream.FlushAsync(); var ignore2 = this.Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () => { pb.Value++; }); } } var itemId = OriginalUriString; this.Frame.Navigate(typeof(ItemDetailPage), itemId); } catch (Exception ex) { bDelete = true; } finally { if (bDelete) outFolder.DeleteAsync(); } } }
To use it, call it this way. In my case I called it from the LoadState method.
StorageFile file; try { file = await ApplicationData.Current.LocalFolder.GetFileAsync(OriginalUriString); } catch (FileNotFoundException) { file = null; } if (file != null) { using (var ws = await file.OpenReadAsync()) using (var forReadRandomStream = ws.AsStreamForRead(0)) { string path = ApplicationData.Current.LocalFolder.Path + @"\" + Path.GetFileNameWithoutExtension(file.Name) + @"\"; await UnzipWithProgress(await StorageFolder.GetFolderFromPathAsync(path), forReadRandomStream, progressBar1); } }
Apologize that this is not a File->New demo, but I thought it might be useful and Scott Hanselman made me do it.
So, being the good dogfooder that I am, I'm posting this using Word 2013 on release day.
Looks like this may be the future of Windows Live Writer (according to the tea leaves). It feels a lot like Writer initially. It can do a lot out of the box but I'll spare you the needless includes from Flickr and other locations. Although I don't see Insert->Code, maybe cut and paste from Visual Studio is formatted well enough.
Even though I'm a Microsoft employee, I haven't been privy to anything with this release—in fact, I don't think I was able to glean anything other than what's been posted online. I'm looking forward to learning more in the next few weeks and months. I'm particularly intrigued by the sync story with Skydrive and the investment in web versions of the apps. Also fascinating to think about is 3rd party apps integrated with Office 365, Skydrive, and Office Web Apps. Looks like there's an Office store where folks can acquire these add-ons.
Here are a few questions that I have after an hour working with some of the release. There seems to be a cohesive connected-device picture coming together.
I'll probably figure some of this out, but if anyone has some of this information already, feel free to include it in the comments.
Thanks!
p.s. Man this thing posts a LOT faster than Writer.
I’d been looking into developing an app for Windows Phone since I picked up the Samsung Focus 18 months ago – to learn the technology and showcase what the platform can do. As a Microsoft employee, I feel tied to the platform, but also felt like it could be approachable since I am familiar with the language and some of the tools already. I also liked what I had heard about the Windows Phone 7.5 update and wanted to try out some of the features. I recently finished a work project using WPF in which I picked up some XAML experience, so I felt energized about wrapping my head around the Silverlight-based development stack, and becoming a published app author.
So I set out to brainstorm ideas. I figured that good mobile app either has an interesting data set or an interesting algorithm, and is something that is useful away from your computer. I thought about places where you might go and need an app, and somehow remembered about a trip that my dad and I took to the Vietnam Veterans Memorial Wall in Washington, DC. While at the Wall, my dad tried to remember some of the folks he knew about who died in the war. We thumbed through some arcane books where the names were listed alphabetically and by hometown, and found one of the fallen GIs. But we had trouble finding others. Given that most of the soldiers, sailors, airmen, marines and coast guardsmen perished or were declared M.I.A. over 40 years ago, it seems like recall could be a problem worth trying to solve.
So grew the idea of having a portable version of the Vietnam Wall database. I contacted multiple organizations that maintain the database of names behind the wall (there are a few parallel copies maintained by different organizations). There was a lot of interest. Even though the number of potential users is relatively small compared to iPhone or Android, the consensus was that the additional interest and exposure for the wall, and the memory of those listed on it, would justify the efforts. I chose to partner with the good folks at the Virtual Wall®, who tirelessly maintain a virtual memorial for each war casualty and M.I.A., and provide updates to their copy of the data. With their agreement to provide a regularly-updated dump of the wall names (surprisingly, even after 40 years, the data is updated monthly with dozens of changes), I agreed to develop the app free of charge and not include ads or solicit donations. The focus would be on providing a new way to search the database, and providing additional information about the wall to visitors including a link to The Virtual Wall®’s memorials.
We decided on an initial set of features:
I chose some technical requirements in order to make the platform shine:
After about 200 hours of work, Vietnam Wall was published just after Memorial Day 2012. I was shooting for a release for that holiday, but it didn’t quite get approved in time.
http://www.windowsphone.com/en-US/apps/0b758fa2-6414-4381-923e-557172cb3edc?wa=wsignin1.0
Here is a collection of tools and resources I used in the process of creating the Vietnam Wall app. In retrospect, I’d say the tools are robust and capable, if you know where to look. In order to create a clean and compelling app, it’s necessary to be conscious about all your pixels. Vietnam Wall isn’t a perfect design by any means, but I think it looks clean and works well, thanks mostly to Scott Hanselman and Jeff Wilcox, as well as the other links I’ve shared below.
These resources are key to getting started and knowing about the tools and processes to develop Windows Phone apps. Scott Hanselman’s volume is quite helpful, although after the 10th or so 6-hour session working on Vietnam Wall, I begin to curse his blog post’s title. Ha!
I used a Mango Local database. Turns out it’s not quite SQL CE 3.5, and you have to create and populate it in a very specific way, by creating a Windows Phone app and using the emulator to pump the data in using LINQ-to-SQL, then copying it from local storage to your “real” app. It seems like a rather convoluted process, but it works OK. In the end, it’s nice to have full LINQ access to a data store and not have to distribute any libraries (since the SQLCE drivers are included in the Windows Phone 7.5 OS).
I used with Telerik RadControls. As a Microsoft employee, I was able to snag a free (normally $99) license. I was happy with their support and the tile, progress bar and animation helper controls (as part of their custom Root Application Frame) were slick. In particular, I like how transition animations work when paging away from the tile controls (see it in action in Vietnam Wall). I also used their Diagnostics and Picker controls, which I think saved some effort over the CodePlex versions.
I figure I spent 60% of my time getting this app to look decent. Jeff Wilcox’s design guides for developers were infinitely helpful here, and I set out to apply his guidance as best I could. I also thought the MSDN resources were decent.
I had a pretty good experience developing my first app for Windows Phone. I bit off a fairly complex project (using a Local DB and providing some advanced search functionality), and ended up spending considerable time learning and applying the Metro design language and various Windows Phone design guidelines. I’d say the tools are fairly easy and good to work with (especially the Visual Studio/Blend pass-off), and the documentation is abundant and easy to find. Now that Vietnam Wall is out the door, developing additional apps will have a lot smaller learning curve.
When reading about how Microsoft does business, it’s quickly evident that we’re a metrics-driven organization. Even my wife, who works in strategic planning, mentioned that the instructor at a recent training class cited Steve Ballmer as a core example of someone who leads by scorecard.
On the surface, one might think this would be frustrating. Feeling micromanaged, like your time revolves around the numbers. If the numbers became out of sync with business reality, or if they were unreasonable, I might feel this way. But Microsoft leadership seems to be responsive to changes and suggestions each year, and the process gets me regularly thinking about creating goals that help grow our business, increase my impact, and help others succeed (among other things).
I work in a super competitive place. My compensation is partially awarded in the context of others in my pay grade, as well as the one above me. This means some very experienced, passionate, and intelligent people are vying for the same recognition that I am.
So each year I sit down a few times with my manager to tweak my “SMART” goals to help me stand out above my peers. In some ways, it’s a personal exercise rather than an organizational one. For instance, trying to figure out how to put a personal metric on increasing my exposure and influence is a little tough, and the output seems a little goofy. Statements about number of technical discussions outside my immediate team, for instance, represent my intention rather than a metric tied directly to business accomplishments. I think the point is more to consistently think about accomplishing the intention of goals, rather than the language itself.
The process isn’t flawless, and some of the metrics that get assigned to me may not fit exactly with my work conditions. Also, the goals are not explicitly examined as if they were an exam, so some aggressive goals I set (such as a new MCITP or MCPD certification) get lost in the shuffle if I don’t highlight them specifically. But, generally speaking, goal setting at MCS is a motivational process and has helped lead me down an interesting path towards a more visible presence within my team and at my customers.