📄 display_window_win32.cpp
字号:
/* $Id: display_window_win32.cpp,v 1.59 2003/11/11 14:59:44 sphair Exp $
**
** ClanLib Game SDK
** Copyright (C) 2003 The ClanLib Team
** For a total list of contributers see the file CREDITS.
**
** This library is free software; you can redistribute it and/or
** modify it under the terms of the GNU Lesser General Public
** License as published by the Free Software Foundation; either
** version 2.1 of the License, or (at your option) any later version.
**
** This library is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
** Lesser General Public License for more details.
**
** You should have received a copy of the GNU Lesser General Public
** License along with this library; if not, write to the Free Software
** Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "dinput.h"
#include "Display/display_precomp.h"
#include "display_window_win32.h"
#include "input_device_win32keyboard.h"
#include "input_device_win32mouse.h"
#include "input_device_directinput.h"
#include "Core/System/Win32/init_win32.h"
#include "API/Display/input_event.h"
#include "API/Display/keys.h"
#include "API/Display/display_window_description.h"
#include "API/Core/Math/rect.h"
#include "API/Core/System/error.h"
#include "API/Core/System/clanstring.h"
#include "API/Core/System/log.h"
#ifndef WM_MOUSEWHEEL
#define WM_MOUSEWHEEL 0x020A
#endif
#ifndef WM_XBUTTONDOWN
#define WM_XBUTTONDOWN 0x020B
#define WM_XBUTTONUP 0x020C
#define WM_XBUTTONDBLCLK 0x020D
#endif
#ifndef WS_EX_LAYERED
#define WS_EX_LAYERED 0x00080000
#endif
// My dinput.lib seem to be broken (the one with msvc7).
// It gives me a linker error about DirectInput8Create. Easier to create with cocreateinstance than
// download hundred megabytes. :) -- mbn 5 oct 2003
#define BROKEN_DINPUT
/////////////////////////////////////////////////////////////////////////////
// CL_DisplayWindow_Win32 construction:
CL_DisplayWindow_Win32::CL_DisplayWindow_Win32()
: hwnd(NULL), title("nonamed"), fullscreen(false),
allow_resize(false), layered(false), bpp(0), saved_position(0, 0, 0, 0),
left_ctrl_down(false), left_alt_down(false), left_shift_down(false),
right_ctrl_down(false), right_alt_down(false), right_shift_down(false),
mouse_pos(-1,-1), directinput(0)
{
keyboard = CL_InputDevice(new CL_InputDevice_Win32Keyboard(this));
mouse = CL_InputDevice(new CL_InputDevice_Win32Mouse(this));
memset(keys_down, 0, 256);
#ifndef BROKEN_DINPUT
HRESULT result = DirectInput8Create(GetModuleHandle(0), DIRECTINPUT_VERSION, IID_IDirectInput8, (LPVOID *) &directinput, 0);
if (FAILED(result))
{
CL_Log::log("debug", "Unable to initialize direct input");
}
#else
// My directinput doesnt know this directinput8create function (hmm weird)
// So creating it via CoCreateInstance instead..
HRESULT result = CoInitialize(0);
if (FAILED(result))
{
throw CL_Error("CL_DisplayWindow_Win32: Damn murphy must hate you. CoInitialize failed!");
}
result = CoCreateInstance(CLSID_DirectInput8, 0, CLSCTX_INPROC_SERVER, IID_IDirectInput8A, (LPVOID *) &directinput);
if (FAILED(result))
{
CL_Log::log("debug", "Unable to create direct input");
}
else
{
result = directinput->Initialize(GetModuleHandle(0), DIRECTINPUT_VERSION);
if (FAILED(result))
{
directinput->Release();
directinput = 0;
CL_Log::log("debug", "Unable to initialize direct input");
}
}
#endif
}
CL_DisplayWindow_Win32::~CL_DisplayWindow_Win32()
{
if (hwnd) destroy_window();
#ifndef BROKEN_DINPUT
if (directinput) directinput->Release();
#else
if (directinput) directinput->Release();
CoUninitialize();
#endif
}
/////////////////////////////////////////////////////////////////////////////
// CL_DisplayWindow_Win32 attributes:
std::map<HWND, CL_DisplayWindow_Win32 *> CL_DisplayWindow_Win32::window_map;
int CL_DisplayWindow_Win32::get_width() const
{
if (layered) return layered_position.get_width();
RECT rect;
GetClientRect(hwnd, &rect);
return rect.right - rect.left;
}
int CL_DisplayWindow_Win32::get_height() const
{
if (layered) return layered_position.get_height();
RECT rect;
GetClientRect(hwnd, &rect);
return rect.bottom - rect.top;
}
bool CL_DisplayWindow_Win32::is_fullscreen() const
{
return fullscreen;
}
bool CL_DisplayWindow_Win32::has_focus() const
{
return (GetFocus() == hwnd);
}
static CL_PixelBuffer *buffer_todo = 0; // hack until we implement pixelbuffer
CL_PixelBuffer &CL_DisplayWindow_Win32::get_buffer(int i)
{
return *buffer_todo;
}
const CL_PixelBuffer &CL_DisplayWindow_Win32::get_buffer(int i) const
{
return *buffer_todo;
}
int CL_DisplayWindow_Win32::get_buffer_count() const
{
return 1;
}
bool CL_DisplayWindow_Win32::get_keycode(int keycode) const
{
return false;
}
/////////////////////////////////////////////////////////////////////////////
// CL_DisplayWindow_Win32 operations:
void CL_DisplayWindow_Win32::set_fullscreen(int width, int height, int bpp, int refresh_rate)
{
CL_DisplayWindowDescription desc;
desc.set_title(title);
desc.set_size(CL_Size(width, height));
desc.set_bpp(bpp);
desc.set_refresh_rate(refresh_rate);
desc.set_allow_resize(allow_resize);
desc.set_fullscreen(true);
desc.set_layered(layered);
create_window(desc);
}
void CL_DisplayWindow_Win32::set_windowed()
{
if (!fullscreen) return;
CL_DisplayWindowDescription desc;
desc.set_title(title);
desc.set_allow_resize(allow_resize);
desc.set_layered(layered);
create_window(desc);
}
void CL_DisplayWindow_Win32::set_title(const std::string &_title)
{
title = _title;
SetWindowText(hwnd, title.c_str());
}
void CL_DisplayWindow_Win32::set_position(const CL_Rect &pos)
{
layered_position = pos;
SetWindowPos(hwnd, 0, pos.left, pos.top, pos.get_width(), pos.get_height(), SWP_NOREPOSITION|SWP_NOZORDER);
}
void CL_DisplayWindow_Win32::set_position(int x, int y)
{
CL_Size size = layered_position.get_size();
layered_position = CL_Rect(x, y, x+size.width, y+size.height);
SetWindowPos(hwnd, 0, x, y, 0, 0, SWP_NOREPOSITION|SWP_NOZORDER|SWP_NOSIZE);
}
void CL_DisplayWindow_Win32::set_size(int width, int height)
{
layered_position.set_size(CL_Size(width, height));
SetWindowPos(hwnd, 0, 0, 0, width, height, SWP_NOREPOSITION|SWP_NOZORDER|SWP_NOMOVE);
}
void CL_DisplayWindow_Win32::set_buffer_count(int flipping_buffers)
{
}
void CL_DisplayWindow_Win32::update(const CL_Rect &rect)
{
}
void CL_DisplayWindow_Win32::flip()
{
}
void CL_DisplayWindow_Win32::create_window(const CL_DisplayWindowDescription &desc)
{
if (hwnd)
{
modify_window(desc);
}
else
{
create_new_window(desc);
}
}
void CL_DisplayWindow_Win32::modify_window(const CL_DisplayWindowDescription &desc)
{
if (!fullscreen)
{
RECT rect;
GetWindowRect(hwnd, &rect);
saved_position.left = rect.left;
saved_position.top = rect.top;
saved_position.right = rect.right;
saved_position.bottom = rect.bottom;
}
title = desc.get_title();
fullscreen = desc.is_fullscreen();
layered = desc.is_layered();
layered_position = desc.get_position();
allow_resize = desc.get_allow_resize();
int x = 0;
int y = 0;
int width = desc.get_size().width;
int height = desc.get_size().height;
if (desc.is_fullscreen())
{
width = GetSystemMetrics(SM_CXSCREEN);
height = GetSystemMetrics(SM_CYSCREEN);
}
else
{
int scr_width = GetSystemMetrics(SM_CXSCREEN);
int scr_height = GetSystemMetrics(SM_CYSCREEN);
x = scr_width/2 - width/2;
y = scr_height/2 - height/2;
}
if (width == 0 && height == 0)
{
x = saved_position.left;
y = saved_position.top;
width = saved_position.get_width();
height = saved_position.get_height();
}
int style;
if (desc.is_fullscreen())
{
style = WS_POPUP;
}
else if (allow_resize)
{
style = WS_POPUP | WS_SYSMENU | WS_CAPTION | WS_SIZEBOX | WS_MAXIMIZEBOX | WS_MINIMIZEBOX;
}
else
{
style = WS_POPUPWINDOW | WS_CAPTION | WS_MINIMIZEBOX;
}
int ex_style = 0;
if (desc.is_layered())
{
ex_style = WS_EX_LAYERED;
}
// get size of window with decorations to pass to CreateWindow
RECT window_rect = { x, y, x+width, y+height };
AdjustWindowRect( &window_rect, style, false );
SetWindowLong(hwnd, GWL_STYLE, style);
SetWindowLong(hwnd, GWL_EXSTYLE, ex_style);
if (desc.is_fullscreen())
{
// Make always on top
SetWindowPos(hwnd, HWND_TOPMOST, 0, 0, width, height, SWP_FRAMECHANGED);
}
else
{
// Clear always on top flag; size as requested by description struct.
SetWindowPos(
hwnd,
HWND_TOP,
window_rect.left,
window_rect.top,
window_rect.right-window_rect.left,
window_rect.bottom-window_rect.top,
SWP_FRAMECHANGED);
}
ShowWindow(hwnd, SW_SHOW);
UpdateWindow(hwnd);
}
void CL_DisplayWindow_Win32::create_new_window(const CL_DisplayWindowDescription &desc)
{
title = desc.get_title();
fullscreen = desc.is_fullscreen();
layered = desc.is_layered();
layered_position = desc.get_position();
allow_resize = desc.get_allow_resize();
WNDCLASS wndclass;
wndclass.style = 0;
wndclass.lpfnWndProc = (WNDPROC) CL_DisplayWindow_Win32::message_handler;
wndclass.cbClsExtra = 0;
wndclass.cbWndExtra = 0;
wndclass.hInstance = CL_System_Win32::hInstance;
wndclass.hIcon = NULL;
wndclass.hCursor = LoadCursor (NULL,IDC_ARROW);
wndclass.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
wndclass.lpszMenuName = "ClanApplication";
wndclass.lpszClassName = "ClanApplication";
RegisterClass(&wndclass);
int x = 0;
int y = 0;
int width = desc.get_size().width;
int height = desc.get_size().height;
if (desc.is_fullscreen())
{
width = GetSystemMetrics(SM_CXSCREEN);
height = GetSystemMetrics(SM_CYSCREEN);
}
else
{
int scr_width = GetSystemMetrics(SM_CXSCREEN);
int scr_height = GetSystemMetrics(SM_CYSCREEN);
x = scr_width/2 - width/2;
y = scr_height/2 - height/2;
}
if (width == 0 && height == 0)
{
x = saved_position.left;
y = saved_position.top;
width = saved_position.get_width();
height = saved_position.get_height();
}
int style;
if (desc.is_fullscreen())
{
style = WS_POPUP;
}
else if (allow_resize)
{
style = WS_POPUP | WS_SYSMENU | WS_CAPTION | WS_SIZEBOX | WS_MAXIMIZEBOX | WS_MINIMIZEBOX;
}
else
{
style = WS_POPUPWINDOW | WS_CAPTION | WS_MINIMIZEBOX;
}
int ex_style = 0;
if (desc.is_layered())
{
ex_style = WS_EX_LAYERED;
}
// get size of window with decorations to pass to CreateWindow
RECT window_rect = { x, y, x+width, y+height };
AdjustWindowRect( &window_rect, style, false );
hwnd = CreateWindowEx(
ex_style,
"ClanApplication",
title.c_str(),
style,
window_rect.left,
window_rect.top,
window_rect.right - window_rect.left,
window_rect.bottom - window_rect.top,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -