2011-02-04 37 views
8

我想創建一個窗口,將是主要的窗口和Windows本身識別爲一個主應用程序窗口。但是,當我使窗口無邊界,並且根本沒有任何非客戶端區域時,Windows不再認識到此窗口是應用程序主窗口。這有幾個副作用:您可以在Windows中創建無邊界應用程序主窗口,無WS_POPUP樣式嗎?

  1. WindowsKey + M最小化除了我的應用程序的主窗口之外的所有窗口。

  2. 在任務欄(在Win7)上點擊一次,然後再次,應可以切換正常和最小化狀態之間的應用程序主窗口的狀態/可見度。這不適用於這樣的窗口。

在裸Win32編程方面,我問有關dwStyle參數值調用CreateWindow(WS _...常數)時一樣,或CreateWindowEx(WS_EX _...常數)。對於delphi用戶,這些值將在CreateParams方法中設置,您可以覆蓋它,然後設置Params.Style:= WS_xxx;對於MFC/C++用戶和C用戶,框架中的某些內容最終將調用CreateWindow,並帶有此dwStyle值。

德爾福而言,設置你的form.BorderStyle = bsNone,結果在dwStyle = WS_POPUP。但是,我想要一個無邊界窗口,而不使用dwStyle = WS_POPUP。

注意:以下所有答案都很好,但在生產場景中使用每個都是有問題的,而且我嘗試這樣做會導致遇​​到許多小故障,對於專業的高質量應用程序,我仍然發現我無法工作周圍。 Davids答案雖然是一個很好的純Win32 API答案,並且符合法案。看起來,一個工業實力的解決方案應該結合多種品質,包括我上面提到的所有問題。簡而言之,使用BorderStyle = bsNone(dwStyle = WS_POPUP)的無邊界窗體會阻止通常應用於應用程序主窗口的所有Windows功能,並且下面的所有解決方案都將解決其中的一部分問題。

根據David的建議,我編寫了以下內容,這不起作用: 我想要一個沒有邊框的窗口,該窗口在所有方面都像Windows應用程序窗口一樣對系統有效,也就是說,它可以通過點擊任務欄中的窗口最小化/恢復,並通過WindowsKey + M最小化。我開始認爲要做到這一點的唯一方法是添加非客戶端的繪製代碼並將頂級非客戶端區域邊界調整爲零。這當然不是一個簡單的想法。

事實證明,我做我的編碼一個簡單的錯誤(因此上述兩個段落),實際上下面的代碼現在所做的工作,我的願望。這是一個pascal,但它應該很容易轉換爲C++或其他任何東西。

program NoBorderProject; 

uses 
    Windows, Messages; 
    {the Messages unit contains the windows 
    Message constants like WM_COMMAND} 

{$R *.RES} 

var 
    wClass: TWndClass; 
    Msg: TMsg; 
    win:HWND; 
function WindowProc(hWnd,Msg,wParam,lParam:Integer):Integer; stdcall; 
begin 
if Msg = WM_DESTROY then PostQuitMessage(0); 
Result := DefWindowProc(hWnd,Msg,wParam,lParam); 
end; 

begin 
wClass.lpszClassName:= 'CN'; 
wClass.lpfnWndProc := @WindowProc; 
wClass.hInstance := hInstance; 
wClass.hbrBackground:= 1; 
RegisterClass(wClass); 
win := CreateWindow(wClass.lpszClassName,'Title Bar', 
       WS_POPUP,//WS_OVERLAPPEDWINDOW or WS_VISIBLE, 
       10,10,340,220,0,0,hInstance,nil); 
SetWindowLong(win, GWL_STYLE, WS_POPUP or WS_MINIMIZEBOX); 
SetWindowLong(win, GWL_EXSTYLE, 0); 
ShowWindow(win,SW_SHOW); 
while GetMessage(Msg,0,0,0) do 
    DispatchMessage(Msg); 
end. 
+1

我發現了您的錯誤。你設置了兩次`GWL_STYLE`。第二次調用`SetWindowLong`應該設置`GWL_EXSTYLE`。 – 2011-02-05 12:27:13

+0

在這裏使用D7,MainForm.BorderStyle = bsNone不會阻止WinKey + M的工作。還要儘量減少/恢復切換。這可以歸因於TApplication中的MainFormOnTaskbar屬性,它是在較新的Delphi版本中默認設置的? – NGLN 2011-07-13 17:08:30

+0

NGLN-的確如此。 Delphi 7有一個虛假的頂級應用程序窗口,所以Windows本身並不認爲你的窗體是你的應用程序主窗口,它使用古老的Delphi隱藏的特殊主窗口。這種行爲也是Delphi 7時代主要形式黑客固有的Z-Order錯誤的根源。 – 2011-07-14 13:28:28

回答

13

下能夠完成任務:

hWnd = CreateWindow(...); 
SetWindowLong(hWnd, GWL_STYLE, WS_POPUP | WS_MINIMIZEBOX); 
SetWindowLong(hWnd, GWL_EXSTYLE, 0); 
ShowWindow(hWnd, ...); 

你可能失蹤WS_MINIMIZEBOX

+0

這不起作用。我的猜測是,如果你不想有邊框,你不能避免`WS_POPUP`樣式。但是,即使* WS_POPUP位在那裏,也許你可以使窗口正常運行? – 2011-02-04 19:46:05

4

有點噁心,但你可以把這個在YourForm.OnShow事件設置窗口的區域:

var 
    r: TRect; 
begin 
    r := ClientRect; 
    OffsetRect(r, 0, GetSystemMetrics(SM_CYCAPTION)); 
    OffsetRect(r, GetSystemMetrics(SM_CXFRAME), GetSystemMetrics(SM_CYFRAME)); 
    SetWindowRgn(Handle, 
     CreateRectRgn(
      r.Left, r.Top, 
      ClientWidth + r.Left, ClientHeight + r.Top), True); 
-4

你需要重寫TForm的。CreateParams並設置或刪除您感興趣的任何樣式

procedure TYourForm.CreateParams(var Params: TCreateParams); 
begin 
    inherited CreateParams(Params); 
    Params.Style := Params.Style and 
    Params.ExStyle := Params.ExStyle or ; 
end; 
相關問題