2008年07月10日

x64環境でVS2008のATLスマートデバイスプロジェクトがビルドできない件

結論: 単純に、include/lib設定が Program Files (x86) に対応してないだけでした。

既定値で動かないのは明らかにテスト不足だと思います。>VS開発チーム
(ひょっとしたら、うちの環境の作る順番とか原因かもしれないけど...)

具体的に言うと、Wizardでプロジェクト作るだけで、

midl : command line error MIDL1001 : cannot open input file oaidl.idl

こんなビルドエラー。

対策としては、

[ツール]/[オプション]/[プロジェクトおよびソリューション]/[VC++ディレクトリ]
の、

[プラットフォーム] → 作成したいWindows Mobile環境
[ディレクトリを表示するプロジェクト] → [インクルード ファイル] と[ライブラリ ファイル]

を開くと、

C:\Program Files\Windows Mobile 5.0 SDK R2\PocketPC\include\ARMV4I
C:\Program Files\Windows Mobile 5.0 SDK R2\PocketPC\include

とかなっていると思います。

x64環境で、Windows Mobile SDKは通常 Program Files (x86)にインストールされるので、[Program Files] → [Program Files (x86)] と変更するだけ。

あと、おかしいなー、と思ってMIDLの[追加のインクルードファイル]にフルpathを入れたら、空白を含むpathに対応してなかったのもちょっと酷いかも...。

2008年07月09日

ATLアプリでDPAPIを使用するサンプル

Win32のDPAPIをC++/ATLで使用するサンプルがあまりないので公開。

DPAPIを使用すると、システムがWindowsのユーザープロファイルから暗号鍵を生成するため、アプリケーションはキーの管理をすることなくデータの暗号化が可能です。
dwFlagsにCRYPTPROTECT_LOCAL_MACHINEを指定すると、ユーザーではなくシステムプロファイルで解読可能となります。

CAtlArray<BYTE> cypherBytes;
CryptDPAPI::Encrypt(L"DPAPI sample", cypherBytes);
CString strPlain = CryptDPAPI::Decrypt(cypherBytes); 
#pragma once
#pragma comment(lib, "Crypt32.lib")

#include "stdafx.h"
#include <Wincrypt.h>
#include <atlcoll.h>
#include <atlstr.h>


class CryptDPAPI
{
public:
    static DWORD Encrypt(LPCTSTR szSource, CAtlArray<BYTE> &result, LPCTSTR szDescription = L"", DWORD dwFlags = 0L)
    {
        DATA_BLOB plainData;
        DATA_BLOB cypherData = {0};

        plainData.pbData = (BYTE *)szSource;    
        plainData.cbData = (lstrlen(szSource)+1) * sizeof(TCHAR);

        if(CryptProtectData(&plainData, szDescription, NULL, NULL, NULL, dwFlags, &cypherData))
        {
            result.SetCount(cypherData.cbData);
            ::CopyMemory(&result[0], cypherData.pbData, cypherData.cbData);
            LocalFree(cypherData.pbData);

            return cypherData.cbData;
        }
        return 0L;
    }

    static CString Decrypt(CAtlArray<BYTE> &cypherBytes, LPTSTR *pszDescription = NULL, DWORD dwFlags = 0L)
    {
        return Decrypt(&cypherBytes[0], cypherBytes.GetCount(), pszDescription, dwFlags);
    }

    static CString Decrypt(BYTE *pCypherBytes, DWORD count, LPTSTR *pszDescription = NULL, DWORD dwFlags = 0L)
    {
        DATA_BLOB cypherData;
        DATA_BLOB plainData = {0};
        cypherData.pbData = pCypherBytes;
        cypherData.cbData = count;
        if (CryptUnprotectData(&cypherData, pszDescription, NULL, NULL, NULL, dwFlags, &plainData))
        {
            CString strResult;
            strResult = (LPTSTR)plainData.pbData;
            LocalFree(plainData.pbData);

            return strResult;
        }
    }
};

おかしなところなどあれば乞ご指摘。

2008年06月19日

IEツールバーにXP ビジュアルスタイルを適用するVS2005/2008編

ちょっとやり方を見つけるのにものすごく時間と労力がかかることがある。
これもそんなひとつ。

ATLとIBandObject でIEツールバーを作っていると、そのままの状態ではLunaスタイルが適用されなくて、他のGoogleツールバーなどと並べると、カクカクしててしょぼいボタンになってしまったりする。

で、XPのビジュアルスタイルなんてmanifest書くだけじゃん、と思ったらこれがハマった。
リソースに

ISOLATIONAWARE_MANIFEST_RESOURCE_ID RT_MANIFEST "FooBar.dll.manifest"

とか書いてみたら、ビルドすると「出力を登録できませんでした」。
ぇぇー、と思っていろいろCut&Tryしてもさっぱり。

結局なんのことはない、VS2005以降ではVisual Studioが勝手に*.dll.embed.manifestを生成して組み込むようになってて、マニフェストが2重になってただけでした。

VS2005/2008時代のマニフェストの登録方法:

