parkの雑記帳
2009-12-12 [Sat]
・ [プログラミング] Tween改造 -Replyをたどろう
[追記] 以下のコードにはバグがあるかもしれません。必要なら後で修正します。
[追記] 修正版を書きました。
Twitterのtweetには in_reply_to というものがあって、これで「どの発言に対するreplyか」というのが分かるようになっています。Webで見たときの __park宛(英語だと in reply to __park)ってやつですね。
で、TweenではこれをCtrl+Iで見ることができるんですが、これだとメッセージボックスで元発言が出てくるのでたどることができません。発言をたどるものとして左右キーがありますが、これでは in_reply_to と関係ないものまでたどってしまい分からなくなってしまいます。
ということで、I キーを押すことで in_reply_to のみをたどる機能をつけてみようとおもいました。
とりあえず実際に動かしたらうまくいったんですがよく見ると古いバージョン(0.7.5.0)のソースコードだった!ということで最新の物をチェックアウトしようとしたらでてこない。リポジトリ変わってたのね。ということで取ってきたらビルドができない。ファイル追加忘れがあったようで…
ということで、Tween.vbに新しく加えたメソッドを書いておきます。これを I キーが押されたときに呼び出せば動くはず…
Private Sub GoInReplyToPost()
If _curPost IsNot Nothing AndAlso _curPost.InReplyToUser IsNot Nothing AndAlso _curPost.InReplyToId > 0 Then
If _statuses.ContainsKey(_curPost.InReplyToId) Then
Dim i As Integer = _curList.SelectedIndices(0)
While True
Dim post As PostClass = _statuses.Item(_curTab.Text, i)
If post.Id < _curPost.InReplyToId Then
Dim repPost As PostClass = _statuses.Item(_curPost.InReplyToId)
MessageBox.Show(repPost.Name + " / " + repPost.Nickname + " (" + repPost.PDate.ToString() + ")" + Environment.NewLine + repPost.Data)
Exit While
End If
If post.Id = _curPost.InReplyToId Then
SelectListItem(_curList, i)
_curList.EnsureVisible(i)
Exit While
End If
i = i - 1
End While
Else
OpenUriAsync("http://twitter.com/" + _curPost.InReplyToUser + "/statuses/" + _curPost.InReplyToId.ToString())
End If
End If
End Sub
2009-12-14 [Mon]
・ [ソフトウェア] Tween改造 -Replyをちゃんとたどろう
前回のエントリで偉そうに書いていたのは初期設定でしか動きませんでした...
というのも、発言リストのソート順とかに依存していたみたいで、ちょっといじるとアラマうごかないわ。となってしまいましたとさ。
ということで GoInReplyToPost() メソッドを修正。
Private Sub GoInReplyToPost()
If _curPost IsNot Nothing AndAlso _curPost.InReplyToUser IsNot Nothing AndAlso _curPost.InReplyToId > 0 Then
If _statuses.ContainsKey(_curPost.InReplyToId) Then
Dim idx As Integer = _statuses.Tabs(_curTab.Text).IndexOf(_curPost.InReplyToId)
If idx = -1 Then
Dim repPost As PostClass = _statuses.Item(_curPost.InReplyToId)
MessageBox.Show(repPost.Name + " / " + repPost.Nickname + " (" + repPost.PDate.ToString() + ")" + Environment.NewLine + repPost.Data)
Else
SelectListItem(_curList, idx)
_curList.EnsureVisible(idx)
End If
Else
OpenUriAsync("http://twitter.com/" + _curPost.InReplyToUser + "/statuses/" + _curPost.InReplyToId.ToString())
End If
End If
End Sub
・ [ソフトウェア] Tween改造 -ビルドエラーを無視しない
なんかシリーズみたいになってきました。
Tweenを改造して遊ぶにはソースコードをダウンロードして、手元のVisual Studio (2005以降) で適当にいじってビルドします。
しかし、環境によってはビルドしたときに "c:\Program Files\Microsoft.NET\SDK\v2.0\Bin\sgen.exe" が見つからない旨のエラーが表示されると思います。これはおそらくメイン制作者さんの.NET Framework SDKのインストールディレクトリをプロジェクトに直打ちしているから悪いのでしょう。私の環境にはこんなディレクトリありませんし。
実は、Visual Studioのプロジェクトでは $(FrameworkSDKDir) というマクロを使うことでこの問題を回避できます。まあマクロ名通りな内容なんですが。プロジェクトのプロパティからビルドイベントでこのへんを適当に編集するとエラーが無くなるはずです。
・ [ソフトウェア] Tween改造 -Replyをたどって戻ろう、タブをまたいで
in_reply_to をたどる機能を付けた私家版を使っていて思いました。元発言の方向にたどるのも良いけど時系列順でもたどりたい。
ということで、in_reply_to をたどった場合に、たどったのを戻れるようにしてみました。ついでに違うタブに発言があってもたどれるようにしました。スタックにIDとtabを積んでいるだけなんですけどね。
Private Structure ReplyChain
Public OriginalId As Long
Public InReplyToId As Long
Public OriginalTab As TabPage
Sub New(ByVal originalId As Long, ByVal inReplyToId As Long, ByVal originalTab As TabPage)
Me.OriginalId = originalId
Me.InReplyToId = inReplyToId
Me.OriginalTab = originalTab
End Sub
End Structure
Private replyChains As Stack(Of ReplyChain)
Private Sub GoInReplyToPost()
If _curPost IsNot Nothing AndAlso _curPost.InReplyToUser IsNot Nothing AndAlso _curPost.InReplyToId > 0 Then
If _statuses.ContainsKey(_curPost.InReplyToId) Then
Dim tab As TabPage = _curTab
Dim idx As Integer = _statuses.Tabs(tab.Text).IndexOf(_curPost.InReplyToId)
If idx = -1 Then
For Each tab In ListTab.TabPages
idx = _statuses.Tabs(tab.Text).IndexOf(_curPost.InReplyToId)
If idx <> -1 Then
Exit For
End If
Next
End If
If idx = -1 Then
Dim repPost As PostClass = _statuses.Item(_curPost.InReplyToId)
MessageBox.Show(repPost.Name + " / " + repPost.Nickname + " (" + repPost.PDate.ToString() + ")" + Environment.NewLine + repPost.Data)
Exit Sub
End If
If replyChains Is Nothing OrElse (replyChains.Count > 0 AndAlso replyChains.Peek().InReplyToId <> _curPost.Id) Then
replyChains = New Stack(Of ReplyChain)
End If
replyChains.Push(New ReplyChain(_curPost.Id, _curPost.InReplyToId, _curTab))
If tab IsNot _curTab Then
ListTab.SelectTab(tab)
End If
SelectListItem(_curList, idx)
_curList.EnsureVisible(idx)
Else
OpenUriAsync("http://twitter.com/" + _curPost.InReplyToUser + "/statuses/" + _curPost.InReplyToId.ToString())
End If
End If
End Sub
Private Sub GoBackInReplyToPost()
If replyChains Is Nothing OrElse replyChains.Count < 1 Then
Exit Sub
End If
Dim chainHead As ReplyChain = replyChains.Pop()
If chainHead.InReplyToId = _curPost.Id Then
Dim idx As Integer = _statuses.Tabs(chainHead.OriginalTab.Text).IndexOf(chainHead.OriginalId)
If idx = -1 Then
replyChains = Nothing
Else
Try
ListTab.SelectTab(chainHead.OriginalTab)
Catch ex As Exception
replyChains = Nothing
End Try
SelectListItem(_curList, idx)
_curList.EnsureVisible(idx)
End If
Else
replyChains = Nothing
End If
End Sub
そろそろコメント無しだとつらいレベルのコード片になってきましたw
手元の私家版では GoInReplyToPost() を I キーで、GoBackInReplyToPost() を Shift-I キーで呼び出すようにしています。なかなか快適。
本当はコード片ではなくそのまま使える形にしたいんですがいろいろ面倒なので...
2009-12-26 [Sat]
・ [ハードウェア] 新型トラックポイントキーボード届いた
Twitterでとある人にそそのかされてLenovoのUSBトラックポイントキーボード (ThinkPad USB Keyboard with TrackPoint) を買ってしまいました。 これまでもその前身であるところnトラベルキーボードを愛用していたのですが、 最近マウス操作の中ボタンが壊れたりキーの印字が消えたりとかなりボロボロになっていたので ついポチってしまったわけです。
以下感想などをすこし。
ハードウェア面
キータッチは良い感じです。前身のトラベルキーボードは値段に対してかなり安っぽい感じでしたが 今度のはしっかりした感じがします。ただ、キーの形状が変わったため、人によっては 誤って隣のキーを押してしまうことが増えるかもしれません。
キー配列はT400sと同じです。Escと間違えてF1をおしてしまう事故がなくなったのはすばらしいです。 ただ、その関係でF1-F12キーの位置が変わっているので押し間違いがあるかも。
特殊キーはThinkPad専用っぽいのは使えませんでした。 使えるのは音量キー・スタンバイ・ブラウザ戻る進む・メディアプレーヤー操作でした。あと、ブラウザ戻る進むがAlt-左、Alt-右を送出する困った仕様はトラベルキーボードと同じでした。
ソフトウェア面
いつものSynapticsのやつじゃありません。 分解してみた人のレポートによると、 ThinkPadのキーボードユニットをLITEONのチップで変換しているとのことです。 トラベルキーボードではトラックポイントとキー部分とで別々に接続された基板が使われていたので、 内部的には全くちがうものになっているのでしょう。 それで、PCにインストールするプログラムもLITEONの作ったものっぽかったです。
使ってみた感じ、非常に残念。一部のプログラムにはスクロール開始時にCtrl-Kを送ったり、 Tweenをはじめとした.NET Frameworkのプログラムでスクロールできなかったり、なんかもう別物。 トラベルキーボードに戻そうかと本気で考えるぐらいのできでした。
まとめ
トラックポイントの使えるキーボードが今までよりはるかに安く入手できるというのは 非常に喜ばしいことなんですが、ソフトウェアが残念でなりません。 でもまあ、キータッチとかは良いので、6,000円ぐらいだしポチってしまっても 大損はしないんじゃないかなと思います。
・ [ハードウェア][ソフトウェア] 新型トラックポイントキーボードのスクロール改善
前のエントリでも書いた、Tweenをはじめとした.NET Frameworkのプログラムでスクロールできない問題。 これをアドホックな解決策でスクロールできるようにする方法を見つけてプログラム書きました。
FixSkmz.zip ※無保証、自己責任でお願いします。
原理とか
Spy++ (Visual Studio に付いてくる、ウィンドウメッセージとかを監視したりするツール) で ウィンドウメッセージを見てみると、WM_VSCROLL, WM_HSCROLL をPostしているようでした。 しかしながら、スクロールがされません。 試しに任意のウィンドウにPostMessage()するプログラムを作ってWM_VSCROLLをPostすると なんとスクロールされます。 この違いが何であるかをよく見てみると、トラックポイントの操作ではlParamが非NULLなのに対して 自分のPostMessage()ではNULLでした。 だったら、メッセージを細工してlParamをNULLにしてしまえば良い、という発想です。
実際にやるとなると、SetWindowHookEx()でWH_GETMESSAGEフックを仕込むことになりました。 ここでWM_VSCROLL, WM_HSCROLLが来た場合lParamをNULLにしてしまいます。 でもなんか怖いので.NET Frameworkのプログラムだけを対象にすることにしました。 どうやって判断するかは手抜きで、mscoree.dllをロードしているか否かを判断基準にしました。
実際に作ってみて動かす段階になっていざ試してみると完全に期待通りの動作。 なんかもう拍子抜けでした。
話は変わりますが、トラックポイントのスクロール、ちょっと感度が高すぎる気がします。縦方向だけにスクロールとか横方向だけにスクロールとかがやりづらい。まあそのうち改善されるといいんですが...
