2026年7月14日

win32 SDK 以 system() 開啟一個程式之後,如何取得 window 的 handle?


在 Win32 SDK 中,system() 屬於阻斷式呼叫且無法直接回傳 Process ID 或 Window Handle。若要取得該程式的視窗控制代碼 (HWND),必須改用 CreateProcess() 取得 Process ID (PID),再搭配 EnumWindowsGetWindowThreadProcessId 進行過濾。 [1, 2, 3, 4, 5, 6]

2026年7月9日

outlook 2016 如何修改 檢視->檢視設定->設定格式化條件中字型的具體大小如 outlook 2010 之前? 之前的.pst 檔似乎仍存著以前的檢視設定值?

在 Outlook 2016 中,無法像 Outlook 2010 以前那樣自由選擇 9、10、12pt 等具體的字型點數大小,這是微軟在核心介面設計上的一大改動。至於舊的 .pst 檔能維持以前的設定,是因為它完整封存了舊版系統寫入的檢視中介資料(Metadata) [1]

2026年7月2日

藉由 DSC_TotalChunkKBytes(快取硬體上限)與 DSC_MaxSlices(核心分割上限)的交集,共同計算出壓縮後的「目標每像素位元數

 在 HDMI 2.1 訊號傳輸中,發送端(如顯示卡)與接收端(如螢幕)並不是直接溝通「壓縮成 1/2 或 1/3」這種比例概念,而是透過將畫面切碎,並藉由 DSC_TotalChunkKBytes(快取硬體上限)DSC_MaxSlices(核心分割上限)的交集,共同計算出壓縮後的「目標每像素位元數(Target bpp, Bits Per Pixel)」

當目標 bpp 被確定後,它與原始未壓縮影像的 bpc(Bits Per Component,例如 8-bit 或 10-bit 色深)進行對比,就會精準落入 1/2、1/3 甚至 1/4 的壓縮能力區間。
以下為這兩個參數相互作用,最終合併決定壓縮能力的完整拆解:

第一步:理解基本換算關係(bpp 與壓縮比)

我們常說的 1/2、1/3 壓縮能力,在 DSC 技術中對應的是硬體能處理的最低 Target bpp 限制。
以常見的 RGB 4:4:4 / YCbCr 4:4:4 格式為例(一個像素由 3 個顏色通道組成):
  • 原始 8-bit 色深 = 原始一個像素佔用 24 bit (8-bit × 3)
    • 若要達到 1/2 壓縮:壓縮後的目標必須降至 12 bpp
    • 若要達到 1/3 壓縮:壓縮後的目標必須降至 8 bpp
  • 原始 10-bit 色深 = 原始一個像素佔用 30 bit (10-bit × 3)
    • 若要達到 1/2 壓縮:壓縮後的目標必須降至 15 bpp
    • 若要達到 1/3 壓縮:壓縮後的目標必須降至 10 bpp

第二步:兩個參數如何合力「卡死」bpp 上限?

接收端的硬體解碼線緩衝區(Line Buffer)是固定的。在點亮某一條水平掃描線時,硬體必須保證把所有被切碎的 Slice 數據全部塞進暫存區。
核心的硬體限制公式如下:
$$\text{單條線所需的總傳輸數據量} \le \text{DSC\_TotalChunkKBytes} \times 1024 \times 8 \text{ (bits)}$$
當顯示卡要計算這條線能用多高的 bpp(也就是多高的畫質)進行壓縮時,會受到這兩個參數的雙重夾擊:

1. DSC_MaxSlices 限制了「最小切片寬度」

DSC 規定一個 Slice 的水平寬度(Slice Width)不能無限大,因為晶片並行處理能力有限。
  • 假設螢幕水平解析度為 $H_{\text{active}}$(例如 4K 的 3840 像素)。
  • 顯示卡會根據螢幕宣告的 DSC_MaxSlices,計算出每個 Slice 的基本寬度:
    $$\text{Slice Width} = \frac{H_{\text{active}}}{\text{實際使用的 Slices 數量(不超過 DSC\_MaxSlices)}}$$
  • 例如:3840 像素 / 4 個 Slices = 每個 Slice 寬度 960 像素。

