1 // Written by Christopher E. Miller
2 // See the included license.txt for copyright and license details.
3 
4 
5 ///
6 module dfl.base;
7 
8 private import dfl.internal.dlib, dfl.internal.clib;
9 
10 private import dfl.internal.winapi, dfl.drawing, dfl.event;
11 
12 
13 alias HWND HWindow;
14 
15 
16 ///
17 interface IWindow // docmain
18 {
19 	///
20 	@property HWindow handle(); // getter
21 }
22 
23 alias IWindow IWin32Window; // deprecated
24 
25 
26 ///
27 class DflException: Exception // docmain
28 {
29 	///
30 	this(Dstring msg, string file = __FILE__, int line = __LINE__)
31 	{
32 		super(msg, file, line);
33 	}
34 }
35 
36 
37 ///
38 alias DThrowable DflThrowable;
39 
40 
41 ///
42 class StringObject: DObject
43 {
44 	///
45 	Dstring value;
46 	
47 	
48 	///
49 	this(Dstring str) pure nothrow
50 	{
51 		this.value = str;
52 	}
53 	
54 	
55 	override Dstring toString()
56 	{
57 		return value;
58 	}
59 	
60 	
61 	override Dequ opEquals(Object o)
62 	{
63 		return value == getObjectString(o); // ?
64 	}
65 	
66 	
67 	Dequ opEquals(StringObject s)
68 	{
69 		return value == s.value;
70 	}
71 	
72 	
73 	override int opCmp(Object o)
74 	{
75 		return stringICmp(value, getObjectString(o)); // ?
76 	}
77 	
78 	
79 	int opCmp(StringObject s)
80 	{
81 		return stringICmp(value, s.value);
82 	}
83 }
84 
85 
86 ///
87 enum Keys: uint // docmain
88 {
89 	NONE =     0, /// No keys specified.
90 	
91 	///
92 	SHIFT =    0x10000, /// Modifier keys.
93 	CONTROL =  0x20000, /// ditto
94 	ALT =      0x40000, /// ditto
95 	WINDOWS =  0x80000, /// ditto
96 	
97 	A = 'A', /// Letters.
98 	B = 'B', /// ditto
99 	C = 'C', /// ditto
100 	D = 'D', /// ditto
101 	E = 'E', /// ditto
102 	F = 'F', /// ditto
103 	G = 'G', /// ditto
104 	H = 'H', /// ditto
105 	I = 'I', /// ditto
106 	J = 'J', /// ditto
107 	K = 'K', /// ditto
108 	L = 'L', /// ditto
109 	M = 'M', /// ditto
110 	N = 'N', /// ditto
111 	O = 'O', /// ditto
112 	P = 'P', /// ditto
113 	Q = 'Q', /// ditto
114 	R = 'R', /// ditto
115 	S = 'S', /// ditto
116 	T = 'T', /// ditto
117 	U = 'U', /// ditto
118 	V = 'V', /// ditto
119 	W = 'W', /// ditto
120 	X = 'X', /// ditto
121 	Y = 'Y', /// ditto
122 	Z = 'Z', /// ditto
123 	
124 	D0 = '0', /// Digits.
125 	D1 = '1', /// ditto
126 	D2 = '2', /// ditto
127 	D3 = '3', /// ditto
128 	D4 = '4', /// ditto
129 	D5 = '5', /// ditto
130 	D6 = '6', /// ditto
131 	D7 = '7', /// ditto
132 	D8 = '8', /// ditto
133 	D9 = '9', /// ditto
134 	
135 	F1 = 112, /// F - function keys.
136 	F2 = 113, /// ditto
137 	F3 = 114, /// ditto
138 	F4 = 115, /// ditto
139 	F5 = 116, /// ditto
140 	F6 = 117, /// ditto
141 	F7 = 118, /// ditto
142 	F8 = 119, /// ditto
143 	F9 = 120, /// ditto
144 	F10 = 121, /// ditto
145 	F11 = 122, /// ditto
146 	F12 = 123, /// ditto
147 	F13 = 124, /// ditto
148 	F14 = 125, /// ditto
149 	F15 = 126, /// ditto
150 	F16 = 127, /// ditto
151 	F17 = 128, /// ditto
152 	F18 = 129, /// ditto
153 	F19 = 130, /// ditto
154 	F20 = 131, /// ditto
155 	F21 = 132, /// ditto
156 	F22 = 133, /// ditto
157 	F23 = 134, /// ditto
158 	F24 = 135, /// ditto
159 	
160 	NUM_PAD0 = 96, /// Numbers on keypad.
161 	NUM_PAD1 = 97, /// ditto
162 	NUM_PAD2 = 98, /// ditto
163 	NUM_PAD3 = 99, /// ditto
164 	NUM_PAD4 = 100, /// ditto
165 	NUM_PAD5 = 101, /// ditto
166 	NUM_PAD6 = 102, /// ditto
167 	NUM_PAD7 = 103, /// ditto
168 	NUM_PAD8 = 104, /// ditto
169 	NUM_PAD9 = 105, /// ditto
170 	
171 	ADD = 107, ///
172 	APPS = 93, /// Application.
173 	ATTN = 246, ///
174 	BACK = 8, /// Backspace.
175 	CANCEL = 3, ///
176 	CAPITAL = 20, ///
177 	CAPS_LOCK = 20, /// ditto
178 	CLEAR = 12, ///
179 	CONTROL_KEY = 17, ///
180 	CRSEL = 247, ///
181 	DECIMAL = 110, ///
182 	DEL = 46, ///
183 	DELETE = DEL, ///
184 	PERIOD = 190, ///
185 	DOT = PERIOD, /// ditto
186 	DIVIDE = 111, ///
187 	DOWN = 40, /// Down arrow.
188 	END = 35, ///
189 	ENTER = 13, ///
190 	ERASE_EOF = 249, ///
191 	ESCAPE = 27, ///
192 	EXECUTE = 43, ///
193 	EXSEL = 248, ///
194 	FINAL_MODE = 4, /// IME final mode.
195 	HANGUL_MODE = 21, /// IME Hangul mode.
196 	HANGUEL_MODE = 21, /// ditto
197 	HANJA_MODE = 25, /// IME Hanja mode.
198 	HELP = 47, ///
199 	HOME = 36, ///
200 	IME_ACCEPT = 30, ///
201 	IME_CONVERT = 28, ///
202 	IME_MODE_CHANGE = 31, ///
203 	IME_NONCONVERT = 29, ///
204 	INSERT = 45, ///
205 	JUNJA_MODE = 23, ///
206 	KANA_MODE = 21, ///
207 	KANJI_MODE = 25, ///
208 	LEFT_CONTROL = 162, /// Left Ctrl.
209 	LEFT = 37, /// Left arrow.
210 	LINE_FEED = 10, ///
211 	LEFT_MENU = 164, /// Left Alt.
212 	LEFT_SHIFT = 160, ///
213 	LEFT_WIN = 91, /// Left Windows logo.
214 	MENU = 18, /// Alt.
215 	MULTIPLY = 106, ///
216 	NEXT = 34, /// Page down.
217 	NO_NAME = 252, // Reserved for future use.
218 	NUM_LOCK = 144, ///
219 	OEM8 = 223, // OEM specific.
220 	OEM_CLEAR = 254,
221 	PA1 = 253,
222 	PAGE_DOWN = 34, ///
223 	PAGE_UP = 33, ///
224 	PAUSE = 19, ///
225 	PLAY = 250, ///
226 	PRINT = 42, ///
227 	PRINT_SCREEN = 44, ///
228 	PROCESS_KEY = 229, ///
229 	RIGHT_CONTROL = 163, /// Right Ctrl.
230 	RETURN = 13, ///
231 	RIGHT = 39, /// Right arrow.
232 	RIGHT_MENU = 165, /// Right Alt.
233 	RIGHT_SHIFT = 161, ///
234 	RIGHT_WIN = 92, /// Right Windows logo.
235 	SCROLL = 145, /// Scroll lock.
236 	SELECT = 41, ///
237 	SEPARATOR = 108, ///
238 	SHIFT_KEY = 16, ///
239 	SNAPSHOT = 44, /// Print screen.
240 	SPACE = 32, ///
241 	SPACEBAR = SPACE, // Extra.
242 	SUBTRACT = 109, ///
243 	TAB = 9, ///
244 	UP = 38, /// Up arrow.
245 	ZOOM = 251, ///
246 	
247 	// Windows 2000+
248 	BROWSER_BACK = 166, ///
249 	BROWSER_FAVORITES = 171, /// ditto
250 	BROWSER_FORWARD = 167, /// ditto
251 	BROWSER_HOME = 172, /// ditto
252 	BROWSER_REFRESH = 168, /// ditto
253 	BROWSER_SEARCH = 170, /// ditto
254 	BROWSER_STOP = 169, /// ditto
255 	LAUNCH_APPLICATION1 = 182, ///
256 	LAUNCH_APPLICATION2 = 183, /// ditto
257 	LAUNCH_MAIL = 180, /// ditto
258 	MEDIA_NEXT_TRACK = 176, ///
259 	MEDIA_PLAY_PAUSE = 179, /// ditto
260 	MEDIA_PREVIOUS_TRACK = 177, /// ditto
261 	MEDIA_STOP = 178, /// ditto
262 	OEM_BACKSLASH = 226, // OEM angle bracket or backslash.
263 	OEM_CLOSE_BRACKETS = 221,
264 	OEM_COMMA = 188,
265 	OEM_MINUS = 189,
266 	OEM_OPEN_BRACKETS = 219,
267 	OEM_PERIOD = 190,
268 	OEM_PIPE = 220,
269 	OEM_PLUS = 187,
270 	OEM_QUESTION = 191,
271 	OEM_QUOTES = 222,
272 	OEM_SEMICOLON = 186,
273 	OEM_TILDE = 192,
274 	SELECT_MEDIA = 181, ///
275 	VOLUME_DOWN = 174, ///
276 	VOLUME_MUTE = 173, /// ditto
277 	VOLUME_UP = 175, /// ditto
278 	
279 	/// Bit mask to extract key code from key value.
280 	KEY_CODE = 0xFFFF,
281 	
282 	/// Bit mask to extract modifiers from key value.
283 	MODIFIERS = 0xFFFF0000,
284 }
285 
286 
287 ///
288 enum MouseButtons: uint // docmain
289 {
290 	/// No mouse buttons specified.
291 	NONE =      0,
292 	
293 	LEFT =      0x100000, ///
294 	RIGHT =     0x200000, /// ditto
295 	MIDDLE =    0x400000, /// ditto
296 	
297 	// Windows 2000+
298 	//XBUTTON1 =  0x800000,
299 	//XBUTTON2 =  0x1000000,
300 }
301 
302 
303 ///
304 enum CheckState: ubyte
305 {
306 	UNCHECKED = BST_UNCHECKED, ///
307 	CHECKED = BST_CHECKED, /// ditto
308 	INDETERMINATE = BST_INDETERMINATE, /// ditto
309 }
310 
311 
312 ///
313 struct Message // docmain
314 {
315 	union
316 	{
317 		struct
318 		{
319 			HWND hWnd; ///
320 			UINT msg; /// ditto
321 			WPARAM wParam; /// ditto
322 			LPARAM lParam; /// ditto
323 		}
324 		
325 		package MSG _winMsg; // .time and .pt are not always valid.
326 	}
327 	LRESULT result; ///
328 	
329 	
330 	/// Construct a Message struct.
331 	this(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) pure nothrow
332 	{
333 		this.hWnd = hWnd;
334 		this.msg = msg;
335 		this.wParam = wParam;
336 		this.lParam = lParam;
337 		result = 0;
338 	}
339 }
340 
341 
342 ///
343 interface IMessageFilter // docmain
344 {
345 	///
346 	// Return false to allow the message to be dispatched.
347 	// Filter functions cannot modify messages.
348 	bool preFilterMessage(ref Message m);
349 }
350 
351 
352 abstract class WaitHandle
353 {
354 	enum WAIT_TIMEOUT = dfl.internal.winapi.WAIT_TIMEOUT; // DMD 1.028: needs fqn, otherwise conflicts with std.thread
355 	enum INVALID_HANDLE = .INVALID_HANDLE_VALUE;
356 	
357 	
358 	this()
359 	{
360 		h = INVALID_HANDLE;
361 	}
362 	
363 	
364 	// Used internally.
365 	this(HANDLE h, bool owned = true)
366 	{
367 		this.h = h;
368 		this.owned = owned;
369 	}
370 	
371 	
372 	@property HANDLE handle() nothrow // getter
373 	{
374 		return h;
375 	}
376 	
377 	
378 	@property void handle(HANDLE h) // setter
379 	{
380 		this.h = h;
381 	}
382 	
383 	
384 	void close()
385 	{
386 		CloseHandle(h);
387 		h = INVALID_HANDLE;
388 	}
389 	
390 	
391 	~this()
392 	{
393 		if(owned)
394 			close();
395 	}
396 	
397 	
398 	private static DWORD _wait(WaitHandle[] handles, BOOL waitall, DWORD msTimeout)
399 	{
400 		// Some implementations fail with > 64 handles, but that will return WAIT_FAILED;
401 		// all implementations fail with >= 128 handles due to WAIT_ABANDONED_0 being 128.
402 		////if(handles.length >= 128)
403 			////goto fail;
404 		
405 		DWORD result;
406 		HANDLE* hs;
407 		//hs = new HANDLE[handles.length];
408 		hs = cast(HANDLE*)alloca(HANDLE.sizeof * handles.length);
409 		
410 		foreach(size_t i, WaitHandle wh; handles)
411 		{
412 			hs[i] = wh.handle;
413 		}
414 		
415 		result = WaitForMultipleObjects(handles.length, hs, waitall, msTimeout);
416 		if(WAIT_FAILED == result)
417 		{
418 			fail:
419 			throw new DflException("Wait failure");
420 		}
421 		return result;
422 	}
423 	
424 	
425 	static void waitAll(WaitHandle[] handles)
426 	{
427 		return waitAll(handles, INFINITE);
428 	}
429 	
430 	
431 	static void waitAll(WaitHandle[] handles, DWORD msTimeout)
432 	{
433 		_wait(handles, true, msTimeout);
434 	}
435 	
436 	
437 	static int waitAny(WaitHandle[] handles)
438 	{
439 		return waitAny(handles, INFINITE);
440 	}
441 	
442 	
443 	static int waitAny(WaitHandle[] handles, DWORD msTimeout)
444 	{
445 		DWORD result;
446 		result = _wait(handles, false, msTimeout);
447 		return cast(int)result; // Same return info.
448 	}
449 	
450 	
451 	void waitOne()
452 	{
453 		return waitOne(INFINITE);
454 	}
455 	
456 	
457 	void waitOne(DWORD msTimeout)
458 	{
459 		DWORD result;
460 		result = WaitForSingleObject(handle, msTimeout);
461 		if(WAIT_FAILED == result)
462 			throw new DflException("Wait failure");
463 	}
464 	
465 	
466 	private:
467 	HANDLE h;
468 	bool owned = true;
469 }
470 
471 
472 interface IAsyncResult
473 {
474 	@property WaitHandle asyncWaitHandle(); // getter
475 	
476 	// Usually just returns false.
477 	@property bool completedSynchronously(); // getter
478 	
479 	// When true, it is safe to release its resources.
480 	@property bool isCompleted(); // getter
481 }
482 
483 
484 /+
485 class AsyncResult: IAsyncResult
486 {
487 }
488 +/
489 
490 
491 ///
492 interface IButtonControl // docmain
493 {
494 	///
495 	@property DialogResult dialogResult(); // getter
496 	/// ditto
497 	@property void dialogResult(DialogResult); // setter
498 	
499 	///
500 	void notifyDefault(bool); // True if default button.
501 	
502 	///
503 	void performClick(); // Raise click event.
504 }
505 
506 
507 ///
508 enum DialogResult: ubyte // docmain
509 {
510 	NONE, ///
511 	
512 	ABORT = IDABORT, ///
513 	CANCEL = IDCANCEL, ///
514 	IGNORE = IDIGNORE, ///
515 	NO = IDNO, ///
516 	OK = IDOK, ///
517 	RETRY = IDRETRY, ///
518 	YES = IDYES, ///
519 	
520 	// Extra.
521 	CLOSE = IDCLOSE,
522 	HELP = IDHELP,
523 }
524 
525 
526 interface IDialogResult
527 {
528 	// ///
529 	@property DialogResult dialogResult(); // getter
530 	// /// ditto
531 	@property void dialogResult(DialogResult); // setter
532 }
533 
534 
535 ///
536 enum SortOrder: ubyte
537 {
538 	NONE, ///
539 	
540 	ASCENDING, ///
541 	DESCENDING, /// ditto
542 }
543 
544 
545 ///
546 enum View: ubyte
547 {
548 	LARGE_ICON, ///
549 	SMALL_ICON, ///
550 	LIST, ///
551 	DETAILS, ///
552 }
553 
554 
555 ///
556 enum ItemBoundsPortion: ubyte
557 {
558 	ENTIRE, ///
559 	ICON, ///
560 	ITEM_ONLY, /// Excludes other stuff like check boxes.
561 	LABEL, /// Item's text.
562 }
563 
564 
565 ///
566 enum ItemActivation: ubyte
567 {
568 	STANDARD, ///
569 	ONE_CLICK, ///
570 	TWO_CLICK, ///
571 }
572 
573 
574 ///
575 enum ColumnHeaderStyle: ubyte
576 {
577 	CLICKABLE, ///
578 	NONCLICKABLE, ///
579 	NONE, /// No column header.
580 }
581 
582 
583 ///
584 enum BorderStyle: ubyte
585 {
586 	NONE, ///
587 	
588 	FIXED_3D, ///
589 	FIXED_SINGLE, /// ditto
590 }
591 
592 
593 ///
594 enum FlatStyle: ubyte
595 {
596 	STANDARD, ///
597 	FLAT, /// ditto
598 	POPUP, /// ditto
599 	SYSTEM, /// ditto
600 }
601 
602 
603 ///
604 enum Appearance: ubyte
605 {
606 	NORMAL, ///
607 	BUTTON, ///
608 }
609 
610 
611 ///
612 enum ContentAlignment: ubyte
613 {
614 	TOP_LEFT, ///
615 	BOTTOM_CENTER, ///
616 	BOTTOM_LEFT, ///
617 	BOTTOM_RIGHT, ///
618 	MIDDLE_CENTER, ///
619 	MIDDLE_LEFT, ///
620 	MIDDLE_RIGHT, ///
621 	TOP_CENTER, ///
622 	TOP_RIGHT, ///
623 }
624 
625 
626 ///
627 enum CharacterCasing: ubyte
628 {
629 	NORMAL, ///
630 	LOWER, ///
631 	UPPER, ///
632 }
633 
634 
635 ///
636 // Not flags.
637 enum ScrollBars: ubyte
638 {
639 	NONE, ///
640 	
641 	HORIZONTAL, ///
642 	VERTICAL, /// ditto
643 	BOTH, /// ditto
644 }
645 
646 
647 ///
648 enum HorizontalAlignment: ubyte
649 {
650 	LEFT, ///
651 	RIGHT, /// ditto
652 	CENTER, /// ditto
653 }
654 
655 
656 ///
657 enum DrawMode: ubyte
658 {
659 	NORMAL, ///
660 	OWNER_DRAW_FIXED, ///
661 	OWNER_DRAW_VARIABLE, /// ditto
662 }
663 
664 
665 ///
666 enum DrawItemState: uint
667 {
668 	NONE = 0, ///
669 	SELECTED = 1, /// ditto
670 	DISABLED = 2, /// ditto
671 	CHECKED = 8, /// ditto
672 	FOCUS = 0x10, /// ditto
673 	DEFAULT = 0x20, /// ditto
674 	HOT_LIGHT = 0x40, /// ditto
675 	NO_ACCELERATOR = 0x80, /// ditto
676 	INACTIVE = 0x100, /// ditto
677 	NO_FOCUS_RECT = 0x200, /// ditto
678 	COMBO_BOX_EDIT = 0x1000, /// ditto
679 }
680 
681 
682 ///
683 enum RightToLeft: ubyte
684 {
685 	INHERIT = 2, ///
686 	YES = 1, /// ditto
687 	NO = 0, /// ditto
688 }
689 
690 
691 ///
692 enum ColorDepth: ubyte
693 {
694 	DEPTH_4BIT = 0x04, ///
695 	DEPTH_8BIT = 0x08, /// ditto
696 	DEPTH_16BIT = 0x10, /// ditto
697 	DEPTH_24BIT = 0x18, /// ditto
698 	DEPTH_32BIT = 0x20, /// ditto
699 }
700 
701 
702 ///
703 class PaintEventArgs: EventArgs
704 {
705 	///
706 	this(Graphics graphics, Rect clipRect) pure nothrow
707 	{
708 		g = graphics;
709 		cr = clipRect;
710 	}
711 	
712 	
713 	///
714 	final @property Graphics graphics() pure nothrow // getter
715 	{
716 		return g;
717 	}
718 	
719 	
720 	///
721 	final @property Rect clipRectangle() pure nothrow // getter
722 	{
723 		return cr;
724 	}
725 	
726 	
727 	private:
728 	Graphics g;
729 	Rect cr;
730 }
731 
732 
733 ///
734 class CancelEventArgs: EventArgs
735 {
736 	///
737 	// Initialize cancel to false.
738 	this() pure nothrow
739 	{
740 		cncl = false;
741 	}
742 	
743 	/// ditto
744 	this(bool cancel) pure nothrow
745 	{
746 		cncl = cancel;
747 	}
748 	
749 	
750 	///
751 	final @property void cancel(bool byes) pure nothrow // setter
752 	{
753 		cncl = byes;
754 	}
755 	
756 	/// ditto
757 	final @property bool cancel() pure nothrow // getter
758 	{
759 		return cncl;
760 	}
761 	
762 	
763 	private:
764 	bool cncl;
765 }
766 
767 
768 ///
769 class KeyEventArgs: EventArgs
770 {
771 	///
772 	this(Keys keys) pure nothrow
773 	{
774 		ks = keys;
775 	}
776 	
777 	
778 	///
779 	final @property bool alt() pure nothrow // getter
780 	{
781 		return (ks & Keys.ALT) != 0;
782 	}
783 	
784 	
785 	///
786 	final @property bool control() pure nothrow // getter
787 	{
788 		return (ks & Keys.CONTROL) != 0;
789 	}
790 	
791 	
792 	///
793 	final @property void handled(bool byes) pure nothrow // setter
794 	{
795 		hand = byes;
796 	}
797 	
798 	///
799 	final @property bool handled() pure nothrow // getter
800 	{
801 		return hand;
802 	}
803 	
804 	
805 	///
806 	final @property Keys keyCode() pure nothrow // getter
807 	{
808 		return ks & Keys.KEY_CODE;
809 	}
810 	
811 	
812 	///
813 	final @property Keys keyData() pure nothrow // getter
814 	{
815 		return ks;
816 	}
817 	
818 	
819 	///
820 	// -keyData- as an int.
821 	final @property int keyValue() pure nothrow // getter
822 	{
823 		return cast(int)ks;
824 	}
825 	
826 	
827 	///
828 	final @property Keys modifiers() pure nothrow // getter
829 	{
830 		return ks & Keys.MODIFIERS;
831 	}
832 	
833 	
834 	///
835 	final @property bool shift() pure nothrow // getter
836 	{
837 		return (ks & Keys.SHIFT) != 0;
838 	}
839 	
840 	
841 	///
842 	final @property bool windows() pure nothrow // getter
843 	{
844 		return (ks & Keys.WINDOWS) != 0;
845 	}
846 	
847 	
848 	private:
849 	Keys ks;
850 	bool hand = false;
851 }
852 
853 
854 ///
855 class KeyPressEventArgs: KeyEventArgs
856 {
857 	///
858 	this(dchar ch)
859 	{
860 		this(ch, (ch >= 'A' && ch <= 'Z') ? Keys.SHIFT : Keys.NONE);
861 	}
862 	
863 	/// ditto
864 	this(dchar ch, Keys modifiers)
865 	in
866 	{
867 		assert((modifiers & Keys.MODIFIERS) == modifiers, "modifiers parameter can only contain modifiers");
868 	}
869 	body
870 	{
871 		_keych = ch;
872 		
873 		int vk;
874 		if(dfl.internal.utf.useUnicode)
875 			vk = 0xFF & VkKeyScanW(cast(WCHAR)ch);
876 		else
877 			vk = 0xFF & VkKeyScanA(cast(char)ch);
878 		
879 		super(cast(Keys)(vk | modifiers));
880 	}
881 	
882 	
883 	///
884 	final @property dchar keyChar() // getter
885 	{
886 		return _keych;
887 	}
888 	
889 	
890 	private:
891 	dchar _keych;
892 }
893 
894 
895 ///
896 class MouseEventArgs: EventArgs
897 {
898 	///
899 	// -delta- is mouse wheel rotations.
900 	this(MouseButtons button, int clicks, int x, int y, int delta) pure nothrow
901 	{
902 		btn = button;
903 		clks = clicks;
904 		_x = x;
905 		_y = y;
906 		dlt = delta;
907 	}
908 	
909 	
910 	///
911 	final @property MouseButtons button() pure nothrow // getter
912 	{
913 		return btn;
914 	}
915 	
916 	
917 	///
918 	final @property int clicks() pure nothrow // getter
919 	{
920 		return clks;
921 	}
922 	
923 	
924 	///
925 	final @property int delta() pure nothrow // getter
926 	{
927 		return dlt;
928 	}
929 	
930 	
931 	///
932 	final @property int x() pure nothrow // getter
933 	{
934 		return _x;
935 	}
936 	
937 	
938 	///
939 	final @property int y() pure nothrow // getter
940 	{
941 		return _y;
942 	}
943 	
944 	
945 	private:
946 	MouseButtons btn;
947 	int clks;
948 	int _x, _y;
949 	int dlt;
950 }
951 
952 
953 /+
954 ///
955 class LabelEditEventArgs: EventArgs
956 {
957 	///
958 	this(int index)
959 	{
960 		
961 	}
962 	
963 	/// ditto
964 	this(int index, Dstring labelText)
965 	{
966 		this.idx = index;
967 		this.ltxt = labelText;
968 	}
969 	
970 	
971 	///
972 	final @property void cancelEdit(bool byes) // setter
973 	{
974 		cancl = byes;
975 	}
976 	
977 	/// ditto
978 	final @property bool cancelEdit() // getter
979 	{
980 		return cancl;
981 	}
982 	
983 	
984 	///
985 	// The text of the label's edit.
986 	final @property Dstring label() // getter
987 	{
988 		return ltxt;
989 	}
990 	
991 	
992 	///
993 	// Gets the item's index.
994 	final @property int item() // getter
995 	{
996 		return idx;
997 	}
998 	
999 	
1000 	private:
1001 	int idx;
1002 	Dstring ltxt;
1003 	bool cancl = false;
1004 }
1005 +/
1006 
1007 
1008 ///
1009 class ColumnClickEventArgs: EventArgs
1010 {
1011 	///
1012 	this(int col) pure nothrow
1013 	{
1014 		this.col = col;
1015 	}
1016 	
1017 	
1018 	///
1019 	final @property int column() pure nothrow // getter
1020 	{
1021 		return col;
1022 	}
1023 	
1024 	
1025 	private:
1026 	int col;
1027 }
1028 
1029 
1030 ///
1031 class DrawItemEventArgs: EventArgs
1032 {
1033 	///
1034 	this(Graphics g, Font f, Rect r, int i, DrawItemState dis) pure nothrow
1035 	{
1036 		this(g, f, r, i , dis, Color.empty, Color.empty);
1037 	}
1038 	
1039 	/// ditto
1040 	this(Graphics g, Font f, Rect r, int i, DrawItemState dis, Color fc, Color bc) pure nothrow
1041 	{
1042 		gpx = g;
1043 		fnt = f;
1044 		rect = r;
1045 		idx = i;
1046 		distate = dis;
1047 		fcolor = fc;
1048 		bcolor = bc;
1049 	}
1050 	
1051 	
1052 	///
1053 	final @property Color backColor() pure nothrow // getter
1054 	{
1055 		return bcolor;
1056 	}
1057 	
1058 	
1059 	///
1060 	final @property Rect bounds() pure nothrow // getter
1061 	{
1062 		return rect;
1063 	}
1064 	
1065 	
1066 	///
1067 	final @property Font font() pure nothrow // getter
1068 	{
1069 		return fnt;
1070 	}
1071 	
1072 	
1073 	///
1074 	final @property Color foreColor() pure nothrow // getter
1075 	{
1076 		return fcolor;
1077 	}
1078 	
1079 	
1080 	///
1081 	final @property Graphics graphics() pure nothrow // getter
1082 	{
1083 		return gpx;
1084 	}
1085 	
1086 	
1087 	///
1088 	final @property int index() pure nothrow // getter
1089 	{
1090 		return idx;
1091 	}
1092 	
1093 	
1094 	///
1095 	final @property DrawItemState state() pure nothrow // getter
1096 	{
1097 		return distate;
1098 	}
1099 	
1100 	
1101 	///
1102 	void drawBackground()
1103 	{
1104 		/+
1105 		HBRUSH hbr;
1106 		RECT _rect;
1107 		
1108 		hbr = bcolor.createBrush();
1109 		try
1110 		{
1111 			rect.getRect(&_rect);
1112 			FillRect(gpx.handle, &_rect, hbr);
1113 		}
1114 		finally
1115 		{
1116 			DeleteObject(hbr);
1117 		}
1118 		+/
1119 		
1120 		gpx.fillRectangle(bcolor, rect);
1121 	}
1122 	
1123 	
1124 	///
1125 	void drawFocusRectangle()
1126 	{
1127 		if(distate & DrawItemState.FOCUS)
1128 		{
1129 			RECT _rect;
1130 			rect.getRect(&_rect);
1131 			DrawFocusRect(gpx.handle, &_rect);
1132 		}
1133 	}
1134 	
1135 	
1136 	private:
1137 	Graphics gpx;
1138 	Font fnt; // Suggestion; the parent's font.
1139 	Rect rect;
1140 	int idx;
1141 	DrawItemState distate;
1142 	Color fcolor, bcolor; // Suggestion; depends on item state.
1143 }
1144 
1145 
1146 ///
1147 class MeasureItemEventArgs: EventArgs
1148 {
1149 	///
1150 	this(Graphics g, int index, int itemHeight)
1151 	{
1152 		gpx = g;
1153 		idx = index;
1154 		iheight = itemHeight;
1155 	}
1156 	
1157 	/// ditto
1158 	this(Graphics g, int index)
1159 	{
1160 		this(g, index, 0);
1161 	}
1162 	
1163 	
1164 	///
1165 	final @property Graphics graphics() // getter
1166 	{
1167 		return gpx;
1168 	}
1169 	
1170 	
1171 	///
1172 	final @property int index() // getter
1173 	{
1174 		return idx;
1175 	}
1176 	
1177 	
1178 	///
1179 	final @property void itemHeight(int height) // setter
1180 	{
1181 		iheight = height;
1182 	}
1183 	
1184 	/// ditto
1185 	final @property int itemHeight() // getter
1186 	{
1187 		return iheight;
1188 	}
1189 	
1190 	
1191 	///
1192 	final @property void itemWidth(int width) // setter
1193 	{
1194 		iwidth = width;
1195 	}
1196 	
1197 	/// ditto
1198 	final @property int itemWidth() // getter
1199 	{
1200 		return iwidth;
1201 	}
1202 	
1203 	
1204 	private:
1205 	Graphics gpx;
1206 	int idx, iheight, iwidth = 0;
1207 }
1208 
1209 
1210 ///
1211 class Cursor // docmain
1212 {
1213 	private static Cursor _cur;
1214 	
1215 	
1216 	// Used internally.
1217 	this(HCURSOR hcur, bool owned = true)
1218 	{
1219 		this.hcur = hcur;
1220 		this.owned = owned;
1221 	}
1222 	
1223 	
1224 	~this()
1225 	{
1226 		if(owned)
1227 			dispose();
1228 	}
1229 	
1230 	
1231 	///
1232 	void dispose()
1233 	{
1234 		assert(owned);
1235 		DestroyCursor(hcur);
1236 		hcur = HCURSOR.init;
1237 	}
1238 	
1239 	
1240 	///
1241 	static @property void current(Cursor cur) // setter
1242 	{
1243 		// Keep a reference so that it doesn't get garbage collected until set again.
1244 		_cur = cur;
1245 		
1246 		SetCursor(cur ? cur.hcur : HCURSOR.init);
1247 	}
1248 	
1249 	/// ditto
1250 	static @property Cursor current() // getter
1251 	{
1252 		HCURSOR hcur = GetCursor();
1253 		return hcur ? new Cursor(hcur, false) : null;
1254 	}
1255 	
1256 	
1257 	///
1258 	static @property void clip(Rect r) // setter
1259 	{
1260 		RECT rect;
1261 		r.getRect(&rect);
1262 		ClipCursor(&rect);
1263 	}
1264 	
1265 	/// ditto
1266 	static @property Rect clip() // getter
1267 	{
1268 		RECT rect;
1269 		GetClipCursor(&rect);
1270 		return Rect(&rect);
1271 	}
1272 	
1273 	
1274 	///
1275 	final @property HCURSOR handle() // getter
1276 	{
1277 		return hcur;
1278 	}
1279 	
1280 	
1281 	/+
1282 	// TODO:
1283 	final @property Size size() // getter
1284 	{
1285 		Size result;
1286 		ICONINFO iinfo;
1287 		
1288 		if(GetIconInfo(hcur, &iinfo))
1289 		{
1290 			
1291 		}
1292 		
1293 		return result;
1294 	}
1295 	+/
1296 	
1297 	
1298 	///
1299 	// Uses the actual size.
1300 	final void draw(Graphics g, Point pt)
1301 	{
1302 		DrawIconEx(g.handle, pt.x, pt.y, hcur, 0, 0, 0, HBRUSH.init, DI_NORMAL);
1303 	}
1304 	
1305 	/+
1306 	/// ditto
1307 	// Should not stretch if bigger, but should crop if smaller.
1308 	final void draw(Graphics g, Rect r)
1309 	{
1310 	}
1311 	+/
1312 	
1313 	
1314 	///
1315 	final void drawStretched(Graphics g, Rect r)
1316 	{
1317 		// DrawIconEx operates differently if the width or height is zero
1318 		// so bail out if zero and pretend the zero size cursor was drawn.
1319 		int width = r.width;
1320 		if(!width)
1321 			return;
1322 		int height = r.height;
1323 		if(!height)
1324 			return;
1325 		
1326 		DrawIconEx(g.handle, r.x, r.y, hcur, width, height, 0, HBRUSH.init, DI_NORMAL);
1327 	}
1328 	
1329 	
1330 	override Dequ opEquals(Object o)
1331 	{
1332 		Cursor cur = cast(Cursor)o;
1333 		if(!cur)
1334 			return 0; // Not equal.
1335 		return opEquals(cur);
1336 	}
1337 	
1338 	
1339 	Dequ opEquals(Cursor cur)
1340 	{
1341 		return hcur == cur.hcur;
1342 	}
1343 	
1344 	
1345 	/// Show/hide the current mouse cursor; reference counted.
1346 	// show/hide are ref counted.
1347 	static void hide()
1348 	{
1349 		ShowCursor(false);
1350 	}
1351 	
1352 	/// ditto
1353 	// show/hide are ref counted.
1354 	static void show()
1355 	{
1356 		ShowCursor(true);
1357 	}
1358 	
1359 	
1360 	/// The position of the current mouse cursor.
1361 	static @property void position(Point pt) // setter
1362 	{
1363 		SetCursorPos(pt.x, pt.y);
1364 	}
1365 	
1366 	/// ditto
1367 	static @property Point position() // getter
1368 	{
1369 		Point pt;
1370 		GetCursorPos(&pt.point);
1371 		return pt;
1372 	}
1373 	
1374 	
1375 	private:
1376 	HCURSOR hcur;
1377 	bool owned = true;
1378 }
1379 
1380 
1381 ///
1382 class Cursors // docmain
1383 {
1384 	private this() {}
1385 	
1386 	
1387 	static:
1388 	
1389 	///
1390 	@property Cursor appStarting() // getter
1391 	{ return new Cursor(LoadCursorA(HINSTANCE.init, IDC_APPSTARTING), false); }
1392 	
1393 	///
1394 	@property Cursor arrow() // getter
1395 	{ return new Cursor(LoadCursorA(HINSTANCE.init, IDC_ARROW), false); }
1396 	
1397 	///
1398 	@property Cursor cross() // getter
1399 	{ return new Cursor(LoadCursorA(HINSTANCE.init, IDC_CROSS), false); }
1400 	
1401 	///
1402 	//@property Cursor default() // getter
1403 	@property Cursor defaultCursor() // getter
1404 	{ return arrow; }
1405 	
1406 	///
1407 	@property Cursor hand() // getter
1408 	{
1409 		version(SUPPORTS_HAND_CURSOR) // Windows 98+
1410 		{
1411 			return new Cursor(LoadCursorA(HINSTANCE.init, IDC_HAND), false);
1412 		}
1413 		else
1414 		{
1415 			static HCURSOR hcurHand;
1416 			
1417 			if(!hcurHand)
1418 			{
1419 				hcurHand = LoadCursorA(HINSTANCE.init, IDC_HAND);
1420 				if(!hcurHand) // Must be Windows 95, so load the cursor from winhlp32.exe.
1421 				{
1422 					UINT len;
1423 					char[MAX_PATH] winhlppath = void;
1424 					
1425 					len = GetWindowsDirectoryA(winhlppath.ptr, winhlppath.length - 16);
1426 					if(!len || len > winhlppath.length - 16)
1427 					{
1428 						load_failed:
1429 						return arrow; // Just fall back to a normal arrow.
1430 					}
1431 					strcpy(winhlppath.ptr + len, "\\winhlp32.exe");
1432 					
1433 					HINSTANCE hinstWinhlp;
1434 					hinstWinhlp = LoadLibraryExA(winhlppath.ptr, HANDLE.init, LOAD_LIBRARY_AS_DATAFILE);
1435 					if(!hinstWinhlp)
1436 						goto load_failed;
1437 					
1438 					HCURSOR hcur;
1439 					hcur = LoadCursorA(hinstWinhlp, cast(char*)106);
1440 					if(!hcur) // No such cursor resource.
1441 					{
1442 						FreeLibrary(hinstWinhlp);
1443 						goto load_failed;
1444 					}
1445 					hcurHand = CopyCursor(hcur);
1446 					if(!hcurHand)
1447 					{
1448 						FreeLibrary(hinstWinhlp);
1449 						//throw new DflException("Unable to copy cursor resource");
1450 						goto load_failed;
1451 					}
1452 					
1453 					FreeLibrary(hinstWinhlp);
1454 				}
1455 			}
1456 			
1457 			assert(hcurHand);
1458 			// Copy the cursor and own it here so that it's safe to dispose it.
1459 			return new Cursor(CopyCursor(hcurHand));
1460 		}
1461 	}
1462 	
1463 	///
1464 	@property Cursor help() // getter
1465 	{
1466 		HCURSOR hcur;
1467 		hcur = LoadCursorA(HINSTANCE.init, IDC_HELP);
1468 		if(!hcur) // IDC_HELP might not be supported on Windows 95, so fall back to a normal arrow.
1469 			return arrow;
1470 		return new Cursor(hcur);
1471 	}
1472 	
1473 	///
1474 	@property Cursor hSplit() // getter
1475 	{
1476 		// ...
1477 		return sizeNS;
1478 	}
1479 	
1480 	/// ditto
1481 	@property Cursor vSplit() // getter
1482 	{
1483 		// ...
1484 		return sizeWE;
1485 	}
1486 	
1487 	
1488 	///
1489 	@property Cursor iBeam() // getter
1490 	{ return new Cursor(LoadCursorA(HINSTANCE.init, IDC_IBEAM), false); }
1491 	
1492 	///
1493 	@property Cursor no() // getter
1494 	{ return new Cursor(LoadCursorA(HINSTANCE.init, IDC_NO), false); }
1495 	
1496 	
1497 	///
1498 	@property Cursor sizeAll() // getter
1499 	{ return new Cursor(LoadCursorA(HINSTANCE.init, IDC_SIZEALL), false); }
1500 	
1501 	/// ditto
1502 	@property Cursor sizeNESW() // getter
1503 	{ return new Cursor(LoadCursorA(HINSTANCE.init, IDC_SIZENESW), false); }
1504 	
1505 	/// ditto
1506 	@property Cursor sizeNS() // getter
1507 	{ return new Cursor(LoadCursorA(HINSTANCE.init, IDC_SIZENS), false); }
1508 	
1509 	/// ditto
1510 	@property Cursor sizeNWSE() // getter
1511 	{ return new Cursor(LoadCursorA(HINSTANCE.init, IDC_SIZENWSE), false); }
1512 	
1513 	/// ditto
1514 	@property Cursor sizeWE() // getter
1515 	{ return new Cursor(LoadCursorA(HINSTANCE.init, IDC_SIZEWE), false); }
1516 	
1517 	
1518 	/+
1519 	///
1520 	// Insertion point.
1521 	@property Cursor upArrow() // getter
1522 	{
1523 		// ...
1524 	}
1525 	+/
1526 	
1527 	///
1528 	@property Cursor waitCursor() // getter
1529 	{ return new Cursor(LoadCursorA(HINSTANCE.init, IDC_WAIT), false); }
1530 }
1531