窗體皮膚實現 - 重繪窗體非客戶區(二)


第一個實現了基本處理。窗體邊框的寬度有些肥大,需要進行瘦身。

實現:

    1、改變外框線寬度 (WM_NCCALCSIZE

    2、改變外框樣式 (WM_WINDOWPOSCHANGING

 

通過 WM_NCCALCSIZE 消息可以實現目的。

 

procedure WMNCCalcSize(var message: TWMNCCalcSize); message WM_NCCALCSIZE;

procedure TTest.WMNCCalcSize(var message: TWMNCCalcSize);
const
  SIZE_BORDER = 5;
  SIZE_CAPTION = 28;
begin
  // 改變邊框尺寸
  with TWMNCCALCSIZE(Message).CalcSize_Params^.rgrc[0] do
  begin
    Inc(Left, SIZE_BORDER);
    Inc(Top, SIZE_CAPTION);
    Dec(Right, SIZE_BORDER);
    Dec(Bottom, SIZE_BORDER);
  end;
  Message.Result := 0;
  Handled := True;
end;

 

窗體的四個角的表現樣式可以看出是XP的界面輪廓。倒角的幅度感覺有些大改小些。

 

調整外框樣式需要在窗體改變尺寸時進行處理,這種方法還可以實現不規則窗體。

WM_WINDOWPOSCHANGING 這個消息可以滿足需要。

處理是需要注意的問題:

  1、因為是在調整過程中實際窗體的尺寸是無法通過 GetWindowRect 這個函數獲取調整后的狀態,因此需要保存有這個消息產生的窗體調整尺寸信息。

  2、這個消息會有很多模式,這個消息的觸發來源 SetWindowPos 可以設置很多參數。我們只要處理窗體改變大小的模式,其他需要交由系統默認處理。

 

調用控件默認消息處理

procedure TTest.CallDefaultProc(var message: TMessage);
begin
  ///
  ///  調用控件默認消息處理過錯
  ///    為防止出現循環調用,需要使用狀態控制(FCallDefaultProc)
  ///
  if FCallDefaultProc then
    FControl.WindowProc(message)
  else
  begin
    FCallDefaultProc := True;
    FControl.WindowProc(message);
    FCallDefaultProc := False;
  end;
end;

記錄窗體位置和尺寸,並對窗體進行調整外框樣式

procedure TTest.WMWindowPosChanging(var Message: TWMWindowPosChanging);
var
  bChanged: Boolean;
begin
  /// 由外部優先處理消息,完成以下默認的控制
  CallDefaultProc(TMessage(Message));

  Handled := True;
  bChanged := False;

  /// 防止嵌套
  if FChangeSizeCalled then
    Exit;

  /// 調整窗體外框
  ///   如果窗體尺寸有調整時需要重新生成窗體外框區域。
  ///
  if (Message.WindowPos^.flags and SWP_NOSIZE = 0) or
     (Message.WindowPos^.flags and SWP_NOMOVE = 0) then
  begin
    if (Message.WindowPos^.flags and SWP_NOMOVE = 0) then
    begin
      FLeft := Message.WindowPos^.x;
      FTop := Message.WindowPos^.y;
    end;
    if (Message.WindowPos^.flags and SWP_NOSIZE = 0) then
    begin
      bChanged := ((Message.WindowPos^.cx <> FWidth) or (Message.WindowPos^.cy <> FHeight)) and
                 (Message.WindowPos^.flags and SWP_NOSIZE = 0);
      FWidth := Message.WindowPos^.cx;
      FHeight := Message.WindowPos^.cy;
    end;
  end;

  if (Message.WindowPos^.flags and SWP_FRAMECHANGED  <> 0) then
    bChanged := True;

  // 進行調整和重繪處理
  if bChanged then
  begin
    ChangeSize;
    InvalidateNC;
  end;
end;

調整窗體樣式 

 1 procedure TTest.ChangeSize;
 2 var
 3   hTmp: HRGN;
 4 begin
 5   /// 調整窗體樣式
 6   FChangeSizeCalled := True;
 7   try
 8     hTmp := FRegion;
 9     try
10       /// 創建 倒角為3的矩形區域。
11       ///    在這里可以實現不規則界面的創建,可以通過bmp創建繪制區域
12       ///
13       ///  注:
14       ///    HRGN 句柄是是圖形對象,由window管理的資源,不釋放會出現內存泄露,
15       ///    后果,你懂得。
16       FRegion := CreateRoundRectRgn(0, 0, FWidth, FHeight, 3, 3);
17       SetWindowRgn(Handle, FRegion, True);
18     finally
19       if hTmp <> 0 then
20         DeleteObject(hTmp); // 釋放資源
21    end;
22   finally
23     FChangeSizeCalled := False;
24   end;
25 end;

 

調整后的最終效果,瘦身感覺不錯還算精致。

 

代碼下載: TestCaptionToolbar(v0.2).7z   

    http://pan.baidu.com/s/1jG64aFW

    https://github.com/cmacro/simple

蘑菇房 (moguf.com)


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM