关于透明窗体的问题。(100分)

  • 主题发起人 主题发起人 zhangkan
  • 开始时间 开始时间
Z

zhangkan

Unregistered / Unconfirmed
GUEST, unregistred user!
1.我要将窗体设为透明,但为什么我执行程序后,窗体却还是灰色,我将其最小化然后最大
化就正常了。请问要怎样才能不出现这种问题,而且,若有其他窗体覆盖了透明窗体,将该
窗体移开后,那儿就留下一块灰的。(50分)
2.怎样判断当前在哪个系统下面,我是win2000 professional,而我用GetVersionEx,抓出
来的版本还是说win95﹐请问怎样才能确切判断当前是在哪个系统下?(50分)
 
第二个问题:
肯定没有问题的。它取出来说是NT 5(dwMajorVersion = 5)。
 
;可以调用一下refresh那个函数。/
 
1.透明窗体
我试了用refresh,不行。而且若我将Lable的Transparent设为True,当鼠标移到上面时,将
Caption加上文字,而鼠标移走后,再将其变为空。但鼠标一移上去,Label内变为灰底了。
难道要用TextOut吗?请问有没有什么解决的法子?谢谢!
2.怎样判断win3.x,win95/98,win Me,win2000,Win NT4,NT5版本,甚至win2000的
advance server,professional,server等等。
var ver:integer;
major:integer;
minor:integer;
begin
ver:=GetVersion();
major:=ver and 255;
minor:=(ver and 255*256) div 256;
showmessage('系統版本號是'+inttostr(ver));
showmessage('系統主版本號是'+inttostr(major)); //得到5
showmessage('系統次版本號是'+inttostr(minor)); //得到5
不知ver有什么用?另外,我在win98下面试得到的MAJOR和MINOR是4,是不是基于NT的就是5,
而低于5的就是NT以下版本了,但是我要判断NT和win2000,或者是判断NT5和NT4,Win ME怎
么办?
 
第一个有点莫名其妙,就不说了,textout也有一个参数是设置透明背景的
第二个:come from msdn

造成应用程序无法安装在 Windows 2000 上的第一位原因,是它们无法正确处理版本号。
我们发现很多应用程序都进行以下示例代码所做的操作。它们在运行过程中会调用
GetVersionEX,然后写下一条“if”语句,该语句规定:“如果系统是版本 3,
因为没有新的 Shell,我不能正常运行,所以我可能无法安装。如果系统是版本 4,
我可以进行安装和设置”。问题出在如果系统是版本 5,这一“if”语句就没有了下文
。因为版本号是 5.0,这些应用程序由于自身原因而无法安装,所以我们发现了一系列
这样那样的问题。

if (osvi.dwMajorVersion == 3)
{
// 请这样做
}
else if (osvi.dwMajorVersion == 4)
{
// 请那样做
}

测试组继续寻找解决方案,并蒙蔽了许多此类应用程序。在早期的编译中,我们能够采取
措施改变 GetVersionEx 的返回值。我们可以改变其返回值,欺骗应用程序,告诉它版本号
就是 4.0,然后程序就能够继续安装,并正常运行。但有部分应用程序的设计思想就是不
能安装在 Windows 2000 上。对于病毒扫描程序或其他低级实用程序来说,受限于某一操
作系统版本是可以理解的。不过,这些应用程序会显示消息来说明这一点。我们查找的是
那些不能安装或无法正常运行、又根本没有通知用户的应用程序。

怎样才能正确地检查版本号?在 Windows 2000 中我们将添加一个新的 API:
VerifyVersionInfo,这一 API 在运行时将依次检查主版本号、次版本号以及服务包。
如果出现了操作系统的新版本,应用程序仍然能够在其上安装并运行。实际上应用
VerifyVersionInfo 的选项和方式还有很多,但如果只是检查“要是操作系统升级了,
应用程序该如何处理”这一类问题,您只需调用这三个标志,然后检查主版本号、
次版本号以及服务包。您能够定义以下语句:“我的程序需要运行在
Windows NT 4.0、SP2 上”,然后询问 VerifyVersionInfo“我正在运行的操作系统
是否已达到这一标准?”,该 API 将返回真值或假值。

VerifyVersionInfo(&osvi,
VER_MAJORVERSION |
VER_MINORVERSION |
VER_SERVICEPACKMAJOR,
dwlConditionMask);

采用这一方式检查版本,就可以符合 Windows 2000 应用程序的规范,其基本思想是“
只要存在新版本的操作系统,就要在新版本上进行安装。”

应用 VerifyVersionInfo 的一个问题是目前该 API 只能在 Windows 2000 平台上运行。
为了检查 Windows 95 等旧平台的版本,您必须应用GetVersionEx。查看以下示例代码
,即可发现它的功能与 VerifyVersionInfo 基本相同:依次检查主版本号、次版本号以
及服务包。

