ページ 11

ビット演算

Posted: 2015年6月07日(日) 11:46
by みそ油
Win32APIを利用したプログラムのソースコードについての質問です。

コード:

/* ソースコード1 旧タイプのツールバーに変更 */
style = GetWindowLongPtr(hTool, GWL_STYLE);
style = style & ~TBSTYLE_FLAT & ~TBSTYLE_TRANSPARENT;    /* ? */
SetWindowLongPtr(hTool, GWL_STYLE, style);

コード:

/* ソースコード2 フラットタイプのツールバーに変更 */
style = GetWindowLongPtr(hTool, GWL_STYLE);
style = (style | TBSTYLE_FLAT) & ~TBSTYLE_TRANSPARENT;    /* ? */
SetWindowLongPtr(hTool, GWL_STYLE, style);

コード:

/* ソースコード3 透明タイプのツールバーに変更 */
style = GetWindowLongPtr(hTool, GWL_STYLE);
style = style | TBSTYLE_FLAT | TBSTYLE_TRANSPARENT;    /* ? */
SetWindowLongPtr(hTool, GWL_STYLE, style);

コード:

/* 変数の詳細 */
LONG style;
HWND hTool;    /* ツールバーのハンドル */
ソースコード1では、style = TBSTYLE_OLD にしたいのに、/* ? */ の処理だと style = 0 になりますよね。
ソースコード2や、ソースコード3でも、style は望んでいる値にはならないと思います。
/* ? */ の行のコードはどのような意味を持つのでしょうか。

Re: ビット演算

Posted: 2015年6月07日(日) 12:12
by みけCAT
みそ油 さんが書きました:ソースコード1では、style = TBSTYLE_OLD にしたいのに、/* ? */ の処理だと style = 0 になりますよね。
0になるかはもとのstyleの値によります。
みそ油 さんが書きました:ソースコード2や、ソースコード3でも、style は望んでいる値にはならないと思います。
なぜですか?
思うだけでなく、実験はしましたか?
みそ油 さんが書きました:/* ? */ の行のコードはどのような意味を持つのでしょうか。

コード:

/* ソースコード1 旧タイプのツールバーに変更 */
/* styleのTBSTYLE_FLATフラグとTBSTYLE_TRANSPARENTフラグを折る */
style = style & ~TBSTYLE_FLAT & ~TBSTYLE_TRANSPARENT;    /* ? */

/* ソースコード2 フラットタイプのツールバーに変更 */
/* styleのTBSTYLE_FLATフラグを立てたあと、TBSTYLE_TRANSPARENTフラグを折る */
style = (style | TBSTYLE_FLAT) & ~TBSTYLE_TRANSPARENT;    /* ? */

/* ソースコード3 透明タイプのツールバーに変更 */
/* styleのTBSTYLE_FLATフラグとTBSTYLE_TRANSPARENTフラグを立てる */
style = style | TBSTYLE_FLAT | TBSTYLE_TRANSPARENT;    /* ? */

Re: ビット演算

Posted: 2015年6月07日(日) 12:38
by みそ油
>みけCAT さん
回答ありがとうございます。
実験はしたのですが、そのことについては本文では触れていませんでしたね。失礼しました。

まず、ソースコード1についてですが、旧タイプのツールバーに変更ということは、style == TBSTYLE_FLAT あるいは style == TBSTYLE_TRANSPARENT になっているはずです。
ということは、TBSTYLE_FLATの否定とTBSTYLE_TRANSPARENTの否定との論理積であるので、必ず style == 0 になります。

ソースコード2と3については、TBSTYLE_OLD と TBSTYLE_FLAT と TBSTYLE_TRANSPARENT の値を次のように仮定します(各値は2進数とします)。

コード:

/* 各値の仮定をC言語風に書いたもの */
#define TBSTYLE_OLD 00011
#define TBSTYLE_FLAT 00101
#define TBSTYLE_TRANSPARENT 01011
<コード2の場合>
(i)style == TBSTYLE_OLD のとき
最終的な style の値 00100 → 望む値 TBSTYLE_FLAT とは異なる

(ii)style == TBSTYLE_TRANSPARENT のとき
最終的な style の値 00000 → 望む値 TBSTYLE_FLAT とは異なる

<コード3の場合>
(i)style == TBSTYLE_OLD のとき
最終的な style の値 00001 → 望む値 TBSTYLE_TRANSPARENT とは異なる

(ii)style == TBSTYLE_FLAT のとき
最終的な style の値 00001 → 望む値 TBSTYLE_TRANSPARENT とは異なる

Re: ビット演算

