1 module ws.wm.win32.wm; 2 3 version(Windows): 4 5 import 6 std.utf, 7 8 ws.list, 9 ws.log, 10 ws.gui.input, 11 ws.wm.win32.api, 12 ws.wm.win32.window, 13 ws.wm.baseWindowManager, 14 ws.wm; 15 16 __gshared: 17 18 19 class Win32WindowManager: BaseWindowManager { 20 21 T_wglChoosePixelFormatARB wglChoosePixelFormatARB; 22 T_wglCreateContextAttribsARB wglCreateContextAttribsARB; 23 24 HINSTANCE appInstance; 25 WNDCLASSW windowClass = {0}; 26 27 void load(string s)(){ 28 auto ptr = core.sys.windows.wingdi.wglGetProcAddress(s); 29 if(!ptr) 30 throw new Exception("failed to get function \"" ~ s ~ "\""); 31 mixin(s ~ " = cast(typeof(" ~ s ~ "))ptr;"); 32 } 33 34 this(){ 35 super(); 36 DerelictGL3.load(); 37 appInstance = GetModuleHandleW(null); 38 39 windowClass.lpfnWndProc = cast(WNDPROC)&internalEvents; 40 windowClass.hInstance = appInstance; 41 windowClass.hIcon = LoadIconA(null, IDI_APPLICATION); 42 windowClass.hCursor = LoadCursorA(null, IDC_ARROW); 43 windowClass.hbrBackground = cast(HBRUSH)GetStockObject(BLACK_BRUSH); 44 windowClass.lpszClassName = "wm::windowClass".toUTF16z(); 45 windowClass.style = CS_OWNDC; 46 RegisterClassW(&windowClass); 47 // the following is solely to retrieve wglChoosePixelFormat && wglCreateContext 48 HWND dummyWindow = CreateWindowExA( 49 0, "STATIC", "", WS_POPUP | WS_DISABLED, 50 0, 0, 1, 1, null, null, appInstance, null 51 ); 52 PIXELFORMATDESCRIPTOR dummyFormatDescriptor = { 53 (PIXELFORMATDESCRIPTOR).sizeof, 1, 4 | 32 | 1, 0, 8, 0, 54 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 8, 0, 0, 0, 0, 0, 0 55 }; 56 HDC dummyDeviceContext = GetDC(dummyWindow); 57 int pixelFormat = ChoosePixelFormat(dummyDeviceContext, &dummyFormatDescriptor); 58 SetPixelFormat(dummyDeviceContext, pixelFormat, &dummyFormatDescriptor); 59 HGLRC dummyContext = wglCreateContext(dummyDeviceContext); 60 wglMakeCurrent(dummyDeviceContext, dummyContext); 61 try { 62 load!"wglChoosePixelFormatARB"(); 63 load!"wglCreateContextAttribsARB"(); 64 } catch (Exception e) 65 throw new Exception("OpenGL 3.3 not supported"); 66 wglMakeCurrent(null, null); 67 wglDeleteContext(dummyContext); 68 ReleaseDC(dummyWindow, dummyDeviceContext); 69 DestroyWindow(dummyWindow); 70 } 71 72 HINSTANCE getInstance(){ 73 return appInstance; 74 } 75 76 Window[] systemWindows(){ 77 Window[] list; 78 HWND h = GetTopWindow(null); 79 while(h){ 80 list ~= new Win32Window(h); 81 h = GetWindow(h, 2); 82 } 83 return list; 84 } 85 86 void processEvents(){ 87 MSG msg; 88 while(PeekMessageA(&msg, null, 0, 0, PM_REMOVE)){ 89 TranslateMessage(&msg); 90 DispatchMessageA(&msg); 91 } 92 foreach(window; windows){ 93 activeWindow = window; 94 window.processEvents; 95 } 96 } 97 98 long[2] getCursorPos(){ 99 POINT point; 100 GetCursorPos(&point); 101 return [point.x, point.y]; 102 } 103 104 Win32Window findWindow(string title){ 105 HWND window = FindWindowW(null, title.toUTF16z()); 106 if(!window) 107 throw new WindowNotFound("Could not find window \"" ~ title ~ "\""); 108 return new Win32Window(window); 109 } 110 111 bool isKeyDown(Keyboard.key key){ 112 return GetKeyState(cast(int)key) < 0; 113 } 114 115 } 116 117 118 protected: 119 120 static HCURSOR getCursor(int i){ 121 return cast(LPWSTR)(cast(DWORD)(cast(WORD)i)); 122 } 123 124 HCURSOR[] MOUSE_CURSOR_TO_HCUR = [ 125 getCursor(32512), // IDC_ARROW 126 getCursor(32516), // IDC_UPARROW 127 128 getCursor(32513), // IDC_BEAM 129 130 getCursor(32646), // IDC_SIZEALL 131 getCursor(32645), // IDC_SIZENS 132 getCursor(32644), // IDC_SIZEWE 133 getCursor(32642), // IDC_SIZENWSE 134 getCursor(32643), // IDC_SIZENESW 135 getCursor(32643), // IDC_SIZENESW 136 getCursor(32642), // IDC_SIZENWSE 137 138 getCursor(32649), // IDC_HAND 139 140 getCursor(32512), // IDC_ARROW 141 null, 142 ]; 143 144 extern(Windows) 145 static LRESULT internalEvents(HWND window, UINT msg, WPARAM wpar, LPARAM lpar) nothrow { 146 try { 147 foreach(w; cast(List!Win32Window)wm.windows){ 148 if(w.handle == window){ 149 w.addEvent(Event(msg, wpar, lpar)); 150 if(msg == WM_CLOSE) 151 return 0; 152 } 153 } 154 } catch(Throwable) 155 assert(0); 156 return DefWindowProcW(window, msg, wpar, lpar); 157 } 158