2Copyright 2018-2021 Intel Corporation
4Licensed under the Apache License, Version 2.0 (the "License");
5you may not use this file except in compliance with the License.
6You may obtain a copy of the License at
8 http://www.apache.org/licenses/LICENSE-2.0
10Unless required by applicable law or agreed to in writing, software
11distributed under the License is distributed on an "AS IS" BASIS,
12WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13See the License for the specific language governing permissions and
14limitations under the License.
19 NIF_MESSAGE: 0x00000001,
22 NIF_STATE: 0x00000008,
25 NIF_REALTIME: 0x00000040,
26 NIF_SHOWTIP: 0x00000080,
29 NIM_MODIFY: 0x00000001,
30 NIM_DELETE: 0x00000002,
31 NIM_SETFOCUS: 0x00000003,
32 NIM_SETVERSION: 0x00000004
34var NOTIFYICON_VERSION_4 = 4;
35var MessageTypes = { WM_APP: 0x8000, WM_USER: 0x0400 };
36function WindowsConsole()
38 if (process.platform == 'win32')
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');
52 this._handle = this._kernel32.GetConsoleWindow();
53 this.minimize = function () {
54 this._user32.ShowWindow(this._handle, 6);
56 this.restore = function () {
57 this._user32.ShowWindow(this._handle, 9);
59 this.hide = function () {
60 this._user32.ShowWindow(this._handle, 0);
62 this.show = function () {
63 this._user32.ShowWindow(this._handle, 5);
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
72 this.SetTrayIcon = function SetTrayIcon(options)
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);
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);
83 if (!options.noBalloon) { trayType |= TrayIconFlags.NIF_INFO; }
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());
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);
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);
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()); }
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)
118 //console.log('Got HWND');
120 h.pointerBuffer().copy(this.NotifyData.Deref(this.WindowsConsole._Marshal.PointerSize, this.WindowsConsole._Marshal.PointerSize).toBuffer());
122 if(this.WindowsConsole._shell32.Shell_NotifyIconA(TrayIconFlags.NIM_ADD, this.NotifyData).Val == 0)
124 // Something went wrong
127 retVal.MessagePump.on('message', function onWindowsMessage(msg)
129 if(msg.message == this.TrayIcon.Options.filter)
132 if (msg.wparam == 1 && msg.lparam == 1029)
134 this.TrayIcon.emit('ToastClicked');
137 if (msg.wparam == 1 && msg.lparam == 512)
139 this.TrayIcon.emit('IconHover');
142 if (this.TrayIcon.Options.balloonOnly && msg.wparam == 1 && (msg.lparam == 1028 || msg.lparam == 1029))
144 this.TrayIcon.emit('ToastDismissed');
145 this.TrayIcon.remove();
150 retVal.remove = function remove()
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;
163module.exports = new WindowsConsole();