怎么样窗体贴在桌面上,而且还不把窗体置顶? ( 积分: 200 )

  • 主题发起人 主题发起人 runzi_111
  • 开始时间 开始时间
R

runzi_111

Unregistered / Unconfirmed
GUEST, unregistred user!
如题!也就是不管怎么点“显示桌面”还是键盘的操作,都不会让窗体最小化!始终浮在桌面上,而且还不置顶!回答问题者都有分!
 
需要你用api去设置或创建,在注册一个窗体类时设置style,同时拦截窗体的消息循环,屏蔽掉显示桌面等操作给窗体发送的最小化消息.
 
关注中......
明知道2个要求相互矛盾,还是期待高手的出现~~~~
 
有些桌面秀实现了这种效果
但具体如何实现的 还请高手指点
 
用那种层次结构可以实现,但如xuegaoyili所说,不是那么简单,当焦点在窗体上时,可以捕获“显示桌面”消息,但没在的时候,就响应不了了!我测试过了!
不过可能有不到地方,请指教!
 
看破天惊的小程序就明白了。。。[:D]
main.pas单元
--------------------
{********************************************************
*** ***
*** 破天惊工作室
*** 名称:嵌入窗体之桌面嵌入
*** 日期:12.9.2004
*** 环境:Delphi6+WinXP
*** 作者:破天惊
*** E-Mail:Tresss@sohu.com
*** HomePage:http://tresss.com
***
*** 说明:
*** ***
*********************************************************}
unit main;

interface

uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, ExtCtrls;

