1 Star 0 Fork 0

Janisa/GUI

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
文件
克隆/下载
PasswordBox.h 16.67 KB
一键复制 编辑 原始数据 按行查看 历史
Janisa 提交于 2024-07-09 19:24 +08:00 . 添加编译工程脚本
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582
#pragma once
#include "ControlBase.h"
class PasswordBox : public Control
{
public:
virtual UIClass Type() { return UIClass::UI_TextBox; }
bool IsContainer() override
{
return false;
}
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;
D2D1_SIZE_F textSize = {0, 0};
std::wstring MaskText;
int SelectionStart = 0;
int SelectionEnd = 0;
float Boder = 1.5f;
float OffsetX = 0.0f;
float TextMargin = 5.0f;
private:
void UpdatePWD()
{
MaskText.resize(0);
for (int i = 0; i < this->Text.size(); i++)
{
MaskText += L'*';
}
}
public:
PasswordBox(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};
UpdatePWD();
}
private:
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();
}
}
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());
UpdatePWD();
}
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();
}
}
UpdatePWD();
}
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();
}
}
UpdatePWD();
}
void UpdateScroll(bool arrival = false)
{
float render_width = this->Width - (TextMargin * 2.0f);
auto font = this->Font ? this->Font : this->Render->DefaultFontObject;
auto lastSelect = font->HitTestTextRange(this->MaskText, FLT_MAX, FLT_MAX, (UINT32)SelectionEnd, (UINT32)0)[0];
if ((lastSelect.left + lastSelect.width) - OffsetX > render_width)
{
OffsetX = (lastSelect.left + lastSelect.width) - render_width;
}
if (lastSelect.left - OffsetX < 0.0f)
{
OffsetX = lastSelect.left;
}
}
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_height = this->Height - (TextMargin * 2.0f);
textSize = font->GetTextSize(this->MaskText, FLT_MAX, render_height);
float OffsetY = (this->Height - textSize.height) * 0.5f;
if (OffsetY < 0.0f)
OffsetY = 0.0f;
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->MaskText, FLT_MAX, render_height, (UINT32)sels, (UINT32)selLen);
if (selLen != 0)
{
for (auto sr : selRange)
{
d2d->FillRect(sr.left + abslocation.x + TextMargin - OffsetX, (sr.top + abslocation.y) - OffsetY, sr.width, sr.height, this->SelectedBackColor);
}
}
else
{
d2d->DrawLine(
{selRange[0].left + abslocation.x + TextMargin - OffsetX, (selRange[0].top + abslocation.y) - OffsetY},
{selRange[0].left + abslocation.x + TextMargin - OffsetX, (selRange[0].top + abslocation.y + selRange[0].height) + OffsetY},
Colors::Black);
}
d2d->DrawStringLayout(this->MaskText,
(float)abslocation.x + TextMargin - OffsetX, ((float)abslocation.y) + OffsetY,
FLT_MAX, render_height,
this->ForeColor,
DWRITE_TEXT_RANGE{(UINT32)sels, (UINT32)selLen},
this->SelectedForeColor,
font);
}
else
{
d2d->DrawStringLayout(this->MaskText,
(float)abslocation.x + TextMargin - OffsetX, ((float)abslocation.y) + OffsetY,
FLT_MAX, render_height,
this->ForeColor,
DWRITE_TEXT_RANGE{(UINT32)0, (UINT32)0},
this->SelectedForeColor,
font);
}
}
else
{
if (isSelected)
d2d->DrawLine(
{(float)TextMargin + (float)abslocation.x - OffsetX, (float)abslocation.y + OffsetY},
{(float)TextMargin + (float)abslocation.x - OffsetX, (float)abslocation.y + OffsetY + 16.0f},
Colors::Black);
}
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
{
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_height = this->Height - (TextMargin * 2.0f);
SelectionEnd = font->HitTestTextPosition(this->MaskText, FLT_MAX, render_height, (xof - TextMargin) + this->OffsetX, yof - 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_height = this->Height - (TextMargin * 2.0f);
this->SelectionStart = this->SelectionEnd = font->HitTestTextPosition(this->MaskText, FLT_MAX, render_height, (xof - TextMargin) + this->OffsetX, yof - 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_height = this->Height - (TextMargin * 2.0f);
auto font = this->Font ? this->Font : this->Render->DefaultFontObject;
SelectionEnd = font->HitTestTextPosition(this->MaskText, FLT_MAX, render_height, (xof - TextMargin) + this->OffsetX, yof - 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_HOME)
{
auto font = this->Font ? this->Font : this->Render->DefaultFontObject;
auto hit = font->HitTestTextRange(this->MaskText, FLT_MAX, this->Height, (UINT32)this->SelectionEnd, (UINT32)0);
this->SelectionEnd = font->HitTestTextPosition(this->MaskText, 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->MaskText, FLT_MAX, this->Height, (UINT32)this->SelectionEnd, (UINT32)0);
this->SelectionEnd = font->HitTestTextPosition(this->MaskText, 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->MaskText, FLT_MAX, this->Height, (UINT32)this->SelectionEnd, (UINT32)0);
this->SelectionEnd = font->HitTestTextPosition(this->MaskText, 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->MaskText, FLT_MAX, this->Height, (UINT32)this->SelectionEnd, (UINT32)0);
this->SelectionEnd = font->HitTestTextPosition(this->MaskText, 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 == 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();
}
}
}
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;
}
};
Loading...
马建仓 AI 助手
尝试更多
代码解读
代码找茬
代码优化
C++
1
https://gitee.com/Janisa/gui.git
git@gitee.com:Janisa/gui.git
Janisa
gui
GUI
master

搜索帮助