1. 以下のようなマニフェストファイルをプロジェクトに追加

CommCtrl.manifest (ファイル名はまぁなんでもいい)
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly
  xmlns="urn:schemas-microsoft-com:asm.v1"
  manifestVersion="1.0">
  <dependency>
    <dependentAssembly>
      <assemblyIdentity
        type="win32"
        name="Microsoft.Windows.Common-Controls"
        version="6.0.0.0"
        processorArchitecture="*"
        publicKeyToken="6595b64144ccf1df"
        language="*"/>
    </dependentAssembly>
  </dependency>
</assembly>

2. 「プロジェクトのプロパティ/構成プロパティ/マニフェスト ツール/入力と出力/追加のマニフェスト ファイル」に上記のマニフェストファイル(CommCtrl.manifest)を追加。

3. stdafx.hに

#define ISOLATION_AWARE_ENABLED    1

を追加。

以上でなんとかなる、はずです。

2008年05月09日

MT更新のテスト 兼 小ネタ

新しい環境に移行中なので、ついでに今まで気になっていた各種設定を見直しています。

1. Firefox関連:

  • ブックマークをフォルダ優先でソートする
  1. [ブックマーク] メニューを開く
  2. メニュー上で右クリック
  3. [名前順に並び替え]

IEメインの人がFirefoxの初期値で一番イライラするのはたぶんきっとコレ。
前は人力でえっちらおっちらソートしていた...(涙)。
[ブックマークの管理] にもそのような機能・設定は無く、一見並び順でフォルダを優先させることはできないように見えるが、なぜか右クリックメニューからソートした場合のみフォルダが優先される。
(id:ZIGOROuさんにchromeでのソースの場所を教えてもらって発覚。Thanksです!)

  • Ctrl + Tabで最新のページの順でタブを切り替える
  1. Firefox拡張 Ctrl-Tab を入れてみた。
    http://en.design-noir.de/mozilla/ctrl-tab/

個人的にFirefoxが一番気に入らないポイントだったのでなんとかする。
プレビューはいらないんだけどな...。
ちなみに、IEも規定値は違うけど[ツール]/[インターネットオプション]/[詳細設定]/[ブラウズ]/[Ctrl+Tabでタブを切り替えるときに、最新のページ順で切り替える]をOnにするとできる。(確かβの頃まではOnだったから他のブラウザに合わせたとみられる)

  • タブの横に新規タブボタンを付ける
    1. Firefox拡張 New Tab Button on Tab Bar 2.0 を入れてみた。

さらにIE7っぽくということで。
右側に出たほうが直観的だと思うんですけどね...。
(そのままだとFF3では動かない?というコメントあり)

2. Windows Live Writer 2008 + Movable Type の初期設定

  • ブログのパスワードには [Web サービスのパスワード] を使用する

前のマシンはβ版から上書きしてたので、設定項目が変わってて焦った。
とはいえ、前に比べて単に項目が減っただけだった。

[Web サービスのパスワード] の確認方法:

  1. MTの管理画面にログイン
  2. 右上の自分のユーザー名をクリック
  3. 一番下の [Web サービスのパスワード] を確認

3. 検索バーから新しいTabを開く

  • Firefox
    1. キーワード入力 → Alt + Enter

標準の検索BoxでもGoogle Toolbarでも同様。

  • IE7
    1. IE7 + Google Toolbar
      キーワード入力 → Ctrl + Enter
    2. IE7の検索Box
      キーワード入力 → Alt + Enter

まー、どれも改まって書くほどのことでもないですが、自分用に覚書として。

2008年04月08日

Japanize for Internet Explorer Version 1.03

Firefox版拡張とほぼ同等の機能を実現し、Pre-ReleaseしたVersion 1.02の問題点を修正したJapanize for Internet ExplorerのVersion 1.03をリリースいたしました。

Japanize for Internet Explorer 1.03
http://japanize.31tools.com/

Version 1.02からの主な変更点:

  1. 翻訳対応サイトにファイルのダウンロードページが存在し、ページ内でIEの情報バー(ページ上部の黄色いメッセージ)が表示された場合、ブラウザがハングアップするケースが発見されたので修正。

Version 1.00からの主な変更点(再掲載):

  1. サイト設定機能を追加
    任意のサイトに対して、翻訳の有無を選択することが可能になりました。
  2. 翻訳データのローカルディスクへのキャッシュ機構を実装
    これまで、ページ毎にダウンロードしていた翻訳データをローカルディスクへ保存します。
    また、翻訳データの更新方法を変更することも可能です。
  3. 未翻訳サイトへの翻訳スクリプト挿入を抑制
    UserScript版をベースとしていたスクリプトの挿入機構をネイティブコードで実装し高速化と安定性の向上を実現しました。 
  4. 一部表記の変更
  5. その他bugfix, 安定性向上

(Version 1.02 詳細)

IEのDOMオブジェクトの仕様により、翻訳内容はFirefox版に若干見劣りする部分もありますが、ブラウザ拡張としての安定度はかなり向上しているため、ぜひこの機会にお試しいただければと思います。

