|
|

楼主 |
发表于 2005-8-23 19:42:00
|
显示全部楼层
Re:关于RECT结构的一点疑问!
所有代码,包含ddraw.lib即可!
帮我看看!
//8-bit clipping demo
//set tabsize with 3 can make code look well
#define WIN32_LEAN_AND_MEAN //just day no to MFC
#define INITGUID //make sure directX guids are included
#include <windows.h> //include important windows stuff
#include <windowsx.h>
#include <mmsystem.h>
#include <iostream.h> //include important C/C++ stuff
#include <conio.h>
#include <stdlib.h>
#include <malloc.h>
#include <memory.h>
#include <string.h>
#include <stdarg.h>
#include <stdio.h>
#include <math.h>
#include <io.h>
#include <fcntl.h>
#include <ddraw.h> //include directdraw
#define WINDOW_CLASS_NAME "WINCLASS1" //defines for windows
//default screen size
#define SCREEN_WIDTH 640 //size of screen
#define SCREEN_HEIGHT 480 //size of screen
//#define SCREEN_WIDTH 800 //size of screen
//#define SCREEN_HEIGHT 600 //size of screen
//#define SCREEN_WIDTH 1024 //size of screen
//#define SCREEN_HEIGHT 768 //size of screen
#define SCREEN_BPP 8 //bits per pixel
#define MAX_COLORS_PALETTE 256 //maximum colors in 256 color palette
//basic unsigned types
typedef unsigned short USHORT;
typedef unsigned short WORD;
typedef unsigned char UCHAR;
typedef unsigned char BYTE;
#define KEYDOWN(vk_code) ((GetAsyncKeyState(vk_code) & 0x8000) ? 1: 0)
#define KEYUP(vk_code) ((GetAsyncKeyState(vk_code) & 0x8000) ? 0: 1)
//this builds a 16 bit color value in 5.5.5 format (1-bit alpha mode)
#define _RGB16BIT555(r,g,b) ((b & 31) + ((g & 31) << 5) + ((r & 31) << 10))
//this builds a 16 bit color value in 5.6.5 format (green dominate mode)
#define _RGB16BIT565(r,g,b) ((b & 31) + ((g & 63) << 5) + ((r & 31) << 11))
//this builds a 32 bit color value in A.8.8.8 format (8-bit alpha mode)
#define _RGB32BIT(a,r,g,b) ((b) + ((g) << 8) + ((r) << 16) + ((a) << 24))
//initializes a direct draw struct
#define DDRAW_INIT_STRUCT(ddstruct) {memset(&ddstruct, 0, sizeof(ddstruct)); ddstruct.dwSize = sizeof(ddstruct);}
HWND main_window_handle = NULL; //global track main window
int window_closed = 0; //tracks if window is closed
//directdraw stuff
LPDIRECTDRAW7 lpdd = NULL; //dd object
LPDIRECTDRAWSURFACE7 lpddsprimary = NULL; //dd primary surface
LPDIRECTDRAWSURFACE7 lpddsback = NULL; //dd back surface
LPDIRECTDRAWPALETTE lpddpal = NULL; //a pointer to the created dd palette
LPDIRECTDRAWCLIPPER lpddclipper = NULL; //dd clipper
PALETTEENTRY palette[256]; //color palette
DDSURFACEDESC2 ddsd; //a directdraw surface capabilities struct
LPDIRECTDRAWCLIPPER DDraw_Attach_Clipper(LPDIRECTDRAWSURFACE7 lpdds,
int num_rects,
LPRECT clip_list);
//////////////////////////////////////////////////////////////////////////////
// this is the main message handler of the system
//////////////////////////////////////////////////////////////////////////////
LRESULT CALLBACK WindowProc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
{
PAINTSTRUCT ps; //used in WM_PAINT
HDC hdc; //handle to a device context
switch(msg){ //what is the message
case WM_CREATE:
//do initialization stuff here
return 0; //return success
case WM_PAINT:
hdc = BeginPaint(hwnd, &ps); //simply validate the window
EndPaint(hwnd, &ps); //end painting
return 0;
case WM_DESTROY:
PostQuitMessage(0);
return 0;
default:
break;
}
//process any messages that we didn't take care of
return DefWindowProc(hwnd, msg, wparam, lparam);
}
//////////////////////////////////////////////////////////////////////////////
//this function creates a clipper from the sent clip list and attaches it
//to the sent surface.
//////////////////////////////////////////////////////////////////////////////
LPDIRECTDRAWCLIPPER DDraw_Attach_Clipper(LPDIRECTDRAWSURFACE7 lpdds,
int num_rects,
LPRECT clip_list)
{
int i; //looping var
LPDIRECTDRAWCLIPPER lpddclipper; //pointer to the newly created dd clipper
LPRGNDATA region_data; //pointer to the region data that contains the
//header and clip list
//first create the directdraw clipper
if(FAILED(lpdd->CreateClipper(0, &lpddclipper, NULL)))
return NULL;
//now create the clip list from the sent data
//first allocate memory for region data
region_data = (LPRGNDATA)malloc(sizeof(RGNDATAHEADER) + num_rects * sizeof(RECT));
//now copy the rects into region data
memcpy(region_data->Buffer, clip_list, sizeof(RECT) * num_rects);
//set up fields of header
region_data->rdh.dwSize = sizeof(RGNDATAHEADER);
region_data->rdh.iType = RDH_RECTANGLES;
region_data->rdh.nCount = num_rects;
region_data->rdh.nRgnSize = num_rects * sizeof(RECT);
region_data->rdh.rcBound.left = 64000;
region_data->rdh.rcBound.top = 64000;
region_data->rdh.rcBound.right = -64000;
region_data->rdh.rcBound.bottom = -64000;
//region_data->rdh.rcBound.left = -64000;
//region_data->rdh.rcBound.top = -64000;
//region_data->rdh.rcBound.right = 64000;
//region_data->rdh.rcBound.bottom = 64000;
//region_data->rdh.rcBound.left = 64;
//region_data->rdh.rcBound.top = 64;
//region_data->rdh.rcBound.right = -64;
//region_data->rdh.rcBound.bottom = -64;
//region_data->rdh.rcBound.left = -64;
//region_data->rdh.rcBound.top = -64;
//region_data->rdh.rcBound.right = 64;
//region_data->rdh.rcBound.bottom = 64;
//find bounds of all clipping regions
for(i = 0; i < num_rects; i++){
//test if the next rectangle unioned with the current bound is larger
if(clip_list.left < region_data->rdh.rcBound.left)
region_data->rdh.rcBound.left = clip_list.left;
if(clip_list.right < region_data->rdh.rcBound.right)
region_data->rdh.rcBound.right = clip_list.right;
if(clip_list.top < region_data->rdh.rcBound.top)
region_data->rdh.rcBound.top = clip_list.top;
if(clip_list.bottom < region_data->rdh.rcBound.bottom)
region_data->rdh.rcBound.bottom = clip_list.bottom;
}
FILE *fp;
fp = fopen("test.txt", "w");
fprintf(fp, "left = %d, top = %d, right = %d, bottom = %d\n",
region_data->rdh.rcBound.left, region_data->rdh.rcBound.top,
region_data->rdh.rcBound.right, region_data->rdh.rcBound.bottom);
fclose(fp);
//now we have computed the bounding rectangle region and set up the data
//now let's set the clipping list
if(FAILED(lpddclipper->SetClipList(region_data, 0))){
//release memory and return error
free(region_data);
return NULL;
}
//now attach the clipper to the surface
if(FAILED(lpdds->SetClipper(lpddclipper))){
//release memory and return error
free(region_data);
return NULL;
}
//all is well, so release memory and send back the pointer to the new clipper
free(region_data);
return lpddclipper;
}
//////////////////////////////////////////////////////////////////////////////
//this is called once after the initial window is created and
//before the main event loop is entered, do all your initialization here.
//////////////////////////////////////////////////////////////////////////////
int Game_Init(void *parms = NULL, int num_parms = 0)
{
//create IDirectDraw interface 7.0 object and test for error
if(FAILED(DirectDrawCreateEx(NULL, (void **)&lpdd, IID_IDirectDraw7, NULL)))
return 0;
//set cooperation to full screen
if(FAILED(lpdd->SetCooperativeLevel(main_window_handle,
DDSCL_FULLSCREEN | DDSCL_ALLOWMODEX | DDSCL_EXCLUSIVE | DDSCL_ALLOWREBOOT)))
return 0;
//set display mode
if(FAILED(lpdd->SetDisplayMode(SCREEN_WIDTH, SCREEN_HEIGHT, SCREEN_BPP, 0, 0)))
return 0;
//clear ddsd and set size
DDRAW_INIT_STRUCT(ddsd);
ddsd.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT; //enable valid fields
//set the backbuffer count field to 1, use 2 for triple buffering
ddsd.dwBackBufferCount = 1;
//request a complte, flippable
ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP;
//create the primary surface
if(FAILED(lpdd->CreateSurface(&ddsd, &lpddsprimary, NULL)))
return 0;
//this line if needed by the call
ddsd.ddsCaps.dwCaps = DDSCAPS_BACKBUFFER;
//get the attached back buffer surface
if(FAILED(lpddsprimary->GetAttachedSurface(&ddsd.ddsCaps, &lpddsback)))
return 0;
//clear all entries defensive programming
memset(palette, 0, MAX_COLORS_PALETTE * sizeof(PALETTEENTRY));
//create a R,G,B,GR gradient palette
for(int i = 0; i < MAX_COLORS_PALETTE; i++){
//set each entry
if(i < 64)
palette.peRed = i * 4;
else if(i >= 64 && i < 128)
palette.peGreen = (i-64) * 4;
else if(i >= 128 && i < 192)
palette.peBlue = (i-128) * 4;
else if(i >= 192 && i < 256)
palette.peRed = palette.peGreen = palette.peBlue = (i-192) * 4;
//set flag to force directdraw to leave alone
palette.peFlags = PC_NOCOLLAPSE;
}
if(FAILED(lpdd->CreatePalette(DDPCAPS_8BIT | DDPCAPS_ALLOW256 | DDPCAPS_INITIALIZE,
palette, &lpddpal, NULL)))
return 0;
if(FAILED(lpddsprimary->SetPalette(lpddpal)))
return 0;
//Draw a color gradient in back buffer
DDRAW_INIT_STRUCT(ddsd);
//lock the back buffer
if(FAILED(lpddsback->Lock(NULL, &ddsd, DDLOCK_SURFACEMEMORYPTR | DDLOCK_WAIT, NULL)))
return 0;
//get alias to start of surface memory for fast addressing
USHORT *video_buffer = (USHORT *)ddsd.lpSurface;
//draw the gradient
for(int y = 0; y < SCREEN_HEIGHT; y++){
//fill next line with color
memset((void*)video_buffer, y%256, SCREEN_WIDTH);
//advance pointer
video_buffer += ddsd.lPitch;
}
//unlock the back buffer
if(FAILED(lpddsback->Unlock(NULL)))
return 0;
//now create and attach clipper
RECT rect_list[3] = {{10, 10, 50, 50}, {100, 100, 200, 200}, {300, 300, 500, 450}};
if(FAILED(lpddclipper = DDraw_Attach_Clipper(lpddsprimary, 3, rect_list)))
return 0;
return 1; //return success or failure or your own return code here
}
//////////////////////////////////////////////////////////////////////////////
//this is the main loop of the game, do all your processing here
//////////////////////////////////////////////////////////////////////////////
int Game_Main(void *parm = NULL, int num_parms = 0)
{
RECT source_rect; //used to hold the source RECT
RECT dest_rect; //used to hold the destination RECT
if(window_closed) //make sure this isn't executed again
return 0;
//for now test if user is hitting ESC and send WM_CLOSE
if(KEYDOWN(VK_ESCAPE)){
PostMessage(main_window_handle, WM_CLOSE, 0, 0);
window_closed = 1;
}
//get a random rectangle for source
int x1 = rand() % SCREEN_WIDTH;
int y1 = rand() % SCREEN_HEIGHT;
int x2 = rand() % SCREEN_WIDTH;
int y2 = rand() % SCREEN_HEIGHT;
//get a random rectangle for destination
int x3 = rand() % SCREEN_WIDTH;
int y3 = rand() % SCREEN_HEIGHT;
int x4 = rand() % SCREEN_WIDTH;
int y4 = rand() % SCREEN_HEIGHT;
//now set up the RECT structure to fill the region from
//(x1, y1) to (x2, y2) on the source surface
source_rect.left = x1;
source_rect.top = y1;
source_rect.right = x2;
source_rect.bottom = y2;
//now set up the RECT structure to fill the region from
//(x3, y3) to (x4, y4) on the destination surface
dest_rect.left = x3;
dest_rect.top = y3;
dest_rect.right = x4;
dest_rect.bottom = y4;
//make the blitter call
if(FAILED(lpddsprimary->Blt(&dest_rect, //pointer to dest RECT
lpddsback, //pointer to source surface
&source_rect, //pointer to source RECT
DDBLT_WAIT, //control flags
NULL))) //pointer to DDBLTFX holding info
return 0;
//return success or failure or your own return code here
return 1;
}
//////////////////////////////////////////////////////////////////////////////
//this is called after the game is exited and the main event
//loop while is exited, do all you cleanup and shutdown here
//////////////////////////////////////////////////////////////////////////////
void Game_Shutdown(void *parm = NULL, int num_parms = 0)
{
if(lpddpal){ //first the palette
lpddpal->Release();
lpddpal = NULL;
}
if(lpddsback){ //now the back buffer surface
lpddsback->Release();
lpddsback = NULL;
}
if(lpddsprimary){ //now the primary surface
lpddsprimary->Release();
lpddsprimary = NULL;
}
if(lpdd){ //now blow away the IDirectDraw4 interface
lpdd->Release();
lpdd = NULL;
}
}
//////////////////////////////////////////////////////////////////////////////
// WINMAIN
//////////////////////////////////////////////////////////////////////////////
int WINAPI WinMain(HINSTANCE hinstance, HINSTANCE hprevinstance,
LPSTR lpcmdline, int ncmdshow)
{
WNDCLASSEX winclass; //this will hold the class we create
HWND hwnd; //generic window handle
MSG msg; //generic message
//first fill in the window class structure
winclass.cbSize = sizeof(WNDCLASSEX);
winclass.style = CS_DBLCLKS | CS_OWNDC | CS_HREDRAW | CS_VREDRAW;
winclass.lpfnWndProc = WindowProc;
winclass.cbClsExtra = 0;
winclass.cbWndExtra = 0;
winclass.hInstance = hinstance;
winclass.hIcon = LoadIcon(NULL, IDI_APPLICATION);
winclass.hCursor = LoadCursor(NULL, IDC_ARROW);
winclass.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH);
winclass.lpszMenuName = NULL;
winclass.lpszClassName = WINDOW_CLASS_NAME;
winclass.hIconSm = LoadIcon(NULL, IDI_APPLICATION);
if(!RegisterClassEx(&winclass)) //register the windowc class
return 0;
if(!(hwnd = CreateWindowEx(NULL, //extended style
WINDOW_CLASS_NAME, //class
"DirectDraw Clipping Demo", //title
WS_POPUP | WS_VISIBLE,
0, 0, //initial x, y
SCREEN_WIDTH, SCREEN_HEIGHT, //initial width, height
NULL, //handle to parent
NULL, //handle to menu
hinstance, //instance of this application
NULL))) //extra creation parms
return 0;
main_window_handle = hwnd; //save main window handle
if(!Game_Init()) //initialize game here
return 0;
while(TRUE){ //enter main event loop
//test if there is a message in queue, if so get it
if(PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)){
if(msg.message == WM_QUIT) //test if this is a quit
break;
TranslateMessage(&msg); //translate any accelerator keys
DispatchMessage(&msg); //send the message to the window proc
}
Game_Main(); //main game processing goes here
}
Game_Shutdown(); //closedown game here
return msg.wParam; //return to windows like this
}
|
|