Z
zhtx
Unregistered / Unconfirmed
GUEST, unregistred user!
我习惯设置FORM属性为stayontop,这样就不象设置成NORMAL后,窗口老失踪找不到.
但有时会碰到打开的对话框或新开窗口会被原有窗口挡住的现象,因随机出现,不能准确重现,所以老找不到解决方案.
近日偶然发现,如果我最小化当前运行程序,然后再重复执行,选择返回原有程序后就会出现这现象,而如果原程序正常显示就没这问题.这说明这问题是我判断重复执行单元的不完善造成的.
原单元代码如下:
unit UnitWhsInstance;
interface
uses
SysUtils, Windows, Messages, Classes, Dialogs, Controls, WinProcs, Forms;
function LookAtAllWindows(Handle: HWnd; Temp: Longint) : Bool; stdcall;
function GetNumberOfInstances: integer;
//检查是否重复进入,如果重复进入则恢复原来的程序后退出当前程序
procedure CheckPrevInstances(AMaxInstance: integer);
implementation
uses
WhsFunction;
var
CApplicationName : Array[0..255] of Char;
CClassName : Array[0..255] of Char;
CNumberFound : Integer;
CLastFound : HWnd;
CPopup : HWnd;
function LookAtAllWindows(Handle: HWnd; Temp: Longint) : Bool; stdcall;
var
WindowName : Array[0..255] of Char;
ClassName : Array[0..255] of Char;
begin
result:=true;
if GetClassName(Handle, ClassName, SizeOf(ClassName)) > 0 then
if StrComp(ClassName, CClassName) = 0 then
if GetWindowText(Handle, WindowName, SizeOf(WindowName)) > 0 then
if StrComp(WindowName, CApplicationName) = 0 then
begin
CodeSite.SendPChar('win:', WindowName);
CodeSite.SendVariant('handle:', handle);
Inc(CNumberFound);
if Handle <> Application.Handle then CLastFound := Handle;
end;
end;
function GetNumberOfInstances: integer;
begin
CNumberFound := 0;
CLastFound := 0;
GetWindowText(Application.Handle,CApplicationName, SizeOf(CApplicationName));
GetClassName(Application.Handle, CClassName, SizeOf(CClassName));
EnumWindows(@LookAtAllWindows,0);
result := CNumberFound;
end;
procedure CheckPrevInstances(AMaxInstance: integer);
begin
GetNumberOfInstances;
if (CNumberFound > 1) then
begin
if (AMaxInstance = 0) or ((CNumberFound=2) and
WGetYes('返回已运行程序否')) then
begin
//此处加入后来完善的语句,见后
CPopup := GetLastActivePopup(CLastFound);
BringWindowToTop(CLastFound);
if IsIconic(CPopup) then
ShowWindow(CPopup, SW_RESTORE)
else
SetForegroundWindow(CPopup);
if (CPopup<>0) then
Halt(0);
end
else if (CNumberFound > AMaxInstance) then
begin
showmessage('超过允许最大进程数:' +
inttostr(AMaxInstance) + ',不能运行!');
Halt(0);
end;
end;
end;
经反复研究发现,如果程序正常显示,则获得的句柄是主窗口句柄,一切处理正常,程序最小化时则获得的句柄是隐藏的APPLICATION窗口句柄,虽然仍能恢复到原有程序,但导致了后来的FORM或对话框显示不正常,无法显示在最上面.
解决方法很简单:既然最小化不正常,那么在获取句柄前,先让程序恢复到正常状态就行了.
在前面单元相应地方加入如下语句就行了:
SendMessage(CLastFound, WM_SYSCOMMAND, SC_RESTORE, 0);
虽然简单,但我笨啊,花了1天时间才解决,特与大家分享,免得遇到同样问题的兄弟浪费时间!
另外如有更好的方法,欢迎多指教!
但有时会碰到打开的对话框或新开窗口会被原有窗口挡住的现象,因随机出现,不能准确重现,所以老找不到解决方案.
近日偶然发现,如果我最小化当前运行程序,然后再重复执行,选择返回原有程序后就会出现这现象,而如果原程序正常显示就没这问题.这说明这问题是我判断重复执行单元的不完善造成的.
原单元代码如下:
unit UnitWhsInstance;
interface
uses
SysUtils, Windows, Messages, Classes, Dialogs, Controls, WinProcs, Forms;
function LookAtAllWindows(Handle: HWnd; Temp: Longint) : Bool; stdcall;
function GetNumberOfInstances: integer;
//检查是否重复进入,如果重复进入则恢复原来的程序后退出当前程序
procedure CheckPrevInstances(AMaxInstance: integer);
implementation
uses
WhsFunction;
var
CApplicationName : Array[0..255] of Char;
CClassName : Array[0..255] of Char;
CNumberFound : Integer;
CLastFound : HWnd;
CPopup : HWnd;
function LookAtAllWindows(Handle: HWnd; Temp: Longint) : Bool; stdcall;
var
WindowName : Array[0..255] of Char;
ClassName : Array[0..255] of Char;
begin
result:=true;
if GetClassName(Handle, ClassName, SizeOf(ClassName)) > 0 then
if StrComp(ClassName, CClassName) = 0 then
if GetWindowText(Handle, WindowName, SizeOf(WindowName)) > 0 then
if StrComp(WindowName, CApplicationName) = 0 then
begin
CodeSite.SendPChar('win:', WindowName);
CodeSite.SendVariant('handle:', handle);
Inc(CNumberFound);
if Handle <> Application.Handle then CLastFound := Handle;
end;
end;
function GetNumberOfInstances: integer;
begin
CNumberFound := 0;
CLastFound := 0;
GetWindowText(Application.Handle,CApplicationName, SizeOf(CApplicationName));
GetClassName(Application.Handle, CClassName, SizeOf(CClassName));
EnumWindows(@LookAtAllWindows,0);
result := CNumberFound;
end;
procedure CheckPrevInstances(AMaxInstance: integer);
begin
GetNumberOfInstances;
if (CNumberFound > 1) then
begin
if (AMaxInstance = 0) or ((CNumberFound=2) and
WGetYes('返回已运行程序否')) then
begin
//此处加入后来完善的语句,见后
CPopup := GetLastActivePopup(CLastFound);
BringWindowToTop(CLastFound);
if IsIconic(CPopup) then
ShowWindow(CPopup, SW_RESTORE)
else
SetForegroundWindow(CPopup);
if (CPopup<>0) then
Halt(0);
end
else if (CNumberFound > AMaxInstance) then
begin
showmessage('超过允许最大进程数:' +
inttostr(AMaxInstance) + ',不能运行!');
Halt(0);
end;
end;
end;
经反复研究发现,如果程序正常显示,则获得的句柄是主窗口句柄,一切处理正常,程序最小化时则获得的句柄是隐藏的APPLICATION窗口句柄,虽然仍能恢复到原有程序,但导致了后来的FORM或对话框显示不正常,无法显示在最上面.
解决方法很简单:既然最小化不正常,那么在获取句柄前,先让程序恢复到正常状态就行了.
在前面单元相应地方加入如下语句就行了:
SendMessage(CLastFound, WM_SYSCOMMAND, SC_RESTORE, 0);
虽然简单,但我笨啊,花了1天时间才解决,特与大家分享,免得遇到同样问题的兄弟浪费时间!
另外如有更好的方法,欢迎多指教!