Chrome to WP7: Support for Firefox, Opera, Safari, IE8/9

I’ve clearly named Chrome to WP7 poorly, because now it supports all major browsers.

I’ve created an accelerator for IE8 and IE9, and a bookmarklet for all other browsers (Firefox, Opera, Safari, et al).

You’ll need Chrome to WP7 first, then set up your browser.

Coming in v1.2: the ability to delete links and store data offline.

December 6, 2010

Chrome to Windows Phone 7

I’ve just submitted my second app, Chrome to WP7 to the Windows Phone marketplace.  The app has a very simple purpose, to give you the ability to quickly send links and selected text from within the Chrome browser, to your Windows Phone.

The Chrome extension may be downloaded here.

Chrome to WP7 is in the marketplace!

Chrome to WP7 works similarly to Chrome to Phone for Android.  A push notification is sent to the phone, which will show up as a toast, and upon opening the app, a list of your most recent links and text are available, regardless of whether or not the push notification succeeded.  From within the app, you may email the Title/URL/Text, or open the link.

Update! Now supporting Firefox, IE8/9, Safari and Opera.

Screenshots

Screenshots (Phone)

Chrome to WP7 is free.

November 19, 2010

Send Push Notifications to Windows Phone 7 from PHP

I couldn’t find a library for sending Push Notifications to Windows Phone 7 from PHP.  Most samples were using an ASP.NET web service.  For those of us who would like to run Push Notifications from cheaper PHP and cURL enabled hosting, I’ve created a little helper class: (The XML may be break below, so here is the Text Version)

class WindowsPhonePushPriority
{
    const TileImmediately = 1;
    const ToastImmediately = 2;
    const RawImmediately = 3;
    const TileWait450 = 11;
    const ToastWait450 = 12;
    const RawWait450 = 13;
    const TileWait900 = 21;	
    const ToastWait900 = 22;	
    const RawWait900 = 23;
}
 
class WindowsPhonePushClient
{
    private $device_url = '';
    private $debug_mode = false;
 
    function __construct($device_url)
    {
        $this->device_url = $device_url;
    }
 
    public function send_raw_update($msg, $priority = WindowsPhonePushPriority::RawImmediately)
    {
        return $this->_send_push(array('X-NotificationClass: ' . $priority), $msg);
    }
 
    public function send_tile_update($image_url, $count, $title, $priority = WindowsPhonePushPriority::TileImmediately)
    {
        $msg = "< ?xml version=\"1.0\" encoding=\"utf-8\"?>" .
                "<wp :Notification xmlns:wp=\"WPNotification\">" .
                   "</wp><wp :Tile>".
                      "</wp><wp :BackgroundImage>" . $image_url . "</wp>" .
                      "<wp :Count>" . $count . "</wp>" .
                      "<wp :Title>" . $title . "</wp>" .
                   " " .
                "";
 
        return $this->_send_push(array(
                                    'X-WindowsPhone-Target: token',
                                    'X-NotificationClass: ' . $priority,
                                ), $msg);
    }
 
    private function send_toast($title, $message, $priority = WindowsPhonePushPriority::ToastImmediately)
    {
        $msg = "< ?xml version=\"1.0\" encoding=\"utf-8\"?>" .
            "<wp :Notification xmlns:wp=\"WPNotification\">" .
                "</wp><wp :Toast>" .
                    "</wp><wp :Text1>" . $title . "</wp>" .
                    "<wp :Text2>" . $message . "</wp>" .
                "" .
            "";
 
        return $this->_send_push($url, array(
                                      'X-WindowsPhone-Target: toast',
                                      'X-NotificationClass: ' . $priority, 
                                      ), $msg);
    }
 