type
TFrmMain = class(TForm)
Btn1: TButton;
Timer1: TTimer;
Edt1: TEdit;
BtnOwner: TButton;
Label1: TLabel;
Btn2: TButton;
Edt2: TEdit;
Label2: TLabel;
Btn3: TButton;
Edt3: TEdit;
Label3: TLabel;
BtnRnd: TButton;
procedure Timer1Timer(Sender: TObject);
procedure BtnOwnerClick(Sender: TObject);
procedure FormCreate(Sender: TObject);
procedure Btn1Click(Sender: TObject);
procedure Btn2Click(Sender: TObject);
procedure Btn3Click(Sender: TObject);
procedure BtnRndClick(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;

var
FrmMain: TFrmMain;
TmpHandle:THandle;

implementation

{$R *.dfm}

procedure TFrmMain.Timer1Timer(Sender: TObject);
begin
FrmMain.ParentWindow:=0;
end;

procedure TFrmMain.BtnOwnerClick(Sender: TObject);
begin
FrmMain.ParentWindow:=0;
end;

procedure TFrmMain.FormCreate(Sender: TObject);
begin
TmpHandle:=FindWindow('Progman',Nil);
If TmpHandle<>0 Then
Begin
Edt3.Text:=IntToStr(TmpHandle);
TmpHandle:=GetWindow(TmpHandle,GW_CHILD);
Edt2.Text:=IntToStr(TmpHandle);
TmpHandle:=GetWindow(TmpHandle,GW_CHILD);
Edt1.Text:=IntToStr(TmpHandle);
End
Else
ShowMessage('找不到桌面,可能是Explorer已结束!');
end;

procedure TFrmMain.Btn1Click(Sender: TObject);
begin
If Edt1.Text<>'' Then
Begin
FrmMain.ParentWindow:=StrToInt(Edt1.Text);
BringWindowToTop(FrmMain.Handle);
End;
end;

procedure TFrmMain.Btn2Click(Sender: TObject);
begin
If Edt2.Text<>'' Then
Begin
FrmMain.ParentWindow:=StrToInt(Edt2.Text);
BringWindowToTop(FrmMain.Handle);
End;
end;

procedure TFrmMain.Btn3Click(Sender: TObject);
begin
If Edt3.Text<>'' Then
Begin
FrmMain.ParentWindow:=StrToInt(Edt3.Text);
BringWindowToTop(FrmMain.Handle);
End;
end;

procedure TFrmMain.BtnRndClick(Sender: TObject);
begin
If (Edt3.Text<>'') and (Edt2.Text<>'') Then
Begin
FrmMain.ParentWindow:=StrToInt(Edt3.Text);
BringWindowToTop(FrmMain.Handle);
FrmMain.Left:=0;
MoveWindow(StrToInt(Edt2.Text),170,0,screen.Width-170,screen.Height,False);
End;
end;

end.
main.dfm窗体
----------------------------
object FrmMain: TFrmMain
Left = 324
Top = 132
Width = 225
Height = 293
Caption = '嵌入桌面'
Color = clBtnFace
Font.Charset = DEFAULT_CHARSET
Font.Color = clWindowText
Font.Height = -11
Font.Name = 'MS Sans Serif'
Font.Style = []
OldCreateOrder = False
OnCreate = FormCreate
PixelsPerInch = 96
TextHeight = 13
object Label1: TLabel
Left = 9
Top = 9
Width = 125
Height = 13
AutoSize = False
Caption = '第一层:'
end
object Label2: TLabel
Left = 9
Top = 66
Width = 125
Height = 13
AutoSize = False
Caption = '第二层:'
end
object Label3: TLabel
Left = 9
Top = 123
Width = 125
Height = 13
AutoSize = False
Caption = '第三层:'
end
object Btn1: TButton
Left = 113
Top = 28
Width = 68
Height = 30
Caption = '嵌入'
TabOrder = 0
OnClick = Btn1Click
end
object Edt1: TEdit
Left = 9
Top = 28
Width = 96
Height = 21
ImeName = '紫光拼音输入法'
TabOrder = 1
Text = 'http://tresss.com'
end
object BtnOwner: TButton
Left = 9
Top = 217
Width = 172
Height = 30
Caption = '取消嵌入'
TabOrder = 2
OnClick = BtnOwnerClick
end
object Btn2: TButton
Left = 113
Top = 85
Width = 68
Height = 30
Caption = '嵌入'
TabOrder = 3
OnClick = Btn2Click
end
object Edt2: TEdit
Left = 9
Top = 85
Width = 96
Height = 21
ImeName = '紫光拼音输入法'
TabOrder = 4
Text = 'http://tresss.com'
end
object Btn3: TButton
Left = 113
Top = 142
Width = 68
Height = 29
Caption = '嵌入'
TabOrder = 5
OnClick = Btn3Click
end
object Edt3: TEdit
Left = 9
Top = 142
Width = 96
Height = 21
ImeName = '紫光拼音输入法'
TabOrder = 6
Text = 'http://tresss.com'
end
object BtnRnd: TButton
Left = 9
Top = 180
Width = 172
Height = 29
Caption = '嵌入并限制桌面大小'
TabOrder = 7
OnClick = BtnRndClick
end
object Timer1: TTimer
Interval = 20000
OnTimer = Timer1Timer
Left = 56
Top = 96
end
end
 
程序嵌入桌面

前几天在网上看到一个软件的介绍:可以嵌入桌面,即使是“显示桌面”也不会影响此程序。看作者说的好像有多么的神奇一样。周未就回来试一下。最后发现,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的桌面是分四层的。嵌入的窗体如果嵌入到前三层,那么我们所得到的结果是相同的。这时,它只相当于一个位于其它窗体的控件。但是在嵌入到第三层时,我们可以通过调整第二层的大小来使窗体不遮住桌面图标。所以,将窗体嵌入到此是比较理想的。
第四层是个意外的层。嵌在这里的窗体会表显出异样的情况。唯一值得我们嵌入的理由是:它不会随Explorer.exe进程的结束而关闭。
 
这里又有问题了,主窗体调用其它窗体,当点主窗体,其他被调用的窗体会跑到后面去!
问题啊!
 
等待中。。。。。。
 
你把主窗体放在底层桌面,把子窗体放在上一层点的桌面不就行了,即主窗体和子窗体放在不同层次的桌面就不会出现你的情况了。[:)]
 
我只能实现在最上方,且显示桌面不会消失的情况...
可以看我的笔记,类似QQ的.
 
这样你试试先用getwindow得到桌面句柄,然后调用SetParent将你的程序窗口的父窗口设置为桌面,就可以了。
 
把子窗体上移那还能行吗?那些消息什么的不是被截获了啊
 
都设置为第三层为父窗体可以,可是焦点为什么没有啊!跟死机是的!
麻烦死了!把我折腾死了!再弄不好,我就辞职了!
郁闷!郁闷死了!
 
我已经知道解决方案了
 
这种解决方案有个麻烦就是Explorer挂了以后,窗体就没了
 

Similar threads

回复
0
查看
816
不得闲
S
回复
0
查看
3K
SUNSTONE的Delphi笔记
S
S
回复
0
查看
2K
SUNSTONE的Delphi笔记
S
D
回复
0
查看
1K
DelphiTeacher的专栏
D
后退
顶部