| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684 |
- {******************************************************************************}
- { CnPack For Delphi/C++Builder }
- { 中国人自己的开放源码第三方开发包 }
- { (C)Copyright 2001-2018 CnPack 开发组 }
- { ------------------------------------ }
- { }
- { 本开发包是开源的自由软件,您可以遵照 CnPack 的发布协议来修 }
- { 改和重新发布这一程序。 }
- { }
- { 发布这一开发包的目的是希望它有用,但没有任何担保。甚至没有 }
- { 适合特定目的而隐含的担保。更详细的情况请参阅 CnPack 发布协议。 }
- { }
- { 您应该已经和开发包一起收到一份 CnPack 发布协议的副本。如果 }
- { 还没有,可访问我们的网站: }
- { }
- { 网站地址:http://www.cnpack.org }
- { 电子邮件:master@cnpack.org }
- { }
- {******************************************************************************}
- unit CnMDIBackGround;
- {* |<PRE>
- ================================================================================
- * 软件名称:不可视工具组件包
- * 单元名称:MDI 主窗体画背景单元
- * 单元作者:Shenloqi
- * 备 注:
- * 开发平台:PWin2000Pro + Delphi 5.01
- * 兼容测试:PWin9X/2000/XP + Delphi 5/6/7 + C++Builder 5/6
- * 本 地 化:该单元中的字符串支持本地化处理方式
- * 单元标识:$Id$
- * 修改记录:2004.06.08
- * 创建单元
- ================================================================================
- |</PRE>}
- interface
- {$I CnPack.inc}
- uses
- SysUtils, Windows, Messages, Classes, Controls, Forms, StdCtrls, ExtCtrls,
- Graphics, CnConsts, CnClasses, CnCompConsts;
- type
- TCnBMPDisplayStyle = (dsNormal, dsTiled, dsStretched, dsCentered, dsNone);
- TPaintImageEvent = procedure(Sender: TObject; ACanvas: TCanvas) of object;
- TCnMDIBackGround = class(TCnComponent)
- private
- { Private declarations }
- OldWndProc: TFarProc;
- NewWndProc: Pointer;
- OldMDIWndProc: TFarProc;
- NewMDIWndProc: Pointer;
- FBitmap: TBitmap;
- FDisplayStyle: TCnBMPDisplayStyle;
- FColor: TColor;
- FBuffer: TBitmap;
- FBorderLeft: Integer;
- FBorderRight: Integer;
- FBorderBottom: Integer;
- FBorderTop: Integer;
- FOnPaintImage: TPaintImageEvent;
- procedure SetBitmap(const Value: TBitmap);
- procedure SetDStyle(const Value: TCnBMPDisplayStyle);
- procedure SetMDIColor(const Value: TColor);
- protected
- { Protected declarations }
- procedure HookWndProc(var AMsg: TMessage);
- procedure HookWnd;
- procedure UnHookWnd;
- procedure HookMDIWndProc(var AMsg: TMessage);
- procedure HookMDIWin;
- procedure UnhookMDIWin;
- procedure PaintImage(const Msg, wParam, lParam: DWORD);
- procedure DoPaintImage(ACanvas: TCanvas);
- procedure GetComponentInfo(var AName, Author, Email, Comment: string); override;
- public
- { Public declarations }
- constructor Create(AOwner: TComponent); override;
- destructor Destroy; override;
- procedure DrawImage(ACanvas: TCanvas; AImage: TImage);
- procedure DrawLabel(ACanvas: TCanvas; ALabel: TLabel);
- published
- { Published declarations }
- property Bitmap: TBitmap read FBitmap write SetBitmap;
- property BorderBottom: Integer read FBorderBottom write FBorderBottom;
- property BorderLeft: Integer read FBorderLeft write FBorderLeft;
- property BorderRight: Integer read FBorderRight write FBorderRight;
- property BorderTop: Integer read FBorderTop write FBorderTop;
- property Color: TColor read FColor write SetMDIColor default clappWorkspace;
- property DisplayStyle: TCnBMPDisplayStyle read FDisplayStyle write SetDStyle default dsNone;
- property OnPaintImage: TPaintImageEvent read FOnPaintImage write FOnPaintImage;
- end;
- TCnWinControlHookList = class(TObject)
- private
- FWinControl: TWinControl;
- FHooks: TList;
- public
- constructor Create(aWinControl: TWinControl);
- destructor Destroy; override;
- property WinControl: TWinControl read FWinControl;
- procedure AddHook(oldHook: TFarProc);
- function GetNextHook: TFarProc;
- function Count: integer;
- end;
- procedure PushOldProc(aWinControl: TWinControl; OldHook: TFarProc);
- function PopOldProc(aWinControl: TWinControl): TFarProc;
- implementation
- uses
- Math;
- var
- FormList: TList;
- procedure PushOldProc(aWinControl: TWinControl; OldHook: TFarProc);
- var
- iloop: Integer;
- wHook: TCnWinControlHookList;
- bfound: Boolean;
- begin
- bfound := False;
- wHook := nil;
- for iloop := 0 to FormList.Count - 1 do
- begin
- wHook := TCnWinControlHookList(FormList[iloop]);
- bfound := wHook.WinControl = aWinControl;
- if bfound then
- Break;
- end;
- if bfound then
- wHook.AddHook(OldHook)
- else
- begin
- if Assigned(aWinControl) then
- begin
- wHook := TCnWinControlHookList.Create(aWinControl);
- FormList.Add(wHook);
- wHook.AddHook(oldhook);
- end
- end
- end;
- function PopOldProc(aWinControl: TWinControl): TFarProc;
- var
- iloop: Integer;
- wHook: TCnWinControlHookList;
- bfound: Boolean;
- begin
- bfound := False;
- wHook := nil;
- for iloop := 0 to FormList.Count - 1 do
- begin
- wHook := TCnWinControlHookList(FormList[iloop]);
- bfound := wHook.WinControl = aWinControl;
- if bfound then
- Break;
- end;
- if bfound then
- begin
- Result := wHook.GetNextHook;
- if wHook.Count = 0 then
- begin
- FormList.Delete(iloop);
- wHook.Free;
- end
- end
- else
- Result := nil;
- end;
- function _Width(const Rect: TRect): Integer;
- begin
- Result := Rect.Right - Rect.Left;
- end;
- function _Height(const Rect: TRect): Integer;
- begin
- Result := Rect.Bottom - Rect.Top;
- end;
- { TCnMDIBackGround }
- constructor TCnMDIBackGround.Create(AOwner: TComponent);
- begin
- inherited;
- if not ((AOwner is TForm) and (TForm(AOwner).FormStyle = fsMDIForm)) then
- raise Exception.Create('TCnMDIBackGround''s Owner MUST be MDIForm.');
- NewWndProc := nil;
- OldWndProc := nil;
- OldMDIWndProc := nil;
- NewMDIWndProc := nil;
- FBitmap := TBitmap.Create;
- FBuffer := TBitmap.Create;
- FColor := clAppWorkSpace;
- FDisplayStyle := dsNone;
- HookWnd;
- end;
- destructor TCnMDIBackGround.Destroy;
- begin
- UnHookWnd;
- FBitmap.Free;
- FBuffer.Free;
- inherited;
- end;
- procedure TCnMDIBackGround.DoPaintImage(ACanvas: TCanvas);
- begin
- if Assigned(FOnPaintImage) then
- FOnPaintImage(Self, ACanvas)
- end;
- procedure TCnMDIBackGround.DrawImage(ACanvas: TCanvas; AImage: TImage);
- var
- DescRect, Rect: TRect;
- Buffer: TBitmap;
- cx, cy: Integer;
- begin
- if not Assigned(AImage) then
- Exit;
- if AImage.Picture.Graphic.Empty then
- Exit;
- CopyRect(Rect, AImage.ClientRect);
- OffsetRect(Rect, AImage.Left, AImage.Top);
- //忽略 Proportional 和 IncrementalDisplay
- if AImage.AutoSize then
- begin
- ACanvas.Draw(Rect.Left, Rect.Top, AImage.Picture.Graphic);
- Exit
- end
- else if AImage.Stretch then
- begin
- ACanvas.StretchDraw(Rect, AImage.Picture.Graphic);
- Exit
- end;
- Buffer := TBitmap.Create;
- try
- Buffer.Height := AImage.Picture.Height;
- Buffer.Width := AImage.Picture.Width;
- Buffer.Canvas.Draw(0, 0, AImage.Picture.Graphic);
- if AImage.Center then
- begin
- cx := (AImage.Width - Buffer.Width) div 2;
- cy := (AImage.Height - Buffer.Height) div 2;
- Rect := Classes.Rect(Rect.Left + Max(cx, 0),
- Rect.Top + Max(cy, 0),
- Rect.Right - Max(cx, 0),
- Rect.Bottom - Max(cy, 0));
- DescRect := Rect;
- OffsetRect(DescRect, Max(-cx, 0) - DescRect.Left, Max(-cy, 0) - DescRect.Top)
- end
- else
- begin
- cx := Min(AImage.Width, Buffer.Width);
- cy := Min(AImage.Height, Buffer.Height);
- Rect := Classes.Rect(Rect.Left,
- Rect.Top,
- Rect.Left + cx,
- Rect.Top + cy);
- DescRect := Rect;
- OffsetRect(DescRect, - DescRect.Left, - DescRect.Top)
- end;
- ACanvas.CopyRect(Rect, Buffer.Canvas, DescRect)
- finally
- Buffer.Free;
- end
- end;
- procedure TCnMDIBackGround.DrawLabel(ACanvas: TCanvas; ALabel: TLabel);
- const
- Alignments: array[TAlignment] of Word = (DT_LEFT, DT_RIGHT, DT_CENTER);
- WordWraps: array[Boolean] of Word = (0, DT_WORDBREAK);
- var
- CalcRect, Rect: TRect;
- begin
- if not Assigned(ALabel) then
- Exit;
- CopyRect(Rect, ALabel.ClientRect);
- OffsetRect(Rect, ALabel.Left, ALabel.Top);
- with ACanvas do
- begin
- if not ALabel.Transparent then
- begin
- Brush.Color := ALabel.Color;
- Brush.Style := bsSolid;
- FillRect(Rect);
- end;
- Brush.Style := bsClear;
- Font := ALabel.Font;
- if ALabel.Layout <> tlTop then
- begin
- CalcRect := Rect;
- DrawText(Handle, PChar(ALabel.Caption), Length(ALabel.Caption), CalcRect,
- ALabel.DrawTextBiDiModeFlags(DT_EXPANDTABS or WordWraps[ALabel.WordWrap]
- or Alignments[ALabel.Alignment] or DT_NOPREFIX or DT_CALCRECT));
- if ALabel.Layout = tlBottom then
- OffsetRect(Rect, 0, _Height(Rect) - _Height(CalcRect))
- else
- OffsetRect(Rect, 0, (_Height(Rect) - _Height(CalcRect)) div 2);
- end;
- DrawText(Handle, PChar(ALabel.Caption), Length(ALabel.Caption), Rect,
- ALabel.DrawTextBiDiModeFlags(DT_EXPANDTABS or WordWraps[ALabel.WordWrap]
- or Alignments[ALabel.Alignment] or DT_NOPREFIX));
- end
- end;
- procedure TCnMDIBackGround.GetComponentInfo(var AName, Author, Email,
- Comment: string);
- begin
- AName := SCnMDIBackGroundName;
- Author := SCnPack_Shenloqi;
- Email := SCnPack_ShenloqiEmail;
- Comment := SCnMDIBackGroundComment;
- end;
- procedure TCnMDIBackGround.HookMDIWin;
- begin
- if csDesigning in ComponentState then
- Exit;
- if not Assigned(NewMDIWndProc) then
- begin
- OldMDIWndProc := TFarProc(GetWindowLong(TForm(Owner).ClientHandle, GWL_WNDPROC));
- NewMDIWndProc := MakeObjectInstance(HookMDIWndProc);
- SetWindowLong(TForm(Owner).ClientHandle, GWL_WNDPROC, LongInt(NewMDIWndProc));
- end
- end;
- procedure TCnMDIBackGround.HookMDIWndProc(var AMsg: TMessage);
- begin
- with AMsg do
- begin
- Result := CallWindowProc(OldMDIWndProc, TForm(Owner).ClientHandle, Msg, wParam, lParam);
- if Msg in [WM_PAINT{, WM_NCPAINT, WM_ERASEBKGND}] then
- PaintImage(Msg, wParam, lParam);
- end
- end;
- procedure TCnMDIBackGround.HookWnd;
- begin
- if csDesigning in ComponentState then
- Exit;
- if TForm(Owner).FormStyle <> fsMDIForm then
- Exit;
- if not Assigned(NewWndProc) then
- begin
- OldWndProc := TFarProc(GetWindowLong(TForm(Owner).Handle, GWL_WNDPROC));
- NewWndProc := MakeObjectInstance(HookWndProc);
- SetWindowLong(TForm(Owner).Handle, GWL_WNDPROC, LongInt(NewWndProc));
- PushOldProc(TForm(Owner), OldWndProc);
- HookMDIWin
- end
- end;
- procedure TCnMDIBackGround.HookWndProc(var AMsg: TMessage);
- begin
- case AMsg.Msg of
- WM_DESTROY:
- begin
- AMsg.Result := CallWindowProc(OldWndProc, TForm(Owner).Handle, AMsg.Msg, AMsg.wParam, AMsg.lParam);
- UnHookWnd;
- Exit
- end;
- end;
- AMsg.Result := CallWindowProc(OldWndProc, TForm(Owner).Handle, AMsg.Msg, AMsg.wParam, AMsg.lParam);
- case aMsg.Msg of
- //WM_ERASEBKGND,
- //WM_NCPAINT,
- WM_PAINT: PaintImage(AMsg.Msg, AMsg.wParam, AMsg.lParam)
- end;
- end;
- procedure TCnMDIBackGround.PaintImage(const Msg, wParam, lParam: DWORD);
- var
- ACanvas: TCanvas;
- DC: HDC;
- cx, cy: Integer;
- wRect, DescRect: TRect;
- x, y: Integer;
- procedure _ClearBuffer;
- begin
- FBuffer.Canvas.FillRect(Rect(0, 0, FBuffer.Width, FBuffer.Height))
- end;
- procedure _BufferToDC;
- begin
- BitBlt(DC,
- 0,
- 0,
- _Width(wRect),
- _Height(wRect),
- FBuffer.Canvas.Handle,
- 0,
- 0,
- SRCCOPY);
- end;
- begin
- if csDesigning in ComponentState then
- Exit;
- if TForm(Owner).FormStyle <> fsMDIForm then
- Exit;
- GetWindowRect(TForm(Owner).ClientHandle, wRect);
- FBuffer.Height := _Height(wRect);
- FBuffer.Width := _Width(wRect);
- if FBitmap.Empty then
- begin
- DC := GetDC(TForm(Owner).ClientHandle);
- try
- ACanvas := FBuffer.Canvas;
- ACanvas.Brush.Color := FColor;
- _ClearBuffer;
- DoPaintImage(ACanvas);
- _BufferToDC;
- Exit
- finally
- ReleaseDC(TForm(Owner).ClientHandle, DC)
- end
- end;
- if (FBitmap.Width = 0) or (FBitmap.Height = 0) then
- Exit;
- DescRect.Left := FBorderLeft;
- DescRect.Top := FBorderTop;
- DescRect.Right := _Width(wRect) - FBorderRight;
- DescRect.Bottom := _Height(wRect) - FBorderBottom;
- DC := GetDC(TForm(Owner).ClientHandle);
- try
- ACanvas := FBuffer.Canvas;
- ACanvas.Brush.Color := FColor;
- case FDisplayStyle of
- dsNormal, dsTiled, dsStretched, dsCentered:
- begin
- case FDisplayStyle of
- dsNormal:
- begin
- _ClearBuffer;
- BitBlt(FBuffer.Canvas.Handle,
- DescRect.Left,
- DescRect.Top,
- Min(FBitmap.Width, _Width(DescRect)),
- Min(FBitmap.Height, _Height(DescRect)),
- FBitmap.Canvas.Handle,
- 0,
- 0,
- SRCCOPY);
- DoPaintImage(ACanvas);
- end;
- dsTiled:
- begin
- _ClearBuffer;
- cx := DescRect.Right;
- cy := DescRect.Bottom;
- y := DescRect.Top;
- while y < cy do
- begin
- x := DescRect.Left;
- while x < cx do
- begin
- BitBlt(FBuffer.Canvas.Handle,
- x,
- y,
- Min(DescRect.Right - x, FBitmap.Width),
- Min(DescRect.Bottom - y, FBitmap.Height),
- FBitmap.Canvas.Handle,
- 0,
- 0,
- SRCCOPY);
- Inc(x, FBitmap.Width)
- end;
- Inc(y, FBitmap.Height)
- end;
- DoPaintImage(ACanvas);
- end;
- dsStretched:
- begin
- _ClearBuffer;
- cx := (wRect.Right - wRect.Left - FBorderLeft - FBorderRight);
- cy := (wRect.Bottom - wRect.Top - FBorderTop - FBorderBottom);
- FBuffer.Canvas.StretchDraw(Rect(DescRect.Left,DescRect.Top,cx,cy), FBitmap); ///Edit By LXY
- DoPaintImage(ACanvas);
- end;
- dsCentered:
- begin
- _ClearBuffer;
- cx := (_Width(DescRect) - FBitmap.Width) div 2;
- cy := (_Height(DescRect) - FBitmap.Height) div 2;
- BitBlt(FBuffer.Canvas.Handle,
- Max(DescRect.Left, cx),
- Max(DescRect.Top, cy),
- Min(FBitmap.Width, _Width(DescRect)),
- Min(FBitmap.Height, _Height(DescRect)),
- FBitmap.Canvas.Handle,
- Max(0, -cx),
- Max(0, -cy),
- SRCCOPY);
- DoPaintImage(ACanvas);
- end
- end
- end;
- dsNone:
- begin
- _ClearBuffer;
- DoPaintImage(ACanvas);
- end;
- end; // end case
- _BufferToDC;
- finally
- ReleaseDC(TForm(Owner).ClientHandle, DC)
- end
- end;
- procedure TCnMDIBackGround.SetBitmap(const Value: TBitmap);
- begin
- FBitmap.Assign(Value);
- end;
- procedure TCnMDIBackGround.SetDStyle(const Value: TCnBMPDisplayStyle);
- begin
- if FDisplayStyle <> Value then
- begin
- FDisplayStyle := Value;
- TForm(Owner).Invalidate;
- end
- end;
- procedure TCnMDIBackGround.SetMDIColor(const Value: TColor);
- begin
- if FColor <> Value then
- begin
- FColor := Value;
- TForm(Owner).Invalidate;
- end
- end;
- procedure TCnMDIBackGround.UnhookMDIWin;
- begin
- if csDesigning in ComponentState then
- Exit;
- if Assigned(NewMDIWndProc) then
- begin
- SetWindowLong(TForm(Owner).ClientHandle, GWL_WNDPROC, LongInt(OldMDIWndProc));
- if Assigned(NewMDIWndProc) then
- FreeObjectInstance(NewMDIWndProc);
- NewMDIWndProc := nil;
- OldMDIWndProc := nil;
- end
- end;
- procedure TCnMDIBackGround.UnHookWnd;
- begin
- if csDesigning in ComponentState then
- Exit;
- if Assigned(NewWndProc) then
- begin
- SetWindowLong(TForm(Owner).Handle, GWL_WNDPROC, LongInt(PopOldProc(TForm(Owner))));
- if Assigned(NewWndProc) then
- FreeObjectInstance(NewWndProc);
- NewWndProc := nil;
- OldWndProc := nil;
- end;
- UnHookMDIWin;
- end;
- { TCnWinControlHookList }
- procedure TCnWinControlHookList.AddHook(oldHook: TFarProc);
- begin
- FHooks.add(oldHook)
- end;
- function TCnWinControlHookList.Count: integer;
- begin
- Result := FHooks.Count
- end;
- constructor TCnWinControlHookList.Create(aWinControl: TWinControl);
- begin
- FWinControl := aWinControl;
- FHooks := TList.Create
- end;
- destructor TCnWinControlHookList.Destroy;
- begin
- FHooks.Free;
- inherited;
- end;
- function TCnWinControlHookList.GetNextHook: TFarProc;
- begin
- Result := FHooks[FHooks.Count - 1];
- FHooks.Delete(FHooks.Count - 1);
- end;
- initialization
- FormList := TList.Create;
- finalization
- FormList.Free;
- end.
|