【转】高分辨率屏幕远程桌面的时候屏幕内容过小解决方案

转载自:高分辨率屏幕远程桌面的时候屏幕内容过小,有哪位大神知道如何解决这个问题


因为现在新出的笔记本屏幕分辨率较高,使用远程桌面时由于两边分辨率不同,导致自己看到对方桌面的图片和文字都很小,特别影响体验。亲测解决办法如下:

1、修改注册表:

用运行-regedit编辑注册表,找到:

HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\SideBySide

新建DWORD,命名PreferExternalManifest,并双击设置值为1.

2、控制面板-文件资源管理器选项-查看-高级选项-隐藏已知文件类型的扩展名,去掉打勾。

3、到桌面右键新建-文本文档-确认。复制并粘贴如下代码,保存后修改文本名称为:mstsc.exe.manifest(后缀也修改为manifest了)。

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0" xmlns:asmv3="urn:schemas-microsoft-com:asm.v3">
<dependency>
<dependentAssembly>
<assemblyIdentity
type="win32"
name="Microsoft.Windows.Common-Controls"
version="6.0.0.0" processorArchitecture="*"
publicKeyToken="6595b64144ccf1df"
language="*">
</assemblyIdentity>
</dependentAssembly>
</dependency>
<dependency>
<dependentAssembly>
<assemblyIdentity
type="win32"
name="Microsoft.VC90.CRT"
version="9.0.21022.8"
processorArchitecture="amd64"
publicKeyToken="1fc8b3b9a1e18e3b">
</assemblyIdentity>
</dependentAssembly>
</dependency>
<trustInfo xmlns="urn:schemas-microsoft-com:asm.v3">
<security>
<requestedPrivileges>
<requestedExecutionLevel
level="asInvoker"
uiAccess="false"/>
</requestedPrivileges>
</security>
</trustInfo>
<asmv3:application>
<asmv3:windowsSettings xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">
<ms_windowsSettings:dpiAware xmlns:ms_windowsSettings="http://schemas.microsoft.com/SMI/2005/WindowsSettings">false</ms_windowsSettings:dpiAware>
</asmv3:windowsSettings>
</asmv3:application>
</assembly>

———————————————华丽分割

4、将这个文件放到指定路径中:C:\Windows\System32;找不到路径的,在桌面已经生成的远程桌面快捷方式,右键-属性-打开文件所在位置,就能看到C:\Windows\System32\mstsc.exe,将代码文件放到文件夹里,重启电脑,再次打开RemoteAPP和远程链接,Bingo!分辨率是不是正常了,虽然虚了一些,但是起码看得清楚!

【转】Android编程实现自定义ProgressBar样式示例(背景色及一级、二级进度条颜色)

转载自:Android编程实现自定义ProgressBar样式示例(背景色及一级、二级进度条颜色)


本文实例讲述了Android编程实现自定义ProgressBar样式。分享给大家供大家参考,具体如下:

效果图如下,本例中设置了第一级进度条和第二级进度条。

样式资源:progressbar_bg.xml,放在drawable文件夹下:

<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
  <!--3个层的顺序即为显示时的叠加顺序-->
  <!--背景色-->
  <item android:id="@android:id/background">
    <shape>
      <corners android:radius="5dip" />
      <solid android:color="#CCCCCC" />
    </shape>
  </item>
  <!--二级进度条的颜色-->
  <item android:id="@android:id/secondaryProgress">
    <clip>
      <shape>
        <corners android:radius="5dip" />
        <solid android:color="#88F56100" />
      </shape>
    </clip>
  </item>
  <!--一级进度条的颜色,也可以直接替换成图片-->
  <item android:id="@android:id/progress">
    <clip>
      <shape>
        <corners android:radius="5dip" />
        <solid android:color="#F56100" />
      </shape>
    </clip>
  </item>
</layer-list>

布局代码:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
  android:orientation="vertical"
  android:layout_width="match_parent"
  android:layout_height="match_parent">
  <ProgressBar
    android:id="@+id/progress_bar"
    style="?android:attr/progressBarStyleHorizontal"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_marginTop="100dp"
    android:minHeight="20dp"
    android:padding="10dp"
    android:progressDrawable="@drawable/progressbar_bg" />
</LinearLayout>

【转】Toast 在 Android 7.1 崩溃排查及修复

转载自:Toast 在 Android 7.1 崩溃排查及修复


崩溃详情

