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 = (WNDPROC)WindowProcProxy::call;
280 wc.hInstance = m_instance;
281 wc.hIcon = LoadIcon(NULL, IDI_WINLOGO);
282 wc.hCursor = m_defaultCursor;
283 wc.hbrBackground = (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);
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)))
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 = (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 (
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))
588 return DefWindowProc(hWnd, uMsg, wParam, lParam);
602 if(wParam >= 32 && wParam <= 255) {
626 case WM_SYSKEYDOWN: {
628 return DefWindowProc(hWnd, uMsg, wParam, lParam);
633 case WM_LBUTTONDOWN: {
634 SetCapture(m_window);
651 case WM_MBUTTONDOWN: {
652 SetCapture(m_window);
669 case WM_RBUTTONDOWN: {
670 SetCapture(m_window);
690 Point newMousePos(LOWORD(lParam), HIWORD(lParam));
691 if(newMousePos.x >= 32767)
694 newMousePos.x = std::min<int32>(newMousePos.x,
m_size.
width());
696 if(newMousePos.y >= 32767)
699 newMousePos.y = std::min<int32>(newMousePos.y,
m_size.
height());
707 case WM_MOUSEWHEEL: {
720 case WM_GETMINMAXINFO: {
721 LPMINMAXINFO pMMI = (LPMINMAXINFO)lParam;
723 pMMI->ptMinTrackSize.x = adjustedRect.
width();
724 pMMI->ptMinTrackSize.y = adjustedRect.
height();
728 bool forceResize =
false;
746 internalRestoreGLContext();
748 Size size =
Size(LOWORD(lParam), HIWORD(lParam));
749 size.
setWidth(std::max<int32>(std::min<int32>(size.
width(), 7680), 32));
750 size.
setHeight(std::max<int32>(std::min<int32>(size.
height(), 4320), 32));
760 return DefWindowProc(hWnd, uMsg, wParam, lParam);
769 eglSwapBuffers(m_eglDisplay, m_eglSurface);
771 SwapBuffers(m_deviceContext);
787 MessageBoxW(m_window, stdext::latin1_to_utf16(message).c_str(), L
"FATAL ERROR", MB_OK | MB_ICONERROR);
792 int width = image->getWidth();
793 int height = image->getHeight();
794 int numbits = width * height;
795 int numbytes = (width * height)/8;
797 std::vector<uchar> andMask(numbytes, 0);
798 std::vector<uchar> xorMask(numbytes, 0);
800 for(
int i=0;i<numbits;++i) {
802 if(rgba == 0xffffffff) {
803 HSB_BIT_SET(xorMask, i);
804 }
else if(rgba == 0x00000000) {
805 HSB_BIT_SET(andMask, i);
809 HCURSOR cursor = CreateCursor(m_instance, hotSpot.
x, hotSpot.
y, width, height, &andMask[0], &xorMask[0]);
810 m_cursors.push_back(cursor);
811 return m_cursors.size()-1;
816 if(cursorId >= (
int)m_cursors.size() || cursorId < 0)
819 m_cursor = m_cursors[cursorId];
828 SetCursor(m_defaultCursor);
835 SetWindowTextW(m_window, stdext::latin1_to_utf16(title).c_str());
850 DWORD dwStyle = GetWindowLong(m_window, GWL_STYLE);
851 static WINDOWPLACEMENT wpPrev;
852 wpPrev.length =
sizeof(wpPrev);
856 GetWindowPlacement(m_window, &wpPrev);
857 SetWindowLong(m_window, GWL_STYLE, (dwStyle & ~WS_OVERLAPPEDWINDOW) | WS_POPUP | WS_EX_TOPMOST);
858 SetWindowPos(m_window, HWND_TOPMOST, 0, 0, size.
width(), size.
height(), SWP_FRAMECHANGED);
860 SetWindowLong(m_window, GWL_STYLE, (dwStyle & ~(WS_POPUP | WS_EX_TOPMOST)) | WS_OVERLAPPEDWINDOW);
861 SetWindowPlacement(m_window, &wpPrev);
862 SetWindowPos(m_window, HWND_NOTOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_FRAMECHANGED);
869 eglSwapInterval(m_eglDisplay, enable ? 1 : 0);
871 if(!isExtensionSupported(
"WGL_EXT_swap_control"))
874 typedef BOOL (WINAPI * wglSwapIntervalProc)(int);
875 wglSwapIntervalProc wglSwapInterval = (wglSwapIntervalProc)getExtensionProcAddress(
"wglSwapIntervalEXT");
879 wglSwapInterval(enable ? 1 : 0);
892 if(image->getBpp() != 4) {
897 int n = image->getWidth() * image->getHeight();
898 std::vector<uint32> iconData(n);
899 for(
int i=0; i < n;++i) {
901 pixel[2] = *(image->getPixelData() + (i * 4) + 0);
902 pixel[1] = *(image->getPixelData() + (i * 4) + 1);
903 pixel[0] = *(image->getPixelData() + (i * 4) + 2);
904 pixel[3] = *(image->getPixelData() + (i * 4) + 3);
907 HBITMAP hbmColor = CreateBitmap(image->getWidth(), image->getHeight(), 1, 32, &iconData[0]);
908 HBITMAP hbmMask = CreateCompatibleBitmap(GetDC(NULL), image->getWidth(), image->getHeight());
912 ii.hbmColor = hbmColor;
913 ii.hbmMask = hbmMask;
917 HICON icon = CreateIconIndirect(&ii);
918 DeleteObject(hbmMask);
919 DeleteObject(hbmColor);
921 SendMessage(m_window, WM_SETICON, ICON_SMALL, (LPARAM)icon);
922 SendMessage(m_window, WM_SETICON, ICON_BIG, (LPARAM)icon);
927 if(!OpenClipboard(m_window))
930 HGLOBAL hglb = GlobalAlloc(GMEM_MOVEABLE, (text.length() + 1) *
sizeof(WCHAR));
934 std::wstring wtext = stdext::latin1_to_utf16(text);
936 LPWSTR lpwstr = (LPWSTR)GlobalLock(hglb);
937 memcpy(lpwstr, (
char*)&wtext[0], wtext.length() *
sizeof(WCHAR));
938 lpwstr[text.length()] = (WCHAR)0;
942 SetClipboardData(CF_UNICODETEXT, hglb);
948 return Size(GetSystemMetrics(SM_CXSCREEN), GetSystemMetrics(SM_CYSCREEN));
955 if(!OpenClipboard(m_window))
958 HGLOBAL hglb = GetClipboardData(CF_UNICODETEXT);
960 LPWSTR lpwstr = (LPWSTR)GlobalLock(hglb);
962 text = stdext::utf16_to_latin1(lpwstr);
980 Rect WIN32Window::getClientRect()
983 RECT clientRect = {0,0,0,0};
984 int ret = GetClientRect(m_window, &clientRect);
986 return Rect(
Point(clientRect.left, clientRect.top),
Point(clientRect.right, clientRect.bottom));
992 Rect WIN32Window::getWindowRect()
995 RECT windowRect = {0,0,0,0};
996 int ret = GetWindowRect(m_window, &windowRect);
998 return Rect(
Point(windowRect.left, windowRect.top),
Point(windowRect.right, windowRect.bottom));
1000 return adjustWindowRect(getClientRect());
1004 Rect WIN32Window::adjustWindowRect(
const Rect& clientRect)
1009 RECT windowRect = { clientRect.
left(), clientRect.
top(), clientRect.
right(), clientRect.
bottom() };
1011 dwStyle = GetWindowLong(m_window, GWL_STYLE);
1012 dwExStyle = GetWindowLong(m_window, GWL_EXSTYLE);
1014 dwStyle = WS_OVERLAPPEDWINDOW;
1015 dwExStyle = WS_EX_APPWINDOW | WS_EX_WINDOWEDGE;
1017 if(AdjustWindowRectEx(&windowRect, dwStyle, FALSE, dwExStyle) != 0) {
1018 rect =
Rect(
Point(windowRect.left, windowRect.top),
Point(windowRect.right, windowRect.bottom));
1020 g_logger.traceError(
"AdjustWindowRectEx failed");