BOOL bIsWindowsVersionOK(DWORD dwMajor, DWORD dwMinor, DWORD dwSPMajor )
{
OSVERSIONINFO osvi;
// 初始化 OSVERSIONINFO 结构
//
ZeroMemory(&osvi, sizeof(OSVERSIONINFO));
osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
GetVersionEx((OSVERSIONINFO*)&osvi);
// 首先,主版本
if ( osvi.dwMajorVersion > dwMajor )
return TRUE;
else if ( osvi.dwMajorVersion == dwMajor )
{
// 然后,次版本
if (osvi.dwMinorVersion > dwMinor )
return TRUE;
else if (osvi.dwMinorVersion == dwMinor )
{
// 对,最好检查一下 Service Pack
if ( dwSPMajor && osvi.dwPlatformId == VER_PLATFORM_WIN32_NT )
{
HKEY hKey;
DWORD dwCSDVersion;
DWORD dwSize;
BOOL fMeetsSPRequirement = FALSE;

if (RegOpenKeyEx(HKEY_LOCAL_MACHINE,
"System//CurrentControlSet//Control//Windows", 0,
KEY_QUERY_VALUE, &hKey) == ERROR_SUCCESS)
{
dwSize = sizeof(dwCSDVersion);
if (RegQueryValueEx(hKey, "CSDVersion",
NULL, NULL, (unsigned char*)&dwCSDVersion,
&dwSize) == ERROR_SUCCESS)
{
fMeetsSPRequirement = (LOWORD(dwCSDVersion) >= dwSPMajor);
}
RegCloseKey(hKey);
}
return fMeetsSPRequirement;
}
return TRUE;
}
}

return FALSE;

}

//
// 此示例适用于 Windows 2000 和更新版本
//
BOOL bIsWindowsVersionOK(DWORD dwMajor, DWORD dwMinor, DWORD dwSPMajor )
{

OSVERSIONINFOEX osvi;
ZeroMemory(&osvi, sizeof(OSVERSIONINFOEX));
osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);
osvi.dwMajorVersion = dwMajor;
osvi.dwMinorVersion = dwMinor;
osvi.wServicePackMajor = dwSPMajor;
// 设置条件掩码。
VER_SET_CONDITION( dwlConditionMask, VER_MAJORVERSION, VER_GREATER_EQUAL );
VER_SET_CONDITION( dwlConditionMask, VER_MINORVERSION, VER_GREATER_EQUAL );
VER_SET_CONDITION( dwlConditionMask, VER_SERVICEPACKMAJOR, VER_GREATER_EQUAL );
// 执行测试。
return VerifyVersionInfo(&osvi,
VER_MAJORVERSION | VER_MINORVERSION
| VER_SERVICEPACKMAJOR,dwlConditionMask);
}

首先,需要检查主版本号。如果当前操作系统的主版本号高于所需主版本号,则不需要
进行任何检查,直接向下运行即可。如果主版本号相等,则以同样方式检查次版本号。
最后再检查服务包号。在我们获得发布的某一版本时,就可以说“没关系,我们不在乎
是 Service Pack 3、4 还是 5”。如果主版本号或次版本号有所增长,系统同样可以处
理。我们查找了所有要检查版本信息的应用程序,发现它们将分别检查每一组件。它们
在运行中会说“噢,主版本号是 5,我只要求 4,不错。次版本号是 .0,很好,但
Service Pack 是 0,我需要的是 3”。很明显,Windows 2000 还没有推出 SP3,
所以这种检查版本信息的方法是错误的。

检查 Windows NT 的版本号时需要注意以下细节:检查版本号和服务包信息的方法有三种
。第一种是获取 GetVersionEx 的返回值,然后检查“szCSDVersion”字符串。实际的
服务包号嵌入在该字符串的某一位置。分析这一串字符实在是比较繁琐,而且您必须始终
牢记它是否进行了本地化,这是很难做到的。这不是一种最好的方式。如果系统运行的是
Windows NT 4.0,您只需检查以下注册键值,其中有一个数字是服务包号。提取这一数字,
并进行一个“等于”或“大于”比较即可:

HCLM/System/CurrentControlSet/Control/Windows/CSDVersion

如果您运行的是 Windows 2000 或更高版本,则仍可以使用 GetVersionEx,但需要将其传
递到 OSVERSIONINFOEX 结构,而不是正在使用的OSVERSIONINFO 结构。考虑到起始处操作
员成员的大小,Windows 2000 会将其视为一个较大的结构,并且给出一个新的字段(服务
包、主版本、次版本),作为进行比较时所用的整数。如果您还是使用
VerifyVersionInfo,您会发现这是最方便的一种方式。
 
