Archive for the ‘Qt’ Category

昨日書いたエントリ(DirectInput を使うとレジストリ登録される)の原因がわかりました。

DirectInput の初期化の際に、 DirectInput8Create 関数を呼び出すことでレジストリにキーが登録されるようです。
つまり下記のような初期化方法ではレジストリにキーが登録されます。

C++:
  1. HINSTANCE hInstance = ::GetModuleHandle(NULL);
  2. LPDIRECTINPUT8 pDirectInput = NULL;
  3. HRESULT hr = ::DirectInput8Create(hInstance,
  4.                                   DIRECTINPUT_VERSION,
  5.                                   IID_IDirectInput8,
  6.                                   (void **)&pDirectInput,
  7.                                   NULL);
  8. if (FAILED(hr)) {
  9.     //エラー処理
  10. }

ではどうするかというと、下記のような方法で初期化します。

C++:
  1. HINSTANCE hInstance = ::GetModuleHandle(NULL);
  2. LPDIRECTINPUT8 pDirectInput = NULL;
  3.  
  4. HRESULT hr = ::CoCreateInstance(CLSID_DirectInput8,
  5.                                 NULL,
  6.                                 CLSCTX_ALL,
  7.                                 IID_IDirectInput8,
  8.                                 (void **)&pDirectInput);
  9. if (FAILED(hr)) {
  10.     // エラー処理
  11. }
  12.  
  13. hr = pDirectInput->Initialize(hInstance, DIRECTINPUT_VERSION);
  14. if (FAILED(hr)) {
  15.     // エラー処理
  16. }

DirectInput8Create 関数では内部で上記と同じ処理をしているのでしょうが、そのときレジストリに登録する処理を行っているのでしょう。
レジストリにキーが登録されて困っている人は、COMからインスタンス作成&初期化で試してみてください。

久しぶりに Qt [Qt 4.4.0 OpenSource Edition] を弄っていたときのこと。
何だか moc が動かない。

やってることとしては windows 上で CL.exe(9.00.21022.08) でビルドをする。
qmake makefile を作り、nmake でビルドする感じです。
ただこれだけのことなんだけど、moc_hogehoge.cpp といったファイルが生成されていない。
コンソールで moc src.h -o dst.cpp と叩いても動かない。これはおかしい。

解決はしたんだけど、utf16 のファイルを moc にかけることができない模様。utf-8 とかも試してみると駄目なのかもしれない。(未確認)
ファイルを Shift_JIS にしたら直った。

何とも微妙なはまりっぷりだったなぁorz (1時間くらい悩んだよ)

前回のエントリで書いたコンストラクタの問題。
それの解答ってことで。間違ってるって場合はコメントくだちい。

まず、何が問題であったか。
前回のコードでは bad_alloc をまったく考えていないですよね。
で、コンストラクタ内で例外が発生し、コンストラクタが正常終了しないと、デストラクタが呼ばれません。これ重要。
なぜならオブジェクトとして生成されないんだから。

初期化リストやコンストラクタ内でメモリ確保を行って、 bad_alloc が発生するとどうなるでしょう。例えば one_ では確保成功、two_ で確保失敗のようなケースです。
one_ で確保したメモリはデストラクタが呼ばれないので解放されんのです。リーク。

解決策としては下記のようなコードを書きます。

C++:
  1. class Hoge
  2. {
  3. public:
  4.     Hoge() : one_(0), two_(0)
  5.     {
  6.         try {
  7.             one_ = new A;
  8.             two_ = new B;
  9.         }
  10.         catch (...) {
  11.             delete one_;
  12.             delete two_;
  13.         }
  14.     }
  15.  
  16.     ~Hoge() {
  17.         delete one_;
  18.         delete two_;
  19.     }
  20.  
  21. private:
  22.     A* one_;
  23.     B* two_;
  24. };

先日のコードだと長いので要素を減らしましたが、やってることといえば 例外をキャッチして後始末をする ってだけです。
メモリ解放に失敗してもコンストラクタは成功し、デストラクタも呼ばれます。
初期化リストではヌルポでも入れておきましょう。

# Seasons 氏に言われたので 補足しときますね。
# 上記例では int でメモリ確保してますけど、これは例ですので、 class とかに置き換えて考えてくだちい。

