レガシー Windows API(概要)について

ここで紹介しているAPIは、Windows95、Windows NT3.5時代のAPI群であり、最新のAPIは含まれていないことに注しして欲しい。なお、当時の解説書は現在よりもより詳細に解説しているため、参考になるはずである。

  • レイアウトを変換する際、崩れているページがあります。
  • 概要およびSampleコードはありますが、APIの解説はありません。

ご要望があれば旧版のWin32 API(HELP形式)をお譲りします。問い合わせフォームより申し込みください。

Windows API 色の概要

色はWindowsベースのアプリケーションで作成された画像やイメージの重要な要素です。アイデアを理解したり、 項目間の関係を示したり、 訴えたい点を強調したり、 出力品質を向上する場合に、 色が役に立ちます。Windowsでは、 それぞれのデバイスのカラー機能を認識し、 デバイスに最適な色を選択する手段をアプリケーションに与えて、 アプリケーションが画像やイメージで色を使えるようにしています。

このガイドでは、 Windowsベースのアプリケーションが、 ペン、 ブラシ、 テキスト、 およびビットマップで色を管理し使う方法を説明します。

次に示すトピックでは、 Win32の色のサポートについて説明します。

色の基本_

赤、 緑、 青 (RGB値)

色の近似値とディザリング

ビットマップの色

色の混合

カラー パレット

デフォルトのカラー パレット

論理パレット

パレット動画

システム パレット

システム パレットと静的な色

パレット メッセージ

ハーフトーン パレットと色の調整

色の使い方

色の関数

色のメッセージ

 

色の基本

ディスプレイやプリンタなどのデバイスの色の機能は、 単純な白黒から実際に何千色まで広範囲にわたります。どんなアプリケーションでも、 こういった広範囲の色の機能をサポートして、 デバイスに対する出力を作成しなければならない可能性があるため、 アプリケーションではさまざまな色の機能に対応できるよう準備することが重要になります。

アプリケーションでは、 GetDeviceCaps関数を使ってNUMCOLORS値を取得すれば、 特定のデバイスで使える色の数を判断できます。この値は、 アプリケーションが使える色の数を示します。この数は、 通常、 プリンタのインクの数やディスプレイ アダプタがモニタに転送できる色信号の数などの、 出力デバイスの物理的な特性に対応します。

NUMCOLORS値は色の数を示しますが、 使える色は識別しません。アプリケーションでPS_SOLID型を持つすべてのペンを列挙すれば、 使える色が判断できます。特定のデバイスをサポートするデバイス ドライバは、 通常、 全範囲のソリッド ペンを持つため、 また、 Windowsではソリッド ペンはデバイスが作成できる色だけを持つことが必要になるため、 ほとんどの場合、 ペンを列挙すれば、 色を列挙するのと同じになります。アプリケーションは、 EnumObjects関数を使ってペンを列挙できます。

赤、 緑、 青 (RGB値)

Windowsではデフォルトで、 色を3原色 (赤、 緑、 青) の組み合わせとして定義します。Windowsでは、 色の持つ赤と緑と青のそれぞれの量を示す値を指定することにより、 色を識別します。これらの値はRGB値 (赤: red、 緑: green、 青: blue) と呼ばれ、 この3つの要素の輝度を指定する8ビットの値で構成されます。黒は、 赤、 緑、 青の輝度が一番小さいので、 黒のRGB値は (0, 0, 0) になります。白は、 赤、 緑、 青の輝度が一番大きいので、 白のRGB値は (255, 255, 255) になります。

 イメージの色整合が有効になっている場合は、 色の定義とRGB値の意味は、 その時点でデバイス コンテキストに設定されているカラー スペースの種類によって異なります。

