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