2008年04月07日

Silverlight 2 SDK+JavaScriptで無償の開発環境を作る #4 [アニメーションとメディア編]

[ソースコードをダウンロード]
(download sample source code)

ちまちま書いてきましたが、もう少しSilverlightらしいことを、ということで、次は、アニメーションとメディアを利用したサンプルです。

image

リストから選択した動画を再生して、半透明で回転させます。

さすがにちょっと長くなりますが、そんなに複雑じゃありません。

<UserControl
  xmlns="http://schemas.microsoft.com/client/2007"
   xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
   x:Class="System.Windows.Controls.UserControl"
   x:Name="JSSample5">

  <StackPanel Orientation="Vertical" >

  <ListBox x:Name="list_movie">
    <ListBoxItem Content="SPIDER" />
    <ListBoxItem Content="CAR" />
    <ListBoxItem Content="5cm" />
  </ListBox>

  <MediaElement x:Name="video" Source="" Width="0" Height="0"/>
  <StackPanel Orientation="Horizontal">
    <StackPanel.Background>
      <ImageBrush ImageSource="http://silverlight.net/Themes/silverlight/images/logo.jpg"/>
    </StackPanel.Background>
    <Rectangle Width="320" Height="240">
      <Rectangle.Fill>
        <VideoBrush SourceName="video" />
      </Rectangle.Fill>
    </Rectangle>
    <TextBlock Text="転" 
      FontSize="180" FontWeight="Bold" TextWrapping="Wrap" Opacity="0.5">
      <TextBlock.RenderTransform>
         <RotateTransform x:Name="rotater" 
           Angle="30" CenterX="120" CenterY="120" />
      </TextBlock.RenderTransform>
      <TextBlock.Foreground>
        <VideoBrush SourceName="video" />
      </TextBlock.Foreground>
    </TextBlock>
  </StackPanel>

  <StackPanel.Triggers>
    <EventTrigger RoutedEvent="StackPanel.Loaded">
      <BeginStoryboard>
        <Storyboard x:Name="myStoryboard">
        <DoubleAnimation Storyboard.TargetName="rotater" 
          Storyboard.TargetProperty="Angle" From="0" To="360" 
          Duration="0:0:50" RepeatBehavior="Forever" />
        </Storyboard>
      </BeginStoryboard>
    </EventTrigger>
  </StackPanel.Triggers>

  </StackPanel>
</UserControl>
Import("System.Windows.Application")
Import("System.Windows.Controls")
Import("System.Windows.Controls.UserControl")
Import("System")

function App() {
   this.scene = Application.Current.LoadRootVisual(new UserControl(), "app.xaml")
}
App.prototype = {
    start:function() {
        this.scene.list_movie.SelectionChanged += function (s,e){
            var url = app.movies[s.SelectedItem.Content];
            s.Parent.video.Source = new System.Uri(url);
        }
    },
    movies:{
        "SPIDER":"http://www.sonypictures.com/movies/spiderman2/video/sm2_teaser_high.asx",
        "CAR":"http://www.disney.co.jp/movies/cars/yokoku/media/eng_300k.wmv",
        "5cm":"http://rd.yahoo.co.jp/tokushu/5cm/teaser01/?http://i.yimg.jp/images/evt/5cm/teaser8000k1280_720.wmv"
    }
}

app = new App;
app.start();

動画のリンク先がちょっとアレですが、サンプルってことで許してください。
flvが使えないのがSilverlightの辛いところ...。

まずは、新しい要素のListBoxですが、

<ListBox x:Name="list_movie">
  <ListBoxItem Content="SPIDER" />
  <ListBoxItem Content="CAR" />
  <ListBoxItem Content="5cm" />
</ListBox>

これは、まぁ見たままです。
ListBoxコントロールにListBoxItemコントロールを子要素として持たせています。
ちなみに、このアイテムの追加部分は、JS側で、

var arr = ['SPIDER','CARS','5cm'];
this.scene.list_movie.ItemsSource = arr; 

などと処理することもできます。(+イベントハンドラに若干修正が必要)

次に、

<MediaElement x:Name="video" Source="" Width="0" Height="0"/> 

このMediaElementは、ビデオ再生に利用しています。
ここでは、さらにこの動画を別の要素に張り込むため、サイズが0x0pxの不可視コントロールであるローダーとしてのみ使用。
実際の動画アドレスの設定はコード側でSourceプロパティに対して行っています。

そして、ここで「video」として定義したMediaElementを参照しているのが、

<Rectangle Width="320" Height="240"> 
  <Rectangle.Fill> 
    <VideoBrush SourceName="video" /> 
  </Rectangle.Fill> 
</Rectangle>

こちらのRectangleコントロール。
塗りつぶし要素として<VideoBrush>を使用し、videoを参照しています。

もう一つの、TextBlockはもう少し複雑です。

