WM_ERASEBKGND 공식 설명 및 Delphi의 모든 사용 상황(창 컨트롤의 배경색을 그리고 메시지 전달을 막는 것)
Parameters
wParam
A handle to the device context.//장치 컨텍스트 핸들
lParam
This parameter is not used.
Return value
Type: LRESULT
An application should return nonzero if it erases the background; otherwise, it should return zero.
배경을 지우면 함수가 0이 아닌 값을 되돌려줍니다.그렇지 않으면 함수가 0을 반환합니다.
Remarks
The DefWindowProc function erases the background by using the class background brush specified by the hbrBackgroundmember of the WNDCLASS structure. If hbrBackground is NULL, the application should process the WM_ERASEBKGNDmessage and erase the background.
DefWindowProc 함수는 WNDCLASS 구조에서 지정한 hbrBackground 배경 붓을 사용하여 배경을 지웁니다.만약 hbrBackground가 비어 있다면 프로그램은 WM 을 처리해야 합니다ERASEBKGND 메시지 배경을 지웁니다.
An application should return nonzero in response to WM_ERASEBKGND if it processes the message and erases the background; this indicates that no further erasing is required. If the application returns zero, the window will remain marked for erasing. (Typically, this indicates that the fErase member of the PAINTSTRUCT structure will be TRUE.)
응용 프로그램 응답 처리 WMERASEBKGND 메시지 및 배경을 지우고 0이 아닌 값을 반환해야 합니다.Windows에서 더 이상 지울 필요가 없음을 알려줍니다.애플리케이션이 0을 반환해도 Windows는 삭제로 표시됩니다.(일반적으로 이것은 PAINTSTRUCT 구조의 fErase가 진짜임을 나타낸다.)
번역:http://baike.baidu.com/view/9801207.htm
------------------------------------------------------------------------------------------------------
이 메시지는 Delphi에서 재정의됩니다.
TWMEraseBkgnd = packed record
Msg: Cardinal;
DC: HDC;
Unused: Longint;
Result: Longint;
end;
Controls에 있습니다.pas 단원의 관련 코드(1곳 정의, 2곳 사용):
procedure TWinControl.WMEraseBkgnd(var Message: TWMEraseBkgnd);
begin
with ThemeServices do
if ThemesEnabled and Assigned(Parent) and (csParentBackground in FControlStyle) then
begin
{ Get the parent to draw its background into the control's background. }
DrawParentBackground(Handle, Message.DC, nil, False);
end
else
begin
{ Only erase background if we're not doublebuffering or painting to memory. }
if not FDoubleBuffered or
(TMessage(Message).wParam = TMessage(Message).lParam) then
FillRect(Message.DC, ClientRect, FBrush.Handle);
end;
Message.Result := 1; // ,WM_ERASEBKGND , end;
procedure TWinControl.WMPaint(var Message: TWMPaint);
var
DC, MemDC: HDC;
MemBitmap, OldBitmap: HBITMAP;
PS: TPaintStruct;
begin
if not FDoubleBuffered or (Message.DC <> 0) then
begin
if not (csCustomPaint in ControlState) and (ControlCount = 0) then
inherited
else
PaintHandler(Message);
end
else
begin
DC := GetDC(0); // DC,
MemBitmap := CreateCompatibleBitmap(DC, ClientRect.Right, ClientRect.Bottom); // ,
ReleaseDC(0, DC); //
MemDC := CreateCompatibleDC(0);
OldBitmap := SelectObject(MemDC, MemBitmap);
try
DC := BeginPaint(Handle, PS); // DC
Perform(WM_ERASEBKGND, MemDC, MemDC); // TWinControl.WMEraseBkgnd, , , ,
Message.DC := MemDC; // , MemDC , MemDC , DC
WMPaint(Message); // , DC<>0 , ( ),
Message.DC := 0; // , , DC
BitBlt(DC, 0, 0, ClientRect.Right, ClientRect.Bottom, MemDC, 0, 0, SRCCOPY); // MemDC DC
EndPaint(Handle, PS);
finally
SelectObject(MemDC, OldBitmap); //
DeleteDC(MemDC); //
DeleteObject(MemBitmap); // end;
end;
end;
또한 컨트롤을 다른 DC 장치에 인쇄할 수도 있습니다.
// Draws the windowed control to a device context.
procedure TWinControl.PaintTo(DC: HDC; X, Y: Integer);
var
I, EdgeFlags, BorderFlags, SaveIndex: Integer;
R: TRect;
begin
Include(FControlState, csPaintCopy);
SaveIndex := SaveDC(DC);
MoveWindowOrg(DC, X, Y);
IntersectClipRect(DC, 0, 0, Width, Height);
BorderFlags := 0;
EdgeFlags := 0;
if GetWindowLong(Handle, GWL_EXSTYLE) and WS_EX_CLIENTEDGE <> 0 then
begin
EdgeFlags := EDGE_SUNKEN;
BorderFlags := BF_RECT or BF_ADJUST
end else
if GetWindowLong(Handle, GWL_STYLE) and WS_BORDER <> 0 then
begin
EdgeFlags := BDR_OUTER;
BorderFlags := BF_RECT or BF_ADJUST or BF_MONO;
end;
if BorderFlags <> 0 then
begin
SetRect(R, 0, 0, Width, Height);
DrawEdge(DC, R, EdgeFlags, BorderFlags);
MoveWindowOrg(DC, R.Left, R.Top);
IntersectClipRect(DC, 0, 0, R.Right - R.Left, R.Bottom - R.Top);
end;
Perform(WM_ERASEBKGND, DC, 0);
Perform(WM_PAINT, DC, 0);
if FWinControls <> nil then
for I := 0 to FWinControls.Count - 1 do
with TWinControl(FWinControls[I]) do
if Visible then PaintTo(DC, Left, Top);
RestoreDC(DC, SaveIndex);
Exclude(FControlState, csPaintCopy);
end;
------------------------------------------------------------------------------------------------------
Controls.pas에는 다음 정의가 있지만 Tspeed Button에서만 사용됩니다.
procedure PerformEraseBackground(Control: TControl; DC: HDC);
var
LastOrigin: TPoint;
begin
GetWindowOrgEx(DC, LastOrigin);
SetWindowOrgEx(DC, LastOrigin.X + Control.Left, LastOrigin.Y + Control.Top, nil);
Control.Parent.Perform(WM_ERASEBKGND, Integer(DC), Integer(DC)); // TSpeedButton Windows ,
SetWindowOrgEx(DC, LastOrigin.X, LastOrigin.Y, nil);
end;
procedure TSpeedButton.Paint;
const
DownStyles: array[Boolean] of Integer = (BDR_RAISEDINNER, BDR_SUNKENOUTER);
FillStyles: array[Boolean] of Integer = (BF_MIDDLE, 0);
var
PaintRect: TRect;
DrawFlags: Integer;
Offset: TPoint;
Button: TThemedButton;
ToolButton: TThemedToolBar;
Details: TThemedElementDetails;
begin
if not Enabled then
begin
FState := bsDisabled;
FDragging := False;
end
else if FState = bsDisabled then
if FDown and (GroupIndex <> 0) then
FState := bsExclusive
else
FState := bsUp;
Canvas.Font := Self.Font;
if ThemeServices.ThemesEnabled then
begin
PerformEraseBackground(Self, Canvas.Handle);
//
end;
end;
------------------------------------------------------------------------------------------------------
Forms.pas 단원의 정의 및 사용:
procedure TCustomForm.WMEraseBkgnd(var Message: TWMEraseBkgnd);
begin
if not IsIconic(Handle) then inherited else
begin
Message.Msg := WM_ICONERASEBKGND; // ,
DefaultHandler(Message); // MDI , , end;
end;
procedure TCustomForm.ClientWndProc(var Message: TMessage);
procedure Default;
begin
with Message do
Result := CallWindowProc(FDefClientProc, ClientHandle, Msg, wParam, lParam);
end;
function MaximizedChildren: Boolean;
var
I: Integer;
begin
for I := 0 to MDIChildCount - 1 do
if MDIChildren[I].WindowState = wsMaximized then
begin
Result := True;
Exit;
end;
Result := False;
end;
var
DC: HDC;
PS: TPaintStruct;
R: TRect;
begin
with Message do
case Msg of
WM_NCHITTEST:
begin
Default;
if Result = HTCLIENT then Result := HTTRANSPARENT;
end;
WM_ERASEBKGND: begin
FillRect(TWMEraseBkGnd(Message).DC, ClientRect, Brush.Handle);
{ Erase the background at the location of an MDI client window }
if (FormStyle = fsMDIForm) and (FClientHandle <> 0) then
begin
Windows.GetClientRect(FClientHandle, R);
FillRect(TWMEraseBkGnd(Message).DC, R, Brush.Handle);
end;
Result := 1;
end;
$3F://!
begin
Default;
if FFormStyle = fsMDIForm then
ShowMDIClientEdge(FClientHandle, (MDIChildCount = 0) or
not MaximizedChildren);
end;
WM_PAINT:
begin
DC := TWMPaint(Message).DC;
if DC = 0 then
TWMPaint(Message).DC := BeginPaint(ClientHandle, PS);
try
if DC = 0 then
begin
GetWindowRect(FClientHandle, R);
R.TopLeft := ScreenToClient(R.TopLeft);
MoveWindowOrg(TWMPaint(Message).DC, -R.Left, -R.Top);
end;
PaintHandler(TWMPaint(Message));
finally
if DC = 0 then
EndPaint(ClientHandle, PS);
end;
end;
else
Default;
end;
end;
TCustomForm에 대한 추가 설명WMeraseBkgnd에서 전달된 메시지:
procedure TCustomForm.DefaultHandler(var Message);
begin
if ClientHandle <> 0 then
with TMessage(Message) do
if Msg = WM_SIZE then
Result := DefWindowProc(Handle, Msg, wParam, lParam) else
Result := DefFrameProc(Handle, ClientHandle, Msg, wParam, lParam)
else
inherited DefaultHandler(Message)
end;
// message WM_ICONERASEBKGND
procedure TCustomForm.WMIconEraseBkgnd(var Message: TWMIconEraseBkgnd);
begin
if FormStyle = fsMDIChild then
if (FormStyle = fsMDIChild) and not (csDesigning in ComponentState) then
FillRect(Message.DC, ClientRect, Application.MainForm.Brush.Handle)
else inherited;
end;
이 메시지에 대한 TApplication 사용:
procedure TApplication.WndProc(var Message: TMessage);
var
procedure Default;
begin
with Message do
Result := DefWindowProc(FHandle, Msg, WParam, LParam);
end;
begin
try
Message.Result := 0;
for I := 0 to FWindowHooks.Count - 1 do
if TWindowHook(FWindowHooks[I]^)(Message) then Exit;
CheckIniChange(Message);
with Message do
case Msg of
WM_SYSCOMMAND:
case WParam and $FFF0 of
SC_MINIMIZE: Minimize;
SC_RESTORE: Restore;
else
Default;
end;
WM_CLOSE:
if MainForm <> nil then MainForm.Close;
WM_PAINT:
if IsIconic(FHandle) then DrawAppIcon else Default;
WM_ERASEBKGND: // , begin
Message.Msg := WM_ICONERASEBKGND;
Default;
end;
WM_NULL:
CheckSynchronize;
else
Default;
end;
except
HandleException(Self);
end;
end;
------------------------------------------------------------------------------------------------------
StdCtrls 다시 봐.pas 단원의 정의 및 사용:
procedure TCustomComboBox.WMEraseBkgnd(var Message: TWMEraseBkgnd);
begin
if Style = csSimple then
begin
FillRect(Message.DC, ClientRect, Parent.Brush.Handle);
Message.Result := 1;
end
else
DefaultHandler(Message);
end;
procedure TButtonControl.WMEraseBkGnd(var Message: TWMEraseBkGnd);
begin
{ Under theme services the background is drawn in CN_CTLCOLORSTATIC. }
if ThemeServices.ThemesEnabled then
Message.Result := 1
else
inherited;
end;
procedure TButton.WMEraseBkgnd(var Message: TWMEraseBkgnd);
begin
if ThemeServices.ThemesEnabled then
Message.Result := 1
else
DefaultHandler(Message);
end;
procedure TScrollBar.WMEraseBkgnd(var Message: TWMEraseBkgnd);
begin
DefaultHandler(Message);
end;
------------------------------------------------------------------------------------------------------
그리고 Ext Ctrls.pas 단원의:
procedure TCustomControlBar.WMEraseBkgnd(var Message: TWmEraseBkgnd);
var
R: TRect;
I, J: Integer;
Save: Boolean;
begin
if Message.DC <> 0 then
Canvas.Handle := Message.DC;
if Picture.Graphic <> nil then
begin
try
R := ClientRect;
Save := FDrawing;
FDrawing := True;
try
{ Tile image across client area }
for I := 0 to (R.Right - R.Left) div Picture.Width do
for J := 0 to (R.Bottom - R.Top) div Picture.Height do
Canvas.Draw(I * Picture.Width, J * Picture.Height, Picture.Graphic);
finally
FDrawing := Save;
end
finally
if Message.DC <> 0 then
Canvas.Handle := 0;
Message.Result := 1;
end;
end
else
begin
Canvas.Brush.Color := Color;
Canvas.Brush.Style := bsSolid;
Canvas.FillRect(ClientRect);
inherited;
end;
end;
------------------------------------------------------------------------------------------------------
그리고dbcgrids.pas 및 DbCtrls.pas 단원의:
procedure TDBCtrlPanel.WMEraseBkgnd(var Message: TMessage);
begin
Message.Result := 1;
end;
procedure TDBCtrlGrid.WMEraseBkgnd(var Message: TMessage);
begin
Message.Result := 1;
end;procedure TDBMemo.WMPaint(var Message: TWMPaint);
var
S: string;
begin
if not (csPaintCopy in ControlState) then inherited else
begin
if FDataLink.Field <> nil then
if FDataLink.Field.IsBlob then
begin
if FAutoDisplay then
S := AdjustLineBreaks(FDataLink.Field.AsString) else
S := Format('(%s)', [FDataLink.Field.DisplayLabel]);
end else
S := FDataLink.Field.DisplayText;
SendMessage(FPaintControl.Handle, WM_SETTEXT, 0, Integer(PChar(S)));
SendMessage(FPaintControl.Handle, WM_ERASEBKGND, Message.DC, 0);
SendMessage(FPaintControl.Handle, WM_PAINT, Message.DC, 0);
end;
end;
------------------------------------------------------------------------------------------------------
그리고 섀도우 Wnd.pas 단원의:
procedure TShadowWindow.WMEraseBkgnd(var Message: TWMEraseBkgnd);
begin
Message.Result := 0;
end;
------------------------------------------------------------------------------------------------------
그리고Tabs.pas 단원의:
procedure TTabSet.Paint;
var
TabStart, LastTabPos: Integer;
TabPos: TTabPos;
Tab: Integer;
Leading: TEdgeType;
Trailing: TEdgeType;
isFirst, isLast, isSelected, isPrevSelected: Boolean;
R: TRect;
begin
if not HandleAllocated then Exit;
MemBitmap.Canvas.Font := Self.Canvas.Font;
{ draw background of tab area }
with MemBitmap.Canvas do
begin
Brush.Bitmap := BrushBitmap;
if ThemeServices.ThemesEnabled and ParentBackground then
Perform(WM_ERASEBKGND, MemBitmap.Canvas.Handle, 0)
else
FillRect(Rect(0, 0, MemBitmap.Width, MemBitmap.Height));
end;
end;
------------------------------------------------------------------------------------------------------
그리고 OleCtrls.pas 단원의:
procedure TOleControl.WMEraseBkgnd(var Message: TWMEraseBkgnd);
begin
if FMiscStatus and OLEMISC_INVISIBLEATRUNTIME = 0 then
DefaultHandler(Message) else
inherited;
end;
------------------------------------------------------------------------------------------------------
그리고ComCtrls.pas 단원의 5곳 정의와 2곳 사용:
procedure TPageControl.WMEraseBkGnd(var Message: TWMEraseBkGnd);
begin
if (not ThemeServices.ThemesEnabled) or (not ParentBackground) then
inherited
else
Message.Result := 1;
end;
procedure TCustomStatusBar.WMEraseBkGnd(var Message: TWMEraseBkGnd);
var
Details: TThemedElementDetails;
begin
if ThemeServices.ThemesEnabled then
begin
Details := ThemeServices.GetElementDetails(tsStatusRoot);
ThemeServices.DrawElement(Message.DC, Details, ClientRect, nil);
Message.Result := 1;
end
else
inherited;
end;
procedure TTrackBar.WMEraseBkGnd(var Message: TWMEraseBkGnd);
var
R: TRect;
begin
if ThemeServices.ThemesEnabled then
begin
R := ClientRect;
if Focused and ((Perform(WM_QUERYUISTATE, 0, 0) and UISF_HIDEFOCUS) = 0) then
InflateRect(R, -1, -1);
ThemeServices.DrawParentBackground(Handle, Message.DC, nil, False, @R);
Message.Result := 1;
end
else
inherited;
end;
procedure TToolBar.WMEraseBkgnd(var Message: TWMEraseBkgnd);
begin
if not Transparent then
inherited else
DefaultHandler(Message);
end;
procedure TCoolBar.WMEraseBkgnd(var Message: TWMEraseBkgnd);
begin
if not ThemeServices.ThemesEnabled and (IsBackgroundDirty or (IsAutoSized and (Bands.Count = 0))) then
inherited;
DefaultHandler(Message);
end;
procedure TCustomListView.WndProc(var Message: TMessage);
begin
if not (csDesigning in ComponentState) and ((Message.Msg = WM_LBUTTONDOWN) or
(Message.Msg = WM_LBUTTONDBLCLK)) and not Dragging and (DragMode = dmAutomatic) then
begin
if not IsControlMouseMsg(TWMMouse(Message)) then
begin
ControlState := ControlState + [csLButtonDown];
Dispatch(Message);
end;
end
else if not (((Message.Msg = WM_PAINT) or (Message.Msg = WM_ERASEBKGND)) and
Items.FNoRedraw) then
inherited WndProc(Message);
end;
procedure TCoolBar.PaintWindow(DC: HDC);
begin
Perform(WM_ERASEBKGND, DC, 0);
inherited;
end;
총괄: 사실 하는 일이 많지 않다. 자류는 WM 을 일으킨다.ARASEBKGND 메시지는 부모 클래스에 주거나 메시지 값을 바꾸거나 부모 컨트롤러가 하는 일도 적고 가장 중요한 것은 컨트롤러에 배경색을 주거나 더 이상 전달하지 못하게 하는 것이다.
실험:
1. 창 위에 WM을 덮어씌운다ERASEBKGND 메시지의 컨트롤(예: TButton)
2. 덮어쓰지 않는 WM 을 넣는다ERASEBKGND 메시지의 공간, 예를 들어 Tpanel, 도대체 무슨 일이 일어날지 보자.
비고: 사실 이런 소식은 디버깅하기 어려워서 로그에 모두 기록할 수 밖에 없어요.
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
다양한 언어의 JSONJSON은 Javascript 표기법을 사용하여 데이터 구조를 레이아웃하는 데이터 형식입니다. 그러나 Javascript가 코드에서 이러한 구조를 나타낼 수 있는 유일한 언어는 아닙니다. 저는 일반적으로 '객체'{}...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.