通过 GitHub Actions 编译 Lazarus 项目

理论上 Lazarus 是支持交叉编译的,但官方发行的默认版本并没有打包不同平台所依赖的各组件。比如在 Windows 平台上将编译目标设为 Linux 时,编译器会报错:Can’t find unit system used by fcllaz ——缺少 Linux 平台上的预编译文件。

虽然可以使用 fpcupdeluxe (GitHub) 项目安装支持交叉编译的 Lazarus 工具链,不过这个工具似乎不支持命令行环境下的配置和安装。

……

国庆节不是祖国的生日 警惕反动势力用含情脉脉的类比潜移默化地宣扬历史虚无主义

那年的十月一日,城门楼子上庄严宣告的是:“中央人民政府今天成立了”,而不是“中国今天成立了”。真要搞什么“拟人化”修辞,那么这一天也顶多算是那个政权的生日

我们自幼接受的教育就是“中华文明源远流长,历史上下五千年”。若把中国的生命起点定在 1949 年,那这就是一种自我矮化、自我阉割。

再说那首名为《今天是你的生日》的歌曲,其歌词表面上含情脉脉,实则将中国五千年历史统统抹煞。已然是对中华文明的不敬,甚至可以认为是一种暗藏杀机的辱华。当然,我们可以认为歌词作者是政治觉悟低下,或者受人蛊惑犯下了错误,应该给予一个改过自新的机会。建议将歌词改为“今天是你的生日,我的中央人民政府”。这样才算得上尊重历史又政治正确。

……

窗口托盘最小化工具从 Traymond 进化为 Traynard

在前文《增强版 Traymond 让任意窗口最小化到系统托盘》中介绍了一款可以将任意窗口最小化到系统托盘的 Windows 桌面小工具。该工具代码 fork 自另一个同名项目,新增了一些功能并做了界面中文化。不过原项目是基于 Windows API 开发的,没有使用任何 GUI 框架,想要在此之上做进一步扩展非常麻烦,索性推倒重来。

tabris17/traynardgithub.coma Windows desktop utility for minimizing any application window to the system tray

功能介绍

新版本除了保留原来的 icon 外,已全部使用 Lazarus 重写,并在原有功能的基础上,新增了图标分组扩展窗口菜单的功能。

……

《小学生十万个为什么》盗版了谁?

上世纪 80 年代末、90 年代初,黑龙江技术出版社曾出版过一套名为《小学生十万个为什么》的科普丛书。

小学生十万个为什么(第一系列)book.douban.com小博士系列丛书
小学生十万个为什么(第二系列)book.douban.com小博士系列丛书

该丛书以漫画形式进行儿童科普,在当年国内属于首创。丛书一经推出便大受欢迎,发行量很大,至今在二手书市仍可见其踪迹。书中人物画风明显属于日本漫画风格,或者更准确地说,是手冢治虫的漫画风格。

……

什么是 Windows UserChoice 保护驱动(UCPD.sys)

在社交媒体上刷到一条非常扯淡的帖子,算是典型的蛆头为了吃「爱国」流量饭,利用民粹主义,专门针对低认知的蠢货们打造的无耻谣言。冠之以「技术流分析」,实则狗屁不懂。

xhs

言归正传,这个 UCPD.sys 究竟是什么来头呢?故事还要从当年流氓软件大战说起……

早期 Windows 对文件关联(即文件默认打开程序)的管理非常简单——任何程序都可以通过修改注册表键值来修改文件关联。这导致各种流氓软件滥用该特性来霸占用户电脑,特别是国产浏览器,通过修改 http/https 协议关联程序,来劫持用户上网行为。

……

Lazarus 项目支持多语言国际化(进阶篇)

在之前的一篇文章中简单介绍了如何在 Lazarus 项目中启用多语言国际化。不过使用 DefaultTranslatorSetDefaultLang() 无法实现运行时动态切换 GUI 的语言。更准确地说,在程序中首次调用 LCLTranslator.SetDefaultLang(),并将参数 ForceUpdate 设为 True,是能够在运行时修改 GUI 语言的,但若再次调用便无效了。

查看 SetDefaultLang() 源代码:

pascalfunction SetDefaultLang(Lang: string; Dir: string = ''; LocaleFileName: string = ''; ForceUpdate: boolean = true): string;
{ Arguments:
  Lang - language (e.g. 'ru', 'de', 'zh_CN'); empty argument is default language.
  Dir - custom translation files subdirectory (e.g. 'mylng'); empty argument means searching only in predefined subdirectories.
  LocaleFileName - custom translation file name; empty argument means that the name is the same as the one of executable.
  ForceUpdate - true means forcing immediate interface update. Only should be set to false when the procedure is
    called from unit Initialization section. User code normally should not specify it.
}
var
  lcfn: string;
  LocalTranslator: TUpdateTranslator;
  i: integer;

