⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 display_window_win32.cpp

📁 这是一款2d游戏引擎
💻 CPP
📖 第 1 页 / 共 2 页
字号:
		NULL,
		NULL,
		CL_System_Win32::hInstance,
		NULL);

	window_map[hwnd] = this; // register window in "hwnd to window" hash table

	cl_assert(hwnd != NULL);

	if (desc.is_fullscreen())
	{
		// Make always on top
		SetWindowPos(hwnd, HWND_TOPMOST, 0, 0, width, height, 0); 
	}

	ShowWindow(hwnd, SW_SHOW);
	UpdateWindow(hwnd);

	// Connect input context to new window:

	input_context.clear();
	input_context.add_keyboard(keyboard);
	input_context.add_mouse(mouse);

	// Go looking for joysticks:
	if (directinput)
	{
		HRESULT result = directinput->EnumDevices(
			DI8DEVCLASS_GAMECTRL,
			&CL_DisplayWindow_Win32::enum_devices_callback,
			this,
			DIEDFL_ATTACHEDONLY);
		if (FAILED(result))
		{
			CL_Log::log("debug", "Unable to enumerate direct input devices");
		}
	}
}

BOOL CL_DisplayWindow_Win32::enum_devices_callback(LPCDIDEVICEINSTANCE lpddi, LPVOID pvRef)
{
	CL_DisplayWindow_Win32 *self = (CL_DisplayWindow_Win32 *) pvRef;
	try
	{
		CL_InputDevice device(new CL_InputDevice_DirectInput(self, lpddi));
		self->input_context.add_joystick(device);
	}
	catch (CL_Error error)
	{
		CL_Log::log("debug", "Could not setup game controller: %1", error.message);
	}
	return TRUE;
}

void CL_DisplayWindow_Win32::destroy_window()
{
	if (hwnd == NULL) return;

	fullscreen = false;
	layered = false;

	input_context.clear();

	BOOL res = DestroyWindow(hwnd);
	cl_assert(res == TRUE);
	hwnd = NULL;
}

void CL_DisplayWindow_Win32::show_system_cursor()
{
	ShowCursor(TRUE);
}

void CL_DisplayWindow_Win32::hide_system_cursor()
{
	ShowCursor(FALSE);
}

/////////////////////////////////////////////////////////////////////////////
// CL_DisplayWindow_Win32 implementation:

LONG WINAPI CL_DisplayWindow_Win32::message_handler(
	HWND hWnd,
	UINT uMsg,
	WPARAM wParam,
	LPARAM lParam)
{
	// Lookup window and call its event handler:
 	std::map<HWND, CL_DisplayWindow_Win32 *>::iterator it = window_map.find(hWnd);
	if (it != window_map.end())
	{
		bool handled = it->second->received_event(uMsg, wParam, lParam);
		if (handled) return TRUE;
	}

	// Do default window processing if our event handler didnt handle it:
	return DefWindowProc(hWnd, uMsg, wParam, lParam);
}

bool CL_DisplayWindow_Win32::received_event(UINT uMsg, WPARAM wParam, LPARAM lParam)
{
	switch (uMsg)
	{
	case WM_KEYDOWN:
	case WM_SYSKEYDOWN:
	case WM_KEYUP:
	case WM_SYSKEYUP:
		received_keyboard_input(uMsg, wParam, lParam);
		return true;

	case WM_LBUTTONDOWN:
	case WM_LBUTTONUP:
	case WM_LBUTTONDBLCLK:
	case WM_RBUTTONDOWN:
	case WM_RBUTTONUP:
	case WM_RBUTTONDBLCLK:
	case WM_MBUTTONDOWN:
	case WM_MBUTTONUP:
	case WM_MBUTTONDBLCLK:
	case WM_MOUSEWHEEL:
	case WM_XBUTTONDOWN:
	case WM_XBUTTONUP:
	case WM_XBUTTONDBLCLK:
		received_mouse_input(uMsg, wParam, lParam);
		return true;

	case WM_MOUSEMOVE:
		received_mouse_move(uMsg, wParam, lParam);
		return true;

	case WM_SIZE:
		sig_resize(LOWORD(lParam), HIWORD(lParam));
		return true;

	case WM_CLOSE:
		sig_window_close();
		return true;

	case WM_PAINT:
		{
//			HDC hdc = (HDC) wParam;
			RECT rect;
			if (GetUpdateRect(hwnd, &rect, FALSE))
			{
				PAINTSTRUCT paint;
				BeginPaint(hwnd, &paint);

				CL_Rect cl_rect;
				cl_rect.left = rect.left;
				cl_rect.top = rect.top;
				cl_rect.right = rect.right;
				cl_rect.bottom = rect.bottom;

				sig_paint(cl_rect);

				EndPaint(hwnd, &paint);
			}
			else
			{
				CL_Rect cl_rect(0, 0, get_width(), get_height());
				sig_paint(cl_rect);
			}
		}
		return true;

	case WM_DESTROY:
		window_map.erase(window_map.find(hwnd));
		return true;

	case WM_SYSCOMMAND:
		// Do not allow screensaver to start.
		if (wParam == SC_SCREENSAVE) return true;
		break;
	}

	return false;
}