尝试复现

  • 通过崩溃信息从网上找到的一些论述,发现这个问题是因为主线程被阻塞了,而 Toast 没有及时销毁导致的,那么接下来让我们对它进行复现

  • 为什么出现这个问题,是因为 Toast 的显示是通过 Handler.sendMessage,所以这个操作是异步的,而 Thread.sleep 会阻塞主线程,从而导致 Handler.handleMessage 在接收到消息的时候 WindowToken 已经失效了
  • 经过实际的测试:如果是短吐司,sleep 2000 毫秒的时候还是会抛出异常,sleep 1500 毫秒则不会发生异常;如果是长吐司,sleep 3500 毫秒的时候也是会抛出异常,sleep 3000 毫秒的时候就不会发生异常
  • 由此可见,WindowToken 失效的时间是跟 Toast 的显示时长有关,如果是短吐司,那么 WindowToken 有效时长只能在 2 秒以内;如果是长吐司,那么 WindowToken 的有效时长只能在 3.5 秒以内

  • 然后再通过 WindowManager.addView 的时候,它会对 WindowToken 例行检查,如果是失效状态则会抛出异常给上层,而这个机制恰好是 Android 7.1 的时候才有的,谷歌那个时候并没有考虑到对 Toast 的一些处理。因为通过浏览 Android 7.0 和 Android 6.0 的源码,发现谷歌也是没有进行 try 处理,但是崩溃的机型却全是清一色的 Android 7.1

问题排查

  • 通过查看这个崩溃都是在 Android 7.1 的机型才会出现,那么我们可以对比 Android 7.1 的源码和 Android 8.0 看看

  • 通过追踪不同 API 等级的源码,发现这个问题在 Android 8.0 上面已经被被修复了
  • 通过查看 Toast 的源码,发现 Toast 其实就是一个 WindowManager,并且通过 Handler 来显示和隐藏。
  • 而产生崩溃的地方是在 handleShow 方法里面

  • 而 handleShow 方法是被 Toast 中的名为 TN 静态内部类中的 Handler 对象调用

进行修复

  • 那么解决这一问题的方式的思路是,将这个 Handler 对象通过反射获取到,然后使用静态代理的方式对它进行回调并对进行捕获异常

  • 最后经过验证,是 OK 的,已经没有崩溃的问题出现了。
  • 但是新的问题又出现了,我们以前写 Toast 是这样的
Toast.makeText(this, "666", Toast.LENGTH_LONG).show();
  • 但是如果为了修复这个崩溃问题,我们需要这样写
Toast toast = Toast.makeText(this, "666", Toast.LENGTH_LONG);
if (Build.VERSION.SDK_INT == Build.VERSION_CODES.N_MR1) {
    try {

        // 获取 mTN 字段对象
        Field mTNField = Toast.class.getDeclaredField("mTN");
        mTNField.setAccessible(true);
        Object mTN = mTNField.get(toast);

        // 获取 mTN 中的 mHandler 字段对象
        Field mHandlerField = mTNField.getType().getDeclaredField("mHandler");
        mHandlerField.setAccessible(true);
        final Handler mHandler = (Handler) mHandlerField.get(mTN);

        // 偷梁换柱
        mHandlerField.set(mTN, new Handler() {
            @Override
            public void handleMessage(Message msg) {
                // 捕获这个异常,避免程序崩溃
                try {
                    mHandler.handleMessage(msg);
                } catch (WindowManager.BadTokenException ignored) {}
            }
        });

    } catch (IllegalAccessException | NoSuchFieldException ignored) {}
}

toast.show();
  • 这样写感觉心好累,不想这样写,有没有一种方式可以一劳永逸?
  • 答案当然是有了,使用第三方 Toast 封装的框架:https://github.com/getActivity/Toaster,框架内部已经处理了这个问题,调用者无需关心此问题。
  • 使用框架后,可以这么写
Toaster.show("666");
  • 还是一句代码,就问你 6 不 6

问题总结

  • 问题描述:Toast 在主线程阻塞情况下会导致 WindowToken 失效,从而导致应用崩溃
  • 涉及范围:所有 Android 版本为 7.1 的用户,并且项目中使用了原生 Toast 的地方都有可能触发崩溃
  • 解决方案:不直接使用原生 Toast,而使用第三方 Toast 框架

【转】包管理工具npm、yarn以及nvm简介

转载自:包管理工具npm、yarn以及nvm简介及简单使用


基本概念

在使用npm、yarn等包管理工具之前,我们首先了解一些基本的概念

模块(module)

通常以单个文件形式存在的功能片段,入口文件通常称之为入口模块或主模块

库(library,简称lib)

以一个或多个模块组成的完整功能块,为开发中某一方面的问题提供完整的解决方案

包(package)

包含元数据的库,这些元数据包括:名称、描述、git主页、许可证协议、作者、依赖等等

npm

