├── .gitignore ├── CMakeLists.txt ├── LICENSE ├── README.md ├── backend ├── linux │ ├── SkinFileReader_linux.cpp │ ├── UIFileHelper.cpp │ ├── UIFont_linux.cpp │ ├── X11 │ │ ├── DispatchMessage.cpp │ │ ├── DispatchMessage.h │ │ ├── DisplayInstance.cpp │ │ ├── DisplayInstance.h │ │ ├── RoundRectRegion.cpp │ │ ├── RoundRectRegion.h │ │ ├── TimerContext.cpp │ │ ├── TimerContext.h │ │ ├── UIBaseWindow_X11.cpp │ │ ├── UICombo_X11.cpp │ │ ├── UICursor.cpp │ │ ├── UICursor.h │ │ ├── UIEdit.cpp │ │ ├── UIPaintManager_X11.cpp │ │ ├── UIRenderClip_X11.cpp │ │ ├── UIRenderEngine_X11.cpp │ │ ├── UIResourceMgr_X11.cpp │ │ ├── UIScrollBar.cpp │ │ ├── UIWindowImpBase_X11.cpp │ │ ├── X11Bitmap.h │ │ ├── X11HDC.cpp │ │ ├── X11HDC.h │ │ └── X11Window.h │ └── gtk │ │ ├── UIBaseWindow_gtk.cpp │ │ ├── UICombo_gtk.cpp │ │ ├── UIEdit_gtk.cpp │ │ ├── UIPaintManager_gtk.cpp │ │ ├── UIRenderClip_gtk.cpp │ │ ├── UIRenderEngine_gtk.cpp │ │ ├── UIResourceMgr_gtk.cpp │ │ ├── UIScrollBar_gtk.cpp │ │ └── UIWindowImpBase_gtk.cpp └── win32 │ ├── EncodingTransform.cpp │ ├── EncodingTransform.h │ ├── SkinFileReader_win32.cpp │ ├── UIBaseWindow_win32.cpp │ ├── UICombo.cpp │ ├── UIEdit.cpp │ ├── UIFileHelper.cpp │ ├── UIFont_win32.cpp │ ├── UIPaintManager_win32.cpp │ ├── UIRenderClip_win32.cpp │ ├── UIRenderEngine_win32.cpp │ ├── UIResourceMgr_win32.cpp │ ├── UIScrollBar.cpp │ └── UIWindowImpBase_win32.cpp ├── demo ├── 360SafeDemo │ ├── 360SafeRes │ │ ├── ComputerExamine.xml │ │ ├── antivirus.png │ │ ├── button_hover.png │ │ ├── button_normal.png │ │ ├── button_pushed.png │ │ ├── cloud.png │ │ ├── commmon.png │ │ ├── examine_background.bmp │ │ ├── firewall.png │ │ ├── firewall_ok.png │ │ ├── horizontal_border.bmp │ │ ├── icon.ico │ │ ├── icon.png │ │ ├── logo.png │ │ ├── navigationbar.bmp │ │ ├── networkshield.png │ │ ├── preventnumber.png │ │ ├── scanbutton.png │ │ ├── scrollbar.bmp │ │ ├── skin.xml │ │ ├── softwaremanager.png │ │ ├── start.png │ │ ├── sys_dlg_close.png │ │ ├── sys_dlg_max.png │ │ ├── sys_dlg_menu.png │ │ ├── sys_dlg_min.png │ │ ├── sys_dlg_restore.png │ │ ├── tabbar_hover.png │ │ ├── tabbar_normal.png │ │ ├── tabbar_pushed.png │ │ ├── toolbar_hover.png │ │ ├── toolbar_normal.png │ │ ├── toolbar_pushed.png │ │ └── vertical_border.bmp │ ├── CMakeLists.txt │ ├── MainFrame.cpp │ ├── MainFrame.h │ ├── UIComputerExamine.cpp │ ├── UIComputerExamine.h │ └── main.cpp ├── CMakeLists.txt ├── GameDemo │ ├── CMakeLists.txt │ ├── ControlEx.h │ ├── GameFrameWnd.cpp │ ├── GameFrameWnd.h │ ├── GameRes │ │ ├── Combo_nor.bmp │ │ ├── Combo_over.bmp │ │ ├── Headerctrl_Sperator.bmp │ │ ├── button_down.bmp │ │ ├── button_nor.bmp │ │ ├── button_over.bmp │ │ ├── chatmsgbk.png │ │ ├── desk.xml │ │ ├── frame_btn_close_disable.bmp │ │ ├── frame_btn_close_down.bmp │ │ ├── frame_btn_close_hot.bmp │ │ ├── frame_btn_close_normal.bmp │ │ ├── frame_btn_max.bmp │ │ ├── frame_btn_min.bmp │ │ ├── gameicons.png │ │ ├── hall.xml │ │ ├── headerctrl_down.bmp │ │ ├── headerctrl_hot.bmp │ │ ├── headerctrl_normal.bmp │ │ ├── login.xml │ │ ├── scrollbar.bmp │ │ ├── tab_back.bmp │ │ ├── tab_close.png │ │ ├── tab_hot.bmp │ │ ├── tab_normal.bmp │ │ ├── tab_select.bmp │ │ ├── table.png │ │ ├── tree_expand.png │ │ ├── tree_hot.bmp │ │ ├── tree_select.bmp │ │ ├── tree_top.png │ │ ├── user.png │ │ ├── vip.png │ │ └── winbk.bmp │ ├── LoginFrameWnd.cpp │ ├── LoginFrameWnd.h │ └── main.cpp ├── ListDemo │ ├── CMakeLists.txt │ ├── ListDemo.cpp │ ├── ListDemo.h │ ├── ListRes │ │ ├── bg.png │ │ ├── button.png │ │ ├── list_header_bg.png │ │ ├── list_header_hot.png │ │ ├── list_header_pushed.png │ │ ├── list_header_sep.png │ │ ├── max_min.png │ │ ├── max_min_h.png │ │ ├── menu.xml │ │ ├── menu_bk.png │ │ ├── menu_hot_bk.png │ │ ├── scroll.png │ │ ├── search_bg.png │ │ └── skin.xml │ └── main.cpp ├── QQDemo │ ├── CMakeLists.txt │ ├── ColorPicker.cpp │ ├── ColorPicker.h │ ├── UIFriends.cpp │ ├── UIFriends.h │ ├── UIGroups.cpp │ ├── UIGroups.h │ ├── UIListCommonDefine.cpp │ ├── UIListCommonDefine.h │ ├── UIMicroBlog.cpp │ ├── UIMicroBlog.h │ ├── chat_dialog.cpp │ ├── chat_dialog.h │ ├── color_skin.cpp │ ├── color_skin.h │ ├── main.cpp │ ├── observer_impl_base.h │ └── skin_change_event.h └── RichListDemo │ ├── CMakeLists.txt │ ├── RichListRes.zip │ ├── RichListWnd.cpp │ ├── RichListWnd.h │ └── main.cpp ├── images ├── deepin_360safe.png ├── deepin_list.png ├── kylin_360safe.png ├── kylin_list.png ├── ubuntu_360safe.png ├── ubuntu_gamedemo.png ├── ubuntu_list.png ├── ubuntu_richlist.png ├── win_360safe.png ├── win_gamedemo.png ├── win_list.png ├── win_richlist.png └── 微信联系方式.jpg ├── include ├── IContainerUI.h ├── IDialogBuilderCallback.h ├── IMessageFilterUI.h ├── INotifyUI.h ├── NotifyPump.h ├── UIBackend.h ├── UIBaseWindow.h ├── UIBaseWindowObjects.h ├── UIButton.h ├── UICheckbox.h ├── UIChildLayout.h ├── UICombo.h ├── UIContainer.h ├── UIControl.h ├── UIDefine.h ├── UIDelegate.h ├── UIDlgBuilder.h ├── UIEdit.h ├── UIFileHelper.h ├── UIFont.h ├── UIHorizontalLayout.h ├── UILabel.h ├── UIList.h ├── UIOption.h ├── UIPaintManager.h ├── UIProgress.h ├── UIPtrArray.h ├── UIRect.h ├── UIRenderClip.h ├── UIRenderEngine.h ├── UIResourceMgr.h ├── UIScrollBar.h ├── UISlider.h ├── UIString.h ├── UIStringPtrMap.h ├── UITabLayout.h ├── UIText.h ├── UITileLayout.h ├── UITreeView.h ├── UIValArray.h ├── UIVerticalLayout.h ├── UIWindowImpBase.h └── tinyxml2.h ├── src ├── NotifyPump.cpp ├── SkinFileReader.cpp ├── SkinFileReader.h ├── SkinFileReaderService.cpp ├── SkinFileReaderService.h ├── SkinZipFileReader.cpp ├── SkinZipFileReader.h ├── UIBaseWindow.cpp ├── UIBaseWindowObjects.cpp ├── UIButton.cpp ├── UICheckbox.cpp ├── UIChildLayout.cpp ├── UICombo.cpp ├── UIComboWnd.h ├── UIContainer.cpp ├── UIControl.cpp ├── UIDelegate.cpp ├── UIDlgBuilder.cpp ├── UIEdit.cpp ├── UIFont.cpp ├── UIHorizontalLayout.cpp ├── UILabel.cpp ├── UIList.cpp ├── UIOption.cpp ├── UIPaintManager.cpp ├── UIProgress.cpp ├── UIPtrArray.cpp ├── UIRect.cpp ├── UIRenderEngine.cpp ├── UIResourceMgr.cpp ├── UIScrollBar.cpp ├── UISlider.cpp ├── UIString.cpp ├── UIStringPtrMap.cpp ├── UITabLayout.cpp ├── UIText.cpp ├── UITileLayout.cpp ├── UITreeView.cpp ├── UIValArray.cpp ├── UIVerticalLayout.cpp ├── UIWindowImpBase.cpp └── tinyxml2.cpp └── third-party ├── stb └── stb_image.h └── zlib-1.3.1 ├── CMakeLists.txt ├── ChangeLog ├── FAQ ├── INDEX ├── LICENSE ├── Makefile ├── Makefile.in ├── README ├── adler32.c ├── compress.c ├── configure ├── crc32.c ├── crc32.h ├── deflate.c ├── deflate.h ├── gzclose.c ├── gzguts.h ├── gzlib.c ├── gzread.c ├── gzwrite.c ├── infback.c ├── inffast.c ├── inffast.h ├── inffixed.h ├── inflate.c ├── inflate.h ├── inftrees.c ├── inftrees.h ├── make_vms.com ├── minizip ├── crypt.h ├── ioapi.c ├── ioapi.h ├── iowin32.c ├── iowin32.h ├── mztools.c ├── mztools.h ├── unzip.c ├── unzip.h ├── zip.c └── zip.h ├── treebuild.xml ├── trees.c ├── trees.h ├── uncompr.c ├── win32 └── zlib1.rc ├── zconf.h.cmakein ├── zconf.h.in ├── zconf.h.included ├── zlib.h ├── zlib.map ├── zlib.pc.cmakein ├── zlib.pc.in ├── zutil.c └── zutil.h /.gitignore: -------------------------------------------------------------------------------- 1 | .idea 2 | build 3 | cmake-build-debug 4 | cmake-build-release 5 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.11) 2 | project(directui) 3 | 4 | set(CMAKE_CXX_STANDARD 11) 5 | 6 | option(GTK_BACKEND "Gtk backend is option" ON) 7 | 8 | if(${CMAKE_SYSTEM_NAME} STREQUAL "Windows") 9 | FILE(GLOB BACKEND_SRC_FILES "backend/win32/*.cpp") 10 | link_libraries(comctl32) 11 | link_libraries(shlwapi) 12 | link_libraries(imm32) 13 | else() 14 | 15 | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -no-pie") 16 | find_package(PkgConfig REQUIRED) 17 | FILE(GLOB OS_SRC_FILES "backend/linux/*.cpp") 18 | if(GTK_BACKEND) 19 | add_definitions(-DGTK_BACKEND) 20 | # linux操作系统平台下生成的GUI进程,能够通过双击打开进程。 21 | pkg_check_modules(GTK3 REQUIRED gtk+-3.0) 22 | FILE(GLOB BACKEND_SRC_FILES "backend/linux/gtk/*.cpp") 23 | include_directories(${GTK3_INCLUDE_DIRS}) 24 | link_libraries(${GTK3_LIBRARIES}) 25 | else() 26 | FILE(GLOB BACKEND_SRC_FILES "backend/linux/X11/*.cpp") 27 | pkg_check_modules(PANGO REQUIRED pango) 28 | pkg_check_modules(PANGO_XFT REQUIRED pangoxft) 29 | include_directories(${PANGO_INCLUDE_DIRS}) 30 | link_libraries(${PANGO_LIBRARIES} ${PANGO_XFT_LIBRARIES} X11 Xext Xft Xrender) 31 | endif() 32 | list(APPEND BACKEND_SRC_FILES ${OS_SRC_FILES}) 33 | endif() 34 | 35 | FILE(GLOB_RECURSE SRC_FILES "src/*.cpp") 36 | 37 | if(${CMAKE_BUILD_TYPE} STREQUAL "Debug") 38 | add_definitions(-DDebug) 39 | if(${CMAKE_CXX_COMPILER_ID} STREQUAL MSVC) 40 | else() 41 | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -O0 -g3 -fprofile-arcs -ftest-coverage") 42 | endif() 43 | else() 44 | ## 对于release版本,windows下不显示控制台窗口。 45 | if(${CMAKE_SYSTEM_NAME} STREQUAL "Windows") 46 | if(${CMAKE_CXX_COMPILER_ID} STREQUAL MSVC) 47 | set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} /SUBSYSTEM:WINDOWS") 48 | else() 49 | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -mwindows") 50 | endif() 51 | endif() 52 | endif() 53 | 54 | include_directories(third-party/stb) 55 | include_directories(third-party/zlib-1.3.1) 56 | include_directories(third-party/zlib-1.3.1/minizip) 57 | add_subdirectory(third-party/zlib-1.3.1) 58 | 59 | if(${CMAKE_CXX_COMPILER_ID} STREQUAL MSVC) 60 | # msvc不支持动态库生成,目前仅支持静态库的生成 61 | add_library(DuiLib ${BACKEND_SRC_FILES} ${SRC_FILES}) 62 | else() 63 | add_library(DuiLib SHARED ${BACKEND_SRC_FILES} ${SRC_FILES}) 64 | endif() 65 | 66 | target_link_libraries(DuiLib PRIVATE zlibstatic) 67 | 68 | include_directories(include) 69 | add_subdirectory(demo) 70 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2025 mxway 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # directui 2 | 3 | ## 前言 4 | 5 | 本项目将开源项目[duilib]([GitHub - duilib/duilib](https://github.com/duilib/duilib))以及[gtkduilib]([GitHub - progmboy/gtkduilib](https://github.com/progmboy/gtkduilib))两个项目的源码进行整合。提供统一接口,以便duilib能够以统一的接口运行在不同的操作系统平台以及国产化的操作系统。项目中采用了c++11标准编写代码,在涉及的常量字符串中使用u8(这是c++11的字符串常量前缀)作为前缀,表示字符串以utf8的编码方式进行内存存储。这样同一份代码无论是在windows操作系统还是linux操作系统,使用gcc还是vs或是其它编译器进行编译,字符串都是以utf8编码的格式编译到目标文件中。由于windows操作系统平台使用A和W两种版本的API函数,Linux操作系统的API默认使用utf8编码,对于操作系统API的调用在windows操作系统平台只需要utf8编码的字符串转换为UCS2,然后调用windows操作系统的W版本API如CreateWindowW、GetTextMetricsW、CreateFontIndirectW等。 6 | 7 | ## 简介 8 | 9 | 项目目标是将duilib及gtkduilib两个项目进行整合,提供统一的接口。实现一个适合windows、linux以及国产化操作系统的duilib项目,通过简单的xml就能够实现界面效果。为了实现源码能够在不同操作系统,不同的编译器进行编译的目标,所有源码文件的编码格式默认都是UTF8+BOM,这样能够保证无论使用gcc还是vs、在windows还是linux操作系统或是国产化操作系统上进行编译时都不会有编译错误。若使用其它的文件编码格式,源码中存在汉字时可能会造成不同编译器在编译过程中出现错误。 10 | 11 | ## 源码编译 12 | 13 | 源码使用cmake进行项目的代码管理。在CMakeLists.txt中会自动根据操作系统将对应的源码文件加入到源码工程中,对于cmake只要cmake版本大小3.11即可,用cmake可以生成Makefile以及vs的源码工程文件。同时要求编译器需要支持c++11特性,在编译时需要判断自己的编译器是否支持c++11特性,对于gcc工具链高于4.8.5的版本即可。目前项目所使用的编译器在windows以及linux操作系统平台下都是使用gcc编译工具链,后续支持windows下vs编译器。 14 | 15 | ### Windows编译 16 | 17 | #### gcc编译 18 | 19 | windows下使用mingw对项目进行编译。编译过程如下 20 | 21 | 切换到项目source目录下。 22 | 23 | * 系统环境检查 24 | 25 | 确定系统中是否支持cmake以及g++编译器。 26 | 27 | ```bat 28 | cmake --version 29 | ``` 30 | 31 | 输出以下信息 32 | 33 | ```bat 34 | cmake version 3.16.6 35 | 36 | CMake suite maintained and supported by Kitware (kitware.com/cmake). 37 | ``` 38 | 39 | 确定系统中的mingw中g++版本 40 | 41 | ```c++ 42 | g++ --version 43 | ``` 44 | 45 | 输出如下信息,确保g++的目录被添加到系统的PATH环境变量中。 46 | 47 | ```bat 48 | g++ (MinGW-W64 i686-posix-dwarf, built by Brecht Sanders) 7.5.0 49 | Copyright (C) 2017 Free Software Foundation, Inc. 50 | This is free software; see the source for copying conditions. There is NO 51 | warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 52 | ``` 53 | 54 | * 编译源码 55 | 56 | 执行如下命令 57 | 58 | ```bat 59 | mkdir build 60 | cd build 61 | cmake ../ -DCMAKE_BUILD_TYPE=Release -G "MinGW Makefiles" 62 | mingw32-make -j4 63 | ``` 64 | 65 | ​ 以上命令执行完成后在build目录下生成可执行文件。 双击相应的可执行文件查看demo效果。 66 | 67 | #### msvc编译 68 | 69 | 在windows操作系统下可以使用cmake生成visual studio的sln解决方案工程。具体执行过程如下,命令行切换到source目录。执行命令 70 | 71 | ```bat 72 | mkdir build 73 | cd build 74 | cmake ../ -DCMAKE_BUILD_TYPE=Release 75 | ``` 76 | 77 | 以上命令执行完成后会在build目录下生成.sln文件。使用visual studio打开该解决方案进行编译即可生成可执行程序 78 | 79 | ### Linux编译 80 | 81 | 在Linux操作系统下依赖于gtk库。所以在编译前需要确定系统中是否已安装了gtk库。以ubuntu为例,安装gtk命令如下 82 | 83 | ```shell 84 | sudo apt install libgtk-3-dev 85 | ``` 86 | 87 | 同时在Linux系统下也需要检查是否安装了cmake以及gcc编译工具链。 88 | 89 | ```shell 90 | cmake --version 91 | g++ --version 92 | ``` 93 | 94 | 分别用于查看系统中是否安装了cmake以及g++。 95 | 96 | **代码编译** 97 | 98 | 切换到项目source目录下执行以下命令 99 | 100 | ```shell 101 | mkdir build && cd build 102 | cmake ../ -DCMAKE_BUILD_TYPE=Release 103 | make -j4 104 | ``` 105 | 106 | 执行以上命令后在build目录生成可执行文件。双击或是在命令行中输入可执行文件名运行程序查看软件运行效果。 107 | 108 | ## 效果示例 109 | 110 | 目前已将[duilib]([GitHub - duilib/duilib](https://github.com/duilib/duilib))原版本中部分示例完成了移植,在不同操作系统平台展示出一致的效果。 111 | 112 | * windows 操作系统 113 | 114 | ![360safe_win](images/win_360safe.png) 115 | ![list_win](images/win_list.png) 116 | ![richlist_win](images/win_richlist.png) 117 | ![gamedemo_win](images/win_gamedemo.png) 118 | 119 | * Ubuntu 20 120 | 121 | ![360safe_ubuntu](images/ubuntu_360safe.png) 122 | ![list_ubuntu](images/ubuntu_list.png) 123 | ![richlist_ubuntu](images/ubuntu_richlist.png) 124 | ![gamedemo_ubuntu](images/ubuntu_gamedemo.png) 125 | 126 | * deepin 127 | 128 | ![360safe_deepin](images/deepin_360safe.png) 129 | ![list_deepin](images/deepin_list.png) 130 | 131 | * 银河麒麟 132 | 133 | ​ ![360safe_kylin](images/kylin_360safe.png) 134 | 135 | ​ ![list_kylin](images/kylin_list.png) 136 | 137 | * UOS 138 | 139 | ## 技术交流 140 | 141 | 欢迎添加微信进行技术交流 142 | ![微信联系方式](images/%E5%BE%AE%E4%BF%A1%E8%81%94%E7%B3%BB%E6%96%B9%E5%BC%8F.jpg) 143 | 144 | ## TODO 145 | 146 | - [ ] DrawHtml功能目前已完成window操作系统的W版本修改工作。Linux已完成DrawHtml大部分功能移植,但是对于选中文本背景色功能还未实现 147 | 148 | - [ ] Edit控件不使用原版中的代码,使用自绘控件功能,目前windows及linux已完成Edit部分基础功能;可支持输入法输入文本,backspace删除文字、delete删除文字、home光标定位、end光标定位功能,但不支持全选以及鼠标选择范围,删除选中文字功能。 149 | 150 | - [ ] Duilib原版本中的其它示例的移植 151 | 152 | - [ ] RichEdit控件 153 | -------------------------------------------------------------------------------- /backend/linux/SkinFileReader_linux.cpp: -------------------------------------------------------------------------------- 1 | #include "../../src/SkinFileReader.h" 2 | #include 3 | #include 4 | #include "UIFileHelper.h" 5 | #include "UIResourceMgr.h" 6 | 7 | ByteArray SkinFileReader::ReadFile(const UIString &fileName) { 8 | UIString fullFileName = fileName; 9 | if(!UIFileHelper::IsAbsolutePath(fileName)){ 10 | fullFileName = UIResourceMgr::GetInstance().GetResourcePath() + UIFileHelper::UI_PATH_SEPARATOR + fileName; 11 | } 12 | ByteArray result = {nullptr, 0}; 13 | FILE *fp = fopen(fullFileName.GetData(),"rb"); 14 | if(fp == nullptr){ 15 | return result; 16 | } 17 | fseek(fp, 0, SEEK_END); 18 | result.m_bufferSize = ftell(fp); 19 | result.m_buffer = new unsigned char[result.m_bufferSize+2]; 20 | memset(result.m_buffer, 0, result.m_bufferSize+2); 21 | fseek(fp, 0, SEEK_SET); 22 | fread(result.m_buffer, 1, result.m_bufferSize, fp); 23 | fclose(fp); 24 | return result; 25 | } 26 | -------------------------------------------------------------------------------- /backend/linux/UIFileHelper.cpp: -------------------------------------------------------------------------------- 1 | #include "UIFileHelper.h" 2 | 3 | UIString UIFileHelper::UI_PATH_SEPARATOR = UIString{"/"}; 4 | 5 | bool UIFileHelper::IsAbsolutePath(const UIString &fileName) { 6 | return (fileName.GetLength()>0 && fileName[0]=='/'); 7 | } 8 | -------------------------------------------------------------------------------- /backend/linux/UIFont_linux.cpp: -------------------------------------------------------------------------------- 1 | #include "UIFont.h" 2 | 3 | UIFont::UIFont() 4 | :m_underline{false}, 5 | m_italic{false}, 6 | m_font{nullptr}, 7 | m_size{8} 8 | { 9 | 10 | } 11 | 12 | UIFont::UIFont(const UIString &fontName, int size, bool bold, bool underline, bool italic) 13 | :m_strFontName {fontName}, 14 | m_bold {bold}, 15 | m_underline {underline}, 16 | m_italic {italic} 17 | { 18 | m_size = size; 19 | } 20 | 21 | void UIFont::ReleaseFont() 22 | { 23 | if(m_font){ 24 | pango_font_description_free(m_font); 25 | } 26 | } 27 | uint32_t UIFont::GetFontHeight(HANDLE_DC hdc) 28 | { 29 | UNUSED_PARAMETER(hdc); 30 | if(m_font){ 31 | if(this->GetUnderline()){ 32 | return pango_font_description_get_size(m_font)/PANGO_SCALE + 4; 33 | } 34 | return pango_font_description_get_size(m_font)/PANGO_SCALE + 2; 35 | } 36 | return 0; 37 | } 38 | 39 | HANDLE_FONT UIFont::Create() 40 | { 41 | PangoFontDescription *desc = pango_font_description_new(); 42 | if(desc == nullptr){ 43 | return nullptr; 44 | } 45 | 46 | if(!m_strFontName.IsEmpty()){ 47 | pango_font_description_set_family(desc, m_strFontName.GetData()); 48 | } 49 | if(m_size){ 50 | pango_font_description_set_absolute_size(desc, m_size * PANGO_SCALE); 51 | //pango_font_description_set_size(desc, m_size); 52 | } 53 | if(m_italic){ 54 | pango_font_description_set_style(desc, PANGO_STYLE_ITALIC); 55 | }else{ 56 | pango_font_description_set_style(desc, PANGO_STYLE_NORMAL); 57 | } 58 | if(m_bold){ 59 | pango_font_description_set_weight(desc, PANGO_WEIGHT_BOLD); 60 | }else{ 61 | pango_font_description_set_weight(desc, PANGO_WEIGHT_NORMAL); 62 | } 63 | m_font = desc; 64 | return m_font; 65 | } 66 | -------------------------------------------------------------------------------- /backend/linux/X11/DispatchMessage.cpp: -------------------------------------------------------------------------------- 1 | #include "DispatchMessage.h" 2 | #include "UIDefine.h" 3 | #include 4 | #include "DisplayInstance.h" 5 | #include 6 | 7 | static void DispatchMessage(Window window, uint32_t msgType, WPARAM wParam,LPARAM lParam){ 8 | UIBaseWindow *baseWindow = UIBaseWindowObjects::GetInstance().GetObject(window); 9 | if(baseWindow == nullptr){ 10 | return; 11 | } 12 | baseWindow->HandleMessage(msgType,wParam,lParam); 13 | if(msgType == DUI_WM_DESTROY){ 14 | UIBaseWindowObjects::GetInstance().RemoveObject(window); 15 | baseWindow->OnFinalMessage(nullptr); 16 | } 17 | } 18 | 19 | void DispatchMessage(XEvent& event) { 20 | Atom wm_protocols = XInternAtom(DisplayInstance::GetInstance().GetDisplay(), "WM_PROTOCOLS", False); 21 | Atom wm_delete_window = XInternAtom(DisplayInstance::GetInstance().GetDisplay(), "WM_DELETE_WINDOW", False); 22 | switch(event.type){ 23 | case DestroyNotify: { 24 | DispatchMessage(event.xdestroywindow.window,DUI_WM_DESTROY,&event.xdestroywindow,nullptr); 25 | break; 26 | } 27 | case Expose: { 28 | DispatchMessage(event.xexpose.window,DUI_WM_PAINT,&event.xexpose,nullptr); 29 | break; 30 | } 31 | case KeyPress: { 32 | DispatchMessage(event.xkey.window,DUI_WM_KEYPRESS, &event.xkey,nullptr); 33 | break; 34 | } 35 | case KeyRelease: { 36 | DispatchMessage(event.xkey.window,DUI_WM_KEYRELEASE,&event.xkey,nullptr); 37 | break; 38 | } 39 | case ButtonPress: { 40 | if(event.xbutton.button == 4 || event.xbutton.button==5){ 41 | DispatchMessage(event.xbutton.window,DUI_WM_MOUSEWHEEL,&event.xbutton,nullptr); 42 | }else{ 43 | DispatchMessage(event.xbutton.window,DUI_WM_MOUSEPRESS,&event.xbutton,nullptr); 44 | } 45 | break; 46 | } 47 | case ButtonRelease: { 48 | DispatchMessage(event.xbutton.window,DUI_WM_MOUSERELEASE,&event.xbutton,nullptr); 49 | break; 50 | } 51 | case MotionNotify: { 52 | DispatchMessage(event.xmotion.window,DUI_WM_MOUSEMOVE, &event.xmotion,nullptr); 53 | break; 54 | } 55 | case EnterNotify: { 56 | DispatchMessage(event.xcrossing.window,DUI_WM_MOUSEENTER,&event.xcrossing,nullptr); 57 | break; 58 | } 59 | case LeaveNotify: { 60 | DispatchMessage(event.xcrossing.window,DUI_WM_MOUSEENTER,&event.xcrossing,nullptr); 61 | break; 62 | } 63 | case FocusOut: { 64 | DispatchMessage(event.xfocus.window,DUI_WM_KILLFOCUS,&event.xfocus,nullptr); 65 | break; 66 | } 67 | case ConfigureNotify: { 68 | DispatchMessage(event.xconfigure.window,DUI_WM_SIZE, &event.xconfigure,nullptr); 69 | break; 70 | } 71 | case ClientMessage: { 72 | if (event.xclient.message_type == wm_protocols && 73 | event.xclient.data.l[0] == wm_delete_window) { 74 | DispatchMessage(event.xclient.window,DUI_WM_CLOSE,&event.xclient,nullptr); 75 | }else if (event.xclient.message_type == XInternAtom(DisplayInstance::GetInstance().GetDisplay(), "UI_WINDOW_CLOSE_RESPONSE", False)) { 76 | DispatchMessage(event.xclient.window,DUI_WM_CLOSE,&event.xclient,nullptr); 77 | } 78 | } 79 | default: 80 | break; 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /backend/linux/X11/DispatchMessage.h: -------------------------------------------------------------------------------- 1 | #ifndef DISPATCHMESSAGE_H 2 | #define DISPATCHMESSAGE_H 3 | #include 4 | #include 5 | 6 | void DispatchMessage(XEvent &event); 7 | 8 | #endif //DISPATCHMESSAGE_H 9 | -------------------------------------------------------------------------------- /backend/linux/X11/DisplayInstance.cpp: -------------------------------------------------------------------------------- 1 | #include "DisplayInstance.h" 2 | 3 | DisplayInstance::DisplayInstance() { 4 | m_display = XOpenDisplay(nullptr); 5 | } 6 | 7 | DisplayInstance::~DisplayInstance() { 8 | if(m_display != nullptr){ 9 | XCloseDisplay(m_display); 10 | } 11 | } 12 | 13 | DisplayInstance &DisplayInstance::GetInstance() { 14 | static DisplayInstance displayInstance; 15 | return displayInstance; 16 | } 17 | 18 | Display *DisplayInstance::GetDisplay() const { 19 | return m_display; 20 | } 21 | 22 | int DisplayInstance::GetWidth() const { 23 | return DisplayWidth(m_display,this->GetScreenNumber()); 24 | } 25 | 26 | int DisplayInstance::GetHeight() const { 27 | return DisplayHeight(m_display,this->GetScreenNumber()); 28 | } 29 | 30 | int DisplayInstance::GetScreenNumber() const { 31 | return DefaultScreen(m_display); 32 | } 33 | 34 | int DisplayInstance::GetDisplayDepth() const { 35 | return DefaultDepth(m_display,this->GetScreenNumber()); 36 | } 37 | 38 | Visual *DisplayInstance::GetVisual() const { 39 | return DefaultVisual(m_display,this->GetScreenNumber()); 40 | } 41 | 42 | Colormap DisplayInstance::GetColormap() const { 43 | return DefaultColormap(m_display,this->GetScreenNumber()); 44 | } 45 | -------------------------------------------------------------------------------- /backend/linux/X11/DisplayInstance.h: -------------------------------------------------------------------------------- 1 | #ifndef DIRECTUI_DISPLAYINSTANCE_H 2 | #define DIRECTUI_DISPLAYINSTANCE_H 3 | #include 4 | 5 | class DisplayInstance { 6 | public: 7 | ~DisplayInstance(); 8 | DisplayInstance(const DisplayInstance &)=delete; 9 | DisplayInstance &operator=(const DisplayInstance &)=delete; 10 | static DisplayInstance &GetInstance(); 11 | Display* GetDisplay()const; 12 | int GetWidth()const; 13 | int GetHeight()const; 14 | int GetScreenNumber()const; 15 | int GetDisplayDepth()const; 16 | Visual* GetVisual()const; 17 | Colormap GetColormap()const; 18 | private: 19 | DisplayInstance(); 20 | private: 21 | Display *m_display; 22 | }; 23 | 24 | 25 | #endif //DIRECTUI_DISPLAYINSTANCE_H 26 | -------------------------------------------------------------------------------- /backend/linux/X11/RoundRectRegion.h: -------------------------------------------------------------------------------- 1 | #ifndef DIRECTUI_ROUNDRECTREGION_H 2 | #define DIRECTUI_ROUNDRECTREGION_H 3 | #include 4 | #include 5 | #include 6 | 7 | Region CreateRoundRectRegion(const UIRect &rect,int roundCornerRadius); 8 | 9 | #endif //DIRECTUI_ROUNDRECTREGION_H 10 | -------------------------------------------------------------------------------- /backend/linux/X11/TimerContext.h: -------------------------------------------------------------------------------- 1 | #ifndef TIMERCONTEXT_H 2 | #define TIMERCONTEXT_H 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | typedef struct tagTIMERINFO 10 | { 11 | UIControl *pSender; 12 | uint32_t uTimerId; 13 | bool killed; 14 | UIPaintManager *paintManager; 15 | uint64_t timerOut; 16 | uint32_t intervalValue; 17 | } TIMERINFO; 18 | 19 | const uint32_t MAX_TIMEOUT_EVENTS = 512; 20 | 21 | class TimerContext { 22 | public: 23 | TimerContext(const TimerContext&)=delete; 24 | TimerContext &operator=(const TimerContext&)=delete; 25 | static TimerContext &GetInstance(); 26 | TIMERINFO *AddTimer(UIControl *pSender,UIPaintManager *paintManager,uint32_t interval); 27 | uint64_t GetMinimumTimeout(); 28 | void ProcessTimeout(); 29 | TIMERINFO *Remove(TIMERINFO *timeInfo); 30 | TIMERINFO *Remove(uint32_t timerId); 31 | void RemoveAllTimers(); 32 | private: 33 | void AddTimer_Internal(TIMERINFO *timerInfo); 34 | void ShiftUp(int currentIndex); 35 | void ShiftDown(int currentIndex); 36 | private: 37 | TimerContext(); 38 | private: 39 | uint32_t m_elements; 40 | TIMERINFO *m_timeout[MAX_TIMEOUT_EVENTS]; 41 | std::mutex m_mutex; 42 | }; 43 | 44 | 45 | 46 | #endif //TIMERCONTEXT_H 47 | -------------------------------------------------------------------------------- /backend/linux/X11/UICursor.cpp: -------------------------------------------------------------------------------- 1 | #include "UICursor.h" 2 | #include 3 | #include "DisplayInstance.h" 4 | #include "X11Window.h" 5 | 6 | UICursor::UICursor() { 7 | Display *display = DisplayInstance::GetInstance().GetDisplay(); 8 | m_cursorMapping.insert(make_pair(UI_IDC_ARROW,XCreateFontCursor(display,UI_IDC_ARROW))); 9 | m_cursorMapping.insert(make_pair(UI_IDC_HAND,XCreateFontCursor(display,UI_IDC_HAND))); 10 | m_cursorMapping.insert(make_pair(UI_IDC_TEXT,XCreateFontCursor(display,UI_IDC_TEXT))); 11 | m_cursorMapping.insert(make_pair(UI_IDC_RESIZEWE,XCreateFontCursor(display,UI_IDC_RESIZEWE))); 12 | m_cursorMapping.insert(make_pair(UI_IDC_RESIZENS,XCreateFontCursor(display,UI_IDC_RESIZENS))); 13 | } 14 | 15 | UICursor::~UICursor() { 16 | Display *display = DisplayInstance::GetInstance().GetDisplay(); 17 | for (auto itr : m_cursorMapping) { 18 | XFreeCursor(display,itr.second); 19 | } 20 | } 21 | 22 | UICursor& UICursor::GetInstance() { 23 | static UICursor cursor; 24 | return cursor; 25 | } 26 | 27 | void UICursor::LoadCursor(UIPaintManager *manager,int cursor){ 28 | X11Window *window = manager->GetPaintWindow(); 29 | auto itr = m_cursorMapping.find(cursor); 30 | if (itr == m_cursorMapping.end()) { 31 | return; 32 | } 33 | XDefineCursor(window->display,window->window,itr->second); 34 | } 35 | 36 | void UILoadCursorX11(UIPaintManager *manager,int cursor) { 37 | UICursor::GetInstance().LoadCursor(manager,cursor); 38 | } -------------------------------------------------------------------------------- /backend/linux/X11/UICursor.h: -------------------------------------------------------------------------------- 1 | #ifndef UICURSOR_H 2 | #define UICURSOR_H 3 | #include 4 | #include 5 | 6 | using namespace std; 7 | 8 | class UICursor { 9 | public: 10 | ~UICursor(); 11 | UICursor(const UICursor &)=delete; 12 | UICursor &operator=(const UICursor &)=delete; 13 | static UICursor &GetInstance(); 14 | void LoadCursor(UIPaintManager *manager,int cursor); 15 | private: 16 | UICursor(); 17 | private: 18 | map m_cursorMapping; 19 | }; 20 | 21 | 22 | 23 | #endif //UICURSOR_H 24 | -------------------------------------------------------------------------------- /backend/linux/X11/UIRenderClip_X11.cpp: -------------------------------------------------------------------------------- 1 | #include "UIRenderClip.h" 2 | #include "X11HDC.h" 3 | #include "RoundRectRegion.h" 4 | 5 | class UIRenderClipPrivate 6 | { 7 | public: 8 | RECT rcItem; 9 | HANDLE_DC hDC; 10 | Region hRgn; 11 | Region hOldRgn; 12 | }; 13 | 14 | UIRenderClip::UIRenderClip() 15 | :m_impl{make_shared()} 16 | { 17 | 18 | } 19 | 20 | UIRenderClip::~UIRenderClip() { 21 | //XSetRegion(m_impl->hDC->x11Window->display,m_impl->hDC->gc,m_impl->hOldRgn); 22 | if(m_impl->hDC!=nullptr && m_impl->hOldRgn!=nullptr){ 23 | SelectRegion(m_impl->hDC,m_impl->hOldRgn); 24 | } 25 | //SelectRegion(m_impl->hDC,m_impl->hOldRgn); 26 | if(m_impl->hRgn!=nullptr){ 27 | XDestroyRegion(m_impl->hRgn); 28 | } 29 | } 30 | 31 | static Region CreateRectRegion(XRectangle rect){ 32 | Region region = XCreateRegion(); 33 | XUnionRectWithRegion(&rect,region,region); 34 | return region; 35 | } 36 | 37 | void UIRenderClip::GenerateClip(HANDLE_DC hdc, RECT rc, UIRenderClip &clip) { 38 | clip.m_impl->hOldRgn = GetRegion(hdc); 39 | XRectangle paintRectangle = {static_cast(rc.left), 40 | static_cast(rc.top), 41 | static_cast(rc.right-rc.left), 42 | static_cast(rc.bottom-rc.top)}; 43 | clip.m_impl->hRgn = CreateRectRegion(paintRectangle); 44 | XIntersectRegion(clip.m_impl->hOldRgn,clip.m_impl->hRgn,clip.m_impl->hRgn); 45 | clip.m_impl->hOldRgn = SelectRegion(hdc, clip.m_impl->hRgn); 46 | clip.m_impl->hDC = hdc; 47 | clip.m_impl->rcItem = rc; 48 | } 49 | 50 | void UIRenderClip::GenerateRoundClip(HANDLE_DC hdc, RECT rcPaint,RECT rcItem, int width, int height, UIRenderClip &clip) { 51 | clip.m_impl->hOldRgn = GetRegion(hdc); 52 | UIRect rect{rcPaint.left,rcPaint.top,rcPaint.right,rcPaint.bottom}; 53 | clip.m_impl->hRgn = CreateRoundRectRegion(rect,width); 54 | XIntersectRegion(clip.m_impl->hOldRgn,clip.m_impl->hRgn,clip.m_impl->hRgn); 55 | clip.m_impl->hOldRgn = SelectRegion(hdc, clip.m_impl->hRgn); 56 | clip.m_impl->hDC = hdc; 57 | clip.m_impl->rcItem = rcPaint; 58 | } 59 | 60 | void UIRenderClip::UseOldClipBegin(HANDLE_DC hdc, UIRenderClip &clip) { 61 | SelectRegion(hdc, clip.m_impl->hOldRgn); 62 | } 63 | 64 | void UIRenderClip::UseOldClipEnd(HANDLE_DC hdc, UIRenderClip &clip) { 65 | SelectRegion(hdc, clip.m_impl->hRgn); 66 | } 67 | 68 | -------------------------------------------------------------------------------- /backend/linux/X11/UIScrollBar.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include "UIBackend.h" 3 | #include "UIPaintManager.h" 4 | #include "X11Window.h" 5 | 6 | POINT UIScrollBar::GetCursorPos()const { 7 | POINT pt = { 0 }; 8 | Window root; 9 | Window child; 10 | int root_x = 0; 11 | int root_y = 0; 12 | int win_x = 0; 13 | int win_y = 0; 14 | unsigned int mask = 0; 15 | X11Window *window = this->m_manager->GetPaintWindow(); 16 | XQueryPointer(window->display, window->window, &root, &child, 17 | &root_x, &root_y, &win_x, &win_y, &mask); 18 | pt.x = win_x; 19 | pt.y = win_y; 20 | return pt; 21 | } 22 | -------------------------------------------------------------------------------- /backend/linux/X11/X11Bitmap.h: -------------------------------------------------------------------------------- 1 | #ifndef DIRECTUI_X11BITMAP_H 2 | #define DIRECTUI_X11BITMAP_H 3 | #include 4 | 5 | struct X11Bitmap 6 | { 7 | X11Bitmap():bufferSize{0}, 8 | buffer{nullptr}, 9 | width{0}, 10 | height{0} 11 | { 12 | 13 | } 14 | ~X11Bitmap(){ 15 | free(buffer); 16 | } 17 | uint32_t bufferSize; 18 | unsigned char *buffer; 19 | uint32_t width; 20 | uint32_t height; 21 | }; 22 | 23 | #endif //DIRECTUI_X11BITMAP_H 24 | -------------------------------------------------------------------------------- /backend/linux/X11/X11HDC.cpp: -------------------------------------------------------------------------------- 1 | #include "X11HDC.h" 2 | #include "X11Window.h" 3 | 4 | HANDLE_DC CreateHDC(X11Window *window, Drawable draw,int width,int height){ 5 | auto *hdc = new X11WindowHDC; 6 | hdc->x11Window = window; 7 | //hdc->draw = draw; 8 | hdc->drawablePixmap = XCreatePixmap(hdc->x11Window->display,draw,width,height,window->depth); 9 | hdc->gc = XCreateGC(hdc->x11Window->display,hdc->drawablePixmap,0, nullptr); 10 | hdc->currentRegion = XCreateRegion(); 11 | XRectangle rect = {0,0,static_cast(width),static_cast(height)}; 12 | XUnionRectWithRegion(&rect,hdc->currentRegion,hdc->currentRegion); 13 | return hdc; 14 | } 15 | 16 | Region SelectRegion(HANDLE_DC hdc,Region newRegion){ 17 | Region oldRegion = hdc->currentRegion; 18 | hdc->currentRegion = newRegion; 19 | if (newRegion != nullptr) { 20 | XSetRegion(hdc->x11Window->display,hdc->gc,newRegion); 21 | } 22 | return oldRegion; 23 | } 24 | 25 | Region GetRegion(HANDLE_DC hdc){ 26 | return hdc->currentRegion; 27 | } 28 | 29 | void ReleaseHDC(HANDLE_DC hdc){ 30 | if(hdc->drawablePixmap != 0){ 31 | XFreePixmap(hdc->x11Window->display,hdc->drawablePixmap); 32 | } 33 | if(hdc->currentRegion != nullptr){ 34 | XDestroyRegion(hdc->currentRegion); 35 | } 36 | if(hdc->gc != nullptr){ 37 | XFreeGC(hdc->x11Window->display,hdc->gc); 38 | } 39 | delete hdc; 40 | } 41 | -------------------------------------------------------------------------------- /backend/linux/X11/X11HDC.h: -------------------------------------------------------------------------------- 1 | #ifndef DIRECTUI_X11HDC_H 2 | #define DIRECTUI_X11HDC_H 3 | #include 4 | 5 | struct X11Window; 6 | 7 | struct X11WindowHDC{ 8 | //Display *display; 9 | X11Window *x11Window; 10 | //Drawable draw; 11 | Pixmap drawablePixmap; 12 | Region currentRegion; 13 | GC gc; 14 | }; 15 | 16 | HANDLE_DC CreateHDC(X11Window *window, Drawable draw,int width,int height); 17 | 18 | //设置绘制区域,newRegion为新的绘制区域,返回原来的绘制区域 19 | Region SelectRegion(HANDLE_DC hdc,Region newRegion); 20 | 21 | Region GetRegion(HANDLE_DC hdc); 22 | 23 | void ReleaseHDC(HANDLE_DC hdc); 24 | 25 | 26 | #endif //DIRECTUI_X11HDC_H 27 | -------------------------------------------------------------------------------- /backend/linux/X11/X11Window.h: -------------------------------------------------------------------------------- 1 | #ifndef DIRECTUI_X11WINDOW_H 2 | #define DIRECTUI_X11WINDOW_H 3 | #include 4 | #include 5 | 6 | struct X11WindowHDC; 7 | 8 | struct X11Window{ 9 | X11Window() 10 | :display{nullptr}, 11 | screen{-1}, 12 | window{0}, 13 | visual{nullptr}, 14 | colormap{0}, 15 | hdc {nullptr}, 16 | parent{nullptr}, 17 | depth{0}, 18 | x{0}, 19 | y{0}, 20 | width{0}, 21 | height{0} 22 | { 23 | 24 | } 25 | ~X11Window(){ 26 | 27 | } 28 | Display *display; 29 | int screen; 30 | Window window; 31 | Visual *visual; 32 | Colormap colormap; 33 | X11WindowHDC *hdc; 34 | X11Window *parent; 35 | int depth; 36 | int x; 37 | int y; 38 | int width; 39 | int height; 40 | }; 41 | #endif //DIRECTUI_X11WINDOW_H 42 | -------------------------------------------------------------------------------- /backend/linux/gtk/UIRenderClip_gtk.cpp: -------------------------------------------------------------------------------- 1 | #include "UIRenderClip.h" 2 | #include 3 | 4 | class UIRenderClipPrivate 5 | { 6 | public: 7 | UIRenderClipPrivate() 8 | : m_rcItem{0,0,0,0}, 9 | m_roundClip {false}, 10 | m_roundRadius{0}, 11 | m_clipCreated{false}, 12 | m_hDC {nullptr} 13 | { 14 | 15 | } 16 | RECT m_rcPaint; 17 | RECT m_rcItem; 18 | bool m_roundClip; 19 | uint32_t m_roundRadius; 20 | bool m_clipCreated; 21 | HANDLE_DC m_hDC; 22 | }; 23 | 24 | UIRenderClip::UIRenderClip() 25 | :m_impl{make_shared()} 26 | { 27 | 28 | } 29 | 30 | UIRenderClip::~UIRenderClip() { 31 | if(m_impl->m_clipCreated){ 32 | cairo_restore(m_impl->m_hDC); 33 | } 34 | } 35 | 36 | void UIRenderClip::GenerateClip(HANDLE_DC hdc, RECT rc, UIRenderClip &clip) { 37 | clip.m_impl->m_rcItem = rc; 38 | clip.m_impl->m_hDC = hdc; 39 | clip.m_impl->m_clipCreated = true; 40 | cairo_save(hdc); 41 | cairo_rectangle(clip.m_impl->m_hDC, 42 | clip.m_impl->m_rcItem.left, 43 | clip.m_impl->m_rcItem.top, 44 | clip.m_impl->m_rcItem.right - clip.m_impl->m_rcItem.left, 45 | clip.m_impl->m_rcItem.bottom - clip.m_impl->m_rcItem.top); 46 | cairo_clip(hdc); 47 | } 48 | 49 | static void GenerateRoundSubPath(HANDLE_DC hdc, RECT rcItem, int cornerRadius) 50 | { 51 | double x = rcItem.left, /* parameters like cairo_rectangle */ 52 | y = rcItem.top, 53 | width = rcItem.right - rcItem.left, 54 | height = rcItem.bottom - rcItem.top, 55 | aspect = 1.0; /* aspect ratio */ 56 | //corner_radius = 10; /* and corner curvature radius */ 57 | 58 | double radius = cornerRadius / aspect; 59 | double degrees = 3.1415926 / 180.0; 60 | 61 | cairo_new_sub_path (hdc); 62 | cairo_arc (hdc, x + width - radius, y + radius, radius, -90 * degrees, 0 * degrees); 63 | cairo_arc (hdc, x + width - radius, y + height - radius, radius, 0 * degrees, 90 * degrees); 64 | cairo_arc (hdc, x + radius, y + height - radius, radius, 90 * degrees, 180 * degrees); 65 | cairo_arc (hdc, x + radius, y + radius, radius, 180 * degrees, 270 * degrees); 66 | cairo_close_path (hdc); 67 | } 68 | 69 | void UIRenderClip::GenerateRoundClip(HANDLE_DC hdc, RECT rcPaint,RECT rcItem, int width, int height, UIRenderClip &clip) { 70 | clip.m_impl->m_rcPaint = rcPaint; 71 | clip.m_impl->m_rcItem = rcItem; 72 | clip.m_impl->m_hDC = hdc; 73 | clip.m_impl->m_clipCreated = true; 74 | clip.m_impl->m_roundClip = true; 75 | clip.m_impl->m_roundRadius = width; 76 | cairo_save(hdc); 77 | GenerateRoundSubPath(hdc, rcItem, width); 78 | cairo_clip(hdc); 79 | cairo_rectangle(hdc, rcPaint.left, rcPaint.top, 80 | rcPaint.right - rcPaint.left, 81 | rcPaint.bottom - rcPaint.top); 82 | cairo_clip(hdc); 83 | } 84 | 85 | void UIRenderClip::UseOldClipBegin(HANDLE_DC hdc, UIRenderClip &clip) { 86 | if(!clip.m_impl->m_clipCreated){ 87 | return; 88 | } 89 | cairo_restore(hdc); 90 | } 91 | 92 | void UIRenderClip::UseOldClipEnd(HANDLE_DC hdc, UIRenderClip &clip) { 93 | if(!clip.m_impl->m_clipCreated ){ 94 | return; 95 | } 96 | cairo_save(hdc); 97 | if(clip.m_impl->m_roundClip){ 98 | GenerateRoundSubPath(hdc, clip.m_impl->m_rcItem, clip.m_impl->m_roundRadius); 99 | }else{ 100 | cairo_rectangle(clip.m_impl->m_hDC, 101 | clip.m_impl->m_rcItem.left, 102 | clip.m_impl->m_rcItem.top, 103 | clip.m_impl->m_rcItem.right - clip.m_impl->m_rcItem.left, 104 | clip.m_impl->m_rcItem.bottom - clip.m_impl->m_rcItem.top); 105 | cairo_clip(hdc); 106 | cairo_rectangle(clip.m_impl->m_hDC, 107 | clip.m_impl->m_rcPaint.left, 108 | clip.m_impl->m_rcPaint.top, 109 | clip.m_impl->m_rcPaint.right - clip.m_impl->m_rcPaint.left, 110 | clip.m_impl->m_rcPaint.bottom - clip.m_impl->m_rcPaint.top); 111 | } 112 | cairo_clip(hdc); 113 | } 114 | -------------------------------------------------------------------------------- /backend/linux/gtk/UIResourceMgr_gtk.cpp: -------------------------------------------------------------------------------- 1 | #include "UIResourceMgr.h" 2 | #include 3 | #include 4 | #include "../../../src/SkinFileReaderService.h" 5 | 6 | UIFont *glbSystemDefaultGUIFont=nullptr; 7 | 8 | static void CreateSystemDefaultGUIFont() 9 | { 10 | PangoContext *pangoContext = pango_font_map_create_context(pango_cairo_font_map_get_default()); 11 | PangoFontDescription *fontDescription = pango_context_get_font_description(pangoContext); 12 | glbSystemDefaultGUIFont = new UIFont{ 13 | UIString{pango_font_description_get_family(fontDescription)}, 14 | pango_font_description_get_size(fontDescription)/PANGO_SCALE, 15 | pango_font_description_get_weight(fontDescription)==PANGO_WEIGHT_BOLD, 16 | false, 17 | pango_font_description_get_style(fontDescription) == PANGO_STYLE_ITALIC 18 | }; 19 | g_object_unref(pangoContext); 20 | glbSystemDefaultGUIFont->Create(); 21 | } 22 | 23 | UIResourceMgr::UIResourceMgr() 24 | :m_defaultFont {nullptr}, 25 | m_skinType{ResourceSkinType_Unknown} 26 | { 27 | CreateSystemDefaultGUIFont(); 28 | char exeFileName[4096] = {0}; 29 | ssize_t size = readlink("/proc/self/exe", exeFileName, 4094); 30 | if(size == -1){ 31 | printf("Cannot get current execute file path.\n"); 32 | return; 33 | } 34 | m_currentDir = UIString{dirname(exeFileName)}; 35 | m_strResDir = m_currentDir; 36 | } 37 | 38 | UIResourceMgr &UIResourceMgr::GetInstance() { 39 | static UIResourceMgr uiResourceMgr; 40 | return uiResourceMgr; 41 | } 42 | 43 | void UIResourceMgr::Init(int argc, char **argv) { 44 | gtk_init(&argc, &argv); 45 | m_argc = argc; 46 | for(int i=0;iReadFile(image); 55 | if(resultData.m_bufferSize == 0){ 56 | return false; 57 | } 58 | GdkPixbufLoader *loader = gdk_pixbuf_loader_new(); 59 | gdk_pixbuf_loader_write(loader, resultData.m_buffer,resultData.m_bufferSize,nullptr); 60 | gdk_pixbuf_loader_close(loader, nullptr); 61 | GdkPixbuf *pixBuf = gdk_pixbuf_copy(gdk_pixbuf_loader_get_pixbuf(loader)); 62 | delete []resultData.m_buffer; 63 | g_object_unref(loader); 64 | if(pixBuf == nullptr){ 65 | return false; 66 | } 67 | 68 | auto *imageInfo = new TImageInfo ; 69 | imageInfo->hBitmap = pixBuf; 70 | imageInfo->bAlpha = true; 71 | imageInfo->nX = gdk_pixbuf_get_width(pixBuf); 72 | imageInfo->nY = gdk_pixbuf_get_height(pixBuf); 73 | if(!m_strImageMap.Insert(image, imageInfo)){ 74 | g_object_unref(imageInfo->hBitmap); 75 | delete imageInfo; 76 | return false; 77 | } 78 | return true; 79 | } 80 | 81 | TImageInfo *UIResourceMgr::GetImage(const UIString &image, bool bAdd) { 82 | auto *data = static_cast(m_strImageMap.Find(image)); 83 | if(data == nullptr){ 84 | if(bAdd && AddImage(image)){ 85 | data = static_cast(m_strImageMap.Find(image)); 86 | } 87 | } 88 | return data; 89 | } 90 | 91 | void UIResourceMgr::FreeImageInfo(TImageInfo *imageInfo) { 92 | if(imageInfo->hBitmap){ 93 | g_object_unref(imageInfo->hBitmap); 94 | } 95 | delete imageInfo; 96 | } 97 | 98 | void UIResourceMgr::RemoveImage(const UIString &image) { 99 | auto *data = static_cast(m_strImageMap.Find(image)); 100 | if (data) 101 | { 102 | FreeImageInfo(data) ; 103 | m_strImageMap.Remove(image); 104 | } 105 | } 106 | 107 | void UIResourceMgr::ReleaseDefaultFont() { 108 | delete glbSystemDefaultGUIFont; 109 | } 110 | 111 | UIFont *UIResourceMgr::GetDefaultFont() { 112 | if(m_defaultFont){ 113 | return m_defaultFont; 114 | } 115 | return glbSystemDefaultGUIFont; 116 | } 117 | -------------------------------------------------------------------------------- /backend/linux/gtk/UIScrollBar_gtk.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | POINT UIScrollBar::GetCursorPos()const { 5 | POINT pt = { 0 }; 6 | #if GTK_CHECK_VERSION(3, 20, 0) 7 | GtkWidget *widget = m_manager->GetPaintWindow(); 8 | gdk_window_get_device_position(gtk_widget_get_window(widget), 9 | gdk_seat_get_pointer(gdk_display_get_default_seat(gtk_widget_get_display(widget))), 10 | reinterpret_cast(&pt.x), reinterpret_cast(&pt.y), 0); 11 | #else 12 | gdk_window_get_device_position(gtk_widget_get_window(m_manager->GetPaintWindow()), 13 | gdk_device_manager_get_client_pointer( 14 | gdk_display_get_device_manager(gdk_window_get_display(m_manager->GetPaintWindow()))), 15 | reinterpret_cast(&pt.x), reinterpret_cast(&pt.y), NULL); 16 | #endif 17 | return pt; 18 | } -------------------------------------------------------------------------------- /backend/linux/gtk/UIWindowImpBase_gtk.cpp: -------------------------------------------------------------------------------- 1 | #include "UIWindowImpBase.h" 2 | 3 | static bool glbLeftButtonPressed = false; 4 | static gint glbMouseX = 0; 5 | static gint glbMouseY = 0; 6 | 7 | static long OnMousePress(HANDLE_WND wndHandle,uint32_t uMsg, UIPaintManager *paintManager,WPARAM wParam, LPARAM lParam,bool &bHandled) 8 | { 9 | auto *event = (GdkEventButton*)(wParam); 10 | if(event->type != GDK_BUTTON_PRESS && event->type!=GDK_2BUTTON_PRESS){ 11 | bHandled = false; 12 | return 0; 13 | } 14 | if(event->button != 1){ 15 | bHandled = false; 16 | return 0; 17 | } 18 | 19 | RECT rcCaption = paintManager->GetCaptionRect(); 20 | if(event->y < rcCaption.bottom){ 21 | POINT pt = {(long)event->x, (long)event->y}; 22 | auto* pControl = static_cast(paintManager->FindControl(pt)); 23 | if( pControl && (pControl->GetClass() != DUI_CTR_BUTTON) && 24 | (pControl->GetClass() != DUI_CTR_OPTION) && 25 | (pControl->GetClass() != DUI_CTR_TEXT) ) { 26 | if (event->type == GDK_BUTTON_PRESS) { 27 | glbLeftButtonPressed = true; 28 | glbMouseX = event->x_root; 29 | glbMouseY = event->y_root; 30 | } else { 31 | GdkWindow *gdkWindow = gtk_widget_get_window(wndHandle); 32 | GdkWindowState state = gdk_window_get_state(gdkWindow); 33 | if (state & GDK_WINDOW_STATE_MAXIMIZED) { 34 | gtk_window_unmaximize(GTK_WINDOW(wndHandle)); 35 | } else { 36 | gtk_window_maximize(GTK_WINDOW(wndHandle)); 37 | } 38 | } 39 | } 40 | } 41 | return 1; 42 | } 43 | 44 | static long OnMouseMove(HANDLE_WND widget, uint32_t uMsg, WPARAM wParam, LPARAM lParam) 45 | { 46 | if(!glbLeftButtonPressed){ 47 | return 0; 48 | } 49 | auto *eventMotion = (GdkEventMotion*)wParam; 50 | glbLeftButtonPressed = false; 51 | gtk_window_begin_move_drag(GTK_WINDOW(widget),1,glbMouseX, glbMouseY,eventMotion->time); 52 | return 1; 53 | } 54 | 55 | static long OnMouseRelease(HANDLE_WND widget, uint32_t uMsg, WPARAM wParam, LPARAM lParam) 56 | { 57 | glbLeftButtonPressed = false; 58 | return 0; 59 | } 60 | 61 | long UIWindowImpBase::HandleMessage(uint32_t uMsg, WPARAM wParam, LPARAM lParam) { 62 | bool bHandled = false; 63 | long lRes = 0; 64 | switch(uMsg){ 65 | case DUI_WM_CREATE: 66 | lRes = this->OnCreate(uMsg, wParam, lParam, bHandled); 67 | break; 68 | case DUI_WM_MOUSEPRESS: 69 | lRes = OnMousePress(this->GetWND(),uMsg,&m_pm,wParam,lParam,bHandled); 70 | break; 71 | case DUI_WM_MOUSEMOVE: 72 | lRes = OnMouseMove(this->GetWND(),uMsg, wParam, lParam); 73 | break; 74 | case DUI_WM_MOUSERELEASE: 75 | lRes = OnMouseRelease(this->GetWND(), uMsg, wParam, lParam); 76 | break; 77 | case DUI_WM_SIZE: 78 | lRes = OnSize(uMsg, wParam, lParam, bHandled); 79 | break; 80 | case DUI_WM_DESTROY: 81 | lRes = OnDestroy(uMsg, wParam, lParam, bHandled); 82 | break; 83 | case DUI_WM_CLOSE: 84 | lRes = OnClose(uMsg, wParam, lParam, bHandled); 85 | break; 86 | default: 87 | break; 88 | } 89 | if(bHandled)return lRes; 90 | if( m_pm.MessageHandler(uMsg, wParam, lParam, lRes) ) return lRes; 91 | return UIBaseWindow::HandleMessage(uMsg, wParam, lParam); 92 | //return lRes; 93 | } 94 | 95 | long UIWindowImpBase::OnCreate(uint32_t uMsg, WPARAM wParam, LPARAM lParam, bool &bHandled) { 96 | GtkWidget *widget = GetWND(); 97 | gtk_window_set_decorated(GTK_WINDOW(widget), FALSE); 98 | return 0; 99 | } 100 | 101 | long UIWindowImpBase::OnClose(uint32_t uMsg, WPARAM wParam, LPARAM lParam, bool &bHandled) { 102 | return 0; 103 | } 104 | 105 | long UIWindowImpBase::OnDestroy(uint32_t uMsg, WPARAM wParam, LPARAM lParam, bool &bHandled) { 106 | return 0; 107 | } 108 | 109 | long UIWindowImpBase::OnSize(uint32_t uMsg, WPARAM wParam, LPARAM lParam, bool &bHandled) { 110 | return 0; 111 | } 112 | -------------------------------------------------------------------------------- /backend/win32/EncodingTransform.cpp: -------------------------------------------------------------------------------- 1 | #include "EncodingTransform.h" 2 | #include 3 | #include 4 | 5 | wchar_t *Utf8ToUcs2(const char *str, int length) { 6 | if(str == nullptr){ 7 | return nullptr; 8 | } 9 | int numberOfChar = ::MultiByteToWideChar(CP_UTF8,0, 10 | str, length, 11 | nullptr,0); 12 | if(numberOfChar == 0){ 13 | return nullptr; 14 | } 15 | auto *result = new wchar_t[numberOfChar+1]; 16 | memset(result, 0, sizeof(wchar_t )*(numberOfChar+1)); 17 | ::MultiByteToWideChar(CP_UTF8, 0, 18 | str, length, result, numberOfChar); 19 | return result; 20 | } 21 | 22 | char *Ucs2ToUtf8(const wchar_t *wideString, int length) { 23 | if(wideString == nullptr){ 24 | return nullptr; 25 | } 26 | int numberOfChar = ::WideCharToMultiByte(CP_UTF8, 0, 27 | wideString, length, 28 | nullptr, 0,nullptr,nullptr); 29 | if(numberOfChar == 0){ 30 | return nullptr; 31 | } 32 | auto *result = new char[numberOfChar+1]; 33 | memset(result, 0, numberOfChar+1); 34 | ::WideCharToMultiByte(CP_UTF8, 0, 35 | wideString, length, 36 | result, numberOfChar,nullptr,nullptr); 37 | return result; 38 | } 39 | -------------------------------------------------------------------------------- /backend/win32/EncodingTransform.h: -------------------------------------------------------------------------------- 1 | #ifndef DIRECTUI_ENCODINGTRANSFORM_H 2 | #define DIRECTUI_ENCODINGTRANSFORM_H 3 | #include 4 | 5 | wchar_t *Utf8ToUcs2(const char *str, int length=-1); 6 | 7 | char *Ucs2ToUtf8(const wchar_t *wideString, int length=-1); 8 | 9 | #endif //DIRECTUI_ENCODINGTRANSFORM_H 10 | -------------------------------------------------------------------------------- /backend/win32/SkinFileReader_win32.cpp: -------------------------------------------------------------------------------- 1 | #include "../../src/SkinFileReader.h" 2 | #include 3 | #include "EncodingTransform.h" 4 | #include 5 | #include 6 | 7 | ByteArray SkinFileReader::ReadFile(const UIString &fileName) { 8 | UIString fullFileName = fileName; 9 | if(!UIFileHelper::IsAbsolutePath(fileName)){ 10 | fullFileName = UIResourceMgr::GetInstance().GetResourcePath() + UIFileHelper::UI_PATH_SEPARATOR + fileName; 11 | } 12 | ByteArray result = {nullptr, 0}; 13 | wchar_t *wideImageFile = Utf8ToUcs2(fullFileName.GetData(),-1); 14 | HANDLE hFile = ::CreateFileW(wideImageFile, GENERIC_READ, FILE_SHARE_READ, nullptr, OPEN_EXISTING, \ 15 | FILE_ATTRIBUTE_NORMAL, nullptr); 16 | delete []wideImageFile; 17 | if( hFile == INVALID_HANDLE_VALUE ) return result; 18 | DWORD dwSize = ::GetFileSize(hFile, nullptr); 19 | if (dwSize == 0) 20 | { 21 | ::CloseHandle(hFile); 22 | return result; 23 | } 24 | 25 | DWORD dwRead = 0; 26 | result.m_buffer = new BYTE[dwSize+2]; 27 | ::ReadFile( hFile, result.m_buffer, dwSize, &dwRead, nullptr ); 28 | ::CloseHandle( hFile ); 29 | result.m_bufferSize = dwRead; 30 | return result; 31 | } 32 | -------------------------------------------------------------------------------- /backend/win32/UIFileHelper.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | UIString UIFileHelper::UI_PATH_SEPARATOR = UIString{"\\"}; 4 | 5 | bool UIFileHelper::IsAbsolutePath(const UIString &fileName) { 6 | if(fileName.GetLength()<2){ 7 | return false; 8 | } 9 | if( (!(fileName[0]>='a' && fileName[0]<='z')) && (!(fileName[0]>='A' && fileName[0]<='Z')) ){ 10 | return false; 11 | } 12 | return fileName[1] == ':'; 13 | } -------------------------------------------------------------------------------- /backend/win32/UIFont_win32.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "EncodingTransform.h" 4 | 5 | UIFont::UIFont() { 6 | 7 | } 8 | 9 | UIFont::UIFont(const UIString &strFaceName, int size, bool bold, bool underline, bool italic) 10 | : m_strFontName {strFaceName}, 11 | m_size{size}, 12 | m_bold {bold}, 13 | m_underline{underline}, 14 | m_italic{italic} 15 | { 16 | 17 | } 18 | 19 | void UIFont::ReleaseFont() 20 | { 21 | if(m_font){ 22 | ::DeleteObject(m_font); 23 | } 24 | } 25 | uint32_t UIFont::GetFontHeight(HANDLE_DC hdc) 26 | { 27 | TEXTMETRICW textmetric = {0}; 28 | auto hOldFont = (HFONT)::SelectObject(hdc, m_font); 29 | ::GetTextMetricsW(hdc, &textmetric); 30 | ::SelectObject(hdc, hOldFont); 31 | return textmetric.tmHeight; 32 | } 33 | 34 | HANDLE_FONT UIFont::Create(){ 35 | //HFONT hguiFont = (HFONT)::GetStockObject(DEFAULT_GUI_FONT); 36 | //TODO for wchar_t 37 | LOGFONTW lf = {0}; 38 | ::GetObjectW(::GetStockObject(DEFAULT_GUI_FONT), sizeof(LOGFONTW),&lf); 39 | // int copyBytes = m_strFontName.GetLength() >= LF_FACESIZE 40 | // ? (LF_FACESIZE -1)*sizeof(wchar_t): m_strFontName.GetLength() * sizeof(wchar_t); 41 | wchar_t *wideFontName = Utf8ToUcs2(m_strFontName.GetData(), -1); 42 | size_t copyBytes = wcslen(wideFontName) >= LF_FACESIZE?(LF_FACESIZE-1)*sizeof(wchar_t):(wcslen(wideFontName)+1)*sizeof(wchar_t); 43 | memcpy(lf.lfFaceName, wideFontName,copyBytes ); 44 | delete []wideFontName; 45 | lf.lfCharSet = DEFAULT_CHARSET; 46 | lf.lfHeight = -m_size; 47 | if(m_bold)lf.lfWeight += FW_BOLD; 48 | if(m_underline)lf.lfUnderline = true; 49 | if(m_italic)lf.lfItalic = true; 50 | m_font = ::CreateFontIndirectW(&lf); 51 | return m_font; 52 | } -------------------------------------------------------------------------------- /backend/win32/UIRenderClip_win32.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | class UIRenderClipPrivate 5 | { 6 | public: 7 | RECT rcItem; 8 | HDC hDC; 9 | HRGN hRgn; 10 | HRGN hOldRgn; 11 | }; 12 | 13 | UIRenderClip::UIRenderClip() 14 | :m_impl {make_shared()} 15 | { 16 | 17 | } 18 | 19 | UIRenderClip::~UIRenderClip() { 20 | assert(::GetObjectType(m_impl->hDC) == OBJ_DC || ::GetObjectType(m_impl->hDC)==OBJ_MEMDC); 21 | assert(::GetObjectType(m_impl->hRgn) == OBJ_REGION); 22 | assert(::GetObjectType(m_impl->hOldRgn) == OBJ_REGION); 23 | ::SelectObject(m_impl->hDC, m_impl->hOldRgn); 24 | ::DeleteObject(m_impl->hOldRgn); 25 | ::DeleteObject(m_impl->hRgn); 26 | } 27 | 28 | void UIRenderClip::GenerateClip(HANDLE_DC hdc, RECT rc, UIRenderClip &clip) { 29 | RECT rcClip = { 0 }; 30 | ::GetClipBox(hdc, &rcClip); 31 | clip.m_impl->hOldRgn = ::CreateRectRgnIndirect(&rcClip); 32 | clip.m_impl->hRgn = ::CreateRectRgnIndirect(&rc); 33 | ::CombineRgn(clip.m_impl->hRgn, clip.m_impl->hRgn, clip.m_impl->hOldRgn, RGN_AND); 34 | ::SelectClipRgn(hdc, clip.m_impl->hRgn); 35 | clip.m_impl->hDC = hdc; 36 | clip.m_impl->rcItem = rc; 37 | } 38 | 39 | void UIRenderClip::GenerateRoundClip(HANDLE_DC hdc, RECT rcPaint,RECT rcItem, int width, int height, UIRenderClip &clip) { 40 | RECT rcClip = { 0 }; 41 | ::GetClipBox(hdc, &rcClip); 42 | clip.m_impl->hOldRgn = ::CreateRectRgnIndirect(&rcClip); 43 | clip.m_impl->hRgn = ::CreateRectRgnIndirect( &rcPaint); 44 | HRGN hRgnItem = ::CreateRoundRectRgn(rcItem.left, rcItem.top, rcItem.right + 1, rcItem.bottom + 1, width, height); 45 | ::CombineRgn(clip.m_impl->hRgn, clip.m_impl->hRgn, hRgnItem, RGN_AND); 46 | ::CombineRgn(clip.m_impl->hRgn, clip.m_impl->hRgn, clip.m_impl->hOldRgn, RGN_AND); 47 | ::SelectClipRgn(hdc, clip.m_impl->hRgn); 48 | clip.m_impl->hDC = hdc; 49 | clip.m_impl->rcItem = rcItem; 50 | ::DeleteObject(hRgnItem); 51 | } 52 | 53 | void UIRenderClip::UseOldClipBegin(HANDLE_DC hdc, UIRenderClip &clip) { 54 | ::SelectClipRgn(hdc, clip.m_impl->hOldRgn); 55 | } 56 | 57 | void UIRenderClip::UseOldClipEnd(HANDLE_DC hdc, UIRenderClip &clip) { 58 | ::SelectClipRgn(hdc, clip.m_impl->hRgn); 59 | } 60 | -------------------------------------------------------------------------------- /backend/win32/UIScrollBar.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | POINT UIScrollBar::GetCursorPos() const{ 6 | POINT pt = { 0 }; 7 | ::GetCursorPos(&pt); 8 | ::ScreenToClient(m_manager->GetPaintWindow(), &pt); 9 | return pt; 10 | } -------------------------------------------------------------------------------- /demo/360SafeDemo/360SafeRes/ComputerExamine.xml: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 |