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 <ae@cy.md>
12  */
13 
14 module ae.sys.windows.window;
15 version (Windows):
16 
17 import std.range;
18 import std.utf;
19 
20 import ae.sys.windows.imports;
21 mixin(importWin32!q{winbase});
22 mixin(importWin32!q{winnt});
23 mixin(importWin32!q{winuser});
24 
25 import ae.sys.windows.exception;
26 import ae.sys.windows.text;
27 
28 /// `FindWindowExW` wrapper as a D range interface.
29 struct WindowIterator
30 {
31 private:
32 	LPCWSTR szClassName, szWindowName;
33 	HWND hParent, h;
34 
35 public:
36 	@property
37 	bool empty() const { return h is null; } ///
38 
39 	@property
40 	HWND front() const { return cast(HWND)h; } ///
41 
42 	void popFront()
43 	{
44 		h = FindWindowExW(hParent, h, szClassName, szWindowName);
45 	} ///
46 }
47 
48 WindowIterator windowIterator(string szClassName, string szWindowName, HWND hParent=null)
49 {
50 	auto iterator = WindowIterator(toWStringz(szClassName), toWStringz(szWindowName), hParent);
51 	iterator.popFront(); // initiate search
52 	return iterator;
53 } /// ditto
54 
55 private static wchar[0xFFFF] textBuf = void;
56 
57 string _windowStringQuery(alias FUNC)(HWND h)
58 {
59 	SetLastError(0);
60 	auto result = FUNC(h, textBuf.ptr, textBuf.length);
61 	if (result)
62 		return textBuf[0..result].toUTF8();
63 	else
64 	{
65 		auto code = GetLastError();
66 		if (code)
67 			throw new WindowsException(code, __traits(identifier, FUNC));
68 		else
69 			return null;
70 	}
71 }
72 
73 alias _windowStringQuery!GetClassNameW  getClassName ; /// `GetClassNameW` wrapper.
74 alias _windowStringQuery!GetWindowTextW getWindowText; /// `GetWIndowTextW` wrapper.
75 
76 /// Create an utility hidden window.
77 HWND createHiddenWindow(string name, WNDPROC proc)
78 {
79 	auto szName = toWStringz(name);
80 
81 	HINSTANCE hInstance = GetModuleHandle(null);
82 
83 	WNDCLASSEXW wcx;
84 
85 	wcx.cbSize = wcx.sizeof;
86 	wcx.lpfnWndProc = proc;
87 	wcx.hInstance = hInstance;
88 	wcx.lpszClassName = szName;
89 	wenforce(RegisterClassExW(&wcx), "RegisterClassEx failed");
90 
91 	HWND hWnd = CreateWindowW(
92 		szName,              // name of window class
93 		szName,              // title-bar string
94 		WS_OVERLAPPEDWINDOW, // top-level window
95 		CW_USEDEFAULT,       // default horizontal position
96 		CW_USEDEFAULT,       // default vertical position
97 		CW_USEDEFAULT,       // default width
98 		CW_USEDEFAULT,       // default height
99 		null,                // no owner window
100 		null,                // use class menu
101 		hInstance,           // handle to application instance
102 		null);               // no window-creation data
103 	wenforce(hWnd, "CreateWindow failed");
104 
105 	return hWnd;
106 }