commit dcbd38596ef17a985934975294f61e33819b019c Author: serenitatis <30504381+serenitatis@users.noreply.github.com> Date: Fri Jun 19 21:44:28 2026 +0300 Начальный коммит diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..3e759b7 --- /dev/null +++ b/.gitignore @@ -0,0 +1,330 @@ +## Ignore Visual Studio temporary files, build results, and +## files generated by popular Visual Studio add-ons. +## +## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore + +# User-specific files +*.suo +*.user +*.userosscache +*.sln.docstates + +# User-specific files (MonoDevelop/Xamarin Studio) +*.userprefs + +# Build results +[Dd]ebug/ +[Dd]ebugPublic/ +[Rr]elease/ +[Rr]eleases/ +x64/ +x86/ +bld/ +[Bb]in/ +[Oo]bj/ +[Ll]og/ + +# Visual Studio 2015/2017 cache/options directory +.vs/ +# Uncomment if you have tasks that create the project's static files in wwwroot +#wwwroot/ + +# Visual Studio 2017 auto generated files +Generated\ Files/ + +# MSTest test Results +[Tt]est[Rr]esult*/ +[Bb]uild[Ll]og.* + +# NUNIT +*.VisualState.xml +TestResult.xml + +# Build Results of an ATL Project +[Dd]ebugPS/ +[Rr]eleasePS/ +dlldata.c + +# Benchmark Results +BenchmarkDotNet.Artifacts/ + +# .NET Core +project.lock.json +project.fragment.lock.json +artifacts/ +**/Properties/launchSettings.json + +# StyleCop +StyleCopReport.xml + +# Files built by Visual Studio +*_i.c +*_p.c +*_i.h +*.ilk +*.meta +*.obj +*.iobj +*.pch +*.pdb +*.ipdb +*.pgc +*.pgd +*.rsp +*.sbr +*.tlb +*.tli +*.tlh +*.tmp +*.tmp_proj +*.log +*.vspscc +*.vssscc +.builds +*.pidb +*.svclog +*.scc + +# Chutzpah Test files +_Chutzpah* + +# Visual C++ cache files +ipch/ +*.aps +*.ncb +*.opendb +*.opensdf +*.sdf +*.cachefile +*.VC.db +*.VC.VC.opendb + +# Visual Studio profiler +*.psess +*.vsp +*.vspx +*.sap + +# Visual Studio Trace Files +*.e2e + +# TFS 2012 Local Workspace +$tf/ + +# Guidance Automation Toolkit +*.gpState + +# ReSharper is a .NET coding add-in +_ReSharper*/ +*.[Rr]e[Ss]harper +*.DotSettings.user + +# JustCode is a .NET coding add-in +.JustCode + +# TeamCity is a build add-in +_TeamCity* + +# DotCover is a Code Coverage Tool +*.dotCover + +# AxoCover is a Code Coverage Tool +.axoCover/* +!.axoCover/settings.json + +# Visual Studio code coverage results +*.coverage +*.coveragexml + +# NCrunch +_NCrunch_* +.*crunch*.local.xml +nCrunchTemp_* + +# MightyMoose +*.mm.* +AutoTest.Net/ + +# Web workbench (sass) +.sass-cache/ + +# Installshield output folder +[Ee]xpress/ + +# DocProject is a documentation generator add-in +DocProject/buildhelp/ +DocProject/Help/*.HxT +DocProject/Help/*.HxC +DocProject/Help/*.hhc +DocProject/Help/*.hhk +DocProject/Help/*.hhp +DocProject/Help/Html2 +DocProject/Help/html + +# Click-Once directory +publish/ + +# Publish Web Output +*.[Pp]ublish.xml +*.azurePubxml +# Note: Comment the next line if you want to checkin your web deploy settings, +# but database connection strings (with potential passwords) will be unencrypted +*.pubxml +*.publishproj + +# Microsoft Azure Web App publish settings. Comment the next line if you want to +# checkin your Azure Web App publish settings, but sensitive information contained +# in these scripts will be unencrypted +PublishScripts/ + +# NuGet Packages +*.nupkg +# The packages folder can be ignored because of Package Restore +**/[Pp]ackages/* +# except build/, which is used as an MSBuild target. +!**/[Pp]ackages/build/ +# Uncomment if necessary however generally it will be regenerated when needed +#!**/[Pp]ackages/repositories.config +# NuGet v3's project.json files produces more ignorable files +*.nuget.props +*.nuget.targets + +# Microsoft Azure Build Output +csx/ +*.build.csdef + +# Microsoft Azure Emulator +ecf/ +rcf/ + +# Windows Store app package directories and files +AppPackages/ +BundleArtifacts/ +Package.StoreAssociation.xml +_pkginfo.txt +*.appx + +# Visual Studio cache files +# files ending in .cache can be ignored +*.[Cc]ache +# but keep track of directories ending in .cache +!*.[Cc]ache/ + +# Others +ClientBin/ +~$* +*~ +*.dbmdl +*.dbproj.schemaview +*.jfm +*.pfx +*.publishsettings +orleans.codegen.cs + +# Including strong name files can present a security risk +# (https://github.com/github/gitignore/pull/2483#issue-259490424) +#*.snk + +# Since there are multiple workflows, uncomment next line to ignore bower_components +# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) +#bower_components/ + +# RIA/Silverlight projects +Generated_Code/ + +# Backup & report files from converting an old project file +# to a newer Visual Studio version. Backup files are not needed, +# because we have git ;-) +_UpgradeReport_Files/ +Backup*/ +UpgradeLog*.XML +UpgradeLog*.htm +ServiceFabricBackup/ +*.rptproj.bak + +# SQL Server files +*.mdf +*.ldf +*.ndf + +# Business Intelligence projects +*.rdl.data +*.bim.layout +*.bim_*.settings +*.rptproj.rsuser + +# Microsoft Fakes +FakesAssemblies/ + +# GhostDoc plugin setting file +*.GhostDoc.xml + +# Node.js Tools for Visual Studio +.ntvs_analysis.dat +node_modules/ + +# Visual Studio 6 build log +*.plg + +# Visual Studio 6 workspace options file +*.opt + +# Visual Studio 6 auto-generated workspace file (contains which files were open etc.) +*.vbw + +# Visual Studio LightSwitch build output +**/*.HTMLClient/GeneratedArtifacts +**/*.DesktopClient/GeneratedArtifacts +**/*.DesktopClient/ModelManifest.xml +**/*.Server/GeneratedArtifacts +**/*.Server/ModelManifest.xml +_Pvt_Extensions + +# Paket dependency manager +.paket/paket.exe +paket-files/ + +# FAKE - F# Make +.fake/ + +# JetBrains Rider +.idea/ +*.sln.iml + +# CodeRush +.cr/ + +# Python Tools for Visual Studio (PTVS) +__pycache__/ +*.pyc + +# Cake - Uncomment if you are using it +# tools/** +# !tools/packages.config + +# Tabs Studio +*.tss + +# Telerik's JustMock configuration file +*.jmconfig + +# BizTalk build output +*.btp.cs +*.btm.cs +*.odx.cs +*.xsd.cs + +# OpenCover UI analysis results +OpenCover/ + +# Azure Stream Analytics local run output +ASALocalRun/ + +# MSBuild Binary and Structured Log +*.binlog + +# NVidia Nsight GPU debugger configuration file +*.nvuser + +# MFractors (Xamarin productivity tool) working folder +.mfractor/ diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..e5d4ac9 --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2024 Max Ignatiev + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/README.md b/README.md new file mode 100644 index 0000000..4601f8b --- /dev/null +++ b/README.md @@ -0,0 +1,6 @@ +# SwitchyAlt + +Переключатель раскладки клавиатуры про помощи правой клавиши Alt. +Нажатие левого и правого Alt пристанавливает работу приложения до его перезапуска. + +Основано на https://github.com/erryox/Switchy \ No newline at end of file diff --git a/Switchy/Switchy.rc b/Switchy/Switchy.rc new file mode 100644 index 0000000..d758c85 --- /dev/null +++ b/Switchy/Switchy.rc @@ -0,0 +1,186 @@ +// Microsoft Visual C++ generated resource script. +// +#include "resource.h" + +#define APSTUDIO_READONLY_SYMBOLS +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 2 resource. +// +#include "winres.h" + +///////////////////////////////////////////////////////////////////////////// +#undef APSTUDIO_READONLY_SYMBOLS + +///////////////////////////////////////////////////////////////////////////// +// () resources + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_RUS) +LANGUAGE LANG_RUSSIAN, SUBLANG_DEFAULT +#pragma code_page(1251) + +#ifdef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// TEXTINCLUDE +// + +1 TEXTINCLUDE +BEGIN + "resource.h\0" +END + +2 TEXTINCLUDE +BEGIN + "#include ""winres.h""\r\n" + "\0" +END + +3 TEXTINCLUDE +BEGIN + "\r\n" + "\0" +END + +#endif // APSTUDIO_INVOKED + + +///////////////////////////////////////////////////////////////////////////// +// +// Icon +// + +// Icon with lowest ID value placed first to ensure application icon +// remains consistent on all systems. +IDI_ICON1 ICON "icon.ico" + + +///////////////////////////////////////////////////////////////////////////// +// +// Dialog +// + +IDD_ABOUTBOX DIALOGEX 0, 0, 201, 223 +STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | DS_CENTER | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION " " +FONT 8, "MS Shell Dlg", 400, 0, 0x1 +BEGIN + DEFPUSHBUTTON "",IDOK,144,201,50,14 + CTEXT "IDC_STATIC_BASEDON",IDC_STATIC_BASEDON,7,185,187,10 + CTEXT "IDC_STATIC_APPINFO",IDC_STATIC_APPINFO,7,7,186,22 + EDITTEXT IDC_INFO,7,31,187,149,ES_MULTILINE | ES_READONLY | WS_VSCROLL +END + + +///////////////////////////////////////////////////////////////////////////// +// +// DESIGNINFO +// + +#ifdef APSTUDIO_INVOKED +GUIDELINES DESIGNINFO +BEGIN + IDD_ABOUTBOX, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 194 + TOPMARGIN, 7 + BOTTOMMARGIN, 215 + END +END +#endif // APSTUDIO_INVOKED + + +///////////////////////////////////////////////////////////////////////////// +// +// AFX_DIALOG_LAYOUT +// + +IDD_ABOUTBOX AFX_DIALOG_LAYOUT +BEGIN + 0 +END + + +///////////////////////////////////////////////////////////////////////////// +// +// Version +// + +VS_VERSION_INFO VERSIONINFO + FILEVERSION 1,0,0,0 + PRODUCTVERSION 1,0,0,0 + FILEFLAGSMASK 0x3fL +#ifdef _DEBUG + FILEFLAGS 0x1L +#else + FILEFLAGS 0x0L +#endif + FILEOS 0x40004L + FILETYPE 0x1L + FILESUBTYPE 0x0L +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "041904b0" + BEGIN + VALUE "CompanyName", "serenitatis" + VALUE "FileDescription", "SwitchyAlt" + VALUE "FileVersion", "1.0.0.0" + VALUE "InternalName", "SwitchyAlt.exe" + VALUE "LegalCopyright", "2026, serenitatis" + VALUE "OriginalFilename", "SwitchyAlt.exe" + VALUE "ProductName", "SwitchyAlt" + VALUE "ProductVersion", "1.0.0.0" + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x419, 1200 + END +END + + +///////////////////////////////////////////////////////////////////////////// +// +// String Table +// + +STRINGTABLE +BEGIN + IDS_ABOUT_TEXT " Alt.\r\n Alt .\r\n\r\n******************************************\r\n \r\n\r\n1.0\r\n- ." + IDS_APP_MUTEX_ERROR " SwitchyAlt" + IDS_APP_ALREADY_RUNNING " SwitchyAlt" + IDS_ERROR_REG_CLASS " " + IDS_ERROR_CREATE_WINDOW " " + IDS_ERROR_TRAY_ICON " " +END + +STRINGTABLE +BEGIN + IDS_ERROR_SETHOOK " SetWindowsHookEx" + IDS_MENU_PAUSE "" + IDS_MENU_RESUME "" + IDS_MENU_ABOUT " " + IDS_MENU_EXIT "" + IDS_TRAY_TOOLTIP "SwitchyAlt" + IDS_ABOUT_TITLE " " + IDS_BASEDON " https://github.com/erryox/Switchy" + IDS_APPINFO "SwitchyAlt 1.0\r\n 2026, serenitatis." +END + +#endif // () resources +///////////////////////////////////////////////////////////////////////////// + + + +#ifndef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 3 resource. +// + + +///////////////////////////////////////////////////////////////////////////// +#endif // not APSTUDIO_INVOKED + diff --git a/Switchy/Switchy.vcxproj b/Switchy/Switchy.vcxproj new file mode 100644 index 0000000..9b4ec64 --- /dev/null +++ b/Switchy/Switchy.vcxproj @@ -0,0 +1,151 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + 16.0 + {16A46215-C3FC-4F84-966D-22B97CADE8C0} + SwitchyAlt + 10.0 + SwitchyAlt + + + + Application + true + v143 + MultiByte + + + Application + false + v143 + true + MultiByte + + + Application + true + v142 + MultiByte + + + Application + false + v142 + true + MultiByte + + + + + + + + + + + + + + + + + + + + + + + Level3 + Disabled + true + true + + + + + Console + + + + + Level3 + Disabled + true + true + %(AdditionalIncludeDirectories) + + + Windows + + + + + Level3 + MaxSpeed + true + true + true + true + + + + + Windows + true + true + mainCRTStartup + + + + + Level3 + MaxSpeed + true + true + true + true + + + + + Windows + true + true + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Switchy/Switchy.vcxproj.filters b/Switchy/Switchy.vcxproj.filters new file mode 100644 index 0000000..fe13d42 --- /dev/null +++ b/Switchy/Switchy.vcxproj.filters @@ -0,0 +1,37 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hh;hpp;hxx;hm;inl;inc;ipp;xsd + + + + + Source Files + + + + + Header Files + + + + + Resource Files + + + + + Resource Files + + + \ No newline at end of file diff --git a/Switchy/icon.ico b/Switchy/icon.ico new file mode 100644 index 0000000..4043c8a Binary files /dev/null and b/Switchy/icon.ico differ diff --git a/Switchy/main.c b/Switchy/main.c new file mode 100644 index 0000000..ef9c24e --- /dev/null +++ b/Switchy/main.c @@ -0,0 +1,253 @@ +#include +#include +#include +#include "resource.h" + +#pragma comment(lib, "comctl32.lib") +#pragma comment(lib, "user32.lib") +#pragma comment(lib, "shell32.lib") + +#pragma comment(linker, \ + "\"/manifestdependency:type='win32' " \ + "name='Microsoft.Windows.Common-Controls' " \ + "version='6.0.0.0' " \ + "processorArchitecture='*' " \ + "publicKeyToken='6595b64144ccf1df' " \ + "language='*'\"") + +#define WM_TRAYNOTIFY (WM_USER + 100) +#define ID_TRAYICON 1 +#define IDM_EXIT 1001 +#define IDM_TOGGLE 1002 +#define IDM_ABOUT 1003 + +HHOOK hHook = NULL; +HWND hWndHidden = NULL; +NOTIFYICONDATA nid = { 0 }; +BOOL enabled = TRUE; +BOOL keystrokeRightAltProcessed = FALSE; + +HINSTANCE g_hInstance = NULL; + +LPCTSTR LoadStr(UINT id) +{ + static TCHAR buf[1024]; + buf[0] = TEXT('\0'); + LoadString(g_hInstance, id, buf, _countof(buf)); + return buf; +} + +void ShowError(UINT id) +{ + MessageBox(NULL, LoadStr(id), TEXT("SwitchyAlt"), MB_OK | MB_ICONERROR); +} + +void SwitchLayout() +{ + HWND hwndForeground = GetForegroundWindow(); + if (!hwndForeground) return; + + char className[256]; + GetClassNameA(hwndForeground, className, sizeof(className)); + + BOOL isRDP = (strstr(className, "TscShellContainerClass") != NULL); + BOOL isConsole = (strstr(className, "ConsoleWindowClass") != NULL); + + if (isRDP || isConsole) + { + INPUT inputs[4] = { 0 }; + for (int i = 0; i < 4; i++) inputs[i].type = INPUT_KEYBOARD; + inputs[0].ki.wVk = VK_MENU; inputs[0].ki.wScan = 0x38; + inputs[1].ki.wVk = VK_SHIFT; inputs[1].ki.wScan = 0x2A; + inputs[2].ki.wVk = VK_SHIFT; inputs[2].ki.wScan = 0x2A; inputs[2].ki.dwFlags = KEYEVENTF_KEYUP; + inputs[3].ki.wVk = VK_MENU; inputs[3].ki.wScan = 0x38; inputs[3].ki.dwFlags = KEYEVENTF_KEYUP; + SendInput(4, inputs, sizeof(INPUT)); + } + else + { + GUITHREADINFO gti = { sizeof(GUITHREADINFO) }; + HWND targetWnd = hwndForeground; + + if (GetGUIThreadInfo(0, >i) && gti.hwndFocus != NULL) + { + targetWnd = gti.hwndFocus; + } + + PostMessage(targetWnd, WM_INPUTLANGCHANGEREQUEST, 0, (LPARAM)HKL_NEXT); + } +} + +LRESULT CALLBACK LowLevelKeyboardProc(int nCode, WPARAM wParam, LPARAM lParam) +{ + if (nCode != HC_ACTION) + return CallNextHookEx(hHook, nCode, wParam, lParam); + + KBDLLHOOKSTRUCT* p = (KBDLLHOOKSTRUCT*)lParam; + + if (p->flags & LLKHF_INJECTED) + return CallNextHookEx(hHook, nCode, wParam, lParam); + + if (p->vkCode == VK_RMENU) + { + if (wParam == WM_KEYDOWN || wParam == WM_SYSKEYDOWN) + { + if (!keystrokeRightAltProcessed) + { + keystrokeRightAltProcessed = TRUE; + + if (GetAsyncKeyState(VK_LMENU) & 0x8000) + { + enabled = !enabled; + return 1; + } + + if (enabled) + { + SwitchLayout(); + } + } + return 1; + } + + if (wParam == WM_KEYUP || wParam == WM_SYSKEYUP) + { + keystrokeRightAltProcessed = FALSE; + return 1; + } + } + + return CallNextHookEx(hHook, nCode, wParam, lParam); +} + +INT_PTR CALLBACK AboutDlgProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) +{ + switch (message) + { + case WM_INITDIALOG: + SetDlgItemText(hDlg, IDC_INFO, LoadStr(IDS_ABOUT_TEXT)); + SetDlgItemText(hDlg, IDC_STATIC_APPINFO, LoadStr(IDS_APPINFO)); + SetDlgItemText(hDlg, IDC_STATIC_BASEDON, LoadStr(IDS_BASEDON)); + return (INT_PTR)TRUE; + + case WM_COMMAND: + if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL) + { + EndDialog(hDlg, LOWORD(wParam)); + return (INT_PTR)TRUE; + } + break; + } + return (INT_PTR)FALSE; +} + +LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) +{ + switch (msg) + { + case WM_TRAYNOTIFY: + if (lParam == WM_RBUTTONUP) + { + POINT pt; + GetCursorPos(&pt); + + HMENU hMenu = CreatePopupMenu(); + if (hMenu) + { + AppendMenu(hMenu, MF_STRING, IDM_TOGGLE, + enabled ? LoadStr(IDS_MENU_PAUSE) : LoadStr(IDS_MENU_RESUME)); + + AppendMenu(hMenu, MF_STRING, IDM_ABOUT, LoadStr(IDS_MENU_ABOUT)); + AppendMenu(hMenu, MF_SEPARATOR, 0, NULL); + AppendMenu(hMenu, MF_STRING, IDM_EXIT, LoadStr(IDS_MENU_EXIT)); + + SetForegroundWindow(hwnd); + UINT cmd = TrackPopupMenu(hMenu, TPM_RETURNCMD | TPM_NONOTIFY, pt.x, pt.y, 0, hwnd, NULL); + DestroyMenu(hMenu); + + if (cmd == IDM_TOGGLE) enabled = !enabled; + if (cmd == IDM_ABOUT) + DialogBox(g_hInstance, MAKEINTRESOURCE(IDD_ABOUTBOX), hwnd, AboutDlgProc); + if (cmd == IDM_EXIT) + PostQuitMessage(0); + } + } + break; + + case WM_DESTROY: + PostQuitMessage(0); + break; + + default: + return DefWindowProc(hwnd, msg, wParam, lParam); + } + return 0; +} + +int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrev, LPSTR lpCmd, int nShow) +{ + g_hInstance = hInstance; + + HANDLE hMutex = CreateMutex(NULL, FALSE, TEXT("SwitchyAltUnique")); + if (GetLastError() == ERROR_ALREADY_EXISTS) + { + ShowError(IDS_APP_MUTEX_ERROR); + return 1; + } + + WNDCLASSEX wc = { sizeof(WNDCLASSEX) }; + wc.lpfnWndProc = WndProc; + wc.hInstance = hInstance; + wc.lpszClassName = TEXT("SwitchyHiddenClass"); + + if (!RegisterClassEx(&wc)) + { + ShowError(IDS_ERROR_REG_CLASS); + return 1; + } + + hWndHidden = CreateWindowEx(0, wc.lpszClassName, TEXT("SwitchyAlt"), + 0, 0, 0, 0, 0, HWND_MESSAGE, NULL, hInstance, NULL); + + if (!hWndHidden) + { + ShowError(IDS_ERROR_CREATE_WINDOW); + return 1; + } + + InitCommonControls(); + + nid.cbSize = sizeof(NOTIFYICONDATA); + nid.hWnd = hWndHidden; + nid.uID = ID_TRAYICON; + nid.uFlags = NIF_ICON | NIF_MESSAGE | NIF_TIP; + nid.uCallbackMessage = WM_TRAYNOTIFY; + nid.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_ICON1)); + lstrcpy(nid.szTip, LoadStr(IDS_TRAY_TOOLTIP)); + + if (!Shell_NotifyIcon(NIM_ADD, &nid)) + { + ShowError(IDS_ERROR_TRAY_ICON); + } + + hHook = SetWindowsHookEx(WH_KEYBOARD_LL, LowLevelKeyboardProc, hInstance, 0); + if (!hHook) + { + ShowError(IDS_ERROR_SETHOOK); + Shell_NotifyIcon(NIM_DELETE, &nid); + DestroyWindow(hWndHidden); + return 1; + } + + MSG msg; + while (GetMessage(&msg, NULL, 0, 0)) + { + TranslateMessage(&msg); + DispatchMessage(&msg); + } + + UnhookWindowsHookEx(hHook); + Shell_NotifyIcon(NIM_DELETE, &nid); + DestroyWindow(hWndHidden); + + return (int)msg.wParam; +} \ No newline at end of file diff --git a/Switchy/resource.h b/Switchy/resource.h new file mode 100644 index 0000000..70d00e9 --- /dev/null +++ b/Switchy/resource.h @@ -0,0 +1,36 @@ +//{{NO_DEPENDENCIES}} +// , Microsoft Visual C++. +// Switchy.rc +// +#define IDI_ICON1 102 +#define IDD_ABOUTBOX 104 +#define IDS_ABOUT_TEXT 106 +#define IDS_APP_MUTEX_ERROR 107 +#define IDS_APP_ALREADY_RUNNING 108 +#define IDS_ERROR_REG_CLASS 109 +#define IDS_ERROR_CREATE_WINDOW 110 +#define IDS_ERROR_TRAY_ICON 111 +#define IDS_ERROR_SETHOOK 112 +#define IDS_MENU_PAUSE 113 +#define IDS_MENU_RESUME 114 +#define IDS_MENU_ABOUT 115 +#define IDS_MENU_EXIT 116 +#define IDS_TRAY_TOOLTIP 117 +#define IDS_ABOUT_TITLE 118 +#define IDS_BASEDON 119 +#define IDS_APPINFO 120 +#define IDC_CUSTOM1 1002 +#define IDC_INFO 1004 +#define IDC_STATIC_BASEDON 1005 +#define IDC_STATIC_APPINFO 1007 + +// Next default values for new objects +// +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS +#define _APS_NEXT_RESOURCE_VALUE 121 +#define _APS_NEXT_COMMAND_VALUE 40001 +#define _APS_NEXT_CONTROL_VALUE 1008 +#define _APS_NEXT_SYMED_VALUE 101 +#endif +#endif diff --git a/SwitchyAlt.sln b/SwitchyAlt.sln new file mode 100644 index 0000000..69c7922 --- /dev/null +++ b/SwitchyAlt.sln @@ -0,0 +1,31 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 16 +VisualStudioVersion = 16.0.29306.81 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Switchy", "Switchy\Switchy.vcxproj", "{16A46215-C3FC-4F84-966D-22B97CADE8C0}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|x64 = Debug|x64 + Debug|x86 = Debug|x86 + Release|x64 = Release|x64 + Release|x86 = Release|x86 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {16A46215-C3FC-4F84-966D-22B97CADE8C0}.Debug|x64.ActiveCfg = Debug|x64 + {16A46215-C3FC-4F84-966D-22B97CADE8C0}.Debug|x64.Build.0 = Debug|x64 + {16A46215-C3FC-4F84-966D-22B97CADE8C0}.Debug|x86.ActiveCfg = Debug|Win32 + {16A46215-C3FC-4F84-966D-22B97CADE8C0}.Debug|x86.Build.0 = Debug|Win32 + {16A46215-C3FC-4F84-966D-22B97CADE8C0}.Release|x64.ActiveCfg = Release|x64 + {16A46215-C3FC-4F84-966D-22B97CADE8C0}.Release|x64.Build.0 = Release|x64 + {16A46215-C3FC-4F84-966D-22B97CADE8C0}.Release|x86.ActiveCfg = Release|Win32 + {16A46215-C3FC-4F84-966D-22B97CADE8C0}.Release|x86.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {3A751753-9F42-4929-A0D8-8B9011CE60FB} + EndGlobalSection +EndGlobal