Posted: 2015年6月07日(日) 12:52
by h2so5
ヘッダを見たり実行してみればわかることなのに、なぜすべて仮定で話を進めているのですか?
本当に実験したならそんな定数値の仮定は出てこないはずです。

Re: ビット演算

Posted: 2015年6月07日(日) 13:02
by みそ油
>h2so5 さん

回答ありがとうございます。
windows.h を参照したのですが、その中で他のヘッダファイルがいくつもインクルードされており、どのヘッダファイルに TBSTYLE_OLD などの値が定義されているのかがわかりませんでしたので、仮定で話を進めさせていただきました。
どちらのヘッダファイルに、TBSTYLE_OLD などの値が定義されているのでしょうか。

Re: ビット演算

Posted: 2015年6月07日(日) 13:11
by みそ油
書き忘れていましたが、プログラムを実行したところ、正常に動作しました。

Re: ビット演算

Posted: 2015年6月07日(日) 13:27
by h2so5
VisualStudioを使っているなら右クリックで「定義へ移動」を使えばその場所へジャンプできます。
そうでなくても、ブレークポイントを使うとか結果を出力するようにすればわかります。

Re: ビット演算

Posted: 2015年6月07日(日) 13:38
by みそ油
ビット演算子にフラグとしての使い方があったのですね。
/* ? */ 部分のコードのもつ意味については解決しました。
しかし、新たな疑問が生まれました。
GetWindowLongPtr 関数で現在のスタイルを取得して style に代入し、style をいじってSetWindowLongPtr 関数に渡していますが、わざわざそのようなまわりくどいことをする必要があるのでしょうか。
直接 SetWindowLongPtr 関数でスタイルを指定してもいいのではないかな、と思ったのですが、そうすると何か問題があるのでしょうか。

Re: ビット演算

Posted: 2015年6月07日(日) 13:46
by みそ油
TBSTYLE_OLD というマクロが定義されているわけではなかったのですね。自己解決しました。
ありがとうございました。

Re: ビット演算

Posted: 2015年6月07日(日) 13:47
by みそ油
「解決」にするのを忘れていました。失礼しました。

Re: ビット演算

Posted: 2015年6月07日(日) 17:12
by みけCAT
みそ油 さんが書きました:2と3については、TBSTYLE_OLD と TBSTYLE_FLAT と TBSTYLE_TRANSPARENT の値を次のように仮定します(各値は2進数とします)。

コード:

/* 各値の仮定をC言語風に書いたもの */
#define TBSTYLE_OLD 00011
#define TBSTYLE_FLAT 00101
#define TBSTYLE_TRANSPARENT 01011
この仮定のもと、
みそ油 さんが書きました:<コード2の場合>
(i)style == TBSTYLE_OLD のとき
最終的な style の値 00100 → 望む値 TBSTYLE_FLAT とは異なる

(ii)style == TBSTYLE_TRANSPARENT のとき
最終的な style の値 00000 → 望む値 TBSTYLE_FLAT とは異なる
どちらも00100になるはずです。
みそ油 さんが書きました:<コード3の場合>
(i)style == TBSTYLE_OLD のとき
最終的な style の値 00001 → 望む値 TBSTYLE_TRANSPARENT とは異なる

(ii)style == TBSTYLE_FLAT のとき
最終的な style の値 00001 → 望む値 TBSTYLE_TRANSPARENT とは異なる
どちらも01111になるはずです。
みそ油 さんが書きました:しかし、新たな疑問が生まれました。
GetWindowLongPtr 関数で現在のスタイルを取得して style に代入し、style をいじってSetWindowLongPtr 関数に渡していますが、わざわざそのようなまわりくどいことをする必要があるのでしょうか。
直接 SetWindowLongPtr 関数でスタイルを指定してもいいのではないかな、と思ったのですが、そうすると何か問題があるのでしょうか。
直接SetWindowLongPtr 関数でスタイルを指定してしまうと、元から指定されているスタイルが消えて不都合が生じることがあるからでしょう。

Re: ビット演算

Posted: 2015年6月07日(日) 19:28
by みけCAT
みそ油 さんが書きました:windows.h を参照したのですが、その中で他のヘッダファイルがいくつもインクルードされており、どのヘッダファイルに TBSTYLE_OLD などの値が定義されているのかがわかりませんでしたので、仮定で話を進めさせていただきました。
どちらのヘッダファイルに、TBSTYLE_OLD などの値が定義されているのでしょうか。
ヘッダファイルがあるディレクトリで、

コード:

grep -r TBSTYLE_FLAT *.h
のようにして検索するといいでしょう。
※正確なオプションは未検証です

Windowsでgrepが入っていなければこれをどうぞ。
Grep for Windows