master
js 163 lines 6.89 KB
Raw
1 /*
2 Copyright 2018-2021 Intel Corporation
3
4 Licensed under the Apache License, Version 2.0 (the "License");
5 you may not use this file except in compliance with the License.
6 You may obtain a copy of the License at
7
8 http://www.apache.org/licenses/LICENSE-2.0
9
10 Unless required by applicable law or agreed to in writing, software
11 distributed under the License is distributed on an "AS IS" BASIS,
12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 See the License for the specific language governing permissions and
14 limitations under the License.
15 */
16
17 var TrayIconFlags =
18 {
19 NIF_MESSAGE: 0x00000001,
20 NIF_ICON: 0x00000002,
21 NIF_TIP: 0x00000004,
22 NIF_STATE: 0x00000008,
23 NIF_INFO: 0x00000010,
24 NIF_GUID: 0x00000020,
25 NIF_REALTIME: 0x00000040,
26 NIF_SHOWTIP: 0x00000080,
27
28 NIM_ADD: 0x00000000,
29 NIM_MODIFY: 0x00000001,
30 NIM_DELETE: 0x00000002,
31 NIM_SETFOCUS: 0x00000003,
32 NIM_SETVERSION: 0x00000004
33 };
34 var NOTIFYICON_VERSION_4 = 4;
35 var MessageTypes = { WM_APP: 0x8000, WM_USER: 0x0400 };
36 function WindowsConsole()
37 {
38 if (process.platform == 'win32')
39 {
40 this._ObjectID = 'win-console';
41 this._Marshal = require('_GenericMarshal');
42 this._kernel32 = this._Marshal.CreateNativeProxy("kernel32.dll");
43 this._user32 = this._Marshal.CreateNativeProxy("user32.dll");
44 this._kernel32.CreateMethod("GetConsoleWindow");
45 this._kernel32.CreateMethod('GetCurrentThread');
46 this._user32.CreateMethod("ShowWindow");
47 this._user32.CreateMethod("LoadImageA");
48 this._user32.CreateMethod({ method: 'GetMessageA', threadDispatch: 1 });
49 this._shell32 = this._Marshal.CreateNativeProxy('Shell32.dll');
50 this._shell32.CreateMethod('Shell_NotifyIconA');
51
52 this._handle = this._kernel32.GetConsoleWindow();
53 this.minimize = function () {
54 this._user32.ShowWindow(this._handle, 6);
55 };
56 this.restore = function () {
57 this._user32.ShowWindow(this._handle, 9);
58 };
59 this.hide = function () {
60 this._user32.ShowWindow(this._handle, 0);
61 };
62 this.show = function () {
63 this._user32.ShowWindow(this._handle, 5);
64 };
65
66
67 this._loadicon = function (imagePath) {
68 var h = this._user32.LoadImageA(0, this._Marshal.CreateVariable(imagePath), 1, 0, 0, 0x00000010 | 0x00008000 | 0x00000040); // LR_LOADFROMFILE | LR_SHARED | LR_DEFAULTSIZE
69 return (h);
70 };
71
72 this.SetTrayIcon = function SetTrayIcon(options)
73 {
74 var data = this._Marshal.CreateVariable(this._Marshal.PointerSize == 4 ? 508 : 528);
75 //console.log('struct size = ' + data._size);
76 //console.log('TryIcon, WM_MESSAGE filter = ' + options.filter);
77 data.toBuffer().writeUInt32LE(data._size, 0);
78
79 var trayType = TrayIconFlags.NIF_TIP | TrayIconFlags.NIF_MESSAGE
80 options.filter = MessageTypes.WM_APP + 1;
81 data.Deref(this._Marshal.PointerSize == 4 ? 16 : 24, 4).toBuffer().writeUInt32LE(options.filter);
82
83 if (!options.noBalloon) { trayType |= TrayIconFlags.NIF_INFO; }
84
85 if (options.icon)
86 {
87 trayType |= TrayIconFlags.NIF_ICON;
88 var hIcon = data.Deref(this._Marshal.PointerSize == 4 ? 20 : 32, this._Marshal.PointerSize);
89 options.icon.pointerBuffer().copy(hIcon.toBuffer());
90 }
91
92 data.Deref(this._Marshal.PointerSize * 2, 4).toBuffer().writeUInt32LE(1);
93 data.Deref(this._Marshal.PointerSize == 4 ? 12 : 20, 4).toBuffer().writeUInt32LE(trayType);
94 data.Deref(this._Marshal.PointerSize == 4 ? 416 : 432, 4).toBuffer().writeUInt32LE(NOTIFYICON_VERSION_4);
95
96 var szTip = data.Deref(this._Marshal.PointerSize == 4 ? 24 : 40, 128);
97 var szInfo = data.Deref(this._Marshal.PointerSize == 4 ? 160 : 176, 256);
98 var szInfoTitle = data.Deref(this._Marshal.PointerSize == 4 ? 420 : 436, 64);
99
100 if (options.szTip) { Buffer.from(options.szTip).copy(szTip.toBuffer()); }
101 if (options.szInfo) { Buffer.from(options.szInfo).copy(szInfo.toBuffer()); }
102 if (options.szInfoTitle) { Buffer.from(options.szInfoTitle).copy(szInfoTitle.toBuffer()); }
103
104
105 var MessagePump = require('win-message-pump');
106 retVal = { _ObjectID: 'WindowsConsole.TrayIcon', MessagePump: new MessagePump(options) };
107 var retValEvents = require('events').inherits(retVal);
108 retValEvents.createEvent('ToastClicked');
109 retValEvents.createEvent('IconHover');
110 retValEvents.createEvent('ToastDismissed');
111 retVal.Options = options;
112 retVal.MessagePump.TrayIcon = retVal;
113 retVal.MessagePump.NotifyData = data;
114 retVal.MessagePump.WindowsConsole = this;
115 retVal.MessagePump.on('exit', function onExit(code) { console.log('Pump Exited'); if (this.TrayIcon) { this.TrayIcon.remove(); } });
116 retVal.MessagePump.on('hwnd', function onHwnd(h)
117 {
118 //console.log('Got HWND');
119 options.hwnd = h;
120 h.pointerBuffer().copy(this.NotifyData.Deref(this.WindowsConsole._Marshal.PointerSize, this.WindowsConsole._Marshal.PointerSize).toBuffer());
121
122 if(this.WindowsConsole._shell32.Shell_NotifyIconA(TrayIconFlags.NIM_ADD, this.NotifyData).Val == 0)
123 {
124 // Something went wrong
125 }
126 });
127 retVal.MessagePump.on('message', function onWindowsMessage(msg)
128 {
129 if(msg.message == this.TrayIcon.Options.filter)
130 {
131 var handled = false;
132 if (msg.wparam == 1 && msg.lparam == 1029)
133 {
134 this.TrayIcon.emit('ToastClicked');
135 handled = true;
136 }
137 if (msg.wparam == 1 && msg.lparam == 512)
138 {
139 this.TrayIcon.emit('IconHover');
140 handled = true;
141 }
142 if (this.TrayIcon.Options.balloonOnly && msg.wparam == 1 && (msg.lparam == 1028 || msg.lparam == 1029))
143 {
144 this.TrayIcon.emit('ToastDismissed');
145 this.TrayIcon.remove();
146 handled = true;
147 }
148 }
149 });
150 retVal.remove = function remove()
151 {
152 this.MessagePump.WindowsConsole._shell32.Shell_NotifyIconA(TrayIconFlags.NIM_DELETE, this.MessagePump.NotifyData);
153 this.MessagePump.stop();
154 delete this.MessagePump.TrayIcon;
155 delete this.MessagePump;
156 };
157 return (retVal);
158
159 };
160 }
161 }
162
163 module.exports = new WindowsConsole();