我用 Winamp 时,觉得它的一项设计比较实用,不知如何实现。当在运行 Winamp 期间,再次运行 Winamp.exe 时,它不会多次运行(这个我会),并

I

incool2

Unregistered / Unconfirmed
GUEST, unregistred user!
我用 Winamp 时,觉得它的一项设计比较实用,不知如何实现。当在运行 Winamp 期间,再次运行 Winamp.exe 时,它不会多次运行(这个我会),并可以恢复被其它窗口遮盖的 Winamp 主窗口(把主窗口恢复到屏幕的最前,假使原来被其它窗口遮盖住)。 (50分)<br />我用过几个函数(下面所写的),它们都能激活程序,但都不能把程序的主窗口显示在屏幕最前:
Form1.Show;
Application.Restore;
ShowWindow(Application.handle,SW_show);
ShowWindow(Application.handle,SW_RESTORE);
ShowWindow(Application.handle,SW_SHOWDEFAULT);
ShowWindow(Application.handle,SW_SHOWNA);
ShowWindow(Application.handle,SW_SW_SHOWNOACTIVATE);
ShowWindow(Application.handle,SW_SW_SHOWNOMAL);
请高手指导
 
1.SetWindowPos(Handle, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE or SWP_NOSIZE);
2.Application.BringToFront;
 
首先用findwindow找到这个程序的句柄,你现在的Application.handle是你当前第二次运行这个程序时的句柄,
而不是你要激活的哪个窗口的句柄,所以你你这段代码不能拿那个窗口怎么样。
解决的办法是:
在你的程序工程文件的代码中写上:
Application.Title:='程序的标题';

在这句代码之前(注意:是这句代码之前)写findwindow代码;


如下:(是在DELPHI工程文件中写的)
uses windows;

var Hnd:THandle;
begin
Hnd:=findwindow(nil,'程序的标题');
if Hnd<>0 then
begin
ShowWindow(Hnd,1);
SetForeGroundWindow(Hnd);
Exit;
end;
Application.Title:='程序的标题';
//其他创建窗体的语句
Application.run;
end.

 
要注册一个消息,然后,你的程序里处理这个消息,在这个消息处理函数里,
把窗口显示到最前面,变成活动窗口
然后,如果你发现你的程序已经运行了,就Broadcase这个消息。
你原来的程序接收到这个消息,就会编为活动窗口
function BroadcastSystemMessage(Flags:DWORD; Recipients:pDWORD;uiMessage:UINT;
wParam:WPARAM; lParam:LPARAM):longint;stdcall;external 'user32.dll';广播消息
RegisterWindowMessage注册windows消息。
 
看我的源码
//在共享模块中声明SAppName:='你的程序名';
//并在主窗体的OnCreate事件中设置Application.Title:=SAppName;
var
hMutex,hApp:HWND;
begin
Application.Initialize;
//建立互斥对象
hMutex:=CreateMutex(nil,False,PChar(SAppName));
If GetLastError=ERROR_ALREADY_EXISTS Then
begin
//已经运行,找到句柄
hApp:=FindWindow('TApplication',PChar(SAppName));
//激活
if IsIconic(hApp) then
PostMessage(hApp,WM_SYSCOMMAND,SC_RESTORE,0);
SetForegroundWindow(hApp);
//释放互斥对象
ReleaseMutex(hMutex);
Application.Terminate;
exit;
end;
Application.CreateForm(TMDIMainForm, MDIMainForm);
Application.Run;
//释放互斥对象
ReleaseMutex(hMutex);
end.
 
