简介: DrawIcon
是Windows API中的一个基础图形函数,用于在窗口或设备上下文中绘制图标。本文将全面解析 DrawIcon
函数,包括其参数、返回值、使用场景以及扩展相关函数。通过实际代码示例,将帮助理解如何在Windows应用程序中使用 DrawIcon
函数来设计用户界面。
1. DrawIcon函数的用途与基本原理
DrawIcon函数的用途
在Windows编程中, DrawIcon
函数主要用来在指定的设备上下文中绘制图标。这个函数是图形用户界面(GUI)设计中的基础工具之一,广泛应用于窗口界面元素的绘制,如按钮图标、窗口图标以及工具栏图标等。通过DrawIcon函数,开发者可以轻松地将图标资源展示在应用程序的界面上,增强用户交互体验。
DrawIcon函数的基本原理
DrawIcon
函数通过接收设备上下文(HDC)、图标句柄(HICON)、以及坐标参数(x, y)来在屏幕上渲染图标。它将图标绘制在由设备上下文指定的画布上,该画布可以是窗口、控件或者内存中的图形对象。 x
和 y
坐标定义了图标在画布上的位置。通过这个函数,开发者能够控制图标的大小和位置,实现精确的图标绘制。
DrawIcon函数的应用场景
在实际的编程实践中, DrawIcon
函数常用于:
- 窗口类的
WM_PAINT
消息处理过程中,当需要在客户区域绘制图标时。 - 当需要在对话框中插入图标,并且需要对图标的外观和位置进行精细控制时。
- 在滚动条、工具栏、状态栏等控件上绘制图标,以提供视觉反馈。
接下来,我们将深入探讨 DrawIcon
函数的参数细节和使用方法,揭示其在不同编程场景中的应用与优化策略。
2. DrawIcon函数的参数解析
2.1 HDC参数的作用与使用方法
2.1.1 设备上下文HDC概述
设备上下文(HDC,Handle to Device Context)是一个重要的概念,在Windows编程中,它是用于绘图的一个环境。它包含了绘图时所需的所有信息,比如图形的颜色、字体、坐标系统等。HDC能够将设备无关的GDI(图形设备接口)函数调用转换为设备特定的命令,确保在不同设备上都能得到正确的输出。
在使用DrawIcon函数时,HDC参数是必须的,因为它指定了绘图的目标位置。要使用HDC,你需要首先获取一个与特定设备或窗口相关联的HDC,然后将该HDC传递给DrawIcon函数。
2.1.2 如何获取和传递HDC参数
获取HDC的方法主要有两种:一种是获取与一个窗口句柄相关的HDC,另一种是创建一个内存设备上下文(Memory DC)。以下是一些常用的函数及其实现步骤:
// 获取窗口设备上下文
HDC hdc = GetDC(windowHandle);
// 创建内存设备上下文
HDC hdcMemory = CreateCompatibleDC(hdc);
// 绘图到内存设备上下文
HGDIOBJ hOldBitmap = SelectObject(hdcMemory, hBitmap);
// 使用DrawIcon绘制到HDC
BOOL result = DrawIcon(hdc, x, y, hIcon);
// 清理资源
SelectObject(hdcMemory, hOldBitmap);
DeleteDC(hdcMemory);
ReleaseDC(windowHandle, hdc);
在这段代码中, GetDC
用于获取与窗口句柄 windowHandle
相关的HDC。如果需要在内存中进行绘图操作,那么创建一个内存DC是必要的步骤,这里使用了 CreateCompatibleDC
来创建与指定HDC兼容的内存DC, SelectObject
用于将位图选入内存DC中进行绘制。
2.2 坐标参数x和y的意义
2.2.1 坐标系统在绘图中的作用
在2D图形编程中,坐标系统定义了图形元素的位置。它将画布划分为一个由坐标点组成的网格,每个点都有唯一的x和y值。x值代表水平位置,y值代表垂直位置。在Windows编程中,坐标系统的原点(0, 0)位于左上角,向右是x坐标的正方向,向下是y坐标的正方向。
2.2.2 x和y值的确定及应用场景
在使用DrawIcon函数时,x和y参数用于指定图标的左上角坐标。这就意味着,x值决定了图标在水平方向上的起始位置,而y值则决定了图标在垂直方向上的起始位置。例如,当x值为100,y值为150时,图标的左上角将出现在屏幕坐标(100, 150)的位置。
在应用程序中确定x和y值时,需要根据实际需求进行调整。例如,在一个窗口中居中显示图标,则需要计算窗口的宽度和高度的一半,然后将图标定位在这些值上。
2.3 HICON参数的细节解析
2.3.1 图标资源的创建与引用
HICON是“Handle to an Icon”的缩写,它是一个句柄,指向一个图标资源。在Windows编程中,图标资源是一个常见的元素,它可以被加载到内存中,以便在应用程序的不同部分中重复使用。
创建图标资源通常有几种方法,包括使用资源编辑器创建,或者在代码中动态地使用 CreateIcon
、 LoadIcon
等函数创建图标。一个图标可以包含多个尺寸和颜色深度,以便在不同的显示设置下都能提供最佳的显示效果。
// 使用LoadIcon函数加载预定义的图标资源
HICON hIcon = LoadIcon(NULL, IDI_APPLICATION);
// 使用CreateIcon函数创建自定义图标
ICONINFO ii = { sizeof(ii) };
ii.fIcon = TRUE; // 制作图标
ii.xHotspot = 0;
ii.yHotspot = 0;
ii.hbmMask = CreateCompatibleBitmap(hdc, width, height);
ii.hbmColor = CreateCompatibleBitmap(hdc, width, height);
HICON hMyIcon = CreateIconIndirect(&ii);
在上面的代码中, LoadIcon
用于加载一个标准的图标,而 CreateIconIndirect
用于根据给定的 ICONINFO
结构创建一个新图标。
2.3.2 HICON参数的传递与变换处理
在传递HICON参数给DrawIcon函数时,需要确保图标已经被正确加载到内存中。传递图标时,可以使用 CopyIcon
函数复制图标资源,或者通过变量直接传递已存在的图标句柄。
// 将图标传递给DrawIcon函数
DrawIcon(hdc, x, y, hIcon);
如果需要对图标进行变换处理(如旋转或缩放),则需要使用其他GDI函数如 SetStretchBltMode
、 SetBrushOrgEx
、 SetMapMode
等来设置绘图模式。这些变换通常用于图标在屏幕上显示时的视觉效果调整。
表格和流程图展示
下面的表格展示了HDC、x/y和HICON在实际编程中的使用场景及注意事项:
参数类型 | 使用场景 | 注意事项 |
---|---|---|
HDC | 在绘图前获取,必须与窗口或设备关联 | 确保使用后释放资源,避免内存泄漏 |
x, y | 在DrawIcon中指定图标位置 | 需要根据窗口大小调整以实现居中 |
HICON | 用于引用已存在的图标或创建新图标 | 图标资源在程序关闭时应适当释放 |
接下来是展示如何正确使用DrawIcon函数的流程图:
graph TD
A[开始] --> B[获取HDC]
B --> C[确定x和y坐标]
C --> D[创建或加载HICON]
D --> E[调用DrawIcon]
E --> F[检查返回值]
F --> |成功| G[绘图完成]
F --> |失败| H[错误处理]
H --> I[结束]
G --> I
流程图展示了DrawIcon函数使用的顺序逻辑,强调了在绘图前需要获取HDC,定位图标位置,以及正确处理返回值。
3. DrawIcon函数的返回值及其实现效果
3.1 返回值的含义及其在编程中的意义
3.1.1 成功与失败的返回值判断
DrawIcon
函数是GDI(图形设备接口)的一个函数,用于在指定的设备上下文中绘制一个图标。当调用该函数时,它会返回一个布尔值,指示操作是成功还是失败。在大多数Windows API函数中,返回值为非零(通常是 TRUE
或 1
)表示成功,而返回值为零( FALSE
或 0
)表示失败。具体到 DrawIcon
函数,根据Microsoft官方文档,函数没有返回值,实际上 DrawIcon
会直接操作设备上下文(DC),并不会返回任何值。
在编程实践中,开发者通常不会对 DrawIcon
函数的返回值进行判断,因为该函数没有返回值。但是,开发者可以利用返回值这个机制来处理其他类似的API函数,或者检查绘图操作的结果。当使用 DrawIcon
函数的变体 DrawIconEx
时,情况会有所不同。 DrawIconEx
函数返回一个布尔值,表示操作是否成功。
3.1.2 返回值与程序逻辑的关联
在编写涉及图形绘制的程序时,正确处理返回值对于维持程序的稳定性和可靠性是非常重要的。尽管 DrawIcon
本身没有返回值,但是对其他有返回值的API函数的返回值进行检查,可以允许程序在绘图操作失败时采取适当的错误处理措施。例如,如果 DrawIconEx
的调用失败,可能是因为传递了无效的参数,或者系统资源不足,这时程序可以输出错误信息、尝试恢复或通知用户。
错误处理可以涉及简单的通知消息,也可以进行更复杂的资源清理操作,例如释放已经分配的资源、恢复到一致的状态等。错误处理的具体实施取决于程序的复杂程度和对稳定性的需求。无论如何,通过适当的错误处理,开发者可以确保程序在遇到问题时不会无故崩溃,而是能够优雅地处理异常情况。
3.2 DrawIcon函数绘制效果的深入分析
3.2.1 绘图效果的影响因素
DrawIcon
函数的绘制效果受到多种因素的影响,包括设备上下文(DC)的类型、图标资源(HICON)的属性、以及其他相关的绘图参数。
-
设备上下文(DC)的类型 :DC是描述一个显示设备表面的结构,它定义了绘图的环境。根据DC的不同类型,比如屏幕DC、内存DC或者打印DC,绘图的表现会有所差异。例如,在屏幕DC上绘制的效果会直接显示在屏幕上,而在内存DC上绘制的效果可以作为位图对象被进一步处理。
-
图标资源(HICON)的属性 :图标资源本身包含了图标的数据,如大小、颜色深度、图像数据等。不同的图标资源在相同的DC中绘制出来效果也不尽相同。图标的设计和属性直接影响到最终的显示效果。
-
其他相关绘图参数 :包括图标的位置坐标(x和y)、图标是否透明、是否允许图标和背景混合等。这些参数通过
DrawIcon
函数的参数被设置,对最终绘制的图标外观有直接影响。
3.2.2 实际绘图结果与预期的对比
在实际应用中,开发者可能会遇到绘制出来的图标与预期效果有差异的情况。为了解决这种问题,开发者可以通过以下步骤进行调试:
-
验证输入参数 :仔细检查传递给
DrawIcon
函数的所有参数,确保它们符合预期和文档描述。 -
调整图标资源 :如果使用的是外部资源,需要确认图标文件本身没有损坏,并且其属性与设计一致。
-
控制绘图环境 :通过设置DC属性,比如背景色,来观察图标如何与背景相互作用。
-
测试不同的DC :为了确定绘图效果是否受DC类型的影响,可以尝试在不同类型的DC中绘制图标。
-
查看文档和示例代码 :查阅官方文档以及寻找现有的使用示例代码,可以帮助理解如何正确使用
DrawIcon
以及其参数。
通过这些步骤,开发者通常能够发现并解决绘图效果与预期不符的问题,从而让图标在用户界面上表现出更好的视觉效果和用户体验。下面是一个简单的示例代码,演示如何使用 DrawIcon
函数:
// 示例代码,演示如何使用DrawIcon函数
HICON hIcon = LoadIcon(NULL, IDI_APPLICATION); // 加载默认的图标资源
HDC hdc = GetDC(hWnd); // 获取窗口的设备上下文
DrawIcon(hdc, x, y, hIcon); // 绘制图标到设备上下文
ReleaseDC(hWnd, hdc); // 释放设备上下文句柄
DestroyIcon(hIcon); // 销毁图标资源
在使用 DrawIcon
函数时,开发者需要确保所有操作符合GDI资源管理和绘图规则,以保证图形输出的正确性和效率。
4. DrawIcon在Windows编程中的应用示例
4.1 DrawIcon函数在窗口绘制中的使用
4.1.1 窗口绘制流程介绍
在Windows编程中,使用 DrawIcon
函数绘制图标到窗口是一种常见的操作。窗口绘制流程可以分为几个步骤,首先是窗口类的注册,然后是创建窗口并显示,接着进行消息循环处理,在消息循环中会处理绘制消息如 WM_PAINT
。 DrawIcon
函数通常在 WM_PAINT
消息处理函数中被调用,用于在窗口中绘制图标。
绘制流程的伪代码大致如下:
// 伪代码示例:窗口绘制流程
RegisterClass(&wndClass); // 注册窗口类
CreateWindow(...); // 创建窗口
ShowWindow(hwnd, nCmdShow); // 显示窗口
UpdateWindow(hwnd); // 更新窗口
// 消息循环
MSG msg;
while(GetMessage(&msg, NULL, 0, 0)) {
TranslateMessage(&msg);
DispatchMessage(&msg);
}
// WM_PAINT消息处理
case WM_PAINT: {
PAINTSTRUCT ps;
HDC hdc = BeginPaint(hwnd, &ps);
DrawIcon(hdc, x, y, hIcon); // 在窗口绘制图标
EndPaint(hwnd, &ps);
}
在窗口的 WM_PAINT
消息处理中,通过 BeginPaint
函数开始绘制,得到设备上下文(HDC),然后调用 DrawIcon
函数绘制图标,最后使用 EndPaint
结束绘制。
4.1.2 DrawIcon函数与其他绘制函数的结合使用
在进行窗口绘制时, DrawIcon
函数通常与其他绘制函数结合起来使用,以便实现更加丰富的视觉效果。例如,可以先用 Rectangle
函数绘制一个矩形框,然后在该矩形框内部使用 DrawIcon
来绘制图标。这样,图标的视觉效果会被框定在一个特定区域内。
一个结合使用 Rectangle
和 DrawIcon
的示例代码如下:
// 示例代码:DrawIcon函数与其他绘制函数结合使用
case WM_PAINT: {
PAINTSTRUCT ps;
HDC hdc = BeginPaint(hwnd, &ps);
// 绘制矩形框
Rectangle(hdc, xRect, yRect, xRect + widthRect, yRect + heightRect);
// 在矩形框内绘制图标
DrawIcon(hdc, xIcon, yIcon, hIcon);
EndPaint(hwnd, &ps);
}
通过合理地结合使用 DrawIcon
和其他绘制函数,可以灵活地控制图标在窗口中的位置和外观,从而满足复杂的用户界面设计需求。
4.2 DrawIcon函数在用户界面美化中的应用
4.2.1 图标在用户界面设计中的重要性
图标是用户界面设计中不可或缺的元素之一,它不仅能够美化界面,还能提供直观的信息给用户。在Windows编程中,使用 DrawIcon
函数将图标绘制到指定位置,可以增强用户对应用程序功能的认知,并提升用户的交互体验。
图标通常用在工具栏按钮、状态栏提示、对话框以及各种提示消息中。当一个图标正确地放置和设计时,用户可以通过视觉感知迅速理解界面所要表达的功能或状态,从而提高效率和满意度。
4.2.2 使用DrawIcon优化界面视觉效果
利用 DrawIcon
函数,开发者可以将图标精确地放置到窗口的任何位置,为用户提供清晰、一致的视觉体验。通过设置不同的图标和大小,以及使用透明和半透明效果,可以进一步增强界面的美感和功能性。
下面是一个使用 DrawIcon
来优化对话框中图标视觉效果的示例代码:
// 示例代码:使用DrawIcon优化对话框中图标视觉效果
case WM_INITDIALOG: {
// 在对话框初始化时设置图标
HWND hwndIcon = GetDlgItem(hwndDialog, IDC_MYICON);
HDC hdc = GetDC(hwndIcon);
DrawIcon(hdc, 10, 10, hIconMyApp); // 将图标绘制到对话框控件中
ReleaseDC(hwndIcon, hdc);
}
在这段代码中, IDC_MYICON
是在对话框模板中定义的图标控件ID。 DrawIcon
函数在对话框初始化时调用,将应用程序的图标 hIconMyApp
绘制到指定控件上,从而优化了界面的视觉效果。
4.3 DrawIcon函数在图形处理软件中的角色
4.3.1 图形处理软件的需求分析
图形处理软件通常需要在画布上显示各种图形元素,包括图像、图标等。在这些软件中,开发者需要提供灵活的图形绘制功能,以满足用户的编辑和处理需求。 DrawIcon
函数因其简便性和高效性,成为实现这些功能的重要工具。
在图形处理软件中,用户可能需要插入图标到正在编辑的图像中,或者使用图标作为图层的一部分。 DrawIcon
函数可以快速实现这些操作,而且还可以和其他图形绘制API一起使用,为用户带来更加丰富的编辑体验。
4.3.2 DrawIcon函数在软件中的实际应用案例
在实际的图形处理软件开发中, DrawIcon
函数可以被用来在图像上标记重要的位置,或者在用户界面上提供直观的工具和功能提示。例如,在一个图像编辑器中,当用户想要标注图像中某个特定的区域时,可以使用 DrawIcon
在鼠标点击位置绘制一个小图标。
下面是一个在图像编辑器中使用 DrawIcon
标记特定区域的示例代码:
// 示例代码:在图像编辑器中使用DrawIcon标记特定区域
case WM_LBUTTONDOWN: {
// 获取鼠标点击位置坐标
POINT pt;
GetCursorPos(&pt);
// 获取对应图像坐标的绘制位置
int x = pt.x - IMAGE_OFFSET_X;
int y = pt.y - IMAGE_OFFSET_Y;
// 在图像上绘制标记图标
HDC hdcImage = GetDC(hwndImage); // 获取图像控件的HDC
DrawIcon(hdcImage, x, y, hIconMarker); // 在点击位置绘制标记
ReleaseDC(hwndImage, hdcImage);
}
在这段代码中, WM_LBUTTONDOWN
是一个鼠标左键按下消息,当用户在图像编辑器的图像控件上点击时,程序会捕获鼠标位置,并将其转换为图像坐标,然后在该位置使用 DrawIcon
绘制一个标记图标。
通过这些实际的应用案例,可以看到 DrawIcon
函数在Windows编程中的多样性和实用性。从基础的窗口图标绘制到复杂的图形处理软件开发, DrawIcon
都扮演着重要的角色。
5. DrawIcon相关知识点及扩展函数的深入探讨
在前几章中,我们已经了解到DrawIcon函数的基本原理、参数解析、返回值以及在Windows编程中的应用实例。为了进一步加强我们对绘图函数的理解,本章将深入探讨与DrawIcon相关的一些高级知识点以及扩展函数的使用,包括设备上下文(DC)与图标资源(HICON)的关系,LoadIcon和SendMessage/PostMessage函数的解析,以及WM_PAINT与WM_SETICON消息的应用。最后,我们将介绍DrawIconEx函数和内存设备上下文(Memory DC)的高级应用。
5.1 设备上下文(DC)与图标资源(HICON)的关联
5.1.1 设备上下文DC的创建和配置
设备上下文(Device Context, DC)是GDI(图形设备接口)中用于管理窗口图形输出的核心对象。它包含了绘图操作所必需的所有信息,包括绘图目标的位置、颜色、字体等。
HDC hdc = GetDC(hWnd); // 获取指定窗口的设备上下文句柄
上述代码展示了如何获取一个窗口的设备上下文句柄。 GetDC
函数会返回一个指向设备上下文的指针,该指针可用于后续的绘图操作。
5.1.2 HICON的创建与资源管理
HICON是一个句柄,指向图标资源。它在资源文件中定义,并通过资源标识符(IDI_XXX)引用。
HICON hIcon = LoadIcon(NULL, IDI_APPLICATION); // 加载一个预定义的图标
这里使用 LoadIcon
函数加载了一个标准的应用程序图标。创建HICON之后,必须确保在不再需要时进行适当的资源释放,以防止内存泄漏。
DestroyIcon(hIcon); // 销毁图标资源
ReleaseDC(hWnd, hdc); // 释放设备上下文
DestroyIcon
用于销毁图标资源,而 ReleaseDC
用于释放设备上下文句柄。
5.2 LoadIcon、SendMessage/PostMessage函数解析
5.2.1 LoadIcon的使用及其在资源加载中的作用
LoadIcon
函数用于加载一个图标资源,以便在应用程序中使用。
HICON LoadIcon(HINSTANCE hInstance, LPCSTR lpszIcon);
该函数有两个参数,第一个为模块句柄,第二个为图标名称或标识符。加载图标后,可以将其与窗口关联或在其他GDI操作中使用。
5.2.2 SendMessage与PostMessage的对比与选择
SendMessage
和 PostMessage
函数都是用于向窗口发送消息,但两者在消息处理机制上有显著不同。
-
SendMessage
:函数会直接将消息发送到指定窗口的队列,等待窗口处理该消息后才返回。 -
PostMessage
:将消息发送到队列之后立即返回,不会等待消息处理。
SendMessage(hWnd, WM_SETICON, ICON_BIG, (LPARAM)hIcon);
PostMessage(hWnd, WM_PAINT, 0, 0);
在实际编程中,选择 SendMessage
还是 PostMessage
取决于是否需要同步或异步处理消息。
5.3 WM_PAINT与WM_SETICON消息的理解和应用
5.3.1 WM_PAINT消息的处理流程
WM_PAINT
消息是通知应用程序必须重绘其内容。这通常在窗口被部分或全部最小化后再恢复时发生。
case WM_PAINT:
PAINTSTRUCT ps;
HDC hdc = BeginPaint(hWnd, &ps);
// 在此处进行绘图操作
EndPaint(hWnd, &ps);
break;
处理 WM_PAINT
消息通常涉及调用 BeginPaint
和 EndPaint
函数。在这两个函数之间的代码块内进行实际的绘图操作。
5.3.2 WM_SETICON消息的作用及其与DrawIcon的交互
WM_SETICON
消息用于设置窗口的图标。它常用于响应用户界面的定制需求。
case WM_SETICON:
if (wParam == ICON_BIG)
hIconBig = (HICON)lParam;
else if (wParam == ICON_SMALL)
hIconSmall = (HICON)lParam;
InvalidateRect(hWnd, NULL, TRUE); // 使窗口区域无效,强制重绘
break;
窗口通过接收 WM_SETICON
消息来更换大图或小图图标。 InvalidateRect
函数用于使指定的窗口区域无效,从而导致重绘,这样新设置的图标才会显示在窗口上。
5.4 DrawIconEx函数与内存设备上下文(Memory DC)的高级应用
5.4.1 DrawIconEx函数的特性和优势
DrawIconEx
函数提供了对 DrawIcon
函数的增强功能,它允许更精细地控制图标的位置和拉伸方式。
BOOL DrawIconEx(
HDC hdc, // 设备上下文句柄
int x, // 图标的左上角x坐标
int y, // 图标的左上角y坐标
HICON hIcon, // 图标句柄
int cx, // 图标的宽度
int cy, // 图标的高度
UINT uFlags, // 描绘选项
HBRUSH hbrFore // 可选的前景色画刷
);
通过使用 DrawIconEx
,开发者可以更细致地指定图标的尺寸、位置和样式,甚至可以为图标的背景指定颜色。
5.4.2 内存设备上下文(Memory DC)在图形绘制中的应用
内存设备上下文(Memory DC)是一种特殊类型的设备上下文,它在内存中创建图形表面,而不是在屏幕或其他输出设备上。
HDC hdcMemory = CreateCompatibleDC(hdc); // 创建内存DC
BITMAPINFO bmi;
ZeroMemory(&bmi, sizeof(BITMAPINFO));
bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
bmi.bmiHeader.biWidth = nWidth;
bmi.bmiHeader.biHeight = -nHeight; // 翻转y坐标,因为通常以原点在左上角开始
bmi.bmiHeader.biPlanes = 1;
bmi.bmiHeader.biBitCount = 32;
bmi.bmiHeader.biCompression = BI_RGB;
HBITMAP hbm = CreateDIBSection(hdc, &bmi, DIB_RGB_COLORS, (void**)&pBits, NULL, 0);
SelectObject(hdcMemory, hbm); // 选择位图到内存DC
// 在此处使用内存DC绘制图像...
上述代码创建了一个内存DC和一个兼容的位图。在内存DC上进行的任何绘图操作都不会直接显示到屏幕上,从而可以灵活地处理图形数据。一旦绘图完成,可以将内存中的位图直接显示到屏幕或输出到文件。
内存DC常用于复杂图形操作,如双缓冲、图像处理和图形合成。借助于 DrawIconEx
和内存DC,开发者可以在不干扰用户界面的情况下,高效地进行图形绘制和处理。
简介: DrawIcon
是Windows API中的一个基础图形函数,用于在窗口或设备上下文中绘制图标。本文将全面解析 DrawIcon
函数,包括其参数、返回值、使用场景以及扩展相关函数。通过实际代码示例,将帮助理解如何在Windows应用程序中使用 DrawIcon
函数来设计用户界面。