2. DSC_TotalChunkKBytes 限制了「每個切片的位元數」

在 DSC 語法中,一個 Slice 的水平像素壓縮後會被封裝成一個 Chunk(數據塊)
為了讓硬體不溢流,所有 Slice 的 Chunk 大小加起來,不能超過 DSC_TotalChunkKBytes
$$\text{每個 Chunk 的最大 Bits 數} = \frac{\text{DSC\_TotalChunkKBytes} \times 1024 \times 8}{\text{實際使用的 Slices 數量}}$$

3. 兩者合併求出 Target bpp

把上面兩個限制結合,就能算出每個像素在被壓縮時,硬體所允許的最大目標 bpp(Target bpp)
$$\text{Max Target bpp} = \frac{\text{每個 Chunk 的最大 Bits 數}}{\text{Slice Width}} = \frac{\text{DSC\_TotalChunkKBytes} \times 8192}{H_{\text{active}}}$$
💡 關鍵發現:當我們把公式展開,實際使用的 Slices 數量被消去了。這意味著:DSC_TotalChunkKBytes 與螢幕的解析度寬度 $H_{\text{active}}$ 直接決定了這台螢幕最高能承受多大的 bpp 能力!
DSC_MaxSlices 則是在背後當守門員,確保在超高解析度下,有足夠的硬體並行核心(Slices)去把頻寬拆小消化。如果 DSC_MaxSlices 太小,即使緩衝區夠大,晶片也來不及解碼。

第三步:實例模擬(以 4K 畫面為例)

我們來看看硬體宣告不同的 DSC_TotalChunkKBytes 時,如何改變壓縮能力。
假設我們要在 4K(水平 3840 像素)10-bit 色深(原始 30 bit/pixel) 的螢幕上開通 DSC:

情況 A:硬體配置較低(只能做到約 1/2 壓縮)

  • 螢幕宣告:DSC_TotalChunkKBytes = 32 KBDSC_MaxSlices = 4
  • 帶入公式算最大允許 bpp:
    $$\text{Max Target bpp} = \frac{32 \times 1024 \times 8}{3840} \approx \mathbf{68.26 \text{ bpp}}$$
  • 解讀:硬體緩衝區上限允許非常高的 bpp,但 DSC 標準規定的最高目標壓縮 bpp 通常為 12 或 15(以滿足 VESA 視覺無損標準)。此時硬體限制完全不是瓶頸,顯示卡可以從容地選擇 15 bpp(將 30-bit 壓縮成 15-bit,即精準的 1/2 壓縮),提供極高畫質。

情況 B:硬體配置極度受限(被迫進入 1/3 或 1/4 強制壓縮)

  • 螢幕宣告:DSC_TotalChunkKBytes = 4 KB(極小的快取),DSC_MaxSlices = 4
  • 帶入公式算最大允許 bpp:
    $$\text{Max Target bpp} = \frac{4 \times 1024 \times 8}{3840} \approx \mathbf{8.53 \text{ bpp}}$$
  • 解讀:此時因為硬體緩衝區太小,算出來的限制值卡在 8.53 bpp
  • 結果:顯示卡被逼無奈,絕對不能使用 1/2 壓縮(15 bpp),因為會撐爆緩衝區。它必須向下尋找 DSC 規格內支援的更低檔位,選擇 8 bpp 進行編碼(將 30-bit 壓縮成 8-bit,即 1/3.75 壓縮,逼近 1/4 壓縮)。

總結

發送端在讀取 EDID 時的決策鏈如下:
  1. 看解析度寬度與 DSC_TotalChunkKBytes 算出這台螢幕在硬體上最高承受的 bpp 上限
  2. DSC_MaxSlices 決定要橫向切成幾個區塊來並行解碼。
  3. 根據算出的 bpp 上限,在 VESA DSC 標準定義的檔位中(如 8 bpp, 10 bpp, 12 bpp 等),選擇一個符合當下 HDMI FRL 頻寬、且不超過硬體上限的數值。這個數值就直接定義了當前是運作在 1/2、1/3 或更低的壓縮比率。
