ウインドウの壁紙

 ウインドウのクライアント領域全体にビットマップを描画すると、任意のビットマップを「壁紙」にする事ができます。でも、この場合はウインドウ上にボタンなどの他のウインドウを置いてもその部分には壁紙が表示されず、文字通り「浮いて」しまいますね。今回は、ウインドウに壁紙を張り、ウインドウ上の子ウインドウにもその壁紙を描いてみましょう。

ウインドウの壁紙

 ウインドウに「壁紙」を張るには、WM_PAINTメッセージの処理でクライアント領域の全体にビットマップを描きます。これはGetClientRect()でクライアント領域の大きさを取得し、その大きさでビットマップを描くだけですから、特に問題はないでしょう。

  case WM_PAINT:

    hdc=BeginPaint(hwnd,&ps);

    GetClientRect(hwnd,&rec); /* クライアント領域取得 */

    StretchDIBits(hdc,0,0,rec.right,rec.bottom,0,0,dwWidth,dwHeight,
      lpPixel,lpInfo,DIB_RGB_COLORS,SRCCOPY); /* DIBを画面に描画 */

    EndPaint(hwnd,&ps);

    break;

 これで、dwWidth×dwHeightDIBをクライアント領域全体に描画できます。ビットマップとウインドウの縦横比が違うと不自然になってしまいますが、拡大処理は意外にきれいですね。

 問題は、ウインドウの上に配置した子ウインドウの描画です。GetDC()でウインドウのデバイスコンテキストを取得できるのですが、ここにはすでに「子ウインドウ自身」が描かれているので、その部分の壁紙を取得する事はできません。子ウインドウの「背後」(メインウインドウのクライアント領域)に描かれている壁紙を取得したくても、そこにはすでに子ウインドウ自身(=子ウインドウの描画結果)が描きこまれ、壁紙が「上書き」されてしまっているわけです。そこで、今回はメインウインドウの描画時に子ウインドウの領域の部分を保存しておく、という方法をとる事にしました。

子ウインドウの描画

 メインウインドウのクライアント領域を保存するには、メインウインドウのWM_PAINTで描画した結果をDIB化します。DIBであれば、半透明化などピクセル単位の処理が行いやすいので好都合でしょう。

 保存処理では、まずメインウインドウのクライアント領域のデバイスコンテキストと同形式のデバイスコンテキスト・ビットマップを作成し、デバイスコンテキストにビットマップを選択します。今回は、子ウインドウを(16,16)〜(144,80)までの128×64ピクセルに配置するので、128×64ピクセルのビットマップを作成しました。

  hBMP=CreateCompatibleBitmap(hdc,128,64); /* ビットマップ作成 */
  hdcMem=CreateCompatibleDC(hdc); /* ビットマップ描画用DC作成 */
  hOBMP=SelectObject(hdcMem,hBMP); /* ビットマップをDCに選択

 次に、メインウインドウのクライアント領域の子ウインドウを配置する部分をBitBlt()でビットマップに描きます。その後GetDIBits()でビットマップをDIB化すれば、準備完了。この関数に渡すBITMAPINFOは、24ビットDIBヘッダとしてあらかじめ作成しておきます。

  /* ビットマップに現在のクライアント領域をコピー */
  BitBlt(hdcMem,0,0,128,64,hdc,16,16,SRCCOPY);

  SelectObject(hdcMem,hOBMP); /* ビットマップの選択を解除 */

  /* ビットマップをDIBに変換 */
  GetDIBits(hdcMem,hBMP,0,64,lpBGPixel,lpBGInfo,DIB_RGB_COLORS);

 これでlpBGPixelに子ウインドウ部分のピクセル列を24ビットDIB形式で取得できたので、次はいよいよ子ウインドウ自身の描画。でも、これはDIBに退避しておいたメインウインドウのクライアント領域を子ウインドウ全体に描画するだけですから簡単です。今回は、ピクセルの青成分を0にして子ウインドウの部分を黄色っぽくしてみました。

  case WM_PAINT: /* 子ウインドウの描画処理 */

      hdc=BeginPaint(hwnd,&ps);

      for (i=0;i<64;i++) /* 全ピクセルの青成分を0に */
          for (j=0;j<128;j++)
              lpBGPixel[j*3+i*128*3]=0;

      StretchDIBits(hdc,0,0,128,64,0,0,128,64,lpBGPixel,lpBGInfo,
        DIB_RGB_COLORS,SRCCOPY);

      EndPaint(hwnd,&ps);

      break;

プログラム

 実行すると、白いクライアント領域の左上に黄色の子ウインドウが描画されます。ウインドウに24ビットフルカラービットマップファイルをドロップすると、そのビットマップがウインドウ全体に描かれ子ウインドウにも青成分を除いたピクセルが描画されるので試してみてください。子ウインドウの描画処理を半透明や彩度低下などにすれば、壁紙上のコントロールらしくなりますね。

プログラムソース表示


Windowsプログラミング実験室 > プログラミング資料庫