ウインド表示直後に処理

久々に SDK チップスネタでも書こう。

WM_SHOW を捕まえて処理するとウインド表示に時間が掛かる場合がある。
このイベント処理が終わった後でないと実際の描写が行われないからだ。

だから表示された直後に作成や描写を行えば見た目の起動速度が向上する。
しかしそんな都合のよいメッセージは飛んでこない。

が、実はデルヒャァにはある。

procedure CMShowingChanged(var Message:TMessage);message CM_SHOWINGCHANGED;

をフォームの private に定義してハンドラを書くだけ…
但し表示状態が変わる毎に飛んでくるので一番最初に捕まえた時以外は弾くこと。
Y901 はそのツマラン方法で見た目の起動時間を短縮するセコイことをやっていた。

はて、CM_SHOWINGCHANGED なんて無い VC++ ではどうすんだ?
で考えた、PostMessage を使ってまえ!

SendMessage は処理が終わるまで制御を戻してくれない。
PostMessage はキューにメッセージを放り込んで即制御を戻す。
だから WM_SHOW 処理の一番最後で適当なメッセージを投げればよい。

#define WM_SHOWEND (WM_APP + 3)

とか定義しておいて WM_SHOW 処理の一番最後に

PostMessage(hWnd, WM_SHOWEND, 0L, 0L);

とすればキューに自分宛の WM_SHOWEND がセットされる。
キューって何?な人は Windows をもっと勉強してください。
後は WndProc で普通に

case WM_SHOWEND:

を処理、これで見た目の起動時間が早いアプリのできあがり!
詳しくは Cinema のソースコードで、オープンソースは楽だ。

フォーム表示直後に実行されるメソッド OnShowed を作る – Sakura scope

他にも同じコトを考える人がいるのね。
ビルダァ(名古屋弁化できん…)には CM_SHOWINGCHANGED は無いのかな?
でも WM_USER を使うのは止めておいたほうがいいみたいよ

WM_APPの薦め。

それより Windows SuperFetch がある Vista ではあまり意味が無い…

STL の本

そういえば去年財布を盗まれてクレカの再発行をしたのを忘れていた。
SAKURA から「引き落とし不能」のメールが…やっちまったい!
再発行すると番号が変わっちゃうのよ。

たった今オンラインで振り込んだけどもし止められたらゴメン。
多分今年中に移転するような気がするんですけど、今は決定していないけど。
といっても急に無くなったら行方不明だしマイッタわ。

つーことで久々に本の紹介。

今コレを読んでいます。
今度は STL かい…と呆れないでくれ。

この本は、、、、、恐ろしく解りにくい!

とにかく難しい、といっても STL 自体が解りにくいのであるが。
だいたい反復子って名前はなんじゃい、もっとイイ翻訳は無かったのか?

知識がある人が本を書くと、ついうっかり深い所まで説明しようとする。
だから難しさが倍増して投げ出したくなってしまう、その典型な文章。

でもだから深い所まで書いているので今はとても嬉しい。
素晴らしい内容の本です、人間って調子がいい生物だなと。

STL は一端使い方を覚えてしまえば楽ちんなのはポインタと同じだね。
てゆーか std::vector だけなら反復子は完全にポインタと同じだと。
それが解るようになる本という事ならとても勧められない文章である。
逆に解っている人であれば買いです、自分でコンテナを作る方法まで解説してる。

プログラミング本を買う決めてがなんとなく解った。
とにかく文字ばっかで画像がほとんど無い本を選びましょう。
今は全然解読できなくても後で役に立つ場合がある。

Intellisense の更新

全然完璧じゃなかった…
コレじゃ Add で同一キーが混在する場合があるやないの。

void CPairList::Add(LPCWSTR szKey, LPCWSTR szValue)
{
    vec_t::iterator it = m_vec.begin();
    vec_t::iterator itend = m_vec.end();
    for (; it != itend; it++)
    {
        if ( (*it).first == szKey)
        {
            (*it).second = szValue;
            return;
        }
    }
    m_vec.push_back(Pair(szKey, szValue));
}

でいいかな。
つーか wstring を二回も typedef する必要なんて無いわな。
キリがないので続きは多分今週末に更新する Cinema のソースで。

ところで。

Intellisense の更新は手動でやれないのかなぁ?
一度作ったクラスにメソッドを追加していくと認識されない場合が多い。

知らない人のために一応書くとコード補完機能のことである。
Ctrl+Space や先頭に :: を打つとグローバルな関数や変数を補完してくれたりとか
ドットや -> を打つと全自動でクラスメソッドを一覧表示してくれてありがたい。