begin
  Result := '';
  LocalTranslator := nil;
  // search first po translation resources
  try
    lcfn := FindLocaleFileName('.po', Lang, Dir, LocaleFileName, Result);
    if lcfn <> '' then
    begin
      Translations.TranslateResourceStrings(lcfn);
      LocalTranslator := TPOTranslator.Create(lcfn);
    end
    else
    begin
      // try now with MO translation resources
      lcfn := FindLocaleFileName('.mo', Lang, Dir, LocaleFileName, Result);
      if lcfn <> '' then
      begin
        GetText.TranslateResourceStrings(UTF8ToSys(lcfn));
        LocalTranslator := TDefaultTranslator.Create(lcfn);
      end;
    end;
  except
    Result := '';
    lcfn := '';
  end;

  if lcfn<>'' then
    TranslateLCLResourceStrings(Lang, lcfn);

  if LocalTranslator<>nil then
  begin
    if Assigned(LRSTranslator) then
      LRSTranslator.Free;
    LRSTranslator := LocalTranslator;

    // Do not update the translations when this function is called from within
    // the unit initialization.
    if ForceUpdate=true then
    begin
      for i := 0 to Screen.CustomFormCount-1 do
        LocalTranslator.UpdateTranslation(Screen.CustomForms[i]);
      for i := 0 to Screen.DataModuleCount-1 do
        LocalTranslator.UpdateTranslation(Screen.DataModules[i]);
    end;
  end;
end;
lcltranslator.pas

该函数首先查找本地的 .po.mo 翻译文件;然后,将程序的资源字符串翻译成本地语言;接下来,创建一个新的 TUpdateTranslator 对象替代全局对象。

……

Free Pascal Hack 之访问对象的 protected 成员

默认情况下,Free Pascal 类中 protected 成员只能被当前类、子类以及同一个 Unit 中的代码访问。然而在实践中,往往会碰到访问其他 Unit 中定义的类实例对象的 protected 成员的需求。通常我们会通过类继承以及修改原始类成员的代码来暴露 protected 成员,然而当该对象来自第三方库,甚至 FCL 和 LCL 时,情况就会比较棘手。有一种 Hack 方法可以实现这个需求,且不用修改原始 Unit 的代码,没有额外副作用。

……

修复 scoop update 后 vcpkg 无法运行的故障

系统使用的 vcpkg 是由 scoop 安装的,在某次 scoop update -a 更新后故障无法运行。通过分析发现是由于安装脚本未能正确执行导致文件缺失引起的。以下是故障分析过程。

发现问题

打开 UniGetUI 更新时发现 vcpkg 的安装源不见了。

在命令行中运行 vcpkg 提示:

Shim: Could not determine if target is a GUI app. Assuming console.
Shim: Could not create process with command '"D:\Apps\scoop\apps\vcpkg\current\vcpkg.exe" '.

运行命令 scoop list vcpkg,显示软件已安装:

Installed apps matching 'vcpkg':

Name  Version    Source Updated             Info
----  -------    ------ -------             ----
vcpkg 2025.07.25 main   2025-07-29 10:56:05

尝试修复

看起来是 scoop shim 出了问题。尝试用 scoop reset vcpkg 命令重置。再次运行 vcpkg,无响应。接着尝试卸载 vcpkg 重新安装。运行 scoop uninstall vcpkg 命令,卡在运行 uninstall script 无响应。

……

Scoop 安装 Chrome 浏览器的用户数据问题

不知道从哪个版本开始,通过 Scoop 安装的 Chrome 浏览器不再保留本地用户数据。每次更新后,用户数据都要从 Google 账户同步。

Scoop 官方的解释是因为浏览器限制导致的:

Profile might point to default location (e.g. $env:LOCALAPPDATA\Google\Chrome\User Data), when --user-data-dir point to a specified path(e.g. $dir\userdata(persist\googlechrome\userdata)).

官方的建议是:

I would recommend that you install the default/main browser by its official installer.

不过 Chrome 并不是我的主力浏览器,即便官方不支持,也还是可以补救一下的。

根据以下路径找到开始菜单里 Chrome 的快捷方式:

……

为什么 Windows 额外定义了 F13 ~ F24 虚拟功能键

上网冲浪偶然看到一个 PowerToys 的 issue。具体问题就是 PC 微信启动后会一直模拟按下 F22 功能键,导致 PowerToys 设置的快捷键失效。解决方法是在 PowerToy 键盘管理器中屏蔽 F22 按键。

不清楚微信又在搞什么幺蛾子,倒是突然想到一个问题——为什么通用键盘明明只有 F1 ~ F12 总共 12 个功能键,而 Windows 虚拟按键代码却要从 VK_F1 一直定义到 VK_F24 呢?如果是为了预留扩充,那为什么不像苹果那样定义到 F19 ,或像 X11 那样定义到 F35难道这又是 Windows 的某种历史包袱吗

……