弹出一个非阻塞对话框

今天有个小需求, 程序要求执行一个检测操作, 如果检测失败的话则弹出信息并且关闭程序

由于检测代码是封装到一个独立进程里的, 所以直接使用TerminateProcess(GetCurrentProcess, 0);来关闭当前进程

可是在测试时却发现, 原本使用MessageBox来弹出消息却会阻塞结束进程的操作

一般我们在系统里弹出对话框都是调用Windows.MessageBox, 这个方法在一般情况下, 可以不阻塞本程序的操作(虽然在代码层面仍然是阻塞的)

大家可以用一个小例子试试

procedure TForm1.Button1Click(Sender: TObject);
begin
  MessageBox(0, ‘测试内容1‘, ‘测试标题‘, MB_OK);
  MessageBox(0, ‘测试内容2‘, ‘测试标题‘, MB_OK);
end;

实际情况执行以后, 点击按钮弹出第一个对话框, 这时, 虽然程序界面仍然可以移动输入等执行其他操作, 但是测试内容2却没有弹出

只有吧第一个对话框关闭以后, 第2个对话框才能弹出来

所以, 猜测MessageBox的非阻塞只是在内部处理了对当前进程的消息循环, 但是代码层面并没有返回并向后执行, 所以并不是真正意义上的非阻塞

那需求怎么办呢.......

伟大的Google, 码农们需要你的时候来了(虽然这几天Google又被伟大的GFW给墙了...不过咱们可以换IP...嘿嘿 你懂的: 啦啦啦)

终于搜到一个相关的文章, 关于在win7下如果让一个服务向用户界面推送消息的问题: 穿透Session0隔离

其中有一个关键性函数: WTSSendMessage, 可以向指定的Session发送消息

既然是想Session发送消息, 那肯定是桌面级的, 和应用程序无关了呗, 咱们再看看他的定义: WTSSendMessage function

显然, 最后一个参数是控制是否阻塞等待的, 看来这就是我要的东西了, 马上写代码试试:

补充一下, 不知道为什么 这个自从XP就出现的函数, 直到Delphi XE5都没有被定义到Windows单元中, 而其他的2个WTS相关函数却定义了(也许定义到其他单元我没找到?)

const
  WTS_CURRENT_SERVER_HANDLE = 0;

function WTSSendMessage(Server: HWND; SessionId: DWORD; Title: PChar;
  TitleLength: DWORD; AMessage: PChar; MessageLength: DWORD; Style: DWORD;
  Timeout: DWORD; var Response: DWORD; Wait: Boolean): Boolean; stdcall;
  external ‘wtsapi32.dll‘ name ‘WTSSendMessageA‘;

function WTSGetActiveConsoleSessionId: DWORD; stdcall;
  external kernel32 name ‘WTSGetActiveConsoleSessionId‘;

procedure TForm1.Button1Click(Sender: TObject);
var
  nTitle, nMessage: string;
  nResponse: DWORD;
begin
  nTitle := ‘测试标题‘;
  nMessage := ‘测试内容1‘;
  WTSSendMessage(WTS_CURRENT_SERVER_HANDLE, WTSGetActiveConsoleSessionId,
    PChar(nTitle), Length(nTitle), PChar(nMessage), Length(nMessage),
    MB_OK, 0, nResponse, False);
  nMessage := ‘测试内容2‘;
  WTSSendMessage(WTS_CURRENT_SERVER_HANDLE, WTSGetActiveConsoleSessionId,
    PChar(nTitle), Length(nTitle), PChar(nMessage), Length(nMessage),
    MB_OK, 0, nResponse, False);
end;

执行测试一下, 我擦....居然还是必须先吧内容1确定了以后才能弹出内容2? 难道是我理解错了不成?

单步跟踪一下...#^&%^*

不对啊, 弹出了内容1马上就执行到内容2的代码了啊, 然后就直接end结束了, 可是为什么只弹出了1个对话框呢?

再补充一下测试

const
  WTS_CURRENT_SERVER_HANDLE = 0;

function WTSSendMessage(Server: HWND; SessionId: DWORD; Title: PChar;
  TitleLength: DWORD; AMessage: PChar; MessageLength: DWORD; Style: DWORD;
  Timeout: DWORD; var Response: DWORD; Wait: Boolean): Boolean; stdcall;
  external ‘wtsapi32.dll‘ name ‘WTSSendMessageA‘;

function WTSGetActiveConsoleSessionId: DWORD; stdcall;
  external kernel32 name ‘WTSGetActiveConsoleSessionId‘;

procedure TForm1.Button1Click(Sender: TObject);
var
  nTitle, nMessage: string;
  nResponse: DWORD;
begin
  nTitle := ‘测试标题‘;
  nMessage := ‘测试内容1‘;
  WTSSendMessage(WTS_CURRENT_SERVER_HANDLE, WTSGetActiveConsoleSessionId,
    PChar(nTitle), Length(nTitle), PChar(nMessage), Length(nMessage),
    MB_OK, 0, nResponse, False);
  nMessage := ‘测试内容2‘;
  WTSSendMessage(WTS_CURRENT_SERVER_HANDLE, WTSGetActiveConsoleSessionId,
    PChar(nTitle), Length(nTitle), PChar(nMessage), Length(nMessage),
    MB_OK, 0, nResponse, False);
  TerminateProcess(GetCurrentProcess, 0);