如果想要進一步了解在特定解析度(例如 8K @ 60Hz)下,如何逆推這兩個參數在 EDID(SCDS 暫存器) 的正確填寫數值,請告訴我!

2026年6月25日

displayport spec 中提道的 SCR 是什麼?

 在 VESA 組織制定的 DisplayPort (DP) 規格書與相關測試規範(CTS)中,SCR 代表的是 Specification Change Notice(或 Specification Change Request,即規格變更通知/請求)。 [1, 2]

2026年6月10日

windows 11, 如何以簡單的 script 一次設定一堆副檔名的程式如 windows 95 的 HKEY_ROOT\xxxxx ?

 在 Windows 11 中,微軟為了安全防護(防止惡意軟體私自篡改預設程式),已經無法像 Windows 95 那樣,單純透過修改 HKEY_CLASSES_ROOT 登錄檔(Registry)就直接改變預設關聯。現在如果直接改登錄檔,系統會因為雜湊值(Hash)不符而失效或跳出重設提示。

目前最簡單、有效且不需要第三方工具的大量設定方法,是使用 Windows 內建的 PowerShell 指令搭配 XML 設定檔

上面 GetObject 的第一個參數未提供,是什麼? On Error Goto 0, 是什麼意思?

 這三個問題都問到了 VBS 核心控制的關鍵。以下為您用最簡單、直白的方式逐一解答:

一個既存的 word 程式,可以用 VBS 進行介入將其存檔關閉嗎?

 是的,完全可以。你可以透過 VBS (VBScript) 的 GetObject 函數,直接「介入」並控制電腦中已經在執行(既存)的 Word 程式,將所有開啟的文件自動存檔並關閉。 [1, 2]

請參考下方的範例與操作步驟。

2026年6月4日

Python Code 打包成 exe

打包成 exe

2026年6月3日

IT6616 Linux V4L2 driver


在 Linux 嵌入式系統中,

2026年6月1日

在 C 語言中如何使用 regular expression 進行搜尋與替代?

在 C 語言中處理正規表達式不像 Perl 或 Python 那樣有豐富的語法糖或內建高階函式。C 語言標準函式庫(POSIX 標準)只內建了搜尋功能(regcomp, regexec),沒有內建替代(Replace)功能

2026年5月31日

我在 perl 工作 30 年,現在學習 python 所以比較一下


三十年的 Perl 資歷是非常深厚的底蘊!Perl 作為文字處理的文字堂級語言,其正規表達式(Regex)已經深入到語言的骨髓裡(語法糖非常甜);而 Python 則是將其收納在內建的 re 模組中。
為了讓您能將三十年的 Perl 功力無縫平移到 Python,我幫您整理了一份 Perl vs Python Regex 核心語法對照表

2026年5月29日

VSCODE 如何只替代所選區域或全部?

 在 VS Code 中,您可以自由選擇將替代範圍限制在特定選取區域或套用到整份檔案(全部)

vscode 如何使用 regular expression 進行搜尋與替代?

 在 Visual Studio Code (VS Code) 中,使用正規表達式(Regular Expression)進行搜尋與替代非常直覺。您可以使用快速鍵 Ctrl + H(Mac 上為 Cmd + Option + F)開啟搜尋替代面板。

vbscript 搜尋替代功能如何使用 regular expression?


在 VBScript 中,若要使用正規表達式(Regular Expression)進行搜尋與取代,必須使用 VBScript.RegExp 物件以及其內建的 Replace 方法。 [1, 2]

2026年5月20日

 windows 10, 如何使用 batch , vbs 將桌面上的視窗移至特定位置?
這些腳本語言缺乏直接控制 Windows GUI 視窗 API(如 MoveWindow)的能力。

powershell 腳本過於複雜,有其它方法嗎?

 windows 10, 如何使用 batch , vbs 將桌面上的視窗移至特定位置?

在 Windows 10 中,單純使用原生 Batch 或 VBScript 是無法直接移動第三方視窗的,因為這些腳本語言缺乏直接控制 Windows GUI 視窗 API(如 MoveWindow)的能力。
要達成這個目的,最有效率的原生做法是使用 PowerShell,或是用 VBScript 呼叫 PowerShell/Excel 內建的 API
以下為您提供三種最實用的解決方案:

