代码拉取完成,页面将自动刷新
#pragma once
#include "ControlBase.h"
class RichTextBox : public Control
{
public:
virtual UIClass Type() { return UIClass::UI_RichTextBox; }
bool IsContainer() override
{
return false;
}
bool InScroll = false;
D2D1_SIZE_F textSize = {0, 0};
D2D1_COLOR_F UnderMouseColor = Colors::White;
D2D1_COLOR_F SelectedBackColor = Colors::Blue;
D2D1_COLOR_F SelectedForeColor = Colors::White;
D2D1_COLOR_F FocusedColor = Colors::White;
D2D1_COLOR_F ScrollBackColor = Colors::LightGray;
D2D1_COLOR_F ScrollForeColor = Colors::DimGrey;
bool AllowMultiLine = false;
int SelectionStart = 0;
int SelectionEnd = 0;
float Boder = 1.5f;
float OffsetY = 0.0f;
float TextMargin = 5.0f;
RichTextBox(std::wstring text, int x, int y, int width = 120, int height = 24)
{
this->Text = text;
this->Location = POINT{x, y};
this->Size = SIZE{width, height};
this->BackColor = D2D1_COLOR_F{0.75f, 0.75f, 0.75f, 0.75f};
}
private:
void DrawScroll()
{
auto d2d = this->Render;
auto abslocation = this->AbsLocation;
auto font = this->Font ? this->Font : d2d->DefaultFontObject;
auto size = this->ActualSize();
float _render_width = this->Width - (TextMargin * 2.0f);
float _render_height = this->Height - (TextMargin * 2.0f);
if (textSize.height > _render_height)
{
int max_scroll = textSize.height - _render_height;
float scroll_block_height = _render_height / max_scroll;
if (scroll_block_height < MIN_SCROLL_BLOCK)
scroll_block_height = MIN_SCROLL_BLOCK;
float scroll_block_move_space = this->Height - scroll_block_height;
float yt = scroll_block_height * 0.5f;
float yb = this->Height - (scroll_block_height * 0.5f);
float per = (float)this->OffsetY / (float)max_scroll;
float scroll_tmp_y = per * scroll_block_move_space;
float scroll_block_top = scroll_tmp_y;
d2d->FillRoundRect(abslocation.x + (this->Width - 8.0f), abslocation.y, 8.0f, this->Height, this->ScrollBackColor, 4.0f);
d2d->FillRoundRect(abslocation.x + (this->Width - 8.0f), abslocation.y + scroll_block_top, 8.0f, scroll_block_height, this->ScrollForeColor, 4.0f);
}
}
void SetScrollByPos(float yof)
{
auto d2d = this->Render;
auto abslocation = this->AbsLocation;
auto font = this->Font ? this->Font : d2d->DefaultFontObject;
auto size = this->ActualSize();
float _render_width = this->Width - (TextMargin * 2.0f);
float _render_height = this->Height - (TextMargin * 2.0f);
if (textSize.height > _render_height)
{
yof -= this->Top;
yof -= this->TextMargin;
float per = yof / _render_height;
}
else
{
this->OffsetY = 0.0f;
}
}
void InputText(std::wstring input)
{
int sels = SelectionStart <= SelectionEnd ? SelectionStart : SelectionEnd;
int sele = SelectionEnd >= SelectionStart ? SelectionEnd : SelectionStart;
if (sele >= this->Text.size() && sels >= this->Text.size())
{
this->Text += input;
SelectionEnd = SelectionStart = this->Text.size();
}
else
{
List<wchar_t> tmp = List<wchar_t>();
tmp.AddRange((wchar_t *)this->Text.c_str(), this->Text.size());
if (sele > sels)
{
int sublen = sele - sels;
for (int i = 0; i < sublen; i++)
{
tmp.RemoveAt(sels);
}
for (int i = 0; i < input.size(); i++)
{
tmp.Insert(sels + i, input[i]);
}
SelectionEnd = SelectionStart = sels + (input.size());
tmp.Add(L'\0');
this->Text = std::wstring(tmp.Pointer());
}
else if (sele == sels && sele >= 0)
{
for (int i = 0; i < input.size(); i++)
{
tmp.Insert(sels + i, input[i]);
}
SelectionEnd += input.size();
SelectionStart += input.size();
tmp.Add(L'\0');
this->Text = std::wstring(tmp.Pointer());
}
else
{
this->Text += input;
SelectionEnd = SelectionStart = this->Text.size();
}
}
if (!this->AllowMultiLine)
{
List<wchar_t> tmp = List<wchar_t>();
tmp.AddRange((wchar_t *)this->Text.c_str(), this->Text.size() + 1);
for (int i = 0; i < tmp.Count; i++)
{
if (tmp[i] == L'\r' || tmp[i] == L'\n')
{
tmp[i] = L' ';
}
}
this->Text = std::wstring(tmp.Pointer());
}
}
void InputBack()
{
int sels = SelectionStart <= SelectionEnd ? SelectionStart : SelectionEnd;
int sele = SelectionEnd >= SelectionStart ? SelectionEnd : SelectionStart;
int selLen = sele - sels;
if (selLen > 0)
{
List<wchar_t> tmp = List<wchar_t>((wchar_t *)this->Text.c_str(), this->Text.size());
for (int i = 0; i < selLen; i++)
{
tmp.RemoveAt(sels);
}
tmp.Add(L'\0');
this->SelectionStart = this->SelectionEnd = sels;
this->Text = tmp.data();
}
else
{
if (sels > 0)
{
List<wchar_t> tmp = List<wchar_t>((wchar_t *)this->Text.c_str(), this->Text.size());
tmp.RemoveAt(sels - 1);
tmp.Add(L'\0');
this->SelectionStart = this->SelectionEnd = sels - 1;
this->Text = tmp.data();
}
}
}
void InputDelete()
{
int sels = SelectionStart <= SelectionEnd ? SelectionStart : SelectionEnd;
int sele = SelectionEnd >= SelectionStart ? SelectionEnd : SelectionStart;
int selLen = sele - sels;
if (selLen > 0)
{
List<wchar_t> tmp = List<wchar_t>((wchar_t *)this->Text.c_str(), this->Text.size());
for (int i = 0; i < selLen; i++)
{
tmp.RemoveAt(sels);
}
tmp.Add(L'\0');
this->SelectionStart = this->SelectionEnd = sels;
this->Text = tmp.data();
}
else
{
if (sels < this->Text.size())
{
List<wchar_t> tmp = List<wchar_t>((wchar_t *)this->Text.c_str(), this->Text.size());
tmp.RemoveAt(sels);
tmp.Add(L'\0');
this->SelectionStart = this->SelectionEnd = sels;
this->Text = tmp.data();
}
}
}
void UpdateScroll(bool arrival = false)
{
float render_width = this->Width - (TextMargin * 2.0f);
float render_height = this->Height - (TextMargin * 2.0f);
if (textSize.height > render_height)
render_width -= 8.0f;
auto font = this->Font ? this->Font : this->Render->DefaultFontObject;
auto lastSelect = font->HitTestTextRange(this->Text, render_width, render_height, (UINT32)SelectionEnd, (UINT32)0)[0];
if ((lastSelect.top + lastSelect.height) - OffsetY > render_height)
{
OffsetY = (lastSelect.top + lastSelect.height) - render_height;
}
if (lastSelect.top - OffsetY < 0.0f)
{
OffsetY = lastSelect.top;
}
}
public:
std::wstring GetSelectedString()
{
int sels = SelectionStart <= SelectionEnd ? SelectionStart : SelectionEnd;
int sele = SelectionEnd >= SelectionStart ? SelectionEnd : SelectionStart;
if (sele > sels)
{
std::wstring s = L"";
for (int i = sels; i < sele; i++)
{
s += this->Text[i];
}
return s;
}
return L"";
}
void Update() override
{
if (this->IsVisual == false)
return;
bool isUnderMouse = this->MostParent->UnderMouse == this;
auto d2d = this->Render;
auto font = this->Font ? this->Font : d2d->DefaultFontObject;
float render_width = this->Width - (TextMargin * 2.0f);
float render_height = this->Height - (TextMargin * 2.0f);
textSize = font->GetTextSize(this->Text, render_width, render_height);
if (textSize.height > render_height)
{
render_width -= 8.0f;
textSize = font->GetTextSize(this->Text, render_width, render_height);
}
auto abslocation = this->AbsLocation;
auto size = this->ActualSize();
auto absRect = this->AbsRect;
bool isSelected = this->MostParent->Selected == this;
d2d->PushDrawRect(absRect.left, absRect.top, absRect.right - absRect.left, absRect.bottom - absRect.top);
{
Control *tmpc = this;
List<Control *> need_render_background;
while (tmpc->BackColor.a < 1.0f)
{
tmpc = tmpc->Parent;
need_render_background.Add(tmpc);
}
if (this->BackColor.a < 1.0f)
{
for (int i = need_render_background.Count - 1; i >= 0; i--)
{
d2d->FillRect(abslocation.x, abslocation.y, size.cx, size.cy, need_render_background[i]->BackColor);
if (need_render_background[i]->Image)
{
need_render_background[i]->RenderImage();
}
}
}
d2d->FillRect(abslocation.x, abslocation.y, size.cx, size.cy, isSelected ? this->FocusedColor : this->BackColor);
if (this->Image)
{
this->RenderImage();
}
if (this->Text.size() > 0)
{
auto font = this->Font ? this->Font : d2d->DefaultFontObject;
if (isSelected)
{
int sels = SelectionStart <= SelectionEnd ? SelectionStart : SelectionEnd;
int sele = SelectionEnd >= SelectionStart ? SelectionEnd : SelectionStart;
int selLen = sele - sels;
auto selRange = font->HitTestTextRange(this->Text, render_width, render_height, (UINT32)sels, (UINT32)selLen);
if (selLen != 0)
{
for (auto sr : selRange)
{
d2d->FillRect(sr.left + abslocation.x + TextMargin, (sr.top + abslocation.y + TextMargin) - this->OffsetY, sr.width, sr.height, this->SelectedBackColor);
}
}
else
{
d2d->DrawLine(
{selRange[0].left + abslocation.x + TextMargin, (selRange[0].top + abslocation.y + TextMargin) - this->OffsetY},
{selRange[0].left + abslocation.x + TextMargin, (selRange[0].top + abslocation.y + selRange[0].height + TextMargin) - this->OffsetY},
Colors::Black);
}
d2d->DrawStringLayout(this->Text,
(float)abslocation.x + TextMargin, ((float)abslocation.y + TextMargin) - this->OffsetY,
render_width, render_height,
this->ForeColor,
DWRITE_TEXT_RANGE{(UINT32)sels, (UINT32)selLen},
this->SelectedForeColor,
font);
}
else
{
d2d->DrawStringLayout(this->Text,
(float)abslocation.x + TextMargin, ((float)abslocation.y + TextMargin) - this->OffsetY,
render_width, render_height,
this->ForeColor,
DWRITE_TEXT_RANGE{(UINT32)0, (UINT32)0},
this->SelectedForeColor,
font);
}
}
else
{
if (isSelected)
d2d->DrawLine(
{(float)TextMargin + (float)abslocation.x, (float)abslocation.y},
{(float)TextMargin + (float)abslocation.x, (float)abslocation.y + 16.0f},
Colors::Black);
}
this->DrawScroll();
d2d->DrawRect(abslocation.x, abslocation.y, size.cx, size.cy, this->BolderColor, this->Boder);
}
d2d->PopDrawRect();
}
bool ProcessMessage(UINT message, WPARAM wParam, LPARAM lParam, int xof, int yof) override
{
switch (message)
{
case WM_DROPFILES:
{
HDROP hDropInfo = HDROP(wParam);
UINT uFileNum = DragQueryFile(hDropInfo, 0xffffffff, NULL, 0);
TCHAR strFileName[MAX_PATH];
List<std::wstring> files;
for (UINT i = 0; i < uFileNum; i++)
{
DragQueryFile(hDropInfo, i, strFileName, MAX_PATH);
files.Add(strFileName);
}
DragFinish(hDropInfo);
if (files.Count > 0)
{
this->OnDropFile(this, files);
}
}
break;
case WM_MOUSEWHEEL: // mouse wheel
{
if (GET_WHEEL_DELTA_WPARAM(wParam) > 0)
{
if (this->OffsetY > 0)
{
this->OffsetY -= 10;
if (this->OffsetY < 0)
this->OffsetY = 0;
this->SingleUpdate();
}
}
else
{
auto font = this->Font ? this->Font : this->Render->DefaultFontObject;
float render_width = this->Width - (TextMargin * 2.0f);
float render_height = this->Height - (TextMargin * 2.0f);
if (textSize.height > render_height)
render_width -= 8.0f;
if (this->OffsetY < textSize.height - render_height)
{
this->OffsetY += 10;
if (this->OffsetY > textSize.height - render_height)
this->OffsetY = textSize.height - render_height;
this->SingleUpdate();
}
}
MouseEventArgs event_obj = MouseEventArgs(MouseButtons::MouseButtons_None, 0, xof, yof, GET_WHEEL_DELTA_WPARAM(wParam));
this->OnMouseWheel(this, event_obj);
}
break;
case WM_MOUSEMOVE: // mouse move
{
this->MostParent->UnderMouse = this;
if ((GetKeyState(VK_LBUTTON) & 0x8000) && this->MostParent->Selected == this)
{
auto font = this->Font ? this->Font : this->Render->DefaultFontObject;
float render_width = this->Width - (TextMargin * 2.0f);
float render_height = this->Height - (TextMargin * 2.0f);
if (textSize.height > render_height)
render_width -= 8.0f;
SelectionEnd = font->HitTestTextPosition(this->Text, render_width, render_height, xof - TextMargin, (yof + this->OffsetY) - TextMargin);
UpdateScroll();
this->SingleUpdate();
}
MouseEventArgs event_obj = MouseEventArgs(MouseButtons::MouseButtons_None, 0, xof, yof, HIWORD(wParam));
this->OnMouseMove(this, event_obj);
}
break;
case WM_LBUTTONDOWN: // mouse down
case WM_RBUTTONDOWN:
case WM_MBUTTONDOWN:
{
if (WM_LBUTTONDOWN == message)
{
if (this->MostParent->Selected != this)
{
auto lse = this->MostParent->Selected;
this->MostParent->Selected = this;
if (lse)
lse->SingleUpdate();
}
auto font = this->Font ? this->Font : this->Render->DefaultFontObject;
float render_width = this->Width - (TextMargin * 2.0f);
float render_height = this->Height - (TextMargin * 2.0f);
if (textSize.height > render_height)
render_width -= 8.0f;
this->SelectionStart = this->SelectionEnd = font->HitTestTextPosition(this->Text, render_width, render_height, xof - TextMargin, (yof + this->OffsetY) - TextMargin);
}
MouseEventArgs event_obj = MouseEventArgs(FromParamToMouseButtons(message), 0, xof, yof, HIWORD(wParam));
this->OnMouseDown(this, event_obj);
this->SingleUpdate();
}
break;
case WM_LBUTTONUP: // mouse up
case WM_RBUTTONUP:
case WM_MBUTTONUP:
{
if (this->MostParent->Selected == this)
{
float render_width = this->Width - (TextMargin * 2.0f);
float render_height = this->Height - (TextMargin * 2.0f);
if (textSize.height > render_height)
render_width -= 8.0f;
auto font = this->Font ? this->Font : this->Render->DefaultFontObject;
SelectionEnd = font->HitTestTextPosition(this->Text, render_width, render_height, xof - TextMargin, (yof + this->OffsetY) - TextMargin);
}
MouseEventArgs event_obj = MouseEventArgs(FromParamToMouseButtons(message), 0, xof, yof, HIWORD(wParam));
this->OnMouseUp(this, event_obj);
this->SingleUpdate();
}
break;
case WM_LBUTTONDBLCLK: // mouse double click
{
this->MostParent->Selected = this;
MouseEventArgs event_obj = MouseEventArgs(FromParamToMouseButtons(message), 0, xof, yof, HIWORD(wParam));
this->OnMouseDoubleClick(this, event_obj);
this->SingleUpdate();
}
break;
case WM_KEYDOWN: // keyboard down
{
auto pos = this->AbsLocation;
HIMC hImc = ImmGetContext(this->MostParent->Handle);
COMPOSITIONFORM form;
form.dwStyle = CFS_RECT;
form.ptCurrentPos = pos;
form.rcArea = RECT{pos.x, pos.y + this->Height, pos.x + 300, pos.y + 240};
ImmSetCompositionWindow(hImc, &form);
if (wParam == VK_DELETE)
{
this->InputDelete();
UpdateScroll();
}
else if (wParam == VK_RIGHT)
{
if (this->SelectionEnd < this->Text.size())
{
this->SelectionEnd = this->SelectionEnd + 1;
if ((GetKeyState(VK_SHIFT) & 0x8000) == false)
{
this->SelectionStart = this->SelectionEnd;
}
if (this->SelectionEnd > this->Text.size())
{
this->SelectionEnd = this->Text.size();
}
UpdateScroll();
}
}
else if (wParam == VK_LEFT)
{
if (this->SelectionEnd > 0)
{
this->SelectionEnd = this->SelectionEnd - 1;
if ((GetKeyState(VK_SHIFT) & 0x8000) == false)
{
this->SelectionStart = this->SelectionEnd;
}
if (this->SelectionEnd < 0)
{
this->SelectionEnd = 0;
}
UpdateScroll();
}
}
else if (wParam == VK_UP)
{
auto font = this->Font ? this->Font : this->Render->DefaultFontObject;
auto hit = font->HitTestTextRange(this->Text, FLT_MAX, this->Height, (UINT32)this->SelectionEnd, (UINT32)0);
this->SelectionEnd = font->HitTestTextPosition(this->Text, hit[0].left, hit[0].top - (font->GetTextSize(L"I").height * 0.5f));
if ((GetKeyState(VK_SHIFT) & 0x8000) == false)
{
this->SelectionStart = this->SelectionEnd;
}
if (this->SelectionEnd < 0)
{
this->SelectionEnd = 0;
}
UpdateScroll();
}
else if (wParam == VK_DOWN)
{
auto font = this->Font ? this->Font : this->Render->DefaultFontObject;
auto hit = font->HitTestTextRange(this->Text, FLT_MAX, this->Height, (UINT32)this->SelectionEnd, (UINT32)0);
this->SelectionEnd = font->HitTestTextPosition(this->Text, hit[0].left, hit[0].top + (font->GetTextSize(L"I").height * 1.5f));
if ((GetKeyState(VK_SHIFT) & 0x8000) == false)
{
this->SelectionStart = this->SelectionEnd;
}
if (this->SelectionEnd > this->Text.size())
{
this->SelectionEnd = this->Text.size();
}
UpdateScroll();
}
else if (wParam == VK_HOME)
{
auto font = this->Font ? this->Font : this->Render->DefaultFontObject;
auto hit = font->HitTestTextRange(this->Text, FLT_MAX, this->Height, (UINT32)this->SelectionEnd, (UINT32)0);
this->SelectionEnd = font->HitTestTextPosition(this->Text, 0, hit[0].top + (font->GetTextSize(L"I").height * 0.5f));
if ((GetKeyState(VK_SHIFT) & 0x8000) == false)
{
this->SelectionStart = this->SelectionEnd;
}
if (this->SelectionEnd < 0)
{
this->SelectionEnd = 0;
}
UpdateScroll();
}
else if (wParam == VK_END)
{
auto font = this->Font ? this->Font : this->Render->DefaultFontObject;
auto hit = font->HitTestTextRange(this->Text, FLT_MAX, this->Height, (UINT32)this->SelectionEnd, (UINT32)0);
this->SelectionEnd = font->HitTestTextPosition(this->Text, FLT_MAX, hit[0].top + (font->GetTextSize(L"I").height * 0.5f));
if ((GetKeyState(VK_SHIFT) & 0x8000) == false)
{
this->SelectionStart = this->SelectionEnd;
}
if (this->SelectionEnd > this->Text.size())
{
this->SelectionEnd = this->Text.size();
}
UpdateScroll();
}
else if (wParam == VK_PRIOR)
{
auto font = this->Font ? this->Font : this->Render->DefaultFontObject;
auto hit = font->HitTestTextRange(this->Text, FLT_MAX, this->Height, (UINT32)this->SelectionEnd, (UINT32)0);
this->SelectionEnd = font->HitTestTextPosition(this->Text, hit[0].left, hit[0].top - this->Height);
if ((GetKeyState(VK_SHIFT) & 0x8000) == false)
{
this->SelectionStart = this->SelectionEnd;
}
if (this->SelectionEnd < 0)
{
this->SelectionEnd = 0;
}
UpdateScroll(true);
}
else if (wParam == VK_NEXT)
{
auto font = this->Font ? this->Font : this->Render->DefaultFontObject;
auto hit = font->HitTestTextRange(this->Text, FLT_MAX, this->Height, (UINT32)this->SelectionEnd, (UINT32)0);
this->SelectionEnd = font->HitTestTextPosition(this->Text, hit[0].left, hit[0].top + this->Height);
if ((GetKeyState(VK_SHIFT) & 0x8000) == false)
{
this->SelectionStart = this->SelectionEnd;
}
if (this->SelectionEnd > this->Text.size())
{
this->SelectionEnd = this->Text.size();
}
UpdateScroll(true);
}
KeyEventArgs event_obj = KeyEventArgs((Keys)(wParam | 0));
this->OnKeyDown(this, event_obj);
this->SingleUpdate();
}
break;
case WM_CHAR:
{
wchar_t ch = (wchar_t)(wParam);
if (ch >= 32 && ch <= 126) // input char
{
const wchar_t c[] = {ch, L'\0'};
this->InputText(c);
UpdateScroll();
}
else if (ch == 13 && this->AllowMultiLine) // Enter
{
const wchar_t c[] = {L'\n', L'\0'};
this->InputText(c);
UpdateScroll();
}
else if (ch == 1) // ctrl+a
{
this->SelectionStart = 0;
this->SelectionEnd = this->Text.size();
UpdateScroll();
}
else if (ch == 8) // back
{
if (this->Text.size() > 0)
{
this->InputBack();
UpdateScroll();
}
}
else if (ch == 22) // crlt+v
{
if (OpenClipboard(this->MostParent->Handle))
{
if (IsClipboardFormatAvailable(CF_TEXT))
{
HANDLE hClip;
char *pBuf;
hClip = GetClipboardData(CF_TEXT);
pBuf = (char *)GlobalLock(hClip);
GlobalUnlock(hClip);
this->InputText(Convert::A2WS(pBuf));
UpdateScroll();
CloseClipboard();
}
}
}
else if (ch == 3) // crlt+c
{
AutoFree<char> s = Convert::W2A(this->GetSelectedString());
if (strlen(s) > 0 && OpenClipboard(this->MostParent->Handle))
{
EmptyClipboard();
HANDLE hData = GlobalAlloc(GMEM_MOVEABLE, strlen(s) + 1);
char *pData = (char *)GlobalLock(hData);
lstrcpyA(pData, s);
GlobalUnlock(hData);
SetClipboardData(CF_TEXT, hData);
CloseClipboard();
}
}
else if (ch == 24) // crlt+x
{
AutoFree<char> s = Convert::W2A(this->GetSelectedString());
if (strlen(s) > 0 && OpenClipboard(this->MostParent->Handle))
{
EmptyClipboard();
HANDLE hData = GlobalAlloc(GMEM_MOVEABLE, strlen(s) + 1);
char *pData = (char *)GlobalLock(hData);
lstrcpyA(pData, s);
GlobalUnlock(hData);
SetClipboardData(CF_TEXT, hData);
CloseClipboard();
}
this->InputBack();
}
this->SingleUpdate();
}
break;
case WM_IME_COMPOSITION: // imm action
{
if (lParam & GCS_RESULTSTR)
{
const auto GetMousePos = [](HWND Hwnd)
{
POINT p;
GetCursorPos(&p);
ScreenToClient(Hwnd, &p);
return p;
};
HIMC hIMC;
DWORD dwSize;
POINT pos = GetMousePos(this->MostParent->Handle);
hIMC = ImmGetContext(this->MostParent->Handle);
dwSize = ImmGetCompositionStringW(hIMC, GCS_RESULTSTR, NULL, 0);
dwSize += sizeof(WCHAR);
AutoFree<wchar_t> input(dwSize);
ImmGetCompositionStringW(hIMC, GCS_RESULTSTR, input, dwSize);
List<wchar_t> tmp;
for (DWORD i = 0; i < dwSize - 2; i++)
{
if (input[i] > 255)
{
tmp.Add(input[i]);
}
if (!input[i])
break;
}
tmp.Add(L'\0');
this->InputText(tmp.data());
ImmReleaseContext(this->MostParent->Handle, hIMC);
UpdateScroll();
this->SingleUpdate();
}
}
break;
case WM_KEYUP: // keyboard up
{
KeyEventArgs event_obj = KeyEventArgs((Keys)(wParam | 0));
this->OnKeyUp(this, event_obj);
this->SingleUpdate();
}
break;
}
return true;
}
};
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。