2013-09-05 15 views
4

我想知道畫布的寬度和高度,但我只知道它的HDC。如何通過只知道它的句柄來確定畫布的尺寸?

我已經試過與此代碼:

procedure TForm92.Button1Click(Sender: TObject); 
var 
    hBitmap: HGDIOBJ; 
    Header: TBitmapInfoHeader; 
begin 
    hBitmap := GetCurrentObject(PaintBox1.Canvas.Handle, OBJ_BITMAP); 
    GetObject(hBitmap, sizeof(TBitmapInfoHeader), @Header); 
    ShowMessage(IntToStr(Header.biWidth)); 
end; 

但是它不會返回我PaintBox1畫布的尺寸,而是我得到在其上PaintBox1放置在窗體的尺寸。

我在做什麼錯?

+1

然後你的結果是正確的。一個窗口的檢索DC的句柄,其餘部分是VCL的詭計。 –

+2

[如何找出DC的維度?](http:// stackoverflow。com/questions/3154620/how-to-find-out-dcs-dimensions) –

+0

@David - 問題詢問TCanvas的維度,並且問題中的案例展示了差異。 –

回答

3

鑑於只有處理設備上下文,通常不可能確定與其關聯的對象的尺寸。 TGraphicControl的後代全部共享其父控件的DC,因爲只有窗口控件可以具有設備上下文,並且對象不是窗口控件。

TGraphicControl後代(包括TPaintBox)需要畫布時,TControlCanvas回調到控件的GetDeviceContext方法。該方法返回父控制的DC句柄,但在返回前,它修改DC一點:

Result := Parent.GetDeviceContext(WindowHandle); 
SetViewportOrgEx(Result, Left, Top, nil); 
IntersectClipRect(Result, 0, 0, Width, Height); 

也就是說,它改變原點到電流控制的左上角匹配,並且它更新裁剪區域排除當前控件邊框外的任何內容。

一些情況下,你也許可以通過檢查DC的剪輯區域確定畫布的尺寸(含GetClipRgn),但前提是該區域尚未被任何其他方式調整,那是。裁剪區域可能小於控件的尺寸。 (由於上面顯示的IntersectClipRect的調用,它永遠不會更大。)

正如你所看到的,你需要的不僅僅是DC處理來獲取你想要的信息。理想情況下,這將包括一個TControl參考;那麼您只需閱讀其HeightWidth屬性即可瞭解控件的畫布的尺寸。

+0

感謝您的解釋。 – Wodzu

1

TCanvas的句柄指向Windows設備上下文(DC)。假設顯示設備上下文(而不是打印機,內存或信息DC),則該DC的邏輯大小等於(總)屏幕分辨率,可通過GetDeviceCapsGetSystemMetrics獲得。 (雖然你可以繪製超出這個尺寸,產量將被削減)。

顯示設備上下文的最大可見部分受其相關窗口大小限制,可通過WindowFromDCGetClientRect獲取。

當前可見部分可能受到當前框架(如Delphi VCL中的TPaintBox)的限制,該框架沒有窗口句柄,取而代之的是依賴框架將尺寸轉換爲父級DC內控件大小,這可通過檢查控制器的尺寸獲得)或由當前設置的剪輯區域(可通過GetClipRgn獲得)來實現。