📄 display_window_win32.cpp
字号:
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 + -