37章 グラフィックス・デバイス・インターフェース(GDI)入門(その2)

<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=shift_jis"></meta>
<title>37章 グラフィックス・デバイス・インターフェース(GDI)入門(その2)
</title>
</head>

<body bgcolor="WHITE">
<font size="5">37章 グラフィックス・デバイス・インターフェース(GDI)入門(その2)
</font>
<hr>
<p align="CENTER">
<a href="chap37.lzh">ダウンロード</a>
<p>
 今回は、最も基本的なウインドウへの描画について説明します。プログラムそのものは単純ですが、GDIについて得る事は非常に多いので、気を抜かないでください。
<hr>
<p>
<b>
・デバイスコンテキストを取得する関数群
</b>
<p>
 この講座では、GDI入門(36章)に入る前に、すでに2種類のデバイスコンテキストの取得方法を紹介しています。つまり、<br>
・<b>GetDC関数</b>(4章)<br>
・<b>BeginPaint関数</b>(6章)<br>
です。
<p>
 この講座では、この他に、<br>
・<b>CreateCompatibleDC関数</b><br>
・<b>PrintDlg関数</b><br>
 について言及する予定です。他にも、デバイスコンテキストを取得する方法はありますが、普通にアプリケーションを作成する上で使用頻度が少ないので、言及しません。
<hr>
<p>
 さて、上記の4つのデバイスコンテキストを取得する関数の中で一番使用頻度が多く重要なのは、<u><i><b>BeginPaint関数</b></i></u>です。これは、5章で説明したように、<u><i><b>WM_PAINTメッセージに応答するときに使います</b></i></u>。今回は、この関数のみでデバイスコンテキストの取得を行っています。では、ソースコードの重要な箇所を見てみましょう。
<p>
<p>
<table border="1" bgcolor="#F0F0F0">
<caption align="BOTTOM">リスト37-1(WinMain.c)
<tr><td>
<pre>
/* C言語で始めるWindowsプログラミング */
/* 37章のサンプルプログラム */
/* Programmed by Y.Kondo */
/* 注:TABサイズは4で見てください */
/* このファイルではWinMain関数が定義して*/
/*ある */

#define STRICT
#include &lt;windows.h&gt;
#include "wndproc.h"
#include "resource.h"

/* アプリケーションエントリーポイント */
int WINAPI WinMain(HINSTANCE hInstance,
                 HINSTANCE    hPrevInstance,
                  LPSTR        CmdLine,
                  int          CmdShow)
{
  HWND            hwnd;   /*  メインウインドウのウインドウハンドル    */
   MSG             msg;    /*  メッセージキューから取得したメッセージ  */
   WNDCLASS        wc;     /*  ウインドウクラス登録用の構造体          */

  wc.style        =<b>CS_HREDRAW|CS_VREDRAW</b>;
   wc.lpfnWndProc  =WindowProc;
   wc.cbClsExtra   =0;
   wc.cbWndExtra   =0;
   wc.hInstance    =hInstance;
   wc.hIcon        =LoadIcon(hInstance,MAKEINTRESOURCE(IDI_ICON1));
   wc.hCursor      =LoadCursor(NULL,IDC_ARROW);
   wc.hbrBackground=(HBRUSH)(COLOR_WINDOW+1);
   wc.lpszMenuName =NULL;
   wc.lpszClassName="MainWindowClass";
   
   if(RegisterClass(&wc;)==0)               /*  ウインドウクラス登録    */
       return  0;

  hwnd=CreateWindow(  "MainWindowClass",  /*  ウインドウ作成          */  
                       "37章サンプル",
                       WS_OVERLAPPEDWINDOW,
                       CW_USEDEFAULT,
                       CW_USEDEFAULT,
                       CW_USEDEFAULT,
                       CW_USEDEFAULT,
                       NULL,
                       (HMENU)NULL,
                       hInstance,
                       0);
   if(hwnd==NULL)
       return  0;

  ShowWindow(hwnd,CmdShow);           /*  ウインドウの表示        */
   UpdateWindow(hwnd);                 /*  ウインドウの最初の更新  */

  while(GetMessage(&msg;,NULL,0,0))    /*  メッセージループ        */
   {
       TranslateMessage(&msg;);
       DispatchMessage(&msg;);
   }
   return  msg.wParam;
}
</pre>
</table>
<p>
<table border="1" bgcolor="#F0F0F0">
<caption align="BOTTOM">リスト37-2(WndProc.c)
<tr><td>
<pre>
/* C言語で始めるWindowsプログラミング */
/* 37章のサンプルプログラム */
/* Programmed by Y.Kondo */
/* 注:TABサイズは4で見てください */
/* このファイルでは、メインウインドウのウインド*/
/*ウプロシージャが定義されている */

