热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

第二人生的源码分析(九十二)LLLineEditor实现编辑框

在基于GUI界面的软件交互时,最基本的输入就是编辑框了,比如下图里输入的用户名称和密码,在游戏界面的编辑框里输入文字是一个高技术难度的问题,因为Windows输入法调用,也是难点之一
在基于 GUI界面的软件交互时,最基本的输入就是编辑框了,比如下图里输入的用户名称和密码,在游戏界面的编辑框里输入文字是一个高技术难度的问题,因为Windows输入法调用,也是难点之一。
 
那么在第二人生里的用户名称和密码的编辑框是怎么样实现的呢?现在就来分析这部份的代码,它的类继承关系如下:
class LLLineEditor
: public LLUICtrl, public LLEditMenuHandler, protected LLPreeditor
LLLineEditor继续了 LLUICtrl类,说明它是一个控件类。它的主要显示代码如下:
#001 void LLLineEditor::draw()
#002 {
 
判断不能显示时就直接返回去。
#003     if( !getVisible() )
#004     {
#005         return;
#006     }
#007 
 
获取显示字符串的长度。
#008     S32 text_len = mText.length();
#009 
 
如果是密码的方式,就只显示为星字符串。
#010     LLString saved_text;
#011     if (mDrawAsterixes)
#012     {
#013         saved_text = mText.getString();
#014         LLString text;
#015         for (S32 i = 0; i
#016         {
#017             text += '*';
#018         }
#019         mText = text;
#020     }
#021 
 
设置背景框的大小。
#022     // draw rectangle for the background
#023     LLRect background( 0, getRect().getHeight(), getRect().getWidth(), 0 );
 
根据边框的大小设置合适的显示背景。
#024     background.stretch( -mBorderThickness );
#025 
#026     LLColor4 bg_color = mReadOnlyBgColor;
#027 
 
显示背景的颜色。
#028     // drawing solids requires texturing be disabled
#029     {
#030         LLGLSNoTexture no_texture;
#031         // draw background for text
#032         if( !mReadOnly )
#033         {
#034             if( gFocusMgr.getKeyboardFocus() == this )
#035             {
#036                 bg_color = mFocusBgColor;
#037              }
#038             else
#039             {
#040                 bg_color = mWriteableBgColor;
#041             }
#042         }
#043         gl_rect_2d(background, bg_color);
#044     }
#045 
#046     // draw text
#047 
 
开始显示字符串。
#048     S32 cursor_bottom = background.mBottom + 1;
#049     S32 cursor_top = background.mTop - 1;
#050 
 
获取字体显示的颜色。
#051     LLColor4 text_color;
#052     if (!mReadOnly)
#053     {
#054         if (!getTentative())
#055         {
#056             text_color = mFgColor;
#057         }
#058         else
#059         {
#060             text_color = mTentativeFgColor;
#061         }
#062     }
#063     else
#064     {
#065         text_color = mReadOnlyFgColor;
#066     }
#067     LLColor4 label_color = mTentativeFgColor;
#068 
 