这个太Easy了
Application.BringToFront;

 
只要引入本单元就可以了:) (从D5编程人员指南而来)
unit ShenOneInstanceMutux;
interface
const
MI_QUERYWINDOWHANDLE = 1;
MI_RESPONDWINDOWHANDLE = 2;
MI_ERROR_NONE = 0;
MI_ERROR_FAILSUBCLASS = 1;
MI_ERROR_CREATINGMUTEX = 2;
function GetMIError: Integer;
implementation
uses Forms, Windows, SysUtils;
const
UniqueAppStr = 'Shen: TOOI' + 'Program_Name'+ 'VERSION';//更改成你的唯一标示
var
MessageId: Integer;
WProc: TFNWndProc;
MutHandle: THandle;
MIError: Integer;
function GetMIError: Integer;
begin
Result := MIError;
end;
function NewWndProc(Handle: HWND; Msg: Integer; wParam, lParam: Longint):
Longint; stdcall;
begin
Result := 0;
if Msg = MessageID then
begin
case wParam of
MI_QUERYWINDOWHANDLE:
begin
if IsIconic(Application.Handle) then
begin
Application.MainForm.WindowState := wsNormal;
Application.Restore;
end;
PostMessage(HWND(lParam), MessageID, MI_RESPONDWINDOWHANDLE,
Application.MainForm.Handle);
end;
MI_RESPONDWINDOWHANDLE:
begin
SetForegroundWindow(HWND(lParam));
Application.ShowMainForm := False;
Application.Terminate;
end;
end;
end
else
Result := CallWindowProc(WProc, Handle, Msg, wParam, lParam);
end;
procedure SubClassApplication;
begin
WProc := TFNWndProc(SetWindowLong(Application.Handle, GWL_WNDPROC,
Longint(@NewWndProc)));
if WProc = nil then
MIError := MIError or MI_ERROR_FAILSUBCLASS;
end;
procedure DoFirstInstance;
begin
MutHandle := CreateMutex(nil, False, UniqueAppStr);
if MutHandle = 0 then
MIError := MIError or MI_ERROR_CREATINGMUTEX;
end;
procedure BroadcastFocusMessage;
var
BSMRecipients: DWORD;
begin
Application.ShowMainForm := False;
BSMRecipients := BSM_APPLICATIONS;
BroadCastSystemMessage(BSF_IGNORECURRENTTASK or BSF_POSTMESSAGE,
@BSMRecipients, MessageID, MI_QUERYWINDOWHANDLE,
Application.Handle);
end;
procedure InitInstance;
begin
SubClassApplication; // hook application message loop
MutHandle := OpenMutex(MUTEX_ALL_ACCESS, False, UniqueAppStr);
if MutHandle = 0 then
DoFirstInstance
else
BroadcastFocusMessage;
end;
initialization
MessageID := RegisterWindowMessage(UniqueAppStr);
InitInstance;
finalization
if WProc <> Nil then
SetWindowLong(Application.Handle, GWL_WNDPROC, LongInt(WProc));
if MutHandle <> 0 then CloseHandle(MutHandle); // Free mutex
end.
 
大家的方法我都用过了,zyg_zm的最简单最方便
 
我第一次来,我对大家的帮助很感激.但我想问一下:我已登陆了,怎结束讨论,并分配积分.

登陆后只有以下东西,我选择后并没有确认按键

问题讨论没有结束 ...
incool2,对此问题,您可以:

接受答案,并为 shenloqitwoswind2000xuzhudiysaizyg_zm 加上 50 点积分
接受答案,并分配积分

shenloqi
twos
wind2000
xuzhudi
ysai
zyg_zm

请注意分数总和应为 50 分

 
1.选第一项
2.选择base7
3.按提交(如果没有的话刷新一下)
 
提交 按键在哪里?我刷新了好多次啦
 
实在不知道怎么结束,就把你想分配积分的情况说出来,让斑竹帮你结束这个帖子吧
 
我给 zyg_zm 50分
 
TO:zyg_zm
你有没有试过与你程序标题同名的程序正在运行的情况?
 
1.这个Application.title不是窗体caption,
2.findwindow函数,在windowclass参数为nil的时候,是不能区分Application.title相同的情况,
所以在定这个Title的时候注意不要取和别人相同的Application.Title,这是一个不足,不过也是可以避免的
 
不必将全部分都给我,我也只是说出了一个简单点的方法,大家都提出了一些方法,大家都分点分吧。
 
多人接受答案了。
 

Similar threads

S
回复
0
查看
3K
SUNSTONE的Delphi笔记
S
S
回复
0
查看
2K
SUNSTONE的Delphi笔记
S
I
回复
0
查看
467
import
I
D
回复
0
查看
1K
DelphiTeacher的专栏
D
I
回复
0
查看
656
import
I
顶部