1 module iota.etc.window; 2 3 version (Windows) { 4 import core.sys.windows.windows; 5 import core.sys.windows.wtypes; 6 } 7 import std.utf : toUTF16z; 8 import std.algorithm.searching; 9 public import iota.etc.vers; 10 11 public enum MessageWindowType { 12 init, 13 } 14 /** 15 * Implements Window handles for GUI apps. 16 */ 17 version (Windows) { 18 alias WindowH = HWND; 19 } else { 20 alias WindowH = void*; 21 } 22 /** 23 * Used for automatic reference counting for window handles. 24 */ 25 public WindowH[] allAppWindows; 26 27 shared static ~this() { 28 foreach (WindowH w ; allAppWindows) { 29 version (Windows) 30 DestroyWindow(w); 31 } 32 } 33 /** 34 * Returns the handle of the currently active Window. 35 */ 36 public WindowH getActiveWindowH() @nogc nothrow { 37 version (Windows) { 38 return GetActiveWindow(); 39 } else { 40 return null; 41 } 42 } 43 /** 44 * Window style identifiers. 45 * These can be supplied to the createWindow function in an array, then the desired window will be created. 46 */ 47 public enum WindowStyleIDs { 48 Border, 49 Caption, 50 Child, 51 Parent, 52 Disabled, 53 Resizable, 54 Minimized, 55 Maximized, 56 MinimizeBtn, 57 MaximizeBtn, 58 PopUp, 59 Visible, 60 Default, 61 } 62 /** 63 * Creates a window and returns its handle, while also saving its reference for later and to safe and automatic 64 * deallocation. 65 * Params: 66 * title = The title of the window. 67 * x = X position of the window, or -1 for OS default. 68 * y = Y position of the window, or -1 for OS default. 69 * width = Width of the window, or -1 for OS default. 70 * height = Height of the window, or -1 for OS default. 71 * parent = Parent if there's any 72 * styleIDs = Style identifiers, see enum `WindowStyleIDs` for details. 73 * Returns: The Window handle, or null if an error have happened. 74 * Note: Only some basic functionality can be accessed from here. More advanced functionality is out of scope of this 75 * library to minimize its complexity, and it's not supposed to be a GUI library. However, function `addWindow` will 76 * add any window handle to the reference counting if needed. 77 */ 78 public WindowH createWindow(io_str_t title, int x, int y, int width, int height, WindowH parent = null, 79 uint[] styleIDs = [WindowStyleIDs.Default]) { 80 version (Windows) { 81 LPCTSTR name = toUTF16z(title); 82 WNDCLASSEXW clsReg; 83 clsReg.cbSize = cast(UINT)WNDCLASSEXW.sizeof; 84 clsReg.lpfnWndProc = &wndprocCallback; 85 clsReg.lpszClassName = name; 86 uint clsRegResult = RegisterClassExW(&clsReg); 87 if (!clsRegResult) return null; 88 89 90 DWORD flags; 91 foreach (uint i ; styleIDs) { 92 switch(i) { 93 case WindowStyleIDs.Border: 94 flags |= WS_BORDER; 95 break; 96 case WindowStyleIDs.Caption: 97 flags |= WS_CAPTION; 98 break; 99 case WindowStyleIDs.Child: 100 flags |= WS_CHILD; 101 break; 102 case WindowStyleIDs.Disabled: 103 flags |= WS_DISABLED; 104 break; 105 case WindowStyleIDs.Resizable: 106 flags |= WS_THICKFRAME; 107 break; 108 case WindowStyleIDs.Maximized: 109 flags |= WS_MAXIMIZE; 110 break; 111 case WindowStyleIDs.Minimized: 112 flags |= WS_MINIMIZE; 113 break; 114 case WindowStyleIDs.MaximizeBtn: 115 flags |= WS_MAXIMIZEBOX | WS_SYSMENU; 116 break; 117 case WindowStyleIDs.MinimizeBtn: 118 flags |= WS_MINIMIZEBOX | WS_SYSMENU; 119 break; 120 case WindowStyleIDs.PopUp: 121 flags |= WS_POPUPWINDOW; 122 break; 123 case WindowStyleIDs.Visible: 124 flags |= WS_VISIBLE; 125 break; 126 case WindowStyleIDs.Default: 127 flags |= WS_TILEDWINDOW | WS_VISIBLE; 128 break; 129 default: 130 break; 131 } 132 } 133 if (x == -1) x = CW_USEDEFAULT; 134 if (y == -1) y = CW_USEDEFAULT; 135 if (width == -1) width = CW_USEDEFAULT; 136 if (height == -1) height = CW_USEDEFAULT; 137 WindowH handle; 138 139 handle = CreateWindowW(name, name, flags, x, y, width, height, parent, 140 null, null, null); 141 if (handle) 142 allAppWindows ~= handle; 143 return handle; 144 } else { 145 return null; 146 } 147 } 148 /** 149 * Adds a non-library created window handle to its references to cooperation with the library. 150 * Params: 151 * ext = The window handle that needs to be added. 152 * Returns: The reference, or null if either already added or an error happened. 153 */ 154 public WindowH addWindowRef(WindowH ext) nothrow { 155 try { 156 if (!count(allAppWindows, ext)) { 157 allAppWindows ~= ext; 158 return ext; 159 } else { 160 return null; 161 } 162 } catch (Exception e) { //The count function should not throw, but still let know the user that some error have happened 163 return null; 164 } 165 } 166 version (Windows) { 167 ///As of now, this works as a dummy function. If more functionality needed in the future, then it might become part 168 ///of a class. 169 extern (Windows) LRESULT wndprocCallback(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) nothrow @system { 170 return LRESULT.init; 171 } 172 }