void CL_DisplayWindow_Win32::set_videomode(int width, int height, int bpp, int refresh_rate)
{
	DEVMODE devmode;
	memset(&devmode, 0, sizeof(DEVMODE));

	// Default to 16 bit BPP:
	if (bpp == 0) bpp = 16;
	
	int index = 0;

	// User wants a specific refresh-rate:
	if (refresh_rate != 0)
	{
		while (true)
		{
			DEVMODE cur_devmode;
			memset(&cur_devmode, 0, sizeof(DEVMODE));
			cur_devmode.dmSize = sizeof(DEVMODE);
			if (EnumDisplaySettings(0, index++, &cur_devmode) == 0) break;

			if (
				cur_devmode.dmPelsWidth == width &&
				cur_devmode.dmPelsHeight == height &&
				cur_devmode.dmBitsPerPel == bpp &&
				cur_devmode.dmDisplayFrequency == refresh_rate)
			{
				devmode = cur_devmode;
			}
		}
	}
	
	// If specific mode not found, try to find the highest possible refresh-rate mode:
	if (devmode.dmFields == 0)
	{
		while (true)
		{
			DEVMODE cur_devmode;
			memset(&cur_devmode, 0, sizeof(DEVMODE));
			cur_devmode.dmSize = sizeof(DEVMODE);
			if (EnumDisplaySettings(0, index++, &cur_devmode) == 0) break;
			
			if (
				cur_devmode.dmPelsWidth == width &&
				cur_devmode.dmPelsHeight == height &&
				cur_devmode.dmBitsPerPel == bpp &&
				cur_devmode.dmDisplayFrequency > devmode.dmDisplayFrequency)
			{
				devmode = cur_devmode;
			}
		}
	}

	// If the mode wasnt found, try anyway but without refresh mode info:
	if (devmode.dmFields == 0)
	{
		devmode.dmSize = sizeof(DEVMODE);
		devmode.dmPelsWidth = width;
		devmode.dmPelsHeight = height;
		devmode.dmBitsPerPel = bpp;
		devmode.dmFields = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT;
	}

	LONG err = ChangeDisplaySettings(&devmode, CDS_FULLSCREEN);

	if (err != DISP_CHANGE_SUCCESSFUL)
	{
		switch (err)
		{
		case DISP_CHANGE_RESTART:
			throw CL_Error("This OS sucks! It wants you to restart your computer to change to fullscreen!!!");

		case DISP_CHANGE_FAILED:
			throw CL_Error("The display driver failed the specified graphics mode.");

		case DISP_CHANGE_BADMODE:
			throw CL_Error("The graphics mode is not supported.");

		default:
			throw CL_Error(CL_String::format("Could not change videomode, error %1", (int)err));
		}
	}
}

void CL_DisplayWindow_Win32::restore_videomode()
{
	ChangeDisplaySettings(NULL, 0);
}