    private function _send_push($headers, $msg)
    {
        $ch = curl_init();
        curl_setopt($ch, CURLOPT_URL, $this->device_url);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
        curl_setopt($ch, CURLOPT_POST, true);
        curl_setopt($ch, CURLOPT_HEADER, true); 
        curl_setopt($ch, CURLOPT_HTTPHEADER,    // Add these headers to all requests
            $headers + array(
                            'Content-Type: text/xml',
                            'Accept: application/*'
                            )
            ); 
        curl_setopt($ch, CURLOPT_POSTFIELDS, $msg);
 
        if ($this->debug_mode)
        {
            curl_setopt($ch, CURLOPT_VERBOSE, $this->debug_mode);
            curl_setopt($ch, CURLOPT_STDERR, fopen('debug.log','w'));
        }
        $output = curl_exec($ch);
        curl_close($ch);
 
        return array(
            'X-SubscriptionStatus'     => $this->_get_header_value($output, 'X-SubscriptionStatus'),
            'X-NotificationStatus'     => $this->_get_header_value($output, 'X-NotificationStatus'),
            'X-DeviceConnectionStatus' => $this->_get_header_value($output, 'X-DeviceConnectionStatus')
            );
    }
 
    private function _get_header_value($content, $header)
    {
        return preg_match_all("/$header: (.*)/i", $content, $match) ? $match[1][0] : "";
    }
}

This code supports sending all three types of push notifications, Tile, Toast and Raw.

To use the class, simply include the file and call the constructor with the Device URL, which has already been uploaded to your server from the devices themselves.

November 15, 2010

Pandora One Media Keys – Enable them!

I really enjoy Pandora – and I recently bought the upgrade to Pandora One, since I listen to it at work most of the day.  Aside from the player being AIR-based, my only gripe is the lack of media key support.  I’ve put together a simple application that runs in the background, redirecting media key input to the Pandora One player.

  • .NET 2.0 – Windows 2000 to Windows 7
  • Only the Next and PlayPause keys are mapped.  The attached source code includes Like and Dislike as well.
  • if the player is minimized, it will be restored, so you’ll want to keep the player behind your other windows.
  • The player needs to be in the now playing state, if you’re at the list of stations, the keys won’t work.
  • If you’d like to run the program at startup, create a shortcut and place it in your Startup folder, on the start menu.

Download Pandora One Media Keys.  This is a tiny project, so I’m sharing the relevant parts of the source code if you’d like to do something other than map the Next and PlayPause keys.

If this app is useful to you, please donate. :)

June 27, 2010

ThumbPreview – Movable taskbar thumbnails

I’ve had this project hanging around for a long time – it’s not quite complete but it does a nice job of letting you preview a window like the windows 7 taskbar, but in a more persistent and flexible way.

It’s easy, just tap Win+Z to create a movable thumbnail window for the window you have in focus.

Check out the application page and download.

Video


Screenshots


March 27, 2010

WPF Windows 7 Explorer Toolbar Control

Today I have been working on emulating the Windows 7 Explorer Toolbar in WPF.  I really like this control as it blends the older toolbar and menubar concepts into one which may support icons and dropdown menus.

WPF makes creating new controls quite easy.  I decided to base my controls off of System.Windows.Controls.Toolbar, and similarly each item in the Toolbar is based off of the Button control.

Here’s the XAML that I came up with

Creating a new WPF application and using this code for Window1.xaml, you should see this:

Note that while this control is visually similar to the Windows 7 Explorer Toolbar, it does not handle overflow, or collapse menu items like the Explorer one does. Perhaps an eventual update to this control will provide more advanced support.

This control does handle the IsMouseOver, IsMouseDown, and IsKeyboardFocused states.  Adding the menu glyph is a WPF Polygon.

February 12, 2010

C# Threading Shorthand

As the complexity of an application increases, often so does the threading complication.  I have two snippets which often come in useful when dealing with threads in C#.

Quickly execute code in the background:

new Thread((ThreadStart)delegate()
    {
        // code here is executed on a new thread
        // blocking operations will not block the calling thread
    }).Start();

Note that if this code is to be called often, a ThreadPool may be the better choice. ThreadPools’ have less overhead for instances when many threads would be created and destroyed.

Execute code that manipulates UI:

if (Control.IsHandleCreated)
{
   Control.Invoke((MethodInvoker)delegate()
   {
        // code here is safe to interact with Control
   });
}

Replace ‘Control’ with ‘this’ inside the Form class. Control may refer to any control created on the UI thread.

January 22, 2010

TraceListener to a textbox