#define STRICT
#include &lt;windows.h&gt;
#include &lt;stdio.h&gt;
#include "wndproc.h"

/*===============================================================================*/

/* このファイル内でのみ用いられる関数のプロトタイプ宣言 */
static LRESULT Wm_DestroyProc(void);
static LRESULT Wm_PaintProc(HWND);

/* メインウインドウのウインドウプロシージャ */
LRESULT CALLBACK WindowProc(HWND hwnd,UINT message,WPARAM wparam,LPARAM lparam)
{
  switch(message)
   {
       case    WM_PAINT:           /*  再描画処理              */
           return  Wm_PaintProc(hwnd);
       case    WM_DESTROY:         /*  ウインドウの破壊後処理  */
           return  Wm_DestroyProc();
   }
   return  DefWindowProc(hwnd,message,wparam,lparam);
}

/*===============================================================================*/

static LRESULT Wm_PaintProc(HWND hwnd)
{
  PAINTSTRUCT ps;
   HDC         PaintDC;
   char        text[]="既定値のフォント";
   RECT        Rect;
   HBRUSH      hBrush;
   POINT       forPolyline[]={{10,100},{50,120},{100,100},{200,120}};
   POINT       forPolyBezier[]={{10,130},{50,150},{100,90},{200,150}};

  if(GetUpdateRect(hwnd,NULL,TRUE))
   {<b>
       PaintDC=BeginPaint(hwnd,&ps;);   /*  ウインドウ描画用のデバイスコンテキスト取得  */
       /*  描画を行う  (ここから)    */

      /*既定値のフォントで文字を表示する*/
       TextOut(PaintDC,10,5,text,strlen(text));

      /*既定値のペンで線を描画する*/
       MoveToEx(PaintDC,10,30,NULL); LineTo(PaintDC,200,30);

      /*DKGRAY_BRUSHで矩形を描画する*/
       Rect.left=10; Rect.top=40; Rect.right=200; Rect.bottom=60;
       hBrush=GetStockObject(DKGRAY_BRUSH);
       SelectObject(PaintDC,hBrush);
       FillRect(PaintDC,&Rect;,hBrush);

      /*既定値のペンで矩形を描画し、内部をLTGRAY_BRUSHで塗りつぶす*/
       hBrush=GetStockObject(LTGRAY_BRUSH);
       SelectObject(PaintDC,hBrush);
       Rectangle(PaintDC,10,70,200,90);

      /*既定値のペンで折れ線を描く*/
       Polyline(PaintDC,forPolyline,sizeof(forPolyline)/sizeof(POINT));

      /*規定のペンで、ベジエ曲線を描く*/
       PolyBezier(PaintDC,forPolyBezier,sizeof(forPolyBezier)/sizeof(POINT));

      /*既定値のペンで楕円を描画し、*現在選択されてる*ブラシで塗りつぶす*/
       Ellipse(PaintDC,210,10,400,150);
       
       /*  描画を行う  (ここまで)    */
       EndPaint(hwnd,&ps;);             /*  ウインドウ描画用のデバイスコンテキスト開放  */</b>
   }
   return  0;
}

static LRESULT Wm_DestroyProc(void)
{
  PostQuitMessage(0);
   return  0;
}
</pre>
</table>
<p>
 太文字の箇所が、描画に関わる重要な箇所です。
<hr>
<p>
<b>
・関数概略
</b>
<p>
 GDIに関する関数の詳細な説明をしていれば、きりがないのと、GDIでの描画の概念を理解してもらい為に、各関数について詳細な説明を省きます。
<p>
<b>
・GetUpdateRect関数
</b>
<p>
 この関数は、更新すべきエリアを完全に囲む矩形の座標を取得します。今回の様に、第2引数がNULLの場合、更新すべきエリアがあるかどうかを調べます。しかし、この関数は、特に必要がありません。実際、この関数で条件判断をしなくても、問題無く、アプリケーションは動作します。
<p>
<b>
・BeginPaint関数
</b>
<p>
 この関数で、WM_PAINTに応答するためのデバイスコンテキストを取得します。引数として、PAINTSTRUCT構造体変数へのポインタを取ります。戻り値は、デバイスコンテキストのハンドルです。
<p>
<b>
・GetStockObject関数
</b>
<p>
 Windowsはペイントブラシの様にあらかじめ複数の描画オブジェクトを持っています。これらの中から描画オブジェクトのハンドルを取得する関数です。この描画オブジェクトを用いる限り、どのディスプレーでも安全に描画できると言う事です。<br>
 筆者の使っている環境(VC5)のマニュアルによると、以下の描画オブジェクトを取得出来ます。