Windowsおよびアプリケーションでは、 COLORREF型を持つパラメータや変数を使って、 RGB値を渡したり格納します。たとえばEnumObjects関数は、 LOGPEN構造体のlopnColorメンバにRGB値を設定することにより、 それぞれのペンの色を識別します。アプリケーションは、 GetRValueGetGValue、 およびGetBValueマクロを使って、 RGB値から赤、 緑、 青の要素のそれぞれの値を抽出できます。アプリケーションはRGBマクロを使って、 個々の要素の値からRGB値を作成できます。また、 アプリケーションはRGBQUAD構造体を使って、 個々の要素の値を格納し、 Windowsに渡すこともできます。

 

色の近似値とディザリング

アプリケーションでは、 デバイスの色機能に関係なく色を使うこともできますが、 そうすると注意深く色を選択したときと比べて、 あまり効果的でなく、 望みどおりの結果が得られないことがあります。ほとんどのデバイスでは、 あらゆるRGB値の完全な色整合は保証されていないため、 デバイスで作成できない色をアプリケーションから要求した場合は、 デバイスが作成できる色でその色に一番近い色をWindowsが選びます。たとえば、 アプリケーションで白黒のプリンタに赤のペンを作成しようとした場合、 プリンタは黒のペンを受け取ります。Windowsが赤の近似値として黒を使うからです。

アプリケーションで、 GetNearestColor関数を使うと、 Windowsが特定の色に近似値を使うかどうかを判断できます。関数はRGB値を受け取り、 デバイスが作成できる色でそのRGB値に一番近い色のRGB値を返します。Windowsが近似値を判断するために使う方法は、 デバイス ドライバと色の機能により異なります。ほとんどの場合、 近似値の全体の輝度が、 要求された色の輝度に一番近いものになっています。

アプリケーションがテキストにペンを作成するか、 または色を設定したときに、 完全に一致する色がない場合は、 Windowsでは常に近似値を設定します。アプリケーションがソリッド ブラシを作成すると、 Windowsは要求された色をディザリングによってシミュレートしようとする場合があります。ディザリングとは、 パターンで2つ以上の色を交互に使って色をシミュレートすることです。たとえば、 赤と白の組み合わせる量を変えることによって、 いろいろな色合いのピンクをシミュレートできます。使う色とパターンによっては、 ディザリングでそれなりの色をシミュレートできます。ディザリングはモノクロのデバイスで最も効果的です。それは、 使える「色」の数を黒と白の2色から、 はるかに拡張できるためです。

ディザ カラーを作成する方法は、 デバイス ドライバにより異なります。ほとんどのデバイス ドライバでは、 要求された赤、 緑、 青の輝度の値に基づいたパターンを作成する、 標準のディザリング アルゴリズムを使っています。一般に、 要求された色がデバイスで作成できない場合は、 シミュレーションの対象になりますが、 Windowsは色をシミュレートしたときにアプリケーションには知らせません。さらに、 デバイス ドライバのディザリング アルゴリズムは、 アプリケーションでは修正または変更はできません。アルゴリズムをバイパスするには、 使いたい色とパターンを持つビットマップをアプリケーションで作成し、 アプリケーションでこのビットマップを使ってパターン ブラシを作成する必要があります。

 

ビットマップの色

Windowsでは、 ビットマップの色は、 ペン、 ブラシ、 テキストの色とは違う方法で扱われます。CreateBitmapまたはCreateCompatibleBitmap関数を使って作成された、 互換性のあるビットマップは、 デバイス固有であり、 デバイスに依存する形式で色情報を保持します。RGB値は使われず、 色の近似値もなく、 ディザリングも行われません。

デバイスに依存しないビットマップ (DIB) は、 RGB値またはカラー パレット インデックスとして色情報を保持します。RGB値を使う場合は、 色の近似は行われますが、 ディザリングは行われません。カラー パレット インデックスは、 カラー パレットをサポートするデバイスでのみ使えます。Windowsでは、 インデックスで識別された色の近似やディザリングは行いませんが、 結果の色が意図されたものと違う場合があります。これは、 インデックスが、 ビットマップ作成時のカラー パレットのコンテキスト内だけで有効な結果を作成するからです。パレットが変更されると、 ビットマップの色も変わります。

 

