SQLの窓

2013年07月12日


Live SDK v5.4 : VS2012(C#) + Form アプリ / ファイルアップロード

SkyDrive へ移動( VS2012 用テンプレート )




VS2010 では動作しませんでした。

SkyDrive でアプリを作成して、クライアント ID を取得して使用します。
Form1.cs
using Microsoft.Live;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace WindowsFormsApplication1
{
	public partial class Form1 : Form
	{
		public LiveAuthClient auth;
		public LiveConnectClient lcc = null;
		private CancellationTokenSource ctsUpload = new CancellationTokenSource();

		public Form1()
		{
			InitializeComponent();
		}

		// ログイン結果より、セッションを作成
		private async void webBrowser1_Navigated(object sender, WebBrowserNavigatedEventArgs e)
		{
			// リダイレクトされた URL の処理
			string url = e.Url.ToString();
			string[] param = url.Split(new string[] { "=", "&" }, StringSplitOptions.None);
			Debug.WriteLine(param);

			// ( テスト的な方法 )
			// リダイレクトされた結果の中で、必要な情報が含まれる処理を対象とする
			if (param[2] == "lc")
			{
				Debug.WriteLine(auth.Session);
				var target = await auth.ExchangeAuthCodeAsync(param[1]);
				Debug.WriteLine(auth.Session);
				// セッションの作成
				lcc = new LiveConnectClient(target);

				// テスト的な情報表示
				Debug.WriteLine(lcc.Session);
				var Result = await lcc.GetAsync("me/skydrive/files");
				Debug.WriteLine(Result.RawResult);

				// アップロード用の参照ボタンを有効にする
				this.button2.Enabled = true;

			}
		}

		// ログイン処理をブラウザ内で行う
		private void button1_Click(object sender, EventArgs e)
		{
			auth = new LiveAuthClient("クライアント ID");
//			auth.IntializeAsync();
			string url = auth.GetLoginUrl(new string[] { "wl.signin", "wl.basic", "wl.skydrive_update" });
			Debug.WriteLine(url);
			// WebBrowser でログイン画面を表示
			this.webBrowser1.Navigate(url);
		}

		// ファイルを参照してアップロード
		private async void button2_Click(object sender, EventArgs e)
		{
			this.openFileDialog1.Filter = "すべて|*.*";
			this.openFileDialog1.FilterIndex = 0;
			DialogResult dr = this.openFileDialog1.ShowDialog();
			if (dr == System.Windows.Forms.DialogResult.OK)
			{
				// 中止ボタンを有効にする
				this.button3.Enabled = true;
				// 選択されたファイルのパス
				string FileName = Path.GetFileName(openFileDialog1.FileName);
				Debug.WriteLine(openFileDialog1.FileName + "をアップロードします");

				// トークンにキャンセル直後の処理を登録
				ctsUpload.Token.Register(() =>
				{
					Debug.WriteLine("キャンセルされました");
				});

				// 経過処理用プライベートクラス
				ProgressUpload pu = new ProgressUpload();
				// アップロードが正常終了した時の戻り値
				LiveOperationResult Result = null;

				// キャンセルすると、WebException が発生
				try
				{
					Result = await lcc.UploadAsync(
						"me/skydrive",
						FileName,
						File.OpenRead(openFileDialog1.FileName),
						OverwriteOption.Overwrite,
						ctsUpload.Token,
						pu
					);
				}
				catch (Exception ex)
				{
					Debug.WriteLine(ex.Message);
				}

				// トークンより、キャンセルを判断
				if (ctsUpload.Token.IsCancellationRequested)
				{
					MessageBox.Show("アップロードはキャンセルされました");
				}
				else
				{
					// 正常終了
					Debug.WriteLine(Result.RawResult);
					MessageBox.Show("アップロードしました");
				}
			}
		}

		// 経過処理用のクラス
		private class ProgressUpload : IProgress<LiveOperationProgress> {
			public void Report(LiveOperationProgress value) {
				Debug.WriteLine(value.ProgressPercentage);
			}
		}

		// キャンセル
		private void button3_Click(object sender, EventArgs e)
		{
			ctsUpload.Cancel();
		}
	}
}

関連する記事

わりと簡単に作れるので、SkyDrive の運用はアプリケーションを作ると便利になると思います。Windows ストアの場合はもっと統合されているのですが、現状では落ちるので使えません。
Windows8 ストアアプリは、年額4900円を払って登録しないと専用の API は使用できません。
Live SDK v5.4 : VS2010 + Windows Phone / 画像アップロード
posted by lightbox at 2013-07-12 19:55 | VS(C#) | このブログの読者になる | 更新情報をチェックする

Google Chrome 拡張の『instant translate』という翻訳機能の翻訳ウインドウを大きくする

バグもある上に、元々の大きさが小さすぎて長い文章の翻訳結果がとても読みにくいので CSS を変更して大きくしました。

instant translate



▼ 対象ファイル
C:\Users\ユーザ名\AppData\Local\Google\Chrome\User Data\Default\Extensions\ihmgiclibbndffejedjimfjmfoabpcke\1.8.1_0\resources\styles\ui_components\tooltip\helpSelected.css
/* Local ID ? mndocdiojkckhpnhpeminpalidafeink */
/* Web Store ID ? ihmgiclibbndffejedjimfjmfoabpcke */

.TnITTtw-help-selected-wrap {
  border: 1px solid #C7C6C2;
  box-shadow: 0 0 10px rgba(43, 43, 43, 0.325);
  border-radius: 4px;
  width: 431px
}

  .TnITTtw-help-inside-layout {
    height: 433px;
    background: #F5F5F5;
    border-radius: 3px
  }

    .TnITTtw-left-particle {
      border-top-left-radius: 4px;
      border-bottom-left-radius: 4px;
      box-shadow: inset 0 1px 0 white;
      color: #4E4E4E;
      text-shadow: 0 1px 0 white;
      width: 394px;
      display: inline-block;
      border-right: 1px solid #D9D9D9
    }

      .TnITTtw-content-layout {
        text-align: left;
        margin: 10px 15px
      }

        .TnITTtw-variant-bunch-wrap {

        }

          .TnITTtw-variant-bunch-wrap .inside-layout {

          }

            .TnITTtw-main-variant-wrap {

            }

              .TnITTtw-main-variant {
                font-weight: 700;
                font-size: 15px;
                text-shadow: 0 1px 0 rgba(255, 255, 255, 0.775);
                display: inline-block;
                vertical-align: top;
                color: #2B2B2B
              }

            .TnITTtw-variants-by-pos {
              
            }

              .TnITTtw-TnITTtw-variant-row {
                text-shadow: 0 1px 0 rgba(255, 255, 255, 0.775)
              }

                .TnITTtw-v-pos {
                  font-weight: 700;
                  margin-top: 10px;
                  font-size: 12px;
                  color: #545454
                }

                  .TnITTtw-v-pos:first-child {
                    margin-top: 8px
                  }

                .TnITTtw-v-closest-wrap {
                  font-size: 13px;
                  color: #4E4E4E
                }

                  .TnITTtw-v-item {
                    display: inline-block
                  }

        .TnITTtw-listen-disabled {
          opacity: 0.475;
          cursor: default
        }

    .TnITTtw-right-particle {
      background: rgba(255, 255, 255, 0.125);
      border-top-right-radius: 4px;
      border-bottom-right-radius: 4px;
      display: inline-block;
      width: 36px;
      height: 433px;
      vertical-align: top;
      box-shadow: inset 1px 0 3px rgba(43, 43, 43, 0.05), inset 0 1px 0 #F5F5F5
    }

      .TnITTtw-sidebar {

      }

        .TnITTtw-sbutton {
          position: absolute;
          -webkit-user-select: none;
          cursor: pointer
        }

        .TnITTtw-listen-button {
          width: 16px;
          height: 17px;
          background: url(chrome-extension://ihmgiclibbndffejedjimfjmfoabpcke/resources/images/sprites/sprite.png);
          background-position: -54px 153px;
          margin: 10px 0 0 10px
        }

          .TnITTtw-listen-button:active, .TnITTtw-listen-disabled {
            background-position: -54px 136px
          }

/* ========== */
/* Scrollbars */

#TnITTtw-trVisibleLayout {
  position: relative !important;
  overflow: hidden;
  height: 433px;
  width: 100%
}

#TnITTtw-tr-scrollbar {
  position: absolute;
  display: block;
  width: 9px; 
  height: 435px; 
  font-size: 1px
}

#TnITTtw-track { 
  position: absolute;
  left: 385px;
  top: -434px;
  width: 11px;
  height: 429px;
  background: transparent
}

