0utsidethebox

Keyboard layout indicator

Mar 1st, 2026
229
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. Add-Type -Language CSharp -ReferencedAssemblies @(
  2.     "System.Windows.Forms",
  3.     "System.Drawing"
  4. ) -TypeDefinition @"
  5.  
  6. using System;
  7. using System.Drawing;
  8. using System.Windows.Forms;
  9. using System.Runtime.InteropServices;
  10. using System.Globalization;
  11.  
  12. public class KeyboardTrayApp : Form
  13. {
  14.    NotifyIcon trayIcon;
  15.    Timer timer;
  16.    ContextMenuStrip menu;
  17.  
  18.    [DllImport("user32.dll")]
  19.    private static extern IntPtr GetKeyboardLayout(uint idThread);
  20.  
  21.    [DllImport("user32.dll")]
  22.    private static extern IntPtr GetForegroundWindow();
  23.  
  24.    [DllImport("user32.dll")]
  25.    private static extern uint GetWindowThreadProcessId(IntPtr hWnd, IntPtr ProcessId);
  26.  
  27.    string lastLang = "";
  28.  
  29.    public KeyboardTrayApp()
  30.    {
  31.        ShowInTaskbar = false;
  32.        WindowState = FormWindowState.Minimized;
  33.  
  34.        trayIcon = new NotifyIcon();
  35.        trayIcon.Visible = true;
  36.  
  37.        menu = new ContextMenuStrip();
  38.        menu.Items.Add("Exit", null, OnExit);
  39.        trayIcon.ContextMenuStrip = menu;
  40.  
  41.        timer = new Timer();
  42.        timer.Interval = 200;   // Fast, but lightweight
  43.        timer.Tick += PollLayout;
  44.        timer.Start();
  45.  
  46.        PollLayout(null, null);
  47.    }
  48.  
  49.    private void OnExit(object sender, EventArgs e)
  50.    {
  51.        trayIcon.Visible = false;
  52.        timer.Stop();
  53.        Application.Exit();
  54.    }
  55.  
  56.    private void PollLayout(object sender, EventArgs e)
  57.    {
  58.        string lang = GetLayoutCode();
  59.  
  60.        if (lang == lastLang)
  61.            return;
  62.  
  63.        lastLang = lang;
  64.  
  65.        trayIcon.Icon = CreateTextIcon(lang);
  66.        trayIcon.Text = "Keyboard: " + lang;
  67.    }
  68.  
  69.    private string GetLayoutCode()
  70.    {
  71.        IntPtr hwnd = GetForegroundWindow();
  72.  
  73.        if (hwnd == IntPtr.Zero)
  74.            return "??";
  75.  
  76.        uint threadId = GetWindowThreadProcessId(hwnd, IntPtr.Zero);
  77.  
  78.        IntPtr layout = GetKeyboardLayout(threadId);
  79.        int langId = ((int)layout) & 0xFFFF;
  80.  
  81.        try
  82.        {
  83.            CultureInfo culture = CultureInfo.GetCultureInfo(langId);
  84.            return culture.TwoLetterISOLanguageName.ToUpper();
  85.        }
  86.        catch
  87.        {
  88.            return "??";
  89.        }
  90.    }
  91.  
  92.    private Icon CreateTextIcon(string text)
  93.    {
  94.        Bitmap bmp = new Bitmap(16, 16);
  95.        Graphics g = Graphics.FromImage(bmp);
  96.  
  97.        g.Clear(Color.Black);
  98.  
  99.        using (Font font = new Font("Segoe UI", 8, FontStyle.Bold))
  100.        using (Brush brush = new SolidBrush(Color.White))
  101.        {
  102.            SizeF size = g.MeasureString(text, font);
  103.            g.DrawString(text, font, brush,
  104.                (16 - size.Width) / 2,
  105.                (16 - size.Height) / 2);
  106.        }
  107.  
  108.        return Icon.FromHandle(bmp.GetHicon());
  109.    }
  110. }
  111.  
  112. "@
  113.  
  114. $app = New-Object KeyboardTrayApp
  115. [System.Windows.Forms.Application]::Run($app)
  116.  
Advertisement
Add Comment
Please, Sign In to add comment