色の混合

色の混合で、 既存のイメージの色にペンやブラシの色を組み合わせて、 アプリケーションで新しい色を作成できます。アプリケーションでは、 ペンまたはブラシの色をそのまま描く (既存のイメージが何であってもその上に描く) か、 または既存の色に混合するかを選択できます。

前景混合モードは、 バイナリ ラスタ操作とも呼ばれますが、 色の混合を決定します。色のマージ、 つまり両方の色のすべての構成要素をそのまま保持すること、 色のマスク、 つまり共通ではない構成要素を削除または抑制すること、 および色の排他マスク、 つまり共通の構成要素を削除または抑制すること、 の3つをアプリケーションで実行できます。こういった基本的な混合操作には、 いくつかバリエーションがあります。

色の混合は、 色の近似の対象になります。色の混合の結果、 デバイスで作成できない色になったら、 Windowsではその結果の色を、 デバイスが作成できる色に近似処理します。アプリケーションでディザ カラーを混合する場合は、 ディザ カラーを作成するために使われた個別の色を混合し、 結果が色の近似の対象になります。

アプリケーションでは、 SetROP2関数を使って前景混合モードを設定し、 GetROP2関数を使って現在のモードを取得できます。

 

カラー パレット

カラー パレットは、 RGB値を含む配列で、 出力デバイスに現在表示または描画できる色を識別します。カラー パレットは、 多数の色を作成できるが、 同時に表示したり描画するのはその中のサブセットだけしかできないというデバイスにより使われます。こういったデバイスに対して、 Windowsはシステム パレットを保守して、 そのデバイスの現在の色を追跡し管理します。システム パレットは、 アプリケーションからは直接アクセスできません。そのかわり、 Windowsでは、 デフォルトのカラー パレットをそれぞれのデバイス コンテキストに関連付けます。アプリケーションはデフォルトのカラー パレットの色を使うか、 または論理パレットを作成して、 それぞれのデバイス コンテキストに関連付けることにより、 独自の色を定義できます。

デバイスがカラー パレットをサポートするかどうかは、 GetDeviceCaps関数が返すRASTERCAPS値のRC_PALETTEビットを調べればわかります。

 

デフォルトのカラー パレット

デフォルトのカラー パレットは、 デバイス コンテキストにデフォルトで使える色を識別するRGB値の配列です。Windowsでは、 アプリケーションがカラー パレットをサポートするデバイスにコンテキストを作成するたびに、 デフォルトのパレットをコンテキストに関連付けます。デフォルト パレットにより、 アプリケーションはそれ以上のアクションを必要としないで色を使えます。

デフォルト パレットは一般にエントリ (色) が20ありますが、 エントリの正確な数はデバイスごとに異なります。この数は、 GetDeviceCaps関数が返すNUMCOLORS値と同じです。アプリケーションは、 ソリッド ペンを列挙してデフォルト パレットの色のRGB値を取得できます。これは、 パレットのないデバイスで使える色を判断するために使うのと、 同じテクニックです。デフォルト パレットの色は、 デバイスにより異なります。たとえば、 ディスプレイ デバイスではほとんどの場合、 VGAディスプレイの標準の16色と、 Windowsで定義された追加の4色を使います。プリンタ デバイスではこれ以外のデフォルトの色を使う場合があります。

デフォルト パレットを使う場合は、 アプリケーションではRGB値を使ってペンやテキストの色を指定します。要求された色がパレットにない場合、 Windowsはパレットの中の一番近い色を使って色を近似させます。アプリケーションでパレットにないソリッド ブラシの色を要求した場合は、 Windowsはパレットの中の色を使ってディザリングすることにより、 その色をシミュレートします。