<TextBlock Text="転" 
  FontSize="180" FontWeight="Bold" TextWrapping="Wrap" 
  Opacity="0.5"> 
  <TextBlock.RenderTransform> 
     <RotateTransform x:Name="rotater" 
       Angle="30" CenterX="120" CenterY="120" /> 
  </TextBlock.RenderTransform> 
  <TextBlock.Foreground> 
    <VideoBrush SourceName="video" /> 
  </TextBlock.Foreground> 
</TextBlock> 

基本的には「転」と書かれたTextBlockですが、ここでTransform(変形)オブジェクトを用いて、<TextBlock.RenderTransform>と<RotateTransform>を使うことでとりあえず30度回転させ、 <TextBlock.Foreground>で、前面の塗りつぶしとして、同じくvideoを参照しています。
<RotateTransform>は次のアニメーション用ストーリーボードで値を変更するために「rotater」と命名してあります。

最後に、StackPanelにアニメーション動作の引き金となるトリガとその実体を追加しています。

<StackPanel.Triggers> 
  <EventTrigger RoutedEvent="StackPanel.Loaded"> 
    <BeginStoryboard> 
      <Storyboard x:Name="myStoryboard"> 
      <DoubleAnimation Storyboard.TargetName="rotater" 
        Storyboard.TargetProperty="Angle" From="0" To="360" 
        Duration="0:0:50" RepeatBehavior="Forever" /> 
      </Storyboard> 
    </BeginStoryboard> 
  </EventTrigger> 
</StackPanel.Triggers>
  • 「StackPanelがロードされたら」
  • 「rotaterのAngleプロパティを」
  • 「0~360°まで」
  • 「50秒間で」
  • 「double値のアニメーションを行うストーリーボードを実行せよ」

というトリガが定義されています。

このようにアニメーションをXAML側で定義できてしまうため、さまざまな動的デザイン要素をプログラマではなくデザイナが定義することが可能になるわけです。
ここでは、XAMLを手書きしていますが、Expression Blendなどのデザインツールを使用すれば、FlashライクにGUIでタイムテーブルを編集してストーリーボードを作成することでアニメーションを定義できます。
また、Expression Blendでの編集結果をその場でXAMLとして堪忍できる点がSilverlightやWPFの面白いポイントだと言えるでしょう。
タグで見ていると頭がワヤになりますが、Blendを使って図形をぐりぐり動かしつつ出力されたXAMLをチェックしてみることで、Silverlightを使ってどのようなアニメーションが実現できるかを探ることができると思います。

以上、駆け足ですが、Silverlightの環境構築から、基本的なXAMLの書き方などSilverlightアプリ作成の基礎をまとめてみました。
Windowsやクライアントアプリにこれまで全く縁がない方々でも、基本的な部分さえわかってしまえば、Javascript、Python、Rubyなどの言語を利用することができ、なおかつ(今のところ)ブラウザ間の互換性をほとんど意識する必要もなく、比較的多くの環境で動作するリッチアプリケーションを作ることができる点がSilverlight2の一つのポイントだと思います。

Silverlight2による開発は、ほぼどんな環境でも利用可能で、ライセンスも不要、というわけで手軽に始めることができますので、このエントリーが興味を持っていただくきっかけになれば幸いです。

#1 [環境整備編]に戻る...

Silverlight 2 SDK+JavaScriptで無償の開発環境を作る #3 [参照と配置編]

[ソースコードをダウンロード]
(download sample source code)

今度はミニマムなフォームを作ってみましょう。

<UserControl 
    xmlns="http://schemas.microsoft.com/client/2007" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
    x:Name="JSSample4"> 
  <StackPanel> 
    <TextBlock x:Name="label_top" Text="What's your name?" /> 
    <TextBox x:Name="text_name" /> 
    <Button x:Name="cmd_submit" x:Content="submit" /> 
  </StackPanel> 
</UserControl> 

と書いてみますが、これはそのままだとchironでは動いてくれません。

Silverlight2で利用可能なコントロールにはcore APIとlibrary API群に分けられており、純粋にコアとなるのSilverlightランタイムには最小限のコントロールしか用意されていません。
このため、たとえボタンのように一見標準コントロールのように見えてもlibraryに追い出されているコントロールがあるのです。
Visual Studioを使用したCLRアプリであれば、参照設定などもできるのですが、現時点で私が見つけているchironから利用可能な方法はもう少し回りくどい方法になります。

これを解決するためにappフォルダに新しい定義ファイル
app\AppManifest.xaml
を追加します。

<Deployment 
    xmlns="http://schemas.microsoft.com/client/2007/deployment" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
    RuntimeVersion="2.0.30226.00" 
    EntryPointAssembly="Microsoft.Scripting.Silverlight" 
    EntryPointType="Microsoft.Scripting.Silverlight.DynamicApplication"> 

  <Deployment.Parts> 
    <!-- Core DLR and DLR <-> Silverlight shim assemblies --> 
    <AssemblyPart Name="Microsoft.Scripting.Silverlight" 
        Source="Microsoft.Scripting.Silverlight.dll" /> 
    <AssemblyPart Source="Microsoft.Scripting.dll" /> 

    <!-- Language assemblies --> 
    <AssemblyPart Source="Microsoft.JScript.Compiler.dll" /> 
    <AssemblyPart Source="Microsoft.JScript.Runtime.dll" /> 

    <!-- Silverlight SDK controls assemblies --> 
    <AssemblyPart Name="System.Windows.Controls" 
        Source="System.Windows.Controls.dll" /> 
  </Deployment.Parts> 