<p align="CENTER">
<table border="1" bgcolor="#F0F0F0" width="95%">
<tr><td>BLACK_BRUSH<td>Black brush.
<tr><td>DKGRAY_BRUSH<td>Dark gray brush.
<tr><td>GRAY_BRUSH<td>Gray brush.
<tr><td>HOLLOW_BRUSH<td>Hollow brush (equivalent to NULL_BRUSH).
<tr><td>LTGRAY_BRUSH<td>Light gray brush.
<tr><td>NULL_BRUSH<td>Null brush (equivalent to HOLLOW_BRUSH).
<tr><td>WHITE_BRUSH<td>White brush.
<tr><td>BLACK_PEN<td>Black pen.
<tr><td>NULL_PEN<td>Null pen.
<tr><td>WHITE_PEN<td>White pen.
<tr><td>ANSI_FIXED_FONT<td>Windows fixed-pitch (monospace) system font.
<tr><td>ANSI_VAR_FONT<td>Windows variable-pitch (proportional space) system font.
<tr><td>DEVICE_DEFAULT_FONT<td>Windows NT only: Device-dependent font.
<tr><td>DEFAULT_GUI_FONT<td>Windows 95 only: Default font for user interface objects such as menus and dialog boxes.
<tr><td>OEM_FIXED_FONT<td>Original equipment manufacturer (OEM) dependent fixed-pitch (monospace) font.
<tr><td>SYSTEM_FONT<td>System font. By default, Windows uses the system font to draw menus, dialog box controls, and text. In Windows versions 3.0 and later, the system font is a proportionally spaced font; earlier versions of Windows used a monospace system font.
<tr><td>SYSTEM_FIXED_FONT<td>Fixed-pitch (monospace) system font used in Windows versions earlier than 3.0. This stock object is provided for compatibility with earlier versions of Windows.
<tr><td>DEFAULT_PALETTE<td>Default palette. This palette consists of the static colors in the system palette.
</table>
<p>
 ここで重要なのは、<u><i><b>Windowsは、描画オブジェクトして、ブラシ・ペン・フォント・パレットを持っている</b></i></u>と言う事です。その他に、プログラマーが作成しなければいけませんが、描画オブジェクトとして、ビットマップとリージョンと言う物を持っています。<u><i><b>GDIで表示デバイス(ディスプレーやプリンター)に描画すると言う事は、これらの描画オブジェクトを使って描画する事にほかなりません</b></i></u>。もちろん、ブラシ・ペン・フォント・パレットもプログラマーが独自に作成出来ます。これは、これからの章で説明いたします。
<p>
<b>
・SelectObject関数
</b>
<p>
 第1引数は、デバイスコンテキストのハンドル。第2引数は、描画オブジェクトのハンドルです。選択する描画オブジェクトは、ブラシ・ペン・フォント・パレット・ビットマップ・リージョンは、排他的で、新たなペンを選択しても、他の選択されている描画オブジェクトは変更されません。<br> そして、ここからが重要なのですが、<u><i><b>デバイスコンテキストが解放されない限り、選択されている描画オブジェクトの状態は保存されている</b></i></u>と言う事です。つまり、デバイスコンテキストは状態を持っている。つまり、オブジェクトと言えます。リスト37-2の楕円の描画を参考にしてください。
<p>
<b>
・他の第1引数としてデバイスコンテキストのハンドルをとる描画関数群
</b>
<p>
 サンプルプログラムでは、TextOut関数、MoveToEx関数、LineTo関数、FillRect関数、Rectangle関数、PolyLine関数、PolyBezier関数、Ellipse関数です。<br>
 これらの描画関数は無数にあり、とてもこの講座で説明出来ません。リファレンスマニュアルを参照して下さい。ただ、どの描画関数も、現在選択されている描画オブジェクトを用いて、描画します。
<p>
<b>
・EndPaint関数
</b>
<p>
 BeginPaint関数で取得したデバイスコンテキストを開放する関数です。
<hr>
<p>
 今回は、Windowsが最初から用意しているストックオブジェクトを用いて、GDIでの描画の実際を提示しました。次回は、用意されている描画オブジェクトでは描画しにくい物を表示する方法を説明します。つまり、ビットマップの貼り付けです。また、これだけでは面白くないので、簡単なアニメーションも行います。
<p>
 では、お楽しみに。
<p align="RIGHT">
2003年1月27日<br>
<hr>
<p align="RIGHT">
<a href="/web/20150829043811/http://web.kyoto-inet.or.jp:80/people/ysskondo/index.html">目次</a><br>
<hr>
<p align="RIGHT">
著作権者:近藤妥
</body>
</html>

  • 最終更新:2018-03-11 05:32:32

このWIKIを編集するにはパスワード入力が必要です

認証パスワード