现在的位置: 首页 > 综合 > 正文

娃娃鸭深入核心VCL架构剖析(李维)笔记

2013年09月09日 ⁄ 综合 ⁄ 共 5080字 ⁄ 字号 评论关闭

 

35TApplication创建的主窗体

Application.CreateForm(TForm1, Form1);

procedure TApplication.CreateForm(InstanceClass: TComponentClass; var Reference);

var

  Instance: TComponent;

begin

  Instance := TComponent(InstanceClass.NewInstance);

  TComponent(Reference) := Instance;

  try

    Instance.Create(Self);

  except

    TComponent(Reference) := nil;

    raise;

  end;

  if (FMainForm = nil) and (Instance is TForm) then

  begin

    TForm(Instance).HandleNeeded;

    FMainForm := TForm(Instance);

  end;

end;

 

constructor TWinControl.Create(AOwner: TComponent);

begin

  inherited Create(AOwner);

{$IFDEF LINUX}

  FObjectInstance := WinUtils.MakeObjectInstance(MainWndProc);

{$ENDIF}

{$IFDEF MSWINDOWS}

  FObjectInstance := Classes.MakeObjectInstance(MainWndProc);

  //设置回调函数

{$ENDIF}

  FBrush := TBrush.Create;

  FBrush.Color := FColor;

  FParentCtl3D := True;

  FTabOrder := -1;

  FImeMode := imDontCare;

  if SysLocale.PriLangID = LANG_JAPANESE then

    FImeName := ''

  else

    FImeName := Screen.DefaultIme;

  FUseDockManager := False;

  FBevelEdges := [beLeft, beTop, beRight, beBottom];

  FBevelInner := bvRaised;

  FBevelOuter := bvLowered;

  FBevelWidth := 1;

  FHelpType := htContext;

end;

 

constructor TControl.Create(AOwner: TComponent);

begin

  inherited Create(AOwner);

  FWindowProc := WndProc;

end;

 

TControl = class(TComponent)

  private

    FParent: TWinControl;

FWindowProc: TWndMethod;

end;

 

procedure TWinControl.MainWndProc(var Message: TMessage);

begin

  try

    try

      WindowProc(Message);

    finally

      FreeDeviceContexts;

      FreeMemoryContexts;

    end;

  except

    Application.HandleException(Self);

  end;

end;

 

申明:

procedure MainWndProc(var Message: TMessage);

不希望程序员覆盖,但是可以覆盖WindowProc方法。

TWinCtrol=class(TControl)

procedure WndProc(var Message: TMessage); override;

end;

TForm(Instance).HandleNeeded;

其实调用的是TWinControl.HandleNeeded;

procedure TWinControl.HandleNeeded;

begin

  if FHandle = 0 then

  begin

    if Parent <> nil then Parent.HandleNeeded;

    CreateHandle;

  end;

end;

 

procedure TWinControl.CreateHandle;

var

  I: Integer;

begin

  if FHandle = 0 then

  begin

    CreateWnd;

    SetProp(FHandle, MakeIntAtom(ControlAtom), THandle(Self));

    SetProp(FHandle, MakeIntAtom(WindowAtom), THandle(Self));

    if Parent <> nil then

      SetWindowPos(FHandle, Parent.PrecedingWindow(Self), 0, 0, 0, 0,

        SWP_NOMOVE + SWP_NOSIZE + SWP_NOACTIVATE);

    for I := 0 to ControlCount - 1 do

      Controls[I].UpdateAnchorRules;

  end;

end;

procedure TCustomForm.CreateWnd;

var

  ClientCreateStruct: TClientCreateStruct;

begin

  inherited CreateWnd;

  if NewStyleControls then

    if BorderStyle <> bsDialog then

      SendMessage(Handle, WM_SETICON, 1, GetIconHandle) else

      SendMessage(Handle, WM_SETICON, 1, 0);

  if not (csDesigning in ComponentState) then

    case FormStyle of

      fsMDIForm:

        begin

          with ClientCreateStruct do

          begin

            idFirstChild := $FF00;

            hWindowMenu := 0;

            if FWindowMenu <> nil then hWindowMenu := FWindowMenu.Handle;

          end;

          FClientHandle := Windows.CreateWindowEx(WS_EX_CLIENTEDGE, 'MDICLIENT',

            nil, WS_CHILD or WS_VISIBLE or WS_GROUP or WS_TABSTOP or

            WS_CLIPCHILDREN or WS_HSCROLL or WS_VSCROLL or WS_CLIPSIBLINGS or

            MDIS_ALLCHILDSTYLES, 0, 0, ClientWidth, ClientHeight, Handle, 0,

            HInstance, @ClientCreateStruct);

{$IFDEF LINUX}

          FClientInstance := WinUtils.MakeObjectInstance(ClientWndProc);

{$ENDIF}

{$IFDEF MSWINDOWS}

          FClientInstance := Classes.MakeObjectInstance(ClientWndProc);//设置回调函数

{$ENDIF}

          FDefClientProc := Pointer(GetWindowLong(FClientHandle, GWL_WNDPROC));

          SetWindowLong(FClientHandle, GWL_WNDPROC, Longint(FClientInstance));

        end;

      fsStayOnTop:

        SetWindowPos(Handle, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE or

          SWP_NOSIZE or SWP_NOACTIVATE);

    end;

end;

 

TWincontrol=class(TControl)

    procedure CreateWnd; virtual;

end;

 

procedure TWinControl.CreateWnd;

var

  Params: TCreateParams;

  TempClass: TWndClass;

  ClassRegistered: Boolean;

begin

  CreateParams(Params);//设定窗口注册属性,虚拟方法

  with Params do

  begin

    if (WndParent = 0) and (Style and WS_CHILD <> 0) then

      if (Owner <> nil) and (csReading in Owner.ComponentState) and

        (Owner is TWinControl) then

        WndParent := TWinControl(Owner).Handle

      else

        raise EInvalidOperation.CreateFmt(SParentRequired, [Name]);

    FDefWndProc := WindowClass.lpfnWndProc;

    ClassRegistered := GetClassInfo(WindowClass.hInstance, WinClassName, TempClass);

    if not ClassRegistered or (TempClass.lpfnWndProc <> @InitWndProc) then

    begin

      if ClassRegistered then Windows.UnregisterClass(WinClassName,

        WindowClass.hInstance);

      WindowClass.lpfnWndProc := @InitWndProc;

      WindowClass.lpszClassName := WinClassName;

      if Windows.RegisterClass(WindowClass) = 0 then RaiseLastOSError;

    end;

    CreationControl := Self;

    CreateWindowHandle(Params);

    if FHandle = 0 then

      RaiseLastOSError;

    if (GetWindowLong(FHandle, GWL_STYLE) and WS_CHILD <> 0) and

      (GetWindowLong(FHandle, GWL_ID) = 0) then

      SetWindowLong(FHandle, GWL_ID, FHandle);

  end;

  StrDispose(FText);

  FText := nil;

  UpdateBounds;

  Perform(WM_SETFONT, FFont.Handle, 1);

  if AutoSize then AdjustSize;

end;

 

procedure TWinControl.CreateWindowHandle(const Params: TCreateParams);

begin

  with Params do

    FHandle := CreateWindowEx(ExStyle, WinClassName, Caption, Style,

      X, Y, Width, Height, WndParent, 0, WindowClass.hInstance, Param);

end;

 

TWinControl = class(TControl)

  procedure CreateParams(var Params: TCreateParams); virtual;

抱歉!评论已关闭.