コレがメソッド追加で自動反映されるまでの時間がチト長いのよ。
酷いときにはいつまでたっても反映されないということもあるんです。
古い VC++ はよく知らないけどデルヒャァ5は即時反映だったので気になるわ。

普通に手書きすればコンパイルは通るから Intellisense だけの問題だね。
コレでは Visual Studio のエディタを使っている意味はまったく無いんだが…
便利だからと頼りまくってコーディングというのもどうかと思うけど。

なんとかならんかと検索しまくったがみんなやっぱりそんな感じなのね。

どうやらソリューションのディレクトリにある .nbc がその実体らしい。
一端終了後にこのファイルを削除して再起動で作り直しリセットする。
やっぱりこの方法しかないのかな?メンドクセ。

CPairListClass

完璧だ。
Classes.h,Classes.cpp として

#pragma once   

class CPairList 
{ 
private: 
??? typedef std::wstring m_a; 
??? typedef std::wstring m_b; 
??? typedef std::pair<m_a, m_b> Pair; 
??? typedef std::vector<Pair> vec_t; 
??? vec_t m_vec; 
public: 
??? void Add(LPCWSTR szKey, LPCWSTR szValue); 
??? void Remove(LPCWSTR szKey); 
??? std::wstring operator[](std::wstring szKey); 
??? std::wstring GetValue(int i); 
??? std::wstring GetKey(int i); 
??? int Count(); 
};
//??? TODO: "StdAfx.h" #include <vector>    

#include "StdAfx.h"
#include "Classes.h"   

/* 
 *??? CPairListClass 
 */   

void CPairList::Add(LPCWSTR szKey, LPCWSTR szValue) 
{ 
??? m_vec.push_back(Pair(szKey, szValue)); 
}   

void CPairList::Remove(LPCWSTR szKey) 
{ 
??? vec_t::iterator it = m_vec.begin(); 
??? vec_t::iterator itend = m_vec.end(); 
??? for (; it != itend; it++)? 
??  {? 
?????? if ( (*it).first == szKey)? 
?????? {? 
?????????? m_vec.erase(it); 
?????????? break;? 
?????? } 
??? } 
}   

std::wstring CPairList::operator[](std::wstring szKey) 
{ 
??? std::wstring result; 
??? vec_t::iterator it = m_vec.begin(); 
??? vec_t::iterator itend = m_vec.end(); 
??? for (; it != itend; it++)? 
 ?? {? 
?????? if ( (*it).first == szKey)? 
?????? {? 
?????????? result = (*it).second; 
?????????? break; 
??????? } 
??  } 
??? return result; 
}   

int CPairList::Count() 
{ 
??? return m_vec.size(); 
}   

std::wstring CPairList::GetValue(int i) 
{ 
??? return m_vec[i].second; 
}   

std::wstring CPairList::GetKey(int i)  

{ 
??? return m_vec[i].first; 
}

と定義しておいて

CPairList aList; 
aList.Add(L"おまえ", L"あほ");  

wstring ws = aList[L"おまえ"];

な感じで順番は保持されたままの連想配列もどきの完成、STL 恐るべし。
でも現在 ini 保存に std::map を使っているのでココでソートされてしまう…
こっちも変更しなきゃ、あぁ先は長い。

しかしワシもいつのまにかこんなコードが普通に書けるようになった。

思えば二年前に唐突にデルヒャァから C++ に乗り換えして
「やっぱりポインタがワカンネェ!意味は解るけど使い方が全然ワカンネェ!」
だったのにね。

std::pair<_Ty1, _Ty2>

何故気がつかなかったのだ…

std::pair<_Ty1, _Ty2>

のテンプレートに wstring を両方突っ込んで vector コンテナって方法があった。
使うときには first メンバをキーにして取り出せばイイだけだ。
この方法なら設定の並び順は保持可能かつ拡張時の並び順も問題無い!

でもやってみないとどうなるか解らないわな。

class CGesMap
{
private:
    typedef std::wstring m_a;
    typedef std::wstring m_b;
    typedef std::pair<m_a, m_b> Pair;
    typedef std::vector<Pair> vec;
    vec m_vec;
public:
    void SetGesture(LPCWSTR szGesture, LPCWSTR szValue);
    std::wstring GetValue(std::wstring szGesture);
    std::wstring GetValue(int i);
    std::wstring GetKey(int i);
    int Count();
};

こんな感じで明日色々やってみます。
今日も休日出勤で疲れているのでまた明日。