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