2017-01-17 9 views
6

次のコードはWindows 10 Anniversary Update SDKのものです。 DelphiではAPIを使用するために定数ハンドルが必要です。今日の時点では、これらのヘッダーはDelphiには含まれていないためです。DECLARE_HANDLEとその後のconstをwindef.hからDelphiに変換する方法

DECLARE_HANDLE(DPI_AWARENESS_CONTEXT); 

    #define DPI_AWARENESS_CONTEXT_UNAWARE   ((DPI_AWARENESS_CONTEXT)-1) 
    #define DPI_AWARENESS_CONTEXT_SYSTEM_AWARE  ((DPI_AWARENESS_CONTEXT)-2) 
    #define DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE ((DPI_AWARENESS_CONTEXT)-3) 

私は、さまざまなDPIシナリオでGetThreadDpiAwarenessContextを使用する場合、私はNativeUIntsなどの値が何であるかを学びました:

DPI_AWARENESS_CONTEXT_UNAWARE = 16; 
    DPI_AWARENESS_CONTEXT_SYSTEM_AWARE = 17; 
    DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE = 18; 

しかし、私は、これらの値は、将来性であることを100%と一定になりたいです。彼らはSetThreadDpiAwarenessContextコールで働き、望ましい効果がありますが、私はこれらの値がどのように到着したかについては不明です。明示的な整数宣言のほかに、Delphiのヘッダ構造を複製してその結果を作り出すことができませんでした。

+0

以下に述べるように、これらの「マジックナンバー」は、それぞれの条件でGetThreadDpiAwarenessContextから返される値です。また、SetThreadDpiAwarenessContextで動作し、期待された/望ましい結果を達成します。 –

+0

私はこの宣言を理解できません:https://msdn.microsoft.com/en-us/library/windows/desktop/mt791579(v=vs.85).aspx。宣言されたものは何ですか?これはenum、構造体、配列なのですか? 'typedefハンドルxxx {aaa、bbb、ccc} Txxx;'のようなものです。それはどんな宣言ですか? –

+0

@Rudyだから私は実際の宣言のためにSDKで掘ったのです。私は明らかに欠落してしまった - 基本的にこれらの定数のそれぞれは、ハンドルに負の整数キャストだけです。 –

答えて

9

SetThreadDpiAwarenessContextでの使用のためには、

type 
    DPI_AWARENESS_CONTEXT = type THandle; 
const 
    DPI_AWARENESS_CONTEXT_UNAWARE   = DPI_AWARENESS_CONTEXT(-1); 
    DPI_AWARENESS_CONTEXT_SYSTEM_AWARE  = DPI_AWARENESS_CONTEXT(-2); 
    DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE= DPI_AWARENESS_CONTEXT(-3); 

としてそれを宣言する必要がありますが、あなたがGetThreadDpiAwarenessContextからの応答を取得するときには、受信した値にGetAwarenessFromDpiAwarenessContextを使用してDPI_AWARENESS列挙型とそれを比較する必要があります。

DPI_AWARENESS_CONTEXTには複数の情報が含まれており、将来的に変更する可能性があるため、直接比較することはできません。

+0

これは正しい答えです。ありがとう。何らかの理由で、私は明らかな型キャスティングを完全に見逃していました。 –

+1

@BrandonStaggsこれはデータを設定するためのちょうど_magic_番号です。値を取得しているときに、DPI認識用の現在値と継承値が含まれていれば、そこに何か追加されている可能性があります。余分な機能を使用することで、将来的にコードを破損することを防ぐことができます。 – EugeneK

+0

今は明らかです。ありがとう! –

6

DelphiはC/C++インクルードファイルをまったく使用しないため、Windows SDKがIDEに同梱されているかどうかは関係ありません.Delphiプロジェクトでは使用されません。さて、もしDelphiがのCヘッダファイルのパスフレーズを提供していないことを心配しているなら、それは別の話です。

#ifdef STRICT 
typedef void *HANDLE; 
#if 0 && (_MSC_VER > 1000) 
#define DECLARE_HANDLE(name) struct name##__; typedef struct name##__ *name 
#else 
#define DECLARE_HANDLE(name) struct name##__{int unused;}; typedef struct name##__ *name 
#endif 
#else 
typedef PVOID HANDLE; 
#define DECLARE_HANDLE(name) typedef HANDLE name 
#endif 

STRICTは、より型安全性を提供:

