-----------开发环境Delphi7--------------------------
1 unit Unit1; 2 3 interface 4 5 uses 6 Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, 7 Dialogs, StdCtrls; 8 9 type 10 TFrm_210907 = class(TForm) 11 Button1: TButton; 12 Button2: TButton; 13 Edit1: TEdit; 14 Button3: TButton; 15 Button4: TButton; 16 procedure Button1Click(Sender: TObject); 17 procedure Button2Click(Sender: TObject); 18 procedure Button3Click(Sender: TObject); 19 procedure Button4Click(Sender: TObject); 20 private 21 { Private declarations } 22 public 23 { Public declarations } 24 end; 25 26 var 27 Frm_210907: TFrm_210907; 28 29 implementation 30 31 {$R *.dfm} 32 33 procedure TFrm_210907.Button1Click(Sender: TObject); 34 var 35 TmpHandle,TmpHandle2:HWND; 36 begin 37 TmpHandle:=FindWindow('Progman',Nil);//桌面第三层 38 //TmpHandle:=GetWindow(TmpHandle,GW_OWNER); 39 //GetLastError; 40 TmpHandle:=GetWindow(TmpHandle,GW_CHILD);//桌面第二层 41 //TmpHandle:=GetWindow(TmpHandle,GW_CHILD); //桌面第一层 42 //showmessage(IntToStr(TmpHandle));显示桌面第二层的句柄 43 Frm_210907.ParentWindow:=TmpHandle;//把窗体的拥有者指定为第二层 44 Frm_210907.Top:=0; //把窗体放在左上方 45 Frm_210907.Left:=0; 46 47 TmpHandle2:=FindWindow('Progman',Nil); 48 TmpHandle2:=GetWindow(TmpHandle2,GW_CHILD);//桌面第二层 49 TmpHandle2:=GetWindow(TmpHandle2,GW_CHILD);//桌面第一层 50 MoveWindow(TmpHandle2,0,200,1024,740,True);//桌面把第一层:Left:=0 ; Top:=200 ,Width:=1024 , Height:=740 ;True的意思就是重画当前桌面第一层 51 end; 52 53 procedure TFrm_210907.Button2Click(Sender: TObject); 54 var 55 TmpHandle:HWND; 56 begin 57 //恢复桌面 58 TmpHandle:=FindWindow('Progman',Nil); 59 TmpHandle:=GetWindow(TmpHandle,GW_CHILD); //桌面第二层 60 TmpHandle:=GetWindow(TmpHandle,GW_CHILD); //桌面第一层 61 //MoveWindow(TmpHandle,0,20,1024,740,False); 62 MoveWindow(TmpHandle,0,0,Screen.Width ,Screen.Height,True); //Button1改变了桌面第一层,Button2恢复桌面第一层 //也可以利用任务管理器,先关闭Explorer.exe,然后再在任务管理器中点击文件下的新建任务,输入Explorer后点击确定 63 end; 64 65 procedure TFrm_210907.Button3Click(Sender: TObject); 66 begin 67 Frm_210907.ParentWindow:=GetDesktopWindow; //把桌面设置为容器 68 end; 69 70 procedure TFrm_210907.Button4Click(Sender: TObject); 71 begin 72 Frm_210907.ParentWindow:=strtointdef(Edit1 .text,0 );//指定容器 73 end; 74 75 end.
1 object Frm_210907: TFrm_210907 2 Left = 503 3 Top = 225 4 Width = 728 5 Height = 675 6 Caption = 'Frm_210907' 7 Color = clBtnFace 8 Font.Charset = DEFAULT_CHARSET 9 Font.Color = clWindowText 10 Font.Height = -11 11 Font.Name = 'MS Sans Serif' 12 Font.Style = [] 13 OldCreateOrder = False 14 PixelsPerInch = 96 15 TextHeight = 13 16 object Button1: TButton 17 Left = 96 18 Top = 224 19 Width = 75 20 Height = 25 21 Caption = 'Button1' 22 TabOrder = 0 23 OnClick = Button1Click 24 end 25 object Button2: TButton 26 Left = 104 27 Top = 280 28 Width = 75 29 Height = 25 30 Caption = 'Button2' 31 TabOrder = 1 32 OnClick = Button2Click 33 end 34 object Edit1: TEdit 35 Left = 200 36 Top = 168 37 Width = 121 38 Height = 21 39 ImeName = '中文(简体) - 搜狗拼音输入法' 40 TabOrder = 2 41 Text = 'Edit1' 42 end 43 object Button3: TButton 44 Left = 112 45 Top = 344 46 Width = 75 47 Height = 25 48 Caption = 'Button3' 49 TabOrder = 3 50 OnClick = Button3Click 51 end 52 object Button4: TButton 53 Left = 336 54 Top = 168 55 Width = 75 56 Height = 25 57 Caption = 'Button4' 58 TabOrder = 4 59 OnClick = Button4Click 60 end 61 end
----资料--------资料来源-------------
delphi 在桌面中嵌入窗体 http://www.delphitop.com/html/xitong/2007.html
前几天在网上看到一个软件的介绍:可以嵌入桌面,即使是“显示桌面”也不会影响此程序。看作者说的好像有多么的神奇一样。周未就回来试一下。最后发现,Windows这个桌面还真是复杂和有意思。
首先要分析Windows桌面。
打开老牌软件"Spy Window"。查看一下桌面。取得一个“SysListView32”类的句柄(本系统为XP版本)。将其最小化,可以看出刚才取得的控件好像是透明的。因为将其最小化之后,还可以看到你所设置的桌面图片。
重新用"Spy Window"获取桌面上的控件句柄(也可以直接点击"Parent Window"取得其父窗口句柄),得到一个"SHELLDLL_DefView"类的句柄。将其最小化,可以看到桌面图片依然存在,难道又是一个透明控件吗?先不理会它,我们继续向“下”找。再一次取得“桌面”上一个类名为“Progman”的控件句柄。而且此时你会发现Spy Window的"Parent Window"按钮已不可用了。
这个类为“Progman”的窗口“下面”真的没有其它窗口了吗?按“Ctrl+Alt+Del“在任务管理器里结束“explorer”,后再使用“Spy Window”看一下,是不是又有一个类名为“#32769”的窗口出了。试着对此窗口进行禁用,最小化,隐藏操作试一下。好像一切都是无效的。
到此为至,应该说把这张桌面的结构搞清楚了。相当于图像处理中的四个图层,而且是透明图层。
按类名由前至里的排序为:
SysListView32
SHELLDLL_DefView
Progman
#32769
看来这个桌面果然不是一般的复杂。
回忆一下以前用代码来隐藏桌面的操作:
FindWindow(''''Progman'''',Nil);
ShowWindow(...);
这里的''''Progman''''就是第三层(本文中我们就以层来称呼它们)的窗口了。在结束进程“Explorer”时,此窗口消失,说明此窗口是由“Explorer.exe”建立的。
下面进行将程序嵌入到桌面里的操作。
这里所需要的只有一个语句:
FrmMain.ParentWindow:=ParentHandle;其中,ParentHandle是你所要嵌人的控件句柄。
按此实现,可以建立一个窗体,拖入一个TButton,一个TEdit。在Button的Click事件中写入代码FrmMain.ParentWindow:=StrToInt(EdtHandle.Text);
下面,先来嵌入“第一层桌面”看一下。用"Spy Window”取得当前桌面句柄,也就是第一层''''SysListView32''''。转为十进制后复制到EdtHandle。点击按钮。
程序是不是转为非焦点状态了。按一下“Win+D”(显示桌面)。是不是窗口仍停留在桌面上。
好像文章开头的目的已经实现了。
仔细测试一下当前的窗体,是不是与原来有很大的不同。首先,窗口的标题栏总是非焦点状态。第二窗体上的右击被桌面拦截了下来。
第三Edit里表显不出TEdit本身对消息的响应。如点击时,拖动时,按键时右击时,Edit缺少相应的闪烁输入光标,抹黑所选字符,文字处理,显示上下文菜单等。这是因为窗体得不到焦点,而得不到焦点对于TEdit控件来说,一切都是无效的。
动态取得第一层控件句柄的方法是:
TmpHandle:=FindWindow(''''Progman'''',Nil);
TmpHandle:=GetWindow(TmpHandle,GW_CHILD);
TmpHandle:=GetWindow(TmpHandle,GW_CHILD);
此时TmpHandle即是桌面的句柄了。
依照此方法,我们可以将窗体嵌入第二层''''SHELLDLL_DefView''''了。当嵌入第二层时,你会发现。所嵌入的程序窗口不见了。当我们把第一层最小化时,可以看到我们所嵌入的窗口是存在的。只是被第一层所遮住了。所以说,第一层并不是透明的!
第一层最小化之后,可以看到,桌面上的图标都不见了。再看一下第一层的类名“SysListView32”,可以确定,第一层这个控件的作用主要就是列出系统桌面上的图标。我们在当前第二层中点击一下右键。桌面菜单出来了吧?原来一切的消息及处理都是在这一层接收和处理的。这时可以用“新建”命令新建一个文档,之后再恢复第一层桌面,可以看到,新建的文档出现了。
可以这样理解,第一层是“显示层”,第二层是“功能层”。我们的窗体在这里是显示不出来的。而且同样得不到焦点。
现在,将我们的程序嵌入到第三层''''Progman'''',嵌入之后,出现了和第二层相同的结果,按功能来说这一层应该没有什么实际的用途,可能只是给上面两层提供一个容器。现在''''Progman''''中有了两个窗体,一个是原有的''''SHELLDLL_DefView'''',另一个便是这个嵌入窗体。但是前者用尽了所有的可视区域,所以才使得嵌入的窗体显示不出来。这种情况似乎平时也会遇到,那我们在嵌入时加入一句:BringWindowToTop(FrmMain.Handle);试试;
呵呵,看到了什么?是不是嵌入的窗口出现了?按一下"Win+D"看一下。如何?还在吧?如果桌面上有图标的话,此时这个窗体应该是挡遮住了一部分图标的。
处理的办法就是将上一层窗体缩小。如:
TmpHandle:=FindWindow(''''Progman'''',Nil);
TmpHandle:=GetWindow(TmpHandle,GW_CHILD);
MoveWindow(TmpHandle,0,20,1024,740,False);
这样,在窗体顶部留出了二十象素的高度。可以放一个任务栏式的窗体了。
现在只剩下最后一层"#32769"了。只要在系统登陆前的启动程序不变,此窗口的句柄应该是不变化的(有可能系统登陆前启动的程序有变化此句柄也不变,具体情况没试过)。
按前面的方法将窗体嵌入到此窗口中。
窗体又是得不到焦点的状态了。可以看出来这和嵌入到第一层差不多。但是我们拖动一下窗体看一下。此时窗体并不是实时跟随鼠标的。再仔细看一下,任务栏上出现了两个此程序的按钮。一个是程序的名称,一个是窗口的名称。这是一种奇怪的现象,从来没有见过的。或许我们可以这样解释它。Explorer会将符合要求的窗体显示在任务栏上(非ToolsWindows,并且可见)。本窗体就符合,而且Explorer又会将窗口"#32769"里的所有窗口放到任务栏上而不管它是否复。所以才会得到此结果。
总结一下:
Windows的桌面是分四层的。嵌入的窗体如果嵌入到第三层,并将Z轴顺序移到最上的话,程序就会一个正常的嵌入桌面的程序。这符合我们的要求。而且可以通过调整第二层的大小来使窗体不遮住桌面图标。所以,将窗体嵌入到此是很理想的。
第一层的嵌入也是可以的。但是在这里窗体会得不到焦点和使用不了右键。所以这里的窗体受很多限制。
第二层是一个根本不考虑嵌入窗体的地方,因为这里的窗体根本显示不出来。而且与第一层相同的得不到焦点。
第四层是个意外的层。嵌在这里的窗体会表显出异样的情况。唯一值得我们嵌入的理由是:它不会随Explorer.exe进程的结束而关闭。
首先要分析Windows桌面。
打开老牌软件"Spy Window"。查看一下桌面。取得一个“SysListView32”类的句柄(本系统为XP版本)。将其最小化,可以看出刚才取得的控件好像是透明的。因为将其最小化之后,还可以看到你所设置的桌面图片。
重新用"Spy Window"获取桌面上的控件句柄(也可以直接点击"Parent Window"取得其父窗口句柄),得到一个"SHELLDLL_DefView"类的句柄。将其最小化,可以看到桌面图片依然存在,难道又是一个透明控件吗?先不理会它,我们继续向“下”找。再一次取得“桌面”上一个类名为“Progman”的控件句柄。而且此时你会发现Spy Window的"Parent Window"按钮已不可用了。
这个类为“Progman”的窗口“下面”真的没有其它窗口了吗?按“Ctrl+Alt+Del“在任务管理器里结束“explorer”,后再使用“Spy Window”看一下,是不是又有一个类名为“#32769”的窗口出了。试着对此窗口进行禁用,最小化,隐藏操作试一下。好像一切都是无效的。
到此为至,应该说把这张桌面的结构搞清楚了。相当于图像处理中的四个图层,而且是透明图层。
按类名由前至里的排序为:
SysListView32
SHELLDLL_DefView
Progman
#32769
看来这个桌面果然不是一般的复杂。
回忆一下以前用代码来隐藏桌面的操作:
FindWindow(''''Progman'''',Nil);
ShowWindow(...);
这里的''''Progman''''就是第三层(本文中我们就以层来称呼它们)的窗口了。在结束进程“Explorer”时,此窗口消失,说明此窗口是由“Explorer.exe”建立的。
下面进行将程序嵌入到桌面里的操作。
这里所需要的只有一个语句:
FrmMain.ParentWindow:=ParentHandle;其中,ParentHandle是你所要嵌人的控件句柄。
按此实现,可以建立一个窗体,拖入一个TButton,一个TEdit。在Button的Click事件中写入代码FrmMain.ParentWindow:=StrToInt(EdtHandle.Text);
下面,先来嵌入“第一层桌面”看一下。用"Spy Window”取得当前桌面句柄,也就是第一层''''SysListView32''''。转为十进制后复制到EdtHandle。点击按钮。
程序是不是转为非焦点状态了。按一下“Win+D”(显示桌面)。是不是窗口仍停留在桌面上。
好像文章开头的目的已经实现了。
仔细测试一下当前的窗体,是不是与原来有很大的不同。首先,窗口的标题栏总是非焦点状态。第二窗体上的右击被桌面拦截了下来。
第三Edit里表显不出TEdit本身对消息的响应。如点击时,拖动时,按键时右击时,Edit缺少相应的闪烁输入光标,抹黑所选字符,文字处理,显示上下文菜单等。这是因为窗体得不到焦点,而得不到焦点对于TEdit控件来说,一切都是无效的。
动态取得第一层控件句柄的方法是:
TmpHandle:=FindWindow(''''Progman'''',Nil);
TmpHandle:=GetWindow(TmpHandle,GW_CHILD);
TmpHandle:=GetWindow(TmpHandle,GW_CHILD);
此时TmpHandle即是桌面的句柄了。
依照此方法,我们可以将窗体嵌入第二层''''SHELLDLL_DefView''''了。当嵌入第二层时,你会发现。所嵌入的程序窗口不见了。当我们把第一层最小化时,可以看到我们所嵌入的窗口是存在的。只是被第一层所遮住了。所以说,第一层并不是透明的!
第一层最小化之后,可以看到,桌面上的图标都不见了。再看一下第一层的类名“SysListView32”,可以确定,第一层这个控件的作用主要就是列出系统桌面上的图标。我们在当前第二层中点击一下右键。桌面菜单出来了吧?原来一切的消息及处理都是在这一层接收和处理的。这时可以用“新建”命令新建一个文档,之后再恢复第一层桌面,可以看到,新建的文档出现了。
可以这样理解,第一层是“显示层”,第二层是“功能层”。我们的窗体在这里是显示不出来的。而且同样得不到焦点。
现在,将我们的程序嵌入到第三层''''Progman'''',嵌入之后,出现了和第二层相同的结果,按功能来说这一层应该没有什么实际的用途,可能只是给上面两层提供一个容器。现在''''Progman''''中有了两个窗体,一个是原有的''''SHELLDLL_DefView'''',另一个便是这个嵌入窗体。但是前者用尽了所有的可视区域,所以才使得嵌入的窗体显示不出来。这种情况似乎平时也会遇到,那我们在嵌入时加入一句:BringWindowToTop(FrmMain.Handle);试试;
呵呵,看到了什么?是不是嵌入的窗口出现了?按一下"Win+D"看一下。如何?还在吧?如果桌面上有图标的话,此时这个窗体应该是挡遮住了一部分图标的。
处理的办法就是将上一层窗体缩小。如:
TmpHandle:=FindWindow(''''Progman'''',Nil);
TmpHandle:=GetWindow(TmpHandle,GW_CHILD);
MoveWindow(TmpHandle,0,20,1024,740,False);
这样,在窗体顶部留出了二十象素的高度。可以放一个任务栏式的窗体了。
现在只剩下最后一层"#32769"了。只要在系统登陆前的启动程序不变,此窗口的句柄应该是不变化的(有可能系统登陆前启动的程序有变化此句柄也不变,具体情况没试过)。
按前面的方法将窗体嵌入到此窗口中。
窗体又是得不到焦点的状态了。可以看出来这和嵌入到第一层差不多。但是我们拖动一下窗体看一下。此时窗体并不是实时跟随鼠标的。再仔细看一下,任务栏上出现了两个此程序的按钮。一个是程序的名称,一个是窗口的名称。这是一种奇怪的现象,从来没有见过的。或许我们可以这样解释它。Explorer会将符合要求的窗体显示在任务栏上(非ToolsWindows,并且可见)。本窗体就符合,而且Explorer又会将窗口"#32769"里的所有窗口放到任务栏上而不管它是否复。所以才会得到此结果。
总结一下:
Windows的桌面是分四层的。嵌入的窗体如果嵌入到第三层,并将Z轴顺序移到最上的话,程序就会一个正常的嵌入桌面的程序。这符合我们的要求。而且可以通过调整第二层的大小来使窗体不遮住桌面图标。所以,将窗体嵌入到此是很理想的。
第一层的嵌入也是可以的。但是在这里窗体会得不到焦点和使用不了右键。所以这里的窗体受很多限制。
第二层是一个根本不考虑嵌入窗体的地方,因为这里的窗体根本显示不出来。而且与第一层相同的得不到焦点。
第四层是个意外的层。嵌在这里的窗体会表显出异样的情况。唯一值得我们嵌入的理由是:它不会随Explorer.exe进程的结束而关闭。
用mfc实现就是这样的代码
HWND hDesktop = ::FindWindow("Progman", NULL);
hDesktop = ::GetWindow(hDesktop, GW_CHILD);
CWnd* pWndDesktop = CWnd::FromHandle(hDesktop);
this->SetParent(pWndDesktop);
---资料-------------