2016-05-26 11 views
3

私はC++を学んで新鮮で、winapiを学ぶために、私はForgers Win32 APIチュートリアルを行っています。ここで理解:long_ptrからboolへの変換可能性のあるデータ損失

は私のコードです:

//MyControl.h 
#pragma once 

#include <windows.h> 
#include "resource.h" 

BOOL CALLBACK DlgProc(HWND hwnd, UINT Message, WPARAM wParam, LPARAM lParam); 
BOOL BrushExists(HBRUSH hBrush); 
------------------------------------------------------- 
//MyControl.cpp 
#include "MyControl.h" 

HBRUSH g_hbrBackground = NULL; 

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, 
    LPSTR lpCmdLine, int nCmdShow) 
{ 
    return (int)DialogBox(hInstance, MAKEINTRESOURCE(IDD_MAIN), NULL, (DLGPROC)DlgProc); 
} 

BOOL BrushExists(HBRUSH hBrush) // I added this to better understand what is happening 
{ 
    if (hBrush) 
     return TRUE; 
    else 
     return FALSE; 
} 

BOOL CALLBACK DlgProc(HWND hwnd, UINT Message, WPARAM wParam, LPARAM lParam) 
{ 
    switch (Message) 
    { 
    case WM_INITDIALOG: 
    { 
     g_hbrBackground = CreateSolidBrush(RGB(0, 0, 0)); 
//... Other code skipped copy pasting ... 
    } 
     break; 
    case WM_COMMAND: 
//... Other code skipped copy pasting ... 
     break; 
    case WM_CTLCOLORDLG: 
     return (LONG_PTR)g_hbrBackground; // Where casting happens 
//  return BrushExists(g_hbrBackground); // Tried this to understand things 
     break; 
    case WM_CTLCOLORSTATIC: 
    { 
     HDC hdcStatic = (HDC)wParam; 
     SetTextColor(hdcStatic, RGB(255, 255, 255)); 
     SetBkMode(hdcStatic, TRANSPARENT); 
     return (LONG_PTR)g_hbrBackground; // Where casting happens 
//  return BrushExists(g_hbrBackground); // Tried this to understand things 
    } 
     break; 
//... Other code skipped copy pasting ... 
} 

コードが警告をコンパイルしています:予想通りC4244: 'return': conversion from 'LONG_PTR' to 'BOOL', possible loss of data

鋳造作品やダイアログボックスが右に着色されている: Black colored dialog.

私の質問:HBRUSHがBOOLを返す関数(DLGPROC)からLONG_PTRとして返されたとき、バックグラウンドではどうなりますか? LONG_PTRが0でなければ返されるBOOLはTRUEで、LONG_PTRが0の場合返されるBOOLはFALSEです。これを確認するために、私は関数BOOL BrushExists(HBRUSH hBrush);// See codeを作成しました。この関数を使用してHBRUSHをチェックし、TRUEを返し、警告なしでコンパイルし、エラーなしで実行します。しかし、ダイアログボックスの色付けは行われません。 Black color missing.

私の前提は間違っています。 LONG_PTRは、BOOLの代わりにwin32 APIによって数値として評価されているようです。誰かが私にこれがどのように起こっているのか説明することができますか?

答えて

3

BOOLであり、boolではないことに注意してください。 Windows SDKではBOOLintのtypedefで、32ビット値を格納できます。これはtrueまたはfalseしか格納できない単純なブール値ではありません。

これは基本的にAPIのkludgeです。 32ビットWindowsでは、ブラシハンドルは32ビット値に収まりますが、醜く、混乱させる可能性があるにもかかわらず、BOOLとしてキャストされたブラシハンドルを返すのは安全です(キャストしなければならなかったので、DialogProcでした)。戻り値として定義されます)。

Windowsが64ビットのサポートを獲得すると、この状況は明らかに受け入れられませんでした。この例では、ブラシハンドル(ポインタ)は64ビットです。32ビット型にキャストすることは安全ではありません。

したがって、DialogProcの定義は、BOOLではなくINT_PTRを返すように変更されました。これは、x86では32ビット、x64では64ビットにtypedefedされています。使用したサンプルコードは明らかにこの変更の日付より前ですが、新しいコードではDialogProcという正しい定義を使用して、INT_PTRを返します。

+1

*「これはAPIのクルーギーです。」* - クルーグではなく、必要です。 Windows APIは 'bool'データ型に先立っています。 – IInspectable

+0

ありがとうございます。それは物事を説明し、私の混乱を解決しました。 –

+0

まだkludge。 BOOLがどのように型定義されているか(すなわち、その表現が何ビットの実際のビットを有するかにかかわらず)、それでも*意味的に*はブール値を表す。 true/false以外の何かを返すと、意味論的な契約が破られます。ダイアログプロシージャは、最初からINTまたはDWORDまたは同等のものを戻す必要があります。 –

0
  • BOOLint typedefとなります。
  • LONG_PTRは、選択されたプラットフォームに応じて、long intまたは__int64のいずれかです。 Fromヘッダー

#ifdef _WIN64 
typedef __int64    LONG_PTR; 
#else 
typedef long   LONG_PTR; 
#endif 

あなたは警告与えている(int64と本質的にint)のx64コンパイラとしてプロジェクトを構築し、ひいてはBOOLLONG_PTRにしているようです。

Visual C++/Windowsでは、intlongが本質的に同じであることに注意してください。

+0

説明をありがとうございました。 –

+0

ようこそ。答えが良かったら、評価してください。 – Ajay

関連する問題