近似とディザリングを回避するためには、 アプリケーションで、 RGB値ではなくカラー パレットのインデックスを使って、 ペン、 ブラシ、 およびテキストの色を指定することもできます。カラー パレットのインデックスは、 特定のパレット エントリを識別する整数値です。

アプリケーションはRGB値のかわりにカラー インデックスを使えますが、 インデックスを作成するにはPALETTEINDEXマクロを使わなければなりません。カラー パレットのインデックスは、 カラー パレットをサポートするデバイスだけに使えます。このデバイス依存性を回避するために、 パレットを使うデバイスにも使わないデバイスにも同じコードで描画するアプリケーションでは、 ペン、 ブラシ、 およびテキストの色を指定するためにパレット相対RGB値を使う必要があります。

これらの値は、 ソリッド ブラシを作成するとき以外は、 RGB値とまったく同じです (パレット デバイスでは、 パレット相対RGB値で指定されたソリッド ブラシの色は、 ディザリングではなく、 色の近似の対象になります)。パレット相対RGB値を作成するには、 アプリケーションでPALETTERGBマクロを使わなければなりません。

Windowsでは、 アプリケーションはデフォルト パレットのエントリを変更することはできません。デフォルト パレットの色以外の色を使うには、 アプリケーションで独自の論理カラー パレットを作成し、 そのパレットをデバイス コンテキストで選択する必要があります。

 

論理パレット

論理パレットとは、 アプリケーションが作成し、 特定のデバイス コンテキストに関連付けるカラー パレットです。論理パレットにより、 アプリケーションは特定の要求に合う色を定義し、 使うことができます。

アプリケーションは、 CreatePalette関数を使って論理パレットを作成します。アプリケーションは、 エントリ数と各エントリのRGB値を指定するLOGPALETTE構造体を設定し、 この構造体をCreatePalette関数に渡します。関数がパレット ハンドルを返し、 アプリケーションはこのハンドルを使って、 それ以降の操作でパレットを識別します。論理パレットの色を使うには、 アプリケーションでSelectPalette関数を使って、 デバイス コンテキストにパレットを選択し、 RealizePalette関数を使ってパレットを実体化します。論理パレットが実体化できたらすぐにパレット内の色が使えます。

アプリケーションでは、 論理パレットのサイズを、 必要な色を表すエントリの数に制限する必要があります。アプリケーションは最大のパレット サイズ (デバイスに依存する値) 以上の大きさの論理パレットを作成することはできません。GetDeviceCaps関数を使って、 SIZEPALETTE値を取得すれば、 最大のパレット サイズがわかります。

アプリケーションでは、 論理パレットの指定されたエントリにどんなRGB値を指定することもできますが、 デバイスではすべての色が作成できるわけではありません。Windowsではデバイスでサポートされている色を判断する方法は提供していませんが、 アプリケーションでデバイスの色の解像度を取得して、 色の数の合計は判断できます。

ピクセル当たりのカラー ビット数で示される色の解像度は、 GetDeviceCaps関数が返すCOLORRES値と同じです。色の解像度が18のデバイスが持つ色は、 262,144色です。アプリケーションがサポートされていない色を要求した場合、 Windowsは適切な近似値を選びます。

論理パレットが作成されると、 アプリケーションは、 SetPaletteEntries関数を使って、 このパレットの色を変更できます。論理パレットが選択され実体化されている場合、 パレットを変えても、 表示されている色にはすぐには影響しません。色を更新するには、 アプリケーションでUnrealizeObjectおよびRealizePalette関数を使わなければなりません。

色が要求されたとおりに更新されることを保証するには、 アプリケーションで選択を解除し、 実体化を解除し、 再び選択し、 実体化しなければならない場合があります。アプリケーションで複数のデバイス コンテキストに1つの論理パレットを選択している場合は、 論理パレットを変更すると、 そのパレットが選択されているすべてのデバイス コンテキストに影響します。

