已知一窗体的句柄,如何将一组件的parent赋予此窗体?(真的无法解决吗?) (100分)

  • 主题发起人 主题发起人 yostgxf
  • 开始时间 开始时间
难道真的不行了,还是没有高手出现?这个问题没人遇到过吗?
 
我还是没有听明白你的意思。
 
看看这个,我想是你需要的:

在MDI程序中,由于MDI的主窗口一般的功能是提供子窗口显示的位置和提供菜单、工具条、状态条等,而窗口的客户区则一般不会有其它的用途,如果在这里画上一些软件的标志、公司的标志或者其它的背景图案的话,不仅可以使MDI的主窗口更加充实、美观,而且还可以更加突出公司的形象和增加公司标志在客户心中的地位。
由于MDI主窗口的特性,使用普通OnPaint和使用TImage等方法都不会产生作用。下面将用编写一个简单的MDI程序来介绍如何实现。
第一步:打开Delphi(Delphi 1,2,3都可以),创建一个新的工程。
第二步:将Form1的FormStyle设置为fsMDIForm,设置成MDI的主窗口。
第三步:在Form1上增加一个Image元件,并选择要设置的背景到Image的Picture中。
第四步:在Form1的Private中定义:
FClientInstance,
FPrevClientProc : TFarProc;
PROCEDURE ClientWndProc(VAR Message: TMessage);
第五步:在实现(implementation)中加入上述过程的具体内容:
PROCEDURE TForm1.ClientWndProc(VAR Message: TMessage);
VAR
MyDC : hDC;
Ro, Co : Word;
begin
with Message do
case Msg of
WM_ERASEBKGND:
begin
MyDC := TWMEraseBkGnd(Message).DC;
FOR Ro := 0 TO ClientHeight DIV Image1.Picture.Height DO
FOR Co := 0 TO ClientWIDTH DIV Image1.Picture.Width DO
BitBlt(MyDC, Co*Image1.Picture.Width, Ro*Image1.Picture.Height,
Image1.Picture.Width, Image1.Picture.Height,
Image1.Picture.Bitmap.Canvas.Handle, 0, 0, SRCCOPY);
Result := 1;
end;
else
Result := CallWindowProc(FPrevClientProc, ClientHandle, Msg, wParam, lParam);
end;
end;
第六步:在Form1的创建事件中加入:
FClientInstance := MakeObjectInstance(ClientWndProc);
FPrevClientProc := Pointer(GetWindowLong(ClientHandle, GWL_WNDPROC));
SetWindowLong(ClientHandle, GWL_WNDPROC, LongInt(FClientInstance));
上面的步骤已经完成了MDI主窗口背景图案的设置,下面可以增加一个MDIChild窗口,实现MDI程序。
第七步:新增加一个Form,并将FormStyle设置为fsMDIChild。
现在你可以编译运行这个程序,你会发现,Image元件并不会在Form上显示出来,但是整个Form的客户区域被Image中的图像所铺满。

 
谢谢你,网事如风。圣诞快乐!
你说的内容我明白,我不是想用截取事件的方法画一张静止的图。我想把一个可操作的组件放到客户区域去使用,比如GIS控件,TChart等。其它操作都已经实现,就是它的显示区域大小的控制很不方便,必须到主窗体的FormOnReSize,RePaint事件中去控制。因为我把它的Parent设为nil了,这样Align属性就不起作用了。
我想知道有没有其它的方法可以解决它?希望大家帮忙!
 
版主,对这个问题有了解吗?能否发表一点看法
 
我有个方法,当然思路可能简单了些,就是用一个panel覆盖掉客户区,然后将你说的控件拖到panel上去,一切ok了吧. 楼主,不要老钻牛角尖吗[:)]
 
to yostgxf
有办法的,我看到过一个高人的例子。
我找一下,不一定能找到。
 
谢谢savetime,希望你好好找一下。
to fima:你的方法不行的,这样子窗体没法显示。我也想绕过,可是没满意的方法。
 
to yostgxf,
我说有的办法是基于你下面的话:
>>我想把一个可操作的组件放到客户区域去使用,比如GIS控件,TChart等。其它操作都已
>>经实现,就是它的显示区域大小的控制很不方便,必须到主窗体的FormOnReSize,
>>RePaint事件中去控制。因为我把它的Parent设为nil了,这样Align属性就不起作用了。
实际上不是真的可以,那样要改写 VCL 类库了。我这里有个例子,能模拟在 MDI 客户
放置子窗口。效果还可以了。
如果你要的话,请告知你的邮箱或发信到我的邮箱 savetime2k@yahoo.com
 
to yostgxf
看下面的可以吗。
var
Edit1: TEdit;
...
begin
Edit1.CreateParented(句柄);
Edit1.Text := '可以吗';
ShowWindow(Edit1.Handle, SW_SHOW);
end;
 
to wjh_wy
我没明白你解决方法的意思
 
楼主:我试了一下,用主窗体的事件控制也不复杂的。
 
其实我觉得这是Borland的Bug。而VB设计出来的MDI窗体就没有此问题,为什么呢。其实如果你的是MDI主窗体,他会在MDI主窗体创建MDIClient对象,而这个MDIClient对象只能在运行时控制。而且MDI主窗体只提供了仅有的几个属性给你操作MDIClient对象,所以根本不能很好的控制。而用VB设计出来的MDI窗体,在设计时都提供了让你操作MDIClient对象。
办法不是没有的,有可能要修改VCL源代码了。
请VCL源码:
procedure TCustomForm.CreateWnd;
var
ClientCreateStruct: TClientCreateStruct;
begin
inherited CreateWnd;
if NewStyleControls then
if BorderStyle <> bsDialog then
SendMessage(Handle, WM_SETICON, 1, GetIconHandle) else
SendMessage(Handle, WM_SETICON, 1, 0);
if not (csDesigning in ComponentState) then
case FormStyle of
fsMDIForm:
begin
with ClientCreateStruct do
begin
idFirstChild := $FF00;
hWindowMenu := 0;
if FWindowMenu <> nil then hWindowMenu := FWindowMenu.Handle;
end;
FClientHandle := Windows.CreateWindowEx(WS_EX_CLIENTEDGE, 'MDICLIENT',
nil, WS_CHILD or WS_VISIBLE or WS_GROUP or WS_TABSTOP or
WS_CLIPCHILDREN or WS_HSCROLL or WS_VSCROLL or WS_CLIPSIBLINGS or
MDIS_ALLCHILDSTYLES, 0, 0, ClientWidth, ClientHeight, Handle, 0,
HInstance, @ClientCreateStruct);
FClientInstance := MakeObjectInstance(ClientWndProc);
FDefClientProc := Pointer(GetWindowLong(FClientHandle, GWL_WNDPROC));
SetWindowLong(FClientHandle, GWL_WNDPROC, Longint(FClientInstance));
end;
fsStayOnTop:
SetWindowPos(Handle, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE or
SWP_NOSIZE or SWP_NOACTIVATE);
end;
end;
 
请看下图,你仔细看一下主窗体上的滚动条,是不是不同呀,就是因为主窗体中有MDIClient对象才产生了这样的效果。
http://www.efile.com.cn/efile/cjsh/images/MDI.BMP
 
to wjh_wy
谢谢,我试一下。
 
没有很好解决,时间久了,还是先结帖了
 

Similar threads

S
回复
0
查看
3K
SUNSTONE的Delphi笔记
S
S
回复
0
查看
2K
SUNSTONE的Delphi笔记
S
I
回复
0
查看
601
import
I
后退
顶部