创建两种方法:(1)常规的initWithFrame的方式 UIButton *btn1 = [[UIButton alloc]initWithFrame:CGRectMake(100, 50, 100, 75)];[btn1 setTitle:@"close" forState:UIControlStateNormal];btn1.backgroundColor = [UIColor greenColor];//button的背景颜色
[btn1 setBackgroundImage:[UIImage imageNamed:@"1.png"] forState:UIControlStateNormal];//button的背景图片
(2)UIButton 的一个类方法(也可以说是静态方法)buttonWithType UIButton *btn2 = [UIButton buttonWithType:UIButtonTypeRoundedRect];btn2.frame = CGRectMake(200, 20, 50, 60);btn2.backgroundColor = [UIColor blackColor];[btn2 setTitle:@"clicke" forState:UIControlStateNormal];[self.window addSubview:btn1];[self.window addSubview:btn2]; 能够定义的button类型由6种typedef enum { UIButtonTypeCustom = 0, // 自定义,无风格
UIButtonTypeRoundedRect, // 白色圆角矩形,类似偏好设置表格单元或者地址簿卡片
UIButtonTypeDetailDisclosure, // 蓝色的披露按钮,可放在任何文字旁
UIButtonTypeInfoLight, // 微件(widget)使用的小圆圈信息按钮,可以放在任何文字旁
UIButtonTypeInfoDark, // 白色背景下使用的深色圆圈信息按钮
UIButtonTypeContactAdd, // 蓝色加号(+)按钮,可以放在任何文字旁
} UIButtonType; [btn1 setTitle:@"BTN1" forState:UIControlStateNormal]; //设置按钮的标题
[btn1 setTitle:@"高亮状态" forState:UIControlStateHighlighted]; //高亮状态按钮title值
[btn2 setImage:[UIImage imageNamed:@"pic"] forState:UIControlStateNormal]; //你也可以为按钮的某一状态设置为图
[btn1 setTitleColor:[UIColor redColor] forState:UIControlStateNormal]; //设置标题颜色
[btn1 setTitleShadowColor:[UIColor grayColor] forState:UIControlStateNormal ]; //阴影
[btn1 setBackgroundImage:[UIImage imageNamed:@"PIC"] forState:UIControlStateHighlighted]; //背景图像
btn1.titleLabel.font = [UIFont fontWithName:@“test” size:18]; //设置按钮字体大小
[btn1 setTag:101] ; //设置tag值btn1.layer.cornerRadius = 4.5; //设置圆角——四个圆角半径 btn1.layer.borderWidth = 0.5; // 按钮边框宽度
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB(); // 设置颜色空间为rgb,用于生成ColorRef
CGColorRef borderColorRef = CGColorCreate(colorSpace,(CGFloat[]){ 0, 0, 0, 1 }); // 新建一个红色的ColorRef,用于设置边框(四个数字分别是 r, g, b, alpha)
参数 forState . 这个参数决定了标题、图像或其他属性将在何种状态下显现。你可以编程令按钮在那个状态变化 enum { UIControlStateNormal = 0, // 常态
UIControlStateHighlighted = 1 << 0, // 高亮
UIControlStateDisabled = 1 << 1, // 禁用
UIControlStateSelected = 1 << 2, // 选中
UIControlStateApplication = 0x00FF0000, // 当应用程序标志使用时
UIControlStateReserved = 0xFF000000 // 为内部框架预留的
}; typedef NSUInteger UIControlState; 你只要掌握前四种状态就好了。当按钮高亮或者禁用,UIButton 类可以调整自己的外观,下面几个属性可以让你按照需要对按钮的外观进行微调:adjustsImageWhenHighlighted默认情况下,在按钮被禁用时,图像会被画的颜色深一些。要禁用此功能,请将这个属性设置为NO:btn1.adjustsImageWhenHighlighted = NO; adjustsImageWhenDisabled默认情况下,按钮在被禁用时,图像会被画的颜色淡一些。要禁用此功能,请将这个属性设置为NO:btn1.adjustsImageWhenDisabled = NO; showsTouchWhenHighlighted这个属性设置为YES,可令按钮在按下时发光。这可以用于信息按钮或者有些重要的按钮:btn1.showsTouchWhenHighlighted = YES; 显示控件[self.view addSubview:btn1]; [self.view addSubview:btn2]; 重写绘制行为 你可以通过子类化按钮来定制属于你自己的按钮类。在子类化的时候你可以重载下面这些方法,这些方法返回CGRect结构,指明了按钮每一组成部分的边界。注意:不要直接调用这些方法, 这些方法是你写给系统调用的。 backgroundRectForBounds //指定背景边界
contentRectForBounds // 指定内容边界
titleRectForContentRect // 指定文字标题边界
imageRectForContentRect //指定按钮图像边界
例:- (CGRect)imageRectForContentRect:(CGRect)bounds{ return CGRectMake(0.0, 0.0, 44, 44); } [btn1 addTarget:self action:@selector(btnPressed:) forControlEvents:UIControlEventTouchUpInside];//添加点击按钮事件
-(void)btnPressed:(id)sender{ UIButton* btn = (UIButton*)sender; //开始写你自己的动作
}forControlEvents参数类型 typedef NS_OPTIONS(NSUInteger, UIControlEvents) { UIControlEventTouchDown = 1 << 0, // 单点触摸按下事件:用户点触屏幕,或者又有新手指落下的时候。
UIControlEventTouchDownRepeat = 1 << 1, // 多点触摸按下事件,点触计数大于1:用户按下第二、三、或第四根手指的时候。
UIControlEventTouchDragInside = 1 << 2, // 当一次触摸在控件窗口内拖动时。
UIControlEventTouchDragOutside = 1 << 3, // 当一次触摸在控件窗口之外拖动时。
UIControlEventTouchDragEnter = 1 << 4, // 当一次触摸从控件窗口之外拖动到内部时
UIControlEventTouchDragExit = 1 << 5, // 当一次触摸从控件窗口内部拖动到外部时。
UIControlEventTouchUpInside = 1 << 6, // 所有在控件之内触摸抬起事件
UIControlEventTouchUpOutside = 1 << 7, // 所有在控件之外触摸抬起事件(点触必须开始与控件内部才会发送通知)。
UIControlEventTouchCancel = 1 << 8, //所有触摸取消事件,即一次触摸因为放上了太多手指而被取消,或者被上锁或者电话呼叫打断。
UIControlEventValueChanged = 1 << 12, // 当控件的值发生改变时,发送通知。用于滑块、分段控件、以及其他取值的控件。你可以配置滑块控件何时发送通知,在滑块被放下时发送,或者在被拖动时发送。
UIControlEventEditingDidBegin = 1 << 16, // 当文本控件中开始编辑时发送通知
UIControlEventEditingChanged = 1 << 17, // 当文本控件中的文本被改变时发送通知。
UIControlEventEditingDidEnd = 1 << 18, // 当文本控件中编辑结束时发送通知。
UIControlEventEditingDidEndOnExit = 1 << 19, // 当文本控件内通过按下回车键(或等价行为)结束编辑时,发送通知。
UIControlEventAllTouchEvents = 0x00000FFF, // 通知所有触摸事件。
UIControlEventAllEditingEvents = 0x000F0000, // 通知所有关于文本编辑的事件。
UIControlEventApplicationReserved = 0x0F000000, // range available for application use
UIControlEventSystemReserved = 0xF0000000, // range reserved for internal framework use
UIControlEventAllEvents = 0xFFFFFFFF // 通知所有事件
};
posted @
2014-07-15 13:37 王海光 阅读(6269) |
评论 (0) |
编辑 收藏
//手动定义一个UITextField 及其基本的属性:
UITextField *text = [[UITextField alloc]initWithFrame:CGRectMake(20, 20, 130, 30)];
//设置边框样式,只有设置了才会显示边框样式
text.borderStyle = UITextBorderStyleRoundedRect;
typedef enum
{
UITextBorderStyleNone,
UITextBorderStyleLine,
UITextBorderStyleBezel,
UITextBorderStyleRoundedRect
} UITextBorderStyle;
text.backgroundColor = [UIColor whiteColor]; //设置输入框的背景颜色,此时设置为白色 如果使用了自定义的背景图片边框会被忽略掉
text.background = [UIImage imageNamed:@"dd.png"]; //设置背景
text.disabledBackground = [UIImage imageNamed:@"cc.png"]; //设置背景
text.placeholder = @"password"; //当输入框没有内容时,水印提示 提示内容为password
text.font = [UIFont fontWithName:@"Arial" size:20.0f]; //设置输入框内容的字体样式和大小
text.textColor = [UIColor redColor]; //设置字体颜色
text.clearButtonMode = UITextFieldViewModeAlways; //输入框中是否有个叉号,在什么时候显示,用于一次性删除输入框中的内容
typedef enum
{
UITextFieldViewModeNever, //重不出现
UITextFieldViewModeWhileEditing, //编辑时出现
UITextFieldViewModeUnlessEditing, // 除了编辑外都出现
UITextFieldViewModeAlways //一直出现
} UITextFieldViewMode;
text.text = @"一开始就在输入框的文字"; //输入框中一开始就有的文字
text.secureTextEntry = YES; //每输入一个字符就变成点 用语密码输入
text.autocorrectionType = UITextAutocorrectionTypeNo;//是否纠错
typedef enum
{
UITextAutocorrectionTypeDefault, // 默认
UITextAutocorrectionTypeNo, //不自动纠错
UITextAutocorrectionTypeYes, //自动纠错
} UITextAutocorrectionType;
text.clearsOnBeginEditing = YES; //再次编辑就清空
text.textAlignment = UITextAlignmentLeft; //内容对齐方式
text.contentVerticalAlignment = UIControlContentVerticalAlignmentCenter;//内容的垂直对齐方式 UITextField继承自UIControl,此类中有一个属性contentVerticalAlignment
textFied.adjustsFontSizeToFitWidth = YES; //设置为YES时文本会自动缩小以适应文本窗口大小.默认是保持原来大小,而让长文本滚动
text.minimumFontSize = 20; //设置自动缩小显示的最小字体大小
text.keyboardType = UIKeyboardTypeNumberPad; //设置键盘的样式
typedef enum
{
UIKeyboardTypeDefault, 默认键盘,支持所有字符
UIKeyboardTypeASCIICapable, 支持ASCII的默认键盘
UIKeyboardTypeNumbersAndPunctuation, 标准电话键盘,支持+*#字符
UIKeyboardTypeURL, URL键盘,支持.com按钮 只支持URL字符
UIKeyboardTypeNumberPad, 数字键盘
UIKeyboardTypePhonePad, 电话键盘
UIKeyboardTypeNamePhonePad, 电话键盘,也支持输入人名
UIKeyboardTypeEmailAddress, 用于输入电子 邮件地址的键盘
UIKeyboardTypeDecimalPad, 数字键盘 有数字和小数点
UIKeyboardTypeTwitter, 优化的键盘,方便输入@、#字符
UIKeyboardTypeAlphabet = UIKeyboardTypeASCIICapable,
} UIKeyboardType;
text.autocapitalizationType = UITextAutocapitalizationTypeNone;//首字母是否大写
typedef enum
{
UITextAutocapitalizationTypeNone, 不自动大写
UITextAutocapitalizationTypeWords, 单词首字母大写
UITextAutocapitalizationTypeSentences, 句子的首字母大写
UITextAutocapitalizationTypeAllCharacters, 所有字母都大写
} UITextAutocapitalizationType;
text.returnKeyType =UIReturnKeyDone;//return键变成什么键
typedef enum
{
UIReturnKeyDefault, 默认 灰色按钮,标有Return
UIReturnKeyGo, 标有Go的蓝色按钮
UIReturnKeyGoogle, 标有Google的蓝色按钮,用语搜索
UIReturnKeyJoin, 标有Join的蓝色按钮
UIReturnKeyNext, 标有Next的蓝色按钮
UIReturnKeyRoute, 标有Route的蓝色按钮
UIReturnKeySearch, 标有Search的蓝色按钮
UIReturnKeySend, 标有Send的蓝色按钮
UIReturnKeyYahoo, 标有Yahoo的蓝色按钮
UIReturnKeyYahoo, 标有Yahoo的蓝色按钮
UIReturnKeyEmergencyCall, 紧急呼叫按钮
} UIReturnKeyType;
textView.keyboardAppearance=UIKeyboardAppearanceDefault;//键盘外观
typedef enum
{
UIKeyboardAppearanceDefault, 默认外观,浅灰色
UIKeyboardAppearanceAlert, 深灰 石墨色
} UIReturnKeyType;
text.delegate = self;//设置代理 用于实现协议
[self.window addSubview:text];//把textfield加到视图中
//最右侧加图片是以下代码 左侧类似
UIImageView *image=[[UIImageView alloc] initWithImage:[UIImage imageNamed:@"right.png"]];
text.rightView=image;
text.rightViewMode = UITextFieldViewModeAlways;
typedef enum
{
UITextFieldViewModeNever,
UITextFieldViewModeWhileEditing,
UITextFieldViewModeUnlessEditing,
UITextFieldViewModeAlways
} UITextFieldViewMode;
//按return键键盘往下收 becomeFirstResponder
类要采用UITextFieldDelegate协议
text.delegate = self; 声明text的代理是我,我会去实现把键盘往下收的方法 这个方法在UITextFieldDelegate里所以我们要采用UITextFieldDelegate这个协议
- (BOOL)textFieldShouldReturn:(UITextField *)textField
{
[text resignFirstResponder]; //主要是[receiver resignFirstResponder]在哪调用就能把receiver对应的键盘往下收
return YES;
}
重写绘制行为
除了UITextField对象的风格选项,你还可以定制化UITextField对象,为他添加许多不同的重写方法,来改变文本字段的显示行为。这些方法都会返回一个CGRect结构,制定了文本字段每个部件的边界范围。以下方法都可以重写。
– textRectForBounds: //重写来重置文字区域
– drawTextInRect: //改变绘文字属性.重写时调用super可以按默认图形属性绘制,若自己完全重写绘制函数,就不用调用super了.
– placeholderRectForBounds: //重写来重置占位符区域
– drawPlaceholderInRect: //重写改变绘制占位符属性.重写时调用super可以按默认图形属性绘制,若自己完全重写绘制函数,就不用调用super了.
– borderRectForBounds: //重写来重置边缘区域
– editingRectForBounds: //重写来重置编辑区域
– clearButtonRectForBounds: //重写来重置clearButton位置,改变size可能导致button的图片失真
– leftViewRectForBounds:
– rightViewRectForBounds:
委托方法
- (BOOL)textFieldShouldBeginEditing:(UITextField *)textField
{
//返回一个BOOL值,指定是否循序文本字段开始编辑
return YES;
}
- (void)textFieldDidBeginEditing:(UITextField *)textField
{
//开始编辑时触发,文本字段将成为first responder
}
- (BOOL)textFieldShouldEndEditing:(UITextField *)textField
{
//返回BOOL值,指定是否允许文本字段结束编辑,当编辑结束,文本字段会让出first responder
//要想在用户结束编辑时阻止文本字段消失,可以返回NO
//这对一些文本字段必须始终保持活跃状态的程序很有用,比如即时消息
return NO;
}
- (BOOL)textField:(UITextField*)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string
{
//当用户使用自动更正功能,把输入的文字修改为推荐的文字时,就会调用这个方法。
//这对于想要加入撤销选项的应用程序特别有用
//可以跟踪字段内所做的最后一次修改,也可以对所有编辑做日志记录,用作审计用途。
//要防止文字被改变可以返回NO
//这个方法的参数中有一个NSRange对象,指明了被改变文字的位置,建议修改的文本也在其中
return YES;
}
- (BOOL)textFieldShouldClear:(UITextField *)textField
{
//返回一个BOOL值指明是否允许根据用户请求清除内容
//可以设置在特定条件下才允许清除内容
return YES;
}
-(BOOL)textFieldShouldReturn:(UITextField *)textField
{
//返回一个BOOL值,指明是否允许在按下回车键时结束编辑
//如果允许要调用resignFirstResponder 方法,这回导致结束编辑,而键盘会被收起[textField resignFirstResponder];
//查一下resign这个单词的意思就明白这个方法了
return YES;
}
通知
UITextField派生自UIControl,所以UIControl类中的通知系统在文本字段中也可以使用。除了UIControl类的标准事件,你还可以使用下列UITextField类特有的事件
UITextFieldTextDidBeginEditingNotification
UITextFieldTextDidChangeNotification
UITextFieldTextDidEndEditingNotification
当文本字段退出编辑模式时触发。通知的object属性存储了最终文本。
因为文本字段要使用键盘输入文字,所以下面这些事件发生时,也会发送动作通知
UIKeyboardWillShowNotification //键盘显示之前发送
UIKeyboardDidShowNotification //键盘显示之后发送
UIKeyboardWillHideNotification //键盘隐藏之前发送
UIKeyboardDidHideNotification //键盘隐藏之后发送
1、Text :设置文本框的默认文本。
2、Placeholder : 可以在文本框中显示灰色的字,用于提示用户应该在这个文本框输入什么内容。当这个文本框中输入了数据时,用于提示的灰色的字将会自动消失。
3、Background :
4、Disabled : 若选中此项,用户将不能更改文本框内容。
5、接下来是三个按钮,用来设置对齐方式。
6、Border Style : 选择边界风格。
7、Clear Button : 这是一个下拉菜单,你可以选择清除按钮什么时候出现,所谓清除按钮就是出一个现在文本框右边的小 X ,你可以有以下选择:
7.1 Never appears : 从不出现
7.2 Appears while editing : 编辑时出现
7.3 Appears unless editing :
7.4 Is always visible : 总是可见
8、Clear when editing begins : 若选中此项,则当开始编辑这个文本框时,文本框中之前的内容会被清除掉。比如,你现在这个文本框 A 中输入了 "What" ,之后去编辑文本框 B,若再回来编辑文本框 A ,则其中的 "What" 会被立即清除。
9、Text Color : 设置文本框中文本的颜色。
10、Font : 设置文本的字体与字号。
11、Min Font Size : 设置文本框可以显示的最小字体(不过我感觉没什么用)
12、Adjust To Fit : 指定当文本框尺寸减小时,文本框中的文本是否也要缩小。选择它,可以使得全部文本都可见,即使文本很长。但是这个选项要跟 Min Font Size 配合使用,文本再缩小,也不会小于设定的 Min Font Size 。
接下来的部分用于设置键盘如何显示。
13、Captitalization : 设置大写。下拉菜单中有四个选项:
13.1 None : 不设置大写
13.2 Words : 每个单词首字母大写,这里的单词指的是以空格分开的字符串
13.3 Sentances : 每个句子的第一个字母大写,这里的句子是以句号加空格分开的字符串
13.4 All Characters : 所以字母大写
14、Correction : 检查拼写,默认是 YES 。
15、Keyboard : 选择键盘类型,比如全数字、字母和数字等。
16、Appearance:
17、Return Key : 选择返回键,可以选择 Search 、 Return 、 Done 等。
18、Auto-enable Return Key : 如选择此项,则只有至少在文本框输入一个字符后键盘的返回键才有效。
19、Secure : 当你的文本框用作密码输入框时,可以选择这个选项,此时,字符显示为星号。
1.Alignment Horizontal 水平对齐方式
2.Alignment Vertical 垂直对齐方式
3.用于返回一个BOOL值 输入框是否 Selected(选中) Enabled(可用) Highlighted(高亮)
限制只能输入特定的字符
(BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string
{
NSCharacterSet *cs;
cs = [[NSCharacterSet characterSetWithCharactersInString:NUMBERS]invertedSet];
NSString *filtered = [[string componentsSeparatedByCharactersInSet:cs]componentsJoinedByString:@""]; //按cs分离出数组,数组按@""分离出字符串
BOOL canChange = [string isEqualToString:filtered];
return canChange;
}
上面那个NUMBERS是一个宏,可以在文件顶部定义:
#define NUMBERS @”0123456789n” (这个代表可以输入数字和换行,请注意这个n,如果不写这个,Done按键将不会触发,如果用在SearchBar中,将会不触发Search事件,因为你自己限制不让输入n,好惨,我在项目中才发现的。)
所以,如果你要限制输入英文和数字的话,就可以把这个定义为:
#define kAlphaNum @”ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789″。
当然,你还可以在以上方法return之前,做一提示的,比如提示用户只能输入数字之类的。如果你觉得有需要的话。
限制只能输入一定长度的字符
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string;
{
//string就是此时输入的那个字符 textField就是此时正在输入的那个输入框 返回YES就是可以改变输入框的值 NO相反
if ([string isEqualToString:@"n"]) //按会车可以改变
{
return YES;
}
NSString * toBeString = [textField.text stringByReplacingCharactersInRange:range withString:string]; //得到输入框的内容
if (self.myTextField == textField) //判断是否时我们想要限定的那个输入框
{
if ([toBeString length] > 20)
{
//如果输入框内容大于20则弹出警告
textField.text = [toBeString substringToIndex:20];
UIAlertView *alert = [[[UIAlertView alloc] initWithTitle:nil message:@"超过最大字数不能输入了" delegate:nil cancelButtonTitle:@"Ok" otherButtonTitles:nil, nil] autorelease];
[alert show];
return NO;
}
}
return YES;
}
本文转自:http://www.3lian.com/edu/2012/11-08/43227.html
posted @
2014-07-15 11:02 王海光 阅读(1397) |
评论 (0) |
编辑 收藏
1、根据年、月、日获取星期几
- (int)getWeekdayFromDate:(int)nYead andMonth:(int)nMonth andDay:(int)nDay
{
NSDateComponents *_comps = [[NSDateComponents alloc] init];
[_comps setDay:nDay];
[_comps setMonth:nMonth];
[_comps setYear:nYead];
NSCalendar *gregorian = [[NSCalendar alloc]
initWithCalendarIdentifier:NSGregorianCalendar];
NSDate *_date = [gregorian dateFromComponents:_comps];
NSDateComponents *weekdayComponents =
[gregorian components:NSWeekdayCalendarUnit fromDate:_date];
int _weekday = [weekdayComponents weekday];
return _weekday;
}
或
- (NSUInteger)getWeekdayFromDate:(NSDate*)date
{
NSCalendar* calendar = [[[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar] autorelease];
NSDateComponents* components = [[[NSDateComponents alloc] init] autorelease];
NSInteger unitFlags = NSYearCalendarUnit |
NSMonthCalendarUnit |
NSDayCalendarUnit |
NSWeekdayCalendarUnit |
NSHourCalendarUnit |
NSMinuteCalendarUnit |
NSSecondCalendarUnit;
components = [calendar components:unitFlags fromDate:date];
NSUInteger weekday = [components weekday];
return weekday;
}
2、根据月和日获取星座
-(NSString *)getAstroWithMonth:(int)m day:(int)d
{
NSString *astroString = @"魔羯水瓶双鱼白羊金牛双子巨蟹狮子处女天秤天蝎射手魔羯";
NSString *astroFormat = @"102123444543";
NSString *result;
if (m < 1 || m > 12 || d < 1 || d > 31)
{
return @"错误日期格式!";
}
if(m == 2 && d > 29)
{
return @"错误日期格式!!";
}
else if(m == 4 || m == 6 || m == 9 || m == 11)
{
if (d > 30)
{
return @"错误日期格式!!!";
}
}
result = [NSString stringWithFormat:@"%@",[astroString substringWithRange:NSMakeRange(m*2 - (d < [[astroFormat substringWithRange:NSMakeRange((m - 1), 1)] intValue] - (-19))*2, 2)]];
return result;
}
3、计算两个日期之间相差几天几小时几分钟
NSDateFormatter *dateFormatter=[[NSDateFormatter alloc] init];
[dateFormatter setDateFormat:@"yyyy-MM-dd HH:mm:ss"];
NSDate * senddate=[NSDate date];
//结束时间
NSDate *endDate = [dateFormatter dateFromString:@"2014-6-24 00:00:00"];
//当前时间
NSDate *senderDate = [dateFormatter dateFromString:[dateFormatter stringFromDate:senddate]];
//得到相差秒数
NSTimeInterval time=[endDate timeIntervalSinceDate:senderDate];
int days = ((int)time)/(3600*24);
int hours = ((int)time)%(3600*24)/3600;
int minute = ((int)time)%(3600*24)600/60;
if (days <= 0&&hours; <= 0&&minute; <= 0)
dateContent=@"0天0小时0分钟";
else
dateContent=[[NSString alloc] initWithFormat:@"%i天%i小时%i分钟",days,hours,minute];
4、获取当前时间
NSDate *now = [NSDate date];
NSLog(@”now date is: %@”, now);
NSCalendar *calendar = [NSCalendar currentCalendar];
NSUInteger unitFlags = NSYearCalendarUnit | NSMonthCalendarUnit | NSDayCalendarUnit | NSHourCalendarUnit | NSMinuteCalendarUnit | NSSecondCalendarUnit;
NSDateComponents *dateComponent = [calendar components:unitFlags fromDate:now];
int year = [dateComponent year];
int month = [dateComponent month];
int day = [dateComponent day];
int hour = [dateComponent hour];
int minute = [dateComponent minute];
int second = [dateComponent second];
NSLog(@”year is: %d”, year);
NSLog(@”month is: %d”, month);
NSLog(@”day is: %d”, day);
NSLog(@”hour is: %d”, hour);
NSLog(@”minute is: %d”, minute);
NSLog(@”second is: %d”, second);
注:根据互联网资料整理
posted @
2014-07-15 10:43 王海光 阅读(292) |
评论 (0) |
编辑 收藏
在iOS应用开发中,有三类视图对象会打开虚拟键盘,进行输入操作,但如何关闭虚拟键盘,却没有提供自动化的方法。这个需要我们自己去实现。这三类视图对象分别是UITextField,UITextView和UISearchBar。
这里介绍一下UITextField中关闭虚拟键盘的几种方法。
(原文链接: http://mikixiyou.iteye.com/blog/1753330 )
第一种方法,使用它的委托UITextFieldDelegate中的方法textFieldShouldReturn:来关闭虚拟键盘。
在UITextField视图对象如birdNameInput所在的类中实现这个方法。
- (BOOL)textFieldShouldReturn:(UITextField *)textField {
if ((textField == self.birdNameInput) || (textField == self.locationInput)) {
[textField resignFirstResponder];
}
return YES;
}
这样,在输入框birdNameInput中打开虚拟键盘后,轻击键盘的return键就会自动关闭掉虚拟键盘。
第二种方法,将birdNameInput的属性中Return Key修改为done,再定义一个方法和Done键的Did End On Exit连接。通过轻击done键触发这个事件来关闭虚拟键盘。
定义的方法如下:
- (IBAction) textFieldDoneEditing:(id)sender
{
[sender resignFirstResponder];
}
这两个方法都是轻击虚拟键盘上一个键来关闭它。这属于精确操作,而手指不像鼠标,做这种操作不容易。因此就UI层面而言,这两个方法都不是最好的方法。
在iphone或ipad屏幕上,虚拟键盘占用的面积大小是有限的。通过轻击虚拟键盘之外的区域而关闭虚拟键盘。
第三种方法,通过轻击键盘之外的空白区域关闭虚拟键盘。
在birdNameInput所属的视图控制器类的viewDidLoad方法中定义一个UITapGestureRecognizer的对象,然后将它赋值为它的视图。
UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(dismissKeyboard)];
[self.view addGestureRecognizer:tap];
[tap release];
再定义一下选择器调用的方法dismissKeyboard。
-(void)dismissKeyboard {
[birdNameInput resignFirstResponder];
}
如果屏幕上有多个textField的话,一个一个地列出来就有些麻烦。那么将方法修改一下,如下:
-(void)dismissKeyboard {
NSArray *subviews = [self.view subviews];
for (id objInput in subviews) {
if ([objInput isKindOfClass:[UITextField class]]) {
UITextField *theTextField = objInput;
if ([objInput isFirstResponder]) {
[theTextField resignFirstResponder];
}
}
}
}
如果这个屏幕上的视图对象很复杂的话,另当别论。
这个方法是编码新建一个手势对象。也可以直接使用interface builder图形化开发工具,在storyboard中拉入一个手势对象到视图控制器类中,再将此手势对象建立一个IBACTION,名称可以是dismissKeyboard。
第四种方法,通过轻击键盘之外的空白区域关闭虚拟键盘。
将屏幕上的view也就是textField的父视图拖一个touch down事件出来,和一个能关闭虚拟键盘的方法连接。如果视图没有touch down事件,可将view的父类从UIView修改为UIButton。
首先定义并实现一个方法backgroundTap:。
- (IBAction) backgroundTap:(id)sender
{
NSArray *subviews = [self.view subviews];
for (id objInput in subviews) {
if ([objInput isKindOfClass:[UITextField class]]) {
UITextField *theTextField = objInput;
if ([objInput isFirstResponder]) {
[theTextField resignFirstResponder];
}
}
}
}
然后选择背景视图的Touch Down事件,连接 backgroundTap:即可。这样只要轻击一下虚拟键盘之外的区域,就能关闭虚拟键盘。这些方法都是使用resignFirstResponder方法来关闭虚拟键盘,还有其他的方法。
第五种方法,使用endEditing:方法
在所在的视图控制器类中,覆盖这个方法。
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
[[self view] endEditing:YES];
}
This method looks at the current view and its subview hierarchy for the text field that is currently the first responder. If it finds one, it asks that text field to resign as first responder. If the force parameter is set to YES, the text field is never even asked; it is forced to resign.
但是,如果这个屏幕很复杂,虚拟键盘之外的区域中有很多按钮。轻击这些区域时可能会轻击到这些按钮,这样虚拟键盘就不能关闭。
要是找到一个没有按钮的空白区域都不容易且还有隐藏的视图对象时,通过轻击虚拟键盘之外的区域关闭虚拟键盘的方法实现起来就难了。
第六种方法,覆盖hitTest:withEvent:方法关闭虚拟键盘
在stackoverflow.com上,有人这样总结。说使用hitTest:withEvent:方法是最好的,也是最容易的解决方法。
I think the easiest (and best) way to do this is to subclass your global view and use hitTest:withEvent method to listen to any touch.
Touches on keyboard aren't registered, so hitTest:withEvent is only called when you touch/scroll/swipe/pinch... somewhere else, then call [self endEditing:YES].
This is better than using touchesBegan because touchesBegan are not called if you click on a button on top of the view.
It is better than UITapGestureRecognizer which can't recognize a scrolling gesture for example. It is also better than using a dim screen because in a complexe and dynamic user interface, you can't put dim screen every where. Moreover, it doesn't block other actions, you don't need to tap twice to select a button outside (like in the case of a UIPopover).
Also, it's better than calling [textField resignFirstResponder], because you may have many text fields on screen, so this works for all of them.
因此,我再建立一个继承UIView的视图类。在这个视图类中,覆盖hitTest:withEvent:方法,增加[self endEditing:YES]方法。
- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event {
UIView *result = [super hitTest:point withEvent:event];
[self endEditing:YES]
return result;
}
我将视图控制器的主视图所属类修改为这个新建视图类。这样在屏幕上轻击任何位置都会关闭虚拟键盘。
这个方法是最简单,也是最好的关闭虚拟键盘的方法。
使用好hitTest:withEvent:这个方法,还可以实现很多很复杂的功能。
The implementation of hitTest:withEvent: in UIResponder does the following:
- It calls pointInside:withEvent: of self
- If the return is NO, hitTest:withEvent: returns nil. the end of the story.
- If the return is YES, it sends hitTest:withEvent: messages to its subviews. it starts from the top-level subview, and continues to other views until a subview returns a non-nil object, or all subviews receive the message.
- If a subview returns a non-nil object in the first time, the first hitTest:withEvent: returns that object. the end of the story.
- If no subview returns a non-nil object, the first hitTest:withEvent: returns self
This process repeats recursively, so normally the leaf view of the view hierarchy is returned eventually.
However, you might override hitTest:withEvent to do something differently. In many cases, overriding pointInside:withEvent: is simpler and still provides enough options to tweak event handling in your application.
posted @
2014-06-23 13:54 王海光 阅读(297) |
评论 (0) |
编辑 收藏
摘要: IOS开发使用委托delegate在不同窗口之间传递数据是本文要介绍的内容,主要是来讲解如何使用委托delegate在不同窗口之间传递数据,具体内容来看详细内容。在IOS开发里两个UIView窗口之间传递参数方法有很多,比如
1、使用SharedApplication,定义一个变量来传递.
2、使用文件,或者NSUserdefaul...
阅读全文
posted @
2014-06-18 14:50 王海光 阅读(333) |
评论 (0) |
编辑 收藏
1、设置背景图片
1 UIImageView *imgView =[[UIImageView alloc] initWithFrame:CGRectMake(128, 80,64,64)];
2 imgView.image = [UIImage imageNamed:@"portrait.png"];
3 imgView.userInteractionEnabled=YES;
4 UITapGestureRecognizer *singleTap =[[UITapGestureRecognizer alloc]initWithTarget:self action:@selector(onClickPortraitImage)];
5 [imgView addGestureRecognizer:singleTap];
6 [self.view addSubview:imgView];
2、响应点击事件
1 -(void)onClickPortraitImage{
2
3 NSLog(@"图片被点击!");
4 }
开发工具Xcode5 系统版本:OS X 10. 9. 3 ( 13D65 )
posted @
2014-05-28 14:33 王海光 阅读(334) |
评论 (0) |
编辑 收藏
鼠标滚轮消息似乎只会发给当前获得焦点的窗口,所以当子窗体没有焦点时是收不到滚轮消息的,收到消息的可能是父窗口。
解决:添加鼠标单击相应函数,在响应函数中添加SetFoucs();一句,这样强制设置焦点给子窗口,然后再滚动鼠标滚轮,子窗体就能收到滚轮消息了。
问题继续,当子窗口上有其他可以获得焦点的控件时,比如下拉列表,这时在窗口函数中执行SetFoucs();焦点会自动跑到那个控件上去,子窗口同样收不到滚轮消息。
解决:在执行SetFoucs();语句前先Disable子窗体上的所有控件,然后执行SetFoucs();,再Enanle所有控件,这时焦点才会在子窗口上。
本文转自:http://blog.csdn.net/vanship/article/details/4119246
posted @
2014-05-08 16:33 王海光 阅读(4626) |
评论 (0) |
编辑 收藏
一般地,当在目标机器编译安装某个服务程序后,为了使服务能开机自启动和关机自停止,则需要将其添加为系统服务。但不同的Linux系统管理服务的方法不同,如Ubuntu使用update-rc.d命令,而RedHat则使用 chkconfig命令。因此为了能自动识别系统的类型,减少人工控制,编写了一个简单的autosrv脚本,要求至少1个最多2个参数,特点如下: ● 第1个参数只能为install或uninstall,表示安装或卸载服务。 ● 第2参数是可选的,表示系统名称,如果没有指定,那么会自动识别,若出现提示错误,则表示应该要显式指定系统名称了。 1#! /bin/bash
2# autosrv
3
4if [ $# -lt 1 ]; then
5 echo "Usage: $(basename "$0") install | uninstall [sysname]"
6 exit
7elif [ "$1" != "install" -a "$1" != "uninstall" ]; then
8 echo "The first parameter must be install or uninstall"
9 exit
10fi
11
12action=$1
13sysname=$2
14srv_path=/etc/init.d/srv_name
15
16if [ -z "$sysname" ]; then
17 sysname=`lsb_release -a | sed -n '2p' | awk '{if($0~/[Uu][Bb][Uu][Nn][Tt][Uu]/) print "ubuntu"; else if($0~/[Dd][Ee][Bb][Ii][Aa][Nn]/) print "debian"; else if($0~/[Rr][Ee][Dd][Hh][Aa][Tt]/) print "redhat"; else if($0~/[Cc][Ee][Nn][Tt][Oo][Ss]/) print "centos"; else print ""}'`
18 if [ -z "$sysname" ]; then
19 echo "Unknown system, please manual special it with the second parameter"
20 exit
21 fi
22 echo "Current system is $sysname"
23fi
24
25create_file_ubuntu_debian()
26{
27cat << END > $srv_path
28#! /bin/bash
29. /lib/lsb/init-functions
30
31END
32cat srv_name.body >> $srv_path
33}
34
35create_file_redhat_centos()
36{
37cat << END > $srv_path
38#! /bin/bash
39#chkconfig:2345 90 10
40#description: srv name
41
42. /etc/rc.d/init.d/functions
43
44END
45cat srv_name.body >> $srv_path
46}
47
48chmod_file()
49{
50 chmod u+x $srv_path
51}
52
53remove_file()
54{
55 rm -f $srv_path
56}
57
58install_ubuntu_debian()
59{
60 create_file_ubuntu_debian
61 chmod_file
62 update-rc.d srv_name defaults 90 10
63}
64
65uninstall_ubuntu_debian()
66{
67 update-rc.d -f srv_name remove
68 remove_file
69}
70
71install_redhat_centos()
72{
73 create_file_redhat_centos
74 chmod_file
75 chkconfig --add srv_name
76}
77
78uninstall_redhat_centos()
79{
80 chkconfig --del srv_name
81 remove_file
82}
83
84case "$sysname" in
85 ubuntu|debian)
86 if [ "$action" = "install" ]; then
87 install_ubuntu_debian
88 else
89 uninstall_ubuntu_debian
90 fi
91 ;;
92
93 redhat|centos)
94 if [ "$action" = "install" ]; then
95 install_redhat_centos
96 else
97 uninstall_redhat_centos
98 fi
99 ;;
100
101 *)
102 echo "Currently only support ubuntu, debian, redhat and centos system"
103 exit
104 ;;
105esac 从上可知,自动识别的方法是获取lsb_release -a返回的文本再使用awk来匹配ubuntu,redhat,debian,centos这几个子串(忽略大小写)。要注意的是,返回的文本可能有所不同,当系统安装了LSB模块时,返回结果如下 没有安装时,返回结果如下
posted @
2014-04-23 17:06 王海光 阅读(427) |
评论 (0) |
编辑 收藏
C++使用共享内存实现进程间通信文件映射是一种实现进程间单向或双向通信的机制。它允许两个或多个本地进程间相互通信。为了共享文件或内存,所有的进程必须使用相同的文件映射的名字或是句柄。为了实现共享文件,第一个进程先调用CreateFile方法。接下来调用CreateFileMapping方法来创建一个文件映射对象。并为文件映射指明一个句柄和名称。由于事件,信号,互斥对象和文件映射等这些内核对象都共享同一个名字空间,所以如果这个名字和其他一个对象的名称重名的话那么将创建失败。为了实现共享内存,进程应首先调用CreateFileMapping函数然后在hFile参数中传入INVALID_HANDLE_VALUE宏来替代句柄。相应的文件映射对象会从系统的分页文件中获得一段内存。如果hFile参数的值是INVALID_HANDLE_VALUE,那么你在调用CreateFileMapping时必须给共享内存指定一个大小值。使用共享内存或文件的进程必须使用MapViewOfFile函数或MapViewOfFileEx函数来创建一个文件视图。示例代码:服务端:HANDLE hfilemapping = NULL;
void CCSharedMemoryDlg::OnButton1()
{
// TODO: Add your control notification handler code here
hfilemapping = CreateFileMapping(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, 16, "COMBANC_SHARE");
//创建错误
if ((hfilemapping == NULL) || (hfilemapping == INVALID_HANDLE_VALUE))
// return lx_invalid_sharedmemory;
MessageBox("error");
//共享内存已经存在
if (GetLastError() == ERROR_ALREADY_EXISTS)
{
MessageBox("共享内存已经存在");
return;
}
BYTE *psize = (BYTE *)MapViewOfFile(hfilemapping, FILE_MAP_WRITE, 0, 0, sizeof(BYTE));
if(psize == NULL)
{
if (hfilemapping != NULL)
{
CloseHandle(hfilemapping);
hfilemapping = NULL;
}
return;
}
CString sTest = "abc";
char ch[16] = "COMBANC_TEST";
memcpy(psize,sTest,sTest.GetLength());
if (psize != NULL)
{
UnmapViewOfFile(psize );
psize = NULL;
}
}
客户端:HANDLE hfilemapping = NULL;
void CTestShareMemoryDlg::OnBnClickedButton1()
{
// TODO: Add your control notification handler code here
hfilemapping = OpenFileMapping(FILE_MAP_READ, FALSE, "COMBANC_SHARE");
if ((hfilemapping == NULL) || (hfilemapping == INVALID_HANDLE_VALUE))
MessageBox("error");
BYTE *psize = (BYTE *)MapViewOfFile(hfilemapping, FILE_MAP_READ, 0, 0, sizeof(BYTE));
if(psize == NULL)
{
if (hfilemapping != NULL)
{
CloseHandle(hfilemapping);
hfilemapping = NULL;
}
return;
}
char ch[16];
memcpy(ch,psize,16);
MessageBox(ch);
if (psize != NULL)
{
UnmapViewOfFile(psize );
psize = NULL;
}
if (hfilemapping != NULL)
{
CloseHandle(hfilemapping);
hfilemapping = NULL;
}
}
posted @
2014-04-11 18:37 王海光 阅读(589) |
评论 (0) |
编辑 收藏
google 的开源项目 值 得我们一用的,这些项目很有意义,甚至可以直接用在我们自己的工作上!学习编程的的一个比较好的方式就是阅读优秀项目的源代码,从而能够了解作者的方法、 思路、技巧,另外阅读源代码对于一些朋友是枯燥乏味的,这是就可以看看项目的readme,找到项目的闪光点,我们不做开拓者那我们就做实践者和使用者, 呵呵,下面是这些项目的列表,在这里存档,已备今后查阅之用
文本文件处理:
Google CRUSH (Custom Reporting Utilities for SHell)
CRUSH是为命令行或shell scripts处理特定文字数据而制作的一系列工具,这里有指南。
C++库和源代码:
Google Breakpad
一个开源的多平台崩溃报告系统。
Google GFlags
Gflags是一个命令行标记的处理库,它可以替代“getopt()”,其内置对C++的支持比如string。指南在此 。
Google Glog Glog库可执行应用级的登陆,提供基于C++式的登陆API,可用于Linux、BSD和Windows。指南见此 。
Google PerfTools
这个工具可让开发创建更强大的应用程序,特别是那些用C++模版开发的多线程应用程序,包括TCMalloc, heap-checker, heap-profiler 和cpu-profiler。指南见此 还有这里 。
Google Sparse Hash
非常节省内存的hash-map。指南见此 。
Omaha – Google Update
Omaha,也就是Google Update,它可以保证你的软件随时升级到最新版本,目前很多Windows下的Google软件都是用Omaha升级的,包括Google Chrome和Google Earth,当然你也可以用于自己的应用程序。指南看这里 还有这里 。
Protocol Buffers
Protocol Buffers是一种可扩展编码序列数据的方式,Google在几乎所有内部RPC协议和文件格式都使用了Protocol Buffers。指南见此 。它可以用于很多语言而且被一些IDE所支持,比如NetBeans 。
互联网:
Google Code Pretiffy 这 是一个Javascript模块和CSS文件,它可以让HTML页面里的部分源码高亮显示,支持C/C++, Java, Python, Ruby, PHP, VisualBasic, AWK, Bash, SQL, HTML, XML, CSS, JavaScript, Makefiles和部分Perl,不支持Smalltalk和所有的CAML。例子见此 。
SpriteMe – easy “CSS spirtes” SpriteMe使你可以更轻松的创造CSS Sprites(俗称雪碧……)就是把网站要用到的图片都堆在一张图片里,用CSS控制调用哪个区域。它有一个自己的官网在这里 。
Redacisaurus
Reducisaurus是一个压缩CSS和JS文件的网络服务,基于YUI压缩算法,运行于App Engine。
JaikuEngine
JaikuEngine是一个运行于App Engine的微博系统,由jaiku.com 运营。要查看移动客户端的源码可以看这里 ,这里还有介绍 。
Selector Shell
Selector Shell是一个基于浏览器的测试工具,它可以让你看到CSS在不同浏览器里的样式,用Javascript写的,你可以在这里测试 。
Google Feed Server
Google Feed Server是一个开源Atom发布协议服务,基于Apache Abdera框架,允许开发者快速为当前数据源(比如数据库)配置feed。指南见这里 和这里 。
Melange, the Spice of Creation
这 个项目的目标是创建出一个适合开源贡献流程的框架,比如Google Summer of Code TM (GSoC)项目。使用这个框架你就可以用Google App Engine来运行Google Summer of Code项目,和其它类似项目比如Google Highly Open Participation TM Contest和GHOP。指南见此 。
NameBench
它可以查找最快的DNS服务器给你的电脑用,在Mac OS X、Windows和UNIX系统下都有命令行也有用户界面可以帮你测试,这是Google工程师用20%自由时间写出来的。
Rat Proxy
一个半自动化的大型被动网络应用安全审查工具,专为精确的探测而优化,文档在此 。
TopDraw
Top Draw是一个图形生成程序,使用简单的文字脚本,基于JavaScript编程语言,Top Draw可以创造出非常复杂和有趣的图形。支持Mac OS 10.5以上系统,使用XCode开发。
etherpad
开源的EtherPad,这是一个基于网络的实时合作文档编辑器,这个项目主要是为了演示代码而开发,帮助那些想在自己服务器部署Etherpad的人使用,这里有如何安装的指南。EtherPad使用JavaScript、Java和Comet服务器来建造实时协作服务。
Chromium
Chromium是开源版的Chrome浏览器,Chromium的目标是建立一个新一代的强大网络应用程序,它与Chrome有很多不同之处。这里有指导如何在Linux上编译Chromium 。
V8 Google’s open source JavaScript engine V8 是Google的开源JavaScript引擎,用C++写成,用于Chrome浏览器之上。V8使用ECMAScript的ECMA-262第三版可运 行于Windows XP、Vista、Mac OS 10.5和使用IA-32或ARM处理器的Linux。V8可独立运行也可嵌入到任何C++程序里使用,这里有指南 。
Chromium OS
Chromium OS是开源版的Chrome OS操作系统,提供快速、简单而安全的网络体验,源码在此 。
Android
Android是第一个免费、开源而且可完全自定义的移动平台,提供完整的堆栈:一个操作系统、中间件和重要的一用应用,它包含丰富的API可以让第三方开发者开发出强大的应用程序。
MySQL工具:
各种管理、维护和改进MySQL数据库性能的工具,由Google编写,包括:
- mypgrep.py:一个类似pgrep的工具来管理MySQL连接
- compact_innodb.py:可导出和重载所有表格的密集型innodb数据文件
Google mMAIM
mMAIM的目标是对MySQL的监控和分析更简单,且可以和任何环境整合使用。它可显示主/从同步状态,一些性能状态,可以返回大量“show”命令的状态等等。
其它:
Stressful Application Test (stressapptest)
Stressful Application Test试图让来自处理器和I/O到内存的数据尽量随机化,以创造出模拟现实的环境来测试现在的硬件设备是否稳定,Google就在使用它,现在是Apache 2.0许可,这里有介绍 、安装向导 和指南 。
Pop and IMAP Troubleshooter
它用于诊断并解决客户端到邮件服务器的连接问题。
OpenDuckBill
Openduckbill是一个Linux下简单的命令行备份工具,可用于监视文件/目录在有变化后是否标记为备份,并传输这些变化到本地备份目录、远程NFS导出分卷或是用rsync命令导出到远程SSH服务器。见安装向导 。
ZXing
ZXing(发音类似Zebra crossing)是Java的开源多格式1D/2D条码图像处理库,目的是使用内置在手机上的摄像头拍照并对条码进行解码,而不必与服务器通讯,它被用于Android系统。这里有向导 和支持的设备列表 。 Tesseract OCR Engine
Tesseract OCR引擎是1995年UNLV Accuracy测试的前三名之一,在1995和2006年之间它的进展不大,但依然是当前精度最高的OCR引擎。这个源码可读取二进制、灰阶或彩色图片 并输出文字,内置一个TIFF阅读器可读取非压缩的TIFF文件,增加libtiff后也可读取压缩图片。指南 和问答 。
Neatx – Open Source NX server
Neatx是一个开源NX服务,类似NoMachine公司商业的NX服务。NX协议比VNX更强大,它们的区别主要在:
- NX是X11客户端所以不会发送位图
- NX可兼容X、VNC和Windows版的Remote Desktop
- NX可缓存数据
- NX安装简单
另外一个可选的项目可以看看Google的FreeNx 。
PSVM
它是这个文件 的代码,这是一个SVM的“支持所有核心”的版本,可多机并行运行,实例见此 。
GO
Google开发的新编程语言,谷奥有报道 。
The Google Collections Library for Java
这是一系列与Java 5以及更高版本有关的库,Google花钱给买过来了。
Google styleguide
每个主流的开源项目 都有它自己的向导形式,比如一系列的演示代码。如果这些代码都按照“Style”的形式来演示,会更友好。
本文转自:http://blog.csdn.net/hkx1n/article/details/6176573
posted @
2014-03-28 09:43 王海光 阅读(642) |
评论 (0) |
编辑 收藏