015:リージョン

リージョン

regionとは
地方、地域、領域などと訳されますが、WindowsAPIでは、多角形で定義された領域を表す図形要素を表します。
日本語では、図形領域、とでも訳せばわかりやすいでしょうか。

リージョンを作成するにはCreateRectRgn関数を使用します。

HRGN CreateRectRgn(
  int nLeftRect,   // 左上隅のX座標
  int nTopRect,    // 左上隅のY座標
  int nRightRect,  // 右下隅のX座標
  int nBottomRect  // 右下隅のY座標
);

リージョンは領域を表す情報なので、リージョンを作っただけでは画面には何も描画されません。これだけでは利用価値がありませんが、通常はクリッピングリージョンとして利用します。

リージョンをデバイスコンテキストに設定すると、そのリージョンの範囲内のみが描画可能な領域となるのです。このように画面の一部分だけを描画可能にすることをクリッピングといいます。リージョンをデバイスコンテキストに割り当てるにはSelectClipRgn関数を使用します。

int SelectClipRgn(
  HDC
hdc,    // デバイスコンテキストのハンドル
  HRGN hrgn   // リージョンのハンドル
);

作成したリージョンは、他のオブジェクト同様、DeleteObject関数で破棄します。

さて、ではリージョンを使った描画をおこなってみましょう。

// gdi008.cpp
//
// リージョンによるクリッピング

#include <windows.h>

LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
ATOM InitApp(HINSTANCE);
HWND InitInstance(HINSTANCE, int);

WCHAR szClassName[] = _T("gdi008"); // ウィンドウクラス。UNICODEとしての文字列定数

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine,int nShowCmd)
{
   MSG msg;
   BOOL bRet;
   HWND hWnd;

   if (!InitApp(hInstance))
       return FALSE;
   if (!(hWnd = InitInstance(hInstance,nShowCmd)))
       return FALSE;
   while((bRet = GetMessage(&msg, NULL, 0, 0)) != 0) {
       if (bRet == -1){
           break;
       } else {
           TranslateMessage(&msg);
           DispatchMessage(&msg);
       }
   }
   return (int)msg.wParam;
}

// ウィンドウクラスの登録

ATOM InitApp(HINSTANCE hInst)
{
   WNDCLASS wc;
   wc.style        = CS_HREDRAW|CS_VREDRAW;
   wc.lpfnWndProc  = WndProc;  // プロシージャ名
   wc.cbClsExtra   = 0;
   wc.cbWndExtra   = 0;
   wc.hInstance    = hInst;
   wc.hIcon        = NULL;     // 未サポート
   wc.hCursor      = NULL;     // 未サポート
   wc.hbrBackground= (HBRUSH) COLOR_WINDOW;
   wc.lpszMenuName = NULL;     // 未サポート
   wc.lpszClassName=(LPCTSTR) szClassName;

   return (RegisterClass(&wc));
}

// ウィンドウの生成
HWND InitInstance(HINSTANCE hInst, int nShowCmd)
{
   HWND hWnd;

   hWnd = CreateWindow(szClassName,_T("Window Title"),
       WS_CLIPCHILDREN,    // ウィンドウの種類
       CW_USEDEFAULT,      // x座標
       CW_USEDEFAULT,      // y座標
       CW_USEDEFAULT,      // 幅
       CW_USEDEFAULT,      // 高さ
       NULL,               // 親ウィンドウのハンドル。親を作るのでNULL
       NULL,               // メニューハンドルまたは子ウィンドウID
       hInst,              // インスタンスハンドル
       NULL);
   if (!hWnd)
       return FALSE;
   ShowWindow(hWnd, nShowCmd);
   UpdateWindow(hWnd);
   return hWnd;
}

// ウィンドウプロシージャ
LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wp, LPARAM lp)
{
   PAINTSTRUCT ps;
   HDC hdc;
   HGDIOBJ hPen,hOldPen,hBrush,hOldBrush;
   HRGN hRgn;

   switch (msg){
       case WM_PAINT:
           hdc = BeginPaint(hWnd,&ps);                     // 描画処理を開始します。

           hPen = CreatePen(PS_SOLID, 1, RGB(255, 0, 0));  // 赤色のペンを作成
 &nb
sp;         hOldPen = SelectObject(hdc, hPen);              // 作成したペンを選択する
           hBrush = CreateSolidBrush(RGB(0, 255, 0));      // 緑色のブラシを作成
           hOldBrush = SelectObject(hdc, hBrush);          // 作成したペンを選択する

           hRgn = CreateRectRgn(0,20,100,80);              // リージョンの作成
           SelectClipRgn(hdc,hRgn);                        
// デバイスコンテキストにリージョンを設定

           Ellipse(hdc, 0, 0, 100, 100);                   // 円を描く

           SelectObject(hdc, hOldPen);                     // ペンを元に戻す
           SelectObject(hdc, hOldBrush);                   // ブラシを元に戻す
           DeleteObject(hPen);                             // 作成したペンを削除
           DeleteObject(hBrush);                           // 作成したブラシを削除
           DeleteObject(hRgn);                             // 作成したリージョンを削除

           EndPaint(hWnd,&ps);             // 描画処理を終了します。

           break;
       case WM_DESTROY:
           PostQuitMessage(0);
           break;
       default:
           return (DefWindowProc(hWnd, msg, wp, lp));
   }
   return 0;
}

描画領域が 横長の長方形リージョンに限定することで、円の上下がリージョンからはみ出るために描画されず切り取られました。

リージョンは、XPやVistaなどのデスクトップ用Windowsであれば長方形・多角形・円形などのリージョンを駆使して、複雑な図形を表現するのに使われるもので、高度な描画処理には欠かせません。しかし、WindowsMobileの場合、長方形のリージョンしか扱うことが出来ません。
円や、多角形を用いたリージョンは用意されていなのです。
そのため、リージョンを用いた複雑な描画は期待できませんね。

またWindowsには、リージョンとよく似た機能でありリージョンと同時に説明されることの多い「パス」という機能があります。
パスは直線と曲線を表すもので、複雑な図形をあらわことができます。このパスをリージョンに変換することができるため、複雑な描画処理に使われます。
しかしながらWindo
wsMobileではパスは一切使用できないようです。

まとめると、WindowsMobileにおいては、リージョンを用いた複雑な図形の描画は出来ない、ということになりますね。

今日はここまでです。 

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です