</Deployment> 

これで、まずはOk。

image

そして、フォームのイベントハンドラをapp.jsに追加します。

Import("System.Windows.Application")
Import("System.Windows.Controls.UserControl")

function sample_app() {
    this.scene = Application.Current.LoadRootVisual(new UserControl(), "app.xaml");
}
sample_app.prototype = {
    start:function() {
        this.scene.cmd_submit.Click += function(s,e){
            s.Parent.label_top.Text = "Welcome ";
        }
        this.scene.cmd_submit.Click += function(s,e){
            s.Parent.label_top.Text += s.Parent.text_name.Text + "!";
        }
    }
}

app = new sample_app;
app.start();

これでフォームのボタンが動作したと思います。

image

このコード、JSの使い手の方なら、ボタンのイベントハンドラの追加部分に違和感を感じると思います。

this.scene.cmd_submit.Click += function(s,e){
   s.Parent.label_top.Text = "Welcome ";
}
this.scene.cmd_submit.Click += function(s,e){
    s.Parent.label_top.Text += s.Parent.text_name.Text + "!";
}
一般のJSであれば、Clickイベントに=でfunctionを代入するところですが、SilverlightのManaged Javascriptでは += でdelegate(デリゲート)を使用します。C#や.NETの特徴の話でよく出てくる奴ですね。

これにより、このサンプルのように、特に意識する必要なく、複数のイベントハンドラを一つのイベントに割り当てることができます(厳密に言うと、この場合マルチキャスト デリゲートかな)。functionはイベントに追加された順に呼び出されます。 delegateを使用することで、元のイベントハンドラをローカル変数に保存してイベントチェーンを...、などという手間が必要なくなるわけです。delegateの詳細に関しては別途いろいろ調べてみてください。

Silverlightコントロールのxap化と配置:

次に、コマンドラインオプションを変更してchironを起動してみましょう。
chiron /z:app.xap
これで、プロジェクトルートのindex.htmlの隣にapp.xapファイルが作成されたと思います。
このapp.xapファイルと、最初に作成したプロジェクトルートのindex.htmlをサーバーに登録すれば、Silverlightの配置は完了です。
(サーバーに.xapのMIMEタイプ(application/x-silverlight-app)の登録も必要)

xapファイルはイメージ的にはFlashのswfファイルに近いSilverlightアプレットファイルですが、JSのコードがコンパイルされてバイナリになっているわけではありません。
試しに、app.xapのファイル名をapp.xap.zipへリネームしてみれば、zip形式のアーカイブになっているのが確認できると思います。

image

Office2007のOffice Open XML形式(docxとかxlsxとか)と同じ、最近のMicrosoftのお得意の手口ですね。
また、このアーカイブにはこのアプリから参照設定されている各種DLLが含まれているのも確認できると思います。

これを踏まえた上で、AppManifest.xaml内の

EntryPointAssembly="Microsoft.Scripting.Silverlight" 
EntryPointType="Microsoft.Scripting.Silverlight.DynamicApplication" 
に注目してください。

CLRによる.NETコンポーネントに対応したSilverlight2では、DLRアプリの場合もCLRコンポーネントであるMicrosoft.Scripting.Silverlightがエントリーポイントとして呼び出され、これがDLRとしてLLにより書かれたコードをダイナミックにロードしていく形になります。
クライアントにインストールされたSilverlightランタイムが直接JSを実行しているわけではなく、xap内に収められたMicrosoft.Scripting.Silverlight.dllを呼び出しているため、これによって、コントロールを追加する、など、Silverlight自体の機能をダイナミックに拡張できる構造となっているようです。
この点を頭に入れておくと、モジュールのロードプロセスの理解やdebugの際のイメージに役立つでしょう。

[アニメーションとメディア編]へ続く...

Silverlight 2 SDK+JavaScriptで無償の開発環境を作る #2 [XAML基礎編]

[ソースコードをダウンロード]
(download sample source code)

さて、環境はできました、でもSilverlightってナニ? さっぱりですよ? という方々のために、とりあえず基礎の基礎だけ解説します。

先の[環境整備編]でも書いたように、基本的なSilverlightアプリの構造は、
XAML(ザムル)によるマークアップ + コーディング(.NET or LL)
です。

Silverlight2からは、どのプラットフォーム(IE,Firefox,Safari,Windows,Mac、先々はMoonlightでLinux)でもCLRが動き、.NETが利用可能ですよ、どこでもC#やVB.NETが使えますよ、というところが一つの売りではあるのですが、ここでは.NET周りについては全く触れません。

