You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Windows下Delphi程序终止后保留提示及记事本交互问题

问题:Delphi程序退出后通过记事本显示提示消息的实现问题

需求背景

在Windows 11 Pro环境下,使用Delphi 11.3-12.1开发程序,要求程序终止后仍显示提示消息(如“未移除USB驱动器”)。程序会在30秒无操作后自动执行USB断开并退出,担忧托盘提示无法被操作员注意到,因此选择通过记事本展示消息。

现有尝试代码

主逻辑代码

ExecuteProcess('Notepad.EXE','','', false, false, false, I);
Notepad := FindWindow('Notepad', nil);
if Bool(Notepad) then
begin
  NoteEdit := FindWindowEx(Notepad, 0, 'Edit', nil);
  if Bool(NoteEdit) then
  begin
    S:='Ciao' + #13 + 'Questa e'' una prova ....';
    SendMessage(NoteEdit, WM_SETTEXT, 0, Longint(S));
  end; 

变量定义

Notepad: HWND;
NoteEdit: HWND;

ExecuteProcess函数实现

function ExecuteProcess(const FileName, Params: string; Folder: 
 string; WaitUntilTerminated, WaitUntilIdle, RunMinimized: boolean;
   var ErrorCode: integer): boolean;
var CmdLine: string;
    WorkingDirP: PChar;
    StartupInfo: TStartupInfo;
    ProcessInfo: TProcessInformation;

 begin
   Result := true;
   CmdLine := '"' + FileName + '" ' + Params;
   if Folder = '' then Folder :=
          ExcludeTrailingPathDelimiter(ExtractFilePath(FileName));
   ZeroMemory(@StartupInfo, SizeOf(StartupInfo));
   StartupInfo.cb := SizeOf(StartupInfo);
   if RunMinimized then
   begin
     StartupInfo.dwFlags := STARTF_USESHOWWINDOW;
     StartupInfo.wShowWindow := SW_SHOWMINIMIZED;
   end;
   if Folder <> '' then WorkingDirP := PChar(Folder)
   else WorkingDirP := nil;
   if not CreateProcess(nil, PChar(CmdLine), nil, nil, false, 0,
          nil, WorkingDirP, StartupInfo, ProcessInfo) then
   begin
     Result := false;
     ErrorCode := GetLastError;
     exit;
   end;
   with ProcessInfo do
   begin
     CloseHandle(hThread);
     if WaitUntilIdle then WaitForInputIdle(hProcess, INFINITE);
     if WaitUntilTerminated then
     repeat
       Application.ProcessMessages;
     until MsgWaitForMultipleObjects(1, hProcess, false, INFINITE,
                         QS_ALLINPUT) <> WAIT_OBJECT_0 + 1;
     CloseHandle(hProcess);
   end;
 end;

遇到的问题

  • 记事本已打开时,无法新建标签页展示消息
  • 记事本未打开时,虽能启动但无法设置文本,怀疑FindWindowEx使用了错误的类名
  • 希望不创建临时文本文件,直接动态设置记事本内容,且参考的fisi-pjm代码无法正常弹出消息

解决方案

1. 实现记事本新标签页打开

Windows 11的记事本支持多标签,启动时传入"-"作为参数,即可打开空白新标签(无论是否已有记事本实例)。修改ExecuteProcess调用:

ExecuteProcess('Notepad.EXE', '-', '', false, true, false, ErrorCode);

2. 正确定位记事本编辑控件

Windows 11的记事本编辑控件类名已从Edit改为RichEditD2DPT,同时需增加进程初始化等待逻辑,避免窗口未创建就查找。修改后的主逻辑代码:

var
  ErrorCode: Integer;
  Notepad: HWND;
  NoteEdit: HWND;
  S: string;
begin
  // 启动记事本并打开新空白标签
  if ExecuteProcess('Notepad.EXE', '-', '', false, true, false, ErrorCode) then
  begin
    // 循环等待记事本窗口创建,最多等待5秒
    Notepad := 0;
    for var i := 1 to 50 do
    begin
      Notepad := FindWindow('Notepad', nil);
      if Notepad <> 0 then Break;
      Sleep(100);
    end;

    if Notepad <> 0 then
    begin
      // 查找Windows 11记事本的编辑控件
      NoteEdit := FindWindowEx(Notepad, 0, 'RichEditD2DPT', nil);
      if NoteEdit <> 0 then
      begin
        S := '未移除USB驱动器' + #13#10 + '请确保已安全移除USB设备后再关闭此窗口';
        // 使用PWideChar适配Unicode编码,避免乱码
        SendMessage(NoteEdit, WM_SETTEXT, 0, LPARAM(PWideChar(S)));
        // 置顶记事本窗口,确保操作员能看到
        SetForegroundWindow(Notepad);
      end;
    end;
  end;
end;

关键说明

  • 调用ExecuteProcess时设置WaitUntilIdle := true,确保记事本进程初始化完成后再执行后续逻辑
  • 增加循环等待窗口创建的逻辑,解决进程启动延迟导致的查找失败问题
  • 替换编辑控件类名为RichEditD2DPT,适配Windows 11记事本的控件结构
  • 使用PWideChar传递字符串,避免Unicode编码乱码问题
  • 调用SetForegroundWindow将记事本窗口置顶,提升提示的可见性

内容的提问来源于stack exchange,提问作者Daniele

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.12 18:13:09