屏幕坐標與客戶坐標的區別
- 2019 年 10 月 8 日
- 筆記
屏幕坐標是相對於屏幕左上角(0,0)位置的坐標,客戶坐標是相對於某個窗口客戶區左上角的坐標,當談到客戶坐標時需要說明是相對哪個窗口的客戶坐標。

如上圖,點A(屏幕左上角),點B(應用主窗口客戶區左上角),控件1的C點的屏幕坐標和客戶坐標是不同的,屏幕坐標是相對於A點坐標(50,100),客戶坐標(相對於父窗口)是相對於B點坐標(20,50)。
Windows有五個API跟屏幕坐標、客戶坐標有關,要注意區分。
第一,GetWindowRect(HWND, LPRECT) 獲取指定窗口在屏幕的位置,要特別注意該窗口不區分POPUP窗口還是子窗口(子控件)。
第二,GetClientRect(HWND, LPRECT) 獲取指定窗口的客戶區(不包含標題欄)。
第三,ScreenToClient(HWND, LPPOINT) 將屏幕坐標轉換為相對於指定窗口的客戶坐標。
第四,ClientToScreen(HWND, LPPOINT) 將相對於指定窗口的客戶坐標轉換為屏幕坐標。
第五,CreateWindow() 創建窗口,其中窗口位置的坐標跟窗口類型有關,如果窗口是POPUP或OVERLAPPED(也就是指定WS_POPUP或WS_OVERLAPPED)時為屏幕坐標,如果窗口是子窗口(子控件)時為相對於父窗口的客戶坐標。
通過控件1的位置向右平移計算控件2的位置並創建,步驟如下:
第一,調GetWindowRect()指定控件1的句柄,獲取控件1的屏幕坐標。
第二,調ScreenToClient()指定父窗口句柄,獲取控件1在父窗口的客戶坐標。
第三,調OffsetRect()將客戶坐標向右平移
第四,調CreateWindow()指定平移後的坐標,就是控件2的窗口位置。
筆者開發過程中誤以為GetWindowRect()返回的坐標跟窗口類型有關,如果窗口是子窗口(控件)時是客戶坐標,缺少調用ScreenToClient()接口,導致位置不對。