2

我希望对 Delphi 7 中的透明 TMemo 控件有所帮助。我在网上找到了一些运行良好的代码,在某种程度上,刷新率有点垃圾,但我可以忍受。主要问题是未选择的文本看起来好像它实际上已被选中。

这是使用 SelectAll() 选择所有文本的地方; 这是使用 SelectAll() 选择所有文本的地方;

这里实际上没有选择文本,但之前已经选择了,请注意浮线表示输入将发生在改进中的“p”之后。 这里实际上没有选择文本,但之前已经选择了,请注意浮线表示输入将发生在改进中的“p”之后。

最后是一张显示差异的图像。 最后是一张显示差异的图像。

我觉得很奇怪的是,例如,如果我按箭头键,错误的突出显示就会消失,但使用鼠标时却不会。

这个自定义 TMemo 的代码如下:

unit TrMemo;

interface

uses
 Messages, Controls, StdCtrls, classes;

const TMWM__SpecialInvalidate=WM_USER+1111;

type
  TTransparentMemo = class(TMemo)
  private
   procedure SpecialInvalidate(var Message:TMessage); message TMWM__SpecialInvalidate;
   procedure WMHScroll(var Message: TWMHScroll); message WM_HSCROLL;
   procedure WMVScroll(var Message: TWMVScroll); message WM_VSCROLL;
   procedure WMSetText(var Message:TWMSetText); message WM_SETTEXT;
   procedure CNCTLCOLOREDIT(var Message:TWMCTLCOLOREDIT); message CN_CTLCOLOREDIT;
   procedure WMKeyDown(var Message: TWMKeyDown); message WM_KEYDOWN;
   procedure WMEraseBkgnd(var Message: TWMEraseBkgnd); message WM_ERASEBKGND;
  protected
   procedure CreateParams(var Params: TCreateParams); override;
  public
   constructor Create(AOwner: TComponent); override;
  end;

procedure Register;

implementation

uses Windows;

{ TTransparentMemo }

procedure TTransparentMemo.WMHScroll(var Message: TWMHScroll);
begin
 inherited;
 PostMessage(Handle,TMWM__SpecialInvalidate,0,0);
end;

procedure TTransparentMemo.WMVScroll(var Message: TWMVScroll);
begin
 SendMessage(Handle,TMWM__SpecialInvalidate,0,0);
 inherited;
 PostMessage(Handle,TMWM__SpecialInvalidate,0,0);
end;

procedure TTransparentMemo.CNCTLCOLOREDIT(var Message:TWMCTLCOLOREDIT);
begin
 with Message do
 begin
  SetBkMode(ChildDC,TRANSPARENT);
  Result:=GetStockObject(HOLLOW_BRUSH)
 end
end;

procedure TTransparentMemo.WMSetText(var Message:TWMSetText);
begin
 inherited;
 if not (csDesigning in ComponentState) then PostMessage(Handle,TMWM__SpecialInvalidate,0,0)
end;

procedure TTransparentMemo.SpecialInvalidate(var Message:TMessage);
var
 r:TRect;
begin
 if (Parent <> nil) then
 begin
  r:=ClientRect;
  r.TopLeft:=Parent.ScreenToClient(ClientToScreen(r.TopLeft));
  r.BottomRight:=Parent.ScreenToClient(ClientToScreen(r.BottomRight));
  InvalidateRect(Parent.Handle,@r,true);
  RedrawWindow(Handle,nil,0,RDW_FRAME+RDW_INVALIDATE);
 end;
end;

procedure TTransparentMemo.WMKeyDown(var Message: TWMKeyDown);
begin
 SendMessage(Handle,TMWM__SpecialInvalidate,0,0);
 inherited;
 PostMessage(Handle,TMWM__SpecialInvalidate,0,0);
end;

procedure TTransparentMemo.WMEraseBkgnd(var Message: TWMEraseBkgnd);
begin
 Message.Result:=1
end;

constructor TTransparentMemo.Create(AOwner: TComponent);
begin
 inherited;
 ControlStyle:=[csCaptureMouse, csDesignInteractive, csClickEvents,  csSetCaption, csOpaque, csDoubleClicks, csReplicatable, csNoStdEvents];
end;

procedure TTransparentMemo.CreateParams(var Params: TCreateParams);
begin
 inherited CreateParams(Params);
 with Params do
 begin
  ExStyle:=ExStyle or WS_EX_TRANSPARENT and not WS_EX_WINDOWEDGE
   and not WS_EX_STATICEDGE and not WS_EX_DLGMODALFRAME and not
   WS_EX_CLIENTEDGE;
 end;
end;

procedure Register;
begin
 RegisterComponents('Samples', [tTransparentMemo]);
end;

end.

任何提示/提示/答案将不胜感激!提前干杯!

4

1 回答 1

1

这不是一个完整的修复,但你可以,例如,做类似的事情

protected
  procedure Click; override;

procedure TTransparentMemo.Click;
begin
  PostMessage(Handle,TMWM__SpecialInvalidate,0,0);
  inherited;
end;

等等。也许有更好的地方可以做到这一点。查看您的 VCL 源代码 (StdCtrls.pas),您可能会在其中找到一些内容,TCustomEdit或者TCustomMemo哪些是更好的覆盖选项。

于 2012-04-19T12:13:45.490 回答