Visual Studio 2019 community、MFC、SDI アプリです。
ダイアログ上にリストビューをコードで作成し、リストビュー上でクリックして、ある機
能を行います。
Buildすると、「ビルド: 1 正常終了」にはなりますが、次の警告が出て、カーソルが
コードの ON_NOTIFY の行に移動して、”ここだよ”と知らせてくれます。
”warning C4310: キャストによって定数値が切り捨てられました。”
以下のコードのどこが不適切なのでしょうか?
どうぞよろしくご教授ください。お願いいたします。
<CDlgKabuki.h>
public:
void OnClickLvKabuki(NMHDR* pNMHDR, LRESULT* pResult);
<CDlgKabuki.coo>
BEGIN_MESSAGE_MAP(CDlgKabuki, CDialogEx)
ON_NOTIFY(NM_CLICK, IDC_LV_KABUKI, &CDlgKabuki::OnClickLvKabuki)
END_MESSAGE_MAP()
int CDlgKabuki::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
m_lvKabuki = new CListCtrl();
m_lvKbuki->Create(LVS_REPORT | WS_VISIBLE | WS_BORDER, CRect(0, 0,
rcClient.right, rcClient.bottom), this, IDC_LV_KABUKI);
以下省略
}
void OnClickLvKabuki(NMHDR* pNMHDR, LRESULT* pResult)
{
UNREFERENCED_PARAMETER(*pNMHDR);
ここのコードは省略
}
自力解決しました。
原因は、IDC_LV_KABUKI に 90000台の値を定義していました。
これを 3000台の数字に変えたら警告は出なくなりました。
境界点を調べたら、おおよそ 65500以下ならOKのようです。
UINT の最大値は 4294967295 なのに、不思議です。
ON_NOTIFY(・・・)の定義では第二引数のidはWORD型が要求されています。
これはコントロールのIDを意味しますが、WindowsではコントロールのIDの
上限はWORDの最大値となります。つまり0xFFFF=65535ですね。
これが警告が出る理由です。
以下は蛇足です。
では「なぜWORDに制限されているのか」ですが、
Windowsでは、あるコントロールのアクション、例えばクリックされた場合には
WM_COMMANDがポストされるわけですが、この時引数のWPARAM(=64bit)には
1.上位のWORDにNotifyコードを保持(0と1は特殊な意味を持つ)
2.下位のWORDにコマンドのID(=コントロールのID)を保持
となっているわけです。
つまり、構築時には64bitのIDを与えても警告されませんが、
そのIDがコマンドIDとして処理される場合はWORD=32bitの値しか
扱えないわけですね。WM_NOTIFYも原理的に同じとなります。
つまり、以下の事が言えます。
(A)コントロールのIDには64bitを与えることができるが、
(B)もしそのコントロールが他にWM_COMMAND、WM_NOTIFY等を
送付するならば、32bitまでのIDでなければ、機能しない。
というわけです。
Windowsの歴史的経緯でこの仕様になっているので、注意しましょう。
仲澤@失業者様
解り易い解説を有難うございました。
理屈を理解しないでIDを定義していました。
メニュー(リボンバー)のコントロールのIDは、ON_COMMAND に渡されますが、理屈は知
知らずに3000台にしていたので、良かった訳ですね。
ダイアログ上のコントロールのIDは大きな数値にしています。
ON_BN_CLICKED、ON_EN_CHANGE等に渡されますが、これらは64bitでいいのですね。
勉強になりました。