显示预先编辑的标志。
#069     if (hasPreeditString())
#070     {
#071         // Draw preedit markers. This needs to be before drawing letters.
#072         for (U32 i = 0; i
#073         {
#074             const S32 preedit_left = mPreeditPositions[i];
#075             const S32 preedit_right = mPreeditPositions[i + 1];
#076             if (preedit_right > mScrollHPos)
#077             {
#078                 S32 preedit_pixels_left = findPixelNearestPos(llmax(preedit_left, mScrollHPos) - getCursor());
#079                 S32 preedit_pixels_right = llmin(findPixelNearestPos(preedit_right - getCursor()), background.mRight);
#080                 if (preedit_pixels_left >= background.mRight)
#081                 {
#082                     break;
#083                 }
#084                 if (mPreeditStandouts[i])
#085                 {
#086                     gl_rect_2d(preedit_pixels_left + PREEDIT_STANDOUT_GAP,
#087                         background.mBottom + PREEDIT_STANDOUT_POSITION,
#088                         preedit_pixels_right - PREEDIT_STANDOUT_GAP - 1,
#089                         background.mBottom + PREEDIT_STANDOUT_POSITION -
#090 PREEDIT_STANDOUT_THICKNESS,
#091                         (text_color * PREEDIT_STANDOUT_BRIGHTNESS + bg_color * (1 -
#092 PREEDIT_STANDOUT_BRIGHTNESS)).setAlpha(1.0f));
#093                 }
#094                 else
#095                 {
#096                     gl_rect_2d(preedit_pixels_left + PREEDIT_MARKER_GAP,
#097                         background.mBottom + PREEDIT_MARKER_POSITION,
#098                         preedit_pixels_right - PREEDIT_MARKER_GAP - 1,
#099                         background.mBottom + PREEDIT_MARKER_POSITION -
#100 PREEDIT_MARKER_THICKNESS,
#101                         (text_color * PREEDIT_MARKER_BRIGHTNESS + bg_color * (1 -
#102 PREEDIT_MARKER_BRIGHTNESS)).setAlpha(1.0f));
#103                 }
#104             }
#105         }
#106     }
#107 
#108     S32 rendered_text = 0;
#109      F32 rendered_pixels_right = (F32)mMinHPixels;
#110      F32 text_bottom = (F32)background.mBottom + (F32)UI_LINEEDITOR_V_PAD;
#111 
 
 
显示选中的效果。
#112     if( (gFocusMgr.getKeyboardFocus() == this) && hasSelection() )
#113     {
#114         S32 select_left;
#115         S32 select_right;
#116         if( mSelectionStart
#117         {
#118             select_left = mSelectionStart;
#119             select_right = getCursor();
#120         }
#121         else
#122         {
#123             select_left = getCursor();
#124             select_right = mSelectionStart;
#125         }
#126        
#127         if( select_left > mScrollHPos )
#128         {
#129             // unselected, left side
#130             rendered_text = mGLFont->render(
#131                 mText, mScrollHPos,
#132                 rendered_pixels_right, text_bottom,
#133                 text_color,
#134                 LLFontGL::LEFT, LLFontGL::BOTTOM,
#135                 LLFontGL::NORMAL,
#136                 select_left - mScrollHPos,
#137                 mMaxHPixels - llround(rendered_pixels_right),
#138                 &rendered_pixels_right);
#139         }
#140        
#141         if( (rendered_pixels_right <(F32)mMaxHPixels) && (rendered_text
#142         {
#143             LLColor4 color(1.f - bg_color.mV[0], 1.f - bg_color.mV[1], 1.f - bg_color.mV[2], 1.f);
#144             // selected middle
#145             S32 width = mGLFont->getWidth(mText.getWString().c_str(), mScrollHPos + rendered_text, select_right - mScrollHPos - rendered_text);
#146             width = llmin(width, mMaxHPixels - llround(rendered_pixels_right));
#147             gl_rect_2d(llround(rendered_pixels_right), cursor_top, llround(rendered_pixels_right)+width, cursor_bottom, color);
#148 
 
显示相应选中的字符串。
#149             rendered_text += mGLFont->render(
#150                 mText, mScrollHPos + rendered_text,
#151                 rendered_pixels_right, text_bottom,
#152                 LLColor4( 1.f - text_color.mV[0], 1.f - text_color.mV[1], 1.f - text_color.mV[2], 1 ),
#153                 LLFontGL::LEFT, LLFontGL::BOTTOM,
#154                 LLFontGL::NORMAL,
#155                 select_right - mScrollHPos - rendered_text,
#156                 mMaxHPixels - llround(rendered_pixels_right),
#157                 &rendered_pixels_right);
#158         }
#159 
 
下面开始显示没有选中的字符串。
#160         if( (rendered_pixels_right <(F32)mMaxHPixels) && (rendered_text
#161         {
#162             // unselected, right side
#163             mGLFont->render(
#164                 mText, mScrollHPos + rendered_text,
#165                 rendered_pixels_right, text_bottom,
#166                 text_color,
#167                 LLFontGL::LEFT, LLFontGL::BOTTOM,
#168                 LLFontGL::NORMAL,
#169                 S32_MAX,
#170                 mMaxHPixels - llround(rendered_pixels_right),
#171                 &rendered_pixels_right);
#172         }
#173     }
#174     else
#175     {
#176         mGLFont->render(
#177             mText, mScrollHPos,
#178             rendered_pixels_right, text_bottom,
#179             text_color,
#180             LLFontGL::LEFT, LLFontGL::BOTTOM,
#181             LLFontGL::NORMAL,
#182             S32_MAX,
#183             mMaxHPixels - llround(rendered_pixels_right),
#184             &rendered_pixels_right);
#185     }
#186 
 
