1 /**
2  * Windows GUI window utility code.
3  *
4  * License:
5  *   This Source Code Form is subject to the terms of
6  *   the Mozilla Public License, v. 2.0. If a copy of
7  *   the MPL was not distributed with this file, You
8  *   can obtain one at http://mozilla.org/MPL/2.0/.
9  *
10  * Authors:
11  *   Vladimir Panteleev <vladimir@thecybershadow.net>
12  */
13 
14 module ae.sys.windows.window;
15 
16 import std.range;
17 import std.utf;
18 
19 import win32.winbase;
20 import win32.winnt;
21 import win32.winuser;
22 
23 import ae.sys.windows.exception;
24 import ae.sys.windows.text;
25 
26 struct WindowIterator
27 {
28 private:
29 	LPCWSTR szClassName, szWindowName;
30 	HWND hParent, h;
31 
32 public:
33 	@property
34 	bool empty() const { return h is null; }
35 
36 	@property
37 	HWND front() const { return cast(HWND)h; }
38 
39 	void popFront()
40 	{
41 		h = FindWindowExW(hParent, h, szClassName, szWindowName);
42 	}
43 }
44 
45 WindowIterator windowIterator(string szClassName, string szWindowName, HWND hParent=null)
46 {
47 	auto iterator = WindowIterator(toWStringz(szClassName), toWStringz(szWindowName), hParent);
48 	iterator.popFront(); // initiate search
49 	return iterator;
50 }
51 
52 private static wchar[0xFFFF] textBuf = void;
53 
54 string windowStringQuery(alias FUNC)(HWND h)
55 {
56 	SetLastError(0);
57 	auto result = FUNC(h, textBuf.ptr, textBuf.length);
58 	if (result)
59 		return textBuf[0..result].toUTF8();
60 	else
61 	{
62 		auto code = GetLastError();
63 		if (code)
64 			throw new WindowsException(code, __traits(identifier, FUNC));
65 		else
66 			return null;
67 	}
68 }
69 
70 alias windowStringQuery!GetClassNameW  getClassName;
71 alias windowStringQuery!GetWindowTextW getWindowText;
72 
73 /// Create an utility hidden window.
74 HWND createHiddenWindow(string name, WNDPROC proc)
75 {
76 	auto szName = toWStringz(name);
77 
78 	HINSTANCE hInstance = GetModuleHandle(null);
79 
80 	WNDCLASSEXW wcx;
81 
82 	wcx.cbSize = wcx.sizeof;
83 	wcx.lpfnWndProc = proc;
84 	wcx.hInstance = hInstance;
85 	wcx.lpszClassName = szName;
86 	wenforce(RegisterClassExW(&wcx), "RegisterClassEx failed");
87 
88 	HWND hWnd = CreateWindowW(
89 		szName,              // name of window class
90 		szName,              // title-bar string
91 		WS_OVERLAPPEDWINDOW, // top-level window
92 		CW_USEDEFAULT,       // default horizontal position
93 		CW_USEDEFAULT,       // default vertical position
94 		CW_USEDEFAULT,       // default width
95 		CW_USEDEFAULT,       // default height
96 		null,                // no owner window
97 		null,                // use class menu
98 		hInstance,           // handle to application instance
99 		null);               // no window-creation data
100 	wenforce(hWnd, "CreateWindow failed");
101 
102 	return hWnd;
103 }