カテゴリー: Development

  • Ctrl押しっぱなし問題

    バグ修正

    • Ctrlキーの押下が解除されない

    この件、AutohotKey界隈ではよく知られた現象らしく、Ctrlキー以外にも修飾キー全般で押しっぱなしになる不具合が発生する模様。

    ググると沢山情報が出てくる。

    • AutoHotkey:キー押しっぱなし病・ホットキーすり抜け病対策の研究
    • AutoHotkeyの押しっぱなし問題
    • 快適キーボード操作のためのキーカスタマイズ 〜AutoHotKeyのキー押しっぱなし問題とScrollLockの非推奨~
    • 【AutoHotkey】キーが押しっぱなしになる現象の対策メモ(2024年6月最新版)
    • AutoHotkeyでShiftの単押しと修飾キーとしての押しっぱなしを別のキーマップにする
    • AutoHotkeyを始めるなら最初にこれを書いておこう

    ・・・

    機能修正

    SendMode "Event"
    
    ; 不具合対処
    ; 稀に修飾キーが押下した状態のままになる現象が発生する。
    ; ホットキー終了時に必ずCtrl/Altキーを上げる。
    sendWrap(key)
    {
        try
            Send key
        finally
            Send "{Ctrl Up}"
    }
    setWindowPositionWrap(windowPosition, monitorNum*)
    {
        try
            if (monitorNum.Length > 0)
                setWindowPosition(windowPosition, monitorNum[1])
            else
                setWindowPosition(windowPosition)
        finally
            Send "{Alt Up}"
    }
    ^!r:: {
        Send "{Ctrl Down}"
        Send "{Ctrl Up}"
        Send "{Alt Down}"
        Send "{Alt Up}"
        Reload
    }

    現象がまったく出なくなるような対処方法はないようだけど、SendをSendEventに変更したら発生頻度が下がったとの情報があったので「SendMode “Event”」の1行を追加した。

    また、send/setWindowPosition関数をWrapしてホットキーの終了時に無条件でCtrl/AltのUpイベントを発行するように修正した。無条件でUpイベントが発生することによる副作用が懸念されるけれど押しっぱなしになるよりは良いかと思われる。

    暫定対処で追加したCtrl+Alt+Rキーの処理は残してAltキーの対処も追加しておいた。

    これでも再発するならsleepを入れたり、修飾キーをF13~F14キーに割り当てたり、別の方法で試行錯誤しながら修正していくことになる。

    しばらく様子見です。

    作ったもの

    keyremap_20241222.zip

  • キーのリマッピング

    自分用に修正したので貼っておこー  

    バグ修正

    • Ctrlキーの押下が解除されない

    エレコムのキーボードに変えてからCtrlキーを使ったホットキーでタイポした場合に上記の不具合が顕在化する場合がある。

    再現方法不明。発生頻度は高くない。RealforceやHHKBでは発生しないので安いキーボードのスイッチが原因と思われる。

    チャタリングが発生する

    AutoHotkeyを最新バージョンに入れ替えても改善されず。

    Downloads

    機能追加

    スクリプトでの対処はできないので現象発生時のリカバリー用に以下のホットキーを追加した。

    ^!r:: {
        Send "{Ctrl down}"
        Sleep 100
        Send "{Ctrl up}"
        Sleep 100
        Reload
    }

    Ctrl+Alt+Rキー:ソフトウェア的にCtrlキーを押下してスクリプトをリロードする。

    作ったもの

    keyremap_20241215.zip

  • kozawa.tokyoドメイン更新完了のお知らせ

    ドメイン更新メールきた。

    2019年:106 円
    2020年:1,012 円
    2021年:1,628 円
    2022年:1,628 円
    2023年:1,628 円
    2024年:2,002 円
    2025年:3,200 円 <= これ

    高くなりすぎだわ。.tokyo 止めようかな… kozawa 辞めようかな… 🤔

  • 「Python」で簡単にGUIを構築できる国産フレームワーク「TkEasyGUI」がv1.0に

    https://forest.watch.impress.co.jp/docs/news/1637592.html

    TkEasyGUI – Pythonで最も素早くデスクトップアプリを創るライブラリ

    https://note.com/kujirahand/n/n33a2df3aa3e5

    WindowsのGUIが汚い… これはどうにもならんですね。🤔

  • 「もうええでしょ」のダウンロード方法

    YT-DLP

    yt-dlp is a feature-rich command-line audio/video downloader with support for thousands of sites.

    https://github.com/yt-dlp/yt-dlp?#release-files

    yt-dlp.exeをダウンロードし、URLを引数にして実行する。

    yt-dlp.exe https://www.youtube.com/watch?v=FCt2mryVhtM

    →「もうええでしょ [FCt2mryVhtM].mp4」がダウンロードされる。

    以上

    補足

    ダウンロード時に以下の警告メッセージが出力されます。低画質のmp4ファイルのダウンロードで良い場合は対処不要です。

    WARNING: ffmpeg not found. The downloaded format may not be the best available. Installing ffmpeg is strongly recommended: https://github.com/yt-dlp/yt-dlp#dependencies

    FFmpeg Static Auto-Builds

    https://github.com/yt-dlp/FFmpeg-Builds#downloads

    WINDOWS X64:「ffmpeg-master-latest-win64-gpl.zip」

    警告メッセージに従い ffmpeg をダウンロードしてパスを通すと警告が消えてmkvファイルがダウンロードされるようになります。

    FORMAT SELECTION

    By default, yt-dlp tries to download the best available quality if you don’t pass any options.

    ファイル形式を指定しない場合は、最も高画質な形式でダウンロードされます。

    You can also use a file extension (currently 3gpaacflvm4amp3mp4oggwavwebm are supported) to download the best quality format of a particular file extension served as a single file.

    ファイルの拡張子は、-f mp4 のように指定できます。

  • ざわ・・・メーカー

    /**
     * ざわ・・・メーカー
     * @param {obj} cs: canvas object
     * @param {number} zawaNum: 生成する「ざわ・・・」の数
     * @param {boolean} isBordering: 縁取りするかどうか
     *     黒文字の場合は白フチに、白文字の場合は黒フチに
     * @param {boolean} isColorBlack: 黒文字にするかどうか(falseで白文字)
     * @param {boolean} isRightFlow: 右から流れるようにするか
     */
    var zawaMaker = function(cs, zawaNum, isBordering, isColorBlack, isRightFlow ) {
        var ctx      = cs.getContext('2d');
        var csWidth  = cs.width;
        var csHeight = cs.height;
        var zawas    = [];
    
        /**
         * ランダムな整数を返す
         * @param max 最大値
         * @param min 最小値
         * @return min ~ max
         */
        var getRandomInt = function(max, min) {
            return Math.floor(Math.random() * (max - min)) + min;
        };
    
        /**
         * @constructor
         */
        var ZawaZawa = function() {
            this.initialize();
        };
    
        ZawaZawa.prototype = {
            initialize: function() {
                this.scale     = getRandomInt(10, 5) / 10; // 1 ~ 0.5の倍率
                this.width     = this.scale * 160;  // 元サイズを大体150pxくらいと規定
                this.height    = this.scale * 60;   // 元サイズを大体60pxくらいと規定
                this.moveX     = getRandomInt(csWidth  - this.width, 0);
                this.moveY     = getRandomInt(csHeight - this.height, 0);
                this.addMoveX  = this.scale * 5;  // 奥行きを出すために、小さい要素は移動量を少なくする
                this.alpha     = 1;
            },
            setStatus: function() {
                /* 変換マトリクスを初期化 */
                ctx.setTransform(1, 0, 0, 1, 0, 0);
    
                ctx.scale(this.scale, this.scale);
                ctx.translate(this.moveX, this.moveY);
                ctx.globalAlpha = this.alpha;
            },
            update: function() {
                /* scaleで座標軸がズレているので、scaleした分を割った値をCanvasサイズとする */
                var _csWidth = csWidth / this.scale;
    
                /* 流れる向きの条件分岐 */
                if (isRightFlow) {
                    if (this.moveX + this.width + 50 < 0 ) {
                        this.alpha = 0;
                        this.moveX = _csWidth + this.width;
    
                        /* scaleを変えるため再設定 */
                        this.scale    = getRandomInt(10, 5) / 10;
                        this.width    = this.scale * 160;
                        this.height   = this.scale * 60;
                        this.moveY    = getRandomInt(csHeight - this.height, 0);
                        this.addMoveX = this.scale * 5;
                    } else {
                        this.moveX -= this.addMoveX;
                        this.alpha += 0.01;
                    }
                } else {
                    if (this.moveX >_csWidth) {
                        this.alpha = 0;
                        this.moveX = - this.width;
    
                        /* scaleを変えるため再設定 */
                        this.scale    = getRandomInt(10, 5) / 10;
                        this.width    = this.scale * 160;
                        this.height   = this.scale * 60;
                        this.moveY    = getRandomInt(csHeight - this.height, 0);
                        this.addMoveX = this.scale * 5;
                    } else {
                        this.moveX += this.addMoveX;
                        this.alpha += 0.01;
                    }
                }
    
                /* 透明度が1以上の場合は透明度の増加を止める */
                if (this.alpha > 1) {
                    this.alpha = 1;
                }
            },
            draw: function() {
                /**
                 * @param {number} width: 線の太さ
                 * @param {string} color: 線の色
                 */
                function createZawaPath(width, color) {
                    ctx.lineWidth = width;
                    ctx.strokeStyle = color;
                    ctx.beginPath();
                    ctx.lineCap = "round";
                    ctx.lineJoin = "round";
    
                    // ざ
                    ctx.moveTo(10, 45);
                    ctx.lineTo(50, 45);
    
                    ctx.moveTo(25, 35);
                    ctx.lineTo(50, 60);
                    ctx.lineTo(20, 60);
                    ctx.bezierCurveTo(5, 60, 5, 75, 20, 75);
                    ctx.lineTo(50, 75);
    
                    ctx.moveTo(38, 30);
                    ctx.lineTo(38, 36);
    
                    ctx.moveTo(46, 30);
                    ctx.lineTo(46, 36);
    
                    // わ
                    ctx.moveTo(70, 35);
                    ctx.lineTo(70, 75);
    
                    ctx.moveTo(60, 45);
                    ctx.lineTo(80, 45);
                    ctx.lineTo(60, 75);
                    ctx.bezierCurveTo(80, 25, 120, 70, 85, 75);
    
                    // ・・・
                    ctx.moveTo(110, 60);
                    ctx.lineTo(115, 60);
    
                    ctx.moveTo(125, 60);
                    ctx.lineTo(130, 60);
    
                    ctx.moveTo(140, 60);
                    ctx.lineTo(145, 60);
    
                    ctx.closePath();
                    ctx.stroke();
                }
    
                /* 縁取と黒・白文字の条件分岐 */
                if (isBordering && isColorBlack) {
                    createZawaPath(15, 'white');
                    createZawaPath(6, 'black');
                }
                if (isBordering && !isColorBlack) {
                    createZawaPath(15, 'black');
                    createZawaPath(6, 'white');
                }
                if (!isBordering && isColorBlack) {
                    createZawaPath(6, 'black');
                }
                if (!isBordering && !isColorBlack) {
                    createZawaPath(6, 'white');
                }
    
            },
            render: function() {
                this.setStatus();
                this.draw();
                this.update();
            }
        };
    
    
        /**
         * ざわインスタンスの作成
         * @return zawas[instance, instance...];
         */
        function createZawas(num) {
            var i = 0;
            for (; i < num; i++) {
                zawas[zawas.length] = new ZawaZawa();
            }
        }
    
       /**
         * 描画
         */
        function render() {
            var i = 0;
            var l = zawas.length;
            ctx.setTransform(1,0,0,1,0,0);
            ctx.clearRect(0, 0, csWidth, csHeight);
            for (; i < l; i++) {
                zawas[i].render();
            }
            requestAnimationFrame(render);
        }
    
        /* 実行 */
        createZawas(zawaNum);
        render();
    };
    
    var cs = document.getElementById('myCanvas1');
    
    /* args: canvasオブジェクト, ざわの数, 縁取りか, 黒文字か, 右から流すか */
    zawaMaker(cs, 10, false, true, false);
    

    https://qiita.com/nekoneko-wanwan/items/4b196365183580831758

    👍

  • ざわ…ざわ…ざわ…

  • キーのリマッピング

    自分用に修正したので貼っておこー

    バグ修正

    • Firefox対応
      Firefoxのウインドウを移動した場合、ディスプレイの右側/下側で画面のサイズを変更ができなかったのでウインドウ枠を固定「7px」から可変値に修正した。

    機能変更

    • タスクビューのソースからタスクトレイアイコン周りのソースだけ切り出してマージした。仮想デスクトップ間でのウインドウ移動は意図しない動作が多発してしまうので使用中止。。「VirtualDesktopAccessor.dll」を「KeyRemap.ahk」と同じフォルダに格納するとタスクトレイのアイコンが「R」から「数字」になる。(任意)
    • ホットキーのモディファイア「*」を削除した。
    • 画面サイズの定義をスクリプトの最後に移動した。

    その他

    作ったもの

    keyremap_20240922.zip

  • VPN経由で映画やドラマを視聴する

    注意:広告つきプランをご利用の場合、VPN経由でNetflixを視聴することはできません。NetflixのライブイベントはVPN経由で視聴することはできません。

    https://help.netflix.com/ja/node/114701

    VPN 無料 – VPN Chrome Zenmate

    プライバシーへの取り組み

    https://chromewebstore.google.com/detail/fdcgdnkidjaadafnichfpabhfomcebme/privacy

    拡張機能をインストールして「火垂るの墓」を観たけど個人情報は抜かれてそう。ご利用は自己責任でお願い致します… 🙄

    ブラウザーのストレージ制限と削除基準

    https://developer.mozilla.org/ja/docs/Web/API/Storage_API/Storage_quotas_and_eviction_criteria

    Chromeのゴミ掃除

    1. 「設定」画面で「プライバシーとセキュリティ」メニューを選択する。
    2. 「サイトの設定」を選択する。
    3. 「すべてのサイトに保存されている権限とデータを表示」を選択する。

    または、以下のページを開く。

    chrome://settings/content/all

    1. 表示した画面で「サイトの合計ストレージ使用状況」を確認する。
    2. 「並べ替え」で「保存データ」を選択する。
    3. 各サイトのゴミ箱アイコンから不要なデータを削除する。

    「すべてのデータを削除」ボタンで一括削除するとすべてのサイトのログイン情報が削除されてIDやパスワードの再入力が必要となります。IDやパスワードを適切に管理していない場合には、Webサイト/サービスにログインできなくなりますので、ご利用は自己責任でお願い致します… 🙄

    Windowsのゴミ掃除

    DiskInfo
    https://forest.watch.impress.co.jp/library/software/diskinfo

    フリーソフトを使ってごみファイルを探し、手動で削除しています。

    たまにゴミ掃除したくなるけど数十ギガバイトのゴミファイルを削除しても体感できるようなパフォーマンス改善が見込めるわけではないので悪しからずご了承くださいませ…