在normal窗口剪切线段

在这里有一个重要的获取坐标的区别GetClientRect(main_hwnd, &client)是获取显示客户端坐标,这个是相对坐标;
GetWindowRect(main_hwnd, &client)是获取相对于window窗口的坐标;
以下是1920*1080下的实现:

#include <Windows.h>
#include <ddraw.h>

#pragma comment(lib, "ddraw.lib")
#pragma comment(lib, "dxguid.lib")

#define WINDOW_WIDTH		640
#define WINDOW_HEIGHT		480
#define SCREEN_BPP			32
#define SCREEN_WIDTH		1920
#define SCREEN_HEIGHT		1080
#define KEY_DOWN(vk_code)	(GetAsyncKeyState(vk_code) & 0x8000 ? 1 : 0)
#define KEY_UP(vk_code)		(GetAsyncKeyState(vk_code) & 0x8000 ? 0 : 1)

#define CLIP_CODE_C		0x0000
#define CLIP_CODE_N		0x0008
#define CLIP_CODE_S		0x0004
#define CLIP_CODE_E		0x0002
#define CLIP_CODE_W		0x0001

#define CLIP_CODE_NE	0x000a
#define CLIP_CODE_SE	0x0006
#define CLIP_CODE_NW	0x0009
#define CLIP_CODE_SW	0x0005

HWND main_hwnd = nullptr;
RECT client;
LPDIRECTDRAW7 lpdd7 = nullptr;
LPDIRECTDRAWSURFACE7 lpddsprimary = nullptr;
LPDIRECTDRAWCLIPPER lpddclipper = nullptr;
DDSURFACEDESC2 ddsd;
int pixel;
int window_close = 0;

int Game_Init(void* params = nullptr, int num_params = 0);
int Game_Main(void* params = nullptr, int num_params = 0);
int Game_Shutdown(void* params = nullptr, int num_params = 0);
int Draw_Line(int x1, int y1, int x2, int y2, LONG color, LONG* vb_start, int iPitch);
int Clip_Line(int& x1, int& y1, int& x2, int& y2, int min_clip_x, int min_clip_y, int max_clip_x, int max_clip_y);
int GetInterSectionPoint(int p_code, int& xc, int& yc, int x1, int y1, int x2, int y2, int min_clip_x, int min_clip_y, int max_clip_x, int max_clip_y);

LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam);

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, int iCmdShow)
{
	TCHAR szAppName[] = TEXT("normal window");
	MSG msg;
	WNDCLASS wndclass;


	wndclass.style = CS_VREDRAW | CS_HREDRAW;
	wndclass.lpfnWndProc = WndProc;
	wndclass.cbClsExtra = 0;
	wndclass.cbWndExtra = 0;
	wndclass.hInstance = hInstance;
	wndclass.hIcon = LoadIcon(nullptr, IDI_APPLICATION);
	wndclass.hCursor = LoadCursor(nullptr, IDC_ARROW);
	wndclass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
	wndclass.lpszMenuName = nullptr;
	wndclass.lpszClassName = szAppName;

	if (!RegisterClass(&wndclass))
	{
		MessageBox(nullptr, TEXT("Register Class Failed"), szAppName, MB_ICONERROR);
		return 0;
	}

	client = {0, 0, WINDOW_WIDTH-1, WINDOW_HEIGHT-1};
	AdjustWindowRect(&client, WS_OVERLAPPEDWINDOW, false);

	main_hwnd = CreateWindow(
		szAppName, TEXT("normal_window"), WS_OVERLAPPEDWINDOW | WS_VISIBLE,
		CW_USEDEFAULT, CW_USEDEFAULT, client.right - client.left, client.bottom - client.top,
		nullptr, nullptr, hInstance, nullptr
	);

	Game_Init();

	while (true)
	{
		if (PeekMessage(&msg, nullptr, 0, 0, PM_REMOVE))
		{
			if (msg.message == WM_QUIT)
				break;
			TranslateMessage(&msg);
			DispatchMessage(&msg);
		}
		Game_Main();
	}

	Game_Shutdown();

	return msg.wParam;
}

LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
	HDC hdc;
	PAINTSTRUCT ps;
	int xPos;
	int yPos;


	switch (message)
	{
	case WM_CREATE:
		//create
		//GetClientRect(main_hwnd, &client);
		GetWindowRect(main_hwnd, &client);
		return 0;
	case WM_SIZE:
		//change size
		//GetClientRect(main_hwnd, &client);
		GetWindowRect(main_hwnd, &client);
		return 0;
	case WM_MOVE:
		//move
		//GetClientRect(main_hwnd, &client);
		GetWindowRect(main_hwnd, &client);
		return 0;
	case WM_LBUTTONDOWN:
		xPos = LOWORD(lParam);
		yPos = HIWORD(lParam);
		return 0;

	case WM_PAINT:
		hdc = BeginPaint(hwnd, &ps);
		//draw
		EndPaint(hwnd, &ps);
		return 0;
	case WM_DESTROY:
		window_close = 1;
		PostQuitMessage(0);
		return 0;
	}
	return DefWindowProc(hwnd, message, wParam, lParam);
}