また、Silverlightと言うと、Flash対抗馬、的なとらえ方がよくあると思うのですが、むしろポストHTMLととらえて、HTML+CSS+JSをXAML+JS他に置き換えて考えてみると良いと思います。
SilverlightのXAMLはWPF使われているモノのサブセットなのですが、それもここではスルー。

さて、回りくどい話は置いておいて、さっさとXAMLを書いてみることにしましょう。

XAMLによるレイアウトと属性:

前回と同様に新しいフォルダを作り、
index.html
app\app.xaml
app\app.js
を配置します。
とりあえず、内容もそのままでapp.xamlだけ変更してみましょう。

<UserControl
    xmlns="http://schemas.microsoft.com/client/2007"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    x:Class="System.Windows.Controls.UserControl"
    x:Name="JSSample2">
  <StackPanel>
    <TextBlock Text="foo" />
    <TextBlock Text="bar" />
    <TextBlock Text="baz" />
  </StackPanel>
</UserControl> 

image

新しい要素、<StackPanel>が登場しました。
StackPanelは文字通り配下のコントロールを順番に積み上げてくれるだけのレイアウト用コントロールです。
さらに、

  <StackPanel> 
    <StackPanel Orientation="Horizontal"> 
      <TextBlock Text="hoge" /> 
      <TextBlock Text="fuga" /> 
      <TextBlock Text="piyo" /> 
    </StackPanel> 
    <TextBlock Text="foo" /> 
    <TextBlock Text="bar" /> 
    <TextBlock Text="baz" /> 
  </StackPanel> 

image

とすると、横にも並べられます。

レイアウト系でStackPanelと並んで代表的に使われるのが、Gridコントロールです。
次の例はちょっと複雑になりますが、さらに一歩進んだXAMLの構文が使われています。

<UserControl
    xmlns="http://schemas.microsoft.com/client/2007"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    x:Class="System.Windows.Controls.UserControl"
    x:Name="JSSample3">
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="*"/>
            <RowDefinition Height="*"/>
        </Grid.RowDefinitions>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="*"/>
            <ColumnDefinition Width="*"/>
        </Grid.ColumnDefinitions>
        <TextBlock Grid.Column="0" Grid.Row="0">foo</TextBlock>
        <TextBlock Grid.Column="1" Grid.Row="0">bar</TextBlock>
        <TextBlock Grid.Column="1" Grid.Row="1">baz</TextBlock>
        <Rectangle Width="160" Height="160" Grid.Column="0" Grid.Row="1">
          <Rectangle.Fill>
            <ImageBrush ImageSource="http://www.microsoft.com/silverlight/images/logo.png"/>
          </Rectangle.Fill>
        </Rectangle>
    </Grid>
</UserControl>

image

Grid(格子)上に列と行を2つずつ定義し、TextBlockの属性として追加された Grid.Column="1" Grid.Row="0" などのAttached Property(添付プロパティ)によって、各々のコントロールがグリッド上でどこに配置されるかが記述されています。

また、このサンプルでは、<Grid.RowDefinitions>や<Rectangle.Fill> のように、子要素となるタグの中で親要素のプロパティを設定しています。
XAML要素のプロパティ設定は、先の例の<StackPanel Orientation="Horizontal"> のようなAttrubyte Syntaxと、この子要素を利用したProperty Element Syntaxの併用が可能です。基本的にどちらの書式で書くこともできますが、一行の文字列に収める制約が無い子要素によるProperty Element Syntaxの方がより複雑で入り組んだ設定が可能です。

[参照と配置編]へ続く...

Silverlight 2 SDK+JavaScriptで無償の開発環境を作る #1 [環境整備編]

先日公開されたSilverlight2のSDKを利用すると、Visual StudioやExpression Studio等の開発環境やアプリを全く利用することなく、素の状態のWindows (いや、それどころかMacでも...) でSilverligh2の開発を行うことができます。

やり方がわかってしまえば非常に単純なのですが、そもそもSilverlight2でDLR(Dynamic Language Runtime: LL実行環境)を使用した開発に関する情報がまだほとんど出回っておらず、いろいろ苦労したので、そのあたりをまとめておきます。
以下、ちょっとクド目ですが、素のWindowsにnotepad(メモ帳)だけで開発できるよ、という手順をご紹介。

必要な環境:

  • Windows XP 以降
  • .NET Framework 2.0 (たぶん)
  • 英語が読める人 (現時点でほとんどの資料は英語)

余談ですが、.NET FrameworkやSilverlightのランタイムは基本的にインストールするだけでは他に影響を与えるモノではないので、なんか得体が知れなくてイヤだなぁ、とか思ってもよっぽどディスクの残りが少ないとかいうことでなければ、インストールしても害はないですよ...。

Silverlight2 ランタイムのインストール:

(Express Edition以外の)Visual Studio 2008ユーザーの人は Visual Studio 2008 用 Microsoft Silverlight Tools をインストールすれば、Silverlight2ランタイムとSDKも同時にインストールされるので、このプロセスは不要です。

