forked from metin-server/m2dev-client-src
This commit is well documented, so no need to tell you my life story. Full Unicode patch with RTL Support & BiDi logic. Removed the legacy codePage, normalised to UTF8 (65001). It also comes with: CTRL + A : select text (highlighted) CTRL + C : copy CTRL + V : paste CTRL + X : cut CTRL + Y : redo CTRL + Z : undo
263 lines
4.8 KiB
C++
263 lines
4.8 KiB
C++
#include "StdAfx.h"
|
|
#include "MsWindow.h"
|
|
|
|
#include <windowsx.h>
|
|
#include <utf8.h>
|
|
|
|
CMSWindow::TWindowClassSet CMSWindow::ms_stWCSet;
|
|
HINSTANCE CMSWindow::ms_hInstance = NULL;
|
|
|
|
LRESULT CALLBACK MSWindowProcedure(HWND hWnd, UINT uiMsg, WPARAM wParam, LPARAM lParam)
|
|
{
|
|
CMSWindow * pWnd = (CMSWindow *)GetWindowLongPtr(hWnd, GWLP_USERDATA);
|
|
|
|
if (pWnd)
|
|
return pWnd->WindowProcedure(hWnd, uiMsg, wParam, lParam);
|
|
|
|
return DefWindowProc(hWnd, uiMsg, wParam, lParam);
|
|
}
|
|
|
|
LRESULT CMSWindow::WindowProcedure(HWND hWnd, UINT uiMsg, WPARAM wParam, LPARAM lParam)
|
|
{
|
|
switch (uiMsg)
|
|
{
|
|
case WM_SIZE:
|
|
OnSize(wParam, lParam);
|
|
break;
|
|
|
|
case WM_ACTIVATEAPP:
|
|
m_isActive = (wParam == WA_ACTIVE) || (wParam == WA_CLICKACTIVE);
|
|
break;
|
|
}
|
|
|
|
return DefWindowProc(hWnd, uiMsg, wParam, lParam);
|
|
}
|
|
|
|
void CMSWindow::OnSize(WPARAM wParam, LPARAM /*lParam*/)
|
|
{
|
|
if (wParam == SIZE_MINIMIZED)
|
|
{
|
|
InvalidateRect(m_hWnd, NULL, true);
|
|
m_isActive = false;
|
|
m_isVisible = false;
|
|
}
|
|
else
|
|
{
|
|
m_isActive = true;
|
|
m_isVisible = true;
|
|
}
|
|
}
|
|
|
|
void CMSWindow::Destroy()
|
|
{
|
|
if (!m_hWnd)
|
|
return;
|
|
|
|
if (IsWindow(m_hWnd))
|
|
DestroyWindow(m_hWnd);
|
|
|
|
m_hWnd = NULL;
|
|
m_isVisible = false;
|
|
}
|
|
|
|
bool CMSWindow::Create(const char* c_szName, int brush, DWORD cs, DWORD ws, HICON hIcon, int iCursorResource)
|
|
{
|
|
Destroy();
|
|
|
|
const wchar_t* wClassName =
|
|
RegisterWindowClass(cs, brush, MSWindowProcedure, hIcon, iCursorResource);
|
|
|
|
if (!wClassName)
|
|
return false;
|
|
|
|
// Window title is UTF-8 → convert
|
|
std::wstring wWindowName = Utf8ToWide(c_szName ? c_szName : "");
|
|
|
|
m_hWnd = CreateWindowW(
|
|
wClassName, // already wide
|
|
wWindowName.c_str(), // wide
|
|
ws,
|
|
0, 0, 0, 0,
|
|
nullptr,
|
|
nullptr,
|
|
ms_hInstance,
|
|
nullptr
|
|
);
|
|
|
|
if (!m_hWnd)
|
|
return false;
|
|
|
|
SetWindowLongPtrW(m_hWnd, GWLP_USERDATA, (LONG_PTR)this);
|
|
return true;
|
|
}
|
|
|
|
void CMSWindow::SetVisibleMode(bool isVisible)
|
|
{
|
|
m_isVisible = isVisible;
|
|
|
|
if (m_isVisible)
|
|
{
|
|
ShowWindow(m_hWnd, SW_SHOW);
|
|
}
|
|
else
|
|
{
|
|
ShowWindow(m_hWnd, SW_HIDE);
|
|
}
|
|
}
|
|
|
|
void CMSWindow::Show()
|
|
{
|
|
m_isVisible = true;
|
|
ShowWindow(m_hWnd, SW_SHOW);
|
|
}
|
|
|
|
void CMSWindow::Hide()
|
|
{
|
|
m_isVisible = false;
|
|
ShowWindow(m_hWnd, SW_HIDE);
|
|
}
|
|
|
|
bool CMSWindow::IsVisible()
|
|
{
|
|
return m_isVisible;
|
|
}
|
|
|
|
bool CMSWindow::IsActive()
|
|
{
|
|
return m_isActive;
|
|
}
|
|
|
|
HINSTANCE CMSWindow::GetInstance()
|
|
{
|
|
return ms_hInstance;
|
|
}
|
|
|
|
HWND CMSWindow::GetWindowHandle()
|
|
{
|
|
return m_hWnd;
|
|
}
|
|
|
|
int CMSWindow::GetScreenWidth()
|
|
{
|
|
return GetSystemMetrics(SM_CXSCREEN);
|
|
}
|
|
|
|
int CMSWindow::GetScreenHeight()
|
|
{
|
|
return GetSystemMetrics(SM_CYSCREEN);
|
|
}
|
|
|
|
void CMSWindow::GetWindowRect(RECT* prc)
|
|
{
|
|
::GetWindowRect(m_hWnd, prc);
|
|
}
|
|
|
|
|
|
void CMSWindow::GetClientRect(RECT* prc)
|
|
{
|
|
::GetClientRect(m_hWnd, prc);
|
|
}
|
|
|
|
void CMSWindow::GetMousePosition(POINT* ppt)
|
|
{
|
|
GetCursorPos(ppt);
|
|
ScreenToClient(m_hWnd, ppt);
|
|
}
|
|
|
|
void CMSWindow::SetPosition(int x, int y)
|
|
{
|
|
SetWindowPos(m_hWnd, NULL, x, y, 0, 0, SWP_NOZORDER|SWP_NOSIZE);
|
|
}
|
|
|
|
void CMSWindow::SetCenterPosition()
|
|
{
|
|
RECT rc;
|
|
|
|
GetClientRect(&rc);
|
|
|
|
int windowWidth = rc.right - rc.left;
|
|
int windowHeight = rc.bottom - rc.top;
|
|
|
|
SetPosition((GetScreenWidth()-windowWidth)/2, (GetScreenHeight()-windowHeight)/2);
|
|
}
|
|
|
|
void CMSWindow::AdjustSize(int width, int height)
|
|
{
|
|
SetRect(&m_rect, 0, 0, width, height);
|
|
|
|
AdjustWindowRectEx(&m_rect,
|
|
GetWindowStyle(m_hWnd),
|
|
GetMenu(m_hWnd ) != NULL,
|
|
GetWindowExStyle(m_hWnd ) );
|
|
|
|
MoveWindow
|
|
(
|
|
m_hWnd,
|
|
0,
|
|
0,
|
|
m_rect.right - m_rect.left,
|
|
m_rect.bottom - m_rect.top,
|
|
FALSE
|
|
);
|
|
}
|
|
|
|
void CMSWindow::SetText(const char* c_szText)
|
|
{
|
|
if (!m_hWnd)
|
|
return;
|
|
|
|
std::wstring wText = Utf8ToWide(c_szText ? c_szText : "");
|
|
SetWindowTextW(m_hWnd, wText.c_str());
|
|
}
|
|
|
|
void CMSWindow::SetSize(int width, int height)
|
|
{
|
|
SetWindowPos(m_hWnd, NULL, 0, 0, width, height, SWP_NOZORDER|SWP_NOMOVE);
|
|
}
|
|
|
|
const wchar_t* CMSWindow::RegisterWindowClass(DWORD style, int brush, WNDPROC pfnWndProc, HICON hIcon, int iCursorResource)
|
|
{
|
|
wchar_t szClassName[1024];
|
|
swprintf_s(
|
|
szClassName,
|
|
L"eter - s%x:b%x:p:%p",
|
|
style,
|
|
brush,
|
|
pfnWndProc
|
|
);
|
|
|
|
// Use a set of std::wstring (NOT char*)
|
|
TWindowClassSet::iterator it = ms_stWCSet.find(szClassName);
|
|
if (it != ms_stWCSet.end())
|
|
return it->c_str();
|
|
|
|
// Persist the string
|
|
std::wstring staticClassName = szClassName;
|
|
ms_stWCSet.insert(staticClassName);
|
|
|
|
WNDCLASSW wc{};
|
|
wc.style = style;
|
|
wc.lpfnWndProc = pfnWndProc;
|
|
wc.hCursor = LoadCursor(ms_hInstance, MAKEINTRESOURCE(iCursorResource));
|
|
wc.hIcon = hIcon ? hIcon : LoadIcon(ms_hInstance, IDI_APPLICATION);
|
|
wc.hbrBackground = (HBRUSH)GetStockObject(brush);
|
|
wc.hInstance = ms_hInstance;
|
|
wc.lpszClassName = staticClassName.c_str();
|
|
wc.lpszMenuName = nullptr;
|
|
|
|
if (!RegisterClassW(&wc))
|
|
return nullptr;
|
|
|
|
// Return pointer stable inside the set
|
|
return ms_stWCSet.find(staticClassName)->c_str();
|
|
}
|
|
|
|
CMSWindow::CMSWindow()
|
|
{
|
|
m_hWnd=NULL;
|
|
m_isVisible=false;
|
|
}
|
|
|
|
CMSWindow::~CMSWindow()
|
|
{
|
|
} |