int Game_Init(void* params, int num_params)
{
	if (FAILED(DirectDrawCreateEx(nullptr, (LPVOID*)&lpdd7, IID_IDirectDraw7, nullptr)))
		return 0;

	lpdd7->SetCooperativeLevel(main_hwnd, DDSCL_NORMAL);

	memset(&ddsd, 0, sizeof(ddsd));
	ddsd.dwSize = sizeof(ddsd);
	ddsd.dwFlags = DDSD_CAPS;

	ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
	if (FAILED(lpdd7->CreateSurface(&ddsd, &lpddsprimary, nullptr)))
		return 0;

	//获取像素格式
	DDPIXELFORMAT ddpixelformat;
	memset(&ddpixelformat, 0, sizeof(ddpixelformat));
	ddpixelformat.dwSize = sizeof(ddpixelformat);
	lpddsprimary->GetPixelFormat(&ddpixelformat);
	pixel = ddpixelformat.dwRGBBitCount;

	if (FAILED(lpdd7->CreateClipper(0, &lpddclipper, nullptr)))
		return 0;

	if (FAILED(lpddclipper->SetHWnd(0, main_hwnd)))
		return 0;

	if (FAILED(lpddsprimary->SetClipper(lpddclipper)))
		return 0;

	return 1;
}

int Game_Main(void* params, int num_params)
{
	if (KEY_DOWN(VK_ESCAPE))
	{
		window_close = 1;
		SendMessage(main_hwnd, WM_CLOSE, 0, 0);
		return 0;
	}

	if (window_close)
		return 0;

	//GetClientRect(main_hwnd, &client);
	GetWindowRect(main_hwnd, &client);

	memset(&ddsd, 0, sizeof(ddsd));
	ddsd.dwSize = sizeof(ddsd);
	if (FAILED(lpddsprimary->Lock(nullptr, &ddsd, DDLOCK_SURFACEMEMORYPTR | DDLOCK_WAIT, nullptr)))
		return 0;

	LONG* video_buffer = (LONG*)ddsd.lpSurface;
	int ipitch = ddsd.lPitch;

	if (pixel == 32)
	{
		/*for (int i = 0; i < 10; i++)
		{
			int x = client.left + rand() % (client.right - client.left);
			int y = client.top + rand() % (client.bottom - client.top);
			video_buffer[x + y * (ipitch >> 2)] = RGB(rand() % 256, rand() % 256, rand() % 256);
		}*/
		int p1_x = 0, p1_y = 0;
		int p2_x = SCREEN_WIDTH - 1, p2_y = SCREEN_HEIGHT - 1;
		int isp1_x = p1_x, isp1_y = p1_y;
		int isp2_x = p2_x, isp2_y = p2_y;
		Clip_Line(isp1_x, isp1_y, isp2_x, isp2_y, client.left, client.top, client.right, client.bottom);
		LONG color = RGB(rand() % 256, rand() % 256, rand() % 256);
		Draw_Line(isp1_x, isp1_y, isp2_x, isp2_y, color, video_buffer, ipitch >> 2);
	}

	if (FAILED(lpddsprimary->Unlock(nullptr)))
		return 0;

	//Sleep(10000);
	return 1;
}

int Game_Shutdown(void* params, int num_params)
{
	if (lpddsprimary)
	{
		lpddsprimary->Release();
		lpddsprimary = nullptr;
	}
	if (lpddclipper)
	{
		lpddclipper->Release();
		lpddclipper = nullptr;
	}
	if (lpdd7)
	{
		lpdd7->Release();
		lpdd7 = nullptr;
	}

	return 1;
}

int Draw_Line(int x1, int y1, int x2, int y2, LONG color, LONG* vb_start, int iPitch)
{
	int dx = x2 - x1;
	int dy = y2 - y1;
	int inx, iny, dx2, dy2, error;

	if (dx >= 0)
		inx = 1;
	else
	{
		inx = -1;
		dx = -dx;
	}
	if (dy >= 0)
		iny = iPitch;
	else
	{
		iny = -iPitch;
		dy = -dy;
	}

	dx2 = dx << 1;
	dy2 = dy << 1;
	vb_start += x1 + y1 * iPitch;

	if (dx > dy)
	{
		error = dy2 - dx;
		for (int i = 0; i <= dx; i++)
		{
			*vb_start = color;
			if (error >= 0)
			{
				error -= dx2;
				vb_start += iny;
			}
			error += dy2;
			vb_start += inx;
		}
	}
	else
	{
		error = dx2 - dy;
		for (int i = 0; i <= dy; i++)
		{
			*vb_start = color;
			if (error >= 0)
			{
				error -= dy2;
				vb_start += inx;
			}
			error += dx2;
			vb_start += iny;
		}
	}
	return 1;
}

