WinGUI/WinGUI/GUI/WinUI.cpp
2025-06-05 10:57:43 +08:00

1355 lines
32 KiB
C++

#include "WinUI.h"
#include <windowsx.h>
#include <commctrl.h>
#include <richedit.h>
#include <WinUser.h>
#pragma comment(lib, "Comctl32.lib")
#define ID_EDITCHILD 100
LRESULT CALLBACK Control::CAPTURED_MESSAGE_PROCESS(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
Control* wnd = (Control*)GetWindowLongPtrW(hWnd, GWLP_USERDATA);
if (wnd == NULL && (message == WM_NCCREATE || message == WM_CREATE))
wnd = (Control*)((LPCREATESTRUCTW)(lParam))->lpCreateParams;
if (wnd != NULL)
{
//printf("%ws : %X --- %X\n", wnd->Class.c_str(), message, HIWORD(wParam));
return wnd->MESSAGE_PROCESS(hWnd, message, wParam, lParam);
}
else if (message == WM_COMMAND)
{
HWND hwnd = (HWND)lParam;
Control* child = (Control*)GetWindowLongPtrW(hwnd, GWLP_USERDATA);
//printf("%ws : %X --- %X\n", child->Class.c_str(), message, HIWORD(wParam));
if (!child)
{
return DefWindowProc(hWnd, message, wParam, lParam);
}
return child->ProcessEvent(hWnd, message, wParam, lParam);
}
else
{
return DefWindowProc(hWnd, message, wParam, lParam);
}
}
HFONT Control::DefaultFont()
{
LOGFONT logfont = {};
logfont.lfHeight = 14;
wcscpy_s(logfont.lfFaceName, L"AR PL UKai CN");
return CreateFontIndirect(&logfont);
}
Control::Control()
{
}
void Control::CaptureMessage()
{
MESSAGE_PROCESS = (decltype(MESSAGE_PROCESS))SetWindowLongPtr(m_Handle, GWLP_WNDPROC, (LONG_PTR)CAPTURED_MESSAGE_PROCESS);
}
GET_CPP(Control, HWND, Parent)
{
return ::GetParent(this->m_Handle);
}
SET_CPP(Control, HWND, Parent)
{
::SetParent(this->m_Handle, value);
}
GET_CPP(Control, Control*, ParentControl)
{
return (Control*)GetWindowLongPtrW(::GetParent(this->m_Handle), GWLP_USERDATA);
}
SET_CPP(Control, Control*, ParentControl)
{
::SetParent(this->m_Handle, value->m_Handle);
}
GET_CPP(Control, DWORD, Style)
{
return GetWindowLong(this->m_Handle, GWL_STYLE);
}
SET_CPP(Control, DWORD, Style)
{
SetWindowLong(this->m_Handle, GWL_STYLE, value);
}
GET_CPP(Control, DWORD, StyleEx)
{
return GetWindowLong(this->m_Handle, GWL_EXSTYLE);
}
SET_CPP(Control, DWORD, StyleEx)
{
SetWindowLong(this->m_Handle, GWL_EXSTYLE, value);
}
GET_CPP(Control, std::wstring, Class)
{
wchar_t buffer[256];
::GetClassNameW(this->m_Handle, buffer, 256);
return buffer;
}
GET_CPP(Control, std::wstring, Text)
{
int len = GetWindowTextLengthW(this->m_Handle);
std::wstring str;
str.resize(len);
GetWindowTextW(this->m_Handle, str.data(), len + 1);
return str;
}
SET_CPP(Control, std::wstring, Text)
{
SetWindowTextW(this->m_Handle, value.c_str());
}
GET_CPP(Control, int, Width)
{
RECT rc;
GetWindowRect(this->m_Handle, &rc);
return rc.right - rc.left;
}
SET_CPP(Control, int, Width)
{
RECT rc;
GetWindowRect(this->m_Handle, &rc);
MoveWindow(this->m_Handle, rc.left, rc.top, value, rc.bottom - rc.top, TRUE);
}
GET_CPP(Control, int, Height)
{
RECT rc;
GetWindowRect(this->m_Handle, &rc);
return rc.bottom - rc.top;
}
SET_CPP(Control, int, Height)
{
RECT rc;
GetWindowRect(this->m_Handle, &rc);
MoveWindow(this->m_Handle, rc.left, rc.top, rc.right - rc.left, value, TRUE);
}
GET_CPP(Control, int, Left)
{
RECT rc;
GetWindowRect(this->m_Handle, &rc);
return rc.left;
}
SET_CPP(Control, int, Left)
{
RECT rc;
GetWindowRect(this->m_Handle, &rc);
MoveWindow(this->m_Handle, value, rc.top, rc.right - rc.left, rc.bottom - rc.top, TRUE);
}
GET_CPP(Control, int, Top)
{
RECT rc;
GetWindowRect(this->m_Handle, &rc);
return rc.top;
}
SET_CPP(Control, int, Top)
{
RECT rc;
GetWindowRect(this->m_Handle, &rc);
MoveWindow(this->m_Handle, rc.left, value, rc.right - rc.left, rc.bottom - rc.top, TRUE);
}
GET_CPP(Control, int, X)
{
RECT rc;
GetWindowRect(this->m_Handle, &rc);
return rc.left;
}
SET_CPP(Control, int, X)
{
RECT rc;
GetWindowRect(this->m_Handle, &rc);
MoveWindow(this->m_Handle, value, rc.top, rc.right - rc.left, rc.bottom - rc.top, TRUE);
}
GET_CPP(Control, int, Y)
{
RECT rc;
GetWindowRect(this->m_Handle, &rc);
return rc.top;
}
SET_CPP(Control, int, Y)
{
RECT rc;
GetWindowRect(this->m_Handle, &rc);
MoveWindow(this->m_Handle, rc.left, value, rc.right - rc.left, rc.bottom - rc.top, TRUE);
}
GET_CPP(Control, int, Right)
{
RECT rc;
GetWindowRect(this->m_Handle, &rc);
return rc.right;
}
SET_CPP(Control, int, Right)
{
RECT rc;
GetWindowRect(this->m_Handle, &rc);
MoveWindow(this->m_Handle, rc.left, rc.top, value, rc.bottom - rc.top, TRUE);
}
GET_CPP(Control, int, Bottom)
{
RECT rc;
GetWindowRect(this->m_Handle, &rc);
return rc.bottom;
}
SET_CPP(Control, int, Bottom)
{
RECT rc;
GetWindowRect(this->m_Handle, &rc);
MoveWindow(this->m_Handle, rc.left, rc.top, rc.right - rc.left, value, TRUE);
}
GET_CPP(Control, BOOL, Checked)
{
return SendMessage(this->m_Handle, BM_GETCHECK, 0, 0);
}
SET_CPP(Control, BOOL, Checked)
{
SendMessage(this->m_Handle, BM_SETCHECK, value, 0);
}
GET_CPP(Control, RECT, Rect)
{
RECT rc;
GetWindowRect(this->m_Handle, &rc);
return rc;
}
SET_CPP(Control, RECT, Rect)
{
MoveWindow(this->m_Handle, value.left, value.top, value.right - value.left, value.bottom - value.top, TRUE);
}
GET_CPP(Control, POINT, Location)
{
auto rect = this->Rect;
return POINT{ rect.left,rect.top };
}
SET_CPP(Control, POINT, Location)
{
auto rect = this->Rect;
MoveWindow(this->m_Handle, value.x, value.y, rect.right - rect.left, rect.bottom - rect.top, TRUE);
}
GET_CPP(Control, SIZE, Size)
{
auto rect = this->Rect;
return SIZE{ rect.right - rect.left ,rect.bottom - rect.top };
}
SET_CPP(Control, SIZE, Size)
{
auto rect = this->Rect;
MoveWindow(this->m_Handle, rect.left, rect.top, value.cx, value.cy, FALSE);
}
GET_CPP(Control, BOOL, Enable)
{
return IsWindowEnabled(this->m_Handle);
}
SET_CPP(Control, BOOL, Enable)
{
EnableWindow(this->m_Handle, value);
}
GET_CPP(Control, BOOL, Visable)
{
return IsWindowVisible(this->m_Handle);
}
SET_CPP(Control, BOOL, Visable)
{
ShowWindow(this->m_Handle, value ? SW_SHOWNORMAL : SW_HIDE);
}
GET_CPP(Control, COLORREF, ForeColor)
{
return GetTextColor(GetDC(this->m_Handle));
}
SET_CPP(Control, COLORREF, ForeColor)
{
SetTextColor(GetDC(this->m_Handle), value);
}
GET_CPP(Control, COLORREF, BackColor)
{
return GetBkColor(GetDC(this->m_Handle));
}
SET_CPP(Control, COLORREF, BackColor)
{
SetBkColor(GetDC(this->m_Handle), value);
}
GET_CPP(Control, std::vector<Control*>, Childens)
{
std::vector<Control*> result = std::vector<Control*>();
HWND hWnd = GetWindow(this->m_Handle, GW_CHILD);
while (hWnd)
{
Control* control = (Control*)::GetWindowLongPtrW(hWnd, GWLP_USERDATA);
if (control)
result.push_back(control);
hWnd = GetWindow(hWnd, GW_HWNDNEXT);
}
return result;
}
GET_CPP(Control, std::vector<HWND>, ChildHandles)
{
std::vector<HWND> result = std::vector<HWND>();
HWND hWnd = GetWindow(this->m_Handle, GW_CHILD);
while (hWnd)
{
result.push_back(hWnd);
hWnd = GetWindow(hWnd, GW_HWNDNEXT);
}
return result;
}
GET_CPP(Control, HBITMAP, Bitmap)
{
return (HBITMAP)SendMessage(this->m_Handle, STM_GETIMAGE, IMAGE_BITMAP, 0);
}
SET_CPP(Control, HBITMAP, Bitmap)
{
SendMessage(this->m_Handle, STM_SETIMAGE, IMAGE_BITMAP, (LPARAM)value);
}
GET_CPP(Control, HWND, TopLevelHandle)
{
return GetAncestor(this->m_Handle, GA_ROOT);
}
GET_CPP(Control, class Window*, TopLevelWindow)
{
HWND hTopLevel = GetAncestor(this->m_Handle, GA_ROOT);
class Window* wnd = (class Window*)GetWindowLongPtrW(hTopLevel, GWLP_USERDATA);
return wnd;
}
GET_CPP(Control, HFONT, Font)
{
return (HFONT)SendMessage(this->m_Handle, WM_GETFONT, 0, TRUE);
}
SET_CPP(Control, HFONT, Font)
{
SendMessage(this->m_Handle, WM_SETFONT, (WPARAM)value, TRUE);
}
void Control::SetRect(POINT location, SIZE size)
{
this->Rect = RECT{ location.x,location.y ,location.x + size.cx,location.y + size.cy };
}
void Control::SetRect(int x, int y, int width, int height)
{
this->Rect = RECT{ x,y ,x + width,y + height };
}
BOOL Control::RemoveChild(Control* child)
{
if (child->Parent == this->m_Handle)
{
child->Parent = NULL;
return TRUE;
}
return FALSE;
}
void Control::SetFont(std::wstring fontName, int fontSize)
{
LOGFONT logfont = {};
logfont.lfHeight = fontSize;
wcscpy_s(logfont.lfFaceName, fontName.c_str());
HFONT hFont = CreateFontIndirect(&logfont);
SendMessage(this->m_Handle, WM_SETFONT, (WPARAM)hFont, TRUE);
}
LRESULT Control::ProcessEvent(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message)
{
//case WM_CTLCOLORSTATIC:
//{
// SetBkMode((HDC)wParam, TRANSPARENT);
// return (LRESULT)GetStockObject(WHITE_BRUSH);
//}
case WM_MOUSEWHEEL:
this->OnMouseWheel(this, hWnd, message, wParam, lParam);
break;
case WM_MOUSEMOVE:
this->OnMouseMove(this, hWnd, message, wParam, lParam);
break;
case WM_LBUTTONDOWN:
this->OnMouseLeftButtonDown(this, hWnd, message, wParam, lParam);
break;
case WM_RBUTTONDOWN:
this->OnMouseRightButtonDown(this, hWnd, message, wParam, lParam);
break;
case WM_MBUTTONDOWN:
this->OnMouseMiddleButtonDown(this, hWnd, message, wParam, lParam);
break;
case WM_LBUTTONUP:
this->OnMouseLeftButtonUp(this, hWnd, message, wParam, lParam);
break;
case WM_RBUTTONUP:
this->OnMouseRightButtonUp(this, hWnd, message, wParam, lParam);
break;
case WM_MBUTTONUP:
this->OnMouseMiddleButtonUp(this, hWnd, message, wParam, lParam);
break;
case WM_KEYDOWN:
this->OnKeyDown(this, hWnd, message, wParam, lParam);
break;
case WM_KEYUP:
this->OnKeyUp(this, hWnd, message, wParam, lParam);
break;
case WM_SETFOCUS:
this->OnGotFocus(this, hWnd, message, wParam, lParam);
break;
case WM_KILLFOCUS:
this->OnLostFocus(this, hWnd, message, wParam, lParam);
break;
case WM_MOVE:
this->OnMoved(this, hWnd, message, wParam, lParam);
break;
case WM_SIZE:
this->OnSizeChanged(this, hWnd, message, wParam, lParam);
break;
case WM_COMMAND:
{
switch (HIWORD(wParam))
{
case CBN_SELCHANGE:
this->OnSelectionChanged(this, hWnd, message, wParam, lParam);
break;
case BN_DOUBLECLICKED:
{
if (this->Class == WC_BUTTON)
this->OnDoubleClicked(this, hWnd, message, wParam, lParam);
else
this->OnEditChanged(this, hWnd, message, wParam, lParam);
}
break;
case EN_CHANGE:
this->OnChanged(this, hWnd, message, wParam, lParam);
break;
case BN_CLICKED:
this->OnClicked(this, hWnd, message, wParam, lParam);
break;
case LBN_DBLCLK:
this->OnDoubleClicked(this, hWnd, message, wParam, lParam);
break;
}
}
break;
}
return NULL;
}
Button::Button(Control* parent)
{
this->m_Handle = CreateWindow(
WC_BUTTON,
L"",
WS_TABSTOP | WS_VISIBLE | WS_CHILD | BS_DEFPUSHBUTTON,// | BS_FLAT
CW_USEDEFAULT,
CW_USEDEFAULT,
100,
20,
parent->m_Handle,
NULL,
GetModuleHandle(NULL),
this);
::SetWindowLongPtrW(m_Handle, GWLP_USERDATA, (LONG_PTR)this);
this->SetFont(Control::DefaultFont());
this->CaptureMessage();
}
CheckBox::CheckBox(Control* parent)
{
this->m_Handle = CreateWindow(
WC_BUTTON,
L"",
WS_TABSTOP | WS_VISIBLE | WS_CHILD | BS_AUTOCHECKBOX,
CW_USEDEFAULT,
CW_USEDEFAULT,
CW_USEDEFAULT,
CW_USEDEFAULT,
parent->m_Handle,
NULL,
GetModuleHandle(NULL),
this);
::SetWindowLongPtrW(m_Handle, GWLP_USERDATA, (LONG_PTR)this);
this->SetFont(Control::DefaultFont());
this->CaptureMessage();
}
ComboBox::ComboBox(Control* parent)
{
this->m_Handle = CreateWindow(
WC_COMBOBOX,
L"",
CBS_DROPDOWNLIST | CBS_DISABLENOSCROLL | WS_CHILD | WS_VISIBLE | WS_VSCROLL,
CW_USEDEFAULT,
CW_USEDEFAULT,
CW_USEDEFAULT,
CW_USEDEFAULT,
parent->m_Handle,
NULL,
GetModuleHandle(NULL),
this);
::SetWindowLongPtrW(m_Handle, GWLP_USERDATA, (LONG_PTR)this);
this->SetFont(Control::DefaultFont());
this->CaptureMessage();
}
GET_CPP(ComboBox, int, SelectedIndex)
{
return SendMessage((HWND)this->m_Handle, (UINT)CB_GETCURSEL, (WPARAM)0, (LPARAM)0);
}
SET_CPP(ComboBox, int, SelectedIndex)
{
SendMessage((HWND)this->m_Handle, (UINT)CB_SETCURSEL, (WPARAM)value, (LPARAM)0);
}
GET_CPP(ComboBox, std::wstring, SelectedItem)
{
TCHAR ListItem[256];
SendMessage((HWND)this->m_Handle, (UINT)CB_GETLBTEXT, (WPARAM)this->SelectedIndex, (LPARAM)ListItem);
return ListItem;
}
std::wstring ComboBox::operator[](int index)
{
TCHAR ListItem[256];
SendMessage((HWND)this->m_Handle, (UINT)CB_GETLBTEXT, (WPARAM)index, (LPARAM)ListItem);
return ListItem;
}
void ComboBox::AddItem(std::wstring index)
{
SendMessage((HWND)this->m_Handle, (UINT)CB_ADDSTRING, (WPARAM)0, (LPARAM)index.c_str());
}
GET_CPP(ComboBox, int, Count)
{
return SendMessage((HWND)this->m_Handle, (UINT)CB_GETCOUNT, (WPARAM)0, (LPARAM)0);
}
void ComboBox::Clear()
{
SendMessage((HWND)this->m_Handle, (UINT)CB_RESETCONTENT, (WPARAM)0, (LPARAM)0);
}
void ComboBox::RemoveAt(int index)
{
SendMessage(this->m_Handle, LB_DELETESTRING, index, 0);
}
GroupBox::GroupBox(Control* parent)
{
this->m_Handle = CreateWindow(
WC_BUTTON,
L"",
WS_TABSTOP | WS_VISIBLE | WS_CHILD | BS_GROUPBOX,
CW_USEDEFAULT,
CW_USEDEFAULT,
CW_USEDEFAULT,
CW_USEDEFAULT,
parent->m_Handle,
NULL,
GetModuleHandle(NULL),
this);
::SetWindowLongPtrW(m_Handle, GWLP_USERDATA, (LONG_PTR)this);
this->SetFont(Control::DefaultFont());
this->CaptureMessage();
}
Label::Label(Control* parent)
{
this->m_Handle = CreateWindow(
WC_STATIC,
L"",
WS_CHILD | WS_VISIBLE | SS_NOTIFY,
CW_USEDEFAULT,
CW_USEDEFAULT,
CW_USEDEFAULT,
CW_USEDEFAULT,
parent->m_Handle,
NULL,
GetModuleHandle(NULL),
this);
::SetWindowLongPtrW(m_Handle, GWLP_USERDATA, (LONG_PTR)this);
this->SetFont(Control::DefaultFont());
this->CaptureMessage();
}
ListBox::ListBox(Control* parent)
{
this->m_Handle = CreateWindow(
WC_LISTBOX,
L"",
WS_TABSTOP | WS_VISIBLE | WS_CHILD | WS_BORDER | WS_VSCROLL | ES_AUTOVSCROLL | BS_DEFPUSHBUTTON,
CW_USEDEFAULT,
CW_USEDEFAULT,
CW_USEDEFAULT,
CW_USEDEFAULT,
parent->m_Handle,
NULL,
GetModuleHandle(NULL),
this);
::SetWindowLongPtrW(m_Handle, GWLP_USERDATA, (LONG_PTR)this);
this->SetFont(Control::DefaultFont());
this->CaptureMessage();
}
void ListBox::AddItem(std::wstring item)
{
SendMessage(this->m_Handle, LB_ADDSTRING, 0, (LPARAM)item.c_str());
}
void ListBox::RemoveAt(int index)
{
SendMessage(this->m_Handle, LB_DELETESTRING, index, 0);
}
std::wstring ListBox::operator[](int index)
{
TCHAR ListItem[256];
SendMessage(this->m_Handle, LB_GETTEXT, index, (LPARAM)ListItem);
return ListItem;
}
void ListBox::Clear()
{
SendMessage(this->m_Handle, LB_RESETCONTENT, 0, 0);
}
GET_CPP(ListBox, int, Count)
{
return SendMessage(this->m_Handle, LB_GETCOUNT, 0, 0);
}
ListView::ListView(Control* parent)
{
INITCOMMONCONTROLSEX icex;
icex.dwICC = ICC_LISTVIEW_CLASSES;
InitCommonControlsEx(&icex);
this->m_Handle = CreateWindow(
WC_LISTVIEW,
L"",
WS_BORDER | WS_HSCROLL | LVS_AUTOARRANGE | LVS_ICON | LVS_SINGLESEL | LVS_SHOWSELALWAYS | WS_VISIBLE | WS_CHILD | LVS_REPORT,
CW_USEDEFAULT,
CW_USEDEFAULT,
CW_USEDEFAULT,
CW_USEDEFAULT,
parent->m_Handle,
NULL,
GetModuleHandle(NULL),
this);
SendMessage(this->m_Handle, LVM_SETEXTENDEDLISTVIEWSTYLE,
LVS_EX_FULLROWSELECT, LVS_EX_FULLROWSELECT);
::SetWindowLongPtrW(m_Handle, GWLP_USERDATA, (LONG_PTR)this);
this->SetFont(Control::DefaultFont());
this->CaptureMessage();
}
GET_CPP(ListView, int, ColumnCount)
{
HWND hWndHdr = (HWND)::SendMessage(this->m_Handle, LVM_GETHEADER, 0, 0);
return (int)::SendMessage(hWndHdr, HDM_GETITEMCOUNT, 0, 0L);
}
GET_CPP(ListView, int, RowCount)
{
return ListView_GetItemCount(this->m_Handle);
}
SET_CPP(ListView, int, RowCount)
{
ListView_SetItemCount(this->m_Handle, value);
}
void ListView::AddColumn(LVCOLUMN col)
{
col.iSubItem = this->ColumnCount;
ListView_InsertColumn(this->m_Handle, col.iSubItem, &col);
}
void ListView::AddColumn(std::wstring name, int width, DWORD align, DWORD flag)
{
LVCOLUMN lvc;
lvc.mask = flag;
lvc.cx = width;
lvc.fmt = align;
lvc.pszText = (LPWSTR)name.c_str();
this->AddColumn(lvc);
}
void ListView::RemoveColumn(int colIndex)
{
ListView_DeleteColumn(this->m_Handle, colIndex);
}
int ListView::AddRow()
{
LVITEM ite = { 0 };
ite.mask = LVIF_TEXT;
ite.pszText = (LPWSTR)L"";
ite.iItem = this->RowCount;
return ListView_InsertItem(this->m_Handle, &ite);
}
void ListView::SetItemText(int col, int row, std::wstring text)
{
ListView_SetItemText(this->m_Handle, row, col, (LPWSTR)text.c_str());
}
void ListView::Clear()
{
ListView_DeleteAllItems(this->m_Handle);
}
GET_CPP(ListView, int, SelectedRowIndex)
{
return ListView_GetNextItem(this->m_Handle, -1, LVNI_SELECTED);
}
SET_CPP(ListView, int, SelectedRowIndex)
{
ListView_SetItemState(this->m_Handle, value, LVIS_SELECTED, LVIS_SELECTED);
}
LVITEM ListView::GetItem(int colIndex, int rowIndex)
{
LVITEM item = { 0 };
item.iItem = rowIndex;
item.iSubItem = colIndex;
item.mask = LVIF_TEXT;
item.pszText = new wchar_t[0xFF];
item.cchTextMax = 0xFF;
ListView_GetItem(this->m_Handle, &item);
return item;
}
std::wstring ListView::GetItemText(int colIndex, int rowIndex)
{
LVITEM item = this->GetItem(colIndex, rowIndex);
return item.pszText;
}
ProgressBar::ProgressBar(Control* parent)
{
//ANIMATE_CLASS
this->m_Handle = CreateWindow(
PROGRESS_CLASS,
L"",
WS_CHILD | WS_VISIBLE | PBS_SMOOTH,
CW_USEDEFAULT,
CW_USEDEFAULT,
CW_USEDEFAULT,
CW_USEDEFAULT,
parent->m_Handle,
NULL,
GetModuleHandle(NULL),
this);
::SetWindowLongPtrW(m_Handle, GWLP_USERDATA, (LONG_PTR)this);
this->SetFont(Control::DefaultFont());
this->CaptureMessage();
}
GET_CPP(ProgressBar, int, MaxValue)
{
return SendMessage(this->m_Handle, PBM_GETRANGE, FALSE, 0);
}
SET_CPP(ProgressBar, int, MaxValue)
{
SendMessage(this->m_Handle, PBM_SETRANGE, 0, MAKELPARAM(0, value));
}
GET_CPP(ProgressBar, int, MinValue)
{
return SendMessage(this->m_Handle, PBM_GETRANGE, TRUE, 0);
}
SET_CPP(ProgressBar, int, MinValue)
{
SendMessage(this->m_Handle, PBM_SETRANGE, 0, MAKELPARAM(value, this->MaxValue));
}
GET_CPP(ProgressBar, int, Value)
{
return SendMessage(this->m_Handle, PBM_GETPOS, 0, 0);
}
SET_CPP(ProgressBar, int, Value)
{
SendMessage(this->m_Handle, PBM_SETPOS, value, 0);
}
RadioBox::RadioBox(Control* parent)
{
this->m_Handle = CreateWindow(
WC_BUTTON,
L"",
WS_TABSTOP | WS_VISIBLE | WS_CHILD | BS_AUTORADIOBUTTON,
CW_USEDEFAULT,
CW_USEDEFAULT,
CW_USEDEFAULT,
CW_USEDEFAULT,
parent->m_Handle,
NULL,
GetModuleHandle(NULL),
this);
::SetWindowLongPtrW(m_Handle, GWLP_USERDATA, (LONG_PTR)this);
this->SetFont(Control::DefaultFont());
this->CaptureMessage();
}
RichTextBox::RichTextBox(Control* parent)
{
if (!LoadLibrary(TEXT("Msftedit.dll")))
if (!LoadLibrary(TEXT("Riched20.dll")))
if (!LoadLibrary(TEXT("Riched32.dll")))
throw std::exception("Failed to load RichEdit DLL");
this->m_Handle = CreateWindow(
MSFTEDIT_CLASS,
L"",
ES_MULTILINE | WS_VISIBLE | WS_CHILD | WS_BORDER | WS_TABSTOP | WS_VSCROLL,
CW_USEDEFAULT,
CW_USEDEFAULT,
CW_USEDEFAULT,
CW_USEDEFAULT,
parent->m_Handle,
(HMENU)ID_EDITCHILD,
GetModuleHandle(NULL),
this);
::SetWindowLongPtrW(m_Handle, GWLP_USERDATA, (LONG_PTR)this);
this->SetFont(Control::DefaultFont());
this->CaptureMessage();
}
void RichTextBox::AppendText(std::wstring str)
{
int len = GetWindowTextLength(this->m_Handle);
SendMessage(this->m_Handle, EM_SETSEL, len, len);
SendMessage(this->m_Handle, EM_REPLACESEL, 0, (LPARAM)str.c_str());
}
void RichTextBox::AppendLine(std::wstring str)
{
this->AppendText(str + L"\r\n");
}
void RichTextBox::ScrollToCaret()
{
SendMessage(this->m_Handle, EM_SCROLLCARET, 0, 0);
}
ScrollBar::ScrollBar(Control* parent, ScrollBarDirection dir)
{
this->m_Handle = CreateWindow(
L"SCROLLBAR",
L"",
WS_CHILD | WS_VISIBLE | (DWORD)(dir == ScrollBarDirection::Horizontal ? SBS_HORZ : SBS_VERT),
CW_USEDEFAULT,
CW_USEDEFAULT,
CW_USEDEFAULT,
CW_USEDEFAULT,
parent->m_Handle,
NULL,
GetModuleHandle(NULL),
this);
::SetWindowLongPtrW(m_Handle, GWLP_USERDATA, (LONG_PTR)this);
this->SetFont(Control::DefaultFont());
this->CaptureMessage();
}
TabPage::TabPage(Control* parent)
{
this->m_Handle = CreateWindow(
WC_STATIC,
L"",
WS_CHILD | WS_VISIBLE,
CW_USEDEFAULT,
CW_USEDEFAULT,
CW_USEDEFAULT,
CW_USEDEFAULT,
parent->m_Handle,
NULL,
GetModuleHandle(NULL),
this);
::SetWindowLongPtrW(m_Handle, GWLP_USERDATA, (LONG_PTR)this);
this->SetFont(Control::DefaultFont());
this->CaptureMessage();
}
TabControl::TabControl(Control* parent)
{
INITCOMMONCONTROLSEX icex;
icex.dwSize = sizeof(INITCOMMONCONTROLSEX);
icex.dwICC = ICC_TAB_CLASSES;
InitCommonControlsEx(&icex);
this->m_Handle = CreateWindow(
WC_TABCONTROL,
L"",
WS_CHILD | WS_VISIBLE,
CW_USEDEFAULT,
CW_USEDEFAULT,
CW_USEDEFAULT,
CW_USEDEFAULT,
parent->m_Handle,
NULL,
GetModuleHandle(NULL),
this);
::SetWindowLongPtrW(m_Handle, GWLP_USERDATA, (LONG_PTR)this);
this->SetFont(Control::DefaultFont());
this->CaptureMessage();
}
TabPage* TabControl::AddPage(std::wstring item)
{
TCITEM tie;
tie.mask = TCIF_TEXT;
tie.pszText = (LPWSTR)item.c_str();
SendMessage(this->m_Handle, TCM_INSERTITEM, this->Count, (LPARAM)&tie);
TabPage* page = new TabPage(this);
this->pages.Add(page);
RECT clientRect;
GetClientRect(this->m_Handle, &clientRect);
TabCtrl_AdjustRect(this->m_Handle, FALSE, &clientRect);
page->Rect = clientRect;
this->UpdatePages();
return page;
}
void TabControl::RemoveAt(int index)
{
if (index >= 0 && this->pages.Count > index)
{
this->pages[index]->Visable = false;
this->pages.RemoveAt(index);
SendMessage(this->m_Handle, TCM_DELETEITEM, index, 0);
this->pages[index]->Parent = NULL;
this->UpdatePages();
}
}
std::wstring TabControl::operator[](int index)
{
TCITEM tie;
TabCtrl_GetItem(this->m_Handle, index, &tie);
return tie.pszText;
}
void TabControl::Clear()
{
SendMessage(this->m_Handle, TCM_DELETEALLITEMS, 0, 0);
this->UpdatePages();
}
GET_CPP(TabControl, int, Count)
{
return TabCtrl_GetItemCount(this->m_Handle);
}
GET_CPP(TabControl, int, SelectedIndex)
{
return TabCtrl_GetCurSel(this->m_Handle);
}
GET_CPP(TabControl, TabPage**, Pages)
{
return this->pages.data();
}
void TabControl::UpdatePages()
{
RECT clientRect;
GetClientRect(this->m_Handle, &clientRect);
TabCtrl_AdjustRect(this->m_Handle, FALSE, &clientRect);
for (int i = 0; i < this->pages.Count; i++)
{
if (i != this->SelectedIndex)
{
this->pages[i]->Visable = FALSE;
}
else
{
this->pages[i]->Rect = clientRect;
this->pages[i]->Visable = TRUE;
}
}
}
LRESULT TabControl::ProcessEvent(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message)
{
case WM_MOVE:
{
this->UpdatePages();
break;
}
case WM_SIZE:
{
this->UpdatePages();
break;
}
case WM_NOTIFY:
{
this->UpdatePages();
break;
}
}
return TRUE;
}
TextBox::TextBox(Control* parent)
{
this->m_Handle = CreateWindow(
WC_EDIT,
L"",
WS_CHILD | WS_VISIBLE | WS_BORDER | ES_LEFT | ES_AUTOHSCROLL,
CW_USEDEFAULT,
CW_USEDEFAULT,
CW_USEDEFAULT,
CW_USEDEFAULT,
parent->m_Handle,
(HMENU)ID_EDITCHILD,
GetModuleHandle(NULL),
this);
::SetWindowLongPtrW(m_Handle, GWLP_USERDATA, (LONG_PTR)this);
this->SetFont(Control::DefaultFont());
SendMessage(this->m_Handle, EM_LIMITTEXT, (WPARAM)INT_MAX, 0);
this->CaptureMessage();
}
GET_CPP(TextBox, const wchar_t, PasswordChar)
{
return (wchar_t)SendMessage(this->m_Handle, EM_GETPASSWORDCHAR, 0, 0);
}
SET_CPP(TextBox, const wchar_t, PasswordChar)
{
SendMessage(this->m_Handle, EM_SETPASSWORDCHAR, value, 0);
}
GET_CPP(TextBox, BOOL, PasswordBox)
{
return this->Style & ES_PASSWORD == ES_PASSWORD;
}
SET_CPP(TextBox, BOOL, PasswordBox)
{
if (value)
this->Style |= ES_PASSWORD;
else
this->Style &= ~ES_PASSWORD;
}
Tooltip::Tooltip(Control* parent)
{
this->bindControl = parent;
this->m_Handle = CreateWindowEx(NULL,
TOOLTIPS_CLASS,
NULL,
WS_POPUP | TTS_ALWAYSTIP | TTS_BALLOON,
CW_USEDEFAULT, CW_USEDEFAULT,
CW_USEDEFAULT, CW_USEDEFAULT,
parent->Parent, NULL,
GetModuleHandle(NULL), this);
::SetWindowLongPtrW(m_Handle, GWLP_USERDATA, (LONG_PTR)this);
this->SetFont(Control::DefaultFont());
}
void Tooltip::SetMessage(std::wstring text)
{
TOOLINFO ti = { 0 };
ti.cbSize = sizeof(TOOLINFO);
ti.hwnd = this->bindControl->Parent;
ti.uFlags = TTF_IDISHWND | TTF_SUBCLASS;
ti.uId = (UINT_PTR)this->bindControl->m_Handle;
ti.lpszText = (LPWSTR)text.c_str();
SendMessage(this->m_Handle, TTM_ACTIVATE, TRUE, 0);
SendMessage(this->m_Handle, TTM_ADDTOOL, NULL, (LPARAM)&ti);
}
Trackbar::Trackbar(Control* parent)
{
this->m_Handle = CreateWindow(
TRACKBAR_CLASS,
L"",
WS_CHILD | WS_VISIBLE | TBS_AUTOTICKS | TBS_ENABLESELRANGE,
CW_USEDEFAULT,
CW_USEDEFAULT,
CW_USEDEFAULT,
CW_USEDEFAULT,
parent->m_Handle,
NULL,
GetModuleHandle(NULL),
this);
::SetWindowLongPtrW(m_Handle, GWLP_USERDATA, (LONG_PTR)this);
this->SetFont(Control::DefaultFont());
this->CaptureMessage();
}
GET_CPP(Trackbar, int, Value)
{
return SendMessage(this->m_Handle, TBM_GETPOS, 0, 0);
}
SET_CPP(Trackbar, int, Value)
{
SendMessage(this->m_Handle, TBM_SETPOS, TRUE, value);
}
GET_CPP(Trackbar, int, MinValue)
{
return SendMessage(this->m_Handle, TBM_GETRANGEMIN, 0, 0);
}
SET_CPP(Trackbar, int, MinValue)
{
SendMessage(this->m_Handle, TBM_SETRANGEMIN, TRUE, value);
}
GET_CPP(Trackbar, int, MaxValue)
{
return SendMessage(this->m_Handle, TBM_GETRANGEMAX, 0, 0);
}
SET_CPP(Trackbar, int, MaxValue)
{
SendMessage(this->m_Handle, TBM_SETRANGEMAX, TRUE, value);
}
GET_CPP(Trackbar, int, SelStart)
{
return SendMessage(this->m_Handle, TBM_GETSELEND, 0, 0);
}
SET_CPP(Trackbar, int, SelStart)
{
SendMessage(this->m_Handle, TBM_SETSELSTART, TRUE, value);
}
GET_CPP(Trackbar, int, SelEnd)
{
return SendMessage(this->m_Handle, TBM_GETSELEND, 0, 0);
}
SET_CPP(Trackbar, int, SelEnd)
{
SendMessage(this->m_Handle, TBM_SETSELEND, TRUE, value);
}
TreeView::TreeView(Control* parent)
{
this->m_Handle = CreateWindow(
WC_TREEVIEW,
L"",
WS_VISIBLE | WS_CHILD | WS_BORDER | TVS_HASLINES,
CW_USEDEFAULT,
CW_USEDEFAULT,
CW_USEDEFAULT,
CW_USEDEFAULT,
parent->m_Handle,
NULL,
GetModuleHandle(NULL),
this);
::SetWindowLongPtrW(m_Handle, GWLP_USERDATA, (LONG_PTR)this);
this->SetFont(Control::DefaultFont());
this->CaptureMessage();
}
void TreeView::Clear()
{
TreeView_DeleteAllItems(m_Handle);
}
HTREEITEM TreeView::AddItem(const std::wstring& text, HTREEITEM parent)
{
TVINSERTSTRUCT tvis;
tvis.hParent = parent;
tvis.hInsertAfter = TVI_LAST;
tvis.item.mask = TVIF_TEXT;
tvis.item.pszText = (LPWSTR)text.c_str();
return TreeView_InsertItem(m_Handle, &tvis);
}
BOOL TreeView::RemoveItem(HTREEITEM it)
{
return TreeView_DeleteItem(m_Handle, it);
}
GET_CPP(TreeView, HTREEITEM, Selected)
{
return TreeView_GetSelection(m_Handle);
}
GET_CPP(TreeView, std::wstring, SelectedString)
{
return GetItemString(TreeView_GetSelection(m_Handle));
}
GET_CPP(TreeView, int, Count)
{
return TreeView_GetCount(m_Handle);
}
std::wstring TreeView::GetItemString(HTREEITEM it)
{
TVITEM tvi;
tvi.mask = TVIF_TEXT;
tvi.hItem = it;
tvi.pszText = new TCHAR[256];
tvi.cchTextMax = 256;
TreeView_GetItem(m_Handle, &tvi);
std::wstring ret = tvi.pszText;
delete[] tvi.pszText;
return ret;
}
DatePicker::DatePicker(Control* parent)
{
this->m_Handle = CreateWindow(
DATETIMEPICK_CLASS,
L"",
WS_BORDER | WS_CHILD | WS_VISIBLE | DTS_SHORTDATEFORMAT,
CW_USEDEFAULT,
CW_USEDEFAULT,
CW_USEDEFAULT,
CW_USEDEFAULT,
parent->m_Handle,
NULL,
GetModuleHandle(NULL),
this);
::SetWindowLongPtrW(m_Handle, GWLP_USERDATA, (LONG_PTR)this);
this->SetFont(Control::DefaultFont());
this->CaptureMessage();
}
TimePicker::TimePicker(Control* parent)
{
this->m_Handle = CreateWindow(
DATETIMEPICK_CLASS,
L"",
WS_BORDER | WS_CHILD | WS_VISIBLE | DTS_TIMEFORMAT,
CW_USEDEFAULT,
CW_USEDEFAULT,
CW_USEDEFAULT,
CW_USEDEFAULT,
parent->m_Handle,
NULL,
GetModuleHandle(NULL),
this);
::SetWindowLongPtrW(m_Handle, GWLP_USERDATA, (LONG_PTR)this);
this->SetFont(Control::DefaultFont());
this->CaptureMessage();
}
BOOL Window::ClassInited = FALSE;
int Window::g_WindowCount = 0;
List<HWND> Window::Windows = List<HWND>();
LRESULT CALLBACK WINMSG_PROCESS(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam);
void Window::InitWindowClass()
{
WNDCLASSW wndclass = { 0 };
if (!ClassInited)
{
wndclass.style = CS_HREDRAW | CS_VREDRAW | CS_DBLCLKS;
wndclass.cbClsExtra = NULL;
wndclass.cbWndExtra = NULL;
wndclass.lpfnWndProc = WINMSG_PROCESS;
wndclass.hInstance = GetModuleHandle(NULL);
wndclass.hIcon = LoadIconW(NULL, MAKEINTRESOURCEW(32512));
wndclass.hCursor = LoadCursorW(NULL, MAKEINTRESOURCEW(32512));
wndclass.lpszMenuName = NULL;
wndclass.lpszClassName = L"CoreNativeWindow";
wndclass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
if (!RegisterClassW(&wndclass))
return;
ClassInited = TRUE;
}
}
Window::Window()
{
InitWindowClass();
this->m_Handle = CreateWindow(
L"CoreNativeWindow",
L"",
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT,
CW_USEDEFAULT,
CW_USEDEFAULT,
CW_USEDEFAULT,
NULL,
NULL,
GetModuleHandle(NULL),
this);
::SetWindowLongPtrW(m_Handle, GWLP_USERDATA, (LONG_PTR)this);
this->SetFont(Control::DefaultFont());
this->CaptureMessage();
}
void Window::Show()
{
ShowWindow(m_Handle, SW_SHOWNORMAL);
}
void Window::ShowDialog(HWND parent)
{
::ShowWindow(m_Handle, SW_SHOWNORMAL);
MSG msg;
while (IsWindow(this->m_Handle) && ::GetMessage(&msg, NULL, 0, 0))
{
Control* control = (Control*)GetWindowLongPtr(msg.hwnd, GWLP_USERDATA);
::TranslateMessage(&msg);
if (msg.hwnd == this->m_Handle ||
control == NULL ||
(msg.message == WM_SYSCOMMAND && msg.wParam == SC_RESTORE) ||
control->TopLevelWindow == this
)
{
::DispatchMessageW(&msg);
}
};
}
void Window::Run()
{
MSG msg;
while (GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessageW(&msg);
};
}
void Window::DoEvent()
{
MSG msg;
if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
GET_CPP(Window, COLORREF, BackColor)
{
return m_BackColor;
}
SET_CPP(Window, COLORREF, BackColor)
{
m_BackColor = value;
}
GET_CPP(Window, HICON, Icon)
{
return (HICON)SendMessage(this->m_Handle, WM_GETICON, ICON_BIG, 0);
}
SET_CPP(Window, HICON, Icon)
{
SendMessage(this->m_Handle, WM_SETICON, ICON_BIG, (LPARAM)value);
}
GET_CPP(Window, BOOL, CanResize)
{
return (GetWindowLong(m_Handle, GWL_STYLE) & WS_SIZEBOX) == WS_SIZEBOX;
}
SET_CPP(Window, BOOL, CanResize)
{
if (value)
SetWindowLong(m_Handle, GWL_STYLE, GetWindowLong(m_Handle, GWL_STYLE) | WS_SIZEBOX);
else
SetWindowLong(m_Handle, GWL_STYLE, GetWindowLong(m_Handle, GWL_STYLE) & ~WS_SIZEBOX);
}
GET_CPP(Window, BOOL, MaxBox)
{
return (GetWindowLong(m_Handle, GWL_STYLE) & WS_MAXIMIZEBOX) == WS_MAXIMIZEBOX;
}
SET_CPP(Window, BOOL, MaxBox)
{
if (value)
SetWindowLong(m_Handle, GWL_STYLE, GetWindowLong(m_Handle, GWL_STYLE) | WS_MAXIMIZEBOX);
else
SetWindowLong(m_Handle, GWL_STYLE, GetWindowLong(m_Handle, GWL_STYLE) & ~WS_MAXIMIZEBOX);
}
GET_CPP(Window, BOOL, MinBox)
{
return (GetWindowLong(m_Handle, GWL_STYLE) & WS_MINIMIZEBOX) == WS_MINIMIZEBOX;
}
SET_CPP(Window, BOOL, MinBox)
{
if (value)
SetWindowLong(m_Handle, GWL_STYLE, GetWindowLong(m_Handle, GWL_STYLE) | WS_MINIMIZEBOX);
else
SetWindowLong(m_Handle, GWL_STYLE, GetWindowLong(m_Handle, GWL_STYLE) & ~WS_MINIMIZEBOX);
}
void Window::Close()
{
DestroyWindow(m_Handle);
}
LRESULT CALLBACK WINMSG_PROCESS(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
Control* wnd = (Control*)GetWindowLongPtrW(hWnd, GWLP_USERDATA);
if (wnd == NULL && (message == WM_NCCREATE || message == WM_CREATE))
{
LPCREATESTRUCTW pCreate = reinterpret_cast<LPCREATESTRUCTW>(lParam);
wnd = (Control*)pCreate->lpCreateParams;
}
if (wnd == NULL)
return DefWindowProc(hWnd, message, wParam, lParam);
wnd->ProcessEvent(hWnd, message, wParam, lParam);
//printf("%ws : %X --- %X\n", wnd->Class.c_str(), message, HIWORD(wParam));
switch (message)
{
case WM_CREATE:
{
Window::g_WindowCount += 1;
Window::Windows.Add(hWnd);
}
break;
case WM_DESTROY:
{
Window::g_WindowCount -= 1;
Window::Windows.Remove(hWnd);
if (Window::g_WindowCount <= 0)
exit(0);
}
break;
case WM_CLOSE:
{
DestroyWindow(hWnd);
}
break;
case WM_CTLCOLORSTATIC:
{
SetBkMode((HDC)wParam, TRANSPARENT);
return (LRESULT)GetStockObject(WHITE_BRUSH);
}
case WM_ERASEBKGND:
{
RECT rect = {};
GetClientRect(hWnd, &rect);
HBRUSH blueBrush = CreateSolidBrush(wnd->BackColor);
FillRect((HDC)wParam, &rect, blueBrush);
DeleteObject(blueBrush);
}
break;
case WM_COMMAND:
{
auto child = (Control*)GetWindowLongPtrW((HWND)lParam, GWLP_USERDATA);
if (child)
child->ProcessEvent(hWnd, message, wParam, lParam);
}
break;
case WM_NOTIFY:
{
NMHDR* nmhdr = (NMHDR*)lParam;
auto child = (Control*)GetWindowLongPtrW(nmhdr->hwndFrom, GWLP_USERDATA);
if (child)
child->ProcessEvent(hWnd, message, wParam, lParam);
}
break;
}
return DefWindowProc(hWnd, message, wParam, lParam);
}