目前开发的项目和MES类似,但功能超过了MES,客户的一些设备的运行数据采集是通过一个工控机上MFC程序实现的,可以采集ACCESS、SQL Server 2000数据库表中数据条目,机器数据都是1分钟增加一条历史数据,所以采集的时间间隔也是1分钟左右。但是现场的工人会将数据采集软件关闭,所以取消了关闭按钮的效果,但是还是存在于任务栏里,有的看到了会进行强制关闭,所以现在加了一条可以隐藏的功能,用Ctrl + Q 实现置标志位的功能,定时器实现按照标志位进行数据采集软件的显示和隐藏的效果切换。
具体实现过程如下:
MFC程序APP 源文件中声明钩子程序并实现,g_show_wnd 是一个全局变量,在APP源文件要声明为外部的 extern ,用来确定窗口的显示或隐藏:
//一个拦截系统消息的钩子程序事例
static LRESULT CALLBACK LowLevelKeyboardProc(int nCode, WPARAM wParam, LPARAM lParam);
LRESULT CALLBACK LowLevelKeyboardProc(int nCode, WPARAM wParam, LPARAM lParam)
{
PKBDLLHOOKSTRUCT p = (PKBDLLHOOKSTRUCT) lParam;
if (nCode == HC_ACTION)
{
int vKey = LOBYTE(p->vkCode);
//如果为键盘消息
if (wParam == WM_KEYDOWN)
{
switch(vKey)
{
case 'q':
case 'Q':
{
//如果用户按下了Win + D键盘消息
if(::GetKeyState(VK_CONTROL) < 0)
{
///do anything here///
//AfxMessageBox("QQQ");
g_show_wnd = 1;
}
}
}
}
return CallNextHookEx(NULL, nCode, wParam, lParam);
}
}
在APP源文件的初始化实例函数中调用,其中第一个参数 WH_KEYBOARD_LL 是最底层挂钩 ,监视键盘敲击
BOOL CKApp::InitInstance ()
{
HHOOK hhkKybd = SetWindowsHookEx(WH_KEYBOARD_LL, LowLevelKeyboardProc,
AfxGetApp()->m_hInstance, 0);
//...//
...
//...//
}
在窗口源文件中定义全局变量g_show_wnd 赋初始值1,设置定时器在窗口显示前系统调用的函数BOOL CKMainWnd::OnCreateClient (LPCREATESTRUCT lpcs, CCreateContext *pContext)中:
{
//处理窗口显示或者隐藏
SetTimer(SHOW_MAIN_WINDOW ,2000, NULL);
//...
...
//...
}
定时器函数中实现判断,清标志位的效果:
{
if(SHOW_MAIN_WINDOW == nIDEvent)
{
if (1 == g_show_wnd)
{
BOOL bshow = IsWindowVisible();
if (bshow)
{
ShowWindow(SW_HIDE);
}
else
{
ShowWindow(SW_SHOW);
}
g_show_wnd = 0;
}
}
//
...
//
}
通过上面的程序,当程序运行时,如果用户在键盘上点击Ctrl+q组合键,就可以显示软件窗口,如果再点击一次组合键,就可以隐藏软件窗口,
隐藏时任务管理器中应用程序看不到该采集软件,但是进程管理器可以看到。