int Clip_Line(int& x1, int& y1, int& x2, int& y2, int min_clip_x, int min_clip_y, int max_clip_x, int max_clip_y)
{
	int xc1 = x1, yc1 = y1, xc2 = x2, yc2 = y2;
	int p1_code = 0, p2_code = 0;

	if (y1 < min_clip_y)
		p1_code |= CLIP_CODE_N;
	else if (y1 > max_clip_y)
		p1_code |= CLIP_CODE_S;
	if (x1 < min_clip_x)
		p1_code |= CLIP_CODE_W;
	else if (x1 > max_clip_x)
		p1_code |= CLIP_CODE_E;
	if (y2 < min_clip_y)
		p2_code |= CLIP_CODE_N;
	else if (y2 > max_clip_y)
		p2_code |= CLIP_CODE_S;
	if (x2 < min_clip_x)
		p2_code |= CLIP_CODE_W;
	else if (x2 > max_clip_x)
		p2_code |= CLIP_CODE_E;

	if (p1_code & p2_code)
		return 0;
	if (p1_code == 0 && p2_code == 0)
		return 1;

	GetInterSectionPoint(p1_code, xc1, yc1, x1, y1, x2, y2, min_clip_x, min_clip_y, max_clip_x, max_clip_y);
	GetInterSectionPoint(p2_code, xc2, yc2, x1, y1, x2, y2, min_clip_x, min_clip_y, max_clip_x, max_clip_y);

	x1 = xc1;
	y1 = yc1;
	x2 = xc2;
	y2 = yc2;
}

int GetInterSectionPoint(int p_code, int& xc, int& yc, int x1, int y1, int x2, int y2, int min_clip_x, int min_clip_y, int max_clip_x, int max_clip_y)
{
	switch (p_code)
	{
	case CLIP_CODE_N:
		yc = min_clip_y;
		xc = x1 + (min_clip_y - y1) * (x2 - x1) / (y2 - y1);
		break;
	case CLIP_CODE_S:
		yc = max_clip_y;
		xc = x1 + (max_clip_y - y1) * (x2 - x1) / (y2 - y1);
	case CLIP_CODE_W:
		xc = min_clip_x;
		yc = y1 + (min_clip_x - x1) * (y2 - y1) / (x2 - x1);
		break;
	case CLIP_CODE_E:
		xc = max_clip_x;
		yc = y1 + (max_clip_x - x1) * (y2 - y1) / (x2 - x1);
		break;
	case CLIP_CODE_NW:
		yc = min_clip_y;
		xc = x1 + (min_clip_y - y1) * (x2 - x1) / (y2 - y1);
		if (xc < min_clip_x)
		{
			xc = min_clip_x;
			yc = y1 + (min_clip_x - x1) * (y2 - y1) / (x2 - x1);
		}
		break;
	case CLIP_CODE_SW:
		yc = max_clip_y;
		xc = x1 + (max_clip_y - y1) * (x2 - x1) / (y2 - y1);
		if (xc < min_clip_x)
		{
			xc = min_clip_x;
			yc = y1 + (min_clip_x - x1) * (y2 - y1) / (x2 - x1);
		}
		break;
	case CLIP_CODE_NE:
		yc = min_clip_y;
		xc = x1 + (min_clip_y - y1) * (x2 - x1) / (y2 - y1);
		if (xc > max_clip_x)
		{
			xc = max_clip_x;
			yc = y1 + (max_clip_x - x1) * (y2 - y1) / (x2 - x1);
		}
		break;
	case CLIP_CODE_SE:
		yc = max_clip_y;
		xc = x1 + (max_clip_y - y1) * (x2 - x1) / (y2 - y1);
		if (xc > max_clip_x)
		{
			xc = max_clip_x;
			yc = y1 + (max_clip_x - x1) * (y2 - y1) / (x2 - x1);
		}
		break;
	}
	if (xc < min_clip_x || xc > max_clip_x || yc < min_clip_y || yc > max_clip_y)
		return 0;

	return 1;
}

在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
©️2022 CSDN 皮肤主题:1024 设计师:我叫白小胖 返回首页
评论

打赏作者

明天过后mm

你的鼓励将是我创作的最大动力

¥2 ¥4 ¥6 ¥10 ¥20
输入1-500的整数
余额支付 (余额:-- )
扫码支付
扫码支付:¥2
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、C币套餐、付费专栏及课程。

余额充值