• TEdit,TMemo背景透明(SetWindowLong(WS_EX_TRANSPARENT)增加透明风格)


    The component below works perfectly, except for the following problem:

    1) Saves the component below in a file "trancomp.pas".
    Then, install this component in Delphi;
    2) Later, open Delphi and create a new project;
    3) Adds a TImage and a TTransMemo to the form;
    4) Opens any image in the "PICTURE" property of TIMAGE. Adjust the size of TIMAGE so that TTransMEMO stays on TIMAGE;
    5) Changes the "TRANSPARENT" property of TTransMemo for "TRUE". Also change the "SCROLLBARS" property for "Vertical".
    6) Now, executes the project and try to slide the scroll bar (Up/Down). See that the background image "shakes" when the text is rolled upward or down.

    Please, could anybody repair this problem in the component so that it works correctly?

    ------------------START OF COMPONENT----------------------

    unit TranComp;
    
    interface
    
    uses
    Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
    StdCtrls, ComCtrls;
    
    type
    TCtrl = class(TWinControl);
    
    TTransEdit = class(TEdit)
    private
    FAlignText: TAlignment;
    FTransparent: Boolean;
    FPainting: Boolean;
    procedure SetAlignText(Value: TAlignment);
    procedure SetTransparent(Value: Boolean);
    procedure WMPaint(var Message: TWMPaint); message WM_PAINT;
    procedure WMNCPaint (var Message: TMessage); message WM_NCPAINT;
    procedure WMEraseBkGnd(var Message: TWMEraseBkGnd); message WM_ERASEBKGND;
    procedure CNCtlColorEdit(var Message: TWMCtlColorEdit); message CN_CTLCOLOREDIT;
    procedure CNCtlColorStatic(var Message: TWMCtlColorStatic); message CN_CTLCOLORSTATIC;
    procedure CMParentColorChanged(var Message: TMessage); message CM_PARENTCOLORCHANGED;
    procedure WMSize(var Message: TWMSize); message WM_SIZE;
    procedure WMMove(var Message: TWMMove); message WM_MOVE;
    protected
    procedure RepaintWindow;
    procedure CreateParams(var Params: TCreateParams); override;
    procedure Change; override;
    procedure SetParent(AParent: TWinControl); override;
    public
    constructor Create(AOwner: TComponent); override;
    destructor Destroy; override;
    published
    property AlignText: TAlignment read FAlignText write SetAlignText default taLeftJustify;
    property Transparent: Boolean read FTransparent write SetTransparent default false;
    end;
    
    // Transparent Memo
    TTransMemo = class(TMemo)
    private
    FAlignText: TAlignment;
    FTransparent: Boolean;
    FPainting: Boolean;
    procedure SetAlignText(Value: TAlignment);
    procedure SetTransparent(Value: Boolean);
    procedure WMPaint(var Message: TWMPaint); message WM_PAINT;
    procedure WMNCPaint (var Message: TMessage); message WM_NCPAINT;
    procedure WMEraseBkGnd(var Message: TWMEraseBkGnd); message WM_ERASEBKGND;
    procedure CNCtlColorEdit(var Message: TWMCtlColorEdit); message CN_CTLCOLOREDIT;
    procedure CNCtlColorStatic(var Message: TWMCtlColorStatic); message CN_CTLCOLORSTATIC;
    procedure CMParentColorChanged(var Message: TMessage); message CM_PARENTCOLORCHANGED;
    procedure WMSize(var Message: TWMSize); message WM_SIZE;
    procedure WMMove(var Message: TWMMove); message WM_MOVE;
    protected
    procedure RepaintWindow;
    procedure CreateParams(var Params: TCreateParams); override;
    procedure Change; override;
    procedure SetParent(AParent: TWinControl); override;
    public
    constructor Create(AOwner: TComponent); override;
    destructor Destroy; override;
    published
    property AlignText: TAlignment read FAlignText write SetAlignText default taLeftJustify;
    property Transparent: Boolean read FTransparent write SetTransparent default false;
    end;
    
    procedure Register;
    
    implementation
    
    const
    BorderRec: array[TBorderStyle] of Integer = (1, -1);
    
    procedure Register;
    begin
    RegisterComponents('Transparent Components', [TTransEdit, TTransMemo]);
    end;
    
    function GetScreenClient(Control: TControl): TPoint;
    var
    p: TPoint;
    begin
    p := Control.ClientOrigin;
    ScreenToClient(Control.Parent.Handle, p);
    Result := p;
    end;
    
    constructor TTransEdit.Create(AOwner: TComponent);
    begin
    inherited Create(AOwner);
    FAlignText := taLeftJustify;
    FTransparent := false;
    FPainting := false; 
    end;
    
    destructor TTransEdit.Destroy;
    begin
    inherited Destroy;
    end;
    
    procedure TTransEdit.SetAlignText(Value: TAlignment);
    begin
    if FAlignText <> Value then
    begin
    FAlignText := Value;
    RecreateWnd;
    Invalidate;
    end;
    end;
    
    procedure TTransEdit.SetTransparent(Value: Boolean);
    begin
    if FTransparent <> Value then
    begin
    FTransparent := Value;
    Invalidate;
    end;
    end;
    
    procedure TTransEdit.WMEraseBkGnd(var Message: TWMEraseBkGnd);
    var
    DC: hDC;
    i: integer;
    p: TPoint;
    begin
    if FTransparent then
    begin
    if Assigned(Parent) then
    begin
    DC := Message.DC;
    i := SaveDC(DC);
    p := GetScreenClient(self);
    p.x := -p.x;
    p.y := -p.y;
    MoveWindowOrg(DC, p.x, p.y);
    SendMessage(Parent.Handle, $0014, DC, 0);
    TCtrl(Parent).PaintControls(DC, nil);
    RestoreDC(DC, i);
    end;
    end else inherited;
    end;
    
    procedure TTransEdit.WMPaint(var Message: TWMPaint);
    begin
    inherited;
    if FTransparent then
    if not FPainting then
    RepaintWindow;
    end;
    
    procedure TTransEdit.WMNCPaint(var Message: TMessage);
    begin
    inherited;
    end;
    
    procedure TTransEdit.CNCtlColorEdit(var Message: TWMCtlColorEdit);
    begin
    inherited;
    if FTransparent then
    SetBkMode(Message.ChildDC, 1);
    end;
    
    procedure TTransEdit.CNCtlColorStatic(var Message: TWMCtlColorStatic);
    begin
    inherited;
    if FTransparent then
    SetBkMode(Message.ChildDC, 1);
    end;
    
    procedure TTransEdit.CMParentColorChanged(var Message: TMessage);
    begin
    inherited;
    if FTransparent then
    Invalidate;
    end;
    
    procedure TTransEdit.WMSize(var Message: TWMSize);
    begin
    inherited;
    Invalidate; 
    end;
    
    procedure TTransEdit.WMMove(var Message: TWMMove);
    begin
    inherited;
    Invalidate;
    end;
    
    procedure TTransEdit.RepaintWindow;
    var
    DC: hDC;
    TmpBitmap, Bitmap: hBitmap;
    begin
    if FTransparent then
    begin
    FPainting := true;
    HideCaret(Handle);
    DC := CreateCompatibleDC(GetDC(Handle));
    TmpBitmap := CreateCompatibleBitmap(GetDC(Handle), Succ(ClientWidth), Succ(ClientHeight));
    Bitmap := SelectObject(DC, TmpBitmap);
    PaintTo(DC, 0, 0);
    BitBlt(GetDC(Handle), BorderRec[BorderStyle], BorderRec[BorderStyle], ClientWidth, ClientHeight, DC, 1, 1, SRCCOPY);
    SelectObject(DC, Bitmap);
    DeleteDC(DC);
    ReleaseDC(Handle, GetDC(Handle));
    DeleteObject(TmpBitmap);
    ShowCaret(Handle);
    FPainting := false;
    end;
    end;
    
    procedure TTransEdit.CreateParams(var Params: TCreateParams);
    const
    Alignments: array [TAlignment] of DWord = (ES_LEFT, ES_RIGHT, ES_CENTER);
    begin
    inherited CreateParams(Params);
    Params.Style := Params.Style or ES_MULTILINE or Alignments[FAlignText];
    end;
    
    procedure TTransEdit.Change;
    begin
    RepaintWindow;
    inherited Change;
    end;
    
    procedure TTransEdit.SetParent(AParent: TWinControl);
    begin
    inherited SetParent(AParent);
    end;
    
    // Transparent Memo
    constructor TTransMemo.Create(AOwner: TComponent);
    begin
    inherited Create(AOwner);
    FAlignText := taLeftJustify;
    FTransparent := false;
    FPainting := false;
    end;
    
    destructor TTransMemo.Destroy;
    begin
    inherited Destroy;
    end;
    
    procedure TTransMemo.SetAlignText(Value: TAlignment);
    begin
    if FAlignText <> Value then
    begin
    FAlignText := Value;
    RecreateWnd;
    Invalidate;
    end;
    end;
    
    procedure TTransMemo.SetTransparent(Value: Boolean);
    begin
    if FTransparent <> Value then
    begin
    FTransparent := Value;
    Invalidate;
    end;
    end;
    
    procedure TTransMemo.WMEraseBkGnd(var Message: TWMEraseBkGnd);
    var
    DC: hDC;
    i: integer;
    p: TPoint;
    begin
    if FTransparent then
    begin
    if Assigned(Parent) then
    begin
    DC := Message.DC;
    i := SaveDC(DC);
    p := GetScreenClient(self);
    p.x := -p.x;
    p.y := -p.y;
    MoveWindowOrg(DC, p.x, p.y);
    SendMessage(Parent.Handle, $0014, DC, 0);
    TCtrl(Parent).PaintControls(DC, nil);
    RestoreDC(DC, i);
    end;
    end else inherited;
    end;
    
    procedure TTransMemo.WMPaint(var Message: TWMPaint);
    begin
    inherited;
    if FTransparent then
    if not FPainting then
    RepaintWindow;
    end;
    
    procedure TTransMemo.WMNCPaint(var Message: TMessage);
    begin
    inherited;
    end;
    
    procedure TTransMemo.CNCtlColorEdit(var Message: TWMCtlColorEdit);
    begin
    inherited;
    if FTransparent then
    SetBkMode(Message.ChildDC, 1);
    end;
    
    procedure TTransMemo.CNCtlColorStatic(var Message: TWMCtlColorStatic);
    begin
    inherited;
    if FTransparent then
    SetBkMode(Message.ChildDC, 1);
    end;
    
    procedure TTransMemo.CMParentColorChanged(var Message: TMessage);
    begin
    inherited;
    if FTransparent then
    Invalidate;
    end;
    
    procedure TTransMemo.WMSize(var Message: TWMSize);
    begin
    inherited;
    Invalidate;
    end;
    
    procedure TTransMemo.WMMove(var Message: TWMMove);
    begin
    inherited;
    Invalidate;
    end;
    
    procedure TTransMemo.RepaintWindow;
    var
    DC: hDC;
    TmpBitmap, Bitmap: hBitmap;
    begin
    if FTransparent then
    begin
    FPainting := true;
    HideCaret(Handle);
    DC := CreateCompatibleDC(GetDC(Handle));
    TmpBitmap := CreateCompatibleBitmap(GetDC(Handle), Succ(ClientWidth), Succ(ClientHeight));
    Bitmap := SelectObject(DC, TmpBitmap);
    PaintTo(DC, 0, 0);
    BitBlt(GetDC(Handle), BorderRec[BorderStyle], BorderRec[BorderStyle], ClientWidth, ClientHeight, DC, 1, 1, SRCCOPY);
    SelectObject(DC, Bitmap);
    DeleteDC(DC);
    ReleaseDC(Handle, GetDC(Handle));
    DeleteObject(TmpBitmap);
    ShowCaret(Handle);
    FPainting := false;
    end;
    end;
    
    procedure TTransMemo.CreateParams(var Params: TCreateParams);
    const
    Alignments: array [TAlignment] of DWord = (ES_LEFT, ES_RIGHT, ES_CENTER);
    begin
    inherited CreateParams(Params);
    Params.Style := Params.Style or ES_MULTILINE or Alignments[FAlignText];
    end;
    
    procedure TTransMemo.Change;
    begin
    RepaintWindow;
    inherited Change;
    end;
    
    procedure TTransMemo.SetParent(AParent: TWinControl);
    begin
    inherited SetParent(AParent);
    end;
    
    end.

    下面的代码如果memo已有内容,回到已有内容中间处修改,旧的文本笔画会和新的文本笔画混合。文本笔画背景未完全檫除。效果不好

    type
    TForm1 =class(TForm)
    private
      { Private declarations }
      FBitmap: TBitmap;
      FBrush: HBRUSH;
      Edit1: TEdit;
      Memo1: TMemo;
      Image2:TImage;//背景图片
    protected
      procedure WndProc(var Message: TMessage); override;  
     
    end;
    procedure TForm1.FormCreate(Sender: TObject);
    begin
      FBitmap := TBitmap.Create;
      FBitmap.SetSize(Memo1.Width,Memo1.Height);
      FBitMap.Canvas.CopyRect(
      types.Rect(0,0,FBitmap.Width,FBitmap.Height),
      Image2.Canvas,
      types.Rect(memo1.Left,memo1.Top,memo1.Left+Memo1.Width,memo1.Top+Memo1.Height));
      FBrush := CreateSolidBrush(FBitmap.Handle);
     
    SetWindowLong(Edit1.Handle,GWL_EXSTYLE,GetWindowLong(Edit1.Handle,GWL_EXSTYLE) or WS_EX_TRANSPARENT); // 增加透明风格
    SetWindowLong(Memo1.Handle,GWL_EXSTYLE,GetWindowLong(Memo1.Handle,GWL_EXSTYLE) or WS_EX_TRANSPARENT);
    end;
    
    procedure TForm1.FormPaint(Sender: TObject);
    begin
    Canvas.Brush.Handle:=FBrush;
    Canvas.Rectangle(0,0,width,height);
    end;
    procedure TForm1.WndProc(var Message: TMessage);
    begin
    inherited;
    case Message.Msg of
    WM_CTLCOLOREDIT, WM_CTLCOLORSTATIC:
    SetBkMode(Message.WParam, TRANSPARENT);
    Message.Result := FBrush;//GetStockObject(NULL_BRUSH);
    end;
    end;
  • 相关阅读:
    CentOS 8搭建Kubernetes-k8s集群-1.18.5
    Docker、CICD持续集成部署、Gitlab使用、Jenkins介绍
    落地微服务架构v2.0
    分布式大规模服务调用架构
    .NetCore3.1+微服务架构技术栈
    ASP.NET MVC4 学习笔记-4
    ASP.NET MVC4 学习笔记-3
    SQL Server中获取不同格式的日期
    ASP.NET MVC4 学习笔记-2
    windows ce 5.0 + vs2005 + sql数据库_开发注意事项
  • 原文地址:https://www.cnblogs.com/findumars/p/4740163.html
Copyright © 2020-2023  润新知