2013-03-15 13:11:33 +00:00
|
|
|
namespace phoenix {
|
|
|
|
|
|
|
|
static bool Application_keyboardProc(HWND, UINT, WPARAM, LPARAM);
|
|
|
|
static void Application_processDialogMessage(MSG&);
|
2013-12-21 10:45:58 +00:00
|
|
|
static void Application_processMessageQueue();
|
2013-03-15 13:11:33 +00:00
|
|
|
static LRESULT CALLBACK Application_windowProc(HWND, UINT, WPARAM, LPARAM);
|
|
|
|
|
|
|
|
void pApplication::run() {
|
|
|
|
MSG msg;
|
|
|
|
if(Application::main) {
|
|
|
|
while(applicationState.quit == false) {
|
|
|
|
Application::main();
|
|
|
|
processEvents();
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
MSG msg;
|
|
|
|
while(GetMessage(&msg, 0, 0, 0)) {
|
|
|
|
Application_processDialogMessage(msg);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
bool pApplication::pendingEvents() {
|
|
|
|
MSG msg;
|
|
|
|
return PeekMessage(&msg, 0, 0, 0, PM_NOREMOVE);
|
|
|
|
}
|
|
|
|
|
|
|
|
void pApplication::processEvents() {
|
|
|
|
while(pendingEvents()) {
|
|
|
|
MSG msg;
|
|
|
|
if(PeekMessage(&msg, 0, 0, 0, PM_REMOVE)) {
|
|
|
|
Application_processDialogMessage(msg);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-05-02 11:25:45 +00:00
|
|
|
void Application_processDialogMessage(MSG& msg) {
|
2013-03-15 13:11:33 +00:00
|
|
|
if(msg.message == WM_KEYDOWN || msg.message == WM_KEYUP
|
|
|
|
|| msg.message == WM_SYSKEYDOWN || msg.message == WM_SYSKEYUP) {
|
|
|
|
if(Application_keyboardProc(msg.hwnd, msg.message, msg.wParam, msg.lParam)) {
|
|
|
|
DispatchMessage(&msg);
|
2013-12-21 10:45:58 +00:00
|
|
|
return Application_processMessageQueue();
|
2013-03-15 13:11:33 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if(!IsDialogMessage(GetForegroundWindow(), &msg)) {
|
|
|
|
TranslateMessage(&msg);
|
|
|
|
DispatchMessage(&msg);
|
2013-12-21 10:45:58 +00:00
|
|
|
Application_processMessageQueue();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void Application_processMessageQueue() {
|
|
|
|
while(!messageQueue.empty()) {
|
|
|
|
Message message = messageQueue.takeFirst();
|
|
|
|
if(message.type == Message::Type::ListView_OnActivate) {
|
|
|
|
ListView* listView = (ListView*)message.object;
|
|
|
|
if(listView->onActivate) listView->onActivate();
|
|
|
|
}
|
2013-03-15 13:11:33 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void pApplication::quit() {
|
|
|
|
PostQuitMessage(0);
|
|
|
|
}
|
|
|
|
|
|
|
|
void pApplication::initialize() {
|
|
|
|
CoInitialize(0);
|
|
|
|
InitCommonControls();
|
|
|
|
|
|
|
|
WNDCLASS wc;
|
|
|
|
wc.cbClsExtra = 0;
|
|
|
|
wc.cbWndExtra = 0;
|
|
|
|
wc.hbrBackground = GetSysColorBrush(COLOR_3DFACE);
|
|
|
|
wc.hCursor = LoadCursor(0, IDC_ARROW);
|
|
|
|
wc.hIcon = LoadIcon(GetModuleHandle(0), MAKEINTRESOURCE(2));
|
|
|
|
wc.hInstance = GetModuleHandle(0);
|
|
|
|
wc.lpfnWndProc = Application_windowProc;
|
|
|
|
wc.lpszClassName = L"phoenix_window";
|
|
|
|
wc.lpszMenuName = 0;
|
|
|
|
wc.style = CS_HREDRAW | CS_VREDRAW;
|
|
|
|
RegisterClass(&wc);
|
|
|
|
|
|
|
|
wc.cbClsExtra = 0;
|
|
|
|
wc.cbWndExtra = 0;
|
|
|
|
wc.hbrBackground = GetSysColorBrush(COLOR_3DFACE);
|
|
|
|
wc.hCursor = LoadCursor(0, IDC_ARROW);
|
|
|
|
wc.hIcon = LoadIcon(0, IDI_APPLICATION);
|
|
|
|
wc.hInstance = GetModuleHandle(0);
|
|
|
|
wc.lpfnWndProc = Canvas_windowProc;
|
|
|
|
wc.lpszClassName = L"phoenix_canvas";
|
|
|
|
wc.lpszMenuName = 0;
|
|
|
|
wc.style = CS_HREDRAW | CS_VREDRAW;
|
|
|
|
RegisterClass(&wc);
|
|
|
|
|
|
|
|
wc.cbClsExtra = 0;
|
|
|
|
wc.cbWndExtra = 0;
|
|
|
|
wc.hbrBackground = GetSysColorBrush(COLOR_3DFACE);
|
|
|
|
wc.hCursor = LoadCursor(0, IDC_ARROW);
|
|
|
|
wc.hIcon = LoadIcon(0, IDI_APPLICATION);
|
|
|
|
wc.hInstance = GetModuleHandle(0);
|
|
|
|
wc.lpfnWndProc = Label_windowProc;
|
|
|
|
wc.lpszClassName = L"phoenix_label";
|
|
|
|
wc.lpszMenuName = 0;
|
|
|
|
wc.style = CS_HREDRAW | CS_VREDRAW;
|
|
|
|
RegisterClass(&wc);
|
|
|
|
|
|
|
|
wc.cbClsExtra = 0;
|
|
|
|
wc.cbWndExtra = 0;
|
|
|
|
wc.hbrBackground = CreateSolidBrush(RGB(0, 0, 0));
|
|
|
|
wc.hCursor = LoadCursor(0, IDC_ARROW);
|
|
|
|
wc.hIcon = LoadIcon(0, IDI_APPLICATION);
|
|
|
|
wc.hInstance = GetModuleHandle(0);
|
|
|
|
wc.lpfnWndProc = Viewport_windowProc;
|
|
|
|
wc.lpszClassName = L"phoenix_viewport";
|
|
|
|
wc.lpszMenuName = 0;
|
|
|
|
wc.style = CS_HREDRAW | CS_VREDRAW;
|
|
|
|
RegisterClass(&wc);
|
|
|
|
|
|
|
|
settings = new Settings;
|
|
|
|
pKeyboard::initialize();
|
|
|
|
}
|
|
|
|
|
|
|
|
static bool Application_keyboardProc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) {
|
|
|
|
if(msg != WM_KEYDOWN && msg != WM_SYSKEYDOWN && msg != WM_KEYUP && msg != WM_SYSKEYUP) return false;
|
|
|
|
|
|
|
|
GUITHREADINFO info;
|
|
|
|
memset(&info, 0, sizeof(GUITHREADINFO));
|
|
|
|
info.cbSize = sizeof(GUITHREADINFO);
|
|
|
|
GetGUIThreadInfo(GetCurrentThreadId(), &info);
|
2013-05-02 11:25:45 +00:00
|
|
|
Object* object = (Object*)GetWindowLongPtr(info.hwndFocus, GWLP_USERDATA);
|
2013-03-15 13:11:33 +00:00
|
|
|
if(object == nullptr) return false;
|
|
|
|
|
|
|
|
if(dynamic_cast<Window*>(object)) {
|
2013-05-02 11:25:45 +00:00
|
|
|
Window& window = (Window&)*object;
|
2013-03-15 13:11:33 +00:00
|
|
|
if(pWindow::modal.size() > 0 && !pWindow::modal.find(&window.p)) return false;
|
|
|
|
Keyboard::Keycode keysym = Keysym(wparam, lparam);
|
|
|
|
if(keysym != Keyboard::Keycode::None) {
|
|
|
|
if((msg == WM_KEYDOWN || msg == WM_SYSKEYDOWN) && window.onKeyPress) window.onKeyPress(keysym);
|
|
|
|
if((msg == WM_KEYUP || msg == WM_SYSKEYUP) && window.onKeyRelease) window.onKeyRelease(keysym);
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(msg == WM_KEYDOWN) {
|
|
|
|
if(dynamic_cast<ListView*>(object)) {
|
2013-05-02 11:25:45 +00:00
|
|
|
ListView& listView = (ListView&)*object;
|
2013-03-15 13:11:33 +00:00
|
|
|
if(wparam == VK_RETURN) {
|
2013-12-21 10:45:58 +00:00
|
|
|
if(listView.selected()) return true; //returning true generates LVN_ITEMACTIVATE message
|
2013-03-15 13:11:33 +00:00
|
|
|
}
|
|
|
|
} else if(dynamic_cast<LineEdit*>(object)) {
|
2013-05-02 11:25:45 +00:00
|
|
|
LineEdit& lineEdit = (LineEdit&)*object;
|
2013-03-15 13:11:33 +00:00
|
|
|
if(wparam == VK_RETURN) {
|
|
|
|
if(lineEdit.onActivate) lineEdit.onActivate();
|
|
|
|
}
|
|
|
|
} else if(dynamic_cast<TextEdit*>(object)) {
|
2013-05-02 11:25:45 +00:00
|
|
|
TextEdit& textEdit = (TextEdit&)*object;
|
2013-03-15 13:11:33 +00:00
|
|
|
if(wparam == 'A' && GetKeyState(VK_CONTROL) < 0) {
|
|
|
|
//Ctrl+A = select all text
|
|
|
|
//note: this is not a standard accelerator on Windows
|
|
|
|
Edit_SetSel(textEdit.p.hwnd, 0, ~0);
|
|
|
|
return true;
|
|
|
|
} else if(wparam == 'V' && GetKeyState(VK_CONTROL) < 0) {
|
|
|
|
//Ctrl+V = paste text
|
|
|
|
//note: this formats Unix (LF) and OS9 (CR) line-endings to Windows (CR+LF) line-endings
|
|
|
|
//this is necessary as the EDIT control only supports Windows line-endings
|
|
|
|
OpenClipboard(hwnd);
|
|
|
|
HANDLE handle = GetClipboardData(CF_UNICODETEXT);
|
|
|
|
if(handle) {
|
2013-05-02 11:25:45 +00:00
|
|
|
wchar_t* text = (wchar_t*)GlobalLock(handle);
|
2013-03-15 13:11:33 +00:00
|
|
|
if(text) {
|
|
|
|
string data = (const char*)utf8_t(text);
|
|
|
|
data.replace("\r\n", "\n");
|
|
|
|
data.replace("\r", "\n");
|
|
|
|
data.replace("\n", "\r\n");
|
|
|
|
GlobalUnlock(handle);
|
|
|
|
utf16_t output(data);
|
|
|
|
HGLOBAL resource = GlobalAlloc(GMEM_MOVEABLE, (wcslen(output) + 1) * sizeof(wchar_t));
|
|
|
|
if(resource) {
|
2013-05-02 11:25:45 +00:00
|
|
|
wchar_t* write = (wchar_t*)GlobalLock(resource);
|
2013-03-15 13:11:33 +00:00
|
|
|
if(write) {
|
|
|
|
wcscpy(write, output);
|
|
|
|
GlobalUnlock(write);
|
|
|
|
if(SetClipboardData(CF_UNICODETEXT, resource) == FALSE) {
|
|
|
|
GlobalFree(resource);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
CloseClipboard();
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2013-11-28 10:29:01 +00:00
|
|
|
/*case WM_GETMINMAXINFO: {
|
|
|
|
MINMAXINFO* mmi = (MINMAXINFO*)lparam;
|
|
|
|
mmi->ptMinTrackSize.x = 256 + window.p.frameMargin().width;
|
|
|
|
mmi->ptMinTrackSize.y = 256 + window.p.frameMargin().height;
|
|
|
|
return TRUE;
|
|
|
|
break;
|
|
|
|
}*/
|
|
|
|
|
2013-03-15 13:11:33 +00:00
|
|
|
static LRESULT CALLBACK Application_windowProc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) {
|
2013-05-02 11:25:45 +00:00
|
|
|
Object* object = (Object*)GetWindowLongPtr(hwnd, GWLP_USERDATA);
|
2013-11-28 10:29:01 +00:00
|
|
|
if(object == nullptr) return DefWindowProc(hwnd, msg, wparam, lparam);
|
|
|
|
Window& window = dynamic_cast<Window*>(object) ? (Window&)*object : *((Widget*)object)->Sizable::state.window;
|
2013-03-15 13:11:33 +00:00
|
|
|
|
|
|
|
bool process = true;
|
2013-11-28 10:29:01 +00:00
|
|
|
if(!pWindow::modal.empty() && !pWindow::modal.find(&window.p)) process = false;
|
2013-03-15 13:11:33 +00:00
|
|
|
if(applicationState.quit) process = false;
|
2013-11-28 10:29:01 +00:00
|
|
|
if(process == false) return DefWindowProc(hwnd, msg, wparam, lparam);
|
|
|
|
|
|
|
|
switch(msg) {
|
|
|
|
case WM_CLOSE: window.p.onClose(); return TRUE;
|
|
|
|
case WM_MOVE: window.p.onMove(); break;
|
|
|
|
case WM_SIZE: window.p.onSize(); break;
|
|
|
|
case WM_DROPFILES: window.p.onDrop(wparam); return FALSE;
|
|
|
|
case WM_ERASEBKGND: if(window.p.onEraseBackground()) return true; break;
|
|
|
|
case WM_ENTERMENULOOP: case WM_ENTERSIZEMOVE: window.p.onModalBegin(); return FALSE;
|
|
|
|
case WM_EXITMENULOOP: case WM_EXITSIZEMOVE: window.p.onModalEnd(); return FALSE;
|
2013-03-15 13:11:33 +00:00
|
|
|
}
|
|
|
|
|
2013-11-28 10:29:01 +00:00
|
|
|
return Shared_windowProc(DefWindowProc, hwnd, msg, wparam, lparam);
|
2013-03-15 13:11:33 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
}
|