如果正在编辑过程中,设置 IME在合适的位置。
#187     // If we're editing...
#188     if( gFocusMgr.getKeyboardFocus() == this)
#189     {
#190         // (Flash the cursor every half second)
#191         if (gShowTextEditCursor && !mReadOnly)
#192         {
#193              F32 elapsed = mKeystrokeTimer.getElapsedTimeF32();
#194             if( (elapsed
#195             {
#196                 S32 cursor_left = findPixelNearestPos();
#197                 cursor_left -= UI_LINEEDITOR_CURSOR_THICKNESS / 2;
#198                 S32 cursor_right = cursor_left + UI_LINEEDITOR_CURSOR_THICKNESS;
#199                 if (LL_KIM_OVERWRITE == gKeyboard->getInsertMode() && !hasSelection())
#200                 {
#201                     const LLWString space(utf8str_to_wstring(LLString(" ")));
#202                     S32 wswidth = mGLFont->getWidth(space.c_str());
#203                     S32 width = mGLFont->getWidth(mText.getWString().c_str(), getCursor(), 1) + 1;
#204                     cursor_right = cursor_left + llmax(wswidth, width);
#205                 }
#206                 // Use same color as text for the Cursor
#207                 gl_rect_2d(cursor_left, cursor_top,
#208                     cursor_right, cursor_bottom, text_color);
#209                 if (LL_KIM_OVERWRITE == gKeyboard->getInsertMode() && !hasSelection())
#210                 {
#211                     mGLFont->render(mText, getCursor(), (F32)(cursor_left + UI_LINEEDITOR_CURSOR_THICKNESS / 2),
#212 text_bottom,
#213                         LLColor4( 1.f - text_color.mV[0], 1.f - text_color.mV[1], 1.f - text_color.mV[2], 1 ),
#214                         LLFontGL::LEFT, LLFontGL::BOTTOM,
#215                         LLFontGL::NORMAL,
#216                         1);
#217                 }
#218 
#219                 // Make sure the IME is in the right place
#220                 S32 pixels_after_scroll = findPixelNearestPos();    // RCalculcate for IME position
#221                 LLRect screen_pos = getScreenRect();
#222                 LLCoordGL ime_pos( screen_pos.mLeft + pixels_after_scroll, screen_pos.mTop - UI_LINEEDITOR_V_PAD );
#223 
#224                 ime_pos.mX = (S32) (ime_pos.mX * LLUI::sGLScaleFactor.mV[VX]);
#225                 ime_pos.mY = (S32) (ime_pos.mY * LLUI::sGLScaleFactor.mV[VY]);
#226                 getWindow()->setLanguageTextInput( ime_pos );
#227             }
#228         }
#229 
 
显示子窗口。
#230         // Draw children (border)
#231         //mBorder->setVisible(TRUE);
#232         mBorder->setKeyboardFocusHighlight( TRUE );
#233         LLView::draw();
#234         mBorder->setKeyboardFocusHighlight( FALSE );
#235         //mBorder->setVisible(FALSE);
#236     }
#237     else // does not have keyboard input
#238     {
 
没有字符串,就显示为一个标签。
#239         // draw label if no text provided
#240         if (0 == mText.length())
#241         {
#242             mGLFont->render(mLabel.getWString(), 0,
#243                             LABEL_HPAD, (F32)text_bottom,
#244                             label_color,
#245                             LLFontGL::LEFT, LLFontGL::BOTTOM,
#246                             LLFontGL::NORMAL,
#247                             S32_MAX,
#248                             mMaxHPixels - llround(rendered_pixels_right),
#249                             &rendered_pixels_right, FALSE);
#250         }
#251         // Draw children (border)
#252         LLView::draw();
#253     }
#254 
 
保存相应的密码字符串。
#255     if (mDrawAsterixes)
#256     {
#257         mText = saved_text;
#258     }
#259 }
 
上面的函数先设置背景的颜色,并且把背景显示,然后根据是否为密码,或者选择字符串来作合适的处理,最后显示相应的字符串,并且输入法窗口在合适的位置上。
 