アプリケーションは、 ResizePalette関数を使って、 論理パレットのエントリの数を変更できます。アプリケーションがこのサイズを減らした場合、 残っているエントリは変更されません。アプリケーションがこのサイズを増やした場合、 Windowsでは、 新しいエントリの色をそれぞれ黒 (0,0,0) に設定し、 フラグを0に設定します。

アプリケーションは、 GetPaletteEntries関数を使って、 特定の論理パレットのエントリの色とフラグの値を取得できます。また、 GetNearestPaletteIndex関数を使って、 特定のRGB値に一番近い、 論理パレットの色のインデックスを取得できます。

アプリケーションで論理パレットが必要なくなった場合は、 DeletePalette関数を使ってパレットを削除します。論理パレットを削除する前に、 そのパレットがデバイス コンテキストでは選択されていないことを、 アプリケーションで確認しなければなりません。

 

パレット動画

パレット動画とは、 カラー パレットの選択されたエントリの色を素早く変化させて、 単純な動画を作成するテクニックです。アプリケーションでは、 「予約」エントリを含む論理パレットを作成し、 次にAnimatePalette関数を使って、 予約エントリの色を変化させて、 パレット動画を実行できます。

アプリケーションでは、 PALETTEENTRY構造体のpeFlagsメンバをPC_RESERVEDに設定して、 論理パレットの予約エントリを作成します。論理パレットが選択され、 実体化されると、 アプリケーションはAnimatePalette関数を呼び出して、 1つ以上のエントリを変更できます。パレットがアクティブなウィンドウに関連付けられている場合、 Windowsは画面の色をすぐに更新します。

システム パレット

システム パレットはデバイスの物理パレットを表します。このためシステム パレットは、 そのデバイスでそのとき表示または描画できるすべての色のRGB値を格納します。システム パレットの内容を表示する以外、 アプリケーションではシステム パレットに直接アクセスできません。Windowsではシステム パレットを完全に制御し、 論理パレットを介してしかシステム パレットにはアクセスできません。

アプリケーションでは、 GetSystemPaletteEntries関数を使って、 システム パレットの内容を表示できます。この関数はシステム パレットのエントリの内容を取得します。内容を取得できるエントリの数は、 1つ以上で、 システム パレットのエントリの総数までです。

総数は、 GetDeviceCaps関数が返すSIZEPALETTE値と常に等しく、 論理パレットの最大のサイズと同じです。

アプリケーションでシステム パレットの色を直接変更することはできませんが、 論理パレットを実体化するときにシステム パレットが変更される場合があります。パレットを実体化するために、 Windowsは要求された色をそれぞれ調べて、 システム パレットの中で完全に一致するエントリを検索しようとします。Windowsが一致する色を見つけた場合は、 論理パレットのインデックスを、 対応するシステム パレットのインデックスにマップします。Windowsが一致する色を見つけなかった場合は、 インデックスをマップする前に、 要求された色を、 システム パレットの中で使われていないエントリにコピーします。システム パレットのすべてのエントリが使用中の場合、 Windowsは要求された色に一番近い色を持つシステム パレットのエントリに、 論理パレットのインデックスをマップします。このマッピングが設定されると、 アプリケーションでこの設定を無効にすることはできません。たとえば、 アプリケーションは色の指定にシステム パレットのインデックスを使えません。論理パレットのインデックスだけが使えます。

アプリケーションでは、 論理パレットを作成するときのpeFlagsメンバの設定によって、 インデックスをマップする方法を変更できます。たとえば、 PC_NOCOLLAPSE値を設定すると、 システム パレットのエントリにすでにその色があるかどうかに関係なく、 システム パレットの使っていないエントリに、 要求された色をすぐコピーするようにWindowsに指示します。また、 PC_EXPLICIT値で、 明示的に指定したシステム パレットのインデックスに論理パレットのインデックスをマップするように、 Windowsに指示します (アプリケーションは、 PALETTEENTRY構造体の下位のワードにシステム パレットのインデックスを与えます)。