#TnITTtw-dragBar {
  position: absolute; 
  left: 1px;
  top: 1px;
  width: 5px; 
  height: 10px;
  background: rgba(43, 43, 43, 0.475);
  cursor: pointer;
  border-radius: 3px;
  box-shadow: 0 1px 0 #FFF
}

  #TnITTtw-dragBar:hover, #TnITTtw-dragBar:active {
    background: rgba(43, 43, 43, 0.775)
  } 

#TnITTtw-scrollbar, #TnITTtw-track, #TnITTtw-dragBar {
  -webkit-user-select: none
}

.TnITTtw-arrow {
  display: none;
  width: 12px;
  height: 6px;
  background: url(chrome-extension://ihmgiclibbndffejedjimfjmfoabpcke/resources/images/sprites/sprite.png);
  position: relative
}

.TnITTtw-top-arrow {
  background-position: -108px 148px;
  bottom: -1px
}

.TnITTtw-bottom-arrow {
  background-position: -108px 154px;
  top: -1px
}


posted by lightbox at 2013-07-12 00:10 | Google Chrome | このブログの読者になる | 更新情報をチェックする

2013年07月07日


Twitter API の自分のアプリのトークンを使って投稿するだけの class VS2010_Twitter

SkyDrive へ移動( Form 用 )


VS2012 になると、使うクラスや非同期の扱いがかなり変わって来ます。一般的に使用する場合は、ユーザ毎にログインしてもらって専用のアクセストークンを取得してもらうので、WebBrowser コントロールを利用するのが簡単だと思います。(専用のCallback URL も必要になります)

ですが、とりあえず API をテストするのならば自分のアプリのトークンをそのまま使うと簡単です。

VS2010_Twitter.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Security.Cryptography;
using System.Net;
using System.Diagnostics;

namespace LBOX_Tool
{
    class VS2010_Twitter
    {
        private string _consumer_key;
        private string _consumer_secret;
        private string _token;
        private string _secret;

        private string _tweet_api = "https://api.twitter.com/1.1/statuses/update.json";

        public VS2010_Twitter (
            string consumer_key,
            string consumer_secret,
            string token,
            string secret
            ) {
                _consumer_key = consumer_key;
                _consumer_secret = consumer_secret;
                _token = token;
                _secret = secret;
        }

        public void Tweet(string text,UploadStringCompletedEventHandler newEvent=null)
        {

            WebClient wc = new WebClient();

            if (newEvent != null)
            {
                wc.UploadStringCompleted += newEvent;
            }

            // ソートされるリスト
            SortedList<string, string> sl = new SortedList<string, string>();
            sl.Add("oauth_consumer_key", _consumer_key);
            sl.Add("oauth_nonce", Nonce());
            sl.Add("oauth_signature_method", "HMAC-SHA1");
            sl.Add("oauth_timestamp", TimeStamp());
            sl.Add("oauth_token", _token);
            sl.Add("oauth_version", "1.0");
            sl.Add("status",  Uri.EscapeDataString(text));

            // http ヘッダ用シグネチャ作成
            string work = "";
            foreach (KeyValuePair<string, string> kvp in sl)
            {
                if (work != "")
                {
                    work += "&";
                }
                work += kvp.Key + "=" + kvp.Value;
            }

            string work2 = "";
            // メソッド
            work2 += "POST" + "&";
            // API URL
            work2 += Uri.EscapeDataString(_tweet_api) + "&";
            // Oauth + データ
            work2 += Uri.EscapeDataString(work);

            // OAuth tool チェック用
            Debug.WriteLine(work2);

            string oauth_signature = Signature(work2);

            // ヘッダ情報を作成
            work = "";
            foreach (KeyValuePair<string, string> kvp in sl)
            {
                // oauth_* のみを使用する
                if (work != "")
                {
                    if (kvp.Key.Substring(0, 6) == "oauth_") {
                        work += ", ";
                    }
                }
                if (kvp.Key.Substring(0, 6) == "oauth_")
                {
                    work += kvp.Key + "=" + Dd(kvp.Value);
                }
            }
            // シグネチャを追加( ヘッダーはソートの必要は無い )
            work += ", oauth_signature=" + Dd(Uri.EscapeDataString(oauth_signature));

            // OAuth tool チェック用
            Debug.WriteLine(work);

            // フォーマットは、 OAuth tool で確認。
            wc.Headers["Authorization"] = "OAuth "  + work;
            // POST 用ヘッダ
            wc.Headers["Content-Type"] = "application/x-www-form-urlencoded";

            // 投稿
            wc.UploadStringAsync(new Uri(_tweet_api), "POST", "status=" + sl["status"] ); 

        }

        // ダブルクォートで挟む
        private string Dd(string base_string)
        {
            return "\"" + base_string + "\"";
        }

        private string Nonce()
        {
            Random rand = new Random();
            int nonce = rand.Next(1000000000);
            return nonce.ToString();
        }

        // タイムスタンプ
        private string TimeStamp()
        {
            TimeSpan ts = DateTime.UtcNow - new DateTime(1970, 1, 1, 0, 0, 0, 0);
            return Convert.ToInt64(ts.TotalSeconds).ToString();
        }

        // シグネチャ
        private string Signature(string target)
        {
            string work = _consumer_secret + "&" + _secret;
            byte[] bin = Encoding.UTF8.GetBytes(target);

            HMACSHA1 hmacsha1 = new HMACSHA1();
            hmacsha1.Key = Encoding.UTF8.GetBytes(work);
            byte[] hash = hmacsha1.ComputeHash(bin);

            return Convert.ToBase64String(hash);
        }

    }

}

以下は、実行時のコードです。

Form1.cs
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Net;
using LBOX_Tool;

namespace WindowsFormsApplication
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private void button1_Click(object sender, EventArgs e)
        {
            VS2010_Twitter twitter = 
                new VS2010_Twitter(
                    "Consumer key",
                    "Consumer secret",
                    "Access token",
                    "Access token secret"
                );

            // ただ投稿するだけなら twitter.Tweet(this.textBox1.Text);
            twitter.Tweet(this.textBox1.Text, (object _sender, UploadStringCompletedEventArgs _e) => {
                if (_e.Error == null)
                {
                    // JSON
                    String stringResult = _e.Result;
                    MessageBox.Show(_e.Result);
                }
                else
                {
                    MessageBox.Show("通信エラーが発生しました。\r\n" + _e.Error.Message);
                }

            });

        }
    }
}