end;

看看这样, 执行结果, 果然 程序关闭了, 但是只有内容1的对话框, 确定以后才弹出内容2的

个人猜测, 应该是WTSSendMessage以类似消息队列方式给Session发对话框消息, 而对于Session的处理, 则必须是阻塞的, 估计是为了能够让用户知道多条消息的先后顺序吧

无所谓啦, 只要程序不阻塞就行, 搞定....嘿嘿嘿嘿.......

弹出一个非阻塞对话框

时间: 2024-10-21 04:48:33

弹出一个非阻塞对话框的相关文章

弹出一个非阻塞对话框(在程序关闭后 仍然显示对话框)

今天有个小需求, 程序要求执行一个检测操作, 如果检测失败的话则弹出信息并且关闭程序 由于检测代码是封装到一个独立进程里的, 所以直接使用TerminateProcess(GetCurrentProcess, 0);来关闭当前进程 可是在测试时却发现, 原本使用MessageBox来弹出消息却会阻塞结束进程的操作 一般我们在系统里弹出对话框都是调用Windows.MessageBox, 这个方法在一般情况下, 可以不阻塞本程序的操作(虽然在代码层面仍然是阻塞的) 大家可以用一个小例子试试 pro

删除数据时弹出一个确认对话框

使用js实现点击按钮删除数据时弹出一个确认是否删除的对话框: <input type="button" class="wz2 btn" value="删除" onClick="sc('{$vo.name}','__URL__/delete?aid={$vo.id}')"/> <script type="text/javascript"> function sc($name,$ulr)

java实现弹出认证输入框(弹出一个带有用户名和密码输入的对话框)

java如何实现如题的效果,效果图如下: 这个效果让我很好奇,这个效果类型与在ftp服务器上下载需要登录认证的文件时会弹出这个框,在网上查阅了一些资料,不过相关的资料真的很少,找到了一些关键的技术点自己简单的实现了下,下面是一些简单的介绍,来源于http://www.blogbus.com/gaomed-logs/106179012.html 标签: TAG: 用户登录框是怎么做的:路由器的用户登录框是怎么做的:通用的用户登录框:authenticate验证:Authorization验证 /*

弹出一个对话框并且对是和否绑定事件

  //String 是用来显示提示内容 protected void dialog(String result) { AlertDialog.Builder builder = new Builder(MainActivity.this); builder.setMessage(result); builder.setTitle("提示"); builder.setPositiveButton("确定", new DialogInterface.OnClickLi

Android 如何监听返回键,弹出一个退出对话框

Android 如何监听返回键,弹出一个退出对话框 分类: 初级android2012-10-21 00:46 48472人阅读 评论(9) 收藏 举报 androiddialogbuttonclass Android 如何监听返回键点击事件,并创建一个退出对话框, 防止自己写的应用程序不小心点击退出键而直接退出.自己记录下这个简单的demo,备用. 注:如下代码当时是从网上copy过来的,现在忘了它出自哪个原作者了,在此说声抱歉. 源码如下: [html] view plaincopy <EM

android 中在activity弹出一个对话框,并不会执行onpause生命周期方法

在实际的应用开发中,我们可能会在onResume中进行网络交互,在网络交互的过程中免不了使用Progressdialog,那么现在问题来了,在我们弹出一个进度对话框的时候如果我们的activity的onpause生命方法得到执行,然后在数据加载完毕,对话框进行消失的时候,activity的onResume再次得到执行,然后再次请求网络,这样一个恶性循环就开始了,这样的错误实在是太严重了,当然了上面只是在我的想象之中,然后就用代码实验了下,在弹出一个对话框的时候我们activity的onpause

Android 点击一个按钮,弹出一个对话框

界面非常的简单,就是一个Button,点击这个Button呢,会弹出一个对话框 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"     xmlns:tools="http://schemas.android.com/tools"     android:layout_width="match_parent"     android:layout

如何弹出一个对话框

怎么实现弹出一个对话窗口: JOptionPane.showMassageDiglog(null,"弹出的对话"); 在弹出的对话窗口输入并接收: String +a(变量名)  =JOptionPane.showInputDialog(null,"请输入"); 将接收的字符串转化为整形: int s(变量名)=Integer.parseInt(a); 将接收的字符串转化为double: double p(变量名)=Double.parseDouble(a); 其中

JavaScript总结之鼠标划过弹出div单击出现对话框

为了满足他们的永无止境的要求,我可谓是任劳任怨啊,累断了双手,看瞎了双眼.这个是来写鼠标划过一个按钮,然后弹出一个小提示框解释,另外根据radio是否选中,判断点击后如何执行,然后执行之后再有一个确认或取消.其实部分想要的功能可以从中截取. js代码: 1 <script type="text/javascript"> 2 function sAlert_jobdel(str){ 3 var msgw,msgh,bordercolor; 4 msgw=400;//提示窗口的