修改窗體客戶區區域

2021-08-27 09:40:06 字數 2969 閱讀 9621

當windows客戶區的大小和位置需要重新計算時會發出該訊息,因此,攔截該訊息可以控制windows窗體客戶

區的尺寸和位置。wm_nccalcsize

的定義為:

#define wm_nccalcsize                   0x0083
c#定義為:

const int wm_nccalcsize = 0x0083;
並且當訊息引數wparam為true時,lparam引數為nccalcsize_params型別的指標,該型別包含了可用於計算客戶區大小和位置的資訊。nccalcsize_params的簽名:

typedef struct tagnccalcsize_params  nccalcsize_params, *lpnccalcsize_params;
c#宣告:

struct nccalcsize_params 

struct _rect

c#對nccalcsize_params的宣告與c/c++的宣告看似有一點點不同,c/c++定義的是rect陣列,而c#

則變成了三個單獨的rect欄位,當前效果是一樣的,只不過乙個使用來所有物件,而乙個是自己訪問而已。

也就是前者的rgrc[0]與後者的rcnewwindow對應,前者的rgrc[1]與rcoldwindow對應,和前者的rgrc[2]與

rcclient對應。只所有c#分別定義,主要是為了更好的說明這三個rect分別表示的意思。

第乙個rect或rcnewwindow儲存了窗體被移動或尺寸被修改後的窗體的座標資訊,這是視窗馬上要應用的資訊,即視窗馬上就移動到座標(rcnewwindow.left, rcnewwindow.top),並且尺寸將調整為

(rcnewwindow.right-rcnewwindow.left, rcnewwindow.bottom-rcnewwindow.top);而第二個rect

或rcoldwindow儲存移動前或尺寸被改變前窗體的座標資訊;第三個rect或rcclient儲存了移動前或尺寸修

改前客戶區的座標資訊。如果窗體是子窗體,那麼座標資訊都使相對父窗體的,否則座標是相對於螢幕的。

然而,當訊息處理完畢後,第乙個rect或rcnewwindow則被用來儲存移動後或大小改變後的客戶區的座標

資訊,即計算夠的結果。也可以推測出計算過程使用rcnewwindow座標與當前作業系統和主題下的窗體標題

欄的高度和窗體邊框的厚度等資訊計算得來。假設窗體高度為captionheight,窗體邊框厚度為borderwidth,

那麼客戶區就可以通過公式計算得出客戶區域座標:

client.left = rcnewwindow.left + borderwidth

client.top = rcnewwindow.top + borderwidth + captionheight

client.right = rcnewwindow.right - borderwidth

client.bottom = rcnewwindow.bottom - borderwidth

其實窗體邊框厚度和窗體高度都可以從類system.windows.forms.systeminformation中獲取,不過要根據窗體型別和主題等選擇不同的厚度和高度,這裡不再詳細說明。你可以在視窗建立時攔截wm_nccalcsize

訊息,獲取nccalcsize_params引數,並根據rcnewwindow和rcclient來計算窗體邊框厚度和標題欄

高度。前面的文字目的,主要是為了說明客戶區域的座標資訊,是根據窗體的新座標資訊、窗體邊框厚度和標題欄的高度進行計算得來的。因此我們可以攔截wm_nccalcsize訊息,人為的修改窗體的座標資訊,從而影響客

戶區座標資訊的計算結果。

由前面說的公式可以看出,對新視窗座標的增減就是對客戶區座標的增減,因此,如下攔截訊息**,實現了加寬,加高客戶區的效果:

private void adjustclientrect(ref _rect rcclient) 

const int wm_nccalcsize = 0x0083;

protected override void wndproc(ref message m)

m.result = new intptr(1);

}break; }

base.wndproc(ref m);

}

由於客戶區的寬和高都增加了,但窗體大大小和位置並沒有變化,因此執行的效果就如圖所示,左右和下邊框

的厚度明顯變小,而標題欄沒有變化,因為我們沒有調整rcclient.top欄位。

因此,如果你再重繪窗體,希望窗體在各版本的windows作業系統和主題中表現一致,可以希望保持窗體的版

塊厚度為borderwidth,你就可以這樣來調整**:

int borerwidth = 1;

private void adjustclientrect(ref _rect rcclient)

這裡也沒有設定rcclient.top,以為窗體頂部的邊框在標題欄上訪,這裡簡單的修改rcclient.top是達不到預期效果的,需要重繪標題欄才行,可以參見《

c#重繪windows窗體標題欄和邊框

》。執行效果如下:

當然,你也可以利用這個方法,在不設定formborderstyle屬性為none的情況下,實現無邊框視窗的效果。

簡單修改**即可實現:

private void adjustclientrect(ref _rect rcclient)
雖然通過攔截wm_nccalcsize訊息的方法可以實現修改客戶區域座標、邊框厚度、無邊框等效果,但還是文章開頭所說的,實現在各種windows作業系統版本和主題下統一樣式才是主要應用,當然這只是統一樣式的

一部分,可以統一視窗邊框的厚度,至於窗體的邊框的樣式,甚至整個窗體的樣式,還是需要結合重繪標題欄

和邊框的,如需要,可以參考《

c#重繪windows窗體標題欄和邊框

》的實現。

修改窗體客戶區區域

當windows客戶區的大小和位置需要重新計算時會發出該訊息,因此,攔截該訊息可以控制windows窗體客戶 區的尺寸和位置。wm nccalcsize 的定義為 define wm nccalcsize 0x0083c 定義為 const int wm nccalcsize 0x0083 並且當訊...

視窗區域和客戶區域

getclientrect 此函式用於取得視窗的客戶區座標。客戶區即視窗客戶區的左上角和右下角之間 的區域。客戶區座標的原點位於視窗客戶區的左上角,即用此函式得到的座標的 原點是視窗客戶區的左上角,左上角的的座標值為 0,0 返回值 成功時返回非0,失敗時返回0 注意 在與結構rect之間的轉換中為...

Qt控制項窗體區域區分

控制項窗體區域區分 幾何引數 指的是視窗的大小和位置,乙個視窗有兩套幾何引數,一套是視窗外邊框所佔的矩形區域,另一套是視窗客戶區所佔的矩形區域,所謂視窗客戶區就是視窗中除去邊框和標題欄用來顯示內容的區域 對於乙個視窗部件來說,它的兩套幾何引數是一致的 const qrect geometry con...