void CL_DisplayWindow_Win32::received_keyboard_input(UINT uMsg, WPARAM wParam, LPARAM lParam)
{
	// Keep get_keycode() up-to-date.
	GetKeyboardState(keys_down);

	// Is message a down or up event?
	bool keydown;
	switch (uMsg)
	{
		case WM_KEYDOWN:
		case WM_SYSKEYDOWN:
			keydown = true;
			break;
		
		case WM_KEYUP:
		case WM_SYSKEYUP:
			keydown = false;
			break;

		default:
			return;
	}

//	int scancode = (lParam & 0xff0000) >> 16;
//	bool extended_key = (lParam & 0x1000000) != 0;

	// Update the ctrl/alt/shift hints:
	int key_id = wParam;

	// Ah fuckit. This platform appearently cant properly tell left from right unless you're
	// polling. -- mbn 6. august 2002.
	switch (key_id)
	{
	case VK_CONTROL: left_ctrl_down = keydown; right_ctrl_down = keydown; break;
	case VK_MENU: left_alt_down = keydown; right_alt_down = keydown; break;
	case VK_SHIFT: left_shift_down = keydown; right_shift_down = keydown; break;
	}

	// Prepare event to be emitted:
	CL_InputEvent key;
	key.type = CL_InputEvent::released;
	if (keydown) key.type = CL_InputEvent::pressed;
	key.mouse_pos = mouse_pos;
	key.id = key_id;
	key.device = keyboard;
	key.repeat_count = lParam & 0xFF;
	key.left_alt = left_alt_down;
	key.right_alt = right_alt_down;
	key.left_ctrl = left_ctrl_down;
	key.right_ctrl = right_ctrl_down;
	key.left_shift = left_shift_down;
	key.right_shift = right_shift_down;

	// Figure out what character sequence this maps to:
	char buf[4];
	int result = ToAscii(
		(UINT) key_id,
		MapVirtualKey((UINT) key_id, 0),
		keys_down,
		(LPWORD) buf,
		0);
	if (result == 1 || result == 2) key.str = std::string(buf, result);

	// Emit message:
	CL_InputDevice keyboard = get_ic()->get_keyboard();
	if (keydown)
		keyboard.sig_key_down()(key);
	else
		keyboard.sig_key_up()(key);
}

void CL_DisplayWindow_Win32::received_mouse_input(UINT uMsg, WPARAM wParam, LPARAM lParam)
{
	// Map windows events to something more interesting:
	int id;
	bool up = false;
	bool down = false;
	bool dblclk = false;

	switch (uMsg)
	{
	case WM_LBUTTONDOWN: id = 0; down = true; break;
	case WM_LBUTTONUP: id = 0; up = true; break;
	case WM_LBUTTONDBLCLK: id = 0; dblclk = true; break;
	case WM_RBUTTONDOWN: id = 1; down = true; break;
	case WM_RBUTTONUP: id = 1; up = true; break;
	case WM_RBUTTONDBLCLK: id = 1; dblclk = true; break;
	case WM_MBUTTONDOWN: id = 2; down = true; break;
	case WM_MBUTTONUP: id = 2; up = true; break;
	case WM_MBUTTONDBLCLK: id = 2; dblclk = true; break;
	case WM_MOUSEWHEEL: id = ((short)HIWORD(wParam) > 0) ? 3 : 4; up = true; down = true; break;
	case WM_XBUTTONDOWN: id = 4 + HIWORD(wParam); down = true; break;
	case WM_XBUTTONUP: id = 4 + HIWORD(wParam); up = true; break;
	case WM_XBUTTONDBLCLK: id = 4 + HIWORD(wParam); dblclk = true; break;
	default:
		return;
	}

	// Prepare event to be emitted:
	CL_InputEvent key;
	key.mouse_pos = mouse_pos;
	key.id = id;
	key.device = mouse;
	key.left_alt = left_alt_down;
	key.right_alt = right_alt_down;
	key.left_ctrl = left_ctrl_down;
	key.right_ctrl = right_ctrl_down;
	key.left_shift = left_shift_down;
	key.right_shift = right_shift_down;

	CL_InputDevice mouse = get_ic()->get_mouse();

	// Emit message:
	if (down)
	{
		key.type = CL_InputEvent::pressed;
		mouse.sig_key_down()(key);
	}
	if (dblclk) 
	{
		key.type = CL_InputEvent::double_clicked;
		mouse.sig_key_dblclk()(key);
	}
	if (up)
	{
		key.type = CL_InputEvent::released;
		mouse.sig_key_up()(key);
	}
}

void CL_DisplayWindow_Win32::received_mouse_move(UINT uMsg, WPARAM wParam, LPARAM lParam)
{
	// Fetch coordinates
	int x = LOWORD(lParam);
	int y = HIWORD(lParam);

	if(mouse_pos.x != x || mouse_pos.y != y)
	{
		mouse_pos.x = x;
		mouse_pos.y = y;

		// Prepare event to be emitted:
		CL_InputEvent key;
		key.type = CL_InputEvent::moved;
		key.device = mouse;
		key.left_alt = left_alt_down;
		key.right_alt = right_alt_down;
		key.left_ctrl = left_ctrl_down;
		key.right_ctrl = right_ctrl_down;
		key.left_shift = left_shift_down;
		key.right_shift = right_shift_down;
		key.mouse_pos = mouse_pos;

		// Fire off signal
		CL_InputDevice mouse = get_ic()->get_mouse();
		mouse.sig_move()(key);
	}
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -