Matrix のような WPF によるツイッタースクリーンセーバーを作ってみた

画面

image 

[1] 名称
    TMScreensaver

[2] 概要
    映画 Matrix のように Twitter のタイムラインを縦に流れるように表示するスクリーンセーバー

[3] バージョン
    0.2

[4]    ダウンロード
http://cid-7cb203a44bf94940.skydrive.live.com/browse.aspx/TMScreensaver
    ここより、Readme.txt と TMSetup.msi をダウンロードしてください。

[5] 動作環境   
    .NET Framework 4.0 が動く環境
    32bit 版
    グラフィックアクセラレータを搭載していること

[6] 必要条件
    .NET Framework 4.0
http://www.microsoft.com/downloads/details.aspx?FamilyID=9cfb2d51-5ff4-4491-b0e5-b386f32c0992&displaylang=ja

[7] インストール方法

  1. TMS.zip を適当な場所で解凍
  2. TMScreensaver.exe.scr を右クリックして、インストールを選択
  3. スクリーンセーバーの接待画面が表示されるので、設定ボタンを押す
  4. TMScreensaver Configurationダイアログが表示されるので、次の情報を入力
  5. Username…twitter のユーザーアカウントを入力
  6. Password…twitter のパスワードを入力
  7. Font Size…スライダーを移動し、適当なサイズに設定
  8. OKボタンを押すと、設定情報をレジストリに格納
  9. プレビューボタンを押し、プレビューで動作を確認

[8] アンインストール方法

  1. TMS.zip を解凍したフォルダーを削除
  2. レジストリの CurrentUser\Software\Uchukamen\TMScreensaver 以下を削除

[9] 注意制限
    1.最大タイムラインは200個
    2.通信エラー等発生した場合は、白いメッセージを表示

[10] バグ報告、要望など
    uchukamen宛に、#TMScreensaver タグでつぶやいてください。

ストーリーボードをC#で手書きすると

DoubleAnimationUsingKeyFrames をコードで書くと、次のように面倒なことになるので、XAMLで書いて、トリガーで起動するようにしたほうがいい。とはいえ、動的にストーリーボードやトリガーをエディタで設定しておいて、それをC#で書き直すときに、デザイナーが処理できるように気をつかってあげないと、デザイナーが表示できなくなる。

private void StoryBoardScale(Storyboard sb, Label label)
{
    DoubleAnimationUsingKeyFrames daukfX = new DoubleAnimationUsingKeyFrames();
    DoubleAnimationUsingKeyFrames daukfY = new DoubleAnimationUsingKeyFrames();

    ScaleTransform scaleTransform = new ScaleTransform();
    label.RenderTransform = scaleTransform;
    string name = "labelS" + num++;
    this.RegisterName(name, scaleTransform);

    daukfX.BeginTime = new TimeSpan(0, 0, 0);
    daukfX.Duration = new TimeSpan(0, 0, 60);
    daukfX.KeyFrames.Add(
         new SplineDoubleKeyFrame(
             0.1,
             KeyTime.FromTimeSpan(new TimeSpan(0, 0, 0))));
    daukfX.KeyFrames.Add(
        new SplineDoubleKeyFrame(
            5.0,
            KeyTime.FromTimeSpan(new TimeSpan(0, 0, 60))));

    Storyboard.SetTargetName(daukfX, name);
    Storyboard.SetTargetProperty(daukfX, new PropertyPath(ScaleTransform.ScaleXProperty));

    sb.Children.Add(daukfX);

    daukfY.BeginTime = new TimeSpan(0, 0, 0);
    daukfY.Duration = new TimeSpan(0, 0, 30);
    daukfY.KeyFrames.Add(
         new SplineDoubleKeyFrame(
             0.1,
             KeyTime.FromTimeSpan(new TimeSpan(0, 0, 0))));
    daukfY.KeyFrames.Add(
        new SplineDoubleKeyFrame(
            5.0,
            KeyTime.FromTimeSpan(new TimeSpan(0, 0, 60))));

    Storyboard.SetTargetName(daukfY, name);
    Storyboard.SetTargetProperty(daukfY, new PropertyPath(ScaleTransform.ScaleYProperty));

    sb.Children.Add(daukfY);
}

Linked Server がうまくいかない・・・

EXCEL のオリジナルデータをSQLから直接扱いたい理由があって、Linked Server で手っ取り早くアクセスしようと思ったら、ハマり中。SQL Server 2008 + EXCEL 2007——————————–

EXCEL 2007 フォーマットの場合

EXEC sp_addlinkedserver
@server = N’ExcelDataSource’,
@srvproduct=N’ExcelData’,
@provider=N’Microsoft.ACE.OLEDB.12.0′,
@datasrc=N’E:\Users\uchukamen\Documents\test3.xlsx’,
@provstr=’EXCEL 12.0′ ;