npm 全称为 node package manager,即 node 包管理器,它运行在 node 环境中,让开发者可以用简单的方式完成包的查找、安装、更新、卸载、上传等操作。几乎可以这样认为,前端所有的包管理器都是基于 npm 的,目前,npm 即是一个包管理器,也是其他包管理的基石。

官网:https://www.npmjs.com/

这个网址非常常用,因为以后的常用插件都是在官网中查找,查看使用方法

yarn

yarn 是由Facebook、Google、Exponent 和 Tilde 联合推出了一个新的 JS 包管理工具,它仍然使用 npm 的registry,不过提供了全新 CLI 来对包进行管理

yarn 官网:https://www.yarnpkg.com/zh-Hans/

在过去npm具有很多缺点,比如依赖目录嵌套太深遍历问题,npm是串行下载的下载速度慢等等问题,于是就有了yarn。

npm6 之后,可以说npm已经和yarn非常接近,甚至没有差距了。很多新的项目,又重新从yarn转回到npm。

cnpm

为解决国内用户连接npm registry缓慢的问题,淘宝搭建了自己的registry,即淘宝npm镜像源。

官网地址:https://npm.taobao.org/

但是现在并没有什么卵用了,因为npm已经支持修改registry了

nvm

nvm并非包管理器,它是用于管理多个node版本的工具。在实际的开发中,可能会出现多个项目分别使用的是不同的node版本,在这种场景下,管理不同的node版本就显得尤为重要。nvm就是用于切换版本的一个工具

下载和安装
最新版下载地址:https://github.com/coreybutler/nvm-windows/releases

下载nvm-setup.zip后,直接安装。以下命令判断是否安装成功

nvm -v

为了加快下载速度,建议设置淘宝镜像
node淘宝镜像:https://npm.taobao.org/mirrors/node/
npm淘宝镜像:https://npm.taobao.org/mirrors/npm/

nvm node_mirror https://npm.taobao.org/mirrors/node/
nvm npm_mirror https://npm.taobao.org/mirrors/npm/

【转】bat批处理笔记(二)-start命令

转载自:bat批处理笔记(二)-start命令


start命令可以在命令行下运行一个程序,可以打开盘符,文件,文件夹,网址,程序。

1.打开盘符:

start C:
start /max E: rem 最大化打开
start /min F: rem 最小化打开

2.打开文件:

start "" "C:\Users\Jerry\Desktop\kali source.txt"

注: 路径中有空格时,不仅路径要加双引号,路径之前也要加(路径之前的空双引号表示空标题)

3.打开文件夹:

start C:\Users\Jerry\Desktop\

4.打开网址:

start www.baidu.com

5.打开程序:

start C:\Users\Jerry\Desktop\雨燕投屏.lnk

【转】android实现扫码枪功能

转载自:android实现扫码枪功能


扫码枪扫码效果等同于键盘录入,会回调dispatchKeyEvent键盘按下事件。

开发环境:有线扫码枪,支持二维码

1. 接收数据

 /**
     * 扫码枪扫码处理
     */
    @Override
    public boolean dispatchKeyEvent(KeyEvent event) {
        if (event.getAction() == KeyEvent.ACTION_DOWN) {
            int keyCode = event.getKeyCode();
            char aChar = (char) event.getUnicodeChar();
            if (aChar != 0) {
                mStringBufferResult.append(aChar);
            }
            mHandler.removeCallbacks(mScanningFishedRunnable);
            //若为回车键,直接返回
            if (keyCode == KeyEvent.KEYCODE_ENTER) {
                mHandler.post(mScanningFishedRunnable);
            } else {
                //延迟post,若500ms内,有其他事件
                mHandler.postDelayed(mScanningFishedRunnable, 500L);
            }
            return true;
        }
        return super.dispatchKeyEvent(event);
    }

2. 处理数据

 /**
 * 二维码信息对象
 */
   private QRCode qrCodeBean;
   /**
   * 二维码信息原始数据容器
   */
   private StringBuilder mStringBufferResult = new StringBuilder();
   private Handler mHandler = new Handler();
 
   private Runnable mScanningFishedRunnable = new Runnable() {
        @Override
        public void run() {
            scanOk = false;
            String qrcode = mStringBufferResult.toString();
            if (!TextUtils.isEmpty(qrcode)) {
                // 扫码确定参数
                Gson gson = new Gson();
                try {
                    qrCodeBean = gson.fromJson(qrcode, QRCode.class);
                    // 你的代码...
                    // 如果要支持中文,数据用可以URLEncoder/URLDecoder编解码
                } catch (JsonSyntaxException e) {
                    // 解析失败...
                } catch (UnsupportedEncodingException e) {
                    // 解码失败...
                } finally {
                    mStringBufferResult.setLength(0);
                }
            }
        }
    };

