IPBS_Station/SDK/Environment/IMUI/WindowOS/CWidget.cpp
2025-09-05 08:44:30 +08:00

481 lines
12 KiB
C++

#include "CWidget.h"
#include <utility>
#define STB_IMAGE_IMPLEMENTATION //必须加上
#include "../ImGui/stb_image.h"
#ifdef _WIN32
HBITMAP CreateIconFrom(unsigned char* rgbaImage,int width,int height)
{
// 创建DC和位图信息头
HDC hdcMem = CreateCompatibleDC(nullptr);
BITMAPINFO bmi = { 0 };
bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
bmi.bmiHeader.biWidth = width;
bmi.bmiHeader.biHeight = -height; // 负值表示位图从上到下
bmi.bmiHeader.biPlanes = 1;
bmi.bmiHeader.biBitCount = 32;
bmi.bmiHeader.biCompression = BI_RGB;
bmi.bmiHeader.biSizeImage = 0;
bmi.bmiHeader.biClrUsed = 0;
bmi.bmiHeader.biClrImportant = 0;
// 创建位图
HBITMAP hBitmap = CreateDIBSection(hdcMem, reinterpret_cast<const BITMAPINFO *>(&bmi.bmiHeader), DIB_RGB_COLORS, (void**)&rgbaImage, nullptr, 0);
if (!hBitmap) {
stbi_image_free(rgbaImage);
DeleteDC(hdcMem);
return nullptr;
}
// 选择位图到内存DC
HBITMAP hOldBitmap = (HBITMAP)SelectObject(hdcMem, hBitmap);
// 清理
SelectObject(hdcMem, hOldBitmap);
DeleteDC(hdcMem);
return hBitmap;
}
#else
#endif
CWidget::CWidget(CWidget *parent)
{
}
void CWidget::Show(CApplication* pApplication)
{
#ifdef _WIN32
#else
#endif
if(pApplication != nullptr)
{
this->argc = pApplication->argc;
this->argv = pApplication->argv;
pApplication->window = this->window;
}
WindowCreateFlag = WindowCreate();
if(NoFrameFlag)
{
SetRound(Round);
}
UI_ID::Font_Init(18);
ImGui::GetStyle().WindowPadding = {0,0};
ImGui::GetStyle().ItemSpacing = {0,0};
ImGui::GetStyle().WindowBorderSize = 0;
//onInit();
if(Fun_onInit)
{
Fun_onInit();
}
if (datas && Iconbool)
{
Icon[0].height = height;
Icon[0].width = width;
Icon[0].pixels = datas;
Icon[1].height = height;
Icon[1].width = width;
Icon[1].pixels = datas;
glfwSetWindowIcon(window, 2, Icon);
stbi_image_free(datas);
}
else
{
// 图像加载失败
printf("Icon loading Eorr!\n");
}
InitGL();
while(NewFrame())
{
Framequeue = false;
funcMutex.lock();
while (!funcQueue.empty())
{
auto func = funcQueue.front();
func();
funcQueue.pop();
}
funcMutex.unlock();
Framequeue = true;
glfwPollEvents();
ImGui_ImplOpenGL3_NewFrame();
ImGui_ImplGlfw_NewFrame();
ImGui::NewFrame();
if(IsWindowFlag)
{
ImGui::SetNextWindowPos({0,0});
this->Size = GetSize();
if(this->ReSize.width != Size.width && this->ReSize.height != Size.height)
{
this->Size = this->Size = this->GetSize();
this->ReSize = Size;
if(Fun_ReSize)
{
std::thread(Fun_ReSize).detach();
}
}
ImGui::PushStyleColor(ImGuiCol_WindowBg,this->Background);
ImGui::PushStyleColor(ImGuiCol_ChildBg,this->Background);
ImGui::PushStyleVar(ImGuiStyleVar_WindowRounding,(float)Round);
ImGui::PushStyleVar(ImGuiStyleVar_ChildRounding,(float)Round);
ImGui::SetNextWindowSize({this->Size.width,this->Size.height});
ImGui::Begin(Title.c_str(),nullptr,ImGuiWindowFlags_NoTitleBar
| ImGuiWindowFlags_NoBackground | ImGuiWindowFlags_NoResize);
ImGui::BeginChild(std::string("_AD" + Title).c_str() ,{this->Size.width,this->Size.height});
}
KeyEventHandler();
//onParent();
if(Fun_onParent)
{
Fun_onParent();
}
if(IsWindowFlag)
{
ImGui::EndChild();
if (ImGui::IsMouseClicked(IMBN::ImGuiMouseButton_Left) && ImGui::IsItemHovered())
{
if (task_Click_L)
{
AB = std::thread(task_Click_L);
AB.detach();
}
}
else if (ImGui::IsMouseClicked(IMBN::ImGuiMouseButton_Right) && ImGui::IsItemHovered())
{
if (task_Click_R)
{
ABC = std::thread(task_Click_R);
ABC.detach();
}
}
else if (ImGui::IsMouseClicked(IMBN::ImGuiMouseButton_Middle) && ImGui::IsItemHovered())
{
if (task_Click_M)
{
ABCD = std::thread(task_Click_M);
ABCD.detach();
}
}
ImGui::End();
ImGui::PopStyleVar(2);
ImGui::PopStyleColor(2);
MouseXY = ImGui::GetMousePos();
if(ImGui::IsMouseReleased(IMBN::ImGuiMouseButton_Left))
{
mouseButtonPressed = 0;
}
}
Render();
Threading::Sleep(this->FrameTime);
}
SwapBuffers();
}
void CWidget::SetSize(HSize size)
{
this->Size = size;
#ifdef _WIN32
#else
#endif
if(window != nullptr)
{
glfwSetWindowSize(this->window,size.width,size.height);
}
}
void CWidget::SetPosition(HPos position)
{
this->Pos = position;
#ifdef _WIN32
#else
#endif
if(window != nullptr)
{
glfwSetWindowPos(window,Pos.X,Pos.Y);
}
}
void CWidget::SetOpacity(int opacity)
{
this->opacity = (float)opacity;
if(!NoFrameFlag) {
#ifdef _WIN32
#else
#endif
if(window != nullptr)
{
//glfwSetWindowOpacity(window,this->opacity);
auto da = this->Background;
this->Background = RGBA(255,255,255,opacity);
this->Background.x = da.x;
this->Background.y = da.y;
this->Background.z = da.z;
}
}
}
HPos CWidget::GetPosition()
{
#ifdef _WIN32
#else
#endif
if(window != nullptr)
{
int xx,yy;
glfwGetWindowPos(window,&xx,&yy);
this->Pos.X = xx;
this->Pos.Y = yy;
}
return this->Pos;
}
HSize CWidget::GetSize()
{
#ifdef _WIN32
#else
#endif
if(window != nullptr)
{
int xx,yy;
glfwGetWindowSize(window,&xx,&yy);
this->Size = {(float)xx,(float)yy};
}
return this->Size;
}
bool CWidget::SetIcon(const unsigned char* Mem,const int MemSize)
{
datas = stbi_load_from_memory(Mem, MemSize, &width, &height, &nrChannels, 3);
#ifdef _WIN32
hicon = (HICON)CreateIconFrom(datas,width,height);
#else
#endif
Iconbool = true;
return true;
}
void CWidget::MouveWindow()
{
#ifdef _WIN32
auto hwnd = glfwGetWin32Window(window);
::GetWindowRect(hwnd, &r1);
::GetCursorPos(&dragStartPos);
XY.x = (float)(dragStartPos.x - r1.left);
XY.y = (float)(dragStartPos.y - r1.top);
mouseButtonPressed = true;
int w = Size.width;
int h = Size.height;
std::thread([this,w,h,hwnd]()
{
while (mouseButtonPressed)
{
// 计算鼠标移动的距离
::GetCursorPos(&dragStartPos);
this->Pos.X = (float)((float)dragStartPos.x - XY.x);
this->Pos.Y = (float)((float)dragStartPos.y - XY.y);
::MoveWindow(hwnd, (int)this->Pos.X, (int)this->Pos.Y, w, h, TRUE);
}
}).detach();
#else
// 获取当前鼠标位置和窗口位置
double xpos, ypos;
glfwGetCursorPos(window, &xpos, &ypos);
int windowX, windowY;
glfwGetWindowPos(window, &windowX, &windowY);
// 保存初始位置和窗口位置
mouseInitialX = (int)xpos;
mouseInitialY = (int)ypos;
windowLastX = windowX;
windowLastY = windowY;
mouseButtonPressed = 1;
std::thread([this]()
{
while (mouseButtonPressed)
{
// 计算鼠标移动的距离
int dx = (int)MouseXY.x - mouseInitialX;
int dy = (int)MouseXY.y - mouseInitialY;
// 应用阻尼来平滑移动
int newX = windowLastX + (int)(dx * damping);
int newY = windowLastY + (int)(dy * damping);
display = glfwGetX11Display();
glfwSetWindowPos(window, newX, newY);
windowLastX = newX;
windowLastY = newY;
#ifdef __linux__
std::this_thread::sleep_for(std::chrono::milliseconds(25));
#endif
}
}).detach();
while(mouseButtonPressed);
#endif
}
void CWidget::SetRound(int x)
{
if(NoFrameFlag)
{
Round = x;
}
}
void CWidget::SetBackground(RGBA rgba)
{
this->Background = rgba;
}
RGBA CWidget::GetBackground()
{
return this->Background;
}
void CWidget::SetNoFrame()
{
this->NoFrameFlag = true;
}
unsigned char* CWidget::LoadIMGMemory(char const *filename, int *x, int *y, int *comp, int req_comp)
{
return stbi_load(filename,x,y,comp,req_comp);
}
unsigned char* CWidget::LoadIMGMemory(const unsigned char *buffer, int len, int *x, int *y, int *comp, int req_comp)
{
return stbi_load_from_memory(buffer,len,x,y,comp,req_comp);
}
void CWidget::SetDamping(float d)
{
this->damping = d;
}
void CWidget::Close()
{
if(Fun_Close)
{
Fun_Close();
}
exit(0);
}
void CWidget::SetCenter()
{
#ifdef _WIN32
// 获取屏幕尺寸
int screenWidth = GetSystemMetrics(SM_CXSCREEN);
int screenHeight = GetSystemMetrics(SM_CYSCREEN);
// 计算窗口位置和大小
int windowWidth = (int)Size.width;
int windowHeight = (int)Size.height;
int windowX = (screenWidth - windowWidth) / 2;
int windowY = (screenHeight - windowHeight) / 2;
this->SetPosition({(float)windowX, (float)windowY});
#else
if(WindowCreateFlag)
{
int width = Size.width, height = Size.height;
int xpos = (mode->width - width) / 2;
int ypos = (mode->height - height) / 2;
SetPosition({(float)xpos,(float)ypos});
}
else
{
CenterFlag = true;
}
#endif
}
bool CWidget::SetIcon(const char* path)
{
#ifdef _WIN32
hicon = (HICON)LoadImage( // returns a HANDLE so we have to cast to HICON
nullptr, // hInstance must be nullptr when loading from a file
path, // the icon file name
IMAGE_ICON, // specifies that the file is an icon
0, // width of the image (we'll specify default later on)
0, // height of the image
LR_LOADFROMFILE| // we want to load a file (as opposed to a resource)
LR_DEFAULTSIZE| // default metrics based on the type (IMAGE_ICON, 32x32)
LR_SHARED // let the system release the handle when it's no longer used
);
#else
datas = stbi_load(path, &width, &height, &nrChannels, 0);
#endif
Iconbool = true;
return true;
}
void CWidget::SetNewFrameTime(int ms)
{
this->FrameTime = ms;
}
void CWidget::KeyEventHandler()
{
#ifdef IMGUI_DISABLE_OBSOLETE_KEYIO
struct funcs { static bool IsLegacyNativeDupe(ImGuiKey) { return false; } };
#else
struct funcs
{
static bool IsLegacyNativeDupe(ImGuiKey key)
{
return key >= 0 && key < 512 && ImGui::GetIO().KeyMap[key] != -1;
}
};
#endif
for (ImGuiKey key = ImGuiKey_KeysData_OFFSET; key < ImGuiKey_COUNT; key = (ImGuiKey)(key + 1))
{
if (funcs::IsLegacyNativeDupe(key) || !ImGui::IsKeyDown(key))
continue;
if(DefaultKeyFun)
{
std::thread(DefaultKeyFun,ImGui::GetKeyName(key),KeyMode::KeyDown).detach();
}
}
for (ImGuiKey key = ImGuiKey_KeysData_OFFSET; key < ImGuiKey_COUNT; key = (ImGuiKey)(key + 1))
{
if (funcs::IsLegacyNativeDupe(key) || !ImGui::IsKeyPressed(key))
continue;
if(DefaultKeyFun)
{
std::thread(DefaultKeyFun,ImGui::GetKeyName(key),KeyMode::KeyPressed).detach();
}
}
for (ImGuiKey key = ImGuiKey_KeysData_OFFSET; key < ImGuiKey_COUNT; key = (ImGuiKey)(key + 1))
{
if (funcs::IsLegacyNativeDupe(key) || !ImGui::IsKeyReleased(key))
continue;
if(DefaultKeyFun)
{
std::thread(DefaultKeyFun,ImGui::GetKeyName(key),KeyMode::KeyReleased).detach();
}
}
}
void CWidget::SetWindowTitle(CCString title) {
this->Title = std::move(title);
}