コマンドは正常に完了しました。

SELECT *
   FROM ExcelDataSource…Sheet1  
GOリンク サーバー “ExcelDataSource” の OLE DB プロバイダ “Microsoft.ACE.OLEDB.12.0” から、メッセージ “エラーを特定できません” が返されました。
メッセージ 7303、レベル 16、状態 1、行 2
リンク サーバー “ExcelDataSource” の OLE DB プロバイダ “Microsoft.ACE.OLEDB.12.0” のデータ ソース オブジェクトを初期化できません。——————————–EXCEL 2000, 2003 フォーマットの場合EXEC sp_addlinkedserver ‘ExcelSource’,
   ‘Jet 4.0’,
   ‘Microsoft.Jet.OLEDB.4.0’,
   ‘E:\Users\uchukamen\Documents\test4.xls’,
   NULL,
   ‘Excel 8.0’
GOコマンドは正常に完了しました。SELECT *
   FROM ExcelSource…Sheet1
GOリンク サーバー “ExcelSource” の OLE DB プロバイダ “Microsoft.Jet.OLEDB.4.0” から、メッセージ “エラーを特定できません” が返されました。
メッセージ 7303、レベル 16、状態 1、行 2
リンク サーバー “ExcelSource” の OLE DB プロバイダ “Microsoft.Jet.OLEDB.4.0″ のデータ ソース オブジェクトを初期化できません。——————————–OpenDataSource もだめ。EXEC sp_configure ‘show advanced options’, 1
RECONFIGURE
EXEC sp_configure ‘Ad Hoc Distributed Queries’, 1
RECONFIGURE

この辺の設定はしている。

SELECT *
FROM OpenDataSource( ‘Microsoft.Jet.OLEDB.4.0’,
‘Data Source=”E:\Users\uchukamen\Documents\test4.xls”;
User ID=Admin;Password=;Extended properties=Excel 12.0’)…Sheet1リンク サーバー “(null)” の OLE DB プロバイダ “Microsoft.Jet.OLEDB.4.0” から、メッセージ “エラーを特定できません” が返されました。
メッセージ 7303、レベル 16、状態 1、行 2
リンク サーバー “(null)” の OLE DB プロバイダ “Microsoft.Jet.OLEDB.4.0” のデータ ソース オブジェクトを初期化できません。——————————–SQL 2005 のときはうまくいったのになぁ・・・http://uchukamen.com/SQL2000/LinkedServer/LinkedServer.htm何か忘れている????

WPF RichTextBox でハイパーリンクをクリックしたとき

WPFアプリケーションの中で、RichTextBox のHyperlink で、NavigationUri をセットしても、Clickイベントがキックされない。

RichTextBox のHyperlink は、NavigationWindow or Frame で navigation がサポートされているときだけ
http://social.msdn.microsoft.com/forums/en-US/wpf/thread/85171e54-7f98-425e-820d-46a17e19721e
という記事があるが、本当?

ということで、WPFアプリケーションの中で、RichTextBox のHyperlink をクリックしたときに、そのURLを開くには、MouseLeftButtonDown を使って、こんな感じ

<RichTextBox Height="100" Name="richTextBox1" Width="200" >
    <FlowDocument>
        <Paragraph>
            <Run>Paragraph 1</Run>
            <Run>Paragraph 2</Run>
            <Label >hello</Label>
            <Hyperlink NavigateUri="http://uchukamen.com"  MouseLeftButtonDown="Hyperlink_MouseLeftButtonDown"  >
                <Run>http://uchukamen.com</Run>
            </Hyperlink>
        </Paragraph>
    </FlowDocument>
</RichTextBox>

private void Hyperlink_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
    System.Diagnostics.Process.Start(((Hyperlink)sender).NavigateUri.ToString());
}

=================

とするか、コードで書く場合は、

var fd = new FlowDocument();
this.RTB.Document = fd;

var p = new Paragraph();
p.Inlines.Add("ハイパーリング");

