简介:本篇文章将介绍在Delphi编程环境中如何自定义绘制并实现一个圆形窗体。Delphi使用Object Pascal语言,基于组件的可视化开发工具,窗体通常为矩形,但通过自定义绘制技术可以创建非矩形窗体。我们将讲解通过覆盖OnPaint事件、禁用边框和标题栏以及处理透明效果等技术点来实现圆形窗体的方法。同时,提供示例代码和扩展应用的介绍。
1. Delphi窗体自定义绘制基础
自定义绘制的重要性
在Delphi应用程序开发中,窗体自定义绘制是实现用户界面个性化和专业化的关键环节。通过精细的自定义绘制技术,开发者可以将应用程序的界面从普通的矩形窗体,转变为具有吸引力的自定义形状窗体。这不仅能提升用户体验,还能让软件在功能上具备更独特的交互方式。
Delphi的绘图机制
Delphi使用GDI(图形设备接口)进行窗体绘制。它为开发者提供了丰富的图形对象和方法,例如 Canvas 对象,让开发者可以在窗体上绘制各种图形。自定义绘制通常涉及到覆盖窗体的 OnPaint 事件,在其中编写绘制代码以实现个性化界面。
开始自定义绘制的步骤
要开始自定义绘制,首先需要了解窗体的 OnPaint 事件,它是窗体进行重绘时触发的事件。接下来,通过 Canvas 对象进行图形绘制是实现自定义界面的基础。下面的章节将深入探讨如何通过覆盖 OnPaint 事件和利用 Canvas 对象来自定义绘制Delphi窗体。
procedure TForm1.FormPaint(Sender: TObject);
begin
// 示例:绘制一个简单的矩形框
Canvas.Rectangle(10, 10, 100, 100);
end;
在上面的代码片段中,我们在窗体的 OnPaint 事件中使用 Canvas 对象的 Rectangle 方法绘制了一个矩形。这只是自定义绘制的起始点,后面章节将深入讨论如何绘制更复杂的图形。
2. 覆盖OnPaint事件进行窗体绘制
2.1 OnPaint事件的触发与作用
2.1.1 理解OnPaint事件的时机
在Delphi应用程序中,窗体(Form)是主要的可视组件,用于承载各种控件并提供用户交互界面。窗体的外观通过绘制来实现,而这一绘制过程主要是通过响应Windows消息系统中的一系列消息来完成的。在这些消息中, WM_PAINT 消息用于指示窗体需要重绘自身的一部分或全部区域。
OnPaint 事件是Delphi封装的事件处理器,它在窗体接收到 WM_PAINT 消息时被触发。开发者可以通过覆盖(override)窗体的 OnPaint 事件处理方法来实现自定义的绘制逻辑。通过这种方式,开发者可以控制窗体在屏幕上显示的内容,如绘制基本图形、文本、复杂的图案和动画等。
OnPaint 事件的触发时机通常包括以下几种情况:
- 窗体首次显示时,系统会发送
WM_PAINT消息以要求绘制整个窗体。 - 窗体大小改变后,未被系统缓存的区域需要重新绘制。
- 窗体被其他窗口遮挡后再次显示时,需要重新绘制被遮挡的部分。
- 应用程序主动调用
Invalidate或Repaint方法时,窗体会被标记为需要重绘,并触发WM_PAINT消息。
2.1.2 OnPaint事件与窗体绘制的关系
OnPaint 事件是窗体绘图过程中最核心的部分,因为它直接关联到应用程序如何响应绘制请求。一个典型的窗体绘制流程如下:
- Windows系统检测到需要进行窗体绘制,比如窗体显示、大小改变等情况。
- Windows向窗体发送
WM_PAINT消息。 - Delphi消息循环捕获到
WM_PAINT消息,然后触发对应的OnPaint事件。 - 在
OnPaint事件的处理过程中,通过调用Canvas对象的方法来绘制所需的图形和内容。 - 绘制完成后,消息循环返回到系统,窗口更新显示。
OnPaint 事件与 Canvas 对象紧密关联, Canvas 提供了绘制各种图形和文本的接口。在 OnPaint 事件处理方法中,可以利用 Canvas 的属性和方法来定义窗体或控件的外观,如颜色、字体、图形、位图等。
接下来,我们将通过具体的代码示例,展示如何覆盖 OnPaint 事件来实现窗体内容的自定义绘制。
2.2 通过OnPaint实现窗体内容自定义
2.2.1 在OnPaint中绘制基本图形
在Delphi中,绘制基本图形如矩形、椭圆、直线等,是通过调用 Canvas 对象的方法来完成的。下面是一个简单的例子,展示了如何在 OnPaint 事件中绘制一个蓝色的矩形和一个红色的椭圆。
procedure TForm1.FormPaint(Sender: TObject);
begin
// 绘制矩形
Canvas.Brush.Color := clBlue; // 设置画刷颜色为蓝色
Canvas.Rectangle(50, 50, 200, 150); // 绘制矩形,参数为左上角和右下角坐标
// 绘制椭圆
Canvas.Brush.Color := clRed; // 设置画刷颜色为红色
Canvas.Ellipse(50, 50, 200, 150); // 绘制椭圆,参数为包含椭圆的矩形区域坐标
end;
在上述代码中, FormPaint 是 TForm 类的一个方法,它是 OnPaint 事件的一个实现。我们使用 Canvas 对象的 Brush 属性来设置填充颜色,并利用 Rectangle 和 Ellipse 方法来绘制矩形和椭圆。 Rectangle 方法的参数是矩形左上角和右下角的坐标,而 Ellipse 方法的参数是包含椭圆的矩形区域的左上角和右下角坐标。
2.2.2 利用OnPaint绘制复杂图形
复杂图形的绘制可能涉及到多边形、贝塞尔曲线、透明度等高级特性。以下是如何在 OnPaint 事件中绘制一个多边形和应用透明度的示例。
procedure TForm1.FormPaint(Sender: TObject);
var
Points: array[0..3] of TPoint;
begin
// 绘制多边形
Points[0] := Point(100, 100);
Points[1] := Point(200, 100);
Points[2] := Point(150, 150);
Points[3] := Point(100, 200);
Canvas.Polygon(Points);
// 绘制具有透明效果的图形
Canvas.Brush.Style := bsClear; // 设置画刷透明
Canvas.Pen.Color := $0000FF00; // 设置画笔颜色,Alpha值控制透明度
Canvas.Rectangle(250, 50, 400, 200);
end;
在这个例子中,我们首先定义了一个 Points 数组,用来存储多边形各个顶点的坐标。然后使用 Polygon 方法绘制一个多边形。接着,我们通过设置 Brush.Style 为 bsClear 和使用具有透明成分的 Pen.Color 来绘制一个带有透明效果的矩形。
通过覆盖 OnPaint 事件,我们不仅可以绘制静态图形,还可以通过改变逻辑和数据,实现动态的图形绘制和复杂的视觉效果。随着应用程序对美观性和用户体验的要求不断提高,掌握如何在Delphi中通过 OnPaint 事件进行窗体绘制变得越来越重要。
3. Canvas对象在自定义绘制中的应用
3.1 Canvas对象的基本使用方法
3.1.1 Canvas对象的属性和方法介绍
在Delphi中,Canvas对象是用于绘图的主要工具。通过它的各种属性和方法,可以在窗体上绘制各种图形和文本。Canvas对象提供了丰富的绘图功能,包括但不限于绘制线条、矩形、圆形、椭圆、多边形、贝塞尔曲线以及设置图形颜色和样式等。
要使用Canvas对象,首先需要确保有一个有效窗体的OnPaint事件处理器。通常,在OnPaint事件中,窗体会向其Canvas对象发出绘图命令。下面列出了一些Canvas对象的基本属性和方法:
-
Pen:用于设置绘制线条的样式、宽度和颜色。 -
Brush:用于设置填充图形的颜色和样式。 -
MoveTo和LineTo:用于绘制线条。 -
Rectangle:用于绘制矩形或正方形。 -
FillRect和FrameRect:用于绘制填充或边框的矩形。 -
Pie:用于绘制扇形。 -
Arc:用于绘制弧线。 -
TextOut和TextRect:用于在指定位置输出文本。 -
SetPixel和GetPixel:用于设置或获取特定像素点的颜色。
3.1.2 Canvas与图形绘制的基本实例
下面通过一个简单的示例,展示如何在Delphi的窗体上使用Canvas对象绘制基本图形:
procedure TForm1.FormPaint(Sender: TObject);
begin
Canvas.Pen.Color := clRed; // 设置绘制线条的颜色为红色
Canvas.Pen.Width := 2; // 设置绘制线条的宽度为2
Canvas.MoveTo(10, 10); // 移动画笔到(10,10)的位置
Canvas.LineTo(100, 100); // 从当前位置绘制一条线到(100,100)
Canvas.Brush.Color := clBlue; // 设置填充颜色为蓝色
Canvas.FillRect(Rect(50, 50, 150, 150)); // 填充一个矩形框
Canvas.Font.Color := clGreen; // 设置字体颜色为绿色
Canvas.TextOut(50, 20, 'Hello World'); // 在位置(50, 20)绘制文本
end;
在上述代码中,我们设置了笔的颜色为红色,并绘制了一条线段。接着,我们设置了画刷的颜色为蓝色,并填充了一个矩形区域。最后,我们设置了字体颜色为绿色,并在指定位置绘制了文本“Hello World”。
在使用Canvas对象进行绘图时,通常会遵循以下步骤: 1. 定义画笔颜色、宽度和样式。 2. 定义画刷颜色和样式。 3. 使用相应的Canvas方法进行绘图。 4. 清理资源,结束绘图。
3.2 Canvas对象在复杂图形绘制中的应用
3.2.1 绘制多边形和路径
在复杂图形绘制中,Canvas对象提供了绘制多边形和路径的方法,这为创建复杂几何形状提供了灵活性。
Polygon 方法用于绘制多边形,它接受一个 TPoint 数组作为参数,该数组定义了多边形的各个顶点:
var
Points: array[0..3] of TPoint;
begin
Points[0] := Point(10, 10);
Points[1] := Point(100, 10);
Points[2] := Point(100, 100);
Points[3] := Point(10, 100);
Canvas.Polygon(Points);
end;
Polyline 方法用于绘制折线,它同样接受一个 TPoint 数组作为参数,但与 Polygon 不同的是, Polyline 不会闭合路径,即不会连接最后一个点和第一个点:
var
Points: array[0..3] of TPoint;
begin
// 定义点数组...
Canvas.Polyline(Points);
end;
BeginPath 、 EndPath 和 StrokePath 用于绘制路径。首先调用 BeginPath 开始一条新路径,接着可以使用Canvas的方法绘制线条和形状,最后用 EndPath 结束路径。如果需要填充路径,可以在调用 EndPath 之前使用 FillPath 方法。 StrokePath 用于将路径按当前画笔样式绘制出来:
Canvas.BeginPath;
try
Canvas.MoveTo(50, 50);
Canvas.LineTo(150, 50);
Canvas.LineTo(100, 150);
Canvas.EndPath;
Canvas.StrokePath; // 绘制路径的边框
Canvas.FillPath; // 填充路径内部
finally
Canvas.EndPath;
end;
3.2.2 图形的样式设置与颜色运用
在使用Canvas进行绘图时,可以通过各种属性来设置图形的样式和颜色。例如:
-
Pen.Style:用于设置绘制线条的样式,如psSolid(实线)、psDash(虚线)等。 -
Brush.Style:用于设置图形填充的样式,如bsSolid(实心)、bsClear(透明)等。 -
Pen.Mode和Brush.Mode:用于设置绘制或填充的颜色模式,如pmCopy(正常颜色)、pmMergePenNot(使用前景色和背景色混合绘制)等。
此外, Canvas 还提供了颜色混合功能,如 ***bineMode 属性,可以根据不同的模式(如 cmMerge 、 cmSourceCopy 等)混合源颜色和目标颜色。
``` bineMode := cmMerge; Canvas.Pen.Color := clRed; Canvas.Brush.Color := clGreen; Canvas.Rectangle(100, 100, 200, 200);
在上述代码中,`CombineMode`设置为`cmMerge`后,绘制的矩形区域将根据前景色(红色笔)和背景色(绿色填充)进行颜色混合。
通过这些属性和方法的组合使用,可以创建出丰富多彩且视觉效果各异的图形界面。
# 4. 创建无边框无标题栏的圆形窗体
在Delphi中,创建一个无边框无标题栏的圆形窗体需要利用Windows API函数以及Delphi的窗体属性和事件。这种窗体在用户界面设计中非常有用,尤其是在需要自定义界面外观时。在本章节中,我们将详细了解如何实现这样的窗体,并讨论其技术要点。
## 4.1 禁用窗体边框和标题栏的方法
### 4.1.1 通过窗体属性设置实现
要创建一个无边框无标题栏的窗体,首先需要在窗体的`OnCreate`事件中禁用窗体的边框和标题栏。这可以通过设置`FormStyle`属性来实现。Delphi 中的窗体可以设置为`fsNormal`(普通窗体),`fsStayOnTop`(总在最上层窗体),或者`fsMDIForm`(MDI窗体)。为了创建一个无边框窗体,需要使用`fsStayOnTop`属性,并进一步调用Windows API来隐藏标题栏。
```delphi
procedure TForm1.FormCreate(Sender: TObject);
begin
// 设置窗体样式为无边框无标题栏样式
Self.WindowState := wsNormal;
Self.FormStyle := fsStayOnTop;
// 其他窗体样式设置...
end;
4.1.2 禁用边框和标题栏后的窗体特性
禁用边框和标题栏后,窗体会失去默认的拖动和尺寸调整功能。这意味着开发者需要自行实现这些功能。例如,可以在窗体上添加自定义的控件或响应鼠标事件来模拟拖动和尺寸调整行为。此外,由于缺乏标题栏,任何需要的功能,如关闭、最小化和最大化按钮,都需要开发者手动添加和管理。
4.2 实现窗体透明效果的技术要点
4.2.1 窗体透明度的设置方法
为了进一步增强窗体的自定义性,开发者可以设置窗体的透明度,从而让窗体背景的部分区域透明。Delphi 提供了 AlphaBlend 属性来设置窗体的透明度,但这个属性在某些版本的Delphi中可能不可用,或者仅在特定的Windows版本上支持。如果要跨平台支持透明效果,可以使用Windows API中的 SetLayeredWindowAttributes 函数。
const
LWA_COLORKEY = $***;
LWA_ALPHA = $***;
function SetLayeredWindowAttributes(hWnd: HWND; crKey: COLORREF;
bAlpha: byte; dwFlags: DWORD): boolean; stdcall; external user32;
procedure TForm1.FormCreate(Sender: TObject);
var
lColorKey: COLORREF;
begin
// 设置窗体透明度
lColorKey := RGB(0, 0, 0); // 选择颜色键值
SetLayeredWindowAttributes(Handle, lColorKey, 128 {Alpha值}, LWA_ALPHA);
end;
4.2.2 透明窗体的兼容性与性能考虑
虽然设置窗体的透明度可以带来美观的效果,但开发者必须考虑透明窗体的兼容性问题和性能影响。在较旧的Windows版本或低配置计算机上,开启窗体透明度可能会导致性能下降,尤其是在窗体覆盖区域较多的情况下。因此,在设计时应考虑是否真的需要透明效果,或者是否可以采用其他视觉效果替代。
在实现无边框无标题栏窗体的过程中,开发者需要了解和解决的不仅仅是外观上的改变,还需要考虑如何处理新窗体的各种行为,比如拖动、大小调整和事件响应。通过本章节的介绍,我们已经了解到如何在Delphi中创建这样的窗体,并且对其技术要点进行了深入探讨。接下来,我们将继续探索圆形窗体的事件处理和功能实现。
5. 圆形窗体的事件处理与功能实现
在上一章中,我们已经深入探讨了创建无边框无标题栏的圆形窗体的方法,并讨论了如何实现窗体的透明效果。在本章中,我们将把注意力转向圆形窗体的事件处理机制以及如何增强其功能,以提供更丰富的用户体验。
5.1 圆形窗体的事件处理机制
5.1.1 事件处理与窗体行为的关联
在Delphi中,事件处理是窗体编程的核心部分,它允许我们为窗体或控件的特定动作指定响应。对于圆形窗体,事件处理机制尤为重要,因为它直接影响到窗体的行为和用户体验。
圆形窗体的一个关键区别在于其形状可能导致用户操作行为上的变化。例如,鼠标事件在圆边上的响应可能与矩形窗体有所不同。理解并实现适当的事件处理可以帮助我们克服这些差异,确保用户操作的流畅性和直观性。
在Delphi中,窗体的事件处理通常通过覆盖特定的事件处理方法来实现,如 OnClick , OnMouseDown , OnMouseMove , OnMouseUp 等。为了处理圆形窗体的事件,我们可能需要自定义一些事件处理逻辑,以适应圆形的几何特性。
例如,我们可能需要计算鼠标指针与窗体中心的距离,并判断其是否在圆内,以此决定是否响应某些事件。代码示例如下:
procedure TForm1.FormMouseDown(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
begin
if PointInCircle(ClientOrigin.X + X, ClientOrigin.Y + Y, Width div 2) then
// 处理圆内部的点击事件
else
// 处理圆外部的点击事件(如果有)
end;
function PointInCircle(OriginX, OriginY, Radius: Integer; CheckX, CheckY: Integer): Boolean;
var
DX, DY: Integer;
begin
DX := CheckX - OriginX;
DY := CheckY - OriginY;
Result := (DX * DX + DY * DY <= Radius * Radius);
end;
在此代码段中, FormMouseDown 事件处理方法检查鼠标点击的位置是否在圆形窗体内部。通过调用 PointInCircle 函数来计算鼠标点击点是否在以窗体中心为圆心,窗体宽度的一半为半径的圆内。
5.1.2 圆形窗体特有事件的处理方法
圆形窗体可能会触发一些特殊的事件,比如用户可能尝试在窗体边缘拖动窗体。为了处理这些情况,我们需要编写特定的逻辑来识别用户的意图,并作出相应的响应。
在实现拖动效果时,我们可以捕捉到鼠标按下事件,并在鼠标移动时更新窗体的位置。这要求我们在事件处理方法中跟踪鼠标的位置,并在适当的条件下改变窗体的 Left 和 Top 属性。
例如:
procedure TForm1.FormMouseDown(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
begin
if Button = mbLeft then
begin
FMouseOffset := Point(X, Y);
FIsDragging := True;
end;
end;
procedure TForm1.FormMouseMove(Sender: TObject; Shift: TShiftState; X, Y: Integer);
begin
if FIsDragging then
begin
Self.Left := Self.Left + (X - FMouseOffset.X);
*** := *** + (Y - FMouseOffset.Y);
FMouseOffset := Point(X, Y);
end;
end;
procedure TForm1.FormMouseUp(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
begin
FIsDragging := False;
end;
在此代码段中,当用户按下鼠标左键时,我们记录下当前鼠标位置,并将 FIsDragging 标志设置为 True 。在鼠标移动时,如果 FIsDragging 为 True ,则更新窗体位置,并重新记录鼠标位置。当用户释放鼠标按钮时,将 FIsDragging 设置为 False ,停止拖动操作。
5.2 圆形窗体的扩展功能实现
5.2.1 实现拖动效果与自定义操作
圆形窗体的拖动效果是通过自定义鼠标事件处理实现的,如前文所述。除了基本的拖动功能外,我们还可以实现一些特殊的自定义操作,以增加窗体的灵活性和实用性。
例如,我们可以通过按住特定的修饰键(如Ctrl或Alt)来允许用户在拖动时调整窗体的大小。这可以通过监听鼠标事件并在适当条件下改变窗体的 Width 和 Height 属性来实现。
5.2.2 圆形窗体的动画效果与交互增强
为了提高用户界面的吸引力,我们可以为圆形窗体添加动画效果。这可以通过在窗体上创建和修改控件的位置和属性来实现。例如,我们可以使某个控件在圆形窗体内部沿着圆形路径移动,创造出有趣的视觉效果。
动画的实现涉及到定时器(TTimer)的使用,我们可以在定时器事件中更新控件的位置来制造动画效果。实现代码如下:
procedure TForm1.Timer1Timer(Sender: TObject);
var
Angle: Double;
begin
Angle := (Timer1.Interval / 1000) * 2 * Pi;
Control1.Left := Width div 2 + Round(Cos(Angle) * (Width div 2 - Control1.Width div 2));
*** := Height div 2 + Round(Sin(Angle) * (Height div 2 - Control1.Height div 2));
end;
在此代码段中, Timer1Timer 事件会在定时器触发时被调用。计算新的 Left 和 Top 值,使控件 Control1 沿着圆形路径移动。
章节小结
在本章中,我们探讨了圆形窗体的事件处理机制及其重要性,并通过代码示例深入分析了如何处理圆形窗体特有的事件。我们还讨论了如何实现圆形窗体的扩展功能,包括拖动效果、自定义操作以及动画效果。通过这些高级功能,圆形窗体的实用性和互动性得到了极大的增强,为最终用户提供更加直观和吸引人的体验。
在下一章中,我们将进一步深入Delphi编程,提供实际圆形窗体的实现代码示例,并探讨它在实际项目中的应用案例。通过这些实际案例,我们可以更全面地理解圆形窗体编程的实践意义和实际效益。
6. 圆形窗体的Delphi实现代码示例
在Delphi中,实现一个圆形窗体需要对窗体的 CreateParams 方法进行重写,以便创建一个圆形的窗口区域,并且还需重写 OnPaint 事件处理程序来进行绘制。以下是一个具体的实现代码示例,以及它的结构和功能解析。
6.1 示例代码片段解读
6.1.1 关键代码的结构与功能解析
在Delphi中创建圆形窗体的关键步骤包括:
- 重写窗体的
CreateParams方法 : 这一步骤用来设置创建窗体时的样式参数,使得窗体边界呈现为圆形。
procedure TForm1.CreateParams(var Params: TCreateParams);
begin
inherited CreateParams(Params);
// 设置窗体为无边框样式
Params.Style := Params.Style and not WS_BORDER;
// 设置扩展样式,以创建圆形窗口
Params.ExStyle := Params.ExStyle or WS_EX_LAYERED or WS_EX_TOPMOST or WS_EX_TOOLWINDOW;
end;
- 重写
OnPaint事件处理程序 : 由于我们不能使用窗体的默认边框来维持圆形,我们需要通过OnPaint事件来手动绘制一个圆形窗体的外观。
procedure TForm1.WMPaint(var Message: TWMPaint);
var
ps: TPaintStruct;
begin
BeginPaint(Handle, ps);
try
// 使用圆形路径创建区域
with ps.rcPaint do
begin
ExcludeClipRect(Canvas.Handle, Left, Top, Right, Bottom);
Canvas.Brush.Style := bsClear;
Canvas.Pen.Style := psDot;
Canvas.Pen.Mode := pmNot;
Canvas.Pen.Color := clWhite;
// 绘制圆形
Canvas.Ellipse(Left, Top, Right, Bottom);
end;
finally
EndPaint(Handle, ps);
end;
end;
6.1.2 示例代码中的优化与扩展点
- 优化 :避免在
OnPaint中处理复杂的逻辑,确保绘制效率。 - 扩展点 :通过自定义消息响应机制,可以实现更丰富的用户交互,比如响应鼠标事件来控制窗体的拖动等。
6.2 圆形窗体在实际项目中的应用案例
6.2.1 圆形窗体在软件界面中的应用
圆形窗体在软件界面中可以提供与众不同的用户体验,例如在游戏、媒体播放器或某些特定的工具应用中,圆形窗体作为临时窗口或通知栏可以提供更加直观和吸引人的视觉效果。
6.2.2 圆形窗体的优势与用户反馈分析
圆形窗体的优势在于能够突出显示特定的内容,同时避免过多的用户界面元素干扰用户的注意力。在某些情况下,用户反馈表明圆形窗体能够带来更为友好的交互体验,尤其是在强调个性化和创造性的应用中。
总结上述内容,圆形窗体的Delphi实现涉及到窗体样式的调整、绘制逻辑的设计以及窗体行为的特定处理。实现过程中,开发者需要对Delphi窗体类的使用有深入的理解,特别是关于窗体样式的设置和事件处理机制。在实际项目中应用圆形窗体,可以为用户提供独特的视觉效果和交互体验,进而增强软件产品的竞争力。
简介:本篇文章将介绍在Delphi编程环境中如何自定义绘制并实现一个圆形窗体。Delphi使用Object Pascal语言,基于组件的可视化开发工具,窗体通常为矩形,但通过自定义绘制技术可以创建非矩形窗体。我们将讲解通过覆盖OnPaint事件、禁用边框和标题栏以及处理透明效果等技术点来实现圆形窗体的方法。同时,提供示例代码和扩展应用的介绍。


1679

被折叠的 条评论
为什么被折叠?



