clipregion.cpp
来自「Windows 图形编程 书籍」· C++ 代码 · 共 403 行
CPP
403 行
//-----------------------------------------------------------------------------------//
// Windows Graphics Programming: Win32 GDI and DirectDraw //
// ISBN 0-13-086985-6 //
// //
// Written by Yuan, Feng www.fengyuan.com //
// Copyright (c) 2000 by Hewlett-Packard Company www.hp.com //
// Published by Prentice Hall PTR, Prentice-Hall, Inc. www.phptr.com //
// //
// FileName : clipregion.cpp //
// Description: Clip/meta region demo program, Chapter 7 //
// Version : 1.00.000, May 31, 2000 //
//-----------------------------------------------------------------------------------//
#define STRICT
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <assert.h>
#include <tchar.h>
#include "..\..\include\win.h"
#include "..\..\include\Canvas.h"
#include "..\..\include\Status.h"
#include "..\..\include\FrameWnd.h"
#include "..\..\include\LogWindow.h"
#include "Resource.h"
class KMyCanvas : public KCanvas
{
virtual void OnDraw(HDC hDC, const RECT * rcPaint);
virtual LRESULT WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
int m_nRepaint;
int m_Red, m_Green, m_Blue;
HRGN m_hRegion;
KLogWindow m_Log;
DWORD m_Redraw;
bool m_bValid[5];
HRGN m_hRandomRgn[5];
int m_test;
public:
BOOL OnCommand(WPARAM wParam, LPARAM lParam);
void DumpRegions(HDC hDC);
void DrawRegions(HDC hDC);
void TestClipMeta(HDC hDC, const RECT & rect);
KMyCanvas()
{
m_nRepaint = 0;
m_hRegion = CreateRectRgn(0, 0, 1, 1);
m_Red = 0x4F;
m_Green = 0x8F;
m_Blue = 0xCF;
m_Redraw = 0;
m_test = IDM_TEST_DEFAULT;
for (int i=1; i<=4; i++)
{
m_hRandomRgn[i] = CreateRectRgn(0, 0, 1, 1);
m_bValid[i] = false;
}
}
};
#ifndef SYSRGN
#define SYSRGN 4
__declspec(dllimport) extern "C" BOOL WINAPI GetRandomRgn(HDC hDC, HRGN hRgn, int which);
#endif
BOOL KMyCanvas::OnCommand(WPARAM wParam, LPARAM lParam)
{
switch ( LOWORD(wParam) )
{
case IDM_VIEW_HREDRAW:
case IDM_VIEW_VREDRAW:
{
HMENU hMenu = GetMenu(GetParent(m_hWnd));
MENUITEMINFO mii;
memset(& mii, 0, sizeof(mii));
mii.cbSize = sizeof(mii);
mii.fMask = MIIM_STATE;
if ( GetMenuState(hMenu, LOWORD(wParam), MF_BYCOMMAND) & MF_CHECKED )
mii.fState = MF_UNCHECKED;
else
mii.fState = MF_CHECKED;
SetMenuItemInfo(hMenu, LOWORD(wParam), FALSE, & mii);
if ( LOWORD(wParam)==IDM_VIEW_HREDRAW )
m_Redraw ^= WVR_HREDRAW;
else
m_Redraw ^= WVR_VREDRAW;
}
return TRUE;
case IDM_TEST_DEFAULT:
case IDM_TEST_SETCLIP:
case IDM_TEST_SETMETA:
case IDM_TEST_SETMETACLIP:
m_test = LOWORD(wParam);
InvalidateRect(m_hWnd, NULL, TRUE);
::UpdateWindow(m_hWnd);
break;
case IDM_FILE_EXIT:
DestroyWindow(GetParent(m_hWnd));
return TRUE;
}
return FALSE; // not processed
}
LRESULT KMyCanvas::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
LRESULT lr;
switch( uMsg )
{
case WM_CREATE:
m_hWnd = hWnd;
m_Log.Create(m_hInst, _T("ClipRegion"), LoadIcon(m_hInst, MAKEINTRESOURCE(IDI_GRAPH)));
return 0;
case WM_NCCALCSIZE:
lr = DefWindowProc(hWnd, uMsg, wParam, lParam);
if ( wParam )
{
lr &= ~ (WVR_HREDRAW | WVR_VREDRAW);
lr |= m_Redraw;
}
break;
case WM_PAINT:
{
PAINTSTRUCT ps;
HDC hDC = BeginPaint(m_hWnd, &ps);
// HRGN hRgn1 = CreateRectRgn(0, 0, 100, 100);
// HRGN hRgn2 = CreateRectRgn(50, 50, 300, 300);
// int value = CombineRgn(hRgn1, hRgn1, NULL, RGN_AND);
// DeleteObject(hRgn1);
// DeleteObject(hRgn2);
OnDraw(hDC, &ps.rcPaint);
EndPaint(m_hWnd, &ps);
hDC = GetDC(m_hWnd);
DrawRegions(hDC);
ReleaseDC(m_hWnd, hDC);
}
return 0;
default:
lr = DefWindowProc(hWnd, uMsg, wParam, lParam);
}
return lr;
}
void KMyCanvas::DumpRegions(HDC hDC)
{
for (int i=1; i<=4; i++)
{
m_bValid[i] = false;
int rslt = GetRandomRgn(hDC, m_hRandomRgn[i], i);
switch ( rslt )
{
case 1:
m_bValid[i] = true;
m_Log.DumpRegion("RandomRgn(%d)", m_hRandomRgn[i], false, i);
break;
case -1:
m_Log.Log("RandomRgn(%d) Error\r\n", i);
break;
case 0:
m_Log.Log("RandomRgn(%d) no region\r\n", i);
break;
default:
m_Log.Log("Unexpected\r\n");
}
}
}
void KMyCanvas::DrawRegions(HDC hDC)
{
HBRUSH hBrush;
SetBkMode(hDC, TRANSPARENT);
if ( m_bValid[1] )
{
hBrush = CreateHatchBrush(HS_VERTICAL, RGB(0xFF, 0, 0));
FillRgn(hDC, m_hRandomRgn[1], hBrush);
DeleteObject(hBrush);
}
if ( m_bValid[2] )
{
hBrush = CreateHatchBrush(HS_HORIZONTAL, RGB(0, 0xFF, 0));
FillRgn(hDC, m_hRandomRgn[2], hBrush);
DeleteObject(hBrush);
}
// if ( m_bValid[3] )
// {
// hBrush = CreateHatchBrush(HS_DIAGCROSS, RGB(0, 0, 0xFF));
// FillRgn(hDC, m_hRandomRgn[3], hBrush);
// DeleteObject(hBrush);
// }
}
void KMyCanvas::OnDraw(HDC hDC, const RECT * rcPaint)
{
RECT rect;
TCHAR mess[64];
GetClientRect(m_hWnd, & rect);
GetRandomRgn(hDC, m_hRegion, SYSRGN);
POINT Origin;
GetDCOrgEx(hDC, & Origin);
if ( ((unsigned) hDC) & 0xFFFF0000 )
OffsetRgn(m_hRegion, - Origin.x, - Origin.y);
m_nRepaint ++;
switch ( m_nRepaint % 3 )
{
case 0: m_Red = (m_Red + 0x31) & 0xFF; break;
case 1: m_Green= (m_Green + 0x31) & 0xFF; break;
case 2: m_Blue = (m_Blue + 0x31) & 0xFF; break;
}
SetTextAlign(hDC, TA_TOP | TA_CENTER);
int size = GetRegionData(m_hRegion, 0, NULL);
int rectcount = 0;
if ( size )
{
RGNDATA * pRegion = (RGNDATA *) new char[size];
GetRegionData(m_hRegion, size, pRegion);
const RECT * pRect = (const RECT *) & pRegion->Buffer;
rectcount = pRegion->rdh.nCount;
TEXTMETRIC tm;
GetTextMetrics(hDC, & tm);
int lineheight = tm.tmHeight + tm.tmExternalLeading;
for (unsigned i=0; i<pRegion->rdh.nCount; i++)
{
int x = (pRect[i].left + pRect[i].right)/2;
int y = (pRect[i].top + pRect[i].bottom)/2;
wsprintf(mess, "sysrgn rect %d", i+1);
::TextOut(hDC, x, y - lineheight, mess, _tcslen(mess));
wsprintf(mess, "(%d, %d, %d, %d)", pRect[i].left, pRect[i].top, pRect[i].right, pRect[i].bottom);
::TextOut(hDC, x, y, mess, _tcslen(mess));
}
delete [] (char *) pRegion;
}
HBRUSH hBrush = CreateSolidBrush(RGB(m_Red, m_Green, m_Blue));
FrameRgn(hDC, m_hRegion, hBrush, 4, 4);
FrameRgn(hDC, m_hRegion, (HBRUSH) GetStockObject(WHITE_BRUSH), 1, 1);
DeleteObject(hBrush);
TestClipMeta(hDC, rect);
}
void KMyCanvas::TestClipMeta(HDC hDC, const RECT & rect)
{
/////////////////////////////////
// Play with clip and meta region
HRGN hRgn;
switch ( m_test )
{
case IDM_TEST_DEFAULT:
break;
case IDM_TEST_SETCLIP:
hRgn = CreateEllipticRgn(0, 0, rect.right*3/4, rect.bottom);
SelectClipRgn(hDC, hRgn);
DeleteObject(hRgn);
break;
case IDM_TEST_SETMETA:
hRgn = CreateEllipticRgn(0, 0, rect.right, rect.bottom*3/4);
SelectClipRgn(hDC, hRgn);
SetMetaRgn(hDC);
break;
case IDM_TEST_SETMETACLIP:
hRgn = CreateEllipticRgn(0, 0, rect.right, rect.bottom*3/4);
SelectClipRgn(hDC, hRgn);
SetMetaRgn(hDC);
DeleteObject(hRgn);
hRgn = CreateEllipticRgn(0, 0, rect.right*3/4, rect.bottom);
SelectClipRgn(hDC, hRgn);
break;
}
DeleteObject(hRgn);
// with meta and clip region selected, only the
// intersection of system region, meta region, clip region can be painted
HBRUSH hBrush = CreateSolidBrush(RGB(0, 0, 0xFF));
FillRect(hDC, & rect, hBrush);
DeleteObject(hBrush);
DumpRegions(hDC);
char mess[64];
mess[0] = 0;
strcat(mess, "Clip: ");
if ( m_bValid[1] ) strcat(mess, "Y"); else strcat(mess, "N");
strcat(mess, ", Meta: ");
if ( m_bValid[2] ) strcat(mess, "Y"); else strcat(mess, "N");
strcat(mess, ", API: ");
if ( m_bValid[3] ) strcat(mess, "Y"); else strcat(mess, "N");
m_pStatus->SetText(0, mess);
}
class KLogoFrame : public KFrame
{
void GetWndClassEx(WNDCLASSEX & wc)
{
KFrame::GetWndClassEx(wc);
wc.hIcon = LoadIcon(m_hInst, MAKEINTRESOURCE(IDI_GRAPH));
}
public:
KLogoFrame(HINSTANCE hInstance, const TBBUTTON * pButtons, int nCount,
KToolbar * pToolbar, KCanvas * pCanvas, KStatusWindow * pStatus) :
KFrame(hInstance, pButtons, nCount, pToolbar, pCanvas, pStatus)
{
}
};
int WINAPI WinMain(HINSTANCE hInst, HINSTANCE, LPSTR, int nShow)
{
KMyCanvas canvas;
KStatusWindow status;
KLogoFrame frame(hInst, NULL, 0, NULL, & canvas, & status);
frame.CreateEx(0, _T("ClassName"), _T("Regions in a Device Context: System/Meta/Clip Regions"),
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
NULL, LoadMenu(hInst, MAKEINTRESOURCE(IDR_MAIN)), hInst);
frame.ShowWindow(nShow);
frame.UpdateWindow();
frame.MessageLoop();
return 0;
}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?