1.桌面到底是个什么东西.
2.为什么要研究桌面.
3.桌面如何实现的.
4.可以如何利用桌面.
桌面对象,以下描述取得MSDN,中文为本人翻译.
Only the desktops of the interactive window station can be visible and receive user input.
仅仅当桌面关联了窗口站才能显示并且接受用户输入(能够处理消息).
Applications can use the following functions for manipulating desktop objects:
应用程序可以通过以下函数操作桌面对象.
CloseDesktop Closes a specified desktop.
关闭一个指定的桌面
CreateDesktop Creates a new desktop on a specified window station.
创建一个桌面以一个指定的窗口站
EnumDesktops Enumerates the desktops on a specified window station by repeatedly calling an application-defined EnumDesktopProc callback function.
枚举桌面,应用程序提供的EnumDesktopProc回调函数处理相应桌面
EnumDesktopWindows Enumerates the windows on a specified desktop by repeatedly calling an application-defined EnumWindowsProc callback function.
枚举桌面窗口以一个指定的桌面,应用程序提供的EEnumWindowsPro回调函数处理相应桌面窗口
GetThreadDesktop Returns a handle to the desktop assigned to the calling thread.
取得关联桌面的线程(也就是为桌面建立消息队列的线程).
GetUserObjectInformation Gets information about a window station or desktop object.
取得用户对象信息,这个对象可以是桌面,也可以是窗口站
GetUserObjectSecurity Gets security information for a window station or desktop object.
取得用户对象安全属性信息,这个对象可以是桌面,也可以是窗口站
OpenDesktop Opens a handle to an existing desktop.
打开一个存在的桌面
SetThreadDesktop Assigns a specified desktop to the calling thread.
设置桌面线程
SetUserObjectInformation Sets information about a window station or desktop object.
设置用户对象的信息,这个对象可以是桌面,也可以是窗口站
SetUserObjectSecurity Sets security information for a window station or desktop object.
设置用户对象安全属性的信息,这个对象可以是桌面,也可以是窗口站
桌面窗口
Desktop Window
The desktop the window displays the desktop list view, which contains icons such as "My Computer", and the task bar containing the Start button.
桌面窗口是个列表视图,它包含一些图标比如"我的文档",以及一个包含开始按钮的任务栏.
This object is rarely queried by clients because the list view and the taskbar cover the entire desktop. The desktop object can be retrieved at login time, before the operating system shell displays the list view and taskbar. In some cases, the desktop can be obtained when navigating from other objects.
桌面对象已经被请求创建好了当它显示到整个屏幕中.
The window class name for the desktop window is "#32769".
桌面类名是"#32769".
以上似乎很抽象,下面我们代码伺候.
桌面对象:
typedef struct _DESKTOP
{
CSHORT Type; //这里是ExDesktopObjectType,他是一个内核对象.
CSHORT Size; //控制版本
LIST_ENTRY ListEntry; //桌面链表入口
LIST_ENTRY PtiList; //???
/* Pointer to the associated window station. */
struct _WINSTATION_OBJECT *WindowStation; //当前桌面对象关联的窗口站
/* Pointer to the active queue. */
PVOID ActiveMessageQueue; //活动的消息队列
/* Rectangle of the work area */
RECTL WorkArea; //桌面RECT
/* Handle of the desktop window. */
HANDLE DesktopWindow; //桌面窗口
/* Thread blocking input */
PVOID BlockInputThread; //输入线程
LIST_ENTRY ShellHookWindows; //HOOK的窗口入口
PWIN32HEAP pheapDesktop; //桌面堆
PSECTION_OBJECT DesktopHeapSection; //桌面堆节
PDESKTOPINFO DesktopInfo; //桌面信息,作为参数传给线程
} DESKTOP, *PDESKTOP;
桌面窗口:
HANDLE
DesktopCreateWindow(IN OUT ITrayWindow *Tray)
{
HANDLE hThread;
HANDLE hEvent;
DWORD DesktopThreadId;
HANDLE hDesktop = NULL;
HANDLE Handles[2];
DWORD WaitResult;
hEvent = CreateEvent(NULL,
FALSE,
FALSE,
NULL);
if (hEvent != NULL)
{
volatile DESKCREATEINFO DeskCreateInfo;
DeskCreateInfo.hEvent = hEvent;
DeskCreateInfo.Tray = Tray;
DeskCreateInfo.hDesktop = NULL;
hThread = CreateThread(NULL,
0,
DesktopThreadProc,
(PVOID)&DeskCreateInfo,
0,
&DesktopThreadId);
if (hThread != NULL)
{
Handles[0] = hThread;
Handles[1] = hEvent;
for (;;) //进入消息循环
{
WaitResult = MsgWaitForMultipleObjects(sizeof(Handles) / sizeof(Handles[0]),
Handles,
FALSE,
INFINITE,
QS_ALLEVENTS);
if (WaitResult == WAIT_OBJECT_0 + (sizeof(Handles) / sizeof(Handles[0])))
TrayProcessMessages(Tray);
else if (WaitResult != WAIT_FAILED && WaitResult != WAIT_OBJECT_0)
{
hDesktop = DeskCreateInfo.hDesktop;
break;
}
}
CloseHandle(hThread);
}
CloseHandle(hEvent);
}
return hDesktop;
}
typedef struct _DESKCREATEINFO
{
HANDLE hEvent;
ITrayWindow *Tray;
HANDLE hDesktop;
} DESKCREATEINFO, *PDESKCREATEINFO;
桌面线程消息循环.
VOID
TrayProcessMessages(IN OUT ITrayWindow *Tray)
{
ITrayWindowImpl *This;
MSG Msg;
This = impl_from_ITrayWindow(Tray);
/* FIXME: We should keep a reference here... */
while (PeekMessage(&Msg,
NULL,
0,
0,
PM_REMOVE))
{
if (Msg.message == WM_QUIT)
break;
if (This->StartMenuBand == NULL ||
IMenuBand_IsMenuMessage(This->StartMenuBand,
&Msg) != S_OK)
{
TranslateMessage(&Msg);
DispatchMessage(&Msg);
}
}
}
桌面Tray数据结构.
typedef struct
{
const ITrayWindowVtbl *lpVtbl; //
const IShellDesktopTrayVtbl *lpVtblShellDesktopTray;
LONG Ref;
HWND hWnd;
HWND hWndDesktop;
HWND hwndStart; //开始按钮
HIMAGELIST himlStartBtn; //开始按钮的ImageList
SIZE StartBtnSize; //开始按钮大小
HFONT hStartBtnFont; //字体
HFONT hCaptionFont; //标题字体
ITrayBandSite *TrayBandSite;
HWND hwndRebar;
HWND hwndTaskSwitch;
HWND hwndTrayNotify;
DWORD Position;
HMONITOR Monitor; //监视器
DWORD DraggingPosition; //正在拖动的位置
HMONITOR DraggingMonitor; //正在拖动的监视器
RECT rcTrayWnd[4]; //
RECT rcNewPosSize;
SIZE TraySize; //
union
{
DWORD Flags;
struct
{
DWORD AutoHide : 1;
DWORD AlwaysOnTop : 1;
DWORD SmSmallIcons : 1;
DWORD HideClock : 1;
DWORD Locked : 1;
/* UI Status */
DWORD InSizeMove : 1;
DWORD IsDragging : 1;
DWORD NewPosSize : 1;
};
};
NONCLIENTMETRICS ncm;
HFONT hFont;
IMenuBand *StartMenuBand;
IMenuPopup *StartMenuPopup;
HBITMAP hbmStartMenu; //开始菜单位图
HWND hWndTrayProperties;
} ITrayWindowImpl;
桌面本身是一个窗口,是在Explorer.exe最重要的一部分.研究它是研究WINDOWS必须的一个环节,它本身和其他的窗口关联也非常大.