2005年02月01日
Perlでプロトタイピング
とりあえず、メッセージの全文を取得することは出来た。
Perl 5.8以上が必要で、
use encoding "euc-jp";
を使ってるけど。
だいたいはmixi Alertの時のスクリプトと同じで、正規表現による判定が増えただけのような感じ。
後はこれをC++にして、インターフェイス作って、保存先をSQLiteにすればO.K.かな。
投稿者 Takenori : 23:53 | トラックバック
2005年02月02日
テーブル構造
各種データはSQLiteを使って保存しようと考えている。
で、テーブル構造は次のようにしようと考え中。
-- Message --
送信
Message ID,受信者 ID,Title,Date-Time,Body
受信
Message ID,送信者 ID,Tile,Date-Time,Body
-- Diary --
Diary ID,Date-Time,Title,Body
-- Diary Comment --
Comment ID,Diary ID,Date-Time,From,Body
-- Person --
user ID, ニックネーム
たぶん、これで大丈夫なはず。
型はまだ考えていない。
型はほとんど決まっているようなものだし。
投稿者 Takenori : 00:00 | トラックバック
2005年02月24日
C++に書き換え
perlで作ったものをC++に書き換えた。
新しいboost:regexなら置換もサポートしているみたいだけど、使っているバージョンはどうかわからないので、ここのコードを使わせてもらった。
データベース周りは面倒なので、SQLitePlusの3.0.7を使用。
SQLite本体はVersion 3.1.3にした。
で、ソースコードを全部突っ込んでメイクしたら tclsqlite.c でエラー。tclsqlite.c はTCL用のインターフェイスみたいなのではずしてメイク。
とりあえず、makeは通った。
で、テーブルを作ってみた。
うまくいったようだ。
投稿者 Takenori : 03:23 | トラックバック
2005年02月27日
SQLiteでテーブルを取得する
sqlite: SQLite データベースを管理するプログラムで発見。
"SELECT name FROM sqlite_master WHERE type='table' UNION ALL SELECT name FROM sqlite_temp_master WHERE type='table' ORDER BY name;"というSQL文を発行すれば、テーブル一覧が得られるようだ。
と言う事は、テーブルがあるかどうか確認するには次のようにすれば良い。
"SELECT name FROM sqlite_master WHERE type='table' AND name = ? UNION ALL SELECT name FROM sqlite_temp_master WHERE type='table' AND name = ? ORDER BY name;"
"?"はテーブル名。
これでテーブルの有無を確認する方法がわかった。
投稿者 Takenori : 02:12 | トラックバック
TListViewのレポート形式で列選択
初めTListViewのレポート形式で、どこをクリックしても列が選択されるようにするにはどのようにすれば良いのかわからず、OnMouseUpを使って独自実装したが、単純に RowSelect をtrueにすれば、列で選択できるようになった。
それだけのことだったんすな。
オーナードローとかいろいろとやったのに・・・
投稿者 Takenori : 02:17 | トラックバック
2005年03月01日
とりあえずそれなりに
メッセージの取得と閲覧、絞込みが出来るようになった。
データにSQLiteを使用しているので、検索ではなく絞込みを使うことにした。
重いかと思ったが、意外と速い。
ほとんど一瞬で出てくる。
データ自体がまだ500KBぐらいなのも影響しているだろうけど。
にしても、SQLite楽しいなぁ。
RDBが楽しいと言うのもあるけど、今後レコードとして保存されるデータはSQLiteで保存していくのが楽でいいかも。
投稿者 Takenori : 00:11 | トラックバック
2005年03月03日
バージョンを取得する
実行ファイルに埋め込まれたバージョンを取得するには次のようにすると良いよう。
std::vector
memset( (void*)&exebuff.at(0), 0, exebuff.size()*sizeof(wchar_t) );
Application->ExeName.WideChar( &exebuff.at(0), exebuff.size()*sizeof(wchar_t) );
DWORD n;
n = GetFileVersionInfoSize(&exebuff.at(0), &n);
if( n > 0 )
{
std::vector
GetFileVersionInfo(&exebuff.at(0), 0, n, &buffer.at(0));
unsigned int Len;
unsigned int cbTranslate;
wchar_t SubBlock[256];
wchar_t *pValue;
struct LANGANDCODEPAGE {
WORD wLanguage;
WORD wCodePage;
} *lpTranslate;
VerQueryValue(&buffer.at(0), L"\\VarFileInfo\\Translation", (LPVOID*)&lpTranslate, &cbTranslate);
swprintf( SubBlock, L"\\StringFileInfo\\%04x%04x\\FileVersion", lpTranslate->wLanguage, lpTranslate->wCodePage);
if( VerQueryValue(&buffer.at(0), SubBlock, (void**)&pValue, &Len) )
{
std::wstring ver(std::wstring(L"Ver. ") + std::wstring(pValue));
Version->Caption = ver.c_str();
}
}
C++Builderのヘルプにもサンプルがあったが、そのままだとコンパイルエラーになった。
まあ、型とかポインタがテキトーだったので、見てすぐにダメだろうとは思ったけど。
なお、上記コードは_UNICODEが定義されている時で、コードページは1つだけとみなしている。
また、最初に確保しているバッファは多分2倍になっていると思われる。
ヘルプにAnsiStringがWideCharBufSizeがバイトサイズを返しているかどうか明記されていなかったので、とりあえず文字数と言うことにした。
投稿者 Takenori : 04:10 | トラックバック
2005年04月07日
足あとページを読む
足あとページを読み込み、時間とユーザーを取得できるようにした。
次はUI。
簡単にフォーム上へコンポーネントを置く。
で、起動時にメッセージ用ウィンドウと両方表示するようにするが、変。
そこで、トレイアイコンから、各ウィンドウを表示/非表示出来るようにした。
トレイアイコン用のアイコンも作った。
後は、足あとをDBへ保存していく機能と、取り出す機能を作ればOK
足あととは関係ないけど、お気に入りページにいるユーザーのログイン時間を表示する機能も欲しいかも。
ブラウザで開けば一発だけど・・・
投稿者 Takenori : 22:34 | コメント (2) | トラックバック
2005年09月16日
バージョンアップしようとしたら
メッセージリストの差分取り込みをするクイック受信モードを追加して、意気揚揚と動作確認しようとしたら……
受信したのにメッセージが増えていない?
どこかミスった?
と思いつつ、mixiでメッセージボックスを見ていたら、メッセージIDがGUIDになっていた。
GUIDならデータベースに問い合わせることなくIDを生成できるからだろうけど、今までは連番だったのでメッセージIDはintegerで作っていた。
SQLiteの型の説明を見ると整数値は8バイトまでとある。
が、GUIDとなると128ビット必要だ。
BLOBかTEXTで格納か。
それより、2つの64ビット値に分離したほうが楽かな?
messageID = とする時のことを考えるとBLOBの方が楽そうだな。
ローカルのデータベース周りはどうとでもなるのでいいとして、問題はデータの移行だな。
データベースの変換する処理を内部に持たせて自動的に変換するようになっているのが、一番使いやすいとは思うが、変換処理は一度だけなので、その処理を内部に取り込むのは避けたいな。
データベースの名前を変えて保存していくようにして、過去のものはそのまま置いておくのがいいかな。
古いデータは、古いバージョンのxilionで閲覧ってなるけど。
で、その内コンバータを作って、そのコンバータでデータを移行させるようにすれば、旧バージョンはいらなくなる。
ちょっと手間と言えば手間だけど、この方法が良さそうだな。
投稿者 Takenori : 02:11 | トラックバック
2005年10月10日
HRESULTからエラー文字列を取得
HRESULT値からエラー文字列を取得する方法として、DirectShowを使っていた時、AMGetErrorTextを使っていたが、これですべてのエラーの文字列が得られるのかどうかは明言されていない。
DirectX9には、DXGetErrorString9 と言う関数があり、これは「このメソッドは、すべての Microsoft® DirectX® コンポーネントおよび Microsoft Win32® 関数からのエラー コードを処理する。」と書かれている。
これは!?と思ったが、このメソッドで返ってくる文字列は、HRESULTの各エラーのdefineされている名前だった。(E_FAILなど)
欲しいのは、名前ではなくてエラーの内容を表した文字列。
で、RPC_S_INVALID_STRING_UUIDと言うRPCのエラーに対しても、AMGetErrorTextを使ってみたところ、きちんとエラー文字列が返ってきた。
AMGetErrorTextは、DirectShow以外のものにも対応している?
他にもいろいろと調べていたところ、GetLastErrorで得られたDWORD値のエラーコードを文字列にするFormatMessageにHRESULTを入れると、きちんとエラー文字列が返ってきた。
もしかして、AMGetErrorTextはFormatMessageのラッパー?
とにかく、HRESULTのエラーもFormatMessageを使って文字列に出来るようだ。
投稿者 Takenori : 19:31 | トラックバック
GUIDラッパークラス
文字列からGUIDを作ったり、GUIDから文字列にしたりするクラスを作ることにした。
実際の処理は、UuidCreate、UuidToString、UuidFromStringに任せればよいようだ。
これらを使うには、インクルードファイルはrpc.hが必要、ライブラリはrpcrt4.libが必要。
ただ、UuidFromStringでは"C3CFD1FC-6102-45dc-BCC5-C5026F325E3B"や"c3cfd1fc-6102-45dc-bcc5-c5026f325e3b"は変換してくれるが、"c3cfd1fc610245dcbcc5c5026f325e3b"は変換してくれない。
最後の文字列は、"文字列のユニバーサル固有識別子(UUID)が無効です"と返ってくる。
ハイフンなしの文字列も変換して欲しいのに。と言うか、それが欲しいのに。
面倒だけど自前で作るか。
ところで、UUIDとGUIDって何が違うの?
ググるとGUIDに書いてあった。
どうやら、UUIDを文字列で表したものがGUIDらしい。
と言うことは、UUIDと呼んだほうが適切?
投稿者 Takenori : 19:52 | トラックバック
2005年10月11日
混在してる
メッセージIDをUUIDに対応して、受信したらなぜかメッセージの数が少ない。
で、mixi上でもメッセージを見てみたら、古いメッセージのIDはそのままだった……
全部、UUIDでアクセスするようにしたのに、どうしよう?
とりあえずは旧バージョンで取得すれば、なんとかなるが。
古いバージョンのDBとは互換性がなくなったので、移動させるにはコンバーターが必要だが、どのような仕様にするかなぁ。
適当なUUIDを生成して登録するしかないかな。
それか、古いIDで上位の4バイトのみを埋めて、下位の28バイトは0にして、文字列として得る時に、下位の28バイトが0の時は上位バイトのみを使うか。ってか、それって大丈夫なんだろうか?
内部結合で何とかするって手もあるか。
もう少し考えよう。