SDKの導入の前に、まずはSilverlightのランタイムを入れましょう。
公式サイト、silverlight.netへアクセスします。
http://silverlight.net/

image
いきなり↑のように、「Silverlightが入ってないよ(意訳)」と言われたら、Silverlight 1.0のランタイムが未だインストールされていないようです。

ここで取り上げるのはSilverlight 2.0なので、1.0のランタイムは必ずしも必要ありませんが、まぁあって困るわけではないので入れておきましょう。
1.0と2.0の違いや過去の経緯についてはあちこちで書かれているモノがあると思うのでここでは触れません。
image
まぁ、基本的にOk,Okしてけばインストールは終わります。この辺のプロセスもシームレスでよくできています。英語だけど...。

さて、今度は2.0のランタイムです。
image 
silverlight.netトップページ上部のメニュー[Get Started]から
http://silverlight.net/GetStarted/
へアクセスします。

次に、ページ内の、
Silverlight 2 Beta Runtime & Tools
Silverlight 2 Beta 1 Runtimes
から、
image
Windows - Silverlight 2 Beta 1 Runtime
http://www.microsoft.com/silverlight/resources/installationFiles.aspx?v=2.0
へアクセス。

インストールページでWindowsロゴのボタンをクリックします。
image
Silverlight2.exeのダウンロードが始まるので、そのまま保存するか直接実行。
image
今度のインストーラーは日本語ですね。
日本語未対応の1.0をスキップして、まだβの2.0から始める理由はここにもあります。

Silverlight 2 SDK の導入:

次はいよいよSDKのダウンロードです。
GET STARTEDのページに戻って、
image
Silverlight 2 Beta 1 SDK
http://www.microsoft.com/downloads/details.aspx?FamilyId=4E03409A-77F3-413F-B108-1243C243C4FE&displaylang=en
のダウンロードを行います。

ダウンロードされたsilverlight_sdk.exeを実行すれば、インストールが行われます。
image
SDKはお手軽なアプリやツールと違うので、基本的にはファイルがコピーされるだけです。
スタートメニューには[Welcome]のドキュメントが一つ登録されるだけなので、とりあえず開いてみましょう。
image

ライセンスやイスントール物の説明がさらっと英語で書かれていますが、まーただのリンク集です。
ページ中ほどの[Tools]のリンクをクリックしてみましょう。
image
規定値でインストールしていれば、
C:\Program Files\Microsoft SDKs\Silverlight\v2.0\Tools
(x64版Windowsならば C:\Program Files (x86)\Microsoft SDKs\Silverlight\v2.0\Tools)
image
フォルダが表示されます。

ここに置かれている[Chiron] (カイロン又はケイロン)が今回の話の肝になるツールです。
実体としては、ここにある、Chiron.exe 一つだけがSilverlight2の開発環境となります。(基本的な使い方は同じフォルダにあるReadme.txtにも書かれているので、目を通しておくといいです)
xapパッキングツール・実行用ローカルサーバーなどを1つのexeで兼ねており、コマンドラインからオプションを指定して使用します。
ので、いざ開発へ、と移るためにこのchiron.exeにpathを通しておかないといけません。

またまた余談ですが、なんとなくWindows開発なんて知らん、という人もいそうなので書いておくと、環境変数は、
  コントロールパネル/システム/システムの詳細設定/環境変数
で設定もできますが、開発関連のpathは何でも入れてしまうのではなく、それぞれbatファイルにしておいて、各種batファイルを一つのフォルダ(例えばc:\bat\)に集めておいて、ユーザー環境変数設定で、%path%;c:\bat\ などとしておくと、お行儀がよく融通が効くのでよいかと思います。

なお、先ほどのWelcomeのドキュメントから、Silverlight SDKドキュメントのCHM(HTML Help)版をダウンロードしておくとネットを使わずに素早く検索できるのでお勧めです。

image
http://go.microsoft.com/fwlink/?LinkId=111131

プロジェクトの作成:

さて、ではシンプルなプロジェクトを作ってchironの動きを見てみましょう。

とりあえず、適当にフォルダを作ります、ここでは、
c:\samples\js_sample1
として、以下、このフォルダをプロジェクトのルートフォルダとします。
ここに
index.html
を作成します。
内容はこんな感じ。

<html xmlns="http://www.w3.org/1999/xhtml">
<head>
    <title>Silverlight Javascript sample</title>
</head>
<body>
    <object data="data:application/x-silverlight," type="application/x-silverlight-2-b1" width="100%" height="100%">
        <param name="source" value="app.xap"/>
    </object>
</body>
</html>

要するにSilverlight2コントロールを張った空のHTMLファイルです。

さらにこの配下にappフォルダを作成
c:\samples\js_sample1\app
ここに、テキストファイル
app.xaml
app.js
を作成します。
内容はこんな感じ。
(ここで、app.pyやapp.rbとするだけで何も追加することなくIronPythonやIronRubyが利用可能です)

