mirror of
https://github.com/smallmain/cocos-enhance-kit.git
synced 2025-10-09 16:55:23 +00:00
初始化
This commit is contained in:
115
cocos2d-x/cocos/ui/edit-box/EditBox-android.cpp
Normal file
115
cocos2d-x/cocos/ui/edit-box/EditBox-android.cpp
Normal file
@@ -0,0 +1,115 @@
|
||||
/****************************************************************************
|
||||
Copyright (c) 2018 Xiamen Yaji Software Co., Ltd.
|
||||
|
||||
http://www.cocos2d-x.org
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
|
||||
#include "EditBox.h"
|
||||
#include "platform/android/jni/JniHelper.h"
|
||||
#include "cocos/scripting/js-bindings/jswrapper/SeApi.h"
|
||||
#include "cocos/scripting/js-bindings/manual/jsb_global.h"
|
||||
|
||||
#ifndef JCLS_EDITBOX
|
||||
#define JCLS_EDITBOX "org/cocos2dx/lib/Cocos2dxEditBox"
|
||||
#endif
|
||||
|
||||
#ifndef ORG_EDITBOX_CLASS_NAME
|
||||
#define ORG_EDITBOX_CLASS_NAME org_cocos2dx_lib_Cocos2dxEditBox
|
||||
#endif
|
||||
#define JNI_EDITBOX(FUNC) JNI_METHOD1(ORG_EDITBOX_CLASS_NAME,FUNC)
|
||||
|
||||
|
||||
NS_CC_BEGIN
|
||||
|
||||
void EditBox::show(const cocos2d::EditBox::ShowInfo& showInfo)
|
||||
{
|
||||
JniHelper::callStaticVoidMethod(JCLS_EDITBOX,
|
||||
"showNative",
|
||||
showInfo.defaultValue,
|
||||
showInfo.maxLength,
|
||||
showInfo.isMultiline,
|
||||
showInfo.confirmHold,
|
||||
showInfo.confirmType,
|
||||
showInfo.inputType);
|
||||
}
|
||||
|
||||
void EditBox::hide()
|
||||
{
|
||||
JniHelper::callStaticVoidMethod(JCLS_EDITBOX, "hideNative");
|
||||
}
|
||||
|
||||
void EditBox::updateRect(int x, int y, int width, int height)
|
||||
{
|
||||
// not supported ...
|
||||
}
|
||||
|
||||
NS_CC_END
|
||||
|
||||
namespace
|
||||
{
|
||||
se::Value textInputCallback;
|
||||
|
||||
void getTextInputCallback()
|
||||
{
|
||||
if (! textInputCallback.isUndefined())
|
||||
return;
|
||||
|
||||
auto global = se::ScriptEngine::getInstance()->getGlobalObject();
|
||||
se::Value jsbVal;
|
||||
if (global->getProperty("jsb", &jsbVal) && jsbVal.isObject())
|
||||
{
|
||||
jsbVal.toObject()->getProperty("onTextInput", &textInputCallback);
|
||||
// free globle se::Value before ScriptEngine clean up
|
||||
se::ScriptEngine::getInstance()->addBeforeCleanupHook([](){
|
||||
textInputCallback.setUndefined();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
void callJSFunc(const std::string& type, const jstring& text)
|
||||
{
|
||||
getTextInputCallback();
|
||||
|
||||
se::AutoHandleScope scope;
|
||||
se::ValueArray args;
|
||||
args.push_back(se::Value(type));
|
||||
args.push_back(se::Value(cocos2d::JniHelper::jstring2string(text)));
|
||||
textInputCallback.toObject()->call(args, nullptr);
|
||||
}
|
||||
}
|
||||
|
||||
extern "C"
|
||||
{
|
||||
JNIEXPORT void JNICALL JNI_EDITBOX(onKeyboardInputNative)(JNIEnv* env, jclass, jstring text)
|
||||
{
|
||||
callJSFunc("input", text);
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL JNI_EDITBOX(onKeyboardCompleteNative)(JNIEnv* env, jclass, jstring text)
|
||||
{
|
||||
callJSFunc("complete", text);
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL JNI_EDITBOX(onKeyboardConfirmNative)(JNIEnv* env, jclass, jstring text)
|
||||
{
|
||||
callJSFunc("confirm", text);
|
||||
}
|
||||
}
|
482
cocos2d-x/cocos/ui/edit-box/EditBox-ios.mm
Normal file
482
cocos2d-x/cocos/ui/edit-box/EditBox-ios.mm
Normal file
@@ -0,0 +1,482 @@
|
||||
/****************************************************************************
|
||||
Copyright (c) 2018 Xiamen Yaji Software Co., Ltd.
|
||||
|
||||
http://www.cocos2d-x.org
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
#include "EditBox.h"
|
||||
#include "platform/CCApplication.h"
|
||||
#include "platform/ios/CCEAGLView-ios.h"
|
||||
#include "cocos/scripting/js-bindings/jswrapper/SeApi.h"
|
||||
#include "cocos/scripting/js-bindings/manual/jsb_global.h"
|
||||
|
||||
#import <UIKit/UITextField.h>
|
||||
#import <UIKit/UITextView.h>
|
||||
|
||||
#define TEXT_LINE_HEIGHT 40
|
||||
#define TEXT_VIEW_MAX_LINE_SHOWN 3
|
||||
#define BUTTON_HIGHT (TEXT_LINE_HEIGHT - 2)
|
||||
#define BUTTON_WIDTH 60
|
||||
|
||||
#define TO_TEXT_VIEW(textinput) ((UITextView*)textinput)
|
||||
#define TO_TEXT_FIELD(textinput) ((UITextField*)textinput)
|
||||
|
||||
/*************************************************************************
|
||||
Inner class declarations.
|
||||
************************************************************************/
|
||||
|
||||
// MARK: class declaration
|
||||
|
||||
@interface ButtonHandler : NSObject
|
||||
-(IBAction) buttonTapped:(UIButton *)button;
|
||||
@end
|
||||
|
||||
@interface KeyboardEventHandler : NSObject
|
||||
-(void)keyboardWillShow: (NSNotification*) notification;
|
||||
-(void)keyboardWillHide: (NSNotification*) notification;
|
||||
@end
|
||||
|
||||
@interface TextFieldDelegate : NSObject<UITextFieldDelegate>
|
||||
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string;
|
||||
- (void)textFieldDidChange:(UITextField *)textField;
|
||||
- (BOOL)textFieldShouldReturn:(UITextField *)textField;
|
||||
@end
|
||||
|
||||
@interface TextViewDelegate : NSObject<UITextViewDelegate>
|
||||
- (BOOL) textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text;
|
||||
- (void) textViewDidChange:(UITextView *)textView;
|
||||
@end
|
||||
|
||||
/*************************************************************************
|
||||
Global variables and functions.
|
||||
************************************************************************/
|
||||
|
||||
// MARK: global variables and functions
|
||||
|
||||
namespace
|
||||
{
|
||||
bool g_isMultiline = false;
|
||||
bool g_confirmHold = false;
|
||||
int g_maxLength = INT_MAX;
|
||||
KeyboardEventHandler* g_keyboardHandler = nil;
|
||||
|
||||
// "#1fa014", a color of dark green, was used for confirm button background
|
||||
static UIColor* g_darkGreen = [UIColor colorWithRed:31/255.0 green:160/255.0 blue:20/255.0 alpha:0.8];
|
||||
|
||||
UITextField* g_textField = nil;
|
||||
TextFieldDelegate* g_textFieldDelegate = nil;
|
||||
UIButton* g_textFieldConfirmButton = nil;
|
||||
ButtonHandler* g_textFieldConfirmButtonHandler = nil;
|
||||
|
||||
UITextView* g_textView = nil;
|
||||
TextViewDelegate* g_textViewDelegate = nil;
|
||||
UIButton* g_textViewConfirmButton = nil;
|
||||
ButtonHandler* g_textViewConfirmButtonHander = nil;
|
||||
|
||||
UIView* getCurrentView()
|
||||
{
|
||||
if (g_isMultiline)
|
||||
return g_textView;
|
||||
else
|
||||
return g_textField;
|
||||
}
|
||||
|
||||
NSString* getCurrentText()
|
||||
{
|
||||
if (g_isMultiline)
|
||||
return g_textView.text;
|
||||
else
|
||||
return g_textField.text;
|
||||
}
|
||||
|
||||
void setText(NSString* text)
|
||||
{
|
||||
if (g_isMultiline)
|
||||
g_textView.text = text;
|
||||
else
|
||||
g_textField.text = text;
|
||||
}
|
||||
|
||||
se::Value textInputCallback;
|
||||
|
||||
void getTextInputCallback()
|
||||
{
|
||||
if (! textInputCallback.isUndefined())
|
||||
return;
|
||||
|
||||
auto global = se::ScriptEngine::getInstance()->getGlobalObject();
|
||||
se::Value jsbVal;
|
||||
if (global->getProperty("jsb", &jsbVal) && jsbVal.isObject())
|
||||
{
|
||||
jsbVal.toObject()->getProperty("onTextInput", &textInputCallback);
|
||||
// free globle se::Value before ScriptEngine clean up
|
||||
se::ScriptEngine::getInstance()->addBeforeCleanupHook([](){
|
||||
textInputCallback.setUndefined();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
void callJSFunc(const std::string& type, const std::string& text)
|
||||
{
|
||||
getTextInputCallback();
|
||||
|
||||
se::AutoHandleScope scope;
|
||||
se::ValueArray args;
|
||||
args.push_back(se::Value(type));
|
||||
args.push_back(se::Value(text));
|
||||
textInputCallback.toObject()->call(args, nullptr);
|
||||
}
|
||||
|
||||
int getTextInputHeight()
|
||||
{
|
||||
if (g_isMultiline)
|
||||
return TEXT_LINE_HEIGHT * TEXT_VIEW_MAX_LINE_SHOWN;
|
||||
else
|
||||
return TEXT_LINE_HEIGHT;
|
||||
}
|
||||
|
||||
void createButton(UIButton** button, ButtonHandler** buttonHandler, const CGRect& viewRect, const std::string& title)
|
||||
{
|
||||
ButtonHandler *btnHandler = [[ButtonHandler alloc] init];
|
||||
UIButton* btn = [UIButton buttonWithType:UIButtonTypeRoundedRect];
|
||||
[btn addTarget:btnHandler action:@selector(buttonTapped:)
|
||||
forControlEvents:UIControlEventTouchUpInside];
|
||||
btn.frame = CGRectMake(0, 0, BUTTON_WIDTH, BUTTON_HIGHT);
|
||||
btn.backgroundColor = g_darkGreen;
|
||||
[btn setTitle: [NSString stringWithUTF8String:title.c_str()]
|
||||
forState:UIControlStateNormal];
|
||||
[btn setTitleColor: [UIColor whiteColor]
|
||||
forState:UIControlStateNormal];
|
||||
|
||||
*button = btn;
|
||||
*buttonHandler = btnHandler;
|
||||
}
|
||||
|
||||
void setTexFiledKeyboardType(UITextField* textField, const std::string& inputType)
|
||||
{
|
||||
if (0 == inputType.compare("password"))
|
||||
{
|
||||
textField.secureTextEntry = TRUE;
|
||||
textField.keyboardType = UIKeyboardTypeDefault;
|
||||
}
|
||||
else
|
||||
{
|
||||
textField.secureTextEntry = FALSE;
|
||||
if (0 == inputType.compare("email"))
|
||||
textField.keyboardType = UIKeyboardTypeEmailAddress;
|
||||
else if (0 == inputType.compare("number"))
|
||||
textField.keyboardType = UIKeyboardTypeDecimalPad;
|
||||
else if (0 == inputType.compare("url"))
|
||||
textField.keyboardType = UIKeyboardTypeURL;
|
||||
else if (0 == inputType.compare("text"))
|
||||
textField.keyboardType = UIKeyboardTypeDefault;
|
||||
}
|
||||
}
|
||||
|
||||
void setTextFieldReturnType(UITextField* textField, const std::string& returnType)
|
||||
{
|
||||
if (0 == returnType.compare("done"))
|
||||
textField.returnKeyType = UIReturnKeyDone;
|
||||
else if (0 == returnType.compare("next"))
|
||||
textField.returnKeyType = UIReturnKeyNext;
|
||||
else if (0 == returnType.compare("search"))
|
||||
textField.returnKeyType = UIReturnKeySearch;
|
||||
else if (0 == returnType.compare("go"))
|
||||
textField.returnKeyType = UIReturnKeyGo;
|
||||
else if (0 == returnType.compare("send"))
|
||||
textField.returnKeyType = UIReturnKeySend;
|
||||
}
|
||||
|
||||
NSString* getConfirmButtonTitle(const std::string& returnType)
|
||||
{
|
||||
NSString* titleKey = [NSString stringWithUTF8String: returnType.c_str()];
|
||||
return NSLocalizedString(titleKey, nil); // get i18n string to be the title
|
||||
}
|
||||
|
||||
void initTextField(const CGRect& rect, const cocos2d::EditBox::ShowInfo& showInfo)
|
||||
{
|
||||
if (! g_textField)
|
||||
{
|
||||
g_textField = [[UITextField alloc] initWithFrame:rect];
|
||||
g_textField.textColor = [UIColor blackColor];
|
||||
g_textField.backgroundColor = [UIColor whiteColor];
|
||||
[g_textField setBorderStyle:UITextBorderStyleLine];
|
||||
g_textField.backgroundColor = [UIColor whiteColor];
|
||||
|
||||
g_textFieldDelegate = [[TextFieldDelegate alloc] init];
|
||||
g_textField.delegate = g_textFieldDelegate;
|
||||
|
||||
// Assign the overlay button to a stored text field
|
||||
createButton(&g_textFieldConfirmButton, &g_textFieldConfirmButtonHandler, rect, showInfo.confirmType);
|
||||
g_textField.rightView = g_textFieldConfirmButton;
|
||||
g_textField.rightViewMode = UITextFieldViewModeAlways;
|
||||
[g_textField addTarget:g_textFieldDelegate action:@selector(textFieldDidChange:) forControlEvents:UIControlEventEditingChanged];
|
||||
}
|
||||
|
||||
g_textField.frame = rect;
|
||||
setTextFieldReturnType(g_textField, showInfo.confirmType);
|
||||
setTexFiledKeyboardType(g_textField, showInfo.inputType);
|
||||
g_textField.text = [NSString stringWithUTF8String: showInfo.defaultValue.c_str()];
|
||||
[g_textFieldConfirmButton setTitle:getConfirmButtonTitle(showInfo.confirmType) forState:UIControlStateNormal];
|
||||
}
|
||||
|
||||
void initTextView(const CGRect& viewRect, const CGRect& btnRect, const cocos2d::EditBox::ShowInfo& showInfo)
|
||||
{
|
||||
if (!g_textView)
|
||||
{
|
||||
g_textView = [[UITextView alloc] initWithFrame:btnRect];
|
||||
g_textView.textColor = [UIColor blackColor];
|
||||
g_textView.backgroundColor = [UIColor whiteColor];
|
||||
g_textViewDelegate = [[TextViewDelegate alloc] init];
|
||||
g_textView.delegate = g_textViewDelegate;
|
||||
|
||||
createButton(&g_textViewConfirmButton, &g_textViewConfirmButtonHander, btnRect, showInfo.confirmType);
|
||||
g_textViewConfirmButton.frame = CGRectMake(viewRect.size.width - BUTTON_WIDTH, 0, BUTTON_WIDTH, BUTTON_HIGHT);
|
||||
[g_textView addSubview:g_textViewConfirmButton];
|
||||
}
|
||||
|
||||
g_textView.frame = btnRect;
|
||||
g_textView.text = [NSString stringWithUTF8String: showInfo.defaultValue.c_str()];
|
||||
[g_textViewConfirmButton setTitle:getConfirmButtonTitle(showInfo.confirmType) forState:UIControlStateNormal];
|
||||
}
|
||||
|
||||
CGRect getSafeAreaRect()
|
||||
{
|
||||
UIView* view = (UIView*)cocos2d::Application::getInstance()->getView();
|
||||
CGRect viewRect = view.frame;
|
||||
|
||||
// safeAreaInsets is avaible since iOS 11.
|
||||
if (@available(iOS 11.0, *))
|
||||
{
|
||||
auto safeAreaInsets = view.safeAreaInsets;
|
||||
|
||||
UIInterfaceOrientation sataus = [UIApplication sharedApplication].statusBarOrientation;
|
||||
if (UIInterfaceOrientationLandscapeLeft == sataus) {
|
||||
viewRect.origin.x = 0;
|
||||
viewRect.size.width -= safeAreaInsets.right;
|
||||
}
|
||||
else {
|
||||
viewRect.origin.x += safeAreaInsets.left;
|
||||
viewRect.size.width -= safeAreaInsets.left;
|
||||
}
|
||||
}
|
||||
|
||||
return viewRect;
|
||||
}
|
||||
|
||||
void addTextInput(const cocos2d::EditBox::ShowInfo& showInfo)
|
||||
{
|
||||
auto safeAreaRect = getSafeAreaRect();
|
||||
int height = getTextInputHeight();
|
||||
CGRect rect = CGRectMake(safeAreaRect.origin.x,
|
||||
safeAreaRect.size.height - height,
|
||||
safeAreaRect.size.width,
|
||||
height);
|
||||
if (showInfo.isMultiline)
|
||||
initTextView(safeAreaRect, rect, showInfo);
|
||||
else
|
||||
initTextField(rect, showInfo);
|
||||
|
||||
UIView* textInput = getCurrentView();
|
||||
UIView* view = (UIView*)cocos2d::Application::getInstance()->getView();
|
||||
[view addSubview:textInput];
|
||||
[textInput becomeFirstResponder];
|
||||
}
|
||||
|
||||
void addKeyboardEventLisnters()
|
||||
{
|
||||
if (!g_keyboardHandler)
|
||||
g_keyboardHandler = [[KeyboardEventHandler alloc] init];
|
||||
|
||||
[[NSNotificationCenter defaultCenter] addObserver:g_keyboardHandler
|
||||
selector:@selector(keyboardWillShow:)
|
||||
name:UIKeyboardWillShowNotification
|
||||
object:nil];
|
||||
|
||||
[[NSNotificationCenter defaultCenter] addObserver:g_keyboardHandler
|
||||
selector:@selector(keyboardWillHide:)
|
||||
name:UIKeyboardWillHideNotification
|
||||
object:nil];
|
||||
}
|
||||
|
||||
void removeKeyboardEventLisnters()
|
||||
{
|
||||
if (!g_keyboardHandler)
|
||||
return;
|
||||
|
||||
[[NSNotificationCenter defaultCenter] removeObserver:g_keyboardHandler];
|
||||
}
|
||||
}
|
||||
|
||||
/*************************************************************************
|
||||
Class implementations.
|
||||
************************************************************************/
|
||||
|
||||
// MARK: class implementation
|
||||
|
||||
@implementation KeyboardEventHandler
|
||||
-(void)keyboardWillShow: (NSNotification*) notification
|
||||
{
|
||||
UIView* textView = getCurrentView();
|
||||
if (!textView)
|
||||
return;
|
||||
|
||||
NSDictionary* keyboardInfo = [notification userInfo];
|
||||
NSValue* keyboardFrame = [keyboardInfo objectForKey:UIKeyboardFrameEndUserInfoKey];
|
||||
CGSize kbSize = [keyboardFrame CGRectValue].size;
|
||||
|
||||
int textHeight = getTextInputHeight();
|
||||
|
||||
CGRect screenRect = getSafeAreaRect();
|
||||
textView.frame = CGRectMake(screenRect.origin.x,
|
||||
screenRect.size.height - textHeight - kbSize.height,
|
||||
screenRect.size.width,
|
||||
textHeight);
|
||||
}
|
||||
|
||||
-(void)keyboardWillHide: (NSNotification*) notification
|
||||
{
|
||||
NSDictionary *info = [notification userInfo];
|
||||
|
||||
CGRect beginKeyboardRect = [[info objectForKey:UIKeyboardFrameBeginUserInfoKey] CGRectValue];
|
||||
CGRect endKeyboardRect = [[info objectForKey:UIKeyboardFrameEndUserInfoKey] CGRectValue];
|
||||
CGFloat yOffset = endKeyboardRect.origin.y - beginKeyboardRect.origin.y;
|
||||
|
||||
if (yOffset <= 0) {
|
||||
cocos2d::EditBox::complete();
|
||||
cocos2d::EditBox::hide();
|
||||
}
|
||||
}
|
||||
@end
|
||||
|
||||
@implementation TextFieldDelegate
|
||||
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string
|
||||
{
|
||||
// REFINE: check length limit before text changed
|
||||
return YES;
|
||||
}
|
||||
|
||||
- (void)textFieldDidChange:(UITextField *)textField
|
||||
{
|
||||
if (textField.markedTextRange != nil)
|
||||
return;
|
||||
|
||||
// check length limit after text changed, a little rude
|
||||
if (textField.text.length > g_maxLength) {
|
||||
NSRange rangeIndex = [textField.text rangeOfComposedCharacterSequenceAtIndex:g_maxLength];
|
||||
auto newText = [textField.text substringToIndex:rangeIndex.location];
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
textField.text = newText;
|
||||
});
|
||||
}
|
||||
|
||||
callJSFunc("input", [textField.text UTF8String]);
|
||||
}
|
||||
|
||||
-(BOOL) textFieldShouldReturn:(UITextField *)textField
|
||||
{
|
||||
cocos2d::EditBox::complete();
|
||||
return YES;
|
||||
}
|
||||
@end
|
||||
|
||||
@implementation ButtonHandler
|
||||
-(IBAction) buttonTapped:(UIButton *)button
|
||||
{
|
||||
const std::string text([getCurrentText() UTF8String]);
|
||||
callJSFunc("confirm", text);
|
||||
if (!g_confirmHold)
|
||||
cocos2d::EditBox::complete();
|
||||
}
|
||||
@end
|
||||
|
||||
|
||||
@implementation TextViewDelegate
|
||||
- (BOOL) textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text
|
||||
{
|
||||
// REFINE: check length limit before text changed
|
||||
return YES;
|
||||
}
|
||||
|
||||
- (void)textViewDidChange:(UITextView *)textView
|
||||
{
|
||||
if (textView.markedTextRange != nil)
|
||||
return;
|
||||
|
||||
// check length limit after text changed, a little rude
|
||||
if (textView.text.length > g_maxLength) {
|
||||
auto newText = [textView.text substringToIndex:g_maxLength];
|
||||
// fix undo crash
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
textView.text = newText;
|
||||
});
|
||||
}
|
||||
|
||||
callJSFunc("input", [textView.text UTF8String]);
|
||||
}
|
||||
@end
|
||||
|
||||
/*************************************************************************
|
||||
Implementation of EditBox.
|
||||
************************************************************************/
|
||||
|
||||
// MARK: EditBox
|
||||
|
||||
NS_CC_BEGIN
|
||||
|
||||
void EditBox::show(const cocos2d::EditBox::ShowInfo& showInfo)
|
||||
{
|
||||
// Should initialize them at first.
|
||||
g_maxLength = showInfo.maxLength;
|
||||
g_isMultiline = showInfo.isMultiline;
|
||||
g_confirmHold = showInfo.confirmHold;
|
||||
|
||||
[(CCEAGLView*)cocos2d::Application::getInstance()->getView() setPreventTouchEvent:true];
|
||||
addKeyboardEventLisnters();
|
||||
addTextInput(showInfo);
|
||||
}
|
||||
|
||||
void EditBox::hide()
|
||||
{
|
||||
removeKeyboardEventLisnters();
|
||||
|
||||
UIView* view = getCurrentView();
|
||||
if (view)
|
||||
{
|
||||
[view removeFromSuperview];
|
||||
[view resignFirstResponder];
|
||||
}
|
||||
|
||||
[(CCEAGLView*)cocos2d::Application::getInstance()->getView() setPreventTouchEvent:false];
|
||||
}
|
||||
|
||||
void EditBox::updateRect(int x, int y, int width, int height)
|
||||
{
|
||||
// not supported ...
|
||||
}
|
||||
|
||||
void EditBox::complete()
|
||||
{
|
||||
NSString* text = getCurrentText();
|
||||
callJSFunc("complete", [text UTF8String]);
|
||||
EditBox::hide();
|
||||
}
|
||||
|
||||
NS_CC_END
|
340
cocos2d-x/cocos/ui/edit-box/EditBox-mac.mm
Normal file
340
cocos2d-x/cocos/ui/edit-box/EditBox-mac.mm
Normal file
@@ -0,0 +1,340 @@
|
||||
/****************************************************************************
|
||||
Copyright (c) 2018 Xiamen Yaji Software Co., Ltd.
|
||||
|
||||
http://www.cocos2d-x.org
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
#include "EditBox.h"
|
||||
#include "platform/desktop/CCGLView-desktop.h"
|
||||
#include "platform/CCApplication.h"
|
||||
#include "cocos/scripting/js-bindings/jswrapper/SeApi.h"
|
||||
#include "cocos/scripting/js-bindings/manual/jsb_global.h"
|
||||
|
||||
/*************************************************************************
|
||||
Forward declaration of global functions.
|
||||
************************************************************************/
|
||||
namespace
|
||||
{
|
||||
void callJSFunc(const std::string& type, const std::string& text);
|
||||
}
|
||||
|
||||
/*************************************************************************
|
||||
Global variables.
|
||||
************************************************************************/
|
||||
namespace
|
||||
{
|
||||
NSTextView* g_textView = nil;
|
||||
NSScrollView* g_scrollView = nil;
|
||||
NSTextField* g_textField = nil;
|
||||
NSSecureTextField* g_secureTextField = nil;
|
||||
bool g_isMultiline = false;
|
||||
bool g_isPassword = false;
|
||||
int g_maxLength = INT_MAX;
|
||||
se::Value g_textInputCallback;
|
||||
}
|
||||
|
||||
/*************************************************************************
|
||||
TextViewDelegate
|
||||
************************************************************************/
|
||||
@interface TextViewDelegate : NSObject<NSTextViewDelegate>
|
||||
@end
|
||||
|
||||
@implementation TextViewDelegate
|
||||
// Get notification when something is input.
|
||||
- (void) textDidChange:(NSNotification *)notification
|
||||
{
|
||||
callJSFunc("input", [[g_textView.textStorage string] UTF8String]);
|
||||
}
|
||||
|
||||
// Max length limitaion
|
||||
- (BOOL) textView:(NSTextView *)textView
|
||||
shouldChangeTextInRange:(NSRange)affectedCharRange
|
||||
replacementString:(NSString *)replacementString
|
||||
{
|
||||
NSUInteger newLength = [textView.string length] + [replacementString length] - affectedCharRange.length;
|
||||
if (newLength > g_maxLength)
|
||||
return FALSE;
|
||||
|
||||
if (!g_isMultiline && [replacementString containsString:@"\n"])
|
||||
return FALSE;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
@end
|
||||
|
||||
/*************************************************************************
|
||||
TextFieldDelegate
|
||||
************************************************************************/
|
||||
@interface TextFieldDelegate: NSObject<NSTextFieldDelegate>
|
||||
@end
|
||||
|
||||
@implementation TextFieldDelegate
|
||||
- (void)controlTextDidChange:(NSNotification *)notification
|
||||
{
|
||||
NSTextField *textField = [notification object];
|
||||
callJSFunc("input", [textField.stringValue UTF8String]);
|
||||
}
|
||||
@end
|
||||
|
||||
/*************************************************************************
|
||||
TextFieldFormatter: used for textfield length limitation.
|
||||
************************************************************************/
|
||||
@interface TextFieldFormatter : NSFormatter
|
||||
{
|
||||
int maxLength;
|
||||
}
|
||||
- (void)setMaximumLength:(int)len;
|
||||
@end
|
||||
|
||||
@implementation TextFieldFormatter
|
||||
|
||||
- (id)init
|
||||
{
|
||||
if(self = [super init])
|
||||
maxLength = INT_MAX;
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)setMaximumLength:(int)len
|
||||
{
|
||||
maxLength = len;
|
||||
}
|
||||
|
||||
- (NSString *)stringForObjectValue:(id)object
|
||||
{
|
||||
return (NSString *)object;
|
||||
}
|
||||
|
||||
- (BOOL)getObjectValue:(id *)object forString:(NSString *)string errorDescription:(NSString **)error
|
||||
{
|
||||
*object = string;
|
||||
return YES;
|
||||
}
|
||||
|
||||
- (BOOL)isPartialStringValid:(NSString **)partialStringPtr
|
||||
proposedSelectedRange:(NSRangePointer)proposedSelRangePtr
|
||||
originalString:(NSString *)origString
|
||||
originalSelectedRange:(NSRange)origSelRange
|
||||
errorDescription:(NSString **)error
|
||||
{
|
||||
if ([*partialStringPtr length] > maxLength)
|
||||
return NO;
|
||||
|
||||
return YES;
|
||||
}
|
||||
|
||||
- (NSAttributedString *)attributedStringForObjectValue:(id)anObject withDefaultAttributes:(NSDictionary *)attributes
|
||||
{
|
||||
return nil;
|
||||
}
|
||||
@end
|
||||
|
||||
/*************************************************************************
|
||||
Implementation of global helper functions.
|
||||
************************************************************************/
|
||||
namespace
|
||||
{
|
||||
void getTextInputCallback()
|
||||
{
|
||||
if (! g_textInputCallback.isUndefined())
|
||||
return;
|
||||
|
||||
auto global = se::ScriptEngine::getInstance()->getGlobalObject();
|
||||
se::Value jsbVal;
|
||||
if (global->getProperty("jsb", &jsbVal) && jsbVal.isObject())
|
||||
{
|
||||
jsbVal.toObject()->getProperty("onTextInput", &g_textInputCallback);
|
||||
// free globle se::Value before ScriptEngine clean up
|
||||
se::ScriptEngine::getInstance()->addBeforeCleanupHook([](){
|
||||
g_textInputCallback.setUndefined();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
void callJSFunc(const std::string& type, const std::string& text)
|
||||
{
|
||||
getTextInputCallback();
|
||||
|
||||
se::AutoHandleScope scope;
|
||||
se::ValueArray args;
|
||||
args.push_back(se::Value(type));
|
||||
args.push_back(se::Value(text));
|
||||
g_textInputCallback.toObject()->call(args, nullptr);
|
||||
}
|
||||
|
||||
void initTextView(const cocos2d::EditBox::ShowInfo& showInfo)
|
||||
{
|
||||
CGRect rect = CGRectMake(showInfo.x, showInfo.y, showInfo.width, showInfo.height);
|
||||
if (! g_textView)
|
||||
{
|
||||
g_textView = [[NSTextView alloc] initWithFrame:rect];
|
||||
g_textView.textColor = [NSColor blackColor];
|
||||
g_textView.backgroundColor = [NSColor whiteColor];
|
||||
g_textView.editable = TRUE;
|
||||
g_textView.hidden = FALSE;
|
||||
g_textView.delegate = [[TextViewDelegate alloc] init];
|
||||
|
||||
g_scrollView = [[NSScrollView alloc] initWithFrame:rect];
|
||||
[g_scrollView setBorderType:NSNoBorder];
|
||||
[g_scrollView setHasVerticalScroller:TRUE];
|
||||
[g_scrollView setAutoresizingMask:NSViewWidthSizable | NSViewHeightSizable];
|
||||
[g_scrollView setDocumentView:g_textView];
|
||||
}
|
||||
g_textView.string = [NSString stringWithUTF8String:showInfo.defaultValue.c_str()];
|
||||
g_textView.frame = rect;
|
||||
g_scrollView.frame = rect;
|
||||
|
||||
auto glfwWindow = ((cocos2d::GLView*)cocos2d::Application::getInstance()->getView())->getGLFWWindow();
|
||||
NSWindow* nsWindow = glfwGetCocoaWindow(glfwWindow);
|
||||
[nsWindow.contentView addSubview:g_scrollView];
|
||||
[nsWindow makeFirstResponder:g_scrollView];
|
||||
}
|
||||
|
||||
void doInitTextField(NSTextField* textField, const CGRect& rect, const cocos2d::EditBox::ShowInfo& showInfo)
|
||||
{
|
||||
textField.editable = TRUE;
|
||||
textField.wantsLayer = TRUE;
|
||||
textField.frame = rect;
|
||||
textField.stringValue = [NSString stringWithUTF8String:showInfo.defaultValue.c_str()];
|
||||
[(TextFieldFormatter*)textField.formatter setMaximumLength: showInfo.maxLength];
|
||||
|
||||
auto glfwWindow = ((cocos2d::GLView*)cocos2d::Application::getInstance()->getView())->getGLFWWindow();
|
||||
NSWindow* nsWindow = glfwGetCocoaWindow(glfwWindow);
|
||||
[nsWindow.contentView addSubview:textField];
|
||||
[textField becomeFirstResponder];
|
||||
}
|
||||
|
||||
void initTextField(const cocos2d::EditBox::ShowInfo& showInfo)
|
||||
{
|
||||
CGRect rect = CGRectMake(showInfo.x, showInfo.y, showInfo.width, showInfo.height);
|
||||
|
||||
// Use NSSecureTextField for password, use NSTextField for others.
|
||||
if (g_isPassword)
|
||||
{
|
||||
if (! g_secureTextField)
|
||||
{
|
||||
g_secureTextField = [[NSSecureTextField alloc] init];
|
||||
g_secureTextField.textColor = [NSColor blackColor];
|
||||
g_secureTextField.backgroundColor = [NSColor whiteColor];
|
||||
g_secureTextField.delegate = [[TextFieldDelegate alloc] init];
|
||||
g_secureTextField.formatter = [[TextFieldFormatter alloc] init];
|
||||
}
|
||||
doInitTextField(g_secureTextField, rect, showInfo);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (! g_textField)
|
||||
{
|
||||
g_textField = [[NSTextField alloc] init];
|
||||
g_textField.textColor = [NSColor blackColor];
|
||||
g_textField.backgroundColor = [NSColor whiteColor];
|
||||
g_textField.delegate = [[TextFieldDelegate alloc] init];
|
||||
g_textField.formatter = [[TextFieldFormatter alloc] init];
|
||||
}
|
||||
doInitTextField(g_textField, rect, showInfo);
|
||||
}
|
||||
}
|
||||
|
||||
void init(const cocos2d::EditBox::ShowInfo& showInfo)
|
||||
{
|
||||
if (showInfo.isMultiline)
|
||||
initTextView(showInfo);
|
||||
else
|
||||
initTextField(showInfo);
|
||||
}
|
||||
}
|
||||
|
||||
/*************************************************************************
|
||||
Implementation of EditBox.
|
||||
************************************************************************/
|
||||
|
||||
NS_CC_BEGIN
|
||||
|
||||
void EditBox::show(const ShowInfo& showInfo)
|
||||
{
|
||||
g_isMultiline = showInfo.isMultiline;
|
||||
g_maxLength = showInfo.maxLength;
|
||||
g_isPassword = showInfo.inputType == "password";
|
||||
|
||||
init(showInfo);
|
||||
((GLView*)Application::getInstance()->getView())->setIsEditboxEditing(true);
|
||||
}
|
||||
|
||||
|
||||
void EditBox::hide()
|
||||
{
|
||||
if (g_scrollView)
|
||||
[g_scrollView removeFromSuperview];
|
||||
|
||||
if (g_textField)
|
||||
{
|
||||
[g_textField resignFirstResponder];
|
||||
[g_textField removeFromSuperview];
|
||||
}
|
||||
|
||||
if (g_secureTextField)
|
||||
{
|
||||
[g_secureTextField resignFirstResponder];
|
||||
[g_secureTextField removeFromSuperview];
|
||||
}
|
||||
|
||||
((GLView*)Application::getInstance()->getView())->setIsEditboxEditing(false);
|
||||
}
|
||||
|
||||
void EditBox::complete()
|
||||
{
|
||||
if (g_isMultiline)
|
||||
callJSFunc("complete", [[g_textView.textStorage string] UTF8String]);
|
||||
else
|
||||
{
|
||||
if (g_isPassword)
|
||||
callJSFunc("complete", [g_secureTextField.stringValue UTF8String]);
|
||||
else
|
||||
callJSFunc("complete", [g_textField.stringValue UTF8String]);
|
||||
}
|
||||
|
||||
EditBox::hide();
|
||||
}
|
||||
|
||||
void EditBox::updateRect(int x, int y, int width, int height) {
|
||||
CGRect rect = CGRectMake(x, y, width, height);
|
||||
auto glfwWindow = ((cocos2d::GLView*)cocos2d::Application::getInstance()->getView())->getGLFWWindow();
|
||||
NSWindow* nsWindow = glfwGetCocoaWindow(glfwWindow);
|
||||
const auto& subviews = [nsWindow.contentView subviews];
|
||||
if (g_scrollView && [subviews containsObject:g_scrollView])
|
||||
{
|
||||
g_scrollView.frame = rect;
|
||||
if (g_textView)
|
||||
{
|
||||
g_textView.frame = rect;
|
||||
}
|
||||
}
|
||||
else if (g_textField && [subviews containsObject:g_textField])
|
||||
{
|
||||
g_textField.frame = rect;
|
||||
}
|
||||
else if (g_secureTextField && [subviews containsObject:g_secureTextField])
|
||||
{
|
||||
g_secureTextField.frame = rect;
|
||||
}
|
||||
}
|
||||
|
||||
NS_CC_END
|
220
cocos2d-x/cocos/ui/edit-box/EditBox-win32.cpp
Normal file
220
cocos2d-x/cocos/ui/edit-box/EditBox-win32.cpp
Normal file
@@ -0,0 +1,220 @@
|
||||
/****************************************************************************
|
||||
Copyright (c) 2018 Xiamen Yaji Software Co., Ltd.
|
||||
|
||||
http://www.cocos2d-x.org
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
#include "EditBox.h"
|
||||
#include "platform/CCApplication.h"
|
||||
#include "platform/desktop/CCGLView-desktop.h"
|
||||
#include "cocos/scripting/js-bindings/jswrapper/SeApi.h"
|
||||
#include "cocos/scripting/js-bindings/manual/jsb_global.h"
|
||||
#include <windows.h>
|
||||
#include <locale>
|
||||
#include <codecvt>
|
||||
#include <stdlib.h>
|
||||
|
||||
NS_CC_BEGIN
|
||||
|
||||
/*************************************************************************
|
||||
Global variables and functions.
|
||||
************************************************************************/
|
||||
|
||||
namespace
|
||||
{
|
||||
HWND g_hwndEditBox = nullptr;
|
||||
WNDPROC g_prevMainWindowProc = nullptr;
|
||||
se::Value g_textInputCallback;
|
||||
|
||||
HWND getCocosWindow()
|
||||
{
|
||||
auto glfwWindow = ((GLView*)Application::getInstance()->getView())->getGLFWWindow();
|
||||
return glfwGetWin32Window(glfwWindow);
|
||||
}
|
||||
|
||||
int getCocosWindowHeight()
|
||||
{
|
||||
HWND parent = getCocosWindow();
|
||||
RECT rect;
|
||||
GetClientRect(parent, &rect);
|
||||
return (rect.bottom - rect.top);
|
||||
}
|
||||
|
||||
void getTextInputCallback()
|
||||
{
|
||||
if (!g_textInputCallback.isUndefined())
|
||||
return;
|
||||
|
||||
auto global = se::ScriptEngine::getInstance()->getGlobalObject();
|
||||
se::Value jsbVal;
|
||||
if (global->getProperty("jsb", &jsbVal) && jsbVal.isObject())
|
||||
{
|
||||
jsbVal.toObject()->getProperty("onTextInput", &g_textInputCallback);
|
||||
// free globle se::Value before ScriptEngine clean up
|
||||
se::ScriptEngine::getInstance()->addBeforeCleanupHook([](){
|
||||
g_textInputCallback.setUndefined();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
void callJSFunc(const std::string& type, const std::string& text)
|
||||
{
|
||||
getTextInputCallback();
|
||||
|
||||
se::AutoHandleScope scope;
|
||||
se::ValueArray args;
|
||||
args.push_back(se::Value(type));
|
||||
args.push_back(se::Value(text));
|
||||
g_textInputCallback.toObject()->call(args, nullptr);
|
||||
}
|
||||
|
||||
std::string getText(HWND hwnd)
|
||||
{
|
||||
int length = GetWindowTextLength(hwnd);
|
||||
LPWSTR str = (LPWSTR)malloc(sizeof(WCHAR) * (length+1));
|
||||
GetWindowText(hwnd, str, length + 1);
|
||||
|
||||
std::wstring_convert<std::codecvt_utf8<wchar_t>> convert;
|
||||
std::string ret(convert.to_bytes(str));
|
||||
free(str);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
std::wstring str2ws(const std::string& text)
|
||||
{
|
||||
if (text.empty())
|
||||
return std::wstring();
|
||||
|
||||
int sz = MultiByteToWideChar(CP_UTF8, 0, &text[0], (int)text.size(), 0, 0);
|
||||
std::wstring res(sz, 0);
|
||||
MultiByteToWideChar(CP_UTF8, 0, &text[0], (int)text.size(), &res[0], sz);
|
||||
return res;
|
||||
}
|
||||
|
||||
LRESULT mainWindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
|
||||
{
|
||||
switch (msg)
|
||||
{
|
||||
case WM_LBUTTONDOWN:
|
||||
EditBox::complete();
|
||||
EditBox::hide();
|
||||
SetFocus(getCocosWindow());
|
||||
break;
|
||||
case WM_COMMAND:
|
||||
if (EN_CHANGE == HIWORD(wParam))
|
||||
callJSFunc("input", getText(g_hwndEditBox).c_str());
|
||||
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return CallWindowProc(g_prevMainWindowProc, hwnd, msg, wParam, lParam);
|
||||
}
|
||||
}
|
||||
|
||||
/*************************************************************************
|
||||
Implementation of EditBox.
|
||||
************************************************************************/
|
||||
void EditBox::show(const EditBox::ShowInfo& showInfo)
|
||||
{
|
||||
int windowHeight = getCocosWindowHeight();
|
||||
if (! g_hwndEditBox)
|
||||
{
|
||||
HWND parent = getCocosWindow();
|
||||
g_prevMainWindowProc = (WNDPROC)SetWindowLongPtr(parent, GWL_WNDPROC, (LONG_PTR)mainWindowProc);
|
||||
|
||||
UINT32 flags = WS_CHILD | ES_LEFT | WS_TABSTOP | ES_AUTOHSCROLL;
|
||||
if (showInfo.isMultiline)
|
||||
flags |= ES_MULTILINE;
|
||||
if (showInfo.inputType == "password")
|
||||
flags |= WS_EX_TRANSPARENT;
|
||||
|
||||
g_hwndEditBox = CreateWindowEx(
|
||||
WS_EX_WINDOWEDGE,
|
||||
L"EDIT",
|
||||
NULL,
|
||||
flags,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
parent,
|
||||
0,
|
||||
NULL,
|
||||
NULL);
|
||||
|
||||
if (! g_hwndEditBox)
|
||||
{
|
||||
wchar_t buffer[256] = { 0 };
|
||||
FormatMessageW(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
|
||||
NULL,
|
||||
GetLastError(),
|
||||
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
|
||||
buffer,
|
||||
sizeof(buffer) / sizeof(wchar_t),
|
||||
NULL);
|
||||
std::wstring_convert<std::codecvt_utf8<wchar_t>> convert;
|
||||
CCLOG("Can not create editbox: %s", convert.to_bytes(buffer).c_str());
|
||||
}
|
||||
}
|
||||
|
||||
::SendMessageW(g_hwndEditBox, EM_LIMITTEXT, showInfo.maxLength, 0);
|
||||
SetWindowPos(g_hwndEditBox,
|
||||
HWND_NOTOPMOST,
|
||||
showInfo.x,
|
||||
windowHeight - showInfo.y - showInfo.height,
|
||||
showInfo.width,
|
||||
showInfo.height,
|
||||
SWP_NOZORDER);
|
||||
|
||||
::SetWindowTextW(g_hwndEditBox, str2ws(showInfo.defaultValue).c_str());
|
||||
::PostMessage(g_hwndEditBox, WM_ACTIVATE, 0, 0);
|
||||
::ShowWindow(g_hwndEditBox, SW_SHOW);
|
||||
SetFocus(g_hwndEditBox);
|
||||
}
|
||||
|
||||
void EditBox::hide()
|
||||
{
|
||||
DestroyWindow(g_hwndEditBox);
|
||||
g_hwndEditBox = nullptr;
|
||||
|
||||
SetWindowLongPtr(getCocosWindow(), GWL_WNDPROC, (LONG_PTR)g_prevMainWindowProc);
|
||||
}
|
||||
|
||||
void EditBox::updateRect(int x, int y, int width, int height)
|
||||
{
|
||||
int windowHeight = getCocosWindowHeight();
|
||||
SetWindowPos(g_hwndEditBox,
|
||||
HWND_NOTOPMOST,
|
||||
x,
|
||||
windowHeight - y - height,
|
||||
width,
|
||||
height,
|
||||
SWP_NOZORDER);
|
||||
}
|
||||
|
||||
void EditBox::complete()
|
||||
{
|
||||
callJSFunc("complete", getText(g_hwndEditBox).c_str());
|
||||
}
|
||||
|
||||
NS_CC_END
|
57
cocos2d-x/cocos/ui/edit-box/EditBox.h
Normal file
57
cocos2d-x/cocos/ui/edit-box/EditBox.h
Normal file
@@ -0,0 +1,57 @@
|
||||
/****************************************************************************
|
||||
Copyright (c) 2018 Xiamen Yaji Software Co., Ltd.
|
||||
|
||||
http://www.cocos2d-x.org
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#include "base/ccMacros.h"
|
||||
|
||||
NS_CC_BEGIN
|
||||
|
||||
class EditBox
|
||||
{
|
||||
public:
|
||||
struct ShowInfo
|
||||
{
|
||||
std::string defaultValue = "";
|
||||
std::string confirmType = "";
|
||||
std::string inputType = "";
|
||||
int maxLength = 0;
|
||||
int x = 0;
|
||||
int y = 0;
|
||||
int width = 0;
|
||||
int height = 0;
|
||||
bool confirmHold = false;
|
||||
bool isMultiline = false;
|
||||
};
|
||||
|
||||
static void show(const ShowInfo& showInfo);
|
||||
static void hide();
|
||||
static void updateRect(int x, int y, int width, int height);
|
||||
|
||||
// It is internally to send a complete message to JS.
|
||||
// Don't call it by yourself untile you know the effect.
|
||||
static void complete();
|
||||
};
|
||||
|
||||
NS_CC_END
|
Reference in New Issue
Block a user