.版本 2 .子程序 取系统DPI缩放率, 整数型, , 修改版 .局部变量 DPI百分比 DPI百分比 ＝ 取数值zc项 (3, “Control Panel\Desktop\WindowMetrics\AppliedDPI”, ) .判断开始 (DPI百分比 ＝ 24) ' 1 DPI百分比 ＝ 25 .判断 (DPI百分比 ＝ 48) ' 2 DPI百分比 ＝ 50 .判断 (DPI百分比 ＝ 72) ' 3 DPI百分比 ＝ 75 .判断 (DPI百分比 ＝ 96) ' 4 DPI百分比 ＝ 100 .判断 (DPI百分比 ＝ 120) ' 5 DPI百分比 ＝ 125 .判断 (DPI百分比 ＝ 144) ' 6 DPI百分比 ＝ 150 .判断 (DPI百分比 ＝ 168) ' 7 DPI百分比 ＝ 175 .判断 (DPI百分比 ＝ 192) ' 8 DPI百分比 ＝ 200 .判断 (DPI百分比 ＝ 216) ' 9 DPI百分比 ＝ 225 .判断 (DPI百分比 ＝ 240) ' 10 DPI百分比 ＝ 250 .判断 (DPI百分比 ＝ 264) ' 11 DPI百分比 ＝ 275 .判断 (DPI百分比 ＝ 288) ' 12 DPI百分比 ＝ 300 .默认 DPI百分比 ＝ 100 .判断结束 返回 (DPI百分比)
代码转字符：https://blog.l54l.com/voldp/180.html)(整数)取字符 ("B", 0)原理也是使用了强制转换。
原理是使用强制转换。信息框 (到文本 ((字符)66))字符取代码方法：/voldp/182.html
升级了handsome9.0.2版本，测试时光机时发现在很多地方支持emoji了。但问题来了，在PC下怎么输入呢？ 试了用搜狗输入发现还是成中文，无法显示emoji表情。下面一起学习 Windows下使用在windows10以上的系统，只要按住win + 。就可以调出emoji表情。Macos下使用使用快捷键[⌘Control+Command+Space]打开emoji键盘。
windows平台下通过注册表获取特定后缀名的默认图标
Windows操作系统的文件图标是根据文件的类型，或者说文件扩展名读取的。下面是一个采用此方法读取指定类型文件图标和类型描述信息的示例。介绍下实现方法：例如一个.txt扩展名的文件图标，通过注册表项HKCR/.txt找到该类型为txtfile再通过HKCR/txtfile得到它的描述信息是“文本文档”（你的操作系统也可能会显示为“Text Document”，或者其他的描述信息）通过HKCR/txtfile/DefaultIcon得到该类型的缺省图标的文件和图标索引信息（注意，你的操作系统也许与截图中的值内容不同）然后我们利用系统API函数ExtractIconExW将图标提取出来就可以了。然而可执行文件exefile类型的图标（通常扩展名为.exe）会取自自身的文件中的第一个图标，因为我们按扩展名取图标，并没有可执行文件本身的路径，那么用一个默认的共同exe图标代替，这里假设为系统目录shell32.dll文件中索引号为2的图标。摘取代码如下：/// /// 通过扩展名得到图标和描述 /// /// 扩展名(如“.txt”) /// 得到大图标 /// 得到小图标 /// 得到类型描述或者空字符串 void GetExtsIconAndDescription(string ext, out Icon largeIcon, out Icon smallIcon, out string description) { GetDefaultIcon(out largeIcon, out smallIcon); //得到缺省图标 description = ""; //缺省类型描述 RegistryKey extsubkey = Registry.ClassesRoot.OpenSubKey(ext); //从注册表中读取扩展名相应的子键 if (extsubkey == null) return; string extdefaultvalue = extsubkey.GetValue(null) as string; //取出扩展名对应的文件类型名称 if (extdefaultvalue == null) return; if (extdefaultvalue.Equals("exefile", StringComparison.OrdinalIgnoreCase)) //扩展名类型是可执行文件 { RegistryKey exefilesubkey = Registry.ClassesRoot.OpenSubKey(extdefaultvalue); //从注册表中读取文件类型名称的相应子键 if (exefilesubkey != null) { string exefiledescription = exefilesubkey.GetValue(null) as string; //得到exefile描述字符串 if (exefiledescription != null) description = exefiledescription; } System.IntPtr exefilePhiconLarge = new IntPtr(); System.IntPtr exefilePhiconSmall = new IntPtr(); NativeMethods.ExtractIconExW(Path.Combine(Environment.SystemDirectory, "shell32.dll"), 2, ref exefilePhiconLarge, ref exefilePhiconSmall, 1); if (exefilePhiconLarge.ToInt32() > 0) largeIcon = Icon.FromHandle(exefilePhiconLarge); if (exefilePhiconSmall.ToInt32() > 0) smallIcon = Icon.FromHandle(exefilePhiconSmall); return; } RegistryKey typesubkey = Registry.ClassesRoot.OpenSubKey(extdefaultvalue); //从注册表中读取文件类型名称的相应子键 if (typesubkey == null) return; string typedescription = typesubkey.GetValue(null) as string; //得到类型描述字符串 if (typedescription != null) description = typedescription; RegistryKey defaulticonsubkey = typesubkey.OpenSubKey("DefaultIcon"); //取默认图标子键 if (defaulticonsubkey == null) return; //得到图标来源字符串 string defaulticon = defaulticonsubkey.GetValue(null) as string; //取出默认图标来源字符串 if (defaulticon == null) return; string[] iconstringArray = defaulticon.Split(','); int nIconIndex = 0; //声明并初始化图标索引 if (iconstringArray.Length > 1) if (!int.TryParse(iconstringArray[1], out nIconIndex)) nIconIndex = 0; //int.TryParse转换失败，返回0 //得到图标 System.IntPtr phiconLarge = new IntPtr(); System.IntPtr phiconSmall = new IntPtr(); NativeMethods.ExtractIconExW(iconstringArray[0].Trim('"'), nIconIndex, ref phiconLarge, ref phiconSmall, 1); if (phiconLarge.ToInt32() > 0) largeIcon = Icon.FromHandle(phiconLarge); if (phiconSmall.ToInt32() > 0) smallIcon = Icon.FromHandle(phiconSmall); } /// /// 获取缺省图标 /// /// /// private static void GetDefaultIcon(out Icon largeIcon, out Icon smallIcon) { largeIcon = smallIcon = null; System.IntPtr phiconLarge = new IntPtr(); System.IntPtr phiconSmall = new IntPtr(); NativeMethods.ExtractIconExW(Path.Combine(Environment.SystemDirectory, "shell32.dll"), 0, ref phiconLarge, ref phiconSmall, 1); if (phiconLarge.ToInt32() > 0) largeIcon = Icon.FromHandle(phiconLarge); if (phiconSmall.ToInt32() > 0) smallIcon = Icon.FromHandle(phiconSmall); }
操作步骤配置Windows Server版本的防火墙功能方法，参考如下步骤。本文以Windows Server 2008系统版本为例。功能一：允许程序或功能通过Windows防火墙远程登录Windows实例。单击开始 > 控制面板 > 系统和安全 > Windows 防火墙。单击允许程序或功能通过 Windows 防火墙。单击允许运行另一组程序。在添加程序页面，程序（P）标签下，双击指定应用程序即可。如果在该标签下没有查看到指定的应用程序，可以单击浏览，在文件系统中查找到指定应用程序文件，双击该文件即可。功能二：允许或禁止特定本地端口访问远程登录Windows实例。单击开始 > 控制面板 > 系统和安全 > Windows 防火墙。单击高级设置。单击入站规则 > 新建规则。单击规则类型，页面右侧选择端口。单击下一步，页面右侧选择端口类型TCP或UDP，选择特定本地端口（S），输入要允许或禁止的本地端口号，比如“8080”。单击下一步，选择阻止连接或允许连接。说明如果端口入站规则缺省规则是允许，那么选择阻止连接表示关闭该端口。如果端口入站规则缺省规则是阻止，那么选择允许连接表示开启该端口。单击下一步，选择合适的作用域，输入规则名称后单击完成。说明域为根据本机的网络环境判断，默认全选。功能三：限制IP地址的访问权限远程登录Windows实例。单击开始 > 控制面板 > 系统和安全 > Windows 防火墙。单击高级设置。单击入站规则 > 新建规则。单击自定义(C) > 下一步。选择所有程序(A)或此程序路径(T)，单击下一步。说明所有程序指本机中所有程序，此程序路径指特定的单个程序，现场操作请根据需要选择所有程序或此程序路径。接受默认设置，单击下一步。在此规则应用于哪些远程IP地址？下选择下列IP地址，单击添加。输入需要过滤的IP，单击确定，再单击下一步。选择阻止连接或允许连接。单击下一步，选择合适的作用域，输入规则名称后单击完成。功能四：允许特定IP访问本机端口远程登录Windows实例。单击开始 > 控制面板 > 系统和安全 > Windows 防火墙。单击高级设置。单击入站规则，查找开启的本地端口，右键单击指定的端口，单击属性，单击属性分页作用域。选择远程IP地址内的下列IP地址。单击添加，选择此IP地址或子网(A) ，输入需要过滤的IP，单击确定。功能五：阻止特定IP地址（段）访问服务器远程登录Windows实例。单击开始，输入gpedit.msc，单击确定，打开本地组策略编辑器页面窗口。双击计算机配置 > Windows 设置 > 安全设置。右键单击IP 安全策略，在本地计算机 > 创建 IP 安全策略。单击下一步，根据提示输入合适的名称和描述。默认单击下一步 > 下一步 > 完成。新建的IP安全策略，单击添加(D)，根据提示单击下一步。在指定IP安全规则的隧道终结点，选择此规则不指定隧道(T)。单击下一步，在选择网络类型，选择所有网络连接。单击下一步，单击添加(A)。根据提示在IP筛选器列表，输入对应信息，单击添加(A) 创建新IP筛选器。在源地址(S) 处，单击选择一个特定的 IP 地址或子网，根据提示在IP地址或子网(I)处，输入对应的IP地址或子网，单击下一步。在目标地址(D)处，单击选择任何IP地址，单击确定。在选择协议类型（S）处，选择任何，单击下一步 > 完成。在IP筛选器列表(I)，选择新建的IP筛选器，单击确定。在筛选器操作(C)，单击下一步，单击添加(A)，创建新的筛选器操作。根据提示单击下一步，输入对应的名称和描述。单击下一步，选择阻止（L）。单击下一步，选择不允许不安全的通讯。单击下一步，选择完整性和加密（E）。单击下一步，根据提示单击完成。创建筛选器操作成功后，单击选择该新建筛选器操作，单击下一步，根据提示单击完成。单击确定，这样一个阻止指定IP地址（段）访问服务器的策略添加完成。
UIAutomation是苹果公司发布的一个测试框架，主要用于自动化测试iOS和OS X应用的UI交互情况。它使用了使用灵活、易于扩展的JavaScript作为其主要的脚本语言，可以用使用者快速上手。UIAutomation是Xcode中测试工具集Instruments中的一个测试工具，因为是内置在Xcode中的所以只要MAC安装了Xcode即可使用。打开TestAutomation.xcodeproj后，注意要到Build Setting中设置ios deployment target修改为iOS 4.2以上，如iOS 9.0否则开始编译时会出现以下错误。ld: -pie can only be used when targeting iOS 4.2 or later clang: error: linker command failed with exit code 1 (use -v to see invocation)Build Setting启动Instruments(Product->Profile)，或者按command+i，出现profiling template的选择画面，选择Automation，按Choose进行下一步。Create ProfilingInstruments窗口出现后，按右边的齿轮图标可以看到脚本列表，默认有一个New Script在里面，选中后可以在左边的窗口编辑脚本，下面的按钮执行脚本。Instruments输入以下代码来完成第一个UIAutomation测试用例var target = UIATarget.localTarget(); var app = target.frontMostApp(); var window = app.mainWindow(); target.logElementTree();按下执行后，如无意外在Editor Log窗口中可以看到执行的日志信息。Run Script接下来，可以跟着原文学习更多UIAutomation的操作。这里要提醒的是，原文有一段Test-1.js代码，如下var testName = "Test 1"; var target = UIATarget.localTarget(); var app = target.frontMostApp(); var window = app.mainWindow(); UIALogger.logStart( testName ); app.logElementTree(); //-- select the elements UIALogger.logMessage( "Select the first tab" ); var tabBar = app.tabBar(); var selectedTabName = tabBar.selectedButton().name(); if (selectedTabName != "First") { tabBar.buttons()["First"].tap(); } //-- tap on the text fiels UIALogger.logMessage( "Tap on the text field now" ); var recipeName = "Unusually Long Name for a Recipe"; window.textFields()[0].setValue(recipeName); target.delay( 2 ); //-- tap on the text fiels UIALogger.logMessage( "Dismiss the keyboard" ); app.logElementTree(); app.keyboard().buttons()["return"].tap(); var textValue = window.staticTexts()["RecipeName"].value(); if (textValue === recipeName){ UIALogger.logPass( testName ); } else{ UIALogger.logFail( testName ); }直接执行这段代码会返回issue（或error），提示Cannot perform action on invalid element：UIAElementNil from target.frontMostApp().keyboard().buttons()["return"]。错误在app.keyboard().buttons()["return"].tap();通过app.logElementTree();这行可以看到所有的元素,"return"键的真正名称是"Return"所以只要将上面的代码改为下面的代码即可。app.keyboard().buttons()["Return"].tap();
Cocos2d-x存在MenuItemFont类，用于创建一个Label按钮，当要用文字而不是图片来制作菜单按钮时，MenuItemFont就很有用了。当使用MenuItemFont需要设置字体和字号时，通常会习惯调用setFontName()和setFontSize()函数，实际上这两个函数是静态函数，分别修改全局字体名和全局字体大小，即改变默认的设置。如果是对象调用了这两个静态方法，那么只有下一次create MenuItemFont对象有效果。使用MenuItemFont时如果需要设置字体和字号，应该调用setFontNameObj()和setFontSizeObj()函数。以下代码，执行后button1为默认字体和默认字号，buuton2字体为黑体，字号为60。auto button1 = MenuItemFont::create("Button I"); backButton->setFontName("黑体"); backButton->setFontSize(60); auto button2 = MenuItemFont::create("Button II"); backButton->setFontName("微软雅黑"); backButton->setFontSize(36);以下代码，执行后button1字体为黑体，字号为60，buuton2字体为微软雅黑，字号为36。auto button1 = MenuItemFont::create("Button I"); backButton->setFontNameObj("黑体"); backButton->setFontSizeObj(60); auto button2 = MenuItemFont::create("Button II"); backButton->setFontNameObj("微软雅黑"); backButton->setFontSizeObj(36);以下代码将和上面代码一样，执行后button1字体为黑体，字号为60，buuton2字体为微软雅黑，字号为36。MenuItemFont::setFontName("黑体"); MenuItemFont::setFontSize(60); auto button1 = MenuItemFont::create("Button I"); MenuItemFont::setFontName("微软雅黑"); MenuItemFont::setFontSize(36); auto button2 = MenuItemFont::create("Button II");
#include "extensions\cocos-ext.h"在3.4版本中，项目的include相关目录早已经添加了extensions文件夹在其中，在Visual Studio的Project->Properties->Configuration Properties->C/C++->General->Additional Include Directories中，可以看到有$(EngineRoot)extensions;在其中。所以，应用EditBox相关的头文件应该是#include "cocos-ext.h"接下来，添加USING_NS_CC_EXT;然后就可以用EditBox::create()创建EditBox，当然完整的创建方法是有参数的。EditBox的create方法有两个，以下是UIEditBox.h中关于create方法的声明。/** * create a edit box with size. * @return An autorelease pointer of EditBox, you don't need to release it only if you retain it again. */ static EditBox* create(const Size& size, Scale9Sprite* normalSprite, Scale9Sprite* pressedSprite = nullptr, Scale9Sprite* disabledSprite = nullptr); /** * create a edit box with size. * @return An autorelease pointer of EditBox, you don't need to release it only if you retain it again. */ static EditBox* create(const Size& size, const std::string& pNormal9SpriteBg, TextureResType texType = TextureResType::LOCAL);在使用Scale9Sprite上遇到了困难，好在发现有第二个create方法。在编译的时候，遇到了fatal error C1083: Cannot open include file: 'extensions/......错误，问题在项目的include相关目录早已经添加了extensions，所以有其它头文件有#include "extensions/..."的话一律会出现error C1083。只要在property->configure property->C/C++->general->additional include directory中添加$(EngineRoot);就可以解决问题了。本来在cocos2d-x中调用EditBox应该是很简单的事情，因为cocos2d-x3.0版本后更新频繁改动，在百度上搜到的教程大多数都跟不上了。现在我所使用的Cocos2d-x版本是3.4，不知道更新的版本是否有其它变动。cocos2d-x 3.4的EditBox包含在cocos-ext.h中，具体点应该是extensions\cocos-ext.h，大部分关于EditBox的教程会添加
这几天在折腾电脑的远程，因为总怕突然单位有啥突发的事儿嘛，然后自己电脑上又没有环境，然后就惦着直接能够遥控给主板上电直接开机并且远程。这个主板上电直接开机倒是挺好办的，主板设置里就有，设置一个上电自动开机，然后 买一个智能插座就全搞定了。但是我发现一个问题，开机了是开机了，但是向日葵之类的远程软件是需要在用户登陆时才会启动服务的。那我电脑有密码呢，我又不想取消掉密码，这咋整呢。想了一会，感觉微软自己的mstsc也许可以，但是单位的个人工作电脑并没有公网ip，那外网远程连接不是就寄了？得，弄个内网穿透吧。伤情最是晚凉天，憔悴斯人不堪怜，邀酒摧肠三杯醉，寻香惊梦五更寒，钗头凤斜卿有泪，荼蘼花了我无缘，小楼寂寞新雨月，也难如勾也难圆定场诗。我写代码的能卖你生定场诗？咱废话就不多说了——这废话就不少了，直接书归正文儿吧。提前注释：了解Linux守护进程而且不需要的直接跳到三就完事儿一、NodeJS为啥写Frp要写NodeJS？因为frp在linux上运行的时候是一个前台应用。只要你打开这个应用的bash一退出，欸，他就没了\~所以我主要是为了弄个pm2作为这个frp的守护进程，让frp作为nohup应用启动，防止自己退出了就。这里以CentOS 7为例：咱首先确定一下咱们有C++的编译器，一会儿下了源码要编译用：yum -y install gcc gcc-c++ kernel-devel ```` （我用的是8.11.3版本，当前lts版本为16.13.2，要安装的话需要升级GCC，升级太麻烦了我懒得升级反正就是用一个npm，如果升级GCC安装新版本可以看这个：[https://blog.l54l.com/Linux/116.html](https://) 然后下载NodeJS的源码压缩包： wget https://nodejs.org/dist/v8.11.3/node-v8.11.3.tar.gz 下载完以后咱就是说直接一个解压缩： ``` tar -xzf node-v8.11.3.tar.gz ``` 接着删除压缩包（不删也行），进入新解压的文件夹，编译之： ``` #删除当前压缩包 rm node-v8.11.3.tar.gz #进入新解压的文件夹 cd node-v8.11.3 #编译 ./configure make ``` 这步时间有点久，我们可以去给鱼缸换个水，给猫洗个澡，然后把手从乌龟嘴里拽出来... 好不容易把手指头扯出来了，我们去贴个创可贴，回来看看基本差不多完成了。 继续，使用编译出来的文件进行安装(这个快)： ``` make install ``` 尝试查看当前是否安装成功： ``` npm -v #5.6.0 ``` 嘚，nice。 ### 二、安装pm2 咱就是说，有了npm以后安装pm2分分钟的事儿： ``` npm install pm2 -g ``` 然后可以将pm2设置为开机启动，不过这个设不设置都行，看个人： ``` #设置开机启动 pm2 startup #取消开机启动 pm2 unstartup ``` 使用pm2打开应用的方式： ``` #启动应用 pm2 start "启动命令" --name 设定应用名称 #保存当前应用列表 pm2 save #查看应用日志 pm2 log ``` ### 三、Frp 废话这么多终于入了正题儿了... 咱可以先去https://github.com/fatedier/frp/releases看看，当前版本啥的... 另外，linux和windows配置大同小异（其实根本就没区别=-=），我就按照我这边之前弄的方式说了啊，服务端linux，客户端windows（谁还记得我是为了啥弄这玩意儿的） linux下载： ``` wget https://github.com/fatedier/frp/releases/download/v0.38.0/frp_0.38.0_linux_amd64.tar.gz ``` 下载完成以后依旧是解压： ``` tar -xzf frp_0.38.0_linux_amd64.tar.gz mv frp_0.38.0_linux_amd64.tar.gz ``` 我们这边用的是服务端，所以调整frps.ini： ``` cd frp_0.38.0_linux_amd64 vim frps.ini ``` 参数在这边： ``` [common] #服务端端口 bind_port = <端口> #ipv4过滤 bind_addr = <允许通过的ipv4地址，不拦截默认0.0.0.0> #客户端连接认证方式 authentication_method = token token = <你自己设置的token> #网页控制台相关 dashboard_port = <控制台端口> dashboard_user = <控制台登陆用户名> dashboard_pwd = <控制台登陆密码> ``` 另外，因为这些东西都是明文保存在服务器上的，所以个人建议密码和token不要用其他平台的常用密码或者是通过某些加密算法先过一遍 然后启动，服务器这边的设置就可以啦！ **记得打开防火墙！！！** ``` #单纯的打开 ./frps -c ./frps.ini #使用pm2 pm2 start "./frps -c ./frps.ini" --name FrpServer ``` 客户端这边也差不多，去https://github.com/fatedier/frp/releases下载**frp\_0.38.0\_windows\_amd64.zip，下载完以后解压，打开文件夹里面的frpc.ini** ``` [common] server_addr = <服务器公网ip> server_port = <服务器端口> authentication_method = token token = <刚才服务器上设置的token> [RDP] #比如，我这边弄的是远程所以local_port是3389 #type还有http，udp，https之类的东西 type = tcp local_ip = 127.0.0.1 local_port = <本地要被映射的端口> remote_port = <服务器的映射的端口> ``` 启动的话就在当前文件夹打开cmd，输入： ``` frpc -c frpc.ini ``` 然后我的话这边是直接扔到计划任务里去执行的，不知道在哪儿的可以按win+r打开运行输入： ``` %windir%\System32\compmgmt.msc ``` 然后找左边的计算机管理->系统工具->任务计划程序->任务计划程序库： ![](https://blog.l54l.com/usr/uploads/2024/11/257238819.png) 点击右边的创建任务： 在常规选项卡选择“不管用户是否登录都要运行”，并勾选“使用最高权限运行”； 在触发器选项卡新建，在弹出窗口的“开始任务”中选择“启动时”； 在操作选项卡新建，在”程序和脚本“中选择刚才frpc.ini所在文件夹下的frpc.exe， ”添加参数“输入 -c frpc.ini，”起始于“中输入刚才frpc.ini所在文件夹 最后确定就可以啦！ 最后重启电脑，在浏览器输入[服务器公网ip:端口号](%E6%9C%8D%E5%8A%A1%E5%99%A8%E5%85%AC%E7%BD%91ip:%E7%AB%AF%E5%8F%A3%E5%8F%B7)，并输入刚才在服务器端设置的dashboard账号密码： ![](https://blog.l54l.com/usr/uploads/2024/11/3145141894.png) 在主页可以看到ClientCounts和ProxyCounts为1 我滴任务，完成老！