【转】Android按键事件KeyEvent的分发处理流程解析

节选自:Android按键事件KeyEvent的分发处理流程解析


1. 在 Activity 里重写 dispatchKeyEvent()—-最常用

举个栗子:

这在 Tv 开发中是很常见的,经常会在 Activity 里重写 dispatchKeyEvent(),然后要么去预先处理一些工作,要么就是对特定的按键进行拦截。

上面这段代码能看懂么?如果你已经清楚这代码是对左右方向按键的拦截,那么你清楚各种 return 的作用么,为什么又有 return true,又有 return false,还有 return super.dispatchKeyEvent() 的?

先说结论:这里的 return true 和 return false 都能起到按键拦截的作用,也就是子 View 不会接收到事件的分发或处理,Activity 的 onKeyDown/Up() 也不会收到任何消息。

要明白这点,先得搞清楚什么是 return, return 是返回的意思,什么情况下需要返回,不就是调用你的那个方法需要你给个反馈,所以 return 的消息是给上一级的调用者的,所以 return 只会对上一级的调用者的行为有影响。调用 Activity.dispatchKeyEvent() 的是 DecorView 的 dispatchKeyEvent() 里,如下图:

那么,既然 Activity 返回 true 或 false 都只对 DecorView 的行为有影响,那么为什么都能起到拦截事件分发的作用呢?

这是因为,事件的分发逻辑其实是在 Activity.java 的 dispatchKeyEvent() 里实现的,如果你重写了 Activity 的 dispatchKeyEvent() 方法,那么根据

Java 的特性程序就会执行你写的 dispatchKeyEvent(),而不会执行基类 Activity.java 的方法,因此你在重写的方法里没有自己实现事件的分发逻辑,事件当然就停止分发了啊。这也是为什么返回 super.dispatchKeyEvent() 时事件会继续分发,因为这最终会调用到基类 Activity.java 的 dispatchKeyEvent() 方法来执行事件分发的逻辑。

既然在 Activity 里返回 true 或 false 都表示拦截,那么有什么区别么?

当然有,因为会影响 DecorView 的行为,比如我们点击遥控器的方向键时界面上的焦点会跟随着移动,这部分逻辑其实是在 DecorView 的上一级调用者中实现的,Activity 返回 true 的话,会导致 DecorView 也返回 true,那么上一级将根据 DecorView 返回 true 的结果停止焦点的移动,这就是我们常见的在 Activity 里重写 dispatchKeyEvent() 返回 true 来实现停止焦点移动的原理。那么,如果 Activity 返回的是 false,DecorView 也跟随着返回 false,那么上一级会继续执行焦点移动的逻辑,表现出来的效果就是,界面上的焦点仍然会移动,但不会触发 Activity 和 View 的事件分发和处理方法,因为已经被 Activity 拦截掉了。

最后,还有一个问题,在 View 或 ViewGroup 里面重写 dispatchKeyEvent() 作用会跟 Activity 一样么?

return true 或 false 或 super 的含义还是一样的,但这里要明白一个层次结构。上层:Activity,中层:ViewGroup,下层:View。

不管在哪一层重写 dispatchKeyEvent(),如果返回 true 或 false,那么它下层包括它本层都不会接收到事件的分发处理,但是它的上层会接收。因为拦截的效果只作用于该层及下层,而上层只会根据你返回的值,行为受到影响。

比如在 ViewGroup 中返回 true,Activity 的 onKeyDown/Up() 就不会被触发,因为被消费了;如果返回 false,那么事件就交由 Activity 处理。但不管返回 true 或 false,子 View 的 dispatchKeyEvent()、各种 onClick() 等事件处理方法都不会被触发到了。

Cocos Creator 接入 Steam SDK

1.下载 Steam SDK

2.解压后得到 sdk 文件夹

3.把 sdk 文件夹中的 public 文件夹放在 .sln 工程同一个文件夹下

4.把 sdk 文件夹中的 redistributable_bin 文件夹中的 steam_api.dll 和 steam_api.lib 复制到 libs 目录

build\jsb-default\frameworks\cocos2d-x\external\win32\libs

5.使用VS2017打开工程

6.配置项目属性(Debug和Release都需要配置)

C/C++ -> 常规 -> 附加包含目录 -> $(ProjectDir)public\steam

链接器 -> 输入 -> 附加依赖项 -> steam_api.lib

参考链接:

【超详尽】有关Cocos Creator打windows 10包且接入STEAM需要注意的事项

Steam官方教学