悪夢の始まり [日記]
<土曜日>
全てはここから始まりました。
調子の悪いノートPCのリプレースを行おうと新しいマシンを用意し、HDDを旧マシンからそのまま移動しようと考えました。
レジストリを編集するために、一度そのHDDをいつも使用しているPCにUSB接続を行いレジストリの編集を行いました。
この際、HDD接続によりどうもブート情報が変わってしまったらしく、いつも使っているPCがブートマネージャでこけるようになってしまいました。
結局にところ、新しく用意したPCへの移動はドライバが足りないため断念。
古いノートPCは元の鞘に収めることにしました。
<日曜日>
いつも使用しているPCが起動できないままなので、とりあえずHDDを取りだし、旧PCに一時的に繋いでバックアップを取ることに。
起動は出来ないが、とりあえず中身は読めるので。
そしてバックアップ中にマシンがフリーズ。
中身すら読めなくなってしまいました。
結局この週末に得られた成果は、いつも使用しているPCのHDDをぶっ潰したということだけでした。
これからHDDを業者に送って復旧が可能かどうか確認してもらいます。
これでダメならもうどうしようもないです。
ただ復旧できたとしても、起動できない状態で返ってくるので、PCの再構築は逃れられなさそうです。
悪夢は続く…
Androidのソフトキーボードが閉じたかどうか検出 [日記]
Androidのソフトキーボードが閉じたかどうかを検出するのが一苦労なのです。
まずAndroidのソフトキーボードが閉じたかどうかを検出するAPIやイベントはありません。
この時点でクソです。
んでグーグルで調べてみると、LinearLayoutを継承してソフトキーボードが出入りした際に発生するonMesureイベントを利用する方法が紹介されています。
しかしこの方法、どうやらSurfaceView(OpenGLなど)を使用している場合などには使えないようで、実際使えませんでした。
この情報を知るまでに結構時間かかりました…
他のViewが必要に応じて押し上げられたりしてHeightが全然変化しないんですよね。
Resizeに設定すると、今度はSurfaceViewの画面が縮小してしまったりして。
たぶんこの状態ならHeightが変わるのかもしれませんが、そもそも画面全体が縮小しては利用が出来ないので試す前に諦めてしまいました。
で、どうしたかというと、まずEditTextを継承しonKeyPreImeをオーバーライドして、バックボタン(物理ボタン)の検出を行い、バックボタンが押されたかどうかを検出します。
@Override
public boolean onKeyPreIme(int keyCode, KeyEvent event){
if(keyCode == KeyEvent.KEYCODE_BACK && event.getAction() == KeyEvent.ACTION_UP){
// バックボタンが押された
}
return super.onKeyPreIme(keyCode, event);
}
ただしこの検出には弱点があり、変換中のバックボタンは変換中解除の機能になる場合もあり、実際にはソフトキーボードは閉じないケースがあるようです。
機種やバージョンによっても異なるようで、対応が難しいところですが、閉じぬなら閉じてやろうキーボードってことで、バックボタンが押された際に強制的に閉じてしまうのも手です。
そしてLandscapeモードで表示されるフルスクリーンモードのキーボードの場合、右側に完了ボタンがあり、これを押されるとキーボードが閉じます。
これを検知するには、
setOnEditorActionListener(new OnEditorActionListener() {
public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
if (actionId == EditorInfo.IME_ACTION_DONE || actionId == EditorInfo.IME_ACTION_NEXT) {
// 完了ボタンが押された
}
return false;
}
});
とすることで検出が可能です。
一応この2つでソフトキーボードが閉じるのを検出できるようになりました。
無理やり閉じてるという話もありますけど…
禁則処理の組み方 [日記]
テキストの表示を行う際に、一定の長さで自動的に折り返す機能が欲しくなる時があります。
一般的にワードラップとよばれる機能です。
ワードラップの機能は、テキストの内容が一定だったり幅が既に決まっている場合は、テキストそのものに改行を入れることで対応ができます。
しかし入力されるテキストが不定だったり、テキストの表示幅やフォントのサイズが可変だったりすると、その状況に合わせて改行位置を修正してやる必要が出てきます。
ワードラップの実装は比較的簡単で、1文字ごとの長さを足していき、所定の長さに達したら改行を挟み込むという形になります。
string baseText;
string resultText = "";
int maxWidth = 200;
int nowWidth = 0;
for (var i = 0; i < baseText; i++) {
var ch = baseText[i];
if (ch == '\n') {
nowWidth = 0;
} else {
var charWidth = GetCharacterWidth(ch); // 文字の幅を取得する
if ((nowWidth + charWidth) > maxWidth) {
// 改行を挟む
resultText += '\n';
nowWidth = 0;
}
nowWidth += charWidth;
}
resultText += ch;
}
上記の処理で所定の範囲内にテキスト表示が行えるようになりましたが、ちょっとした問題も起きます。
いわゆる禁則処理です。
禁則処理とは簡単に言うと、改行をしてはいけない場所があるということです。
(例)
吾輩は、たぶん「猫」なのであーる。
(×)
********
吾輩は、たぶん「
猫」なのであーる
。
(○)
********
吾輩は、たぶん
「猫」なのであー
る。
上記の例では、「の後ろで折り返している点と句点が行頭に来ている点が問題になります。
さらに英文にも「単語の途中で折り返さない」という似たような法則があります。
(例)
My father worked in a game company until last year.
(×)
************************
My father worked in a ga
me company until last ye
ar.
(○)
************************
My father worked in a
game company until last
year.
これらの禁則処理を上記のソースコードに対応させます。
基本的な考え方は「折り返しの必要が出た場合に、どこで折り返せるかを記憶しておく」形になります。
string baseText;
string resultText = "";
int maxWidth = 200;
int nowWidth = 0;
int wordwrapBasePos = -1;
int wordwrapResultPos;
int wordwrapWidth;
for (var i = 0; i < baseText.length; i++) {
var ch = baseText[i];
if (ch == '\n') {
nowWidth = 0;
wordwrapBasePos = -1;
} else {
var charWidth = GetCharacterWidth(ch); // 文字の幅を取得する
// 禁則文字かチェック
if (((nowWidth + charWidth) > maxWidth) || !IsFrontKinsoku(ch)) { // (A)
if (i != (baseText.length - 1) && !IsFrontKinsoku(baseText[i + 1])) { // (B)
if (!IsEnglishKinsoku(ch) && !IsBackKinsoku(ch)) { // (C)
// この文字の後ろに改行を入れることができる
wordwrapBasePos = i;
wordwrapResultPos = resultText.length;
wordwrapWidth = nowWidth;
}
}
}
if ((nowWidth + charWidth) > maxWidth) {
// テキストが指定幅をオーバーする
if (wordwrapBasePos >= 0 && wordwrapBasePos != i) {
// 改行を挟む
resultText = resultText.Substring(0, wordwrapResultPos + 1);
resultText += '\n';
nowWidth = 0;
i = wordwrapBasePos;
wordwrapBasePos = -1;
continue;
}
// 改行を挟む
resultText += '\n';
nowWidth = 0;
wordwrapBasePos = -1;
}
nowWidth += charWidth;
}
resultText += ch;
}
このような感じになります。
まずはチェック部分。
禁則には行末に来てはいけない文字(「{【< など)と、行頭に来てはいけない文字(」}】>、。 など)があります。
行頭に来てはいけない文字かどうかをチェックするのがIsFrontKinsoku()、行末に来てはいけない文字かどうかをチェックするのがIsBackKinsoku()になります。
英文として折り返していい文字かどうかをチェックするのがIsEnglishKinsoku()です。
(A)では次に追加する文字の手前で折り返すことが確定していて、次の文字が行頭に来てはいけない文字かどうかをチェックしています。
(B)では次の次に追加する文字が、行頭に来てはいけない文字かどうかをチェックしています。
(C)では次に追加する文字が、行頭に来てはいけない文字か英文として折り返していい文字かどうかをチェックしています。
これらを全てクリアすると、次に追加する文字の後ろに改行を入れていい場所ということになります。
wordwrapBasePosが0以上の場合、指定された場所までテキストを巻き戻して、改行を追加して引き続き処理を行います。
さてこれで折り返し自体は出来るようになります。
しかし実際に表示してみると、文章によっては折り返し位置が各行でバラバラになってしまい、見栄えが悪いことがあります。
一太郎などを良く見てみると、1行毎に文字数に合わせて字間を調整しているのが分かると思います。
これを行うことで、1行の長さが大体同じになり、見た目的に綺麗になります。
COM経由で初期化するDirectSoundでのDirectSoundEnumerate [日記]
AyameでDirectSoundEnumerateを使いたいと思ったんですが、CoCreateInstanceを使った初期化のため、DirectSoundEnumerateが使えない模様。
LoadLibraryを使えだとさ。
うーん、そこまで改修するのは今さらめんどくさいなぁ。
http://msdn.microsoft.com/ja-jp/library/cc351144.aspx
DirectSound がインストールされているかどうかを検出する方法は?
DirectSoundEnumerate() を使って利用可能な DirectSound デバイスを列挙する必要がない場合には、アプリケーションに dsound.lib をリンクせず、代わりに COM の CoCreateInstance(CLSID_DirectSound. . . ) を使った後に、Initialize(NULL) を使って DirectSound オブジェクトを初期化します。
DirectSoundEnumerate() を使う必要がある場合には、LoadLibrary("dsound.dll") を使って dsound.dll を動的にロードし、GetProcAddress("DirectSoundEnumerateA/W") や GetProcAddress ("DirectSoundCreateA/W") などを使えば、そのメソッドにアクセスできます。
THE MANZAI [日記]
嫁実家帰り中。
なので家でのんびり。
嫁がいない時に面白い番組があるような気がする。
まぁ嫁と子供がいたらTHE MANZAIなんて長丁場の番組は、じっくり観られないわけで。
実力派揃いでどの組も面白かった。
パンクブーブーが勝ったのは妥当だと思いました。
他のコンビでも優勝してもおかしくない感じはしましたけど、もうこれぐらいになると比べられないわけで、まぁまぁお祭りですからね。
しかしダンガンロンパやる時間がないなぁ~
嫁実家帰った報告 [日記]
もう嫁が実家に帰った時にしか更新しなくなったブログです。
子供がいると毎日が慌ただしいですね。
今月は実家に行って帰ってこないそうなので、家仕事したり、やりたかったダンガンロンパでもやりたいなぁとか考えてます。
キングオブコントもゆっくり見ることが出来ました。
モンスターエンジンの一本目と2700の二本目が面白かったです。
ああいう、くっだらないのをリピートされるとジワジワきて最後は笑いが止まらなくなってきます。
最初のつかみの部分でフォーマットというか、パターンをまず提示して認識させ、そのバリエーションを色々見せながら、独自の世界観や価値観を出していくというのが結構好き。
漫才で言えば笑い飯とか。
テレビ購入 [日記]
アナログ放送終了と共にブラウン管テレビの調子が悪くなってしまい、電源を入れても映像がなかなか出なくなってしまったので、液晶テレビを購入しました。
ブラウン管は子供用にDVD鑑賞とゲームで使おうと思ってたんですけど。