Hyperlink l = new Hyperlink();
l.Inlines.Add(http://uchukamen.com);
l.NavigateUri = new Uri("http://uchukamen.com");
l.MouseLeftButtonDown +=new MouseButtonEventHandler(l_MouseLeftButtonDown);

p.Inlines.Add(l);

fd.Blocks.Add(p);

——————————–

void l_MouseLeftButtonDown(object sender, RoutedEventArgs e)
{
    System.Diagnostics.Process.Start(((Hyperlink)sender).NavigateUri.ToString());
}

ラベルをリサイズするユーザーコントロール

ちょっとしたテスト

<UserControl x:Class="WpfControlLibrary1.UserControl1"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
      <UserControl.Resources>
            <Storyboard x:Key="Storyboard1">
            <DoubleAnimationUsingKeyFrames BeginTime="00:00:00" Storyboard.TargetName="label" Storyboard.TargetProperty="(TextElement.FontSize)">
                <SplineDoubleKeyFrame KeyTime="00:00:00" Value="12"/>
                <SplineDoubleKeyFrame KeyTime="00:00:01" Value="32"/>
            </DoubleAnimationUsingKeyFrames>
            <ObjectAnimationUsingKeyFrames BeginTime="00:00:00" Storyboard.TargetName="label" Storyboard.TargetProperty="(FrameworkElement.HorizontalAlignment)">
                <DiscreteObjectKeyFrame KeyTime="00:00:00" Value="{x:Static HorizontalAlignment.Center}"/>
                <DiscreteObjectKeyFrame KeyTime="00:00:01" Value="{x:Static HorizontalAlignment.Center}"/>
            </ObjectAnimationUsingKeyFrames>
            <ObjectAnimationUsingKeyFrames BeginTime="00:00:00" Storyboard.TargetName="label" Storyboard.TargetProperty="(FrameworkElement.VerticalAlignment)">
                <DiscreteObjectKeyFrame KeyTime="00:00:00" Value="{x:Static VerticalAlignment.Center}"/>
                <DiscreteObjectKeyFrame KeyTime="00:00:01" Value="{x:Static VerticalAlignment.Center}"/>
            </ObjectAnimationUsingKeyFrames>
            <ThicknessAnimationUsingKeyFrames BeginTime="00:00:00" Storyboard.TargetName="label" Storyboard.TargetProperty="(FrameworkElement.Margin)">
                <SplineThicknessKeyFrame KeyTime="00:00:00" Value="0"/>
                <SplineThicknessKeyFrame KeyTime="00:00:01" Value="0"/>
            </ThicknessAnimationUsingKeyFrames>
        </Storyboard>
        <Storyboard x:Key="Storyboard2">
            <ThicknessAnimationUsingKeyFrames BeginTime="00:00:00" Storyboard.TargetName="label" Storyboard.TargetProperty="(FrameworkElement.Margin)">
                <SplineThicknessKeyFrame KeyTime="00:00:00" Value="0"/>
                <SplineThicknessKeyFrame KeyTime="00:00:01" Value="0"/>
            </ThicknessAnimationUsingKeyFrames>
            <ObjectAnimationUsingKeyFrames BeginTime="00:00:00" Storyboard.TargetName="label" Storyboard.TargetProperty="(FrameworkElement.VerticalAlignment)">
                <DiscreteObjectKeyFrame KeyTime="00:00:00" Value="{x:Static VerticalAlignment.Stretch}"/>
                <DiscreteObjectKeyFrame KeyTime="00:00:01" Value="{x:Static VerticalAlignment.Stretch}"/>
            </ObjectAnimationUsingKeyFrames>
            <DoubleAnimationUsingKeyFrames BeginTime="00:00:00" Storyboard.TargetName="label" Storyboard.TargetProperty="(TextElement.FontSize)">
                <SplineDoubleKeyFrame KeyTime="00:00:00" Value="32"/>
                <SplineDoubleKeyFrame KeyTime="00:00:01" Value="12"/>
            </DoubleAnimationUsingKeyFrames>
            <ObjectAnimationUsingKeyFrames BeginTime="00:00:00" Storyboard.TargetName="label" Storyboard.TargetProperty="(FrameworkElement.HorizontalAlignment)">
                <DiscreteObjectKeyFrame KeyTime="00:00:00" Value="{x:Static HorizontalAlignment.Center}"/>
                <DiscreteObjectKeyFrame KeyTime="00:00:01" Value="{x:Static HorizontalAlignment.Center}"/>
            </ObjectAnimationUsingKeyFrames>
        </Storyboard>

        </UserControl.Resources>
        <UserControl.Triggers>
            <EventTrigger RoutedEvent="Mouse.MouseEnter" SourceName="label">
                <BeginStoryboard Storyboard="{StaticResource Storyboard1}"/>
            </EventTrigger>
            <EventTrigger RoutedEvent="Mouse.MouseLeave" SourceName="label">
                <BeginStoryboard x:Name="Storyboard2_BeginStoryboard" Storyboard="{StaticResource Storyboard2}"/>
            </EventTrigger>
            <EventTrigger RoutedEvent="FrameworkElement.Loaded">
                <BeginStoryboard x:Name="Storyboard2_BeginStoryboard1" Storyboard="{StaticResource Storyboard2}"/>
            </EventTrigger>
        </UserControl.Triggers>

        <Label x:Name="label" HorizontalAlignment="Center" >Hello world</Label>
</UserControl>

———–

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;

namespace WpfControlLibrary1
{
    /// <summary>
    /// UserControl1.xaml の相互作用ロジック
    /// </summary>
    public partial class UserControl1 : UserControl
    {
        public UserControl1()
        {
            InitializeComponent();
        }

        public UserControl1(string label)
        {
            InitializeComponent();
            this.label.Content = label;
        }
    }
}

—————

それをスタックパネルに入れる

foreach (var v in list)
{
    WpfControlLibrary1.UserControl1 userCont1 = new WpfControlLibrary1.UserControl1(v.Text);
    stackPanel1.Children.Add(userCont1);
}

WPF DisplayMemberBinding

<Window x:Class="WpfApplication3.Window1"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:sys="clr-namespace:System;assembly=mscorlib"
    Title="Window1" Height="189" Width="459">
    <ListView>
        <ListView.View>
            <GridView>
                <GridViewColumn Width="120" Header="Date" />
                <GridViewColumn Width="120" Header="Day Of Week" DisplayMemberBinding="{Binding DayOfWeek}" />
                <GridViewColumn Width="120" Header="Year" DisplayMemberBinding="{Binding Year}" />
            </GridView>
        </ListView.View>
        <sys:DateTime>2001,1,1</sys:DateTime>
        <sys:DateTime>2010,1,1</sys:DateTime>
        <sys:DateTime>7/8/9</sys:DateTime>
        <sys:DateTime>10/11/12</sys:DateTime>
    </ListView>
</Window>

Date のところは、DisplayMemberBinding していないけど、表示されている・・・

image

WPF ListBox で DockPanel を使った例

DockPanel を使った例

複数選択の例だけど、http://msdn.microsoft.com/ja-jp/library/ms742885(VS.80).aspx

image

<Window x:Class="WpfApplication2.Window1"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="Window1" Height="226" Width="292" >
    <Grid>
        <ListBox SelectionMode="Multiple">
            <DockPanel>
                <Image Source="data\cat.jpg" Width="100" Height="80" />
                <TextBlock>CAT</TextBlock>
            </DockPanel>
            <DockPanel>
                <Image Source="data\dog.jpg" Width="100" Height="80"/>
                <TextBlock>DOG</TextBlock>
            </DockPanel>
            <DockPanel>
                <Image Source="data\fish.jpg" Width="100" Height="80"/>
                <TextBlock>FISH</TextBlock>
            </DockPanel>
        </ListBox>
    </Grid>
</Window>

WPF ListBox のバインディング

わかりにくいなぁ・・・

MSDN ListView
http://msdn.microsoft.com/ja-jp/library/ms743602(VS.80).aspx

<Window x:Class="WpfApplication2.Window1"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:src="clr-namespace:WpfApplication1"               <<<<<< ここで、src = ネームスペース

    Title="Window1" Height="300" Width="300" >
    <Canvas>
        <Canvas.Resources>
            <ObjectDataProvider x:Key="Colors" ObjectType="{x:Type src:myColors}"/>    <<<< ここでタイプを指定
        </Canvas.Resources>
        <ListBox Name="myListBox" HorizontalAlignment="Left" SelectionMode="Extended"
      Width="265" Height="117"
      ItemsSource="{Binding Source={StaticResource Colors}}" IsSynchronizedWithCurrentItem="true">  
        </ListBox>
    </Canvas>
</Window>

/////////////////////////////////////////

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Collections.ObjectModel;

namespace WpfApplication1
{
    public class myColors : ObservableCollection<string>
    {
        public myColors()
        {
            Add("LightBlue");
            Add("Pink");
            Add("Red");
            Add("Purple");
            Add("Blue");
            Add("Green");
        }
    }
}

WPF で ListView にデータバインドしたデータソースをアップデートしても表示が自動更新できない

単にデータバインドしていて、データソースをアップデートしただけじゃ、表示は更新してくれないのね。

Queue<Info> queue = new Queue<Info>(200);

Binding myBinding = new Binding();
myBinding.Source = queue;
myBinding.NotifyOnSourceUpdated = true;  /// <<<
BindingOperations.SetBinding(listView1, ListView.ItemsSourceProperty, myBinding);

void DataReceived(object sender, EventArgs e)
{
    foreach (var v in (IList<Info>)sender)
    {
        queue.Enqueue(v);
    }
    listView1.Items.Refresh();  /// <<<<<<<<<<<<<<<< これが必要
}

プログラムソース(C#、VB.NET)をHTMLに変換するツール

zebratchの気まぐれ日記 の [.NET]プログラムコードの変換(C#、VB.NET→HTML)[Page1] に、C#, VB.NETをHTMLに変換してくれるツールが紹介されています。

数行で変換メソッドを呼び出して、きれいな C# HTMLソースコードを生成できる。