方案一:使用 VBScript 呼叫 PowerShell(推薦,免安裝最方便)

這個方法最安全,因為它完全使用 Windows 10 內建的組件。我們利用 VBScript 啟動 PowerShell,並透過 PowerShell 呼叫 Windows API (user32.dll) 來移動視窗。
請建立一個名為 move_window.vbs 的檔案,並寫入以下程式碼:
' 設定目標視窗標題與位置
Dim windowTitle, x, y, width, height
windowTitle = "記事本"  ' 改為您的目標視窗標題(支援部分比對)
x = 100                 ' 畫面 X 座標
y = 100                 ' 畫面 Y 座標
width = 800             ' 視窗寬度
height = 600            ' 視窗高度

' 組合 PowerShell 指令
Dim psCmd
psCmd = "powershell -NoProfile -Command """ & _
"[[void]][System.Reflection.Assembly]::LoadWithPartialName('System.Windows.Forms'); " & _
"$code = @' " & vbCrLf & _
"[DllImport(\""user32.dll\"")] " & vbCrLf & _
"public static extern bool MoveWindow(IntPtr hWnd, int X, int Y, int nWidth, int nHeight, bool bRepaint); " & vbCrLf & _
"[DllImport(\""user32.dll\"")] " & vbCrLf & _
"public static extern IntPtr FindWindow(string lpClassName, string lpWindowName); " & vbCrLf & _
"'@; " & _
"$type = Add-Type -MemberDefinition $code -Name Win32 -PassThru; " & _
"$ws = New-Object -ComObject Shell.Application; " & _
"$win = $ws.Windows() | Where-Object { $_.LocationName -like '*" & windowTitle & "*' -or $_.Name -like '*" & windowTitle & "*' }; " & _
"if (!$win) { $processes = Get-Process | Where-Object { $_.MainWindowTitle -like '*" & windowTitle & "*' }; " & _
"foreach ($p in $processes) { $type::MoveWindow($p.MainWindowHandle, " & x & ", " & y & ", " & width & ", " & height & ", $true) } }" & _
""""

' 執行指令(隱藏視窗背景執行)
CreateObject("Wscript.Shell").Run psCmd, 0, True

方案二:使用純 PowerShell 腳本(程式碼最乾淨)

如果您不一定要用 .vbs.bat 副檔名,直接寫成 .ps1 檔案是 Windows 10 系統下最標準的做法。
請建立一個 MoveWindow.ps1 檔案:
# 定義 Windows API
$API = @'
[DllImport("user32.dll")]
public static extern bool MoveWindow(IntPtr hWnd, int X, int Y, int nWidth, int nHeight, bool bRepaint);
'@
Add-Type -MemberDefinition $API -Name WindowModifier -Namespace Win32

# 設定目標與參數
$ProcessName = "notepad" # 執行緒名稱(例如記事本為 notepad)
$X = 200
$Y = 200
$Width = 1024
$Height = 768

# 取得視窗控制代碼並移動
$Target = Get-Process -Name $ProcessName -ErrorAction SilentlyContinue
if ($Target) {
    [Win32.WindowModifier]::MoveWindow($Target.MainWindowHandle, $X, $Y, $Width, $Height, $true)
}
  • 如何執行:您可以寫一個簡易的 .bat 檔案來啟動它:
    powershell -ExecutionPolicy Bypass -File "C:\路徑\MoveWindow.ps1"
    

方案三:使用 VBScript 模擬鍵盤快速鍵(僅能靠邊或最大化)

如果您的目的只是想把視窗「靠左」、「靠右」或「最大化」,不需要精準的座標(如 X=123),可以用 VBScript 模擬 Windows 10 的快捷鍵(Win + 方向鍵)。
請建立 snap_window.vbs
Set WshShell = CreateObject("WScript.Shell")

' 1. 先將目標視窗帶到最前端(以記事本為例)
WshShell.AppActivate "記事本"
WScript.Sleep 500 ' 等待視窗反應

' 2. 模擬按下 Win + 左方向鍵 (將視窗靠左側拼貼)
' 註:VBScript 無法直接模擬 Win 鍵,但可以透過組合鍵或複製特定行為。
' 這裡改用通用組合鍵:Alt + Space,再按 M (移動),再用方向鍵移動
WshShell.SendKeys "% "
WScript.Sleep 100
WshShell.SendKeys "M"
WScript.Sleep 100
WshShell.SendKeys "{LEFT 50}" ' 往左移動 50 次
WshShell.SendKeys "{ENTER}"   ' 確認位置
(注意:此方法容易受到當前使用者滑鼠點擊干擾,精準度較低。)

如果您想讓腳本更符合您的需求,請告訴我:
  • 您想要移動的目標程式是什麼?(例如:Chrome 瀏覽器、LINE、或是特定的資料夾?)
  • 您的具體移動規則是什麼?(例如:固定移到右下角、或者是偵測雙螢幕移動?)

 cmd for commad, for /r "dir" %i (*) 中,若 dir 要使用另外一個 loop 變數 "%~j" 或者 "!F!" 為何不能使用?

在 Windows 批次檔(Batch)中,FOR /R 的設計有一個核心限制:它的搜尋路徑必須在指令「解析(Parse)階段」就確定,而不能在「執行(Execute)階段」動態改變。
以下是無法使用的具體原因與解決方法:

為什麼不能用?

  • %~j(巢狀迴圈變數)失敗原因FOR /R 語法規定,路徑參數必須是一個靜態字串或環境變數。當它嵌套在另一個迴圈內時,FOR /R 會在外部迴圈開始執行「前」就先被解析,此時 %~j 還沒有被賦值,導致語法錯誤。
  • !F!(延遲環境變數)失敗原因FOR /R 不支援延遲變數擴展(Delayed Expansion)作為其路徑。即使開啟了 setlocal enabledelayedexpansionFOR /R 仍會在處理 !F! 之前就完成路徑解析,導致它把 !F! 當成一個名為 !F! 的字面字串路徑。

解決方法

如果你需要動態改變 FOR /R 的搜尋路徑,請使用以下兩種標準替代方案:

方案一:使用 PUSHD 切換目錄(最推薦)

不要把變數傳給 /R,而是先用 PUSHD 切換到該動態路徑,然後直接執行 FOR /R(不指定路徑,預設為當前目錄)。
@echo off
setlocal enabledelayedexpansion

:: 假設 %~j 或 !F! 的路徑存在變數 dirPath 中
set "dirPath=C:\Your\Dynamic\Path"

pushd "!dirPath!"
for /r %%i in (*) do (
    echo %%i
)
popd

方案二:利用 CALL 呼叫子程序

FOR /R 移到一個獨立的子程序(Label)中,並透過參數將動態路徑傳遞過去。此時參數會變成靜態的 %1FOR /R 就能正常解析。
@echo off

:: 外部迴圈範例,假設從某處取得了變數 %%j
for /d %%j in (C:\Test\*) do (
    call :SubLoop "%%~j"
)
goto :eof

:SubLoop
:: 此時 %1 是從外部傳進來的靜態路徑
for /r "%~1" %%i in (*) do (
    echo %%i
)
goto :eof

如果想進一步調整你的腳本,可以告訴我:
  • 你的外部迴圈 %~j如何取得路徑的?(例如:讀取文字檔、遍歷資料夾?)
  • 這個腳本的最終目的是什麼?(例如:複製檔案、修改副檔名?)
我可以幫你寫出最精簡且能直接執行的完整程式碼。

2026年4月22日

[WIN] DOS Drive Map

 Windows Registry Editor Version 5.00


[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager\DOS Devices]

"R:"="\\??\\d:\\ramdisk"

"H:"="\\??\\E:\\H"

"Z:"="\\??\\d:\\home"


在 Windows 10 中,「預設位置」通常指的是開啟檔案總管時自動進入的資料夾



在 Windows 10 中,「預設位置」通常指的是開啟檔案總管時自動進入的資料夾。


1. 更改預設開啟的資料夾(此電腦或快速存取)

2026年4月21日

若要透過登錄檔(Registry)強制讓所有資料夾預設使用「詳細資料」(Details)檢視模式

 若要透過登錄檔(Registry)強制讓所有資料夾預設使用「詳細資料」(Details)檢視模式,這涉及修改資料夾的 「檢視狀態」(View States) 邏輯。

2026年4月14日

windows cmd 如何使用 dir 顯示一個目錄是否為 junction 與其來源? 而不是用 dir 其所在目錄之後再 parsing 的方式?

 windows cmd 如何使用 dir 顯示一個目錄是否為 junction 與其來源? 而不是用 dir 其所在目錄之後再 parsing 的方式?

2026年3月5日

[VBA] Regular Expression

 在 VBScript 中,內建的 Trim 函數只能移除空白字元 (Space, ASCII 32)。若要移除字串前後的換行符號(如 vbLF、vbCr 或 vbCrLf),你需要使用正規表達式 (RegExp) 或手動循環檢查。 

2026年3月3日

word VBA加速

 

操作文件前先做:

 

    Application.ScreenUpdating = False

    Application.DisplayStatusBar = True

    Application.Options.Pagination = False

 

           …

   

    Set doc = Documents.Add

2026年2月28日

以遠端連線 Windows 10 主機輸入反應過慢,如何解決,但同目標網域之 Windows 7 與 Windows 11 主機無此狀況

 

以遠端連線 Windows 10 主機輸入反應過慢,如何解決,但同目標網域之 Windows 7 Windows 11 主機無此狀況

當同一網域內的 Windows 7 Windows 11 主機皆正常,唯獨 Windows 10 主機出現遠端輸入延遲時,問題通常出在 Windows 10 特有的網路優化機制、顯示驅動程式或特定的通訊協定設定。

您可以嘗試以下解決方案:

2026年1月29日

在 Windows 下,如何關閉遠端桌面的硬體繪圖支援?

在 Windows 中,關閉遠端桌面 (RDP) 的硬體繪圖支援主要可以透過 群組原則 (GPO) 或 登錄編輯器 來達成。這通常用於解決遠端連線時出現的畫面閃爍、格線或效能異常問題。






方法一:透過群組原則編輯器 (推薦)
這是最常見且系統化的方式,適用於 Windows 專業版以上版本:按下 Win + R,輸入 gpedit.msc 並按確認。
導航至:電腦設定 > 系統管理範本 > Windows 元件 > 遠端桌面服務 > 遠端桌面工作階段主機 > 遠端工作階段環境。
尋找 「為遠端桌面連線使用 WDDM 圖形顯示驅動程式」 (Use WDDM graphics display driver for Remote Desktop Connections)。
將其設定為 「已停用」 (Disabled)。
重新啟動電腦或在命令提示字元執行 gpupdate /force 以套用變更。
Microsoft Learn +1

方法二:透過登錄編輯器 (Registry)
如果您使用的是家用版 Windows,或偏好直接修改登錄檔:按下 Win + R,輸入 regedit。
移至路徑:HKEY_LOCAL_MACHINE\SOFTWARE\Policies\Microsoft\Windows NT\Terminal Services。
若沒有對應項目,請右鍵新建一個 DWORD (32 位元) 值,命名為 fEnableWddmDriver。
將數值資料設為 0 以停用 WDDM 驅動程式支援。
針對部分應用程式渲染問題,也可嘗試在 HKEY_CURRENT_USER\Software\Microsoft\Avalon.Graphics 下建立 DisableHWAcceleration (DWORD) 並設為 1。
Microsoft Learn +1

方法三:調整遠端桌面用戶端設定
如果是「用戶端」端造成的卡頓,可在連線前調整:開啟 遠端桌面連線 (mstsc) > 顯示選項 > 體驗。
取消勾選 「永續性點陣圖快取」。
在連線軟體設定中尋找並關閉 「若可用則使用硬體加速」 選項。

您目前的遠端連線是否遇到了特定的顯示異常(如畫面格線或閃爍),需要我針對該現象提供進一步的優化建議嗎?