30 #define HSB_BIT_SET(p, n) (p[(n)/8] |= (128 >>((n)%8)))
205 m_instance = GetModuleHandle(NULL);
208 m_d3d = Direct3DCreate9(D3D_SDK_VERSION);
210 D3DPRESENT_PARAMETERS d3dpp;
212 ZeroMemory(&d3dpp,
sizeof(d3dpp));
213 d3dpp.Windowed = TRUE;
214 d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
215 d3dpp.hDeviceWindow = m_window;
218 m_d3d->CreateDevice(D3DADAPTER_DEFAULT,
221 D3DCREATE_SOFTWARE_VERTEXPROCESSING,
227 internalCreateWindow();
228 internalCreateGLContext();
229 internalRestoreGLContext();
235 if (m_defaultCursor) {
236 DestroyCursor(m_defaultCursor);
237 m_defaultCursor = NULL;
240 for (HCURSOR& cursor : m_cursors)
241 DestroyCursor(cursor);
244 internalDestroyGLContext();
246 if (m_deviceContext) {
247 if (!ReleaseDC(m_window, m_deviceContext))
249 m_deviceContext = NULL;
253 if (!DestroyWindow(m_window))
265 struct WindowProcProxy {
266 static LRESULT CALLBACK call(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {
268 return window->windowProc(hWnd, uMsg, wParam, lParam);
272 void WIN32Window::internalCreateWindow()
274 m_defaultCursor = LoadCursor(NULL, IDC_ARROW);
276 wc.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC;
277 wc.lpfnWndProc =
static_cast<WNDPROC
>(WindowProcProxy::call);
280 wc.hInstance = m_instance;
281 wc.hIcon = LoadIcon(NULL, IDI_WINLOGO);
282 wc.hCursor = m_defaultCursor;
283 wc.hbrBackground =
static_cast<HBRUSH
>(GetStockObject(WHITE_BRUSH));
284 wc.lpszMenuName = NULL;
287 if (!RegisterClassA(&wc))
289 DWORD dwExStyle = WS_EX_APPWINDOW | WS_EX_WINDOWEDGE;
290 DWORD dwStyle = WS_OVERLAPPEDWINDOW;
298 m_window = CreateWindowExA(dwExStyle,
314 ShowWindow(m_window, SW_HIDE);
316 m_deviceContext = GetDC(m_window);
317 if (!m_deviceContext)
321 void WIN32Window::internalCreateGLContext()
324 m_eglDisplay = eglGetDisplay(m_deviceContext);
325 if (m_eglDisplay == EGL_NO_DISPLAY)
328 if (!eglInitialize(m_eglDisplay, NULL, NULL))
331 static int configList[] = {
333 EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
335 EGL_RENDERABLE_TYPE, EGL_OPENGL_ES_BIT,
346 if (!eglGetConfigs(m_eglDisplay, NULL, 0, &numConfig))
349 if (!eglChooseConfig(m_eglDisplay, configList, &m_eglConfig, 1, &numConfig))
355 EGLint contextAtrrList[] = {
357 EGL_CONTEXT_CLIENT_VERSION, 2,
359 EGL_CONTEXT_CLIENT_VERSION, 1,
364 m_eglSurface = eglCreateWindowSurface(m_eglDisplay, m_eglConfig, m_window, NULL);
365 if (m_eglSurface == EGL_NO_SURFACE)
368 m_eglContext = eglCreateContext(m_eglDisplay, m_eglConfig, EGL_NO_CONTEXT, contextAtrrList);
369 if (m_eglContext == EGL_NO_CONTEXT)
374 static PIXELFORMATDESCRIPTOR pfd = {
sizeof(PIXELFORMATDESCRIPTOR),
376 PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER,
391 pixelFormat = ChoosePixelFormat(m_deviceContext, &pfd);
395 if (!SetPixelFormat(m_deviceContext, pixelFormat, &pfd))
398 if ((m_wglContext = wglCreateContext(m_deviceContext)) ==
nullptr)
403 void WIN32Window::internalDestroyGLContext()
408 eglDestroyContext(m_eglDisplay, m_eglContext);
412 eglDestroySurface(m_eglDisplay, m_eglSurface);
415 eglTerminate(m_eglDisplay);
420 if (!wglMakeCurrent(NULL, NULL))
422 if (!wglDeleteContext(m_wglContext))
429 void WIN32Window::internalRestoreGLContext()
432 if (!eglMakeCurrent(m_eglDisplay, m_eglSurface, m_eglSurface, m_eglContext))
435 if (!wglMakeCurrent(m_deviceContext, m_wglContext))
440 bool WIN32Window::isExtensionSupported(
const char* ext)
446 typedef const char* (WINAPI* wglGetExtensionsStringProc)();
447 wglGetExtensionsStringProc wglGetExtensionsString =
static_cast<wglGetExtensionsStringProc
>(getExtensionProcAddress(
"wglGetExtensionsStringEXT"));
448 if (!wglGetExtensionsString)
451 const char* exts = wglGetExtensionsString();
452 if (exts && strstr(exts, ext))
459 void* WIN32Window::getExtensionProcAddress(
const char* ext)
465 return static_cast<void*
>(wglGetProcAddress(ext));
471 Rect clientRect(pos, getClientRect().size());
472 Rect windowRect = adjustWindowRect(clientRect);
473 MoveWindow(m_window, windowRect.
x(), windowRect.
y(), windowRect.
width(), windowRect.
height(), TRUE);
475 ShowWindow(m_window, SW_HIDE);
482 Rect clientRect(getClientRect().topLeft(), size);
483 Rect windowRect = adjustWindowRect(clientRect);
484 MoveWindow(m_window, windowRect.
x(), windowRect.
y(), windowRect.
width(), windowRect.
height(), TRUE);
486 ShowWindow(m_window, SW_HIDE);
493 ShowWindow(m_window, SW_MAXIMIZE);
495 ShowWindow(m_window, SW_SHOW);
501 ShowWindow(m_window, SW_HIDE);
507 ShowWindow(m_window, SW_MAXIMIZE);
517 while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) {
518 TranslateMessage(&msg);
519 DispatchMessage(&msg);
525 Fw::Key WIN32Window::retranslateVirtualKey(WPARAM wParam, LPARAM lParam)
528 if ((wParam >= VK_NUMPAD0 && wParam <= VK_NUMPAD9) || wParam == VK_SEPARATOR)
532 if (!(((HIWORD(lParam) >> 8) & 0xFF) & 1)) {
533 bool numlockOn = GetKeyState(VK_NUMLOCK);
570 #define IsKeyDown(a) (GetKeyState(a) & 0x80)
572 LRESULT WIN32Window::windowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
575 if (IsKeyDown(VK_CONTROL))
577 if (IsKeyDown(VK_SHIFT))
579 if (IsKeyDown(VK_MENU))
589 return DefWindowProc(hWnd, uMsg, wParam, lParam);
606 if (wParam >= 32 && wParam <= 255) {
637 return DefWindowProc(hWnd, uMsg, wParam, lParam);
644 SetCapture(m_window);
664 SetCapture(m_window);
684 SetCapture(m_window);
706 Point newMousePos(LOWORD(lParam), HIWORD(lParam));
707 if (newMousePos.x >= 32767)
710 newMousePos.x = std::min<int32>(newMousePos.x,
m_size.
width());
712 if (newMousePos.y >= 32767)
715 newMousePos.y = std::min<int32>(newMousePos.y,
m_size.
height());
738 case WM_GETMINMAXINFO:
740 LPMINMAXINFO pMMI = (LPMINMAXINFO)lParam;
742 pMMI->ptMinTrackSize.x = adjustedRect.
width();
743 pMMI->ptMinTrackSize.y = adjustedRect.
height();
748 bool forceResize =
false;
766 internalRestoreGLContext();
768 Size size =
Size(LOWORD(lParam), HIWORD(lParam));
769 size.
setWidth(std::max<int32>(std::min<int32>(size.
width(), 7680), 32));
770 size.
setHeight(std::max<int32>(std::min<int32>(size.
height(), 4320), 32));
780 return DefWindowProc(hWnd, uMsg, wParam, lParam);
789 eglSwapBuffers(m_eglDisplay, m_eglSurface);
791 SwapBuffers(m_deviceContext);
807 MessageBoxW(m_window, stdext::latin1_to_utf16(message).c_str(), L
"FATAL ERROR", MB_OK | MB_ICONERROR);
812 int width = image->getWidth();
813 int height = image->getHeight();
814 int numbits = width * height;
815 int numbytes = (width * height) / 8;
817 std::vector<uchar> andMask(numbytes, 0);
818 std::vector<uchar> xorMask(numbytes, 0);
820 for (
int i = 0; i < numbits; ++i) {
822 if (rgba == 0xffffffff) {
823 HSB_BIT_SET(xorMask, i);
825 else if (rgba == 0x00000000) {
826 HSB_BIT_SET(andMask, i);
830 HCURSOR cursor = CreateCursor(m_instance, hotSpot.
x, hotSpot.
y, width, height, &andMask[0], &xorMask[0]);
831 m_cursors.push_back(cursor);
832 return m_cursors.size() - 1;
837 if (cursorId >=
static_cast<int>(m_cursors.size()) || cursorId < 0)
840 m_cursor = m_cursors[cursorId];
849 SetCursor(m_defaultCursor);
856 SetWindowTextW(m_window, stdext::latin1_to_utf16(title).c_str());
871 DWORD dwStyle = GetWindowLong(m_window, GWL_STYLE);
872 static WINDOWPLACEMENT wpPrev;
873 wpPrev.length =
sizeof(wpPrev);
877 GetWindowPlacement(m_window, &wpPrev);
878 SetWindowLong(m_window, GWL_STYLE, (dwStyle & ~WS_OVERLAPPEDWINDOW) | WS_POPUP | WS_EX_TOPMOST);
879 SetWindowPos(m_window, HWND_TOPMOST, 0, 0, size.
width(), size.
height(), SWP_FRAMECHANGED);
882 SetWindowLong(m_window, GWL_STYLE, (dwStyle & ~(WS_POPUP | WS_EX_TOPMOST)) | WS_OVERLAPPEDWINDOW);
883 SetWindowPlacement(m_window, &wpPrev);
884 SetWindowPos(m_window, HWND_NOTOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_FRAMECHANGED);
891 eglSwapInterval(m_eglDisplay, enable ? 1 : 0);
893 if (!isExtensionSupported(
"WGL_EXT_swap_control"))
896 typedef BOOL(WINAPI* wglSwapIntervalProc)(int);
897 wglSwapIntervalProc wglSwapInterval =
static_cast<wglSwapIntervalProc
>(getExtensionProcAddress(
"wglSwapIntervalEXT"));
898 if (!wglSwapInterval)
901 wglSwapInterval(enable ? 1 : 0);
914 if (image->getBpp() != 4) {
919 int n = image->getWidth() * image->getHeight();
920 std::vector<uint32> iconData(n);
921 for (
int i = 0; i < n; ++i) {
923 pixel[2] = *(image->getPixelData() + (i * 4) + 0);
924 pixel[1] = *(image->getPixelData() + (i * 4) + 1);
925 pixel[0] = *(image->getPixelData() + (i * 4) + 2);
926 pixel[3] = *(image->getPixelData() + (i * 4) + 3);
929 HBITMAP hbmColor = CreateBitmap(image->getWidth(), image->getHeight(), 1, 32, &iconData[0]);
930 HBITMAP hbmMask = CreateCompatibleBitmap(GetDC(NULL), image->getWidth(), image->getHeight());
934 ii.hbmColor = hbmColor;
935 ii.hbmMask = hbmMask;
939 HICON icon = CreateIconIndirect(&ii);
940 DeleteObject(hbmMask);
941 DeleteObject(hbmColor);
943 SendMessage(m_window, WM_SETICON, ICON_SMALL, (LPARAM)icon);
944 SendMessage(m_window, WM_SETICON, ICON_BIG, (LPARAM)icon);
949 if (!OpenClipboard(m_window))
952 HGLOBAL hglb = GlobalAlloc(GMEM_MOVEABLE, (text.length() + 1) *
sizeof(WCHAR));
956 std::wstring wtext = stdext::latin1_to_utf16(text);
958 LPWSTR lpwstr =
static_cast<LPWSTR
>(GlobalLock(hglb));
959 memcpy(lpwstr, (
char*)&wtext[0], wtext.length() *
sizeof(WCHAR));
960 lpwstr[text.length()] =
static_cast<WCHAR
>(0);
964 SetClipboardData(CF_UNICODETEXT, hglb);
970 return Size(GetSystemMetrics(SM_CXSCREEN), GetSystemMetrics(SM_CYSCREEN));
977 if (!OpenClipboard(m_window))
980 HGLOBAL hglb = GetClipboardData(CF_UNICODETEXT);
982 LPWSTR lpwstr =
static_cast<LPWSTR
>(GlobalLock(hglb));
984 text = stdext::utf16_to_latin1(lpwstr);
1002 Rect WIN32Window::getClientRect()
1005 RECT clientRect = { 0,0,0,0 };
1006 int ret = GetClientRect(m_window, &clientRect);
1008 return Rect(
Point(clientRect.left, clientRect.top),
Point(clientRect.right, clientRect.bottom));
1015 Rect WIN32Window::getWindowRect()
1018 RECT windowRect = { 0,0,0,0 };
1019 int ret = GetWindowRect(m_window, &windowRect);
1021 return Rect(
Point(windowRect.left, windowRect.top),
Point(windowRect.right, windowRect.bottom));
1024 return adjustWindowRect(getClientRect());
1028 Rect WIN32Window::adjustWindowRect(
const Rect& clientRect)
1033 RECT windowRect = { clientRect.
left(), clientRect.
top(), clientRect.
right(), clientRect.
bottom() };
1035 dwStyle = GetWindowLong(m_window, GWL_STYLE);
1036 dwExStyle = GetWindowLong(m_window, GWL_EXSTYLE);
1039 dwStyle = WS_OVERLAPPEDWINDOW;
1040 dwExStyle = WS_EX_APPWINDOW | WS_EX_WINDOWEDGE;
1042 if (AdjustWindowRectEx(&windowRect, dwStyle, FALSE, dwExStyle) != 0) {
1043 rect =
Rect(
Point(windowRect.left, windowRect.top),
Point(windowRect.right, windowRect.bottom));
1046 g_logger.traceError(
"AdjustWindowRectEx failed");