DECLARE_HANDLE()は、入力パラメータの値とプリプロセッサSTRICTの条件が定義されているか否か基づいて、新しいデータ型の別名を宣言するCプリプロセッサマクロですC/C++コード。多くのWin32ハンドルタイプは、ユーザーコードでは不透明な型です。 DECLARE_HANDLE()を使用してそれらを宣言すると、コンパイラはSTRICTが定義されているときにそれらを異なるデータ型として扱うことができるため、さまざまなハンドル型が誤って混在することを防ぎます(HWNDが期待されるところなどHBITMAPを渡します)。 STRICTが導入される前に、多くの開発者がこの種の間違いを犯しました。すべてのハンドルタイプが実質的にだったため、コンパイル時の検証はできませんでした。

これはDECLARE_HANDLE(DPI_AWARENESS_CONTEXT)は、このようなDPI_AWARENESS_CONTEXTを宣言することを意味します:

  1. STRICTが定義されている場合:

    struct DPI_AWARENESS_CONTEXT__{int unused;}; 
    typedef struct DPI_AWARENESS_CONTEXT__ *DPI_AWARENESS_CONTEXT; 
    
  2. STRICTが定義されていないとき:

    typedef void* DPI_AWARENESS_CONTEXT; 
    

DPI_AWARENESS_CONTEXTのポインタ、タイプのポインタSTRICTに応じてポインタとして宣言されています。

この種の名前解決は、C/C++のようなプリプロセッサマクロをサポートしていないため、Delphiには変換できません。

type 
    {$IFDEF STRICT} 
    DPI_AWARENESS_CONTEXT__ = record 
    end; 
    DPI_AWARENESS_CONTEXT = ^DPI_AWARENESS_CONTEXT__; 
    {$ELSE} 
    DPI_AWARENESS_CONTEXT = Pointer; 
    {$ENDIF} 

それとも単にDelphiで完全STRICTの存在を忘れて::最も近い訳はなく、直接DPI_AWARENESS_CONTEXTを宣言するだろうDPI_AWARENESS_CONTEXTが宣言されると

type 
    DPI_AWARENESS_CONTEXT__ = record 
    end; 
    DPI_AWARENESS_CONTEXT = ^DPI_AWARENESS_CONTEXT__; 

いずれかの方法を、あなたはその定数を宣言することができます値:

const 
    DPI_AWARENESS_CONTEXT_UNAWARE = DPI_AWARENESS_CONTEXT(-1); 
    DPI_AWARENESS_CONTEXT_SYSTEM_AWARE = DPI_AWARENESS_CONTEXT(-2); 
    DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE = DPI_AWARENESS_CONTEXT(-3); 

更新:コメントに基づいて、あなたは、代わりに代わりにこれを使用することができます。これらの定数のみGetThreadDpiAwarenessContext()からSetThreadDpiAwarenessContext()に、NOT出力のために入力するために使用されていることを

type 
    DPI_AWARENESS_CONTEXT = type THandle; 

const 
    DPI_AWARENESS_CONTEXT_UNAWARE = DPI_AWARENESS_CONTEXT(-1); 
    DPI_AWARENESS_CONTEXT_SYSTEM_AWARE = DPI_AWARENESS_CONTEXT(-2); 
    DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE = DPI_AWARENESS_CONTEXT(-3); 

注意を。後者は、不透明なハンドルをプライベートメモリ構造体に返します。その構造から実際のDPI_AWARENESS値を取得するには、を使用する必要があります。

+0

あなたが定義する 'DPI_AWARENESS_CONTEXT__'は不透明なタイプであり、それが指している構造体が何であるかは興味深いことに注意してください。それをPointerまたはそれ以上のものとして宣言するだけで、THandle(整数型)、すべてがうまくいきます。これは、ユーザーが関与する限り、魔法の数ではありません。 –

+0

もちろん、DelphiではCヘッダを使用できません。だから私は変換が必要です。私はすでにGetProcAddressを使って関数ポインタをロードしています。 –

+0

@RudyVelthuis:不透明なレコードタイプであると想定されます。それはC/C++で 'STRICT'がすることです。 'THandle'や' Pointer'のエイリアスとして宣言すれば、すべての型の安全性が失われます( 'DPI_AWARENESS_CONTEXT'が期待される* THANDLEの値を渡すことができます)。それをレコード型(たとえ空のもの)へのポインタとして宣言することによって、型の安全性が維持されます。 –

関連する問題