1 // Written by Christopher E. Miller 2 // See the included license.txt for copyright and license details. 3 4 module dfl.resources; 5 import core.sys.windows.windows; 6 7 import dfl.base; 8 import dfl.drawing; 9 import dfl.exception; 10 import dfl.internal.dlib; 11 import dfl.internal.utf; 12 13 version (DFL_NO_RESOURCES) { 14 } else { 15 16 class Resources { 17 18 this(HINSTANCE inst, WORD language = 0, bool owned = false) { 19 this.hinst = inst; 20 this.lang = language; 21 this._owned = owned; 22 } 23 24 // Note: libName gets unloaded and may take down all its resources with it. 25 this(Dstring libName, WORD language = 0) { 26 HINSTANCE inst; 27 inst = loadLibraryEx(libName, LOAD_LIBRARY_AS_DATAFILE); 28 if (!inst) { 29 throw new DflException("Unable to load resources from '" ~ libName ~ "'"); 30 } 31 this(inst, language, true); // Owned. 32 } 33 34 /+ // Let's not depend on Application; the user can do so if they wish. 35 36 this(WORD language = 0) { 37 this(Application.getInstance(), language); 38 } 39 +/ 40 41 void dispose() { 42 assert(_owned); 43 //if(hinst != Application.getInstance()) // ? 44 FreeLibrary(hinst); 45 hinst = null; 46 } 47 48 final @property WORD language() { 49 return lang; 50 } 51 52 final Icon getIcon(int id, bool defaultSize = true) 53 in { 54 assert(id >= WORD.min && id <= WORD.max); 55 } 56 body { 57 /+ 58 HICON hi; 59 hi = LoadIconA(hinst, cast(LPCSTR)cast(WORD)id); 60 if(!hi) { 61 return null; 62 } 63 return Icon.fromHandle(hi); 64 +/ 65 HICON hi; 66 hi = cast(HICON) LoadImageA(hinst, cast(LPCSTR) cast(WORD) id, 67 IMAGE_ICON, 0, 0, defaultSize ? (LR_DEFAULTSIZE | LR_SHARED) : 0); 68 if (!hi) { 69 return null; 70 } 71 return new Icon(hi, true); // Owned. 72 } 73 74 final Icon getIcon(Dstring name, bool defaultSize = true) { 75 /+ 76 HICON hi; 77 hi = LoadIconA(hinst, unsafeStringz(name)); 78 if(!hi) { 79 return null; 80 } 81 return Icon.fromHandle(hi); 82 +/ 83 HICON hi; 84 hi = cast(HICON) dfl.internal.utf.loadImage(hinst, name, IMAGE_ICON, 85 0, 0, defaultSize ? (LR_DEFAULTSIZE | LR_SHARED) : 0); 86 if (!hi) { 87 return null; 88 } 89 return new Icon(hi, true); // Owned. 90 } 91 92 final Icon getIcon(int id, int width, int height) 93 in { 94 assert(id >= WORD.min && id <= WORD.max); 95 } 96 body { 97 // Can't have size 0 (plus causes Windows to use the actual size). 98 //if(width <= 0 || height <= 0) 99 // _noload("icon"); 100 HICON hi; 101 hi = cast(HICON) LoadImageA(hinst, cast(LPCSTR) cast(WORD) id, 102 IMAGE_ICON, width, height, 0); 103 if (!hi) { 104 return null; 105 } 106 return new Icon(hi, true); // Owned. 107 } 108 109 final Icon getIcon(Dstring name, int width, int height) { 110 // Can't have size 0 (plus causes Windows to use the actual size). 111 //if(width <= 0 || height <= 0) 112 // _noload("icon"); 113 HICON hi; 114 hi = cast(HICON) dfl.internal.utf.loadImage(hinst, name, IMAGE_ICON, width, 115 height, 0); 116 if (!hi) { 117 return null; 118 } 119 return new Icon(hi, true); // Owned. 120 } 121 122 deprecated alias loadIcon = getIcon; 123 124 final Bitmap getBitmap(int id) 125 in { 126 assert(id >= WORD.min && id <= WORD.max); 127 } 128 body { 129 HBITMAP h; 130 h = cast(HBITMAP) LoadImageA(hinst, cast(LPCSTR) cast(WORD) id, IMAGE_BITMAP, 131 0, 0, 0); 132 if (!h) { 133 return null; 134 } 135 return new Bitmap(h, true); // Owned. 136 } 137 138 final Bitmap getBitmap(Dstring name) { 139 HBITMAP h; 140 h = cast(HBITMAP) loadImage(hinst, name, IMAGE_BITMAP, 0, 0, 0); 141 if (!h) { 142 return null; 143 } 144 return new Bitmap(h, true); // Owned. 145 } 146 147 deprecated alias loadBitmap = getBitmap; 148 149 final Cursor getCursor(int id) 150 in { 151 assert(id >= WORD.min && id <= WORD.max); 152 } 153 body { 154 HCURSOR h; 155 h = cast(HCURSOR) LoadImageA(hinst, cast(LPCSTR) cast(WORD) id, IMAGE_CURSOR, 156 0, 0, 0); 157 if (!h) { 158 return null; 159 } 160 return new Cursor(h, true); // Owned. 161 } 162 163 final Cursor getCursor(Dstring name) { 164 HCURSOR h; 165 h = cast(HCURSOR) loadImage(hinst, name, IMAGE_CURSOR, 0, 0, 0); 166 if (!h) { 167 return null; 168 } 169 return new Cursor(h, true); // Owned. 170 } 171 172 deprecated alias loadCursor = getCursor; 173 174 final Dstring getString(int id) 175 in { 176 assert(id >= WORD.min && id <= WORD.max); 177 } 178 body { 179 // Not casting to wDstring because a resource isn't guaranteed to be the same size. 180 wchar* ws = cast(wchar*) _getData(cast(LPCWSTR) RT_STRING, 181 cast(LPCWSTR) cast(WORD)(id / 16 + 1)).ptr; 182 Dstring result; 183 if (ws) { 184 int i; 185 for (i = 0; i < (id & 15); i++) { 186 ws += 1 + cast(size_t)*ws; 187 } 188 result = utf16stringtoUtf8string((ws + 1)[0 .. cast(size_t)*ws]); 189 } 190 return result; 191 } 192 193 deprecated alias loadString = getString; 194 195 // Used internally 196 // NOTE: win9x doesn't like these strings to be on the heap! 197 final void[] _getData(LPCWSTR type, LPCWSTR name) { // internal 198 HRSRC hrc; 199 hrc = FindResourceExW(hinst, type, name, lang); 200 if (!hrc) { 201 return null; 202 } 203 HGLOBAL hg = LoadResource(hinst, hrc); 204 if (!hg) { 205 return null; 206 } 207 LPVOID pv = LockResource(hg); 208 if (!pv) { 209 return null; 210 } 211 return pv[0 .. SizeofResource(hinst, hrc)]; 212 } 213 214 final void[] getData(int type, int id) 215 in { 216 assert(type >= WORD.min && type <= WORD.max); 217 assert(id >= WORD.min && id <= WORD.max); 218 } 219 body { 220 return _getData(cast(LPCWSTR) type, cast(LPCWSTR) id); 221 } 222 223 final void[] getData(Dstring type, int id) 224 in { 225 assert(id >= WORD.min && id <= WORD.max); 226 } 227 body { 228 return _getData(utf8stringToUtf16stringz(type), cast(LPCWSTR) id); 229 } 230 231 final void[] getData(int type, Dstring name) 232 in { 233 assert(type >= WORD.min && type <= WORD.max); 234 } 235 body { 236 return _getData(cast(LPCWSTR) type, utf8stringToUtf16stringz(name)); 237 } 238 239 final void[] getData(Dstring type, Dstring name) { 240 return _getData(utf8stringToUtf16stringz(type), utf8stringToUtf16stringz(name)); 241 } 242 243 ~this() { 244 if (_owned) { 245 dispose(); 246 } 247 } 248 249 private: 250 251 HINSTANCE hinst; 252 WORD lang = 0; 253 bool _owned = false; 254 255 void _noload(Dstring type) { 256 throw new DflException("Unable to load " ~ type ~ " resource"); 257 } 258 } 259 }