文字性的描述留到后续文章再交代,还是先放一个小小的'大招',毕竟眼镜看见的东西,比起抽象的东西,更能引起初学者的注意,
如果你对这个感兴趣的话,这里有个链接,你可以去看看,
<<白话windows之 会话、工作站、桌面、窗口之间的关系>>
http://bbs.pediy.com/showthread.php?t=173271
1.用vs2013创建一个空项目,添加一个cpp文件,
#include
TCHAR szAppName[] = TEXT("TEST"); //窗口类名
#define DESTOP_NAME TEXT("MY_DESTOP") //定义我要创建的桌面名称
ATOM m_HotKeyId1; //用于注册ctrl+shift+F6 ,切换到原来的活动桌面
ATOM m_HotKeyId2; //用于注册ctrl+shift+F7 ,将活动桌面切换到我们新创建的桌面,
ATOM m_HotKeyId3; //用于正确退出程序,因为程序没有相应界面且需要释放一些资源
HDESK hDDesk;
HWINSTA hWinStaThisProcess = GetProcessWindowStation( ); //程序运行起来,获取系统为该进程设置的默认交互工作站
HDESK hDeskOriignInput = OpenInputDesktop(0,FALSE,GENERIC_ALL); //程序运行起来,获取系统为该线程设置的默认活动桌面
void OnHotKey(WPARAM wParam,LPARAM lParam)
{
static
LRESULT lRes = 0;
if(wParam == m_HotKeyId1)//热键1被按下
{
// 该热键按下时的处理
SwitchDesktop(hDeskOriignInput); //原活动桌面被显现出来
//MessageBox(0,TEXT("F6"),0,0);
}
else if(wParam == m_HotKeyId2)//热键2被按下
{
SwitchDesktop(hDDesk); //我们创建的桌面显现出来
//MessageBox(0,TEXT("F7"),0,0);
}
else if(wParam == m_HotKeyId3)//热键2被按下
{
MessageBox(0,TEXT("程序退出"),0,0);
PostQuitMessage(0); //我们创建的桌面显现出来
//MessageBox(0,TEXT("F7"),0,0);
}
return ;
}
LRESULT CALLBACK WndProc(HWND hwnd,UINT message,WPARAM wParam,LPARAM lParam)
{
switch(message)
{
case WM_HOTKEY:
OnHotKey(wParam,lParam);
return 0;
}
return DefWindowProc(hwnd,message,wParam,lParam);
}
int WINAPI WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,PSTR szCmdLine,int iCmdShow)
{
HWND hwnd;
MSG msg;
WNDCLASS wndclass;
wndclass.style = CS_HREDRAW | CS_VREDRAW;
wndclass.lpfnWndProc = WndProc;
wndclass.cbClsExtra = 0;
wndclass.cbWndExtra = 0;
wndclass.hInstance = hInstance;
wndclass.hIcon = LoadIcon(NULL,IDI_APPLICATION);
wndclass.hCursor = LoadCursor(NULL,IDC_ARROW);
wndclass.hbrBackground = (HBRUSH)GetStockObject(GRAY_BRUSH);
wndclass.lpszMenuName = NULL;
wndclass.lpszClassName = szAppName;
if(!RegisterClass(&wndclass))
{
MessageBox(NULL,TEXT("窗口注册失败!"),NULL,0);
return 0;
}
hwnd = CreateWindow(
szAppName,szAppName,
WS_OVERLAPPEDWINDOW,
0,0,
0,0,
NULL,NULL,hInstance,NULL
);
//在进程 默认的交互式工作站中创建 桌面,
hDDesk = CreateDesktop(
DESTOP_NAME,
0,0,0,
GENERIC_ALL,
NULL
);
//设置与本线程相联系的桌面为 我们创建的桌面
SetThreadDesktop(hDDesk);
//填写STARTUPINFO 结构体信息,注意与平常创建进程的不同,这里有了lpDesktop选项的设置,
STARTUPINFO sti = {
sizeof(sti)
};
sti.lpDesktop = DESTOP_NAME;
PROCESS_INFORMATION pi = {0};
CreateProcess(
TEXT("C:\\Windows\\explorer.exe"),NULL,NULL,NULL,TRUE,0,NULL,NULL,&sti,&pi
);
/****************************************************************
注册3个热键
******************************************************************/
//在全局原子表中添加一项字符串得到id一个,这一项跟 CTRL +SHIFT+F6 有关
m_HotKeyId1 = GlobalAddAtomW(TEXT("HotKey1")) - 0xc000;
//注册得到的id与 热键CTRL+SHIFT+F6 关联起来
RegisterHotKey(hwnd,m_HotKeyId1,MOD_CONTROL | MOD_SHIFT,VK_F6);
//在全局原子表中添加一项字符串得到id一个,这一项跟 CTRL +SHIFT+F7 有关
m_HotKeyId2 = GlobalAddAtomW(TEXT("HotKey2")) - 0xc000;
//注册得到的id与 热键CTRL+SHIFT+F7 关联起来
RegisterHotKey(hwnd,m_HotKeyId2,MOD_CONTROL | MOD_SHIFT,VK_F7);
//在全局原子表中添加一项字符串得到id一个,这一项跟 F7 有关
m_HotKeyId3 = GlobalAddAtomW(TEXT("HotKey3")) - 0xc000;
//注册得到的id与 热键F7 关联起来
RegisterHotKey(hwnd,m_HotKeyId3,0,VK_F7);
/**********************************************************
***********************************************************/
//窗口消息循环
while(GetMessage(&msg,NULL,0,0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
//F7 热键按下,即退出,顺便清理资源
UnregisterHotKey(hwnd,m_HotKeyId1);
GlobalDeleteAtom(m_HotKeyId1);
UnregisterHotKey(hwnd,m_HotKeyId2);
GlobalDeleteAtom(m_HotKeyId2);
UnregisterHotKey(hwnd,m_HotKeyId3);
GlobalDeleteAtom(m_HotKeyId3);
CloseHandle(hDDesk);
return msg.wParam;
}
2.1SwitchDesktop失败,GetLastError () 返回 error_access_dinied 这个错误通常跟管理员权限没提权有关,但是这里不是这样的,
而是, 1.你创建的桌面不在交互工作站中,
在这之前你得知道 你的程序, 系统默认给其对应的进程 关联到 一个 交互式工作站,
2.怎样将创建的桌面跟工作站产生 包含的逻辑关系 呢?
通过 给进程SetProcessWinstation()关联工作站 ,(这里省略了这一步,因为我已经知道,进程和工作站的关联关系了)
给线程SetThreadDesktop() 关联桌面,这样一来,二者的关系是不是可以想象出有了联系了呢?
这里的两个函数忽略了参数,要是你有兴趣的话可以看看下面msdn链接的解释
Window Station and Desktop Functions
该页面给出的是一族windows api,这些api都比较好理解
2.2, 64位系统下,用vs2013 64位编译的方式编译,32位系统下,程序用32位编译方式
2.3
STARTUPINFO sti = {
sizeof(sti)
};
sti.lpDesktop = DESTOP_NAME;
若是第一次启动了这个程序的话,将会生成一个explorer.exe进程,此时若是在任务管理器中查看,有2个explorer进程,若是关闭我们的程序,这个2explorer进程个不会受到
影响,当第二次执行我们的程序时,(未关机),会发现窗口2中的东西和之前一样,没有变化