- PR -

WINDOWPLACEMENT構造体のlengthパラメータの存在意義は?

1
投稿者投稿内容
maru
ぬし
会議室デビュー日: 2003/01/27
投稿数: 412
投稿日時: 2003-12-10 15:58
こんにちは。いつもお世話になってます。
.NETではないので、ここに投稿してもいいのか迷いましたが、投稿させていただきます。

今、VC++6.0で簡単なダイアログアプリケーションを作っています。
ダイアログサイズを変更するのに、Win32APIのGetWindowPlacementでWINDOWPLACEMENTの
情報を取得して任意の値に変更し、SetWindowPlacementで新しいウィンドウサイズなどに
変更します。

で、WINDOWPLACEMENTはGetWindowPlacementにわたす前に、

wndpl.length = sizeof(WINDOWPLACEMENT);

と、lengthにWINDOWPLACEMENTの構造体のサイズをいれてやる必要があるようです。
これを入れてやらないと、Win98系では正常に動かないとのことでした。

しかし、そもそもなぜlengthというパラメータがあって、わざわざ引数として渡す前に
可変長でもない構造体のサイズをわたさなくてはいけないのかが理解できません。
「そういうもの」として片付ければそれまでですが、理由をきちんと知っておけば、今後
別のAPIで同じような状況があった場合にミスを減らせると思い、投稿させていただき
ました。

どなたか何かご存知ないでしょうか?

※ちなみに、MFCではGetWindowPlacementのなかでlengthをsizeof(WINDOWPLACEMENT)と
固定で初期化していました。なので、MFCでは特にlengthを初期化する必要はなさそうです。


[ メッセージ編集済み 編集者: maru 編集日時 2003-12-10 16:04 ]
冬寂
ぬし
会議室デビュー日: 2002/09/17
投稿数: 449
投稿日時: 2003-12-10 17:38
ハードウェア寄りの話になるので、普通にプログラムする分には知らなくてもいい知識ではあると思いますが・・・

CPUにとって、アクセスしやすいサイズというのがあるんですが、
「CPUにとって」という事でも分るように、ハードによって、そのサイズというのは変わってくる訳です。

ですから、厳密に見ると、最適化を通すと構造体等のサイズが違ってくる可能性があるので、念の為sizeofを使う訳です。
(あまりよく説明できていないので・・・「#pragma pack」をキーにして検索してみると、もっとよく説明しているページを見つける事が出来ると思います)
maru
ぬし
会議室デビュー日: 2003/01/27
投稿数: 412
投稿日時: 2003-12-11 15:25
こんにちは。返答ありがとうございます。

APIリファレンスを眺めて見たのですが、構造体にcbStructやcbSize、wStructSizeなど
構造体サイズらしきパラメータがポロポロとありますね。
構造体によってはない物もあったり、名称にも一貫性がなかったり。

どうも、JavaやVBにどっぷり使っていると、構造体をわたすのに構造体のサイズも
わたす必要があるというのは違和感がありますね。
今までCでもプログラムを組んだことが何回もありましたが、そのようなことをしたこと
はありませんでした。

以後、WinのAPIを呼び出すときは気をつけないといけませんね。
イクザス
会議室デビュー日: 2003/12/11
投稿数: 16
お住まい・勤務地: 静岡
投稿日時: 2003-12-11 18:48
はじめまして。

私的な見解を申しますと、この構造体のサイズはそのまま、構造体のバージョンに
つながっているものと認識しております。

掲題のWINDOWPLACEMENT構造体では、使用していないかもしれませんが
DEVMODE構造体等では、メモリの不正アクセスを行わないように使用されています。
(この様な使われ方は、いくつかの前提条件が必要です)

上記のDEVMODE構造体をVC付属のMSDNでSDKとMFCでの解説を見比べていただけると幸いですが
#ifの構文を使用して、DEVMODE構造体が拡張されているのがわかるかと思います。

#ifの構文はご存知かと思われますが、コンパイル時に判断されるものであり、
実際に使用される環境とは異なる可能性も有ります。
DEVMODE構造体ではWINVERを用いていますが、これはコンパイル時にどのバージョンの
WINVERで動作することを前提にアプリを作るかと言う話になってきます。

例えば、APIでDEVMODEを使用する場合に、APIとAPIを呼び出すプログラムで
WINVERが異なる設定でコンパイルされていたら、構造体のサイズも異なってしまう
事がお分かりでしょうか。
この時にAPI中で引数の構造体のサイズにアクセスして、自分がサポートしている
構造体のサイズと比較して、構造体のバージョンを調べます。
引数の方が小さければ、拡張されている部分にアクセスしない様にします。
引数と等しいか、引数の方が大きければ、自分がサポートしている部分にアクセスできます。
(例が少しわかりにくいかもしれませんが・・・)

このDEVMODE構造体は実際に構造体の拡張がされていますが、WINDOWPLACEMENT構造体は
この様な拡張がされてもいいように設計されているだけなのではないでしょうか。

では長文になりましたが、この辺で・・・。
1

スキルアップ/キャリアアップ(JOB@IT)