エラー処理が単純であれば、ラムダ式が簡単です。

関連する記事

Twitter API の自分のアプリのトークンを使って投稿するだけの class VS2012_Twitter

Twitter API の自分のアプリのトークンを使って投稿するだけの class Android_Twitter

WSH : VBScript と JavaScript で Twitter に投稿する

Twitter アプリの登録方法と、API キーの利用

PHP : Twitter 投稿関数( twitter_update ) / cURL 関数



タグ:twitter API
posted by lightbox at 2013-07-07 21:58 | VS(C#) | このブログの読者になる | 更新情報をチェックする

2013年07月06日


Visual Studio の『競合の解決』(using 自動作成) と 候補ウインドウ表示キー



赤い波線を右クリック






候補を望む部分にカーソルを置いて CTRL + SPACE



※ キーボードで決定する場合は TAB




posted by lightbox at 2013-07-06 13:28 | VS(C#) | このブログの読者になる | 更新情報をチェックする

2013年07月03日


Google Street View Image API を使った画像の URL を取得する WEBツール

▼ 南極です



汎用ストリートビューコード取得

以前、ブログに貼りこむために、緯度・経度の位置から移動したり向きを変えたりしてからコード取得するものを作ってあったのですが、Google Street View Image API というものがある事を知ったので、このほうが使いやすいと思って URL を取得できるようにしました。





posted by lightbox at 2013-07-03 23:08 | Google | このブログの読者になる | 更新情報をチェックする
Seesaa の各ページの表示について
Seesaa の 記事がたまに全く表示されない場合があります。その場合は、設定> 詳細設定> ブログ設定 で 最新の情報に更新の『実行ボタン』で記事やアーカイブが最新にビルドされます。

Seesaa のページで、アーカイブとタグページは要注意です。タグページはコンテンツが全く無い状態になりますし、アーカイブページも歯抜けページはコンテンツが存在しないのにページが表示されてしまいます。

また、カテゴリページもそういう意味では完全ではありません。『カテゴリID-番号』というフォーマットで表示されるページですが、実際存在するより大きな番号でも表示されてしまいます。

※ インデックスページのみ、実際の記事数を超えたページを指定しても最後のページが表示されるようです

対処としては、このようなヘルプ的な情報を固定でページの最後に表示するようにするといいでしょう。具体的には、メインの記事コンテンツの下に『自由形式』を追加し、アーカイブとカテゴリページでのみ表示するように設定し、コンテンツを用意するといいと思います。


※ エキスパートモードで表示しています

アーカイブとカテゴリページはこのように簡単に設定できますが、タグページは HTML 設定を直接変更して、以下の『タグページでのみ表示される内容』の記述方法で設定する必要があります

<% if:page_name eq 'archive' -%>
アーカイブページでのみ表示される内容
<% /if %>

<% if:page_name eq 'category' -%>
カテゴリページでのみ表示される内容
<% /if %>

<% if:page_name eq 'tag' -%>
タグページでのみ表示される内容
<% /if %>
この記述は、以下の場所で使用します
container 終わり



フリーフォントで簡単ロゴ作成
フリーフォントでボタン素材作成
フリーフォントで吹き出し画像作成
フリーフォントではんこ画像作成
ほぼ自由に利用できるフリーフォント
フリーフォントの書体見本とサンプル
画像を大きく見る為のウインドウを開くボタンの作成

CSS ドロップシャドウの参考デモ
イラストAC
ぱくたそ
写真素材 足成
フリーフォント一覧
utf8 文字ツール
右サイド 終わり
base 終わり