├── linux ├── goproxy-gtk.desktop ├── goproxy-gtk.png └── goproxy-gtk.py ├── macos ├── goproxy-macos.command └── python.icns └── windows ├── .gitignore ├── ReadMe.txt ├── promgui.exe ├── resource.h ├── small.ico ├── taskbar.c ├── taskbar.ico ├── taskbar.o └── taskbar.rc /linux/goproxy-gtk.desktop: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env xdg-open 2 | [Desktop Entry] 3 | Type=Application 4 | Name=GoProxy GTK 5 | Comment=GoProxy GTK Launcher 6 | Categories=Network;Proxy; 7 | Exec=bash -c "export PATH=$PATH:`dirname '%k'`; goproxy-gtk.py" 8 | Icon=applications-internet 9 | Terminal=false 10 | StartupNotify=true -------------------------------------------------------------------------------- /linux/goproxy-gtk.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/phuslu/taskbar/80e4a0b97e8ed9427d9054138891828bf30aad35/linux/goproxy-gtk.png -------------------------------------------------------------------------------- /linux/goproxy-gtk.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python2 2 | # coding:utf-8 3 | 4 | import sys 5 | import os 6 | import re 7 | import threading 8 | import base64 9 | import platform 10 | 11 | if platform.mac_ver()[0] > '10.': 12 | sys.exit(os.system( 13 | 'osascript -e \'display dialog "Please click goproxy-macos.command" buttons {"OK"} default button 1 with icon caution with title "GoProxy GTK"\'')) 14 | 15 | try: 16 | import pygtk 17 | pygtk.require('2.0') 18 | import gtk 19 | # gtk.gdk.threads_init() 20 | except Exception: 21 | sys.exit(os.system( 22 | 'gdialog --title "GoProxy GTK" --msgbox "Please install python-gtk2" 15 60')) 23 | try: 24 | import pynotify 25 | pynotify.init('GoProxy Notify') 26 | except ImportError: 27 | pynotify = None 28 | try: 29 | import appindicator 30 | except ImportError: 31 | if os.getenv('XDG_CURRENT_DESKTOP', '').lower() == 'unity': 32 | sys.exit(gtk.MessageDialog(None, gtk.DIALOG_MODAL, gtk.MESSAGE_ERROR, 33 | gtk.BUTTONS_OK, u'Please install python-appindicator').run()) 34 | appindicator = None 35 | try: 36 | import vte 37 | except ImportError: 38 | sys.exit(gtk.MessageDialog(None, gtk.DIALOG_MODAL, gtk.MESSAGE_ERROR, 39 | gtk.BUTTONS_OK, u'Please install python-vte').run()) 40 | 41 | 42 | def spawn_later(seconds, target, *args, **kwargs): 43 | def wrap(*args, **kwargs): 44 | import time 45 | time.sleep(seconds) 46 | return target(*args, **kwargs) 47 | t = threading.Thread(target=wrap, args=args, kwargs=kwargs) 48 | t.setDaemon(True) 49 | t.run() 50 | 51 | 52 | def rewrite_desktop(filename): 53 | with open(filename, 'rb') as fp: 54 | content = fp.read() 55 | if 'goproxy-gtk.png' not in content: 56 | content = re.sub(r'Icon=\S*', 'Icon=%s/goproxy-gtk.png' % os.getcwd(), content) 57 | with open(filename, 'wb') as fp: 58 | fp.write(content) 59 | 60 | #gtk.main_quit = lambda: None 61 | #appindicator = None 62 | 63 | 64 | class GoProxyGTK: 65 | 66 | command = [ 67 | os.path.join(os.path.dirname(os.path.abspath(__file__)), 'goproxy'), '-v=2'] 68 | message = u'GoProxy already started.' 69 | fail_message = u'GoProxy start failed, see the terminal' 70 | 71 | def __init__(self, window, terminal): 72 | self.window = window 73 | self.window.set_size_request(652, 447) 74 | self.window.set_position(gtk.WIN_POS_CENTER) 75 | self.window.connect('delete-event', self.delete_event) 76 | self.terminal = terminal 77 | 78 | self.window.add(terminal) 79 | self.childpid = self.terminal.fork_command( 80 | self.command[0], self.command, os.getcwd()) 81 | if self.childpid > 0: 82 | self.childexited = self.terminal.connect( 83 | 'child-exited', self.on_child_exited) 84 | self.window.connect('delete-event', lambda w, e: gtk.main_quit()) 85 | else: 86 | self.childexited = None 87 | 88 | spawn_later(0.5, self.show_startup_notify) 89 | 90 | self.window.show_all() 91 | 92 | logo_filename = os.path.join( 93 | os.path.abspath(os.path.dirname(__file__)), 'goproxy-gtk.png') 94 | self.window.set_icon_from_file(logo_filename) 95 | 96 | if appindicator: 97 | self.trayicon = appindicator.Indicator( 98 | 'GoProxy', 'indicator-messages', appindicator.CATEGORY_APPLICATION_STATUS) 99 | self.trayicon.set_status(appindicator.STATUS_ACTIVE) 100 | self.trayicon.set_attention_icon('indicator-messages-new') 101 | self.trayicon.set_icon(logo_filename) 102 | self.trayicon.set_menu(self.make_menu()) 103 | else: 104 | self.trayicon = gtk.StatusIcon() 105 | self.trayicon.set_from_file(logo_filename) 106 | self.trayicon.connect('popup-menu', lambda i, b, t: self.make_menu().popup( 107 | None, None, gtk.status_icon_position_menu, b, t, self.trayicon)) 108 | self.trayicon.connect('activate', self.show_hide_toggle) 109 | self.trayicon.set_tooltip('GoProxy') 110 | self.trayicon.set_visible(True) 111 | 112 | def make_menu(self): 113 | menu = gtk.Menu() 114 | itemlist = [(u'Show', self.on_show), 115 | (u'Hide', self.on_hide), 116 | (u'Stop', self.on_stop), 117 | (u'Reload', self.on_reload), 118 | (u'Quit', self.on_quit)] 119 | for text, callback in itemlist: 120 | item = gtk.MenuItem(text) 121 | item.connect('activate', callback) 122 | item.show() 123 | menu.append(item) 124 | menu.show() 125 | return menu 126 | 127 | def show_notify(self, message=None, timeout=None): 128 | if pynotify and message: 129 | notification = pynotify.Notification('GoProxy Notify', message) 130 | notification.set_hint('x', 200) 131 | notification.set_hint('y', 400) 132 | if timeout: 133 | notification.set_timeout(timeout) 134 | notification.show() 135 | 136 | def show_startup_notify(self): 137 | if self.check_child_exists(): 138 | self.show_notify(self.message, timeout=3) 139 | 140 | def check_child_exists(self): 141 | if self.childpid <= 0: 142 | return False 143 | cmd = 'ps -p %s' % self.childpid 144 | lines = os.popen(cmd).read().strip().splitlines() 145 | if len(lines) < 2: 146 | return False 147 | return True 148 | 149 | def on_child_exited(self, term): 150 | if self.terminal.get_child_exit_status() == 0: 151 | gtk.main_quit() 152 | else: 153 | self.show_notify(self.fail_message) 154 | 155 | def on_show(self, widget, data=None): 156 | self.window.show_all() 157 | self.window.present() 158 | self.terminal.feed('\r') 159 | 160 | def on_hide(self, widget, data=None): 161 | self.window.hide_all() 162 | 163 | def on_stop(self, widget, data=None): 164 | if self.childexited: 165 | self.terminal.disconnect(self.childexited) 166 | os.system('kill -9 %s' % self.childpid) 167 | 168 | def on_reload(self, widget, data=None): 169 | if self.childexited: 170 | self.terminal.disconnect(self.childexited) 171 | os.system('kill -9 %s' % self.childpid) 172 | self.on_show(widget, data) 173 | self.childpid = self.terminal.fork_command( 174 | self.command[0], self.command, os.getcwd()) 175 | self.childexited = self.terminal.connect( 176 | 'child-exited', lambda term: gtk.main_quit()) 177 | 178 | def show_hide_toggle(self, widget, data=None): 179 | if self.window.get_property('visible'): 180 | self.on_hide(widget, data) 181 | else: 182 | self.on_show(widget, data) 183 | 184 | def delete_event(self, widget, data=None): 185 | self.on_hide(widget, data) 186 | return True 187 | 188 | def on_quit(self, widget, data=None): 189 | gtk.main_quit() 190 | 191 | 192 | def main(): 193 | global __file__ 194 | __file__ = os.path.abspath(__file__) 195 | if os.path.islink(__file__): 196 | __file__ = getattr(os, 'readlink', lambda x: x)(__file__) 197 | os.chdir(os.path.dirname(os.path.abspath(__file__))) 198 | 199 | if os.path.isfile('goproxy-gtk.desktop'): 200 | rewrite_desktop('goproxy-gtk.desktop') 201 | 202 | window = gtk.Window() 203 | terminal = vte.Terminal() 204 | GoProxyGTK(window, terminal) 205 | gtk.main() 206 | 207 | if __name__ == '__main__': 208 | main() 209 | -------------------------------------------------------------------------------- /macos/goproxy-macos.command: -------------------------------------------------------------------------------- 1 | (/usr/bin/python2.7 -x "$0" >/dev/null 2>&1 &); exit 2 | #!/usr/bin/python2.7 3 | # coding:utf-8 4 | 5 | __version__ = '1.6' 6 | 7 | GOPROXY_TITLE = "GoProxy macOS" 8 | GOPROXY_ICON_DATA = """\ 9 | iVBORw0KGgoAAAANSUhEUgAAADAAAAAwCAYAAABXAvmHAAAD3ElEQVRoQ+2ZWchN 10 | URTHf58hY2YZQlHGB1NIhlJmEsULyoMpKR4oSciYUDLkRZQylQcZMhOZx1A8kAxJ 11 | SiRjyNS/9qfvu+45e+17Nl+3rLpPd+21/v+z9lnTKaHIpaTI8fOfQEVHMHYEGgB9 12 | gY5Aa6AuUAP4ArwGngB3gCvAuxjkYxBoBEx0vx5gupbfgXPALmAP8KlQMlkINAEW 13 | ANPcUy4UgyKzFtgAfA41UggBnZkOrHZXJNRnkv5DYDJwPsRgKAHd6e3AmBAnAbo/ 14 | XFTXAD8t50IINAOOAZ0thjPqDHe+vGasBBoDF4B2XovZFRYDy61mLASqu4zR02o0 15 | g14QePmxENgMzDSCUno8DOwHrgFPXYqsDbRxNWIcMCCPvWDwFgIDgVNG8MrpC12x 16 | 8h3pDmwC+jjFgsD7CFQB7gLtPWjeA5PcU/cBL/t/ZWAl8DHkzuc6SLtCqq47PYje 17 | AoOAGyHIY+qmEbgFdE1xppwt8GdiAgq1lUSgC3DbY2yVKzqhPqPqJxFYBixK8fTS 18 | dZsFN2GxWCQRUNFSW5wkS4ClsUBksZOPgLLDB0AFLEnaAmq+LDIbGGJR9Oh8Bcbm 19 | 9kj5CGgQeZRi7BnQKgDQVmBKgH6aanPgRVmFfARUXC6mWFFDp2bLKjEJaGC66SOg 20 | cB9PQbfDFa6KIKC0fbqYCQwFTvgI+K6QojPM+viBmFeov2vrf7sv5CV+DrS0TkyR 21 | Cagz0FYjlYAljXYA7hujsMXNuhZ1+U6TeoD6r1QC+lODdb8USys8ldoCNldH+yOB 22 | q5pw+BWgybCcJFViVVn16EmiVYjqhVrpWDLa05IfAUZaCWhwL3fX8qBcB8yNhR44 23 | 6brbJJPz3SrHFAEp+dpprT1GWLcHHqKjgIMeHQ1WD6wRkN4Et/pLs6ueSYXvcoZI 24 | CNglQHvVJLkO9Mr3Z9pAo5FS16iTB5xa6qluxxnKQ6AOAE09BzUd7g4lIH1tD6wT 25 | 1z434FjSa0NgHjAH0INKk3tuMvxWCAGd2QjMMj5avRd6GbVWueo2FIpQLaAF0A1Q 26 | O6CMo7RpkcFpmxHLXqgacBbobfEWWUerF80TiWIhoMP6BqDipgr8r0QPTT2XPo5k 27 | JiADetGOejYVschpqyfwb3wGrREotVMH2AZoPfi35JBL4UrRXgklIIM6oxFRO/z6 28 | Xg92Bb3sWk2uD+h0TcvdJAhqrFTeZwA17Tj/0FR61AZQvZfm7SApJAK5DpTTx7uP 29 | fCpMlYwIVCT3AhpRg4GX+ohBoCxe9eua6PSZVev00s+suh76rPrYzRFqPdQeZ5bY 30 | BDIDCjXwn0DoE4utX/QR+AWJ6qQxh9YO5QAAAABJRU5ErkJggg==""" 31 | 32 | import sys 33 | import subprocess 34 | import pty 35 | import os 36 | import base64 37 | import ctypes 38 | import ctypes.util 39 | 40 | from PyObjCTools import AppHelper 41 | from AppKit import * 42 | 43 | ColorSet = [NSColor.whiteColor(), 44 | NSColor.colorWithDeviceRed_green_blue_alpha_(0.7578125,0.2109375,0.12890625,1.0), 45 | NSColor.colorWithDeviceRed_green_blue_alpha_(0.14453125,0.734375,0.140625,1.0), 46 | NSColor.colorWithDeviceRed_green_blue_alpha_(0.67578125,0.67578125,0.15234375,1.0), 47 | NSColor.colorWithDeviceRed_green_blue_alpha_(0.28515625,0.1796875,0.87890625,1.0), 48 | NSColor.colorWithDeviceRed_green_blue_alpha_(0.82421875,0.21875,0.82421875,1.0), 49 | NSColor.colorWithDeviceRed_green_blue_alpha_(0.19921875,0.73046875,0.78125,1.0), 50 | NSColor.colorWithDeviceRed_green_blue_alpha_(0.79296875,0.796875,0.80078125,1.0)] 51 | 52 | ConsoleFont = NSFont.fontWithName_size_("Monaco", 12.0) 53 | 54 | 55 | class GoProxyMacOS(NSObject): 56 | 57 | console_color = ColorSet[0] 58 | 59 | def applicationDidFinishLaunching_(self, notification): 60 | self.setupUI() 61 | self.startGoProxy() 62 | self.notify() 63 | self.registerObserver() 64 | 65 | def windowWillClose_(self, notification): 66 | self.stopGoProxy() 67 | NSApp.terminate_(self) 68 | 69 | def setupUI(self): 70 | self.statusbar = NSStatusBar.systemStatusBar() 71 | # Create the statusbar item 72 | self.statusitem = self.statusbar.statusItemWithLength_(NSVariableStatusItemLength) 73 | # Set initial image 74 | raw_data = base64.b64decode(''.join(GOPROXY_ICON_DATA.strip().splitlines())) 75 | self.image_data = NSData.dataWithBytes_length_(raw_data, len(raw_data)) 76 | self.image = NSImage.alloc().initWithData_(self.image_data) 77 | self.image.setSize_((18, 18)) 78 | self.image.setTemplate_(True) 79 | self.statusitem.setImage_(self.image) 80 | # Let it highlight upon clicking 81 | self.statusitem.setHighlightMode_(1) 82 | # Set a tooltip 83 | self.statusitem.setToolTip_(GOPROXY_TITLE) 84 | 85 | # Build a very simple menu 86 | self.menu = NSMenu.alloc().init() 87 | # Show Menu Item 88 | self.menu.addItemWithTitle_action_keyEquivalent_('Show', self.show_, '').setTarget_(self) 89 | # Hide Menu Item 90 | self.menu.addItemWithTitle_action_keyEquivalent_('Hide', self.hide2_, '').setTarget_(self) 91 | # Proxy Menu Item 92 | menuitem = NSMenuItem.alloc().initWithTitle_action_keyEquivalent_('Set Proxy', None, '') 93 | submenu = NSMenu.alloc().init() 94 | submenu.addItemWithTitle_action_keyEquivalent_('', self.setproxy0_, '').setTarget_(self) 95 | submenu.addItemWithTitle_action_keyEquivalent_('http://127.0.0.1:8087/proxy.pac', self.setproxy1_, '').setTarget_(self) 96 | submenu.addItemWithTitle_action_keyEquivalent_('127.0.0.1:8087', self.setproxy2_, '').setTarget_(self) 97 | menuitem.setSubmenu_(submenu) 98 | self.menu.addItem_(menuitem) 99 | # Rest Menu Item 100 | self.menu.addItemWithTitle_action_keyEquivalent_('Reload', self.reset_, '').setTarget_(self) 101 | # Default event 102 | self.menu.addItemWithTitle_action_keyEquivalent_('Quit', self.exit_, '').setTarget_(self) 103 | # Bind it to the status item 104 | self.statusitem.setMenu_(self.menu) 105 | 106 | # Console window 107 | frame = NSMakeRect(0, 0, 640, 480) 108 | self.console_window = NSWindow.alloc().initWithContentRect_styleMask_backing_defer_(frame, NSClosableWindowMask | NSTitledWindowMask, NSBackingStoreBuffered, False) 109 | self.console_window.setTitle_(GOPROXY_TITLE) 110 | self.console_window.setDelegate_(self) 111 | 112 | # Console view inside a scrollview 113 | self.scroll_view = NSScrollView.alloc().initWithFrame_(frame) 114 | self.scroll_view.setBorderType_(NSNoBorder) 115 | self.scroll_view.setHasVerticalScroller_(True) 116 | self.scroll_view.setHasHorizontalScroller_(False) 117 | self.scroll_view.setAutoresizingMask_(NSViewWidthSizable | NSViewHeightSizable) 118 | 119 | self.console_view = NSTextView.alloc().initWithFrame_(frame) 120 | self.console_view.setBackgroundColor_(NSColor.blackColor()) 121 | self.console_view.setRichText_(True) 122 | self.console_view.setVerticallyResizable_(True) 123 | self.console_view.setHorizontallyResizable_(True) 124 | self.console_view.setAutoresizingMask_(NSViewWidthSizable) 125 | 126 | self.scroll_view.setDocumentView_(self.console_view) 127 | 128 | contentView = self.console_window.contentView() 129 | contentView.addSubview_(self.scroll_view) 130 | 131 | # Hide dock icon 132 | NSApp.setActivationPolicy_(NSApplicationActivationPolicyProhibited) 133 | 134 | def registerObserver(self): 135 | nc = NSWorkspace.sharedWorkspace().notificationCenter() 136 | nc.addObserver_selector_name_object_(self, 'exit:', NSWorkspaceWillPowerOffNotification, None) 137 | 138 | def startGoProxy(self): 139 | cmd = '%s/goproxy' % os.path.dirname(os.path.abspath(__file__)) 140 | self.master, self.slave = pty.openpty() 141 | self.pipe = subprocess.Popen(cmd, shell=True, stdin=subprocess.PIPE, stdout=self.slave, stderr=self.slave, close_fds=True) 142 | self.pipe_fd = os.fdopen(self.master) 143 | self.performSelectorInBackground_withObject_('readProxyOutput', None) 144 | 145 | def notify(self): 146 | from Foundation import NSUserNotification, NSUserNotificationCenter 147 | notification = NSUserNotification.alloc().init() 148 | notification.setTitle_("GoProxy macOS Started.") 149 | notification.setSubtitle_("") 150 | notification.setInformativeText_("") 151 | notification.setSoundName_("NSUserNotificationDefaultSoundName") 152 | notification.setContentImage_(self.image) 153 | NSUserNotificationCenter.defaultUserNotificationCenter().scheduleNotification_(notification) 154 | 155 | def stopGoProxy(self): 156 | self.pipe.terminate() 157 | 158 | def parseLine(self, line): 159 | if line.startswith('\x1b]2;') and '\x07' in line: 160 | global GOPROXY_TITLE 161 | pos = line.find('\x07') 162 | GOPROXY_TITLE = line[4:pos] 163 | self.statusitem.setToolTip_(GOPROXY_TITLE) 164 | self.console_window.setTitle_(GOPROXY_TITLE) 165 | return self.parseLine(line[pos:]) 166 | while line.startswith('\x1b['): 167 | line = line[2:] 168 | color_number = int(line.split('m',1)[0]) 169 | if 30 <= color_number < 38: 170 | self.console_color = ColorSet[color_number-30] 171 | elif color_number == 0: 172 | self.console_color = ColorSet[0] 173 | line = line.split('m',1)[1] 174 | return line 175 | 176 | def refreshDisplay_(self, line): 177 | line = self.parseLine(line) 178 | console_line = NSMutableAttributedString.alloc().initWithString_(line) 179 | console_line.addAttribute_value_range_(NSForegroundColorAttributeName, self.console_color, NSMakeRange(0,len(line))) 180 | self.console_view.textStorage().appendAttributedString_(console_line) 181 | self.console_view.textStorage().setFont_(ConsoleFont) 182 | need_scroll = NSMaxY(self.console_view.visibleRect()) >= NSMaxY(self.console_view.bounds()) 183 | if need_scroll: 184 | range = NSMakeRange(len(self.console_view.textStorage().mutableString()), 0) 185 | self.console_view.scrollRangeToVisible_(range) 186 | # self.console_view.textContainer().setWidthTracksTextView_(False) 187 | # self.console_view.textContainer().setContainerSize_((640, 480)) 188 | 189 | def readProxyOutput(self): 190 | while(True): 191 | line = self.pipe_fd.readline() 192 | self.performSelectorOnMainThread_withObject_waitUntilDone_('refreshDisplay:', line, None) 193 | 194 | def setproxy0_(self, notification): 195 | cmds = [] 196 | network = 'Wi-Fi' 197 | cmds.append('networksetup -setwebproxystate %s off' % network) 198 | cmds.append('networksetup -setsecurewebproxystate %s off' % network) 199 | cmds.append('networksetup -setautoproxystate %s off' % network) 200 | cmd = "osascript -e 'do shell script \"" + ' && '.join(cmds) + "\" with administrator privileges'" 201 | os.system(cmd) 202 | 203 | def setproxy1_(self, notification): 204 | cmds = [] 205 | network = 'Wi-Fi' 206 | cmds.append('networksetup -setautoproxyurl %s http://127.0.0.1:8087/proxy.pac' % network) 207 | cmds.append('networksetup -setautoproxystate %s on' % network) 208 | cmds.append('networksetup -setwebproxystate %s off' % network) 209 | cmds.append('networksetup -setsecurewebproxystate %s off' % network) 210 | cmd = "osascript -e 'do shell script \"" + ' && '.join(cmds) + "\" with administrator privileges'" 211 | os.system(cmd) 212 | 213 | def setproxy2_(self, notification): 214 | cmds = [] 215 | network = 'Wi-Fi' 216 | cmds.append('networksetup -setwebproxy %s 127.0.0.1 8087' % network) 217 | cmds.append('networksetup -setwebproxystate %s on' % network) 218 | cmds.append('networksetup -setsecurewebproxy %s 127.0.0.1 8087' % network) 219 | cmds.append('networksetup -setsecurewebproxystate %s on' % network) 220 | cmds.append('networksetup -setautoproxystate %s off' % network) 221 | cmd = "osascript -e 'do shell script \"" + ' && '.join(cmds) + "\" with administrator privileges'" 222 | os.system(cmd) 223 | 224 | def show_(self, notification): 225 | self.console_window.center() 226 | self.console_window.orderFrontRegardless() 227 | self.console_window.setIsVisible_(True) 228 | 229 | def hide2_(self, notification): 230 | self.console_window.setIsVisible_(False) 231 | #self.console_window.orderOut(None) 232 | 233 | def reset_(self, notification): 234 | self.show_(True) 235 | self.stopGoProxy() 236 | self.console_view.setString_('') 237 | self.startGoProxy() 238 | 239 | def exit_(self, notification): 240 | self.stopGoProxy() 241 | NSApp.terminate_(self) 242 | 243 | 244 | def main(): 245 | global __file__ 246 | __file__ = os.path.abspath(__file__) 247 | if os.path.islink(__file__): 248 | __file__ = getattr(os, 'readlink', lambda x: x)(__file__) 249 | os.chdir(os.path.dirname(os.path.abspath(__file__))) 250 | 251 | app = NSApplication.sharedApplication() 252 | delegate = GoProxyMacOS.alloc().init() 253 | app.setDelegate_(delegate) 254 | 255 | AppHelper.runEventLoop() 256 | 257 | if __name__ == '__main__': 258 | main() 259 | -------------------------------------------------------------------------------- /macos/python.icns: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/phuslu/taskbar/80e4a0b97e8ed9427d9054138891828bf30aad35/macos/python.icns -------------------------------------------------------------------------------- /windows/.gitignore: -------------------------------------------------------------------------------- 1 | *.ncb 2 | *.plg 3 | *.obj 4 | *.res 5 | *.idb 6 | *.bsc 7 | *.sbr 8 | *.aps 9 | -------------------------------------------------------------------------------- /windows/ReadMe.txt: -------------------------------------------------------------------------------- 1 | i686-w64-mingw32-windres taskbar.rc -O coff -o taskbar.res 2 | i686-w64-mingw32-gcc -Wall -Os -O3 -m32 -s -std=c99 -Wl,--subsystem,windows -c taskbar.c 3 | i686-w64-mingw32-gcc -static -Os -s -o goproxy-gui.exe taskbar.o taskbar.res -lstdc++ -lwininet -------------------------------------------------------------------------------- /windows/promgui.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/phuslu/taskbar/80e4a0b97e8ed9427d9054138891828bf30aad35/windows/promgui.exe -------------------------------------------------------------------------------- /windows/resource.h: -------------------------------------------------------------------------------- 1 | //{{NO_DEPENDENCIES}} 2 | // Microsoft Developer Studio generated include file. 3 | // Used by taskbar.rc 4 | // 5 | #define IDS_CMDLINE 1 6 | #define IDS_ENVIRONMENT 2 7 | #define IDS_PROXYLIST 3 8 | #define IDS_RASPBK 4 9 | #define IDI_ICON1 101 10 | #define IDI_ICON2 104 11 | #define IDI_TASKBAR 105 12 | #define IDI_SMALL 106 13 | 14 | // Next default values for new objects 15 | // 16 | #ifdef APSTUDIO_INVOKED 17 | #ifndef APSTUDIO_READONLY_SYMBOLS 18 | #define _APS_NEXT_RESOURCE_VALUE 107 19 | #define _APS_NEXT_COMMAND_VALUE 40001 20 | #define _APS_NEXT_CONTROL_VALUE 1000 21 | #define _APS_NEXT_SYMED_VALUE 101 22 | #endif 23 | #endif 24 | -------------------------------------------------------------------------------- /windows/small.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/phuslu/taskbar/80e4a0b97e8ed9427d9054138891828bf30aad35/windows/small.ico -------------------------------------------------------------------------------- /windows/taskbar.c: -------------------------------------------------------------------------------- 1 | #define UNICODE 2 | #define _UNICODE 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include "resource.h" 15 | 16 | #ifndef __cplusplus 17 | #undef NULL 18 | #define NULL 0 19 | extern WINBASEAPI HWND WINAPI GetConsoleWindow(); 20 | #else 21 | extern "C" WINBASEAPI HWND WINAPI GetConsoleWindow(); 22 | #endif 23 | 24 | #define NID_UID 123 25 | #define WM_TASKBARNOTIFY WM_USER+20 26 | #define WM_TASKBARNOTIFY_MENUITEM_SHOW (WM_USER + 21) 27 | #define WM_TASKBARNOTIFY_MENUITEM_HIDE (WM_USER + 22) 28 | #define WM_TASKBARNOTIFY_MENUITEM_RELOAD (WM_USER + 23) 29 | #define WM_TASKBARNOTIFY_MENUITEM_ABOUT (WM_USER + 24) 30 | #define WM_TASKBARNOTIFY_MENUITEM_EXIT (WM_USER + 25) 31 | #define WM_TASKBARNOTIFY_MENUITEM_PROXYLIST_BASE (WM_USER + 26) 32 | 33 | HINSTANCE hInst; 34 | HWND hWnd; 35 | HWND hConsole; 36 | WCHAR szTitle[64] = L""; 37 | WCHAR szWindowClass[16] = L"taskbar"; 38 | WCHAR szCommandLine[1024] = L""; 39 | WCHAR szTooltip[512] = L""; 40 | WCHAR szBalloon[512] = L""; 41 | WCHAR szEnvironment[1024] = L""; 42 | WCHAR szProxyString[2048] = L""; 43 | CHAR szRasPbk[4096] = ""; 44 | WCHAR *lpProxyList[8] = {0}; 45 | volatile DWORD dwChildrenPid; 46 | 47 | static DWORD MyGetProcessId(HANDLE hProcess) 48 | { 49 | // https://gist.github.com/kusma/268888 50 | typedef DWORD (WINAPI *pfnGPI)(HANDLE); 51 | typedef ULONG (WINAPI *pfnNTQIP)(HANDLE, ULONG, PVOID, ULONG, PULONG); 52 | 53 | static int first = 1; 54 | static pfnGPI pfnGetProcessId; 55 | static pfnNTQIP ZwQueryInformationProcess; 56 | if (first) 57 | { 58 | first = 0; 59 | pfnGetProcessId = (pfnGPI)GetProcAddress( 60 | GetModuleHandleW(L"KERNEL32.DLL"), "GetProcessId"); 61 | if (!pfnGetProcessId) 62 | ZwQueryInformationProcess = (pfnNTQIP)GetProcAddress( 63 | GetModuleHandleW(L"NTDLL.DLL"), 64 | "ZwQueryInformationProcess"); 65 | } 66 | if (pfnGetProcessId) 67 | return pfnGetProcessId(hProcess); 68 | if (ZwQueryInformationProcess) 69 | { 70 | struct 71 | { 72 | PVOID Reserved1; 73 | PVOID PebBaseAddress; 74 | PVOID Reserved2[2]; 75 | ULONG UniqueProcessId; 76 | PVOID Reserved3; 77 | } pbi; 78 | ZwQueryInformationProcess(hProcess, 0, &pbi, sizeof(pbi), 0); 79 | return pbi.UniqueProcessId; 80 | } 81 | return 0; 82 | } 83 | 84 | 85 | static BOOL MyEndTask(DWORD pid) 86 | { 87 | WCHAR szCmd[1024] = {0}; 88 | wsprintf(szCmd, L"taskkill /f /pid %d", pid); 89 | return _wsystem(szCmd) == 0; 90 | } 91 | 92 | BOOL ShowTrayIcon(LPCTSTR lpszProxy, DWORD dwMessage) 93 | { 94 | NOTIFYICONDATA nid; 95 | ZeroMemory(&nid, sizeof(NOTIFYICONDATA)); 96 | nid.cbSize = (DWORD)sizeof(NOTIFYICONDATA); 97 | nid.hWnd = hWnd; 98 | nid.uID = NID_UID; 99 | nid.uFlags = NIF_ICON|NIF_MESSAGE; 100 | nid.dwInfoFlags=NIIF_INFO; 101 | nid.uCallbackMessage = WM_TASKBARNOTIFY; 102 | nid.hIcon = LoadIcon(hInst, (LPCTSTR)IDI_SMALL); 103 | nid.uTimeout = 3 * 1000 | NOTIFYICON_VERSION; 104 | lstrcpy(nid.szInfoTitle, szTitle); 105 | if (lpszProxy) 106 | { 107 | nid.uFlags |= NIF_INFO|NIF_TIP; 108 | if (lstrlen(lpszProxy) > 0) 109 | { 110 | lstrcpy(nid.szTip, lpszProxy); 111 | lstrcpy(nid.szInfo, lpszProxy); 112 | } 113 | else 114 | { 115 | lstrcpy(nid.szInfo, szBalloon); 116 | lstrcpy(nid.szTip, szTooltip); 117 | } 118 | } 119 | Shell_NotifyIcon(dwMessage?dwMessage:NIM_ADD, &nid); 120 | return TRUE; 121 | } 122 | 123 | BOOL DeleteTrayIcon() 124 | { 125 | NOTIFYICONDATA nid; 126 | nid.cbSize = (DWORD)sizeof(NOTIFYICONDATA); 127 | nid.hWnd = hWnd; 128 | nid.uID = NID_UID; 129 | Shell_NotifyIcon(NIM_DELETE, &nid); 130 | return TRUE; 131 | } 132 | 133 | 134 | LPCTSTR GetWindowsProxy() 135 | { 136 | static WCHAR szProxy[1024] = {0}; 137 | HKEY hKey; 138 | DWORD dwData = 0; 139 | DWORD dwSize = sizeof(DWORD); 140 | 141 | if (ERROR_SUCCESS == RegOpenKeyEx(HKEY_CURRENT_USER, 142 | L"Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings", 143 | 0, 144 | KEY_READ | 0x0200, 145 | &hKey)) 146 | { 147 | szProxy[0] = 0; 148 | dwSize = sizeof(szProxy)/sizeof(szProxy[0]); 149 | RegQueryValueExW(hKey, L"AutoConfigURL", NULL, 0, (LPBYTE)&szProxy, &dwSize); 150 | if (wcslen(szProxy)) 151 | { 152 | RegCloseKey(hKey); 153 | return szProxy; 154 | } 155 | dwData = 0; 156 | RegQueryValueExW(hKey, L"ProxyEnable", NULL, 0, (LPBYTE)&dwData, &dwSize); 157 | if (dwData == 0) 158 | { 159 | RegCloseKey(hKey); 160 | return L""; 161 | } 162 | szProxy[0] = 0; 163 | dwSize = sizeof(szProxy)/sizeof(szProxy[0]); 164 | RegQueryValueExW(hKey, L"ProxyServer", NULL, 0, (LPBYTE)&szProxy, &dwSize); 165 | if (wcslen(szProxy)) 166 | { 167 | RegCloseKey(hKey); 168 | return szProxy; 169 | } 170 | } 171 | return szProxy; 172 | } 173 | 174 | 175 | BOOL SetWindowsProxy(WCHAR* szProxy, const WCHAR* szProxyInterface) 176 | { 177 | INTERNET_PER_CONN_OPTION_LIST conn_options; 178 | BOOL bReturn; 179 | DWORD dwBufferSize = sizeof(conn_options); 180 | 181 | if (wcslen(szProxy) == 0) 182 | { 183 | conn_options.dwSize = dwBufferSize; 184 | conn_options.pszConnection = (WCHAR*)szProxyInterface; 185 | conn_options.dwOptionCount = 1; 186 | conn_options.pOptions = (INTERNET_PER_CONN_OPTION*)malloc(sizeof(INTERNET_PER_CONN_OPTION)*conn_options.dwOptionCount); 187 | conn_options.pOptions[0].dwOption = INTERNET_PER_CONN_FLAGS; 188 | conn_options.pOptions[0].Value.dwValue = PROXY_TYPE_DIRECT; 189 | } 190 | else if (wcsstr(szProxy, L"://") != NULL) 191 | { 192 | conn_options.dwSize = dwBufferSize; 193 | conn_options.pszConnection = (WCHAR*)szProxyInterface; 194 | conn_options.dwOptionCount = 3; 195 | conn_options.pOptions = (INTERNET_PER_CONN_OPTION*)malloc(sizeof(INTERNET_PER_CONN_OPTION)*conn_options.dwOptionCount); 196 | conn_options.pOptions[0].dwOption = INTERNET_PER_CONN_FLAGS; 197 | conn_options.pOptions[0].Value.dwValue = PROXY_TYPE_DIRECT | PROXY_TYPE_AUTO_PROXY_URL; 198 | conn_options.pOptions[1].dwOption = INTERNET_PER_CONN_AUTOCONFIG_URL; 199 | conn_options.pOptions[1].Value.pszValue = szProxy; 200 | conn_options.pOptions[2].dwOption = INTERNET_PER_CONN_PROXY_BYPASS; 201 | conn_options.pOptions[2].Value.pszValue = (LPWSTR)L""; 202 | } 203 | else 204 | { 205 | conn_options.dwSize = dwBufferSize; 206 | conn_options.pszConnection = (WCHAR*)szProxyInterface; 207 | conn_options.dwOptionCount = 3; 208 | conn_options.pOptions = (INTERNET_PER_CONN_OPTION*)malloc(sizeof(INTERNET_PER_CONN_OPTION)*conn_options.dwOptionCount); 209 | conn_options.pOptions[0].dwOption = INTERNET_PER_CONN_FLAGS; 210 | conn_options.pOptions[0].Value.dwValue = PROXY_TYPE_DIRECT | PROXY_TYPE_PROXY; 211 | conn_options.pOptions[1].dwOption = INTERNET_PER_CONN_PROXY_SERVER; 212 | conn_options.pOptions[1].Value.pszValue = szProxy; 213 | conn_options.pOptions[2].dwOption = INTERNET_PER_CONN_PROXY_BYPASS; 214 | conn_options.pOptions[2].Value.pszValue = (LPWSTR)L""; 215 | } 216 | 217 | bReturn = InternetSetOption(NULL, INTERNET_OPTION_PER_CONNECTION_OPTION, &conn_options, dwBufferSize); 218 | free(conn_options.pOptions); 219 | InternetSetOption(NULL, INTERNET_OPTION_SETTINGS_CHANGED, NULL, 0); 220 | InternetSetOption(NULL, INTERNET_OPTION_REFRESH , NULL, 0); 221 | return bReturn; 222 | } 223 | 224 | BOOL SetWindowsProxyForAllRasConnections(WCHAR* szProxy) 225 | { 226 | for (LPCSTR lpRasPbk = szRasPbk; *lpRasPbk; lpRasPbk += strlen(lpRasPbk) + 1) 227 | { 228 | char szPath[2048] = ""; 229 | if (ExpandEnvironmentStringsA(lpRasPbk, szPath, sizeof(szPath)/sizeof(szPath[0]))) 230 | { 231 | char line[2048] = ""; 232 | int length = 0; 233 | FILE * fp = fopen(szPath, "r"); 234 | if (fp != NULL) 235 | { 236 | while (!feof(fp)) 237 | { 238 | if (fgets(line, sizeof(line)/sizeof(line[0])-1, fp)) 239 | { 240 | length = strlen(line); 241 | if (length > 3 && line[0] == '[' && line[length-2] == ']') 242 | { 243 | line[length-2] = 0; 244 | WCHAR szSection[64] = L""; 245 | MultiByteToWideChar(CP_UTF8, 0, line+1, -1, szSection, sizeof(szSection)/sizeof(szSection[0])); 246 | SetWindowsProxy(szProxy, szSection); 247 | } 248 | } 249 | } 250 | fclose(fp); 251 | } 252 | } 253 | } 254 | return TRUE; 255 | } 256 | 257 | BOOL ShowPopupMenu() 258 | { 259 | POINT pt; 260 | HMENU hSubMenu = NULL; 261 | BOOL isZHCN = GetSystemDefaultLCID() == 2052; 262 | LPCTSTR lpCurrentProxy = GetWindowsProxy(); 263 | if (lpProxyList[1] != NULL) 264 | { 265 | hSubMenu = CreatePopupMenu(); 266 | for (int i = 0; lpProxyList[i]; i++) 267 | { 268 | UINT uFlags = wcscmp(lpProxyList[i], lpCurrentProxy) == 0 ? MF_STRING | MF_CHECKED : MF_STRING; 269 | LPCTSTR lpText = wcslen(lpProxyList[i]) ? lpProxyList[i] : ( isZHCN ? L"\x7981\x7528\x4ee3\x7406" : L""); 270 | AppendMenu(hSubMenu, uFlags, WM_TASKBARNOTIFY_MENUITEM_PROXYLIST_BASE+i, lpText); 271 | } 272 | } 273 | 274 | HMENU hMenu = CreatePopupMenu(); 275 | AppendMenu(hMenu, MF_STRING, WM_TASKBARNOTIFY_MENUITEM_SHOW, ( isZHCN ? L"\x663e\x793a" : L"Show") ); 276 | AppendMenu(hMenu, MF_STRING, WM_TASKBARNOTIFY_MENUITEM_HIDE, ( isZHCN ? L"\x9690\x85cf" : L"Hide") ); 277 | if (hSubMenu != NULL) 278 | { 279 | AppendMenu(hMenu, MF_STRING | MF_POPUP, (UINT_PTR)hSubMenu, ( isZHCN ? L"\x8bbe\x7f6e IE \x4ee3\x7406" : L"Set IE Proxy") ); 280 | } 281 | AppendMenu(hMenu, MF_STRING, WM_TASKBARNOTIFY_MENUITEM_RELOAD, ( isZHCN ? L"\x91cd\x65b0\x8f7d\x5165" : L"Reload") ); 282 | AppendMenu(hMenu, MF_STRING, WM_TASKBARNOTIFY_MENUITEM_EXIT, ( isZHCN ? L"\x9000\x51fa" : L"Exit") ); 283 | GetCursorPos(&pt); 284 | TrackPopupMenu(hMenu, TPM_LEFTALIGN, pt.x, pt.y, 0, hWnd, NULL); 285 | PostMessage(hWnd, WM_NULL, 0, 0); 286 | if (hSubMenu != NULL) 287 | DestroyMenu(hSubMenu); 288 | DestroyMenu(hMenu); 289 | return TRUE; 290 | } 291 | 292 | BOOL ParseProxyList() 293 | { 294 | WCHAR * tmpProxyString = _wcsdup(szProxyString); 295 | ExpandEnvironmentStrings(tmpProxyString, szProxyString, sizeof(szProxyString)/sizeof(szProxyString[0])); 296 | free(tmpProxyString); 297 | const WCHAR *sep = L"\n"; 298 | WCHAR *pos = wcstok(szProxyString, sep); 299 | UINT i = 0; 300 | lpProxyList[i++] = (LPWSTR)L""; 301 | while (pos && i < sizeof(lpProxyList)/sizeof(lpProxyList[0])) 302 | { 303 | lpProxyList[i++] = pos; 304 | pos = wcstok(NULL, sep); 305 | } 306 | lpProxyList[i] = 0; 307 | 308 | 309 | for (LPSTR ptr = szRasPbk; *ptr; ptr++) 310 | { 311 | if (*ptr == '\n') 312 | { 313 | *ptr++ = 0; 314 | } 315 | } 316 | return TRUE; 317 | } 318 | 319 | BOOL InitInstance(HINSTANCE hInstance, int nCmdShow) 320 | { 321 | hWnd = CreateWindow(szWindowClass, szTitle, WS_OVERLAPPED|WS_SYSMENU, 322 | NULL, NULL, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, hInstance, NULL); 323 | 324 | if (!hWnd) 325 | { 326 | return FALSE; 327 | } 328 | 329 | ShowWindow(hWnd, nCmdShow); 330 | UpdateWindow(hWnd); 331 | 332 | return TRUE; 333 | } 334 | 335 | BOOL CDCurrentDirectory() 336 | { 337 | WCHAR szPath[4096] = L""; 338 | GetModuleFileName(NULL, szPath, sizeof(szPath)/sizeof(szPath[0])-1); 339 | *wcsrchr(szPath, L'\\') = 0; 340 | SetCurrentDirectory(szPath); 341 | SetEnvironmentVariableW(L"CWD", szPath); 342 | return TRUE; 343 | } 344 | 345 | BOOL SetEenvironment() 346 | { 347 | LoadString(hInst, IDS_CMDLINE, szCommandLine, sizeof(szCommandLine)/sizeof(szCommandLine[0])-1); 348 | LoadString(hInst, IDS_ENVIRONMENT, szEnvironment, sizeof(szEnvironment)/sizeof(szEnvironment[0])-1); 349 | LoadString(hInst, IDS_PROXYLIST, szProxyString, sizeof(szProxyString)/sizeof(szEnvironment[0])-1); 350 | LoadStringA(hInst, IDS_RASPBK, szRasPbk, sizeof(szRasPbk)/sizeof(szRasPbk[0])-1); 351 | 352 | const WCHAR *sep = L"\n"; 353 | WCHAR *pos = NULL; 354 | WCHAR *token = wcstok(szEnvironment, sep); 355 | while(token != NULL) 356 | { 357 | if ((pos = wcschr(token, L'=')) != NULL) 358 | { 359 | *pos = 0; 360 | SetEnvironmentVariableW(token, pos+1); 361 | //wprintf(L"[%s] = [%s]\n", token, pos+1); 362 | } 363 | token = wcstok(NULL, sep); 364 | } 365 | 366 | GetEnvironmentVariableW(L"TASKBAR_TITLE", szTitle, sizeof(szTitle)/sizeof(szTitle[0])-1); 367 | GetEnvironmentVariableW(L"TASKBAR_TOOLTIP", szTooltip, sizeof(szTooltip)/sizeof(szTooltip[0])-1); 368 | GetEnvironmentVariableW(L"TASKBAR_BALLOON", szBalloon, sizeof(szBalloon)/sizeof(szBalloon[0])-1); 369 | 370 | return TRUE; 371 | } 372 | 373 | BOOL WINAPI ConsoleHandler(DWORD CEvent) 374 | { 375 | switch(CEvent) 376 | { 377 | case CTRL_LOGOFF_EVENT: 378 | case CTRL_SHUTDOWN_EVENT: 379 | case CTRL_CLOSE_EVENT: 380 | SendMessage(hWnd, WM_CLOSE, NULL, NULL); 381 | break; 382 | } 383 | return TRUE; 384 | } 385 | 386 | BOOL CreateConsole() 387 | { 388 | WCHAR szVisible[BUFSIZ] = L""; 389 | 390 | AllocConsole(); 391 | _wfreopen(L"CONIN$", L"r+t", stdin); 392 | _wfreopen(L"CONOUT$", L"w+t", stdout); 393 | 394 | hConsole = GetConsoleWindow(); 395 | 396 | if (GetEnvironmentVariableW(L"TASKBAR_VISIBLE", szVisible, BUFSIZ-1) && szVisible[0] == L'0') 397 | { 398 | ShowWindow(hConsole, SW_HIDE); 399 | } 400 | else 401 | { 402 | SetForegroundWindow(hConsole); 403 | } 404 | 405 | if (SetConsoleCtrlHandler((PHANDLER_ROUTINE)ConsoleHandler,TRUE)==FALSE) 406 | { 407 | printf("Unable to install handler!\n"); 408 | return FALSE; 409 | } 410 | 411 | CONSOLE_SCREEN_BUFFER_INFO csbi; 412 | if (GetConsoleScreenBufferInfo(GetStdHandle(STD_ERROR_HANDLE), &csbi)) 413 | { 414 | COORD size = csbi.dwSize; 415 | if (size.Y < 2048) 416 | { 417 | size.Y = 2048; 418 | if (!SetConsoleScreenBufferSize(GetStdHandle(STD_ERROR_HANDLE), size)) 419 | { 420 | printf("Unable to set console screen buffer size!\n"); 421 | } 422 | } 423 | } 424 | 425 | return TRUE; 426 | } 427 | 428 | BOOL ExecCmdline() 429 | { 430 | SetWindowText(hConsole, szTitle); 431 | STARTUPINFO si = { sizeof(si) }; 432 | PROCESS_INFORMATION pi; 433 | si.dwFlags = STARTF_USESHOWWINDOW; 434 | si.wShowWindow = TRUE; 435 | BOOL bRet = CreateProcess(NULL, szCommandLine, NULL, NULL, FALSE, NULL, NULL, NULL, &si, &pi); 436 | if(bRet) 437 | { 438 | dwChildrenPid = MyGetProcessId(pi.hProcess); 439 | } 440 | else 441 | { 442 | wprintf(L"ExecCmdline \"%s\" failed!\n", szCommandLine); 443 | MessageBox(NULL, szCommandLine, L"Error: Cannot execute!", MB_OK); 444 | ExitProcess(0); 445 | } 446 | CloseHandle(pi.hThread); 447 | CloseHandle(pi.hProcess); 448 | return TRUE; 449 | } 450 | 451 | BOOL TryDeleteUpdateFiles() 452 | { 453 | WIN32_FIND_DATA FindFileData; 454 | HANDLE hFind; 455 | 456 | hFind = FindFirstFile(L"~*.tmp", &FindFileData); 457 | if (hFind == INVALID_HANDLE_VALUE) 458 | { 459 | return TRUE; 460 | } 461 | 462 | do 463 | { 464 | DeleteFile(FindFileData.cFileName); 465 | if (!FindNextFile(hFind, &FindFileData)) 466 | { 467 | break; 468 | } 469 | } while(TRUE); 470 | FindClose(hFind); 471 | 472 | return TRUE; 473 | } 474 | 475 | BOOL ReloadCmdline() 476 | { 477 | //HANDLE hProcess = OpenProcess(SYNCHRONIZE|PROCESS_TERMINATE, FALSE, dwChildrenPid); 478 | //if (hProcess) 479 | //{ 480 | // TerminateProcess(hProcess, 0); 481 | //} 482 | ShowWindow(hConsole, SW_SHOW); 483 | SetForegroundWindow(hConsole); 484 | wprintf(L"\n\n"); 485 | MyEndTask(dwChildrenPid); 486 | wprintf(L"\n\n"); 487 | Sleep(200); 488 | ExecCmdline(); 489 | return TRUE; 490 | } 491 | 492 | LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) 493 | { 494 | static UINT WM_TASKBARCREATED = 0; 495 | if (WM_TASKBARCREATED == 0) 496 | WM_TASKBARCREATED = RegisterWindowMessage(L"TaskbarCreated"); 497 | 498 | UINT nID; 499 | switch (message) 500 | { 501 | case WM_TASKBARNOTIFY: 502 | if (lParam == WM_LBUTTONUP) 503 | { 504 | ShowWindow(hConsole, !IsWindowVisible(hConsole)); 505 | SetForegroundWindow(hConsole); 506 | } 507 | else if (lParam == WM_RBUTTONUP) 508 | { 509 | SetForegroundWindow(hWnd); 510 | ShowPopupMenu(); 511 | } 512 | break; 513 | case WM_COMMAND: 514 | nID = LOWORD(wParam); 515 | if (nID == WM_TASKBARNOTIFY_MENUITEM_SHOW) 516 | { 517 | ShowWindow(hConsole, SW_SHOW); 518 | SetForegroundWindow(hConsole); 519 | } 520 | else if (nID == WM_TASKBARNOTIFY_MENUITEM_HIDE) 521 | { 522 | ShowWindow(hConsole, SW_HIDE); 523 | } 524 | if (nID == WM_TASKBARNOTIFY_MENUITEM_RELOAD) 525 | { 526 | ReloadCmdline(); 527 | } 528 | else if (nID == WM_TASKBARNOTIFY_MENUITEM_ABOUT) 529 | { 530 | MessageBoxW(hWnd, szTooltip, szWindowClass, 0); 531 | } 532 | else if (nID == WM_TASKBARNOTIFY_MENUITEM_EXIT) 533 | { 534 | DeleteTrayIcon(); 535 | PostMessage(hConsole, WM_CLOSE, 0, 0); 536 | } 537 | else if (WM_TASKBARNOTIFY_MENUITEM_PROXYLIST_BASE <= nID && nID <= WM_TASKBARNOTIFY_MENUITEM_PROXYLIST_BASE+sizeof(lpProxyList)/sizeof(lpProxyList[0])) 538 | { 539 | WCHAR *szProxy = lpProxyList[nID-WM_TASKBARNOTIFY_MENUITEM_PROXYLIST_BASE]; 540 | SetWindowsProxy(szProxy, NULL); 541 | SetWindowsProxyForAllRasConnections(szProxy); 542 | ShowTrayIcon(szProxy, NIM_MODIFY); 543 | } 544 | break; 545 | case WM_CLOSE: 546 | DeleteTrayIcon(); 547 | PostQuitMessage(0); 548 | break; 549 | case WM_DESTROY: 550 | PostQuitMessage(0); 551 | break; 552 | default: 553 | if (message == WM_TASKBARCREATED) 554 | { 555 | ShowTrayIcon(NULL, NIM_ADD); 556 | break; 557 | } 558 | return DefWindowProc(hWnd, message, wParam, lParam); 559 | } 560 | return 0; 561 | } 562 | 563 | ATOM MyRegisterClass(HINSTANCE hInstance) 564 | { 565 | WNDCLASSEX wcex; 566 | 567 | wcex.cbSize = sizeof(WNDCLASSEX); 568 | 569 | wcex.style = CS_HREDRAW | CS_VREDRAW; 570 | wcex.lpfnWndProc = (WNDPROC)WndProc; 571 | wcex.cbClsExtra = 0; 572 | wcex.cbWndExtra = 0; 573 | wcex.hInstance = hInstance; 574 | wcex.hIcon = LoadIcon(hInstance, (LPCTSTR)IDI_TASKBAR); 575 | wcex.hCursor = LoadCursor(NULL, IDC_ARROW); 576 | wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1); 577 | wcex.lpszMenuName = (LPCTSTR)NULL; 578 | wcex.lpszClassName = szWindowClass; 579 | wcex.hIconSm = LoadIcon(wcex.hInstance, (LPCTSTR)IDI_SMALL); 580 | 581 | return RegisterClassEx(&wcex); 582 | } 583 | 584 | int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) 585 | { 586 | MSG msg; 587 | hInst = hInstance; 588 | CDCurrentDirectory(); 589 | SetEenvironment(); 590 | ParseProxyList(); 591 | MyRegisterClass(hInstance); 592 | if (!InitInstance (hInstance, SW_HIDE)) 593 | { 594 | return FALSE; 595 | } 596 | CreateConsole(); 597 | ExecCmdline(); 598 | ShowTrayIcon(GetWindowsProxy(), NIM_ADD); 599 | TryDeleteUpdateFiles(); 600 | while (GetMessage(&msg, NULL, 0, 0)) 601 | { 602 | TranslateMessage(&msg); 603 | DispatchMessage(&msg); 604 | } 605 | return 0; 606 | } 607 | -------------------------------------------------------------------------------- /windows/taskbar.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/phuslu/taskbar/80e4a0b97e8ed9427d9054138891828bf30aad35/windows/taskbar.ico -------------------------------------------------------------------------------- /windows/taskbar.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/phuslu/taskbar/80e4a0b97e8ed9427d9054138891828bf30aad35/windows/taskbar.o -------------------------------------------------------------------------------- /windows/taskbar.rc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/phuslu/taskbar/80e4a0b97e8ed9427d9054138891828bf30aad35/windows/taskbar.rc --------------------------------------------------------------------------------