1 module ws.wm.win32.window; 2 3 version(Windows): 4 5 import 6 std.conv, 7 std.string, 8 std.utf, 9 10 ws.string, 11 ws.list, 12 ws.gui.base, 13 ws.draw, 14 ws.wm.win32.api, 15 ws.wm.win32.wm, 16 ws.wm; 17 18 __gshared: 19 20 21 class Win32Window: Base { 22 23 Mouse.cursor cursor = Mouse.cursor.inherit; 24 string title; 25 WindowHandle windowHandle; 26 List!Event eventQueue; 27 28 int antiAliasing = 1; 29 HDC deviceContext; 30 31 bool hasMouse; 32 bool _hasFocus; 33 Base _dragging; 34 bool draggingUnfocus; 35 int[2] _cursorPos; 36 37 bool isActive = true; 38 DrawEmpty _draw; 39 40 this(WindowHandle handle){ 41 windowHandle = handle; 42 } 43 44 this(int w, int h, string t){ 45 title = t; 46 size = [w, h]; 47 RECT targetSize = {0, 0, size.w, size.h}; 48 AdjustWindowRect(&targetSize, WS_OVERLAPPEDWINDOW, false); 49 windowHandle = CreateWindowExW( 50 0, wm.windowClass.lpszClassName, title.toUTF16z(), 51 WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, 52 targetSize.right-targetSize.left, targetSize.bottom-targetSize.top, 53 null, null, wm.getInstance, null 54 ); 55 if(!windowHandle) 56 throw new Exception("CreateWindowW failed"); 57 RECT r; 58 GetWindowRect(windowHandle, &r); 59 pos = [r.left, r.right]; 60 61 drawInit; 62 63 RAWINPUTDEVICE rawMouseDevice; 64 rawMouseDevice.usUsagePage = 0x01; 65 rawMouseDevice.usUsage = 0x02; 66 rawMouseDevice.hwndTarget = windowHandle; 67 if(!RegisterRawInputDevices(&rawMouseDevice, 1, RAWINPUTDEVICE.sizeof)) 68 throw new Exception("Failed to register RID"); 69 70 if(GetFocus == windowHandle) 71 onKeyboardFocus(true); 72 73 hidden = true; 74 show; 75 } 76 77 override DrawEmpty draw(){ 78 return _draw; 79 } 80 81 void draw(DrawEmpty draw){ 82 _draw = draw; 83 } 84 85 @property 86 WindowHandle handle(){ 87 return windowHandle; 88 } 89 90 override void show(){ 91 if(!hidden) 92 return; 93 ShowWindow(windowHandle, SW_SHOWNORMAL); 94 UpdateWindow(windowHandle); 95 onKeyboardFocus(true); 96 resized(size); 97 super.show; 98 } 99 100 override void hide(){ 101 if(hidden) 102 return; 103 DestroyWindow(windowHandle); 104 super.hide; 105 } 106 107 override void resize(int[2] size){ 108 SetWindowPos(windowHandle, null, 0, 0, size.w, size.h, SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE); 109 } 110 111 void onDestroy(){ 112 isActive = false; 113 draw.destroy; 114 } 115 116 override void onShow(){ 117 hidden = false; 118 resized(size); 119 } 120 121 void resized(int[2] size){ 122 this.size = size; 123 if(draw) 124 draw.resize(size); 125 } 126 127 void setTitle(string title){ 128 this.title = title; 129 SetWindowTextW(windowHandle, title.toUTF16z()); 130 } 131 132 string getTitle(){ 133 wchar[512] str; 134 int r = GetWindowTextW(windowHandle, str.ptr, str.length); 135 return to!string(str[0..r]); 136 } 137 138 long getPid(){ 139 DWORD pid; 140 DWORD threadId = GetWindowThreadProcessId(windowHandle, &pid); 141 return pid; 142 } 143 144 @property 145 override bool hasFocus(){ 146 return _hasFocus; 147 } 148 149 override void onKeyboardFocus(bool focus){ 150 _hasFocus = focus; 151 } 152 153 void swapBuffers(){ 154 SwapBuffers(deviceContext); 155 } 156 157 override void onDraw(){ 158 super.onDraw; 159 draw.finishFrame; 160 } 161 162 void onRawMouse(int x, int y){} 163 164 void setActive(){ 165 wm.activeWindow = this; 166 } 167 168 override void setCursor(Mouse.cursor cursor){ 169 HCURSOR hcur = null; 170 if(cursor != Mouse.cursor.none) 171 hcur = LoadCursorW(null, cast(const(wchar)*)MOUSE_CURSOR_TO_HCUR[cast(int)cursor]); 172 this.cursor = cursor; 173 SetCursor(hcur); 174 SetClassLongW(windowHandle, -12, cast(LONG)cast(LONG_PTR)hcur); 175 } 176 177 void setCursorPos(int x, int y){ 178 POINT p = {cast(long)x, cast(long)y}; 179 ClientToScreen(windowHandle, &p); 180 SetCursorPos(p.x, p.y); 181 } 182 183 184 void sendMessage(uint message, WPARAM wpar, LPARAM lpar){ 185 SendMessageA(windowHandle, message, wpar, lpar); 186 } 187 188 /+ 189 void setTop(){ 190 SetForegroundWindow(windowHandle); 191 } 192 +/ 193 194 void drawInit(){ 195 //_draw = new GlDraw; 196 } 197 198 override int[2] cursorPos(){ 199 return _cursorPos; 200 } 201 202 override Base draggingChild(){ 203 return _dragging; 204 } 205 206 override void onMouseMove(int x, int y){ 207 _cursorPos = [x, y]; 208 super.onMouseMove(x, y); 209 } 210 211 override void onMouseButton(Mouse.button button, bool pressed, int x, int y){ 212 if(button == Mouse.buttonLeft){ 213 if(pressed){ 214 auto child = mouseChild; 215 while(child && child.mouseChild){ 216 child = child.mouseChild; 217 } 218 _dragging = child; 219 }else{ 220 _dragging = null; 221 if(draggingUnfocus){ 222 onMouseFocus(false); 223 } 224 } 225 } 226 super.onMouseButton(button, pressed, x, y); 227 } 228 229 } 230 231 232 string getLastError(){ 233 DWORD errcode = GetLastError(); 234 if(!errcode) 235 return "No error"; 236 LPCSTR msgBuf; 237 DWORD i = FormatMessageA( 238 cast(uint)( 239 FORMAT_MESSAGE_ALLOCATE_BUFFER | 240 FORMAT_MESSAGE_FROM_SYSTEM | 241 FORMAT_MESSAGE_IGNORE_INSERTS), 242 null, 243 errcode, 244 cast(uint)MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), 245 cast(LPSTR)&msgBuf, 246 0, 247 null 248 ); 249 string text = to!string(msgBuf); 250 LocalFree(cast(HLOCAL)msgBuf); 251 return text; 252 }