Portable Monitor Rotate

One click in the Windows tray flips your portable monitor between landscape and portrait — and it stays exactly where you put it. 在 Windows 工作列點一下,攜帶式螢幕就在橫向與直向之間切換 —— 而且位置不會跑掉。

~49 KB · no installer · no dependencies · MIT licensed · Windows 10 / 11 約 49 KB · 免安裝 · 無相依 · MIT 授權 · Windows 10 / 11

Laptop
MSI

Rotating changes the shape — the side and the bottom edge stay put. 轉向只改變形狀 —— 所在的那一側與下緣基準線維持不變。

The problem問題

Portable USB-C monitors are great in portrait mode. But most have no orientation sensor, so Windows will never auto-rotate them — you open Settings → System → Display and change the dropdown, every single time. 攜帶式 USB-C 螢幕轉成直向非常好用,但這類螢幕大多沒有方向感應器,Windows 永遠不會幫它自動旋轉 —— 你只能每次都打開「設定 → 系統 → 顯示器」改下拉選單。

And then Windows moves it. Rotating 1920×1080 to 1080×1920 changes the monitor's shape, so Windows reflows the desktop and drops it somewhere new. Set it on the left, level with your laptop; after one rotation it floats half a screen too high. 然後 Windows 會把它搬走。1920×1080 轉成 1080×1920,形狀變了,Windows 就重排桌面把它丟到別處。你明明擺在左邊、跟筆電切齊,轉一次就飄到半個螢幕高的位置。

Diagram: the external monitor keeps its side and bottom alignment in both landscape and portrait

What it does功能

One click點一下

Click the tray icon to toggle. The icon itself shows the current orientation.點工作列圖示就切換,圖示本身會顯示目前方向。

Position preserved位置保留

Keeps its side and stays flush against the shared edge, through every rotation.維持在同一側並緊貼共用邊,每次轉向都一樣。

Survives unplugging撐得過拔插

Reconnect and both the monitor and the tray icon return to the same place.重新接上,螢幕與工作列圖示都回到原本的位置。

Cursor stays put游標不亂跳

No more pointer warping to the centre of the primary screen.不再被拉到主螢幕正中央。

Touch lands where you tap觸控不跑錯螢幕

Touches drifting to the laptop screen? It spots the wrong mapping and fixes it in one click.觸控跑到筆電螢幕上?程式會偵測對應錯誤,點一下就修正。

Bilingual & scriptable雙語與腳本

English or Chinese UI, following Windows. A named pipe lets anything drive it.英文或中文介面,跟隨系統語言。另有 named pipe 可供任何程式驅動。

Tiny and quiet小而安靜

A single 49 KB .exe. No installer, no telemetry, no network access.單一 49 KB 執行檔。免安裝、無遙測、不連網。

Three Win32 traps behind it背後的三個 Win32 陷阱

A stable tray position needs a GUID, not a window handle托盤位置要穩定,靠的是 GUID

Windows keys a tray icon's remembered position on its identity. WinForms' NotifyIcon uses (hWnd, uID) — both change every launch, so Windows sees a new icon each time and dumps it in the overflow. Calling Shell_NotifyIcon with a fixed NIF_GUID is what makes the position stick. Windows 記住托盤圖示位置的依據是它的「身分」。WinForms 的 NotifyIcon 使用 (hWnd, uID),兩者每次啟動都會變,所以系統每次都當成新圖示丟回溢位區。直接呼叫 Shell_NotifyIcon 並帶固定的 NIF_GUID,位置才會被記住。

Version 4 tray icons deliver every click twiceVersion 4 的圖示每次點擊送兩份

Under NOTIFYICON_VERSION_4 one left click sends WM_MOUSEMOVE → WM_LBUTTONDOWN → WM_LBUTTONUP → NIN_SELECT. Handle both the raw message and NIN_SELECT and your toggle rotates then instantly rotates back — the app looks dead while doing its job perfectly, twice. 在 NOTIFYICON_VERSION_4 底下,按一次左鍵會送出 WM_MOUSEMOVE → WM_LBUTTONDOWN → WM_LBUTTONUP → NIN_SELECT。原始訊息和 NIN_SELECT 都接,切換就會轉過去又轉回來 —— 程式看起來毫無反應,其實完美地做了兩次。

Orientation and position must be one atomic change方向與位置必須是同一次原子操作

Rotating changes width and height, so Windows reflows the desktop to remove the overlap it just created. Both go into one DEVMODE, staged with CDS_NORESET and committed in a single call. Hotplug needs more: Windows parks the monitor arbitrarily and may reflow again after you act, so geometry is only trusted once it has held still. 轉向會改變寬高,Windows 會為了消除它剛製造的重疊而重排桌面。所以兩者放進同一個 DEVMODE,用 CDS_NORESET 暫存後一次提交。熱插拔更麻煩:Windows 會把螢幕停在任意位置,而且在你動作之後還會再重排一次,因此幾何資料必須靜止一段時間才被採信。

Does your monitor really have no sensor?你的螢幕真的沒有感應器嗎?

A zero-risk test, no code required: turn the monitor to portrait and open its OSD menu. If the on-screen menu rotates to stay upright, a G-sensor is driving the scaler. If it lies on its side, there isn't one. 一個零風險、不用寫程式的測試:把螢幕轉成直向,然後叫出它的 OSD 選單。如果選單跟著轉正,代表有 G-sensor 在驅動 scaler;如果選單是躺著的,就沒有。

The repository documents the full check — Windows sensor stack, HID report descriptors (usage page 0x20), and the DDC/CI capability string (VCP 0xAA). Repo 裡記錄了完整的檢測方法 —— Windows 感應器堆疊、HID 報告描述元(usage page 0x20)、以及 DDC/CI capability 字串(VCP 0xAA)。