navigation button怎么ios 给button设置边框框

1771人阅读
Custom Window Frame Using DWM
Custom Window Frame Using DWM
Custom Window Frame Using DWM
This topic demonstrates how to use the Windows Vista Desktop Window Manager (DWM) APIs to create custom window frames for your application.
这篇文章揭示如何使用windows vista desktop window manager(DWM) APIs为你的应用程序创建自定义的窗口边框.
简介扩展客户区边框去掉系统标准边框绘制扩展的窗口边框在自定义边框中启用点击测试附录A:窗口程序的例子附录B:绘制标题栏附录C:点击测试函数相关主题
Introduction
In Windows Vista, the appearance of the non-client areas of application windows (the title bar, icon, window border, and caption buttons) is controlled by the DWM. Using the DWM APIs, you can manipulate the way the DWM handles the rendering of a window's
在vista系统中,应用程序的非客户区域(标题栏,图标,边框,标题栏按钮)的外观都是DWM控制的.使用DWM的API,你可以控制DWN渲染窗口的边框.
One feature of the DWM APIs is the ability to extend the application frame into the client area. This enables you to integrate client user interface (UI), such as a toolbar, into the frame, giving the UI controls a more prominent place in the application
UI. For example, Windows Internet Explorer 7 on Windows Vista integrates the navigation bar into the window frame by extending the top of the frame.
DWM AP的一个特性是允许扩展应用程序边框到客户端区域。这使你可以集成客户端的用户界面,比如工具栏,到外框中,使某些控件显示在系统界面的最突出的位置。比如,vista上的IE7就通过扩展上边框在外框集成了导航条。
The ability to extend the window frame also enables you to create custom frames while maintaining the window's look and feel. For example, Microsoft Office Word 2007 draws the Office Button and the Quick Access Toolbar inside the custom frame while providing
the standard Minimize, Maximize, and Close caption buttons.
扩展窗口边框的能力同样可以使你可以创建自定义的边框来维护你的整个窗口的外观和感觉统一。比如 Microsoft Office Word 2007画Office按钮和快速访问工具栏在自定义窗口中,并使用了标准的最大化,最小化,关闭按钮。
To create custom frames using the DWM APIs, caption button hit testing, window resizing and moving, and painting on the extended frame. These include extending the frame into the client area, providing custom client area measurements, and hit testing for
the custom frame area.
为了创建自定义的边框,包括了需要标题栏点击测试,窗口大小调整和移动,绘制扩展边框等任务。还包括了扩展边框到客户端区域,提供自己计算的客户端区域的大小,和自己的边框区域点击测试。
Extending the Client Frame
The functionality to extend the frame into the client area is exposed by the
function. To extend the frame, you pass the target window handle along with the margin inset values to
DwmExtendFrameIntoClientArea. The margin inset values determine how much to extend the frame for the four sides of a window (top, bottom, left, and right).
The following code demonstrates the DwmExtendFrameIntoClientArea call used to extend the frame.
使用 扩展窗口边框。传一个窗口的句柄和边的宽度集合给。margin集合决定了扩展的四个边框的宽度。
// Handle window activation.
if (message == WM_ACTIVATE)
// Extend the frame into the client area.
margins.cxLeftWidth = LEFTEXTENDWIDTH;
margins.cxRightWidth = RIGHTEXTENDWIDTH;
margins.cyBottomHeight = BOTTOMEXTENDWIDTH; //20
margins.cyTopHeight = TOPEXTENDWIDTH;
hr = DwmExtendFrameIntoClientArea(hWnd, &margins);
if (!SUCCEEDED(hr))
// Handle error.
fCallDWP =
Note that the frame extension is done within the
message rather than . This ensures that frame extension is handled properly when the window is at its default size and when it is maximized.
请注意,边框扩展是在 的时候完成,而不是
。这样何以确保窗口在缺省大小和最大都能正确处理窗口扩展。
The following image shows a standard window frame (on the left) and the same window frame with an extended frame (on the right). The frame is extended using the previous code sample and the default Visual Studio
() background (COLOR_WINDOW +1).
下边的图片显示了相同的边框,左边是标准窗口和右边含窗口扩展,使用缺省窗口背景COLOR_WINDOW +1。
Note that the only difference between the two windows is the missing thin black line border of the client region from the window on the right. The reason for the missing black border is that it is incorporated into the extended frame, but the rest of the
client area is not. For the extended frames to be visible, the regions underlying each of the extended frame's sides must have pixel data that has an alpha value of 0. The black border around the client region has pixel data in which all color values (red,
green, blue, and alpha) are set to 0. The rest of the background does not have the alpha value set to 0, so the rest of the extended frame is not visible.
注意,上图只能看出右边少了黑色的客户区域的边框。原因是原来的黑色的区域边框,已经成为外框扩展的一部分了,但是客户区域没有。(vcommon注:换言之,外框变大了,客户区域没有相应变小,挡到了外框)。如果希望外框可见可见,那么盖住外框扩展部分的区域必须是alpha为0的像素数据。在黑色边框内部的区域则按平常的色彩值,比如设置为0。如果你没有把其余部分的背景色的alpha不设置为0,那么外框就是不可见得。
(vcommon注:所以自己要自己维护实际的客户区域,和原来直接GetClientRect拿到的已经不一样了)
The easiest way to ensure that the extended frames are visible is to paint the entire client region black. To accomplish this, initialize the
hbrBackground member of your WNDCLASS(EX) structure to the handle of the stock BLACK_BRUSH. The following image shows the same standard window frame (left) and extended frame (right) this time,
however, hbrBackground is set to the BLACK_BRUSH handle obtained from the
最简单的办法就是整个客户区域设置黑色。初始WNDCLASS(EX)的hbrBackground 为BLACK_BRUSH
Removing the Standard Frame
去掉标准边框
After you've extended the frame of your application and made it visible, you can remove the standard frame. Removing the standard frame enables you to control the width of each side of the frame rather than simply extending out the standard frame.
在扩展了边框并且使边框可见之后,你可以接下来去掉标准的边框。这样你就可以控制每一边框的宽度和样子。
To remove the standard window frame, you need to handle the
message, specifically when the
wParam is TRUE and the return is 0. By handling the message in this way, your application uses the entire window region as the client area, removing the standard frame.
为了实现他,你需要处理 消息,当wParam 为 TRUE 的时候,然后返回0。处理这个消息的目的是,把整个窗口作为客户区域,这样就可以去掉边框。
(vcommon注:windows 窗口的行为, 消息,当wParam 为 TRUE 的时候,直接返回0,则默认整个窗口为客户区域,否则要处理NCCALCSIZE_PARAMS的lParam)
Unfortunately, the results of handling the WM_NCCALCSIZE message are not visible until the client region needs to be resized. Until then, the initial view of the window will appear with the standard frame and extended borders. To overcome
this, you must either resize your window or perform an action that initiates a
WM_NCCALCSIZE message at window creation. This can be accomplished using the
function that enables you to move your window and resize it. The following code demonstrates a call to
SetWindowPos that forces a WM_NCCALCSIZE message to be sent using the current window rectangle attributes and the SWP_FRAMECHANGED flag.
不幸的是,只有客户区域被resize的时候WM_NCCALCSIZE 才出现,在这之前,window已经被创建,并且显示了出来。为了克服这个问题,我们必须在WM_CREATE九要先调整窗口大小。可以使用实现。如下:
// Handle window creation.
if (message == WM_CREATE)
GetWindowRect(hWnd, &rcClient);
// Inform application of the frame change.
SetWindowPos(
rcClient.left, rcClient.top,
RECTWIDTH(rcClient), RECTHEIGHT(rcClient),
SWP_FRAMECHANGED);
fCallDWP =
The following image shows the standard frame (left) and the newly extended frame without the standard frame (right).
Drawing in the Extended Frame Window
绘制扩展窗口边框
By removing the standard frame, you lose the automatic drawing of the application icon and title. To add these back to your application, you must draw them yourself. To do this, let's look at the change that has occurred to your client area.
因为移除了标准边框,你就失去了自动画系统图标和标题的功能。为了增加这个功能,你必须自己绘制。
让我们先看下客户区域发生了什么改变。
With the removal of the standard frame, your client area now consists of the entire window, extended frame and all. This even includes the region where the caption buttons are drawn. In the following side-by-side comparison, the client area for both the
standard frame and the custom extended frame is highlighted in red. The client area for the standard frame window (left) is the black region. On the extended frame window (right), the client area is the entire window.
当移除了标准边框后,你的窗口区域覆盖了整个窗口,包括扩展边框和所有的东西。这甚至包括了标题栏按钮的部分。如下的比较,客户区域被标成红色。
Because the entire window is your client area, you can simply draw what you want in the extended frame. So, to add a title to your application, you just need to draw text to the appropriate region.
The following image shows themed text drawn on the custom caption frame. The title is drawn using the
function. To view the code that paints the title, see
因为所有区域都是客户区域,你可以想怎么画就怎么画。如果加个标题,就画个字串在合时的位置。如附录B
(vcommon:为了模拟标准window的标题字体,我们不能简单的画字,必须要根据系统主题相关的字体,大小绘制标题)
Note&& When drawing in your custom frame application, be careful when placing UI controls. Since the entire window is your client region, you must adjust your UI control placement for each frame width if you do not wish them to appear on
or in the extended frame.
注意,你必须时刻注意界面控件的位置,因为整个窗口都是客户区域,防止界面出现在扩展边框上。
Enabling Hit Testing for the Custom Frame
启用点击测试
An unfortunate side effect of removing the standard frame is the loss of the default resizing and move behavior. For your application to properly emulate the standard window behavior, you will need to implement logic to handle caption button hit testing
and frame resizing/moving.
去掉标准边框的另外一个缺陷就是没有了缺省的大小调整和窗口移动行为。所以要通过点击测试去实现。
For caption button hit testing, DWM provides the
function. To properly hit test the caption buttons in custom frame scenarios, messages should first be passed to
DwmDefWindowProc for handling. DwmDefWindowProc returns TRUE if
otherwise, FALSE. If the message is not handled by
DwmDefWindowProc, your application should handle the message itself or pass the message onto
为了使标题栏的button可以响应点击测试(vcommon注:否则只会响应move和resize),可以使用DwmDefWindowProc。返回true,则我们就不需要处理了(vcommon注:点击到了标题栏按钮上)否则我们自己处理它或者默认实现。
For frame resizing and moving, your application must provide the hit testing logic and handle frame hit test messages. Frame hit test messages are sent to you via the
message, even if your application creates a custom frame without the standard frame.
为了自己处理resize和moving,点击测试的逻辑处理如下。边框发给应用程序,而不管又没有标准边框。
The following code demonstrates handling the WM_NCHITTEST message when the
DwmDefWindowProc does not handle it. To see the code of the HitTestNCA function, see
附录C演示了如何处理消息:
// Handle hit testing in the NCA if not handled by DwmDefWindowProc.
if ((message == WM_NCHITTEST) && (lRet == 0))
lRet = HitTestNCA(hWnd, wParam, lParam);
if (lRet != HTNOWHERE)
fCallDWP =
Appendix A: Sample Window Procedure
The following code sample demonstrates a window procedure and its supporting worker functions used to create a custom frame application.
Main WinProc.
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
bool fCallDWP =
BOOL fDwmEnabled = FALSE;
LRESULT lRet = 0;
// Winproc worker for custom frame issues.
if (SUCCEEDED(DwmIsCompositionEnabled(&fDwmEnabled))){
lRet = CustomCaptionProc(hWnd, message, wParam, lParam, &fCallDWP);
// Winproc worker for the rest of the application.
if (fCallDWP)
lRet = AppWinProc(hWnd, message, wParam, lParam);
// Message handler for handling the custom caption messages.
LRESULT CustomCaptionProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam, bool* pfCallDWP)
LRESULT lRet = 0;
HRESULT hr = S_OK;
bool fCallDWP = // Pass on to DefWindowProc?
fCallDWP = !DwmDefWindowProc(hWnd, message, wParam, lParam, &lRet);
// Handle window creation.
if (message == WM_CREATE)
GetWindowRect(hWnd, &rcClient);
// Inform application of the frame change.
SetWindowPos(
rcClient.left, rcClient.top,
RECTWIDTH(rcClient), RECTHEIGHT(rcClient),
SWP_FRAMECHANGED);
fCallDWP =
// Handle window activation.
if (message == WM_ACTIVATE)
// Extend the frame into the client area.
margins.cxLeftWidth = LEFTEXTENDWIDTH;
margins.cxRightWidth = RIGHTEXTENDWIDTH;
margins.cyBottomHeight = BOTTOMEXTENDWIDTH; //20
margins.cyTopHeight = TOPEXTENDWIDTH;
hr = DwmExtendFrameIntoClientArea(hWnd, &margins);
if (!SUCCEEDED(hr))
// Handle error.
fCallDWP =
if (message == WM_PAINT)
hdc = BeginPaint(hWnd, &ps);
PaintCustomCaption(hWnd, hdc);
EndPaint(hWnd, &ps);
fCallDWP =
// Handle the non-client size message.
if ((message == WM_NCCALCSIZE) && (wParam == TRUE))
// Calculate new NCCALCSIZE_PARAMS based on custom NCA inset.
NCCALCSIZE_PARAMS *pncsp = reinterpret_cast&NCCALCSIZE_PARAMS*&(lParam);
pncsp-&rgrc[0].left
= pncsp-&rgrc[0].left
pncsp-&rgrc[0].top
= pncsp-&rgrc[0].top
pncsp-&rgrc[0].right
= pncsp-&rgrc[0].right
pncsp-&rgrc[0].bottom = pncsp-&rgrc[0].bottom - 0;
// No need to pass message on to the DefWindowProc.
fCallDWP =
// Handle hit testing in the NCA if not handled by DwmDefWindowProc.
if ((message == WM_NCHITTEST) && (lRet == 0))
lRet = HitTestNCA(hWnd, wParam, lParam);
if (lRet != HTNOWHERE)
fCallDWP =
*pfCallDWP = fCallDWP;
// Message handler the application.
LRESULT AppWinProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
int wmId, wmE
PAINTSTRUCT
LRESULT result = 0;
switch (message)
case WM_CREATE:
case WM_COMMAND:
= LOWORD(wParam);
wmEvent = HIWORD(wParam);
// Parse the menu selections:
switch (wmId)
return DefWindowProc(hWnd, message, wParam, lParam);
case WM_PAINT:
hdc = BeginPaint(hWnd, &ps);
PaintCustomCaption(hWnd, hdc);
// TODO: Add any drawing code here...
EndPaint(hWnd, &ps);
case WM_DESTROY:
PostQuitMessage(0);
return DefWindowProc(hWnd, message, wParam, lParam);
Appendix B: Painting the Caption Title
The following code demonstrates how to paint a caption title on the extended frame. This function must be called within the
// Paint the title on the custom frame.
void PaintCustomCaption(HWND hWnd, HDC hdc)
GetClientRect(hWnd, &rcClient);
HTHEME hTheme = OpenThemeData(NULL, L&CompositedWindow::Window&);
if (hTheme)
HDC hdcPaint = CreateCompatibleDC(hdc);
if (hdcPaint)
int cx = RECTWIDTH(rcClient);
int cy = RECTHEIGHT(rcClient);
// Define the BITMAPINFO structure used to draw text.
// Note that biHeight is negative. This is done because
// DrawThemeTextEx() needs the bitmap to be in top-to-bottom
BITMAPINFO dib = { 0 };
dib.bmiHeader.biSize
= sizeof(BITMAPINFOHEADER);
dib.bmiHeader.biWidth
dib.bmiHeader.biHeight
dib.bmiHeader.biPlanes
dib.bmiHeader.biBitCount
= BIT_COUNT;
dib.bmiHeader.biCompression
HBITMAP hbm = CreateDIBSection(hdc, &dib, DIB_RGB_COLORS, NULL, NULL, 0);
HBITMAP hbmOld = (HBITMAP)SelectObject(hdcPaint, hbm);
// Setup the theme drawing options.
DTTOPTS DttOpts = {sizeof(DTTOPTS)};
DttOpts.dwFlags = DTT_COMPOSITED | DTT_GLOWSIZE;
DttOpts.iGlowSize = 15;
// Select a font.
LOGFONT lgF
HFONT hFontOld = NULL;
if (SUCCEEDED(GetThemeSysFont(hTheme, TMT_CAPTIONFONT, &lgFont)))
HFONT hFont = CreateFontIndirect(&lgFont);
hFontOld = (HFONT) SelectObject(hdcPaint, hFont);
// Draw the title.
RECT rcPaint = rcC
rcPaint.top += 8;
//rcPaint.right -= 125;
rcPaint.left += 8;
//rcPaint.bottom = 50;
DrawThemeTextEx(hTheme, hdcPaint, 0, 0, szTitle, -1, DT_LEFT | DT_WORD_ELLIPSIS, &rcPaint, &DttOpts);
// Blit text to the frame.
BitBlt(hdc, 0, 0, cx, cy, hdcPaint, 0, 0, SRCCOPY);
SelectObject(hdcPaint, hbmOld);
if (hFontOld)
SelectObject(hdcPaint, hFontOld);
DeleteObject(hbm);
DeleteDC(hdcPaint);
CloseThemeData(hTheme);
Appendix C: HitTestNCA Function
The following code shows the HitTestNCA function used in . This function handles the hit testing logic for the
WM_NCHITTEST when DwmDefWindowProc does not handle the message.
// Hit test the frame for resizing and moving.
LRESULT HitTestNCA(HWND hWnd, WPARAM wParam, LPARAM lParam)
// Get point for the hit test.
POINT ptMouse = { GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam)};
// Get the window rectangle.
GetWindowRect(hWnd, &rcWindow);
// Get frame rectangle, adjusted for the style without a caption.
RECT rcFrame = { 0 };
AdjustWindowRectEx(&rcFrame, WS_OVERLAPPEDWINDOW & ~WS_CAPTION, FALSE, NULL);
// Determine if hit test is for resizing, default middle (1,1).
USHORT uRow = 1;
USHORT uCol = 1;
bool fOnResizeBorder =
// Determine if the point is at the top or bottom of the window.
if ( ptMouse.y &= rcWindow.top && ptMouse.y & rcWindow.top + TOPEXTENDWIDTH)
fOnResizeBorder = (ptMouse.y & (rcWindow.top - rcFrame.top));
else if ( ptMouse.y & rcWindow.bottom && ptMouse.y &= rcWindow.bottom - BOTTOMEXTENDWIDTH)
// Determine if the point is at the left or right of the window.
if ( ptMouse.x &= rcWindow.left && ptMouse.x & rcWindow.left + LEFTEXTENDWIDTH)
uCol = 0; //left side
else if ( ptMouse.x & rcWindow.right && ptMouse.x &= rcWindow.right - RIGHTEXTENDWIDTH)
uCol = 2; //right side
// Hit test (HTTOPLEFT, ... HTBOTTOMRIGHT)
LRESULT hitTests[3][3] =
{ HTTOPLEFT,
fOnResizeBorder ? HTTOP : HTCAPTION,
HTTOPRIGHT
HTNOWHERE,
{ HTBOTTOMLEFT, HTBOTTOM, HTBOTTOMRIGHT },
return hitTests[uRow][uCol];
参考知识库
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:256300次
积分:3337
积分:3337
排名:第8789名
原创:58篇
转载:106篇
评论:47条
(6)(1)(1)(1)(3)(5)(3)(1)(2)(4)(1)(3)(2)(3)(1)(5)(1)(1)(1)(3)(3)(3)(4)(1)(1)(1)(1)(4)(5)(18)(38)(34)(4)3418人阅读
今天这道菜主要是在navigationBar上面加入任意数量的任何控件。
(转载请保留此文字:本文来源:[&http://blog.csdn.net/ipromiseu/archive//6080474.aspx]&write by Gray.Luo guohui.)
&& &基本的navigationBar上面就左,中,右 3个位置,而且默认也是添加UIBarButtonItem/UINavigationBar按钮,但是很多开发过程中会遇到在上面添加更多其它控件,经过研究后,所以特写此文,算是做个笔记,也希望能够帮助朋友解决正在解决的这方面的问题。
1.在固定位置添加UIBarButtonItem
UIBarButtonItem&*myButton&=&[[[UIBarButtonItem&alloc]&&&&&&&&&&&&&&&&&&initWithTitle:@&myButton&&&&&&&&&&&&&&&&&&&style:UIBarButtonItemStyleBordered&&&&&&&&&&&&&&&&&&target:self&&&&&&&&&&&&&&&&&&&action:@selector(action)]autorelease];&&self.navigationItem.leftBarButtonItem&=&myB&&&&&&[myButton&release];&&
&&NavigationItem类有以下一些成员:
-titleview
-backBarButtonItem//这是有返回上一级事件的后退按钮
-rightBarButtonItem
-leftBarButtonItem
2.在任意位置添加一个UIToolbar叠加到navigationBar上,然后设置其背景透明,则可以实现在上这个navigationBar 上面添加多个按钮的效果
UIToolbar&*mycustomToolB&&NSMutableArray&*mycustomButtons&=&[[NSMutableArray&alloc]&init];&&UIBarButtonItem&*myButton1&=&[[[UIBarButtonItem&alloc]&&&&&&&&&&&&&&&&&&initWithTitle:@&Get5&&&&&&&&&&&&&&&&&&&style:UIBarButtonItemStyleBordered&&&&&&&&&&&&&&&&&&target:self&&&&&&&&&&&&&&&&&&&action:@selector(action)]autorelease];&&myButton1.width&=&40;&&[mycustomButtons&addObject:&myButton1];&&UIBarButtonItem&*myButton2&=&[[[UIBarButtonItem&alloc]&&&&&&&&&&&&&&&&&&initWithTitle:@&Play5&&&&&&&&&&&&&&&&&&&style:UIBarButtonItemStyleBordered&&&&&&&&&&&&&&&&&&target:self&&&&&&&&&&&&&&&&&&&action:@selector(action)]autorelease];&&myButton2.width&=&40;&&[mycustomButtons&addObject:&myButton2];&&&&&mycustomToolBar&=&[[UIToolbar&alloc]&initWithFrame:CGRectMake(0.0f,&0.0f,320.0f,&44.0f)];&&&&mycustomToolBar.barStyle&=&UIBarStyleD&&[mycustomToolBar&setItems:mycustomButtons&animated:YES];&&[mycustomToolBar&sizeToFit];&&&&&&[self.view&addSubview:mycustomToolBar];&&&&&&[mycustomToolBar&release];&&[mycustomButtons&release];&&
这里是在UIToolbar&上面添加UIBarButtonItem,然而我们很多时候可能会添加其它控件,如:switch,label等等,所以在UIToolbar上面如何添加各种控件,就参考下一篇文章。
3.在任意位置添加UISegmentedControl
UISegmentedControl&*&myS&&mySegment&=&[[UISegmentedControl&alloc]&&&&&&&&&&&&&&&&&initWithFrame:CGRectMake(5.0f,&10.0,&60.0f,&30.0f)];&&[mySegment&insertSegmentWithTitle:@&mySeg1&&atIndex:0&animated:YES];&&&[get5Segment&insertSegmentWithTitle:@&mySeg2&&atIndex:1&animated:YES];&&&&mySegment.segmentedControlStyle&=&UISegmentedControlStyleB&&[mySegment&addTarget:self&action:@selector(segAction:)&forControlEvents:UIControlEventValueChanged];&&mySegment.selectedSegmentIndex&=&-1;&&[self.navigationController.navigationBar&addSubview:&mySegment];&&[mySegment&release];&&
如果要在navigationBar实现多个按钮,而且某个功能块的类似按钮需要挨在一起,用segment实现还是很不错,用UIBarButtonItem实现的话,按钮间总是有一个间隔。
4.在任意位置添加UILabel
UILabel*&myL&&myLabel=[[UILabel&alloc]&initWithFrame:CGRectMake(100.0f,&14.0f,&100.0f,&10.0f)];&&myLabel.font=[UIFont&systemFontOfSize:10];&&myLabel.backgroundColor&=&[UIColor&clearColor];&&[self.navigationController.navigationBar&addSubview:&myLabel];&&[myLabel&release];&&
5.在任意位置添加UIProgressView&
&&&&UIProgressView&*myP&&myProgress&=[[UIProgressView&alloc]&initWithFrame:CGRectMake(80.0f,&28.0f,&150.0f,&8.0f)];&&[self.navigationController.navigationBar&addSubview:&myProgress];&&[myProgress&release];&&&&
参考知识库
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:55099次
积分:1059
积分:1059
排名:千里之外
原创:45篇
阅读:13016
(1)(1)(2)(2)(2)(3)(3)(1)(5)(3)(14)(17)}

我要回帖

更多关于 ios 给button设置边框 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信