アプリケーションでインデックスのマップ方法を変更するもう1つの方法は、 SelectPalette関数を呼び出すときに、 論理パレットを背景パレットに設定する方法です。背景パレットを実体化する場合、 Windowsでは、 指定された論理パレットのインデックスを、 要求された色に一番近い色を持つシステム パレットのエントリのインデックスに常にマップします。使っていないシステム パレットのエントリに、 要求された色をコピーすることはありません。一般に背景パレットは、 ディスプレイで、 独自のパレットを実体化する複数の子ウィンドウを持つアプリケーションで使います。こうすれば、 システム パレットのエントリへの変更を最小限にできます。

システム パレットの使っていないエントリとは、 予約されていなくて、 静的な色を含まないエントリです。予約エントリとは、 PC_RESERVED値で明示的にマークされたエントリです。アプリケーションがパレット動画のために論理パレットを実体化するときに、 予約エントリが作成されます。静的な色のエントリはWindowsにより作成され、 デフォルト パレットの色に対応します。GetDeviceCaps関数を使ってNUMRESERVED値を取得すれば、 静的な色に予約されているシステム パレット エントリの数を取得できます。

システム パレットには限られた数のエントリしかないため、 特定のデバイスの論理パレットを選択し、 実体化すると、 そのデバイスのほかの論理パレットに関連付けられている色に影響する場合があります。こういった色の変化はディスプレイ上でもっとも顕著に現れます。アプリケーションでは、 論理パレットを使う前にパレットをリセットして、 現在選択されている論理パレットに正しい色が使われることを保証できます。アプリケーションは、 UnrealizeObjectおよびRealizePalette関数を呼び出して、 パレットをリセットします。これにより、 Windowsが論理パレットの色をシステム パレットの正しい色にマップし直します。

 

システム パレットと静的な色

Windowsが静的な色用に予約するシステム パレット エントリは、 通常は変更できません。しかし、 アプリケーションでSetSystemPaletteUse関数を呼び出して、 静的な色のエントリ数を減らして、 システム パレットの使われていないエントリ数を増やすことにより、 このデフォルト動作を無効にできます。

アプリケーションで、 SYSPAL_NOSTATIC値を指定してSetSystemPaletteUse関数を呼び出すと、 Windowsは2つの予約エントリ以外のエントリをすべて解放し、 アプリケーションが次に論理パレットを実体化するときに、 解放されたエントリが新しい色の値を受け取れるようにします。残った2つの静的な色は予約されたままで、 白と黒に設定されます。アプリケーションでは、 SYSPAL_STATIC値を指定してSetSystemPaletteUse関数を呼び出せば、 予約エントリを復元できます。GetSystemPaletteUse関数を使えば、 現在のシステム パレットの色の使用がわかります。

静的な色を変更すると、 ディスプレイ上のすべてのウィンドウに即座に顕著な影響が出るため、 アプリケーションが最大化ウィンドウを使い、 そのアプリケーションに入力フォーカスがある場合以外は、 アプリケーションでSetSystemPaletteUse関数を呼び出してはいけません。

さらに、 システム パレットの使用をSYSPAL_NOSTATICに設定した後は、 アプリケーションでは論理パレットを即座に実体化し、 GetSysColor関数を呼び出して、 現在のシステム カラーの設定を格納し、 SetSysColors関数を呼び出して、 黒と白を使ってシステム カラーを正しい値に設定し、 最後に、 ほかのトップ レベル ウィンドウにWM_SYSCOLORCHANGEメッセージを送って、 新しいシステム カラーで再描画できるようにする必要があります。黒と白を使ってシステム カラーを設定する場合、 アプリケーションでは、 ウィンドウの枠や境界のように隣合うまたは重なり合う項目が、 それぞれ黒と白に設定されることを確認する必要があります。

