制作一个不在任务栏及任务列表中显示的幽灵程序
网上已经有许多地方提到了如何将在任务栏隐藏应用程序,使用的方法都是将Application的属性变为WS_EX_TOOLWINDOW。即在WinMain函数中加入如下代码:
DWORD dwExStyle = GetWindowLong(Application->Handle, GWL_EXSTYLE);
dwExStyle |= WS_EX_TOOLWINDOW;
SetWindowLong(Application->Handle, GWL_EXSTYLE, dwExStyle);
Application->Initialize();
Application->CreateForm(__classid(TForm1), &Form1);
Application->ShowMainForm = false;
ShowWindow(Application->Handle, SW_HIDE);
Application->Run();
这样做之后,应用程序就不会在任务栏显示了,但在WIN9X的任务列表中仍能看到。要想在任务列表也将自己的程序隐藏就要借用kernel32.DLL中的RegisterServiceProcess这个函数了。由于要从DLL加载函数,我们先在头文件中加入:
typedef DWORD (__stdcall *pRegFunction)(DWORD, DWORD);
在主Form的类定义中加入两个私有属性:
HINSTANCE hKernelLib;
pRegFunction RegisterServiceProcess;
用于记录从DLL加入的函数信息。
然后在主Form的构造代码中加入如下代码:
hKernelLib = LoadLibrary("kernel32.dll");
if(hKernelLib)
{
RegisterServiceProcess =
(pRegFunction)GetProcAddress(hKernelLib,
"RegisterServiceProcess");
if(RegisterServiceProcess)
RegisterServiceProcess(GetCurrentProcessId(),RSP_SIMPLE_SERVICE);
}
这段代码主要是把当前进程变为一个系统服务,从而在任务列表中把程序隐藏起来,相应的在构析代码中加入
if(hKernelLib)
{
if(RegisterServiceProcess)
RegisterServiceProcess(GetCurrentProcessId(),
RSP_UNREGISTER_SERVICE);
FreeLibrary(hKernelLib);
}
这样处理之后,程序就不在任务列表中出现了,但仍可用EnumWindows函数查出来。
如何让基于对话框的程序运行时隐藏界面
有些时候需要不让对话框在运行时显示出来,用ShowWindow的方法会有闪动现象,我认为最好的方法是用create.具体过程如下:
假设建立一个VC.NET工程GetTime,首先在CGetTimeApp类中添加一个成员变量:CGetTimeD
lg *dlg;然后在InitInstance()中将原来的:
int nResponse = dlg.DoModal();
if (nResponse == IDOK)
{
// TODO: Place code here to handle when the dialog is
// dismissed with OK
}
else if (nResponse == IDCANCEL)
{
// TODO: Place code here to handle when the dialog is
// dismissed with Cancel
}
以及return FALSE;全部删除掉,改为: dlg=new CGetTimeDlg;
m_pMainWnd = dlg;
return dlg->Create(IDD_GETTIME_DIALOG);
最后别忘了在ExitInstance()中加上一句:delete dlg;好了,这下把本程序的对话框
变成了一个无模式对话框。不过既然是无模式对话框,就不能再用OnOK(),OnCancel()来退
出了,要用DestroyWindow()。
另外将对话框的属性设置为不可见
由于在上面的代码中没有将对话框设为可见,所以运行时就实现了隐藏,而且在Window
s任务栏上也没有显示。
让程序只运行一个实例的简单实用的方法
//首先在InitInstance()函数中创建一个同步对象,如果(GetLastError()返回ERROR_ALREADY_EXISTS就
表明存在
//一个应用实例了,返回false取消
// 创建同步对象
//By cryfish
hMutexOneInstantance=CreateMutex(NULL,TRUE,_T("PreventSecondInstance"));
if(GetLastError()==ERROR_ALREADY_EXISTS)
bFound=TRUE;
if(hMutexOneInstantance)
ReleaseMutex(hMutexOneInstantance);
if (bFound==TRUE)
{ ::AfxMessageBox("You have Run one");
return false;
}
最近经常见论坛上有人问,程序在启动时如何隐藏。以下是我总结的一些方法,欢迎大家讨论,找出更好的方法。
对于这类问题,大家最容易想到的可能就是在PreCreateWindow中添加cs.style &=~WS_VISIBLE;这是不可行的。程序仍可使用ShowWindow()将窗体显示出来.
1.基于对话框的程序
我在论坛上看到有人说在OnInitDialog()中加上ShowWindow(SW_HIDE)对话框便不出现了,其实是不可行的。至于原因,我认为是系统是在OnInitDialog()后调用ShowWindow(SW_SHOW)让对话框显示的.可以添加下面代码:
CXXDlg::OnInitDialog()
{
...
Sleep(5000);
return TRUE;
}
可以发现5秒后对话框才显示出来.至于在何时调用的我也不清楚,但是我们可以在OnPaint()中加上ShowWindow(SW_HIDE),来达到隐藏的目的.不过使用的这种方法,会有一点闪烁.另外一种方法就是在OnInitDialog()中使用SetWindowPlacement()
GetWindowPlacement(&m_wp); //恢复时用
ModifyStyleEx(WS_EX_APPWINDOW,WS_EX_TOOLWINDOW);//从任务栏中去掉.
WINDOWPLACEMENT wp;
wp.length=sizeof(WINDOWPLACEMENT);
wp.flags=WPF_RESTORETOMAXIMIZED;
wp.showCmd=SW_HIDE;
SetWindowPlacement(wp);
还有一种更简单的方法:在OnInitDialog()中调用下面代码.
SetWindowPos(&wndTop,0,0,0,0,NULL);
2.基于单文档的程序
我们一般采用的方法就是将InitInstance()中的:
CXXApp::InitInstance()
{
//m_pMainWnd->ShowWindow(SW_SHOW);
}
但是这样窗体还会有闪烁。
因为MFC还要在ActiveFrame显示框架,所以我们还需要添加下面代码:
void CMainFrame::ActivateFrame(int nCmdShow)
{
nCmdShow=SW_HIDE;
CFrameWnd::ActivateFrame(nCmdShow);
}
或者:
int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
AfxGetApp()->m_nCmdShow=SW_HIDE;
}
顺便说一下,上面通过ModifyStyleEx(WS_EX_APPWINDOW,WS_EX_TOOLWINDOW)的方法来实现从任务栏去掉按钮,这样当显示时还要切换显示的模式,其实还可以通过调用TaskbarList组件直接删除和添加:
ITaskbarList的定义在shobjidl.h(vs.net)中。
也可以手动定义:
DECLARE_INTERFACE_(ITaskbarList,IUnknown)
{
STDMETHOD(QueryInterface)(THIS_ REFIID riid,LPVOID* ppvObj) PURE;
STDMETHOD_(ULONG,AddRef)(THIS) PURE;
STDMETHOD_(ULONG,Release)(THIS) PURE;
STDMETHOD(ActivateTab)(HWND) PURE;
STDMETHOD(AddTab)(HWND) PURE;
STDMETHOD(DeleteTab)(HWND) PURE;
STDMETHOD(HrInit)(void) PURE;
};
BOOL CMy2App::InitInstance()
{
CoInitialize(0);
ITaskbarList *pObj;
CoCreateInstance(CLSID_TaskbarList,NULL,CLSCTX_INPROC_SERVER,IID_ITaskbarList,(void**)&pObj);
pObj->DeleteTab(m_pMainWnd->m_hWnd); //从任务栏上删除
//pObj->AddTab(m_pMainWnd->m_hWnd); //添加
pObj->Release();
CoUninitialize();
}
所以我们还可以用将窗体最小化,并从任备栏上删除按钮的方法来实现隐藏.