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