第一个问题我遇到过同样的现象
不过我是mdi主窗口做成透明的,但如最小化child区域并不重画。但最小化主窗口,
再恢复后就可以了。
解决方案:放弃了透明
 
第一个问题也不奇怪呀。因为我将窗口最小化,然后再恢复视窗就正常了。说明中间哪儿有
一个重绘的动作,只是我找不到。哪位大侠知道,告诉我一下就解决了。第二个问题我还要
试一下。
 
第二个问题给你源代码吧
var
OsInfo : OSVERSIONINFO;
SS,TmpSS : string;
Mem : TMEMORYSTATUS;
begin
//获得操作系统信息
OsInfo.dwOSVersionInfoSize := SizeOf(OSVERSIONINFO);
GetVersionEx(OsInfo);
case OsInfo.dwPlatformId of
VER_PLATFORM_WIN32S : SS := 'Windows 3.x';
VER_PLATFORM_WIN32_WINDOWS : SS := 'Windows 95/98';
VER_PLATFORM_WIN32_NT : SS := 'Windows NT';
end;
TmpSS := String(OsInfo.szCSDVersion);
Label11.Caption := SS + ' '+IntToStr(OsInfo.dwMajorVersion)+'.'+IntToStr(OsInfo.dwMinorVersion)+'.'+IntToStr((OsInfo.dwBuildNumber shl 16) shr 16)+'.'+TmpSS;
......
 
第二个问题解决了,第一个呢?有没有好一点的法子?
 
1.使窗体透明:
在form的Create事件中:
SetWindowLong(Form1.Handle, GWL_EXSTYLE, WS_EX_TRANSPARENT)
即可
 
第一个问题
在form的oncreate 中吊用SetBkMode,大概是SetBkMode(canvas.handle,TRANSPARENT)
最好还拦截一下WM_ERASEBKGND,写如和oncreate中相同的代码。
 
现在的问题是:因为表单是透明的,而label我也设成透明。我用TextOut输出字型,
label1.Canvas.TextOut(0,0,'Hello');
但我用什么法子将输出的字符清除掉呢?我用label1.Canvas.TextOut(0,0,' ');不行。
 
窗体透明源代码如下,试着做一下,看行否?

unit Unit1;

interface

uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs;

type
TForm1 = class(TForm)
procedure FormCreate(Sender: TObject);

private
{ Private declarations }
public
{ Public declarations }
PROCEDURE CMEraseBkgnd(var Message:TWMEraseBkgnd);Message WM_ERASEBKGND;

end;

var
Form1: TForm1;

implementation

{$R *.DFM}
PROCEDURE Tform1.CMEraseBkgnd(var Message:TWMEraseBkgnd);

BEGIN
brush.style:=bsClear;
Inherited;
END;

procedure TForm1.FormCreate(Sender: TObject);
begin

end;

end.
 
窗体透明我已经解决了,下面是我用Label的问题.
因为表单是透明的,而label我也设成透明。我用TextOut输出字型,
label1.Canvas.TextOut(0,0,'Hello');
但我用什么法子将输出的字符清除掉呢?我用label1.Canvas.TextOut(0,0,' ');不行。
这是为什么?怎么解决?谢谢!
 
;小弟 W.N.W.L :( ....
关注
 
将一个FORM变成透明的实质性手段就是拦截CMEraseBkgnd消息。下面是源程序.
Unit Utransform;
interface
uses Windows, Messages, SysUtils,
Classes, Graphics, Controls, Forms, Dialogs, StdCtrls, ExtCtrls;
type TForm1 = class(Tform)
private { Private declarations }
public { Public declarations }
PROCEDURE CMEraseBkgnd(var Message:TWMEraseBkgnd);
Message WM_ERASEBKGND;
end;
var Form1: TForm1;
implementation
{$R *.DFM}
PROCEDURE Tform1.CMEraseBkgnd(var Message:TWMEraseBkgnd);
BEGIN
brush.style:=bsClear;
Inherited;
END;
end.

 
 
拦截CMEraseBkgnd的办法不行

第一个我也没有解决
后来索性将窗体设置为控件的形状
就没有这个问题了

不过这个办法太傻 有别的好办法吗?
 
这里很多人的回答都好象来自程序员大本营。
 
我现在实际上已经将窗体透明了,但是我想鼠标移到一个Label上的时候,通过
label1.Canvas.TextOut(0,0,'Hello');显示出字出来,我不能用Caption等于什么来,因为
这样子Label部分就为变成Label的底色,也就不能透明了,但是用TextOut的方法便可以,
但是我想鼠标移出Label控件的时候,又将字消失掉,但是我用
label1.Canvas.TextOut(0,0,'    ')里面加空格的方法做不到。可能要用到图片处理
方面的办法才行,我不知道用什么办法,因为我对图片处理一点都不熟悉。哪位能告诉我
怎么做?有没有别的法子?
 

Similar threads

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