アプリケーションは入力フォーカスを失い、 ウィンドウを閉じるかまたは終了する前には、 SYSPAL_STATIC値を指定してSetSystemPaletteUse関数を即座に呼び出し、 論理パレットを実体化し、 システム カラーをその前の状態に戻し、 WM_SYSCOLORCHANGEメッセージを送らなければなりません。システム カラーの変更により影響されるすべてのウィンドウに対して、 WindowsがWM_PAINTメッセージを送ります。現在のシステム カラーを使っているブラシを持つアプリケーションは、 ブラシを削除して、 新しいシステム カラーでブラシをもう1度作成しなければなりません。

 

パレット メッセージ

ディスプレイ デバイスの場合、 システム パレットを変更すると、 デスクトップのウィンドウで使われている色への影響が著しく、 ときには好ましくない結果になります。変更の影響を最小限に抑えるために、 Windowsでは一連のメッセージを用意して、 アプリケーションが論理パレットを管理できるようにし、 同時にアクティブ ウィンドウに表示する色をできるだけ意図された色に近いものにできるようにしています。

Windowsは、 トップ レベル ウィンドウやオーバーラップ ウィンドウをアクティブにする直前に、 ウィンドウにWM_QUERYNEWPALETTEメッセージを送ります。このメッセージにより、 アプリケーションは論理パレットに最適のカラー マッピングを受け取れるように、 論理パレットを選択し、 実体化できます。メッセージを受け取ったら、 アプリケーションではSelectPaletteUnrealizeObject、 およびRealizePalette関数を使って、 論理パレットを選択し、 実体化する必要があります。パレットを選択し実体化すると、 システム パレットの色ができるだけ論理パレットの色に一致するよう、 Windowsがシステム パレットを更新します。

アプリケーションで論理パレットを実体化した結果、 システム パレットを変更してしまうと、 Windowsがすべてのトップ レベル ウィンドウとオーバーラップ ウィンドウにWM_PALETTECHANGEDメッセージを送ります。これにより、 アプリケーションはウィンドウのクライアント領域の色を更新することができ、 変更された色を意図された色に近い色に置き換えます。WM_PALETTECHANGEDメッセージを受け取ったアプリケーションでは、 UnrealizeObjectおよびRealizePalette関数を使って、 アクティブでないウィンドウに関連する論理パレットをリセットし、 次に、 UpdateColors関数を使って、 アクティブでないウィンドウのそれぞれのクライアント領域の色を更新します。このテクニックで色の一致が最大限できるわけではありませんが、 論理パレットの色がシステム パレットの正しい色にマップされることは保証できます。無限ループにならないようにするには、 このメッセージのwParamパラメータで渡されるハンドルと一致するハンドルを持つウィンドウのパレットを、 アプリケーションで絶対実体化しないようにします。

アクティブでないウィンドウのクライアント部分を更新する場合は、 一般にUpdateColors関数を使った方が、 その部分を描画し直すよりも早くできますが、 UpdateColors関数は、 システム パレットが変更される前の各ピクセルの色に基づいて色の変換を実行するため、 色の正確性が失われる場合があります。これは、 ウィンドウがアクティブになったときに、 色を更新するためにはUpdateColors関数を使えないということを意味します。この場合は、 アプリケーションでクライアント領域を描画し直す必要があります。

論理パレットが変更されたときに、 WindowsはWM_QUERYNEWPALETTEメッセージを送る場合があります。また、 システム パレットがこれから変更されるというときに、 Windowsはトップ レベル ウィンドウとオーバーラップ ウィンドウに、 WM_PALETTEISCHANGINGメッセージを送る場合もあります。

 

ハーフトーン パレットと色の調整

デバイス コンテキストの伸縮モードがHALFTONEに設定されている場合は、 ハーフトーン パレットが使われます。アプリケーションは、 CreateHalftonePalette関数を使ってハーフトーン パレットを作成します。アプリケーションは、 StretchBltまたはStretchDIBits関数を呼び出す前に、 このパレットをデバイス コンテキストに選択し、 実体化する必要があります。