# アキラ 氏につっこみ貰いましたので、ソースを修正しました (2008/06/10)
# ついでに、クラスが持つメンバ変数を class A, class B のようなものにしてみました (2008/06/10)

Seasons 氏のブログで書かれていますが、Visual C++ 2003, 2005, 2008 で言語仕様がそれぞれ微妙に変化(進化?)してますよね。
# C99対応はまだですが。可変長配列使いたいな

2003 では、

C++:
  1. class Hoge{
  2.     static void f();
  3.     static int v;
  4.     static const int VALUE = 100;
  5.  
  6.     int array_[VALUE];
  7. };
  8.  
  9. int main(int argc, char** argv)
  10. {
  11.     return 0;
  12. }

が許されていませんでした。(定義ないでしょ?ってコンパイラに言われた気がします)
なので、プログラマは enum ハックを使って配列の添え字としたりしていたのです。
ちなみに上記のソースは 2005 と 2008 では普通にコンパイルが通ります。

要するに、言いたいのは

static const int VALUE = 100; のように書くことで定数定義もできる。(2003以前では enum { VALUE = 100 }; のようにしてました)
これは知ってた。

class 宣言で static な変数やら関数を書いたら、定義しなければならないと思っていたが、利用しない場合、定義は必要ない。
こっちは知らなかった。

# あー、2003で確認したいなぁ。会社のPCで試してみるかな。

Qt4.4.0 のビルドが終わらないので今日は何もできてません。
まだビルド中。
もうすぐ3時。

表題の通りです。
Qt では基本的にメッセージ処理を気にせず実装できるようになっとります。(隠されてます)
ですが、メッセージ処理を行いたい場面は多々あります。(通信関係とかDirectShow を使ったりとか)

ってことで、軽くまとめておきます。
自分の環境は下記
OS : Windows Vista Ultimate SP1 32bit
Qt : 4.4RC (Open Source)
VS : 2008 Standard

ってことでさくっとやっちゃいます。
Qt で メッセージを取得するのは QWidget::winEvent です。
こいつを再実装することで実現します。

C++:
  1. bool Window::winEvent(MSG* message, long* result)
  2. {
  3.     using namespace std;
  4.  
  5.     switch (message->message) {
  6.     case WM_KEYDOWN:
  7.         cout <<"push!!" <<endl;
  8.         *result = 0;
  9.         return true;
  10.     };
  11.  
  12.     return false;
  13. }

とりあえず、キーボードのキーが押されたら push!! と表示します。
戻り値に関しては、true を返すと Qt のメッセージ処理を行いません。
false を返すと、Qt のメッセージ処理も行われます。

MSG構造体(WinUser.hにて定義)に wparam, lparam も入っているので普通にメッセージ処理ができると思います。

ぐぐったら最初に出てきた y_mashiro 氏のページ見ながらビルドした。
何か一回エラー出てとまったけど、もう一回ビルドし直したらうまくいったみたい(何だそりゃ
clean はしてない。何でエラー出たんだろう。コンパイルは時間かかるから原因調べるのしんどいっす。

使ったオプションは
-platform win32-msvc2005
これだけ。

QTDIR とか環境変数指定って必要ないんだっけかな。
ともあれ、vista + VS2008 でもビルドはできましたとさー。

ソースはこちら

ウェブキットが導入されるバージョンですが、自分は未確認だったり。
サンプルに一緒に入っていないんだもんさー。(探し足りないだけ?)
safari と組んでるらしくて、速度面は結構期待できそう。

以前より Qt を日本語で解説しているページが増えたんで、導入しやすくなったなーと。

Qt わからん人のために一番簡単なコード紹介。
GUIのウィンドウが出るよ。お手軽。

C++:
  1. int main(int argc, char** argv)
  2. {
  3.     QApplication app(argc, argv);
  4.     QMainWindow w;
  5.     w.show();
  6.     return app.exec();
  7. }

実は昨日から某ゲームのエディタを作り直していたり。
インターフェース面とかデータの持ち方とか直したい。
データに関してはプログラマの人と話さないと無理なんだけども。

今回は Qt + C++ で。

あ、エイプリルフールネタじゃないっすよ?