Trace, in System.Diagnostics is useful for determining where an application failed. .NET has build-in support for writing to the console or a file on disk, but it’s a little bit more complicated to direct this output to a TextBox on a windows form.

Here’s the class you need to get the trace information.

    class FormTracer : TraceListener
    {
        public delegate void OnTextHandler(string msg, bool newLine);
        public event OnTextHandler OnText;
 
        public override void Write(string message)
        {
            if (OnText != null)
                OnText.Invoke(message, false);
        }
 
        public override void WriteLine(string message)
        {
            if (OnText != null)
                OnText.Invoke(message, true);
        }
 
        public FormTracer()
        {
            Trace.Listeners.Add(this);
        }
 
         ~FormTracer()
        {
            Trace.Listeners.Remove(this);
        }
    }

When created, FormTracer will add itself to the tracers collection and start receiving messages. To add these messages to your form, create a FormTracer object like so:

        public Form1()
        {
            InitializeComponent();
 
            FormTracer ft = new FormTracer();
            ft.OnText += new FormTracer.OnTextHandler(ft_OnText);
        }

The event handler may be called on threads outside the UI, so you’ll want to make the OnText handler look something like this

        void ft_OnText(string msg, bool newLine)
        {
            if (this.IsHandleCreated)
            {
                this.Invoke((MethodInvoker)delegate()
                {
                    textBox1.Text += msg;
                    if (newLine) textBox1.Text += "\r\n";
                });
            }
        }

Add a button and handle the Click event for a test Trace message.

          private void button1_Click(object sender, EventArgs e)
        {
            Trace.WriteLine("Button Pressed!");
        }
January 16, 2010

GVNotifier brings Google Voice SMS to the desktop

Welcome Lifehacker!  Follow @davux on twitter!

This is an old version, get the latest GVNotifier here.

This project is superseding the DigsbyGV project.  GVNotifier brings Google Voice services to the desktop in the form of a notification app.

GVNotifier.net supports one-click calling right from the SMS window.

Click the tray icon to display your personalized favorite list.  Contacts are placed on this list if they appear in the inbox.

Send messages to users not in the recent list.

Download:

GVNotifier requires the .NET Framework 3.5 and Windows XP, Windows Vista or Windows 7.  Aero recommended.

GVNotifier.net 1.0 [ClickOnce Install]

Update: 11/19/09 (Build 20)

– A bug that prevented the ‘call’ button from working has been fixed.

Update 11/20/09 (Build 50)

– Fixed a bug loading contacts without names.

– Fixed a UI animation bug.

– Included dialog to send a message to any number.

– Fixed ‘Check for updates’ in About dialog.

– Added option to check for new SMS messages by middle-clicking the tray icon, or selecting the menu option.

– Smooth loading of contact list.

Update 11/21/09 (Build 52)

– ClickOnce installer now manages updates.

– Possible fix for sending SMS on certain GV accounts.

Update 11/22/09

– If you’re having trouble sending SMS and would be willing to let me log into your account so I can figure out why, please let me know!  Several users have reported being unable to send SMS.  I’m unable to reproduce the problem with any of my accounts.

Update 11/25/09 (Build 70)

– Fixed an issue that was causing HTTP 500 errors for some users.  Try using –mobile if it still isn’t working.

Update 11/26/09 (Build 80)

– Fixed some possible issues with logging in.  If you were unable to login (RNR_SE is missing, Invalid User/Pass), get the update and try again.  Restart twice to get the updater to launch.

November 18, 2009

Ping remote host in Javascript using WMI

I’ve been working on a simple Windows Sidebar Gadget that will determine if a remote host is online or not. For the connectivity test I chose ping, since it’s lightweight and unlikely to disturb any services on a device.

Ping using WMI

function Ping(host)
{
	var wmi = GetObject("Winmgmts:");
	var eStatus = new Enumerator(wmi.ExecQuery(
"Select StatusCode from Win32_PingStatus Where Address='" + host + "'"));
	return eStatus.item().StatusCode == 0;
}

The function Ping will return true if the host is online, false otherwise. Optionally, a Timeout parameter may be specified in the WMI query.

September 27, 2009