app.xaml
<UserControl
    xmlns="http://schemas.microsoft.com/client/2007"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    x:Class="System.Windows.Controls.UserControl"
    x:Name="JSSample1">
  <TextBlock Text="Javascript meets Silverlight 2!" />
</UserControl> 
app.js
Import("System.Windows.Application") 
Import("System.Windows.Controls.UserControl") 

function sample_app() { 
    this.scene = Application.Current.LoadRootVisual(
        new UserControl(), "app.xaml"); 
} 
sample_app.prototype = { 
    start:function() { 
    } 
} 

app = new sample_app; 
app.start();

3つのファイルができましたか?

テキストファイルの形式ですが、基本ANSI形式でもOkですが、日本語を含ませることもあると思うので、エンコーディングはUTF-8にしておきましょう。
今のところSilverlight2のランタイムは標準でSJISではなくUTF-8で決め打ちで読むようです。まぁ、ふつうと言えばふつう。
notepadだと規定値ANSIなので、ファイル/名前を付けて保存でこんな感じ。
image

さて、必要なファイルはこれだけです。
では、コマンドプロンプトでindex.htmlのあるプロジェクトルートフォルダへ移動して、
chiron /b
と実行してみましょう。
image 
image

既定のブラウザが立ち上がりましたか?
既定のブラウザがOperaなどのSilverlightが対応していないブラウザの方すいません、既定のブラウザをIE, Firefox系に変更するか、表示されたURLをIEなどへCopy&Pasteしてください。

で、とりあえず、そっ気のないディレクトリ表示がされていると思うので、一覧からindex.htmlをクリックすれば、最初に作成したindex.htmlが表示されます。

image

うまく Javascript meets Silverlight 2! と表示されましたでしょうか?
右クリックすれば、Silverlightコントロールとして表示されているのを確認できると思います。

このように、chiron.exeは自動的にオンメモリでxapファイルを生成し、ローカルサーバーを作成し、ブラウザを開き、と、ランタイムが実行可能な環境を整えてくれる非常に便利なツールです。

ソースを変更し保存して、ブラウザでリロードすれば、自動的にchironがソースを読み直してくれます。
chironを終了したい場合は、コマンドプロンプトでctrl+cするか、ブラウザのアドレスバーに localhost:2060/bye! を入れてブラウズしてください。
また、実行時に表示されるlocalhostのポート番号はchironのコマンドラインオプションで変更が可能です。

まとめ:

Silverlightというと、MS環境べったりのVisual StudioとExpression BlendとIISでゴリゴリ作るみたいなイメージがあるかも知れませんが、実は、SDKをインストールするだけで最低限の環境としては十分に開発が可能となります。

言語もJS,Python,Rubyがそのまま利用可能。XAMLの記述にちょっと慣れが必要ですが、慣れてくるとHTML+CSSやFlash+ActionScriptと比較して強力かつシンプルな面白さが見えてくるのではないかと思います。

もちろん、Expression Blendでコードを書かずにアニメーションをうにうにと設定したり、Visual Studioで.NETでC#を使えば、IntelliSenceバリバリでxamlをがんがん書いたり、と、より一層手軽な部分もあるわけですが、現在のところVSのSilverlight拡張はVS Express Editionには対応してませんし、まずはこのあたりから試してみると面白いのではないかと思うのです。

[XAML基礎編]へ続く...

2008年04月01日

MacでSilverlightの開発が可能に

先日開催されたMIX08に合わせSilverlight 2 Beta1が公開されましたが、このSDKを利用するとMac OS XでSilverlightの開発環境を構築することが可能です。

Hex dump - Silverlight 2 SDK, Mac OS X and Mono
http://hex-dump.blogspot.com/2008/03/silverlight-2-sdk-mac-os-x-and-mono.html

基本的な段取りは単純で、

  1. MonoがインストールされたMacを用意する
  2. Silverlight 2 Mac OS X版ランタイムをインストール
  3. リアルマシンかVMにインストールしたWindowsにSilverlight 2.0 SDK Beta 1をインストール
  4. Program Files\Microsoft SDKs\Silverlight\ 以下をごっそりコピーしてくる

Silverlight SDKのコンパイラパッケージャ&デバッグ用サーバーのchiron.exe(ケイロン)はどうもオール.NETで作られているらしくMono上ですっぱり動いてしまう模様。
なので、あとは、任意のSilverlightプロジェクトがあるフォルダから、

mono ~/Silverlight/v2.0/Tools/Chiron/Chiron.exe /b

とすれば、Silverlight2のchironが立ち上がり、ブラウザからSilverlightコントロールが貼られたWebページが閲覧可能です。

実際にMIX08でのMac + Mono + VIM + IronRubyでSilverlight開発のデモ映像が見られます。

MIX08 - Microsoft Silverlight and Dynamic Languages
http://sessions.visitmix.com/?selectedSearch=T28
http://msstudios.vo.llnwd.net/o21/mix08/08_WMVs/T28.wmv

とりあえず、ご紹介ということで、Silverlight SDKによる開発に関しては、「Silverlight 2 SDK+JavaScriptで無償の開発環境を作る」をご覧ください。