推荐阅读
  • 本文介绍了在MFC下利用C++和MFC的特性动态创建窗口的方法,包括继承现有的MFC类并加以改造、插入工具栏和状态栏对象的声明等。同时还提到了窗口销毁的处理方法。本文详细介绍了实现方法并给出了相关注意事项。 ... [详细]
  • 如何在HTML中获取鼠标的当前位置
    本文介绍了在HTML中获取鼠标当前位置的三种方法,分别是相对于屏幕的位置、相对于窗口的位置以及考虑了页面滚动因素的位置。通过这些方法可以准确获取鼠标的坐标信息。 ... [详细]
  • 本文介绍了pack布局管理器在Perl/Tk中的使用方法及注意事项。通过调用pack()方法,可以控制部件在显示窗口中的位置和大小。同时,本文还提到了在使用pack布局管理器时,应注意将部件分组以便在水平和垂直方向上进行堆放。此外,还介绍了使用Frame部件或Toplevel部件来组织部件在窗口内的方法。最后,本文强调了在使用pack布局管理器时,应避免在中间切换到grid布局管理器,以免造成混乱。 ... [详细]
  • YOLOv7基于自己的数据集从零构建模型完整训练、推理计算超详细教程
    本文介绍了关于人工智能、神经网络和深度学习的知识点,并提供了YOLOv7基于自己的数据集从零构建模型完整训练、推理计算的详细教程。文章还提到了郑州最低生活保障的话题。对于从事目标检测任务的人来说,YOLO是一个熟悉的模型。文章还提到了yolov4和yolov6的相关内容,以及选择模型的优化思路。 ... [详细]
  • GetWindowLong函数
    今天在看一个代码里头写了GetWindowLong(hwnd,0),我当时就有点费解,靠,上网搜索函数原型说明,死活找不到第 ... [详细]
  • 在Android开发中,使用Picasso库可以实现对网络图片的等比例缩放。本文介绍了使用Picasso库进行图片缩放的方法,并提供了具体的代码实现。通过获取图片的宽高,计算目标宽度和高度,并创建新图实现等比例缩放。 ... [详细]
  • Spring源码解密之默认标签的解析方式分析
    本文分析了Spring源码解密中默认标签的解析方式。通过对命名空间的判断,区分默认命名空间和自定义命名空间,并采用不同的解析方式。其中,bean标签的解析最为复杂和重要。 ... [详细]
  • Linux重启网络命令实例及关机和重启示例教程
    本文介绍了Linux系统中重启网络命令的实例,以及使用不同方式关机和重启系统的示例教程。包括使用图形界面和控制台访问系统的方法,以及使用shutdown命令进行系统关机和重启的句法和用法。 ... [详细]
  • android listview OnItemClickListener失效原因
    最近在做listview时发现OnItemClickListener失效的问题,经过查找发现是因为button的原因。不仅listitem中存在button会影响OnItemClickListener事件的失效,还会导致单击后listview每个item的背景改变,使得item中的所有有关焦点的事件都失效。本文给出了一个范例来说明这种情况,并提供了解决方法。 ... [详细]
  • 本文介绍了OC学习笔记中的@property和@synthesize,包括属性的定义和合成的使用方法。通过示例代码详细讲解了@property和@synthesize的作用和用法。 ... [详细]
  • 后台获取视图对应的字符串
    1.帮助类后台获取视图对应的字符串publicclassViewHelper{将View输出为字符串(注:不会执行对应的ac ... [详细]
  • 拥抱Android Design Support Library新变化(导航视图、悬浮ActionBar)
    转载请注明明桑AndroidAndroid5.0Loollipop作为Android最重要的版本之一,为我们带来了全新的界面风格和设计语言。看起来很受欢迎࿰ ... [详细]
  • Go GUIlxn/walk 学习3.菜单栏和工具栏的具体实现
    本文介绍了使用Go语言的GUI库lxn/walk实现菜单栏和工具栏的具体方法,包括消息窗口的产生、文件放置动作响应和提示框的应用。部分代码来自上一篇博客和lxn/walk官方示例。文章提供了学习GUI开发的实际案例和代码示例。 ... [详细]
  • 本文详细介绍了Android中的坐标系以及与View相关的方法。首先介绍了Android坐标系和视图坐标系的概念,并通过图示进行了解释。接着提到了View的大小可以超过手机屏幕,并且只有在手机屏幕内才能看到。最后,作者表示将在后续文章中继续探讨与View相关的内容。 ... [详细]
  • 本文介绍了解决mysql 5.1启动问题的方法,通过修改my.ini文件中的相关配置,包括innodb_data_home_dir和skip-innodb等,可以解决启动问题。同时还介绍了如何调整内存池来存储metadata信息。 ... [详细]
author-avatar
手机用户2502907425_701
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有