デバイス コンテキストの伸縮モードがHALFTONEに設定されているときに、 アプリケーションがStretchBltおよびStretchDIBits関数を呼び出すと、 Windowsがソース ビットマップの入力カラーを自動的に調整します。こういった色の調整により、 コントラストや明るさのようなイメージの属性が影響を受けます。アプリケーションは、 SetColorAdjustment関数を使って、 色の調整値を設定できます。アプリケーションでは、 GetColorAdjustment関数を使えば、 指定されたデバイス コンテキストで使われる色の調整値を取得できます。

 

色の使い方

このガイドでは、 色を使って実行する共通の作業をいくつか説明します。

 

色の列挙

デバイスの色の数を取得し、 ソリッド ペンの色を列挙すれば、 そのデバイスがサポートする色の数と色の種類を判断できます。色の数を取得するには、 NUMCOLORS値を指定してGetDeviceCaps関数を使います。ソリッド ペンを列挙するには、 EnumObjects関数と、 各ペンの情報を取得する、 対応するコールバック関数を使います。

// GetTheColors - 純色の数とRGB値を返す。
// 色を格納する配列のアドレスを返す。
// hdc - デバイス コンテキストのハンドル。

COLORREF *GetTheColors(HDC hdc)
{
int cColors;
COLORREF *aColors;

// get the number of colors
cColors = GetDeviceCaps(hdcCurrent, NUMCOLORS);

// allocate space for the array
aColors = (COLORREF *)LocalAlloc(LPTR, sizeof(COLORREF) *
(cColors+1));

// save the count of colors in first element
aColors[0] = (LONG)cColors;

// enumerate all pens and save solid colors in array
EnumObjects(hdc, OBJ_PEN, (GOBJENUMPROC)MyEnumProc, (LONG)aColors);

// refresh the count of colors
aColors[0] = (LONG)cColors;

return aColors;
}

int MyEnumProc(LPVOID lp, LPBYTE lpb)
{
LPLOGPEN lopn;
COLORREF *aColors;
int iColor;

lopn = (LPLOGPEN)lp;
aColors = (COLORREF *)lpb;

if (lopn->lopnStyle==PS_SOLID) {
// check for too many colors
if ((iColor = (int)aColors[0]) <= 0)
return 0;
aColors[iColor] = lopn->lopnColor;
aColors[0]--;
}
return 1;
}


色付きペンとブラシの作成

ペンを作成するときにはどの色でも指定できますが、 Windowsはデバイスで使える色だけを使います。これは、 Windowsが描画用のペンを実体化するときに、 一番近い色を使うことを意味します。ブラシを作成する場合は、 デバイスでサポートされていない色を指定すると、 Windowsがディザ カラーを作成します。ペンまたはブラシを作成する場合は、 どちらの場合も、 色の指定にRGBマクロが使えます。

// DrawARectangle - 緑の境界付きの赤の長方形を描く。
// 戻り値はない。
// hdc - デバイス コンテキストのハンドル。

void DrawARectangle(HDC hdc)
{
HPEN hpen, hpenOld;
HBRUSH hbrush, hbrushOld;

// Create a green pen.
hpen = CreatePen(PS_SOLID, 10, RGB(0, 255, 0));
// Create a red brush.
hbrush = CreateSolidBrush(RGB(255, 0, 0));

// Select the new pen and brush, then draw.
hpenOld = SelectObject(hdc, hpen);
hbrushOld = SelectObject(hdc, hbrush);
Rectangle(hdc, 100,100, 200,200);

// Don't forget to clean up.
SelectObject(hdc, hpenOld);
DeleteObject(hpen);
SelectObject(hdc, hbrushOld);
DeleteObject(hbrush);
}

 

▲ページトップに戻る

【本を読んでもよくらからない】 … 個別指導でわかりやすくお教えします
inserted by FC2 system