MDI背景的刷新-- 一行解决引出的问题(0分)

  • 主题发起人 主题发起人 Prinse
  • 开始时间 开始时间
P

Prinse

Unregistered / Unconfirmed
GUEST, unregistred user!
各位大侠:
我用http://www.gislab.ecnu.edu.cn/delphibbs/DispQ.asp?LID=130802作试验时
发现:如果动态改变背景图时,不能自动刷新,不知何故。
 
用Repaint,Update,……等等都不行。
 
用invalidate呢?
 
都试过了。
各位大侠是不是因为没分而不语啊?
 
我的试验代码如次:(C++ Builder)
//---------------------------------------------------------------------------
void __fastcall TMainForm::FormCreate(TObject *Sender)
{
// Image0是主Form上的一个TImage对象
Image0->Picture->LoadFromFile("BM_10000.bmp");
this->Brush->Bitmap = Image0->Picture->Bitmap;
// 至此结果非常漂亮
}

void __fastcall TMainForm::Button1Click(TObject *Sender)
{
// Button也是主Form上的一个TButton对象
Image0->Picture->LoadFromFile("BM_00000.bmp");
this->Brush->Bitmap = Image0->Picture->Bitmap;
this->Repaint();
// 但是不能马上刷新, ^&^
}
//---------------------------------------------------------------------------
 
Application.Minimize;
AppliCation.Restore;
 

消息: WM_ERASEBKGND
 
To: Slicker
能否说细一些?
 
To: Liuly
你的方法可以刷新,但闪烁太厉害了。
我用
TForm.Visible := False;
TForm.Visible := True;
也无济于事。

难道这是不能解决的问题?
我加 100分悬赏。各位大侠觉得如何?如果实在不行,我也不必好奇了。
 
在 http://www.gislab.ecnu.edu.cn/delphibbs/DispQ.asp?LID=130802 中
waters已经给出了解决问题的思路,
由于MDI窗体的特性,OnPaint 事件和 TImage控件都无法正确显示背景图像(非MDI窗体可以),
只有截取WM_ERASEBKGND消息并改变Windows对此消息的缺省处理.在此给出我摘录的一篇开发技巧的文章,
********************************************************************************************************
给MDI主窗口加背景
由于MDI主窗口的特性,使用普通OnPaint和使用TImage等方法都不会产生作用。
下面将用编写一个简单的MDI程序来介绍如何实现。
第一步:创建一个新的工程。
第二步:将Form1的FormStyle设置为fsMDIForm,设置成MDI的主窗口。
第三步:在Form1上增加一个Image元件,并选择要设置的背景到Image的Picture中。
第四步:在Form1的Private中定义:
<font color=#0000ff>
FClientInstance,
FPrevClientProc : TFarProc;
PROCEDURE ClientWndProc(VAR Message: TMessage);</font>

第五步:在实现(implementation)中加入上述过程的具体内容:
<font color=#0000ff>
PROCEDURE TForm1.ClientWndProc(VAR Message: TMessage);
VAR
MyDC : hDC;
Ro, Co : Word;
begin
with Message do
case Msg of
<font color=#ff0000>WM_ERASEBKGND:</font>
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;
</font>
第六步:在Form1的创建事件中加入:
<font color=#0000ff
FClientInstance := MakeObjectInstance(ClientWndProc);
FPrevClientProc := Pointer(GetWindowLong(ClientHandle, GWL_WNDPROC));
SetWindowLong(ClientHandle, GWL_WNDPROC, LongInt(FClientInstance));
</font>
上面的步骤已经完成了MDI主窗口背景图案的设置,下面可以增加一个MDIChild窗口,实现MDI程序。

第七步:新增加一个Form,并将FormStyle设置为fsMDIChild。

现在你可以编译运行这个程序,
你会发现,Image元件并不会在Form上显示出来,但是整个Form的客户区域被Image中的图像所铺满。
********************************************************************************************************
当然,更改处理部分的代码,还可以实现诸如居中,缩放等功能...


 
Slicker:
你还是没说如何用WM_ERASEBKGND来刷新背景啊。
 
改变背景图像后,只要激发<font color=#0000ff>WM_ERASEBKGND</font>消息不就行了

 
Slicker:
好象是不行的。
我的例子是:在MDI Form上放一个Button上两个Image:Image1,Image2。
然后我如你上面所说写两个ClientWndProc:ClientWndProc1和ClientWndProc2。其内容
只相差在Image1和Image2上。
在OnClick的响应事件ButtonClick中,我交替ClientWndProc1和ClientWndProc2。但背景
仍不能改变。

你能否看看问题在哪里?谢谢了。

代码如下:

unit Ex1;
interface
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms,
Buttons, StdCtrls, ExtCtrls;
type
TForm1 = class(TForm)
Image1: TImage;
Image2: TImage;
Button1: TButton;
procedure Button1Click(Sender: TObject);
procedure FormCreate(Sender: TObject);
procedure SelfWndProc1(var SelfMsg: TMessage);//window procedure
procedure SelfWndProc2(var SelfMsg: TMessage);//window procedure
procedure FillBitmap(aDC:HDC; aImage:TImage);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form1: TForm1;
implementation
var
PrevProc, SelfProc : TFarProc;
{$R *.DFM}

procedure TForm1.Button1Click(Sender: TObject);
begin
Tag := (Tag + 1) mod 2;
if Tag=0 then SelfProc:=MakeObjectInstance(SelfWndProc1)
else SelfProc:=MakeObjectInstance(SelfWndProc2);
SetWindowLong(ClientHandle,GWL_WNDPROC,LongInt(SelfProc));
PostMessage(Handle, WM_ERASEBKGND, ClientHandle, 0);
Refresh;
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
PrevProc:=TFarProc(GetWindowLong(ClientHandle,GWL_WNDPROC));
SelfProc:=MakeObjectInstance(SelfWndProc1);
SetWindowLong(ClientHandle,GWL_WNDPROC,LongInt(SelfProc));
end;

procedure TForm1.FillBitmap(aDC:HDC; aImage:TImage);
var
aCanvas : TCanvas;
i, j, bH, bW, cH, cW : Word;
begin
bH := aImage.Picture.Height; cH := ClientHeight DIV bH;
bW := aImage.Picture.Width; cW := ClientWidth DIV bW;
aCanvas := aImage.Picture.Bitmap.Canvas;
for i := 0 TO cH DO
for j := 0 TO cW DO
BitBlt(aDC, j*bW, i*bH, bW, bH, aCanvas.Handle, 0, 0, SRCCOPY);
end;

procedure TForm1.SelfWndProc1(var SelfMsg:TMessage);
begin
with SelfMsg do
case Msg of
WM_ERASEBKGND:
begin
FillBitmap(TWMEraseBkGnd(SelfMsg).DC, Image1);
Result := 1;
end
else
Result := CallWindowProc(PrevProc, ClientHandle, Msg, wParam, lParam);
end;
end;

procedure TForm1.SelfWndProc2(var SelfMsg:TMessage);
begin
with SelfMsg do
case Msg of
WM_ERASEBKGND:
begin
FillBitmap(TWMEraseBkGnd(SelfMsg).DC, Image2);
Result := 1;
end
else
Result := CallWindowProc(PrevProc, ClientHandle, Msg, wParam, lParam);
end;
end;

end.
 
接受答案了.
 
后退
顶部