窗体边框基本的绘制和控制完成,在第二篇中主要遗留的问题。

  • 标题区域图标和按钮没绘制
  • 缩放时客户区显示有问题

 

 解决完下面的问题,皮肤处理基本完整。大致的效果GIF

窗体皮肤实现 - 重绘窗体非客户区(三)

 GIF中TShape的颜色表现有些问题,实际是正常的。

 

绘制标题区域内容

  1. 获取标题有效区域
  2. 绘制窗体图标
  3. 绘制按钮
  4. 绘制标题

  标题区域主要考虑窗体是否在最大化状态,最大化后实际的标题绘制区域会有变化。可以通过 IsZoomed 或 GetWindowLong(Handle, GWL_STYLE) and WS_MAXIMIZE = WS_MAXIMIZE 的方式获取。

 1 AMaxed := IsZoomed(Handle);    // 获取窗体最大化状态
 2 
 3 function TTest.GetCaptionRect(AMaxed: Boolean): TRect;
 4 var
 5   rFrame: TRect;
 6 begin
 7   rFrame := GetFrameSize;         // 窗体上下左右的边框尺寸
 8   // 最大化状态简易处理
 9   if AMaxed then
10     Result := Rect(8, 8, FWidth - 9 , rFrame.Top)
11   else
12     Result := Rect(rFrame.Left, 3, FWidth - rFrame.right, rFrame.Top);
13 end;

 

绘制窗体图标稍微有些麻烦,需要获取窗体的Icon图标。窗体图标并不一定是程序图标。主要过程通过WM_GETICON 这个消息获取图标。

1   TmpHandle := THandle(SendMessage(Handle, WM_GETICON, ICON_SMALL, 0));
2   if TmpHandle = 0 then
3     TmpHandle := THandle(SendMessage(Handle, WM_GETICON, ICON_BIG, 0));

如果上述方法无法获得,需要通过GetClassName 和 GetClassInfoEx 这2个API获取。

 1 { Get instance }
 2 GetClassName(Handle, @Buffer, SizeOf(Buffer));
 3 FillChar(Info, SizeOf(Info), 0);
 4 Info.cbSize := SizeOf(Info);
 5 
 6 if GetClassInfoEx(GetWindowLong(Handle, GWL_HINSTANCE), @Buffer, Info) then
 7 begin
 8   TmpHandle := Info.hIconSm;
 9   if TmpHandle = 0 then
10     TmpHandle := Info.HICON;
11 end

  上述这2种方法还是无法获取。那~~ 就没有办法了。如果非要绘制图标可以使用Application的图标进行代替。

1 Application.Icon.Handle
 1 function TTest.GetIcon: TIcon;
 2 var
 3   IconX, IconY: integer;
 4   TmpHandle: THandle;
 5   Info: TWndClassEx;
 6   Buffer: array [0 .. 255] of Char;
 7 begin
 8   ///
 9   /// 获取当前form的图标
10   /// 这个图标和App的图标是不同的
11   ///
12   TmpHandle := THandle(SendMessage(Handle, WM_GETICON, ICON_SMALL, 0));
13   if TmpHandle = 0 then
14     TmpHandle := THandle(SendMessage(Handle, WM_GETICON, ICON_BIG, 0));
15 
16   if TmpHandle = 0 then
17   begin
18     { Get instance }
19     GetClassName(Handle, @Buffer, SizeOf(Buffer));
20     FillChar(Info, SizeOf(Info), 0);
21     Info.cbSize := SizeOf(Info);
22 
23     if GetClassInfoEx(GetWindowLong(Handle, GWL_HINSTANCE), @Buffer, Info) then
24     begin
25       TmpHandle := Info.hIconSm;
26       if TmpHandle = 0 then
27         TmpHandle := Info.HICON;
28     end
29   end;
30 
31   if FIcon = nil then
32     FIcon := TIcon.Create;
33 
34   if TmpHandle <> 0 then
35   begin
36     IconX := GetSystemMetrics(SM_CXSMICON);
37     if IconX = 0 then
38       IconX := GetSystemMetrics(SM_CXSIZE);
39     IconY := GetSystemMetrics(SM_CYSMICON);
40     if IconY = 0 then
41       IconY := GetSystemMetrics(SM_CYSIZE);
42     FIcon.Handle := CopyImage(TmpHandle, IMAGE_ICON, IconX, IconY, 0);
43     FIconHandle := TmpHandle;
44   end;
45 
46   Result := FIcon;
47 end;
完整获取窗体图标的方法

相关文章: