{%MainUnit ../controls.pp} {****************************************************************************** TWinControl ****************************************************************************** ***************************************************************************** * * * This file is part of the Lazarus Component Library (LCL) * * * * See the file COPYING.LCL, included in this distribution, * * for details about the copyright. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * * * ***************************************************************************** } {$IFOPT C-} // Uncomment for local trace // {$C+} // {$DEFINE ASSERT_IS_ON} {$ENDIF} { $DEFINE CHECK_POSITION} { $DEFINE VerboseMouseBugfix} {------------------------------------------------------------------------------ TWinControl AdjustSize Calls DoAutoSize smart. During loading and handle creation the calls are delayed. This method do the same as TWinControl.DoAutoSize at the beginning. But since DoAutoSize is commonly overriden by existing Delphi components, they do not all tests, which can result in too much overhead. To reduce this the LCL calls AdjustSize instead. ------------------------------------------------------------------------------} procedure TWinControl.AdjustSize; begin If not AutoSizeCanStart then exit; if AutoSizeDelayed then begin //debugln('TWinControl.AdjustSize AutoSizeDelayed ',DbgSName(Self)); Include(FWinControlFlags,wcfAutoSizeNeeded); exit; end; //debugln('TWinControl.AdjustSize DoAutoSize ',DbgSName(Self)); DoAutoSize; end; {------------------------------------------------------------------------------ function TWinControl.AutoSizeDelayed: boolean; ------------------------------------------------------------------------------} function TWinControl.AutoSizeDelayed: boolean; begin Result:=(wcfCreatingChildHandles in FWinControlFlags) or (inherited AutoSizeDelayed); //if Result then debugln('TWinControl.AutoSizeDelayed A ',DbgSName(Self),' wcfCreatingChildHandles=',dbgs(wcfCreatingChildHandles in FWinControlFlags),' csLoading=',dbgs(csLoading in ComponentState)); end; {------------------------------------------------------------------------------ TWinControl AdjustClientRect ------------------------------------------------------------------------------} Procedure TWinControl.AdjustClientRect(var ARect: TRect); Begin //Not used. It's a virtual procedure that should be overriden. end; {------------------------------------------------------------------------------ TWinControl AlignControls Align child controls ------------------------------------------------------------------------------} procedure TWinControl.AlignControls(AControl: TControl; var RemainingClientRect: TRect); var AlignList: TList; RemainingBorderSpace: TRect; // borderspace around RemainingClientRect function AlignWork: Boolean; var I: Integer; CurControl: TControl; begin Result := True; for I := ControlCount - 1 downto 0 do begin CurControl:=Controls[I]; if (CurControl.Align <> alNone) or (CurControl.Anchors <> [akLeft, akTop]) or (CurControl.AnchorSide[akLeft].Control<>nil) or (CurControl.AnchorSide[akTop].Control<>nil) then Exit; end; Result := False; end; function Anchored(Align: TAlign; Anchors: TAnchors): Boolean; begin case Align of alLeft: Result := akLeft in Anchors; alTop: Result := akTop in Anchors; alRight: Result := akRight in Anchors; alBottom: Result := akBottom in Anchors; alClient: Result := Anchors = [akLeft, akTop, akRight, akBottom]; else Result := False; end; end; procedure DoPosition(Control: TControl; AAlign: TAlign); var NewLeft, NewTop, NewWidth, NewHeight: Integer; ParentBaseClientSize: TPoint; CurBaseBounds: TRect; NewRight: Integer; NewBottom: Integer; var MinWidth: Integer; MaxWidth: Integer; MinHeight: Integer; MaxHeight: Integer; CurRemainingClientRect: TRect; CurRemainingBorderSpace: TRect; ChildAroundSpace: TRect; AnchorSideCacheValid: array[TAnchorKind] of boolean; AnchorSideCache: array[TAnchorKind] of integer; function ConstraintWidth(NewWidth: integer): integer; begin Result:=NewWidth; if (MaxWidth>=MinWidth) and (Result>MaxWidth) and (MaxWidth>0) then Result:=MaxWidth; if Result=MinHeight) and (Result>MaxHeight) and (MaxHeight>0) then Result:=MaxHeight; if Resultnil)); CurAnchorSide.GetSidePosition(ReferenceControl,ReferenceSide,Position); if ReferenceControl<>nil then Result:=Position; AnchorSideCacheValid[Kind]:=true; AnchorSideCache[Kind]:=Result; end; begin {$IFDEF CHECK_POSITION} if AnsiCompareText(Control.ClassName,'TScrollBar')=0 then with Control do DebugLn('[TWinControl.AlignControls.DoPosition] A Control=',Name,':',ClassName,' ',dbgs(Left),',',dbgs(Top),',',dbgs(Width),',',dbgs(Height),' recalculate the anchors=',dbgs(Control.Anchors <> AnchorAlign[AAlign]),' Align=',AlignNames[AAlign]); {$ENDIF} with Control do begin // get constraints MinWidth:=Constraints.EffectiveMinWidth; if MinWidth<0 then MinWidth:=0; MaxWidth:=Constraints.EffectiveMaxWidth; MinHeight:=Constraints.EffectiveMinHeight; if MinHeight<0 then MinHeight:=0; MaxHeight:=Constraints.EffectiveMaxHeight; // get default bounds NewLeft:=Left; NewTop:=Top; NewWidth:=ConstraintWidth(Width); NewHeight:=ConstraintHeight(Height); end; InitAnchorSideCache; { Recalculate the anchors Use Anchors to ensure that a control maintains its current position relative to an edge of its parent or another sibling. This is controlled with the AnchorSide properties. 1. If AnchorSide[].Control is not set, the distance is kept relative to the edges of the client are of its parent. When its parent is resized, the control holds its position relative to the edges to which it is anchored. If a control is anchored to opposite edges of its parent, the control stretches when its parent is resized. For example, if a control has its Anchors property set to [akLeft,akRight], the control stretches when the width of its parent changes. Anchors is enforced only when the parent is resized. Thus, for example, if a control is anchored to opposite edges of a form at design time and the form is created in a maximized state, the control is not stretched because the form is not resized after the control is created. 2. If AnchorSide[].Control is set, the BorderSpace properties defines the distance to another sibling (i.e. AnchorSide[].Control). } if (AAlign = alNone) or (Control.Anchors <> AnchorAlign[AAlign]) then begin // Get the base bounds. The base bounds are the user defined bounds // without automatic aligning and/or anchoring // get base size of parents client area ParentBaseClientSize:=Control.FBaseParentClientSize; if (ParentBaseClientSize.X=0) and (ParentBaseClientSize.Y=0) then ParentBaseClientSize:=Point(Control.Parent.ClientWidth, Control.Parent.ClientHeight); // get base bounds of Control CurBaseBounds:=Control.FBaseBounds; if (CurBaseBounds.Right=CurBaseBounds.Left) and (CurBaseBounds.Bottom=CurBaseBounds.Top) then CurBaseBounds:=Control.BoundsRect; {$IFDEF CHECK_POSITION} //if csDesigning in ComponentState then if AnsiCompareText(Control.ClassName,'TScrollBar')=0 then DebugLn('[TWinControl.AlignControls.DoPosition] Before Anchoring ', ' ',Name,':',ClassName, ' CurBaseBounds='+dbgs(CurBaseBounds.Left)+','+dbgs(CurBaseBounds.Top)+','+dbgs(CurBaseBounds.Right-CurBaseBounds.Left)+','+dbgs(CurBaseBounds.Bottom-CurBaseBounds.Top), ' ParBaseClient='+dbgs(ParentBaseClientSize.X)+','+dbgs(ParentBaseClientSize.Y), ' ParClient='+dbgs(Control.Parent.ClientWidth)+','+dbgs(Control.Parent.ClientHeight), ' NewBounds='+dbgs(NewLeft)+','+dbgs(NewTop)+','+dbgs(NewWidth)+','+dbgs(NewHeight), ''); {$ENDIF} if akLeft in Control.Anchors then begin // keep distance to left side of parent or another sibling NewLeft:=GetAnchorSidePosition(akLeft,CurBaseBounds.Left); if akRight in Control.Anchors then begin // keep distance to right side of parent or another sibling // -> change the width NewRight:=Control.Parent.ClientWidth -(ParentBaseClientSize.X-CurBaseBounds.Right); NewRight:=GetAnchorSidePosition(akRight,NewRight); NewWidth:=ConstraintWidth(NewRight-NewLeft); end else begin // do not anchor to the right // -> keep new width end; end else begin // do not anchor to the left if akRight in Control.Anchors then begin // keep distance to right side of parent // and keep new width NewRight:=Control.Parent.ClientWidth -(ParentBaseClientSize.X-CurBaseBounds.Right); NewRight:=GetAnchorSidePosition(akRight,NewRight); NewLeft:=NewRight-NewWidth; end else begin // do not anchor to the right // -> keep new width and center horizontally NewLeft:=(Control.Parent.ClientWidth-NewWidth) div 2; end; end; if akTop in Control.Anchors then begin // keep distance to top side of parent NewTop:=GetAnchorSidePosition(akTop,CurBaseBounds.Top); if akBottom in Control.Anchors then begin // keep distance to bottom side of parent // -> change the height NewBottom:=Control.Parent.ClientHeight -(ParentBaseClientSize.Y-CurBaseBounds.Bottom); NewBottom:=GetAnchorSidePosition(akBottom,NewBottom); NewHeight:=ConstraintHeight(NewBottom-NewTop); end else begin // do not anchor to the bottom // -> keep new height end; end else begin // do not anchor to the top if akBottom in Control.Anchors then begin // keep distance to bottom side of parent // and keep new height NewBottom:=Control.Parent.ClientHeight -(ParentBaseClientSize.Y-CurBaseBounds.Bottom); NewBottom:=GetAnchorSidePosition(akBottom,NewBottom); NewTop:=NewBottom-NewHeight; end else begin // do not anchor to the bottom // -> keep new height and center vertically NewTop:=(Control.Parent.ClientHeight-NewHeight) div 2; end; end; {$IFDEF CHECK_POSITION} //if csDesigning in ComponentState then if AnsiCompareText(Control.ClassName,'TScrollBar')=0 then with Control do DebugLn('[TWinControl.AlignControls.DoPosition] After Anchoring', ' ',Name,':',ClassName, ' Align=',AlignNames[AAlign], ' Control=',Name,':',ClassName, ' Old=',Left,',',Top,',',Width,',',Height, ' New=',NewLeft,',',NewTop,',',NewWidth,',',NewHeight, ''); {$ENDIF} end; // set min size to stop circling (this should not be needed. But if someone // plays/fixes the above code, new bugs can enter and there are far too many // combinations to test, and so the LCL can loop for some applications. // Prevent this, so users can at least report a bug.) if NewWidth<0 then NewWidth:=0; if NewHeight<0 then NewHeight:=0; if AAlign in [alLeft,alTop,alRight,alBottom,alClient] then begin { Realign Use Align to align a control to the top, bottom, left, or right of a form or panel and have it remain there even if the size of the form, panel, or component that contains the control changes. When the parent is resized, an aligned control also resizes so that it continues to span the top, bottom, left, or right edge of the parent (more exact: span the remaining client area of its parent). } NewRight:=NewLeft+NewWidth; NewBottom:=NewTop+NewHeight; // calculate current RemainingClientRect for the current Control CurRemainingClientRect:=RemainingClientRect; CurRemainingBorderSpace:=RemainingBorderSpace; Control.BorderSpacing.GetSpaceAround(ChildAroundSpace); AdjustBorderSpace(CurRemainingClientRect,CurRemainingBorderSpace, ChildAroundSpace); {$IFDEF CHECK_POSITION} if AnsiCompareText(Control.ClassName,'TScrollBar')=0 then DebugLn(' Before aligning akRight in AnchorAlign[AAlign]=',akRight in AnchorAlign[AAlign], ' akLeft in Control.Anchors=',akLeft in Control.Anchors, ' ARect=',ARect.Left,',',ARect.Top,',',ARect.Right,',',ARect.Bottom, ' New=',NewLeft,',',NewTop,',',NewRight,',',NewBottom); {$ENDIF} if akLeft in AnchorAlign[AAlign] then begin if (akRight in (Control.Anchors+AnchorAlign[AAlign])) then begin // left align and keep right border NewLeft:=CurRemainingClientRect.Left; NewRight:=NewLeft+ConstraintWidth(NewRight-NewLeft); end else begin // left align and right border free to move (-> keep width) dec(NewRight,NewLeft-RemainingClientRect.Left); NewLeft:=CurRemainingClientRect.Left; end; end; if akTop in AnchorAlign[AAlign] then begin if (akBottom in (Control.Anchors+AnchorAlign[AAlign])) then begin // top align and keep bottom border NewTop:=CurRemainingClientRect.Top; NewBottom:=NewTop+ConstraintHeight(NewBottom-NewTop); end else begin // top align and bottom border is free to move (-> keep height) dec(NewBottom,NewTop-RemainingClientRect.Top); NewTop:=CurRemainingClientRect.Top; end; end; if akRight in AnchorAlign[AAlign] then begin if (akLeft in (Control.Anchors+AnchorAlign[AAlign])) then begin // right align and keep left border NewWidth:=ConstraintWidth(CurRemainingClientRect.Right-NewLeft); if AAlign=alRight then begin // align to right (this overrides the keeping of left border) NewRight:=CurRemainingClientRect.Right; NewLeft:=NewRight-NewWidth; end else begin // keep left border overrides keeping right border NewRight:=NewLeft+NewWidth; end; end else begin // right align and left border free to move (-> keep width) inc(NewLeft,CurRemainingClientRect.Right-NewRight); NewRight:=CurRemainingClientRect.Right; end; end; if akBottom in AnchorAlign[AAlign] then begin if (akTop in (Control.Anchors+AnchorAlign[AAlign])) then begin // bottom align and keep top border NewHeight:=ConstraintHeight(CurRemainingClientRect.Bottom-NewTop); if AAlign=alBottom then begin // align to bottom (this overrides the keeping of top border) NewBottom:=CurRemainingClientRect.Bottom; NewTop:=NewBottom-NewHeight; end else begin // keeping top border overrides keeping bottom border NewBottom:=NewTop+NewHeight; end; end else begin // bottom align and top border free to move (-> keep height) inc(NewTop,CurRemainingClientRect.Bottom-NewBottom); NewBottom:=CurRemainingClientRect.Bottom; end; end; NewWidth:=Max(0,NewRight-NewLeft); NewHeight:=Max(0,NewBottom-NewTop); {$IFDEF CHECK_POSITION} //if csDesigning in Control.ComponentState then if AnsiCompareText(Control.ClassName,'TScrollBar')=0 then with Control do DebugLn('[TWinControl.AlignControls.DoPosition] After Aligning', ' ',Name,':',ClassName, ' Align=',AlignNames[AAlign], ' Control=',Name,':',ClassName, ' Old=',Left,',',Top,',',Width,',',Height, ' New=',NewLeft,',',NewTop,',',NewWidth,',',NewHeight, ' ARect=',ARect.Left,',',ARect.Top,',',ARect.Right-ARect.Left,',',ARect.Bottom-ARect.Top, ''); {$ENDIF} end; // set the new bounds if (Control.Left <> NewLeft) or (Control.Top <> NewTop) or (Control.Width <> NewWidth) or (Control.Height <> NewHeight) then begin {$IFDEF CHECK_POSITION} //if csDesigning in Control.ComponentState then if AnsiCompareText(Control.ClassName,'TScrollBar')=0 then with Control do DebugLn('[TWinControl.AlignControls.DoPosition] NEW BOUNDS Control=',Name,':',ClassName,' NewBounds=',NewLeft,',',NewTop,',',NewWidth,',',NewHeight,' Align=',AlignNames[AAlign]); {$ENDIF} // lock the base bounds, so that the new automatic bounds do not override // the user settings Control.SetAlignedBounds(NewLeft, NewTop, NewWidth, NewHeight); // Sometimes SetBounds change the bounds. For example due to constraints. // update the new bounds with Control do begin NewLeft:=Left; NewTop:=Top; NewWidth:=Width; NewHeight:=Height; end; {$IFDEF CHECK_POSITION} //if csDesigning in Control.ComponentState then if AnsiCompareText(Control.ClassName,'TScrollBar')=0 then with Control do DebugLn('[TWinControl.AlignControls.DoPosition] AFTER SETBOUND Control=',Name,':',ClassName,' Bounds=',Left,',',Top,',',Width,',',Height); {$ENDIF} end; // adjust the remaining client area case AAlign of alTop: begin RemainingClientRect.Top:=NewTop+NewHeight; RemainingBorderSpace.Top:=0; AdjustBorderSpace(RemainingClientRect,RemainingBorderSpace, 0,Max(ChildSizing.VerticalSpacing,ChildAroundSpace.Bottom),0,0); end; alBottom: begin RemainingClientRect.Bottom:=NewTop; RemainingBorderSpace.Bottom:=0; AdjustBorderSpace(RemainingClientRect,RemainingBorderSpace, 0,0,0,Max(ChildSizing.VerticalSpacing,ChildAroundSpace.Top)); end; alLeft: begin RemainingClientRect.Left:=NewLeft+NewWidth; RemainingBorderSpace.Left:=0; AdjustBorderSpace(RemainingClientRect,RemainingBorderSpace, Max(ChildSizing.HorizontalSpacing,ChildAroundSpace.Right),0,0,0); end; alRight: begin RemainingClientRect.Right:=NewLeft; RemainingBorderSpace.Right:=0; AdjustBorderSpace(RemainingClientRect,RemainingBorderSpace, 0,0,Max(ChildSizing.HorizontalSpacing,ChildAroundSpace.Left),0); end; alClient: begin // VCL is tricking here. // For alClients with Constraints do the same as for alLeft {debugln('TWinControl.AlignControls.DoPosition A Self=',Name,' Control=',DbgSName(Control),' ',dbgs(NewLeft),' ',dbgs(NewWidth)); RemainingClientRect.Left:=NewLeft+NewWidth; RemainingBorderSpace.Left:=0; AdjustBorderSpace(RemainingClientRect,RemainingBorderSpace, Max(ChildSizing.HorizontalSpacing,ChildAroundSpace.Right),0,0,0);} end; end; {$IFDEF CHECK_POSITION} if AnsiCompareText(Control.ClassName,'TScrollBar')=0 then with Control do DebugLn('[TWinControl.AlignControls.DoPosition] END Control=', Name,':',ClassName, ' ',Left,',',Top,',',Width,',',Height, ' Align=',AlignNames[AAlign], ' ARect=',ARect.Left,',',ARect.Top,',',ARect.Right-ARect.Left,',',ARect.Bottom-ARect.Top, ''); {$ENDIF} end; function InsertBefore(Control1, Control2: TControl; AAlign: TAlign): Boolean; begin Result := False; case AAlign of alTop: Result := Control1.Top < Control2.Top; alBottom: Result := (Control1.Top + Control1.Height) >= (Control2.Top + Control2.Height); alLeft: Result := Control1.Left < Control2.Left; alRight: Result := (Control1.Left + Control1.Width) >= (Control2.Left + Control2.Width); end; end; procedure DoAlign(AAlign: TAlign); var I, X: Integer; Control: TControl; begin AlignList.Clear; // first add the current control if (AControl <> nil) and (AControl.Align = AAlign) and ((AAlign = alNone) or AControl.Visible or ((csDesigning in AControl.ComponentState) and not (csNoDesignVisible in AControl.ControlStyle))) then AlignList.Add(AControl); // then add all other for I := 0 to ControlCount - 1 do begin Control := Controls[I]; if (Control.Align = AAlign) and ((AAlign = alNone) or (Control.Visible or (Control.ControlStyle * [csAcceptsControls, csNoDesignVisible] = [csAcceptsControls, csNoDesignVisible])) or ((csDesigning in Control.ComponentState) and not (csNoDesignVisible in Control.ControlStyle))) then begin if Control = AControl then Continue; X := 0; while (X < AlignList.Count) and not InsertBefore(Control, TControl(AlignList[X]), AAlign) do Inc(X); AlignList.Insert(X, Control); end; end; if not DoAlignChildControls(AAlign,AControl,AlignList,RemainingClientRect) then for I := 0 to AlignList.Count - 1 do DoPosition(TControl(AlignList[I]), AAlign); end; var i: Integer; ChildControl: TControl; begin if wcfAligningControls in FWinControlFlags then exit; Include(FWinControlFlags,wcfAligningControls); // unset all align needed flags Exclude(FWinControlFlags,wcfReAlignNeeded); for i:=ControlCount-1 downto 0 do begin ChildControl:=Controls[i]; Exclude(ChildControl.FControlFlags,cfRequestAlignNeeded); end; try //if csDesigning in ComponentState then begin //DebugLn('[TWinControl.AlignControls] ',Name,':',Classname,' ',Left,',',Top,',',Width,',',Height,' AlignWork=',AlignWork,' ControlCount=',ControlCount); //if AControl<>nil then DebugLn(' AControl=',AControl.Name,':',AControl.ClassName); //end; if AlignWork then begin AdjustClientRect(RemainingClientRect); RemainingBorderSpace:=Rect(0,0,0,0); // adjust RemainingClientRect by ChildSizing properties AdjustBorderSpace(RemainingClientRect,RemainingBorderSpace, ChildSizing.LeftRightSpacing,ChildSizing.TopBottomSpacing, ChildSizing.LeftRightSpacing,ChildSizing.TopBottomSpacing); //DebugLn('[TWinControl.AlignControls] ',Name,':',Classname,' ',Left,',',Top,',',Width,',',Height,' ClientRect=',RemainingClientRect.Left,',',RemainingClientRect.Top,',',RemainingClientRect.Right,',',RemainingClientRect.Bottom); AlignList := TList.Create; try DoAlign(alTop); DoAlign(alBottom); DoAlign(alLeft); DoAlign(alRight); DoAlign(alClient); DoAlign(alCustom); DoAlign(alNone); finally AlignList.Free; end; end; ControlsAligned; finally Exclude(FWinControlFlags,wcfAligningControls); end; if Showing then AdjustSize; end; function TWinControl.DoAlignChildControls(TheAlign: TAlign; AControl: TControl; AControlList: TList; var ARect: TRect): Boolean; begin Result:=false; end; procedure TWinControl.DoChildSizingChange(Sender: TObject); begin InvalidatePreferredSize; AdjustSize; end; Procedure TWinControl.DoAutoSize; var I : Integer; AControl: TControl; PreferredWidth: LongInt; PreferredHeight: LongInt; ChildBounds: TRect; begin //debugln('TWinControl.DoAutoSize ',DbgSName(Self)); If not AutoSizeCanStart then exit; if AutoSizeDelayed then begin Include(FWinControlFlags,wcfAutoSizeNeeded); exit; end; AutoSizing := True; try // autosize control to preferred size GetPreferredSize(PreferredWidth,PreferredHeight,false); // move childs tight to left and top If ControlCount > 0 then begin GetChildBounds(ChildBounds,true); if (ChildBounds.Left<>0) or (ChildBounds.Top<>0) then begin For I := 0 to ControlCount - 1 do begin AControl:=Controls[I]; If AControl.Visible then begin AControl.SetBoundsKeepBase(AControl.Left - ChildBounds.Left, AControl.Top - ChildBounds.Top, AControl.Width,AControl.Height,true); end; end; end; end; // set new size {$IFDEF VerboseAutoSize} debugln('DoAutoSize A ',DbgSName(Self),' Cur=',dbgs(Width),'x',dbgs(Height),' Prefer=',dbgs(PreferredWidth),'x',dbgs(PreferredHeight),' WidgetClass=',WidgetSetClass.ClassName); {$ENDIF} if (PreferredWidth<>Width) or (PreferredHeight<>Height) then begin //debugln('DoAutoSize Resize ',DbgSName(Self),' W=',dbgs(PreferredWidth),' H=',dbgs(PreferredHeight)); {$IFDEF EnablePreferredSize} SetBoundsKeepBase(Left,Top,PreferredWidth,PreferredHeight,true); {$ENDIF} end; finally AutoSizing := False; end; Exclude(FWinControlFlags,wcfAutoSizeNeeded); end; {------------------------------------------------------------------------------} { TWinControl BroadCast } {------------------------------------------------------------------------------} Procedure TWinControl.BroadCast(var ToAllMessage); var I: Integer; begin for I := 0 to ControlCount - 1 do begin Controls[I].WindowProc(TLMessage(ToAllMessage)); if TLMessage(ToAllMessage).Result <> 0 then Exit; end; end; procedure TWinControl.NotifyControls(Msg: Word); var ToAllMessage: TLMessage; begin ToAllMessage.Msg := Msg; ToAllMessage.WParam := 0; ToAllMessage.LParam := 0; ToAllMessage.Result := 0; Broadcast(ToAllMessage); end; procedure TWinControl.DefaultHandler(var AMessage); begin CallDefaultWndHandler(Self,AMessage); end; {------------------------------------------------------------------------------} { TWinControl CanFocus } {------------------------------------------------------------------------------} Function TWinControl.CanFocus : Boolean; var Control: TWinControl; Form: TCustomForm; begin Result := False; //Verify that every parent is enabled and visible before returning true. Form := GetParentForm(Self); if Form <> nil then begin Control := Self; repeat if not (Control.FVisible and Control.Enabled) then Exit; if Control = Form then break; Control := Control.Parent; until false; Result := True; end; end; {------------------------------------------------------------------------------ TWinControl CMDrag ------------------------------------------------------------------------------} Procedure TWinControl.CMDrag(var Message: TCMDrag); Begin {$IFDEF VerboseDrag} DebugLn('TWinControl.CMDrag ',Name,':',ClassName,' ',ord(Message.DragMessage)); {$ENDIF} DoDragMsg(Message); end; {------------------------------------------------------------------------------ TWinControl CreateSubClass ------------------------------------------------------------------------------} procedure TWinControl.CreateSubClass(var Params: TCreateParams; ControlClassName: PChar); begin // TODO: Check if we need this method end; {------------------------------------------------------------------------------ TWinControl DisableAlign ------------------------------------------------------------------------------} procedure TWinControl.DisableAlign; begin Inc(FAlignLevel); End; {------------------------------------------------------------------------------- TWinControl DoAdjustClientRectChange Asks the interface if clientrect has changed since last AlignControl and calls AlignControl(nil) on change. -------------------------------------------------------------------------------} procedure TWinControl.DoAdjustClientRectChange; var r: TRect; begin r:=GetClientRect; AdjustClientRect(r); //DebugLn(' TWinControl.DoAdjustClientRectChange ',Name,':',ClassName,' ',dbgs(r.Right),',',dbgs(r.Bottom)); if not CompareRect(@r,@FAdjustClientRectRealized) then begin // client rect changed since last AlignControl {$IFDEF VerboseClientRectBugFix} DebugLn('UUU TWinControl.DoAdjustClientRectChange ClientRect changed ',Name,':',ClassName, ' Old=',FAdjustClientRectRealized.Right,'x',FAdjustClientRectRealized.Bottom, ' New=',r.RIght,'x',r.Bottom); {$ENDIF} FAdjustClientRectRealized:=r; ReAlign; Resize; end; end; {------------------------------------------------------------------------------- TWinControl DoConstraintsChange Params: Sender : TObject Call inherited, then send the constraints to the interface -------------------------------------------------------------------------------} procedure TWinControl.DoConstraintsChange(Sender : TObject); begin inherited DoConstraintsChange(Sender); //debugln('TWinControl.DoConstraintsChange ',DbgSName(Self),' HandleAllocated=',dbgs(HandleAllocated)); if HandleAllocated then TWSWinControlClass(WidgetSetClass).ConstraintsChange(Self); end; {------------------------------------------------------------------------------- TWinControl InvalidateClientRectCache(WithChildControls: boolean) The clientrect is cached. Call this procedure to invalidate the cache, so that next time the clientrect is fetched from the interface. -------------------------------------------------------------------------------} procedure TWinControl.InvalidateClientRectCache(WithChildControls: boolean); var I: Integer; begin {$IFDEF VerboseClientRectBugFix} DebugLn('[TWinControl.InvalidateClientRectCache] ',Name,':',ClassName); {$ENDIF} Include(FWinControlFlags,wcfClientRectNeedsUpdate); if WithChildControls then begin // invalidate clients too if Assigned(FWinControls) then for I := 0 to FWinControls.Count - 1 do if Assigned(FWinControls.Items[I]) then TWinControl(FWinControls.Items[I]).InvalidateClientRectCache(true); end; end; {------------------------------------------------------------------------------- TWinControl InvalidateClientRectCache The clientrect is cached. Check if cache is valid. -------------------------------------------------------------------------------} function TWinControl.ClientRectNeedsInterfaceUpdate: boolean; var IntfClientRect: TRect; begin Result:=false; if not HandleAllocated then exit; LCLIntf.GetClientRect(Handle,IntfClientRect); Result:=(FClientWidth<>IntfClientRect.Right) or (FClientHeight<>IntfClientRect.Bottom); end; {------------------------------------------------------------------------------- TWinControl DoSetBounds Params: ALeft, ATop, AWidth, AHeight : integer Anticipate the new clientwidth/height and call inherited Normally the clientwidth/clientheight is adjusted automatically by the interface. But it is up to interface when this will be done. The gtk for example just puts resize requests into a queue. The LCL would resize the childs just after this procedure due to the clientrect. On complex forms with lots of nested controls, this would result in thousands of resizes. Changing the clientrect in the LCL to the most probable size reduces unneccessary resizes. -------------------------------------------------------------------------------} procedure TWinControl.DoSetBounds(ALeft, ATop, AWidth, AHeight : integer); begin if wcfClientRectNeedsUpdate in FWinControlFlags then begin GetClientRect; end; {$IFDEF VerboseClientRectBugFix} DbgOut('[TWinControl.DoSetBounds] ',Name,':',ClassName,' OldClient=',FClientWidth,',',FClientHeight, ' OldHeight=',FHeight,' NewHeight=',AHeight); {$ENDIF} inc(FClientWidth,AWidth-FWidth); if (FClientWidth<0) then FClientWidth:=0; inc(FClientHeight,AHeight-FHeight); if (FClientHeight<0) then FClientHeight:=0; {$IFDEF VerboseClientRectBugFix} DebugLn(' NewClient=',FClientWidth,',',FClientHeight); {$ENDIF} inherited DoSetBounds(ALeft,ATop,AWidth,AHeight); end; {------------------------------------------------------------------------------} { TWinControl EnableAlign } {------------------------------------------------------------------------------} procedure TWinControl.EnableAlign; begin Dec(FAlignLevel); if FAlignLevel = 0 then begin if csAlignmentNeeded in ControlState then ReAlign; end; end; {------------------------------------------------------------------------------} { TWinControl.CanTab } {------------------------------------------------------------------------------} Function TWinControl.CanTab: Boolean; begin Result := CanFocus; end; procedure TWinControl.DoDragMsg(var DragMsg: TCMDrag); var TargetControl: TControl; begin case DragMsg.DragMessage of dmFindTarget: begin {$IFDEF VerboseDrag} DebugLn('TWinControl.DoDragMsg dmFindTarget ',Name,':',ClassName,' Start DragMsg.DragRec^.Pos=',DragMsg.DragRec^.Pos.X,',',DragMsg.DragRec^.Pos.Y); {$ENDIF} TargetControl := ControlatPos(ScreentoClient(DragMsg.DragRec^.Pos),False); if TargetControl = nil then TargetControl := Self; {$IFDEF VerboseDrag} DebugLn('TWinControl.DoDragMsg dmFindTarget ',Name,':',ClassName,' End Result=',TargetControl.Name,':',TargetControl.ClassName); {$ENDIF} DragMsg.Result:=longint(TargetControl); end; else inherited DoDragMsg(DragMsg); end; end; {------------------------------------------------------------------------------} { TWinControl GetChildren } {------------------------------------------------------------------------------} Procedure TWinControl.GetChildren(Proc: TGetChildProc; Root : TComponent); var I : Integer; Control : TControl; Begin for I := 0 to ControlCount-1 do Begin Control := Controls[i]; if Control.Owner = Root then Proc(Control); end; End; {------------------------------------------------------------------------------- function TWinControl.ChildClassAllowed(ChildClass: TClass): boolean; Allow TControl as child. -------------------------------------------------------------------------------} function TWinControl.ChildClassAllowed(ChildClass: TClass): boolean; begin Result:=(ChildClass<>nil) and ChildClass.InheritsFrom(TControl); end; {------------------------------------------------------------------------------- TWinControl GetClientOrigin Result: TPoint returns the screen coordinate of the topleft coordinate 0,0 of the client area Note that this value is the position as stored in the interface and is not always in sync with the LCL. When a control is moved, the LCL sets the bounds to the wanted position and sends a move message to the interface. It is up to the interface to handle moves instantly or queued. -------------------------------------------------------------------------------} Function TWinControl.GetClientOrigin: TPoint; var AControl: TWinControl; Begin Result.X := 0; Result.Y := 0; //DebugLn('[TWinControl.GetClientOrigin] ',Name,':',ClassName,' ',Handle); if HandleAllocated then begin // get the interface idea where the client area is on the screen LCLIntf.ClientToScreen(Handle,Result); // adjust the result by all bounds, that are not yet sent to the interface AControl:=Self; repeat inc(Result.X,AControl.Left-AControl.FBoundsRealized.Left); inc(Result.Y,AControl.Top-AControl.FBoundsRealized.Top); AControl:=AControl.Parent; until AControl=nil; end else Result:=inherited GetClientOrigin; Assert(False, Format('Trace:[TWinControl.GetClientOrigin] %s --> (%d, %d)', [Classname, Result.X, Result.Y])); end; {------------------------------------------------------------------------------- TWinControl GetClientRect Result: TRect returns the client area. Starting at 0,0. -------------------------------------------------------------------------------} function TWinControl.GetClientRect: TRect; procedure StoreClientRect(NewClientRect: TRect); var ClientSizeChanged: boolean; i: Integer; begin if wcfClientRectNeedsUpdate in FWinControlFlags then begin ClientSizeChanged:=(FClientWidth<>NewClientRect.Right) or (FClientHeight<>NewClientRect.Bottom); FClientWidth:=NewClientRect.Right; FClientHeight:=NewClientRect.Bottom; {$IFDEF VerboseSizeMsg} DebugLn('StoreClientRect ',Name,':',ClassName,' ',dbgs(FClientWidth),',',dbgs(FClientHeight)); {$ENDIF} if ClientSizeChanged then begin for i:=0 to ControlCount-1 do Exclude(Controls[i].FControlFlags,cfLastAlignedBoundsValid); end; Exclude(FWinControlFlags,wcfClientRectNeedsUpdate); end; end; var InterfaceWidth, InterfaceHeight: integer; begin if not HandleAllocated then begin Result:=inherited GetClientRect; StoreClientRect(Result); end else if wcfClientRectNeedsUpdate in FWinControlFlags then begin // update clientrect from interface LCLIntf.GetClientRect(Handle, Result); // the LCL is not always in sync with the interface // -> adjust client rect based on LCL bounds // for example: if the Width in LCL differ from the Width of the Interface // object, then adjust the clientwidth accordingly LCLIntf.GetWindowSize(Handle, InterfaceWidth, InterfaceHeight); Result.Right:=Width-(InterfaceWidth-Result.Right); Result.Bottom:=Height-(InterfaceHeight-Result.Bottom); StoreClientRect(Result); {r:=inherited GetClientRect; if (r.Left<>Result.Left) or (r.Top<>Result.Top) or (r.Right<>Result.Right) or (r.Bottom<>Result.Bottom) then begin //DebugLn(' TWinControl.GetClientRect ',Name,':',ClassName, // ' Old=',r.Left,',',r.Top,',',r.Right,',',r.Bottom, // ' New=',Result.Left,',',Result.Top,',',Result.Right,',',Result.Bottom // ); end;} end else begin Result:=Rect(0,0,FClientWidth,FClientHeight); end; end; {------------------------------------------------------------------------------- TWinControl GetControlOrigin Result: TPoint Returns the screen coordinate of the topleft coordinate 0,0 of the control area. (The topleft pixel of the control on the screen) Note that this value is the position as stored in the interface and is not always in sync with the LCL. When a control is moved, the LCL sets the bounds to the wanted position and sends a move message to the interface. It is up to the interface to handle moves instantly or queued. -------------------------------------------------------------------------------} function TWinControl.GetControlOrigin: TPoint; var AControl: TWinControl; IntfBounds: TRect; Begin if HandleAllocated then begin // get the interface idea where the client area is on the screen LCLIntf.GetWindowRect(Handle,IntfBounds); Result.X := IntfBounds.Left; Result.Y := IntfBounds.Top; // adjust the result by all bounds, that are not yet sent to the interface AControl:=Self; repeat inc(Result.X,AControl.Left-AControl.FBoundsRealized.Left); inc(Result.Y,AControl.Top-AControl.FBoundsRealized.Top); AControl:=AControl.Parent; until AControl=nil; end else Result:=inherited GetControlOrigin; end; {------------------------------------------------------------------------------ function TWinControl.GetChildsRect(Scrolled: boolean): TRect; Returns the Client rectangle relative to the controls left, top. If Scrolled is true, the rectangle is moved by the current scrolling values (for an example see TScrollingWincontrol). ------------------------------------------------------------------------------} function TWinControl.GetChildsRect(Scrolled: boolean): TRect; var ScrolledOffset: TPoint; begin if HandleAllocated then begin LCLIntf.GetClientBounds(Handle,Result); if Scrolled then begin ScrolledOffset:=GetClientScrollOffset; inc(Result.Left,ScrolledOffset.X); inc(Result.Top,ScrolledOffset.Y); inc(Result.Right,ScrolledOffset.X); inc(Result.Bottom,ScrolledOffset.Y); end; end else Result:=inherited GetChildsRect(Scrolled); end; {------------------------------------------------------------------------------} { TWinControl ReCreateWnd } {------------------------------------------------------------------------------} procedure TWinControl.ReCreateWnd; var IsFocused: Boolean; begin if csDestroying in ComponentState then Exit; if not HandleAllocated then begin // since the interface should only call us, the handle is always created DebugLN('WARNING: obsolete call to RecreateWnd for %s', [ClassName]); end; IsFocused := Focused; DestroyHandle; UpdateControlState; if IsFocused and HandleAllocated then LCLIntf.SetFocus(FHandle); end; {------------------------------------------------------------------------------} { TWinControl SetBorderStyle } {------------------------------------------------------------------------------} procedure TWinControl.SetBorderStyle(NewStyle: TBorderStyle); begin FBorderStyle := NewStyle; if HandleAllocated then TWSWinControlClass(WidgetSetClass).SetBorderStyle(Self, NewStyle); end; {------------------------------------------------------------------------------} { TWinControl SetBorderWidth } {------------------------------------------------------------------------------} Procedure TWinControl.SetBorderWidth(value : TBorderWidth); Begin //TODO: SETBORDERWIDTH - Not sure if anything more is needed here FBorderWidth := Value; Invalidate; InvalidatePreferredSize; end; Procedure TWinControl.SetZOrder(Topmost: Boolean); const WindowPos: array[Boolean] of Word = (HWND_BOTTOM, HWND_TOP); var i: integer; begin if FParent <> nil then begin if TopMost then i := FParent.FWinControls.Count - 1 else i := 0; if FParent.FControls <> nil then inc(i, FParent.FControls.Count); SetZOrderPosition(i); end else if HandleAllocated then begin SetWindowPos(Handle, WindowPos[TopMost], 0, 0, 0, 0, SWP_NOMOVE + SWP_NOSIZE); end; end; {------------------------------------------------------------------------------ TControl SetTabOrder ------------------------------------------------------------------------------} procedure TWinControl.SetTabOrder(NewTabOrder: TTabOrder); begin if csLoading in ComponentState then FTabOrder := NewTabOrder else UpdateTabOrder(NewTabOrder); end; procedure TWinControl.SetTabStop(NewTabStop: Boolean); begin if FTabStop = NewTabStop then exit; FTabStop := NewTabStop; UpdateTabOrder(FTabOrder); end; {------------------------------------------------------------------------------ TControl UpdateTabOrder ------------------------------------------------------------------------------} procedure TWinControl.UpdateTabOrder(NewTabOrder: TTabOrder); var Count: Integer; begin if FParent <> nil then begin FTabOrder := GetTabOrder; Count := FParent.FTabList.Count; if NewTabOrder < 0 then NewTabOrder := Count; if FTabOrder = -1 then Inc(Count); if NewTabOrder >= Count then NewTabOrder := Count - 1; if NewTabOrder <> FTabOrder then begin if FTabOrder <> - 1 then FParent.FTabList.Delete(FTabOrder); if NewTabOrder <> -1 then begin FParent.FTabList.Insert(NewTabOrder, Self); FTabOrder := NewTabOrder; end; end; end; end; {------------------------------------------------------------------------------- procedure TWinControl.SendMoveSizeMessages(SizeChanged, PosChanged: boolean); Send Move and Size messages through the LCL message paths. This simulates the VCL behaviour and has no real effect. -------------------------------------------------------------------------------} procedure TWinControl.SendMoveSizeMessages(SizeChanged, PosChanged: boolean); var SizeMsg : TLMSize; MoveMsg : TLMMove; //Flags: UINT; begin if (not HandleAllocated) or ((not SizeChanged) and (not PosChanged)) then exit; Perform(LM_WindowposChanged, 0, 0); if SizeChanged then begin with SizeMsg do begin Msg:= LM_SIZE; SizeType:= 6; // force realign Width:= FWidth; Height:= FHeight; {$IFDEF CHECK_POSITION} if AnsiCompareText(ClassName,'TScrollBar')=0 then DebugLn(' [TControl.SendMoveSizeMessages] ',Name,':',ClassName,' SizeMsg Width=',Width,' Height=',Height); {$ENDIF} end; WindowProc(TLMessage(SizeMsg)); end; if PosChanged then begin with MoveMsg do begin Msg:= LM_MOVE; MoveType:= 1; XPos:= FLeft; YPos:= FTop; {$IFDEF CHECK_POSITION} if AnsiCompareText(ClassName,'TScrollBar')=0 then DebugLn(' [TControl.SendMoveSizeMessages] ',Name,':',ClassName,' MoveMsg XPos=',XPos,' YPos=',YPos); {$ENDIF} end; WindowProc(TLMessage(MoveMsg)); end; end; {------------------------------------------------------------------------------} { TWinControl UpdateShowing } {------------------------------------------------------------------------------} procedure TWinControl.UpdateShowing; var bShow: Boolean; n: Integer; ok: boolean; begin bShow := HandleObjectShouldBeVisible; if bShow then begin if not HandleAllocated then CreateHandle; if FWinControls <> nil then begin for n := 0 to FWinControls.Count - 1 do TWinControl(FWinControls[n]).UpdateShowing; end; end; if HandleAllocated then begin //DebugLn('TWinControl.UpdateShowing A ',Name,':',ClassName,' FShowing=',FShowing,' bShow=',bShow); if (not FShowingValid) or (FShowing <> bShow) then begin FShowing := bShow; FShowingValid := true; ok:=false; try Perform(CM_SHOWINGCHANGED, 0, 0); ok:=true; finally if not ok then FShowing := not bShow; end; end; end; end; procedure TWinControl.Update; begin if HandleAllocated then UpdateWindow(Handle); end; {------------------------------------------------------------------------------- procedure TWinControl.SetZOrderPosition(NewPosition: Integer); -------------------------------------------------------------------------------} procedure TWinControl.SetZOrderPosition(NewPosition: Integer); var OldPosition, Count: Integer; Pos: HWND; begin if FParent <> nil then begin if FParent.FControls <> nil then Dec(NewPosition, FParent.FControls.Count); OldPosition := FParent.FWinControls.IndexOf(Self); if OldPosition >= 0 then begin Count := FParent.FWinControls.Count; if NewPosition < 0 then NewPosition := 0; if NewPosition >= Count then NewPosition := Count - 1; if NewPosition = OldPosition then exit; FParent.FWinControls.Move(OldPosition,NewPosition); end else begin // MG: What if OldPosition<0 ? debugln('WARNING: TWinControl.SetZOrderPosition OldPosition<0'); end; if HandleAllocated then begin // In LCL, position 0 is "at the back" and position // Count - 1 is "in front", so the order is reversed from win32 api POV. // In SetWindowPos, you should give the handle of the window // (hWndInsertAfter) of which you want to become just in front of your // window (hWnd). // Keep in mind, that FWinControls is already reordered. if NewPosition <= 0 then Pos := HWND_BOTTOM else if NewPosition >= FParent.FWinControls.Count - 1 then Pos := HWND_TOP else Pos := TWinControl(FParent.FWinControls[NewPosition + 1]).Handle; SetWindowPos(Handle, Pos, 0, 0, 0, 0, SWP_NOMOVE + SWP_NOSIZE); end; end; end; {------------------------------------------------------------------------------} { TWinControl Focused } {------------------------------------------------------------------------------} Function TWinControl.Focused: Boolean; Begin Result := CanTab and (HandleAllocated and (FindOwnerControl(GetFocus)=Self)); end; function TWinControl.PerformTab(ForwardTab: boolean): boolean; Function GetHighestParent(TopControl : TControl) : TWinControl; begin Result := nil; If TopControl = nil then exit; If (TopControl.Parent=nil) then begin if TopControl is TWinControl then Result := TWinControl(TopControl) end else Result := GetHighestParent(TopControl.Parent); end; var I : Integer; List : TList; FirstFocus, OldFocus, NewFocus : TWinControl; TopLevel : TWinControl; begin NewFocus := nil; OldFocus := nil; TopLevel := GetHighestParent(Self); If TopLevel = nil then exit; try List := TList.Create; TopLevel.GetTabOrderList(List); FirstFocus := nil; For I := 0 to List.Count - 1 do If List[I] <> nil then begin If I = 0 then FirstFocus := TWinControl(List[I]); If TWinControl(List[I]).Focused then begin OldFocus := TWinControl(List[I]); Break; end; end; Finally List.Free; end; if OldFocus<>nil then NewFocus := TopLevel.FindNextControl(OldFocus,ForwardTab,True,False); //if NewFocus<>nil then // DebugLn('TControl.PerformTab A ',Name,':',ClassName,' NewFocus=',NewFocus.Name,':',NewFocus.ClassName) //else // DebugLn('TControl.PerformTab B ',Name,':',ClassName,' NewFocus=nil'); If (NewFocus = nil) then NewFocus:=FirstFocus; If NewFocus = OldFocus then begin Result := True; exit; end; if NewFocus<>nil then begin NewFocus.SetFocus; Result := NewFocus.Focused; end else Result:=true; end; {------------------------------------------------------------------------------ TWinControl FindChildControl Find next control (Tab control or Child control). Like VCL the CurControl parameter is ignored. ------------------------------------------------------------------------------} procedure TWinControl.SelectNext(CurControl: TWinControl; GoForward, CheckTabStop: Boolean); begin CurControl := FindNextControl(CurControl, GoForward, CheckTabStop, not CheckTabStop); if CurControl <> nil then CurControl.SetFocus; end; {------------------------------------------------------------------------------ TWinControl FindChildControl ------------------------------------------------------------------------------} function TWinControl.FindChildControl(const ControlName: string): TControl; var I: Integer; begin Result := nil; if FWinControls <> nil then for I := 0 to FWinControls.Count - 1 do if CompareText(TWinControl(FWinControls[I]).Name, ControlName) = 0 then begin Result := TControl(FWinControls[I]); Exit; end; end; procedure TWinControl.FlipChildren(AllLevels: Boolean); var i: Integer; FlipControls: TList; CurControl: TControl; begin if ControlCount = 0 then exit; FlipControls := TList.Create; DisableAlign; try // Collect all controls with Align Right and Left for i := 0 to ControlCount - 1 do begin CurControl:=Controls[i]; if CurControl.Align in [alLeft,alRight] then FlipControls.Add(CurControl); end; // flip the rest DoFlipChildren; // reverse Right and Left alignments while FlipControls.Count > 0 do begin CurControl:=TControl(FlipControls[FlipControls.Count-1]); if CurControl.Align=alLeft then CurControl.Align:=alRight else if CurControl.Align=alRight then CurControl.Align:=alLeft; FlipControls.Delete(FlipControls.Count - 1); end; finally FlipControls.Free; EnableAlign; end; // flip recursively if AllLevels then begin for i := 0 to ControlCount - 1 do begin CurControl:=Controls[i]; if CurControl is TWinControl then TWinControl(CurControl).FlipChildren(true); end; end; end; {------------------------------------------------------------------------------} { TWinControl FindNextControl } {------------------------------------------------------------------------------} function TWinControl.FindNextControl(CurrentControl: TWinControl; GoForward, CheckTabStop, CheckParent: boolean): TWinControl; var List : TList; Next : TWinControl; I, J : Longint; begin Try Result := nil; List := TList.Create; GetTabOrderList(List); If List.Count > 0 then begin J := List.IndexOf(CurrentControl); if J<0 then exit; ///DebugLn('TWinControl.FindNextControl A ',CurrentControl.Name,' ',dbgs(J), // ' '+dbgs(GoForward)+','+dbgs(CheckTabStop)+','+dbgs(CheckParent)+','+dbgs(OnlyWinControls)); I := J; Repeat If GoForward then begin Inc(I); if I>=List.Count then I:=0; end else begin Dec(I); if I<0 then I:=List.Count-1; end; if I=J then exit; Next := TWinControl(List[I]); {DebugLn('TWinControl.FindNextControl B ',Next.Name,' ',dbgs(I), +' ChckTabStop='+dbgs(CheckTabStop)+' TabStop='+dbgs(Next.TabStop) +' ChckParent='+dbgs(CheckParent)+' Parent=Self='+dbgs(Next.Parent = Self) +' Enabled='+dbgs(Next.Enabled)+' OnlyWinC='+dbgs(OnlyWinControls) +' TestTab='+dbgs(((Not CheckTabStop) or Next.TabStop)) +' TestPar='+dbgs(((not CheckParent) or (Next.Parent = Self))) +' TestEnVi='+dbgs(Next.Enabled and Next.IsVisible) +' TestWinC='+dbgs((not OnlyWinControls) or (Next is TWinControl)) );} If (((not CheckTabStop) or Next.TabStop) and ((not CheckParent) or (Next.Parent = Self))) and (Next.Enabled and Next.IsVisible) then Result := Next; until (Result <> nil); //DebugLn('TWinControl.FindNextControl END ',Result.Name,':',Result.ClassName,' ',dbgs(I)); end; finally List.Free; end; end; procedure TWinControl.FixupTabList; var Count, I, J: Integer; List: TList; Control: TWinControl; begin if FWinControls <> nil then begin List := TList.Create; try Count := FWinControls.Count; List.Count := Count; for I := 0 to Count - 1 do begin Control := TWinControl(FWinControls[I]); J := Control.FTabOrder; if (J >= 0) and (J < Count) then List[J] := Control; end; for I := 0 to Count - 1 do begin Control := TWinControl(List[I]); if Control <> nil then Control.UpdateTabOrder(TTabOrder(I)); end; finally List.Free; end; end; end; {------------------------------------------------------------------------------ TWinControl GetTabOrderList ------------------------------------------------------------------------------} Procedure TWinControl.GetTabOrderList(List: TList); var I : Integer; lWinControl : TWinControl; begin If FTabList <> nil then For I := 0 to FTabList.Count - 1 do begin lWinControl := TWinControl(FTabList[I]); If lWinControl.CanTab and lWinControl.TabStop then List.Add(lWinControl); lWinControl.GetTabOrderList(List); end; end; {------------------------------------------------------------------------------} { TWinControl IsControlMouseMsg } {------------------------------------------------------------------------------} function TWinControl.IsControlMouseMsg(var TheMessage: TLMMouse) : Boolean; var Control : TControl; P : TPoint; ClientBounds: TRect; begin if FindOwnerControl(GetCapture) = Self then begin Control := nil; if (CaptureControl <> nil) and (CaptureControl.Parent = Self) then Control := CaptureControl; end else begin Control := ControlAtPos(SmallPointToPoint(TheMessage.Pos),False,True,False); end; Result := False; if Control <> nil then begin // map mouse coordinates to control P.X := TheMessage.XPos - Control.Left; P.Y := TheMessage.YPos - Control.Top; if (Control is TWinControl) and TWinControl(Control).HandleAllocated then begin // map coordinates to client area of control LCLIntf.GetClientBounds(TWinControl(Control).Handle,ClientBounds); dec(P.X,ClientBounds.Left); dec(P.Y,ClientBounds.Top); {$IFDEF VerboseMouseBugfix} DebugLn('TWinControl.IsControlMouseMsg ',Name,' -> ',Control.Name, ' MsgPos=',TheMessage.Pos.X,',',TheMessage.Pos.Y, ' Control=',Control.Left,',',Control.Top, ' ClientBounds=',ClientBounds.Left,',',ClientBounds.Top, ' Scrolled=',GetClientScrollOffset.X,',',GetClientScrollOffset.Y, ' P=',P.X,',',P.Y ); {$ENDIF} end; Control.Perform(TheMessage.Msg, WParam(TheMessage.Keys), LParam(PointToSmallPoint(P))); Result := True; end; end; procedure TWinControl.FontChanged(Sender: TObject); begin if HandleAllocated and ([csLoading,csDestroying]*ComponentState=[]) then begin TWSWinControlClass(WidgetSetClass).SetFont(Self, Font); Exclude(FWinControlFlags,wcfFontChanged); //NotifyControls(CM_ ...); end else Include(FWinControlFlags,wcfFontChanged); end; procedure TWinControl.SetColor(Value: TColor); begin if Value=Color then exit; inherited SetColor(Value); if FBrush <> nil then FBrush.Color := Color; if HandleAllocated and ([csLoading,csDestroying]*ComponentState=[]) then begin TWSWinControlClass(WidgetSetClass).SetColor(Self); Exclude(FWinControlFlags,wcfColorChanged); NotifyControls(CM_PARENTCOLORCHANGED); end else Include(FWinControlFlags,wcfColorChanged); end; procedure TWinControl.PaintHandler(var TheMessage: TLMPaint); function ControlMustBeClipped(AControl: TControl): boolean; begin with AControl do Result:=(Visible or ((csDesigning in ComponentState) and not (csNoDesignVisible in ControlStyle))) and (csOpaque in ControlStyle); end; var I, Clip, SaveIndex: Integer; DC: HDC; PS: TPaintStruct; //defined in LCLIntf.pp ControlsNeedsClipping: boolean; CurControl: TControl; begin //DebugLn('[TWinControl.PaintHandler] ',Name,':',ClassName,' DC=',HexStr(TheMessage.DC,8)); if (csDestroying in ComponentState) or (not HandleAllocated) then exit; {$IFDEF VerboseDsgnPaintMsg} if csDesigning in ComponentState then DebugLn('TWinControl.PaintHandler A ',Name,':',ClassName); {$ENDIF} Assert(False, Format('Trace:> [TWinControl.PaintHandler] %s --> Msg.DC: 0x%x', [ClassName, TheMessage.DC])); DC := TheMessage.DC; if DC = 0 then DC := BeginPaint(Handle, PS); try // check if child controls need clipping //DebugLn('[TWinControl.PaintHandler] ',DbgSName(Self),' B'); ControlsNeedsClipping:=false; if FControls<>nil then for I := 0 to FControls.Count - 1 do if ControlMustBeClipped(TControl(FControls[I])) then begin ControlsNeedsClipping:=true; break; end; // exclude child controls and send new paint message if not ControlsNeedsClipping then begin //DebugLn('[TWinControl.PaintHandler] ',DbgSName(Self),' no clipping ...'); PaintWindow(DC) end else begin SaveIndex := SaveDC(DC); Clip := SimpleRegion; for I := 0 to FControls.Count - 1 do begin CurControl:=TControl(FControls[I]); if ControlMustBeClipped(CurControl) then with CurControl do begin //DebugLn('TWinControl.PaintHandler Exclude Child ',DbgSName(Self),' Control=',DbgSName(CurControl),'(',dbgs(CurControl.BoundsRect),')'); Clip := ExcludeClipRect(DC, Left, Top, Left + Width, Top + Height); if Clip = NullRegion then Break; end; end; //DebugLn('[TWinControl.PaintHandler] ',DbgSName(Self),' with clipping ...'); if Clip <> NullRegion then PaintWindow(DC); RestoreDC(DC, SaveIndex); end; // paint controls //DebugLn('[TWinControl.PaintHandler] ',DbgSName(Self),' PaintControls ...'); PaintControls(DC, nil); finally if TheMessage.DC = 0 then EndPaint(Handle, PS); end; Assert(False, Format('Trace:< [TWinControl.PaintHandler] %s', [ClassName])); //DebugLn('[TWinControl.PaintHandler] END ',Name,':',ClassName,' DC=',HexStr(Message.DC,8)); end; procedure TWinControl.PaintControls(DC: HDC; First: TControl); var I, Count, SaveIndex: Integer; // FrameBrush: HBRUSH; TempControl : TControl; {off $Define VerboseControlDCOrigin} {$IFDEF VerboseControlDCOrigin} P: TPoint; {$ENDIF} begin //DebugLn('[TWinControl.PaintControls] ',Name,':',ClassName,' DC=',HexStr(DC,8)); if (csDestroying in ComponentState) or ((DC=0) and (not HandleAllocated)) then exit; {$IFDEF VerboseDsgnPaintMsg} if csDesigning in ComponentState then DebugLn('TWinControl.PaintControls A ',Name,':',ClassName); {$ENDIF} // Controls that are not TWinControl, have no handle of their own, and so // they are repainted as part of the parent: if FControls <> nil then begin I := 0; if First <> nil then begin I := FControls.IndexOf(First); if I < 0 then I := 0; end; Count := FControls.Count; while I < Count do begin TempControl := TControl(FControls.Items[I]); //DebugLn('TWinControl.PaintControls B Self=',Self.Name,':',Self.ClassName,' Control=',TempControl.Name,':',TempControl.ClassName,' ',TempControl.Left,',',TempControl.Top,',',TempControl.Width,',',TempControl.Height); with TempControl do if (Visible or ((csDesigning in ComponentState) and not (csNoDesignVisible in ControlStyle))) and RectVisible(DC, Rect(Left, Top, Left + Width, Top + Height)) then begin if csPaintCopy in Self.ControlState then Include(FControlState, csPaintCopy); SaveIndex := SaveDC(DC); MoveWindowOrg(DC, Left, Top); {$IFDEF VerboseControlDCOrigin} DebugLn('TWinControl.PaintControls B Self=',DbgSName(Self),' Control=',DbgSName(TempControl),' ',dbgs(Left),',',dbgs(Top),',',dbgs(Width),',',dbgs(Height)); {$ENDIF} IntersectClipRect(DC, 0, 0, Width, Height); {$IFDEF VerboseControlDCOrigin} DebugLn('TWinControl.PaintControls C'); P:=Point(-1,-1); GetWindowOrgEx(DC,@P); debugln(' DCOrigin=',dbgs(P)); {$ENDIF} Perform(LM_PAINT, WParam(DC), 0); {$IFDEF VerboseControlDCOrigin} DebugLn('TWinControl.PaintControls D TempControl=',DbgSName(TempControl)); {$ENDIF} RestoreDC(DC, SaveIndex); Exclude(FControlState, csPaintCopy); end; Inc(I); end; end; // draw specials for the wincontrols: if FWinControls <> nil then for I := 0 to FWinControls.Count - 1 do with TWinControl(FWinControls.Items[I]) do if FCtl3D and (csFramed in ControlStyle) and (Visible or ((csDesigning in ComponentState) and not (csNoDesignVisible in ControlStyle))) then begin //TODO: CreateSolidBrush and FrameRect {FrameBrush := CreateSolidBrush(clBtnShadow); FrameRect(DC, Rect(Left - 1, Top - 1, Left + Width, Top + Height), FrameBrush); DeleteObject(FrameBrush); FrameBrush := CreateSolidBrush(clBtnHighlight); FrameRect(DC, Rect(Left, Top, Left + Width + 1, Top + Height + 1), FrameBrush); DeleteObject(FrameBrush); } end; //DebugLn('[TWinControl.PaintControls] END ',Name,':',ClassName,' DC=',HexStr(DC,8)); end; procedure TWinControl.PaintWindow(DC: HDC); var Message: TLMessage; begin //DebugLn('[TWinControl.PaintWindow] ',Name,':',Classname,' DC=',HexStr(DC,8)); if (csDestroying in ComponentState) or ((DC=0) and (not HandleAllocated)) then exit; {$IFDEF VerboseDsgnPaintMsg} if csDesigning in ComponentState then DebugLn('TWinControl.PaintWindow A ',Name,':',ClassName); {$ENDIF} Message.Msg := LM_PAINT; Message.WParam := WParam(DC); Message.LParam := 0; Message.Result := 0; DefaultHandler(Message); end; procedure TWinControl.CreateBrush; begin if FBrush<>nil then exit; FBrush:=TBrush.Create; FBrush.Color:=Color; // ToDo: ParentColor end; {------------------------------------------------------------------------------ procedure TWinControl.EraseBackground; ------------------------------------------------------------------------------} procedure TWinControl.EraseBackground(DC: HDC); var ARect: TRect; begin if DC=0 then exit; ARect:=Rect(0,0,Width,Height); FillRect(DC,ARect,Brush.Handle) end; {------------------------------------------------------------------------------ function TWinControl.IntfUTF8KeyPress(var UTF8Key: TUTF8Char; RepeatCount: integer): boolean; Called by the interface after the navigation and specials keys are handled (e.g. after KeyDown). ------------------------------------------------------------------------------} function TWinControl.IntfUTF8KeyPress(var UTF8Key: TUTF8Char; RepeatCount: integer): boolean; begin Result:=(RepeatCount>0) and DoUTF8KeyPress(UTF8Key) end; {------------------------------------------------------------------------------ TWinControl ControlAtPos Params: const Pos : TPoint AllowDisabled: Boolean Results: TControl Searches a child (not grand child) control, which client area contains Pos. Pos is relative to the ClientOrigin. ------------------------------------------------------------------------------} Function TWinControl.ControlAtPos(const Pos : TPoint; AllowDisabled : Boolean): TControl; Begin Result := ControlAtPos(Pos,AllowDisabled,false,true); end; {------------------------------------------------------------------------------ TWinControl ControlAtPos Params: const Pos : TPoint AllowDisabled, AllowWinControls: Boolean Results: TControl Searches a child (not grand child) control, which client area contains Pos. Pos is relative to the ClientOrigin. ------------------------------------------------------------------------------} Function TWinControl.ControlAtPos(const Pos : TPoint; AllowDisabled, AllowWinControls: Boolean): TControl; begin Result := ControlAtPos(Pos,AllowDisabled,AllowWinControls,true); end; {------------------------------------------------------------------------------ TWinControl ControlAtPos Params: const Pos : TPoint AllowDisabled, AllowWinControls: Boolean Results: TControl Searches a child (not grand child) control, which contains Pos. Pos is relative to the ClientOrigin. If AllowDisabled is true it will also search in disabled controls. If AllowWinControls is true it will also search in the child wincontrols. If OnlyClientAreas is true then only the client areas are compared. ------------------------------------------------------------------------------} function TWinControl.ControlAtPos(const Pos: TPoint; AllowDisabled, AllowWinControls, OnlyClientAreas: Boolean): TControl; var I: Integer; P: TPoint; LControl: TControl; ClientBounds: TRect; function GetControlAtPos(AControl: TControl): Boolean; var ControlPos: TPoint; ControlClientBounds: TRect; begin with AControl do begin // MG: Delphi checks for PtInRect(ClientRect,P). But the client area is // not always at 0,0, so I guess this is a bug in the VCL. ControlPos:=Point(P.X-Left,P.Y-Top); Result:=(ControlPos.X>=0) and (ControlPos.Y>=0) and (ControlPos.X 0) ) ); {$IFDEF VerboseMouseBugfix} DebugLn('GetControlAtPos ',Name,':',ClassName, ' Pos=',Pos.X,',',Pos.Y, ' P=',P.X,',',P.Y, ' ClientBounds=',ClientBounds.Left,',',ClientBounds.Top,',',ClientBounds.Right,',',ClientBounds.Bottom, ' OnlyCl=',OnlyClientAreas, ' Result=',Result); {$ENDIF} if Result then LControl := AControl; end; end; var ScrolledOffset: TPoint; begin // check if Pos in visible client area ClientBounds:=GetClientRect; if not PtInRect(ClientBounds,Pos) then begin Result:=nil; exit; end; // map Pos to logical client area ScrolledOffset:=GetClientScrollOffset; P:=Point(Pos.X+ScrolledOffset.X,Pos.Y+ScrolledOffset.Y); LControl := nil; // check wincontrols if AllowWinControls and (FWinControls <> nil) then for I := FWinControls.Count - 1 downto 0 do if GetControlAtPos(TControl(FWinControls[I])) then Break; // check controls if (FControls <> nil) and (LControl = nil) then for I := FControls.Count - 1 downto 0 do if GetControlAtPos(TControl(FControls[I])) then Break; Result := LControl; end; {------------------------------------------------------------------------------- function TWinControl.GetControlIndex(AControl: TControl): integer; -------------------------------------------------------------------------------} function TWinControl.GetControlIndex(AControl: TControl): integer; begin if FControls<>nil then Result:=FControls.IndexOf(AControl) else Result:=-1; if (Result<0) and (FWinControls<>nil) then begin Result:=FWinControls.IndexOf(AControl); if (Result>=0) and (FControls<>nil) then inc(Result,FControls.Count); end; end; {------------------------------------------------------------------------------- function TWinControl.GetControlIndex(AControl: TControl): integer; -------------------------------------------------------------------------------} procedure TWinControl.SetControlIndex(AControl: TControl; NewIndex: integer); begin if AControl=nil then exit; AControl.SetZOrderPosition(NewIndex); end; function TWinControl.ControlByName(const ControlName: string): TControl; var i: Integer; begin if FControls<>nil then for i:=0 to FControls.Count-1 do begin Result:=TControl(FControls[i]); if CompareText(Result.Name,ControlName)=0 then exit; end; if FWinControls<>nil then for i:=0 to FWinControls.Count-1 do begin Result:=TControl(FWinControls[i]); if CompareText(Result.Name,ControlName)=0 then exit; end; Result:=nil; end; {------------------------------------------------------------------------------} { TWinControl DestroyHandle } {------------------------------------------------------------------------------} procedure TWinControl.DestroyHandle; var i: integer; AWinControl: TWinControl; begin if not HandleAllocated then begin DebugLn('Warning: TWinControl.DestroyHandle ',Name,':',ClassName,' Handle not Allocated'); //RaiseGDBException(''); end; // First destroy all children handles if FWinControls <> nil then begin for i:= 0 to FWinControls.Count - 1 do begin //DebugLn(' i=',i); //DebugLn(' ',TWinControl(FWinControls[i]).Name,':',TWinControl(FWinControls[i]).ClassName); AWinControl:=TWinControl(FWinControls[i]); if AWinControl.HandleAllocated then AWinControl.DestroyHandle; end; end; DestroyWnd; end; {------------------------------------------------------------------------------ TWinControl WndPRoc ------------------------------------------------------------------------------} Procedure TWinControl.WndProc(Var Message: TLMessage); Var Form: TCustomForm; Begin // Assert(False, Format('Trace:[TWinControl.WndPRoc] %s(%s) --> Message = %d', [ClassName, Name, Message.Msg])); case Message.Msg of LM_SETFOCUS: begin Assert(False, Format('Trace:[TWinControl.WndPRoc] %s --> LM_SETFOCUS', [ClassName])); Form := GetParentForm(Self); {$IFDEF VerboseFocus} DebugLn('TWinControl.WndProc LM_SetFocus ',Name,':',ClassName); {$ENDIF} if (Form <> nil) and not Form.SetFocusedControl(Self) then Exit; Message.Result:=0; end; LM_KILLFOCUS: begin Assert(False, Format('Trace:[TWinControl.WndPRoc] %s --> _KILLFOCUS', [ClassName])); if csFocusing in ControlState then begin {$IFDEF VerboseFocus} DebugLn('TWinControl.WndProc LM_KillFocus during focusing ',Name,':',ClassName); {$ENDIF} Exit; end; Message.Result:=0; end; LM_NCHITTEST: begin inherited WndPRoc(Message); if (Message.Result = HTTRANSPARENT) and (ControlAtPos(ScreenToClient(SmallPointToPoint(TLMNCHitTest(Message).Pos)), False) <> nil) then Message.Result := HTCLIENT; Exit; end; LM_MOUSEFIRST..LM_MOUSELAST, LM_LBUTTONTRIPLECLK, LM_LBUTTONQUADCLK, LM_MBUTTONTRIPLECLK, LM_MBUTTONQUADCLK, LM_RBUTTONTRIPLECLK, LM_RBUTTONQUADCLK: begin {$IFDEF VerboseMouseBugfix} DebugLn('TWinControl.WndPRoc A ',Name,':',ClassName); {$ENDIF} if IsControlMouseMSG(TLMMouse(Message)) then Exit; {$IFDEF VerboseMouseBugfix} DebugLn('TWinControl.WndPRoc B ',Name,':',ClassName); {$ENDIF} end; LM_KEYFIRST..LM_KEYLAST: if Dragging then Exit; LM_CANCELMODE: if (FindOwnerControl(GetCapture) = Self) and (CaptureControl <> nil) and (CaptureControl.Parent = Self) then CaptureControl.Perform(LM_CANCELMODE,0,0); else end; inherited WndProc(Message); end; {------------------------------------------------------------------------------ procedure TWinControl.DoAddDockClient(Client: TControl; const ARect: TRect); Default method for addind a dock client. Just become the new parent. ------------------------------------------------------------------------------} procedure TWinControl.DoAddDockClient(Client: TControl; const ARect: TRect); begin Client.Parent := Self; end; {------------------------------------------------------------------------------ procedure TWinControl.DockOver(Source: TDragDockObject; X, Y: Integer; State: TDragState; var Accept: Boolean); Called to check whether this control allows docking and where. ------------------------------------------------------------------------------} procedure TWinControl.DockOver(Source: TDragDockObject; X, Y: Integer; State: TDragState; var Accept: Boolean); begin PositionDockRect(Source); DoDockOver(Source,X,Y,State,Accept); end; {------------------------------------------------------------------------------ procedure TWinControl.DoDockOver(Source: TDragDockObject; X, Y: Integer; State: TDragState; var Accept: Boolean); ------------------------------------------------------------------------------} procedure TWinControl.DoDockOver(Source: TDragDockObject; X, Y: Integer; State: TDragState; var Accept: Boolean); begin if Assigned(FOnDockOver) then FOnDockOver(Self,Source,X,Y,State,Accept); end; {------------------------------------------------------------------------------ procedure TWinControl.DoRemoveDockClient(Client: TControl); Called to remove client from dock list. This method exists for descendent overrides. ------------------------------------------------------------------------------} procedure TWinControl.DoRemoveDockClient(Client: TControl); begin // empty (this method exists for descendent overrides) end; {------------------------------------------------------------------------------ function TWinControl.DoUnDock(NewTarget: TWinControl; Client: TControl ): Boolean; ------------------------------------------------------------------------------} function TWinControl.DoUnDock(NewTarget: TWinControl; Client: TControl ): Boolean; begin DebugLn('TWinControl.DoUnDock ',Name,' NewTarget=',DbgSName(NewTarget),' Client=',DbgSName(Client)); if Assigned(FOnUnDock) then begin Result := True; FOnUnDock(Self,Client,NewTarget,Result); if not Result then exit; end; // ToDo Dock //Result := (Perform(CM_UNDOCKCLIENT, Integer(NewTarget), Integer(Client)) = 0); end; {------------------------------------------------------------------------------ procedure TWinControl.GetSiteInfo(Client: TControl; var InfluenceRect: TRect; MousePos: TPoint; var CanDock: Boolean); ------------------------------------------------------------------------------} procedure TWinControl.GetSiteInfo(Client: TControl; var InfluenceRect: TRect; MousePos: TPoint; var CanDock: Boolean); begin GetWindowRect(Handle,InfluenceRect); // VCL inflates the docking rectangle. Do we need this too? Why? //InflateRect(InfluenceRect,?,?); if Assigned(FOnGetSiteInfo) then FOnGetSiteInfo(Self,Client,InfluenceRect,MousePos,CanDock); end; {------------------------------------------------------------------------------ procedure TWinControl.ReloadDockedControl(const AControlName: string; var AControl: TControl); ------------------------------------------------------------------------------} procedure TWinControl.ReloadDockedControl(const AControlName: string; var AControl: TControl); begin AControl := Owner.FindComponent(AControlName) as TControl; end; {------------------------------------------------------------------------------ function TWinControl.CreateDockManager: TDockManager; ------------------------------------------------------------------------------} function TWinControl.CreateDockManager: TDockManager; begin if (FDockManager = nil) and DockSite and UseDockManager then Result := DefaultDockTreeClass.Create(Self) else Result := FDockManager; end; {------------------------------------------------------------------------------ procedure TWinControl.SetUseDockManager(const AValue: Boolean); ------------------------------------------------------------------------------} procedure TWinControl.SetUseDockManager(const AValue: Boolean); begin if FUseDockManager=AValue then exit; FUseDockManager:=AValue; if FUseDockManager and ([csDesigning,csDestroying]*ComponentState=[]) then FDockManager := CreateDockManager; end; {------------------------------------------------------------------------------ Procedure TWinControl.MainWndProc(Var Message : TLMessage); The message handler of this wincontrol. Only needed by controls, which needs features not yet supported by the LCL. ------------------------------------------------------------------------------} Procedure TWinControl.MainWndProc(Var Msg: TLMessage); Begin Assert(False, Format('Trace:[TWinControl.MainWndPRoc] %s(%s) --> Message = %d', [ClassName, Name, Msg.Msg])); end; {------------------------------------------------------------------------------ TWinControl SetFocus ------------------------------------------------------------------------------} procedure TWinControl.SetFocus; var Form : TCustomForm; begin {$IFDEF VerboseFocus} DebugLn('[TWinControl.SetFocus] ',Name,':',ClassName,' Visible=',dbgs(Visible),' HandleAllocated=',dbgs(HandleAllocated)); {$ENDIF} Form := GetParentForm(Self); if Form <> nil then Form.FocusControl(Self) else if Visible and HandleAllocated then LCLIntf.SetFocus(Handle); end; {------------------------------------------------------------------------------ TWinControl SetParentCtl3D ------------------------------------------------------------------------------} Procedure TWinControl.SetParentCtl3D(value : Boolean); Begin if FParentCtl3D <> Value then Begin FParentCtl3D := Value; if FParent <> nil then Begin //Sendmessage to do something? End; end; end; procedure TWinControl.AssignTo(Dest: TPersistent); begin inherited AssignTo(Dest); if Dest is TCustomAction then TCustomAction(Dest).HelpContext:=HelpContext; end; procedure TWinControl.ActionChange(Sender: TObject; CheckDefaults: Boolean); begin inherited ActionChange(Sender,CheckDefaults); if Sender is TCustomAction then with TCustomAction(Sender) do if (not CheckDefaults) or (Self.HelpContext = 0) then Self.HelpContext := HelpContext; end; function TWinControl.GetActionLinkClass: TControlActionLinkClass; begin Result := TWinControlActionLink; end; {------------------------------------------------------------------------------ TWinControl KeyDown ------------------------------------------------------------------------------} Procedure TWinControl.KeyDown(var Key: Word; shift : TShiftState); Begin if Assigned(FOnKeyDown) then FOnKeyDown(Self, Key, Shift); end; {------------------------------------------------------------------------------ TWinControl KeyDownBeforeInterface ------------------------------------------------------------------------------} procedure TWinControl.KeyDownBeforeInterface(var Key: Word; Shift: TShiftState ); begin KeyDown(Key,Shift); end; {------------------------------------------------------------------------------ TWinControl KeyDownAfterInterface ------------------------------------------------------------------------------} procedure TWinControl.KeyDownAfterInterface(var Key: Word; Shift: TShiftState); begin end; {------------------------------------------------------------------------------ TWinControl KeyPress ------------------------------------------------------------------------------} Procedure TWinControl.KeyPress(var Key: char); begin if Assigned(FOnKeyPress) then FOnKeyPress(Self, Key); end; {------------------------------------------------------------------------------ TWinControl KeyPress ------------------------------------------------------------------------------} procedure TWinControl.UTF8KeyPress(var UTF8Key: TUTF8Char); begin if Assigned(FOnUTF8KeyPress) then FOnUTF8KeyPress(Self, UTF8Key); end; {------------------------------------------------------------------------------ TWinControl KeyUp ------------------------------------------------------------------------------} Procedure TWinControl.KeyUp(var Key: Word; shift : TShiftState); begin if Assigned(FOnKeyUp) then FOnKeyUp(Self, Key, Shift); end; {------------------------------------------------------------------------------ Method: TWinControl.WantsKey Params: CharCode - the key to inspect whether it is wanted Returns: true if key is wanted before the interface handles it. Checks if control wants the passed key to handle before the interface. ------------------------------------------------------------------------------} function TWinControl.WantsKeyBeforeInterface(Key: word; Shift: TShiftState ): boolean; var lWantKeys: dword; { values for lWantKeys 0 - if not wanted 1 - if wanted, but is special (arrow) 2 - if wanted, but is special (tab) 4 - if wanted, but is special (all) 8 - if wanted, is normal key } begin // For Delphi compatibility we send a LM_GETDLGCODE message to the control // asking if it wants to handle the key. // We don't define a default handler for LM_GETDLGCODE, // so the default return is 0. // Note: Contrary to Delphi/win32api, we don't know what keys are special, // different widgetsets may have different sets of special keys; lWantKeys := Perform(LM_GETDLGCODE, 0, 0); if (lWantKeys and DLGC_WANTALLKEYS) <> 0 then begin lWantKeys := DLGC_WANTALLKEYS; end else begin case Key of VK_TAB: lWantKeys := lWantKeys and DLGC_WANTTAB; VK_UP, VK_LEFT, VK_DOWN, VK_RIGHT: lWantKeys := lWantKeys and DLGC_WANTARROWS; end; end; Result := (lWantKeys<>0); end; {------------------------------------------------------------------------------ TWinControl DoKeyDown returns true if handled ------------------------------------------------------------------------------} function TWinControl.DoKeyDown(Var Message: TLMKey): Boolean; var F: TCustomForm; ShiftState: TShiftState; AParent: TWinControl; begin //debugln('TWinControl.DoKeyDown ',Name,':',ClassName,' '); Result:=true; with Message do begin if CharCode = VK_UNKNOWN then Exit; ShiftState := KeyDataToShiftState(KeyData); // let application handle the key if Application<>nil then Application.NotifyKeyDownBeforeHandler(Self, CharCode, ShiftState); if CharCode = VK_UNKNOWN then Exit; // let each parent form with keypreview handle the key AParent:=Parent; while (AParent<>nil) do begin if (AParent is TCustomForm) then begin F := TCustomForm(AParent); if (F.KeyPreview) and (F.DoKeyDown(Message)) then Exit; end; AParent:=AParent.Parent; end; if CharCode = VK_UNKNOWN then Exit; ShiftState := KeyDataToShiftState(KeyData); // let drag object handle the key if Dragging and (DragObject<>nil) then begin DragObject.KeyDown(CharCode, ShiftState); if CharCode = VK_UNKNOWN then Exit; end; // let user handle the key if not (csNoStdEvents in ControlStyle) then begin KeyDownBeforeInterface(CharCode, ShiftState); if CharCode = VK_UNKNOWN then Exit; end; end; Result := False; end; {------------------------------------------------------------------------------ TWinControl DoRemainginKeyDown Returns True if key handled ------------------------------------------------------------------------------} function TWinControl.DoRemainginKeyDown(var Message: TLMKeyDown): Boolean; var ShiftState: TShiftState; begin Result:=true; ShiftState := KeyDataToShiftState(Message.KeyData); // handle LCL special keys ControlKeyDown(Message.CharCode,ShiftState); if Message.CharCode=VK_UNKNOWN then exit; //DebugLn('TWinControl.WMKeyDown ',Name,':',ClassName); if not (csNoStdEvents in ControlStyle) then begin KeyDownAfterInterface(Message.CharCode, ShiftState); if Message.CharCode=VK_UNKNOWN then exit; // Note: Message.CharCode can now be different or even 0 end; // let application handle the remaining key if Application<>nil then Application.NotifyKeyDownHandler(Self, Message.CharCode, ShiftState); if Message.CharCode = VK_UNKNOWN then Exit; Result := False; end; {------------------------------------------------------------------------------ TWinControl DoKeyPress Returns True if key handled ------------------------------------------------------------------------------} Function TWinControl.DoKeyPress(Var Message : TLMKey): Boolean; var F: TCustomForm; C: char; AParent: TWinControl; begin Result := True; // let each parent form with keypreview handle the key AParent:=Parent; while (AParent<>nil) do begin if (AParent is TCustomForm) then begin F := TCustomForm(AParent); if (F.KeyPreview) and (F.DoKeyPress(Message)) then Exit; end; AParent:=AParent.Parent; end; if not (csNoStdEvents in ControlStyle) then with Message do begin C := char(CharCode); KeyPress(C); CharCode := Ord(C); if Char(CharCode) = #0 then Exit; end; Result := False; End; {------------------------------------------------------------------------------ TWinControl DoUTF8KeyPress Returns True if key handled ------------------------------------------------------------------------------} function TWinControl.DoUTF8KeyPress(var UTF8Key: TUTF8Char): boolean; var AParent: TWinControl; F: TCustomForm; begin Result:=true; // let each parent form with keypreview handle the key AParent:=Parent; while (AParent<>nil) do begin if (AParent is TCustomForm) then begin F := TCustomForm(AParent); if (F.KeyPreview) and (F.DoUTF8KeyPress(UTF8Key)) then Exit; end; AParent:=AParent.Parent; end; if not (csNoStdEvents in ControlStyle) then begin UTF8KeyPress(UTF8Key); if UTF8Key='' then exit; end; Result := False; end; {------------------------------------------------------------------------------ TWinControl DoKeyUp Returns True if key handled ------------------------------------------------------------------------------} Function TWinControl.DoKeyUp(Var Message : TLMKey): Boolean; var F: TCustomForm; ShiftState: TShiftState; AParent: TWinControl; begin Result := True; // let each parent form with keypreview handle the key AParent:=Parent; while (AParent<>nil) do begin if (AParent is TCustomForm) then begin F := TCustomForm(AParent); if (F.KeyPreview) and (F.DoKeyUp(Message)) then Exit; end; AParent:=AParent.Parent; end; with Message do begin ShiftState := KeyDataToShiftState(KeyData); if Dragging and (DragObject<>nil) then DragObject.KeyUp(CharCode, ShiftState); if not (csNoStdEvents in ControlStyle) then begin KeyUp(CharCode, ShiftState); if CharCode = 0 then Exit; end; // TODO //if (CharCode = VK_APPS) and not (ssAlt in ShiftState) then // CheckMenuPopup(SmallPoint(0, 0)); end; Result := False; end; {------------------------------------------------------------------------------ TWinControl ControlKeyDown ------------------------------------------------------------------------------} procedure TWinControl.ControlKeyDown(var Key: Word; Shift: TShiftState); begin Application.ControlKeyDown(Self,Key,Shift); end; {------------------------------------------------------------------------------ TWinControl CreateParams ------------------------------------------------------------------------------} procedure TWinControl.CreateParams(var Params : TCreateParams); begin FillChar(Params, SizeOf(Params),0); with Params do begin Caption := PChar(FCaption); Style := WS_CHILD or WS_CLIPSIBLINGS; if (Parent <> nil) then WndParent := Parent.Handle; end; end; {------------------------------------------------------------------------------} { TWinControl Invalidate } {------------------------------------------------------------------------------} Procedure TWinControl.Invalidate; Begin if HandleAllocated and ([csDestroying,csLoading]*ComponentState=[]) then TWSWinControlClass(WidgetSetClass).Invalidate(Self); end; {------------------------------------------------------------------------------} { TWinControl Repaint } {------------------------------------------------------------------------------} Procedure TWinControl.Repaint; Begin if (not HandleAllocated) or (csDestroying in ComponentState) then exit; {$IFDEF VerboseDsgnPaintMsg} if csDesigning in ComponentState then DebugLn('TWinControl.Repaint A ',Name,':',ClassName); {$ENDIF} { TODO: check what to do with LM_PAINT message, neither gtk nor win32 interface responded to it } //CNSendMessage(LM_PAINT, Self, nil); // Invalidate; // Update; end; {------------------------------------------------------------------------------} { TWinControl DoMouseWheel "Event Handler" } {------------------------------------------------------------------------------} function TWinControl.DoMouseWheel(Shift: TShiftState; WheelDelta: Integer; MousePos: TPoint): Boolean; begin Result := False; if Assigned(FOnMouseWheel) then FOnMouseWheel(Self, Shift, WheelDelta, MousePos, Result); if not Result then begin if WheelDelta < 0 then Result := DoMouseWheelDown(Shift, MousePos) else Result := DoMouseWheelUp(Shift, MousePos); end; end; {------------------------------------------------------------------------------} { TWinControl DoMouseWheelDown "Event Handler" } {------------------------------------------------------------------------------} function TWinControl.DoMouseWheelDown(Shift: TShiftState; MousePos: TPoint): Boolean; begin Result := False; if Assigned(FOnMouseWheelDown) then FOnMouseWheelDown(Self, Shift, MousePos, Result); end; {------------------------------------------------------------------------------} { TWinControl DoMouseWheelUp "Event Handler" } {------------------------------------------------------------------------------} function TWinControl.DoMouseWheelUp(Shift: TShiftState; MousePos: TPoint): Boolean; begin Result := False; if Assigned(FOnMouseWheelUp) then FOnMouseWheelUp(Self, Shift, MousePos, Result); end; {------------------------------------------------------------------------------} { TWinControl Insert } {------------------------------------------------------------------------------} procedure TWinControl.Insert(AControl : TControl); begin Insert(AControl,ControlCount); End; {------------------------------------------------------------------------------ procedure TWinControl.Insert(AControl: TControl; Index: integer); ------------------------------------------------------------------------------} procedure TWinControl.Insert(AControl: TControl; Index: integer); begin if AControl = nil then exit; if AControl = Self then raise EInvalidOperation.Create(rsAControlCanNotHaveItselfAsParent); if AControl is TWinControl then begin if (FControls<>nil) then dec(Index,FControls.Count); if (FWinControls<>nil) and (Indexnil) and (Index[]) or (not HandleAllocated) then begin Include(FWinControlFlags,wcfReAlignNeeded); exit; end; //DebugLn('TWinControl.ReAlign ',Name,':',ClassName); AlignControl(nil); Exclude(FWinControlFlags,wcfReAlignNeeded); end; {------------------------------------------------------------------------------} { TWinControl Remove } {------------------------------------------------------------------------------} Procedure TWinControl.Remove(AControl : TControl); begin if AControl <> nil then begin Assert(False, Format('trace:[TWinControl.Remove] %s(%S) --> Remove: %s(%s)', [ClassName, Name, AControl.ClassName, AControl.Name])); if AControl is TWinControl then begin ListRemove(FTabList, AControl); ListRemove(FWInControls, ACOntrol); end else Listremove(FControls, AControl); AControl.FParent := Nil; end; End; {------------------------------------------------------------------------------} { TWinControl RemoveFocus } {------------------------------------------------------------------------------} Procedure TWinControl.RemoveFocus(Removing : Boolean); //TODO: FINISH TWINCONTROL.REMOVEFOCUS var Form: TCustomForm; begin Form := GetParentForm(Self); if Form <> nil then Form.DefocusControl(Self, Removing); end; {------------------------------------------------------------------------------} { TWinControl UpdateControlState } {------------------------------------------------------------------------------} procedure TWinControl.UpdateControlState; var AWinControl: TWinControl; begin AWinControl:= Self; { If any of the parent is not visible, exit } while AWinControl.Parent <> nil do begin AWinControl:= AWinControl.Parent; if (not AWinControl.Showing) or (not AWinControl.HandleAllocated) then Exit; end; if ((AWinControl is TCustomForm) and (AWinControl.Parent=nil)) or (AWinControl.FParentWindow <> 0) then UpdateShowing; end; {------------------------------------------------------------------------------} { TWinControl InsertControl } {------------------------------------------------------------------------------} Procedure TWinControl.InsertControl(AControl: TControl); Begin InsertControl(AControl,ControlCount); End; procedure TWinControl.InsertControl(AControl: TControl; Index: integer); begin AControl.ValidateContainer(Self); Perform(CM_CONTROLLISTCHANGE, WParam(AControl), LParam(True)); Insert(AControl,Index); if not (csReadingState in AControl.ControlState) then begin AControl.Perform(CM_PARENTCOLORCHANGED, 0, 0); AControl.Perform(CM_PARENTFONTCHANGED, 0, 0); AControl.Perform(CM_PARENTSHOWHINTCHANGED, 0, 0); AControl.Perform(CM_PARENTBIDIMODECHANGED, 0, 0); if AControl is TWinControl then begin AControl.Perform(CM_PARENTCTL3DCHANGED, 0, 0); UpdateControlState; end else if HandleAllocated then AControl.Invalidate; //DebugLn('TWinControl.InsertControl ',Name,':',ClassName); end; AControl.RequestAlign; Perform(CM_CONTROLCHANGE, WParam(AControl), LParam(True)); end; {------------------------------------------------------------------------------ TWinControl removeControl ------------------------------------------------------------------------------} Procedure TWinControl.RemoveControl(AControl: TControl); var AWinControl: TWinControl; Begin Perform(CM_CONTROLCHANGE, WParam(AControl), LParam(False)); if AControl is TWinControl then begin AWinControl:=TWinControl(AControl); AWinControl.RemoveFocus(True); if AWinControl.HandleAllocated then AWinControl.DestroyHandle; end else if HandleAllocated then AControl.InvalidateControl(AControl.Visible, False, True); Remove(AControl); // Perform(CM_CONTROLLISTCHANGE, WParam(AControl), LParam(False)); Realign; End; {------------------------------------------------------------------------------ TWinControl AlignControl ------------------------------------------------------------------------------} procedure TWinControl.AlignControl(AControl: TControl); var ARect: TRect; i: Integer; ChildControl: TControl; begin //if csDesigning in ComponentState then begin // DbgOut('TWinControl.AlignControl ',Name,':',ClassName); // if AControl<>nil then DebugLn(' AControl=',AControl.Name,':',AControl.ClassName) else DebugLn(' AControl=nil');; //end; if csDestroying in ComponentState then exit; if FAlignLevel <> 0 then begin Include(FControlState, csAlignmentNeeded); exit; end; // check if all childs have finished loading for i:=0 to ControlCount-1 do begin ChildControl:=Controls[i]; if csLoading in ChildControl.ComponentState then begin // child is loading // -> mark the child, that itself and its brothers needs realigning // (it will do this, when it has finished loading) Include(ChildControl.FControlFlags,cfRequestAlignNeeded); exit; end; end; DisableAlign; try ARect:= GetClientRect; AlignControls(AControl, ARect); finally Exclude(FControlState, csAlignmentNeeded); EnableAlign; end; End; {------------------------------------------------------------------------------ Method: TWinControl.ContainsControl Params: Control: the control to be checked Returns: Self is a (super)parent of Control Checks if Control is a child of Self ------------------------------------------------------------------------------} function TWinControl.ContainsControl(Control: TControl): Boolean; begin while (Control <> nil) and (Control <> Self) do Control := Control.Parent; Result := Control = Self; end; {------------------------------------------------------------------------------ TWinControl GetBorderStyle ------------------------------------------------------------------------------} function TWinControl.GetBorderStyle: TBorderStyle; begin Result := TBorderStyle(FBorderStyle); end; {------------------------------------------------------------------------------ TWinControl GetBrush ------------------------------------------------------------------------------} function TWinControl.GetBrush: TBrush; begin if FBrush=nil then CreateBrush; Result:=FBrush; end; {------------------------------------------------------------------------------} { TWinControl GetControl } {------------------------------------------------------------------------------} function TWinControl.GetControl(const Index: Integer): TControl; var N: Integer; begin if FControls <> nil then N := FControls.Count else N := 0; if Index < N then Result := TControl(FControls[Index]) else Result := TControl(FWinControls[Index - N]); end; {------------------------------------------------------------------------------} { TWinControl GetControlCount } {------------------------------------------------------------------------------} function TWinControl.GetControlCount: Integer; begin Result := 0; if FControls <> nil then Inc(Result, FControls.Count); if FWinControls <> nil then Inc(Result, FWinControls.Count); end; function TWinControl.GetDockClientCount: Integer; begin if FDockClients<>nil then Result := FDockClients.Count else Result := 0; end; function TWinControl.GetDockClients(Index: Integer): TControl; begin if FDockClients<>nil then Result := TControl(FDockClients[Index]) else Result := nil; end; {------------------------------------------------------------------------------} { TWinControl GetHandle } {------------------------------------------------------------------------------} function TWinControl.GetHandle: HWND; begin if not HandleAllocated then //Assert(False, Format('Trace:[TWinControl.GetHandle] %s(%s)', [ClassNAme, Name])) ; HandleNeeded; Result := FHandle; end; {------------------------------------------------------------------------------ TWinControl SetHandle Params: NewHandle Returns: Nothing -------------------------------------------------------------------------------} procedure TWincontrol.SetHandle(NewHandle: HWND); begin //if (NewHandle=0) and (AnsiCompareText(ClassName,'TPAGE')=0) then // RaiseGDBException('TWincontrol.SetHandle'); FHandle:=NewHandle; InvalidatePreferredSize; end; {------------------------------------------------------------------------------ Method: TWinControl.Create Params: None Returns: Nothing Contructor for the class. ------------------------------------------------------------------------------} constructor TWinControl.Create(TheOwner : TComponent); begin // do not set borderstyle, as tcustomform needs to set it before calling // inherited, to have it set before handle is created via streaming // use property that bsNone is zero //FBorderStyle := bsNone; inherited Create(TheOwner); FCompStyle := csWinControl; FChildSizing:=TControlChildSizing.Create(Self); FChildSizing.OnChange:=@DoChildSizingChange; FBrush := nil; // Brush will be created on demand. Only few controls need it. FParentCtl3D:=true; FTabOrder := -1; FTabStop := False; FTabList := TList.Create; end; {------------------------------------------------------------------------------} { TWinControl CreateParented } {------------------------------------------------------------------------------} constructor TWinControl.CreateParented(ParentWindow: hwnd); begin FParentWindow := ParentWindow; inherited Create(nil); end; {------------------------------------------------------------------------------ TWinControl CreateParentedControl ------------------------------------------------------------------------------} class function TWinControl.CreateParentedControl(ParentWindow: hwnd): TWinControl; begin // ToDo Result:=nil; end; {------------------------------------------------------------------------------ TWinControl Hide ------------------------------------------------------------------------------} procedure TWinControl.Hide; begin Visible := False; end; {------------------------------------------------------------------------------ Method: TWinControl.Destroy Params: None Returns: Nothing Destructor for the class. ------------------------------------------------------------------------------} destructor TWinControl.Destroy; var n: Integer; Control: TControl; begin //DebugLn('[TWinControl.Destroy] A ',Name,':',ClassName); // prevent parent to try to focus a to be destroyed control if Parent <> nil then RemoveFocus(true); if HandleAllocated then DestroyHandle; //DebugLn('[TWinControl.Destroy] B ',Name,':',ClassName); //for n:=0 to ComponentCount-1 do // DebugLn(' n=',n,' ',Components[n].ClassName); n := ControlCount; while n > 0 do begin Control := Controls[n - 1]; //DebugLn('[TWinControl.Destroy] C ',Name,':',ClassName,' ',Control.Name,':',Control.ClassName); Remove(Control); // don't free the control just set parent to nil // controls are freed by the owner //Control.Free; Control.Parent := nil; n := ControlCount; end; FreeThenNil(FBrush); FreeThenNil(FChildSizing); FreeThenNil(FDockClients); FreeThenNil(FTabList); //DebugLn('[TWinControl.Destroy] D ',Name,':',ClassName); inherited Destroy; //DebugLn('[TWinControl.Destroy] END ',Name,':',ClassName); end; {------------------------------------------------------------------------------ Method: TWinControl.DoEnter Params: none Returns: Nothing Call user's callback for OnEnter. ------------------------------------------------------------------------------} procedure TWinControl.DoEnter; begin if Assigned(FOnEnter) then FOnEnter(Self); end; {------------------------------------------------------------------------------ Method: TWinControl.DoExit Params: none Returns: Nothing Call user's callback for OnExit. ------------------------------------------------------------------------------} procedure TWinControl.DoExit; begin if Assigned(FOnExit) then FOnExit(Self); end; {------------------------------------------------------------------------------ procedure TWinControl.DoFlipChildren; Flip children horizontally. That means mirroring the left position. ------------------------------------------------------------------------------} procedure TWinControl.DoFlipChildren; var i: Integer; CurControl: TControl; AWidth: Integer; begin AWidth:=ClientWidth; for i:=0 to ControlCount-1 do begin CurControl:=Controls[i]; CurControl.Left:=AWidth-CurControl.Left-CurControl.Width; end; end; {------------------------------------------------------------------------------ Method: TWinControl.CMEnabledChanged Params: Message Returns: Nothing Called when enabled is changed. Takes action to enable control ------------------------------------------------------------------------------} procedure TWinControl.CMEnabledChanged(var Message: TLMessage); begin if not Enabled and (Parent <> nil) then RemoveFocus(False); if HandleAllocated and not (csDesigning in ComponentState) then begin //if (not Enabled) then debugln('TWinControl.CMEnabledChanged disable ',Name,':',CLassName); EnableWindow(Handle, Enabled); end; end; {------------------------------------------------------------------------------ Method: TWinControl.CMShowHintChanged Params: Message Returns: Nothing Called when showhint is changed. Notifies children ------------------------------------------------------------------------------} procedure TWinControl.CMShowHintChanged(var Message: TLMessage); begin NotifyControls(CM_PARENTSHOWHINTCHANGED); end; {------------------------------------------------------------------------------ Method: TWinControl.WMSetFocus Params: Message Returns: Nothing SetFocus event handler ------------------------------------------------------------------------------} Procedure TWinControl.WMSetFocus(var Message: TLMSetFocus); Begin //DebugLn('TWinControl.WMSetFocus A ',Name,':',ClassName); Assert(False, Format('Trace: %s', [ClassName])); if [csLoading,csDestroying,csDesigning]*ComponentState=[] then begin DoEnter; end; end; {------------------------------------------------------------------------------ Method: TWinControl.LMKillFocus Params: Msg: The message Returns: nothing event handler. ------------------------------------------------------------------------------} procedure TWinControl.WMKillFocus(var Message: TLMKillFocus); begin //DebugLn('TWinControl.WMKillFocus A ',Name,':',ClassName); Assert(False, Format('Trace: %s', [ClassName])); if [csLoading,csDestroying,csDesigning]*ComponentState=[] then begin EditingDone; DoExit; end; end; {------------------------------------------------------------------------------ Method: TWinControl.WMPaint Params: Msg: The paint message Returns: nothing Paint event handler. ------------------------------------------------------------------------------} procedure TWinControl.WMPaint(var Msg: TLMPaint); var DC,MemDC: HDC; {$ifdef BUFFERED_WMPAINT} MemBitmap, OldBitmap : HBITMAP; MemWidth: Integer; MemHeight: Integer; {$ENDIF} PS : TPaintStruct; ClientBoundRect: TRect; begin //DebugLn('[TWinControl.WMPaint] ',Name,':',ClassName,' ',HexStr(Msg.DC,8)); if ([csDestroying,csLoading]*ComponentState<>[]) or (not HandleAllocated) then exit; {$IFDEF VerboseDsgnPaintMsg} if csDesigning in ComponentState then DebugLn('TWinControl.WMPaint A ',Name,':',ClassName); {$ENDIF} Assert(False, Format('Trace:> [TWinControl.WMPaint] %s Msg.DC: 0x%x', [ClassName, Msg.DC])); if (Msg.DC <> 0) then begin if not (csCustomPaint in ControlState) and (ControlCount = 0) then begin DefaultHandler(Msg); end else PaintHandler(Msg); end else begin // NOTE: not every interface uses this part //DebugLn('TWinControl.WMPaint Painting doublebuffered ',Name,':',classname); {$ifdef BUFFERED_WMPAINT} DC := GetDC(0); MemWidth:=Width; MemHeight:=Height; MemBitmap := CreateCompatibleBitmap(DC, MemWidth, MemHeight); ReleaseDC(0, DC); MemDC := CreateCompatibleDC(0); OldBitmap := SelectObject(MemDC, MemBitmap); {$ENDIF} try // Fetch a DC of the whole Handle (including client area) DC := BeginPaint(Handle, PS); if DC=0 then exit; {$ifNdef BUFFERED_WMPAINT} MemDC := DC; {$ENDIF} // erase background Include(FWinControlFlags,wcfEraseBackground); Perform(LM_ERASEBKGND, WParam(MemDC), 0); Exclude(FWinControlFlags,wcfEraseBackground); // create a paint message to paint the child controls. // WMPaint expects the DC origin to be equal to the client origin of its // parent // -> Move the DC Origin to the client origin if not GetClientBounds(Handle,ClientBoundRect) then exit; MoveWindowOrgEx(MemDC,ClientBoundRect.Left,ClientBoundRect.Top); // handle the paint message Msg.DC := MemDC; Perform(LM_PAINT, WParam(MemDC), 0); Msg.DC := 0; // restore the DC origin MoveWindowOrgEx(MemDC,-ClientBoundRect.Left,-ClientBoundRect.Top); {$ifdef BUFFERED_WMPAINT} BitBlt(DC, 0,0, MemWidth, MemHeight, MemDC, 0, 0, SRCCOPY); {$ENDIF} EndPaint(Handle, PS); finally Exclude(FWinControlFlags,wcfEraseBackground); {$ifdef BUFFERED_WMPAINT} SelectObject(MemDC, OldBitmap); DeleteDC(MemDC); DeleteObject(MemBitmap); {$ENDIF} end; end; Assert(False, Format('Trace:< [TWinControl.WMPaint] %s', [ClassName])); //DebugLn('[TWinControl.WMPaint] END ',Name,':',ClassName); end; {------------------------------------------------------------------------------ Method: TWinControl.WMDestroy Params: Msg: The destroy message Returns: nothing event handler. ------------------------------------------------------------------------------} procedure TWinControl.WMDestroy(var Message: TLMDestroy); begin Assert(False, Format('Trace: [TWinControl.LMDestroy] %s', [ClassName])); //DebugLn('TWinControl.WMDestroy ',Name,':',ClassName); // Our widget/window doesn't exist anymore Handle := 0; end; {------------------------------------------------------------------------------ Method: TWinControl.WMMove Params: Msg: The message Returns: nothing event handler. ------------------------------------------------------------------------------} procedure TWinControl.WMMove(var Message: TLMMove); var NewWidth, NewHeight: integer; begin {$IFDEF VerboseSizeMsg} DebugLn('TWinControl.WMMove A ',Name,':',ClassName,' Message=',dbgs(Message.XPos),',',dbgs(Message.YPos), ' BoundsRealized='+dbgs(FBoundsRealized.Left)+','+dbgs(FBoundsRealized.Top), ','+dbgs(FBoundsRealized.Right-FBoundsRealized.Left), 'x'+dbgs(FBoundsRealized.Bottom-FBoundsRealized.Top)); {$ENDIF} NewWidth:=Width; NewHeight:=Height; if Message.MoveType=Move_SourceIsInterface then begin // interface widget has moved // -> update size and realized bounds NewWidth:=FBoundsRealized.Right-FBoundsRealized.Left; NewHeight:=FBoundsRealized.Bottom-FBoundsRealized.Top; if HandleAllocated then GetWindowSize(Handle,NewWidth,NewHeight); FBoundsRealized:=Bounds(Message.XPos,Message.YPos,NewWidth,NewHeight); end; SetBoundsKeepBase(Message.XPos,Message.YPos,NewWidth,NewHeight,Parent<>nil); end; {------------------------------------------------------------------------------ Method: TWinControl.WMSize Params: Message: TLMSize Returns: nothing Event handler for size messages. This is called, whenever width, height, clientwidth or clientheight have changed. If the source of the message is the interface, the new size is stored in FBoundsRealized to avoid sending a size message back to the interface. ------------------------------------------------------------------------------} procedure TWinControl.WMSize(var Message: TLMSize); var NewLeft, NewTop: integer; NewBoundsRealized: TRect; begin {$IFDEF VerboseSizeMsg} DebugLn('TWinControl.WMSize A ',Name,':',ClassName,' Message=',dbgs(Message.Width),',',dbgs(Message.Height), ' BoundsRealized=',dbgs(FBoundsRealized)); {$ENDIF} NewLeft:=Left; NewTop:=Top; if (Message.SizeType and Size_SourceIsInterface)>0 then begin // interface widget has resized // -> update position and realized bounds NewLeft:=FBoundsRealized.Left; NewTop:=FBoundsRealized.Top; if HandleAllocated then GetWindowRelativePosition(Handle,NewLeft,NewTop); //DebugLn('TWinControl.WMSize B ',Name,':',ClassName,' ',NewLeft,',',NewTop); NewBoundsRealized:=Bounds(NewLeft,NewTop,Message.Width,Message.Height); If CompareRect(@NewBoundsRealized,@FBoundsRealized) then exit; FBoundsRealized:=NewBoundsRealized; end; SetBoundsKeepBase(NewLeft,NewTop,Message.Width,Message.Height,Parent<>nil); end; {------------------------------------------------------------------------------ Method: TWinControl.CNKeyDown Params: Msg: The message Returns: nothing event handler. ------------------------------------------------------------------------------} procedure TWinControl.CNKeyDown(var Message: TLMKeyDown); begin //DebugLn('TWinControl.CNKeyDown ',Name,':',ClassName); if not DoKeyDown(Message) then {inherited}; // there is nothing to inherit end; {------------------------------------------------------------------------------ procedure TWinControl.CNSysKeyDown(var Message: TLMKeyDown); ------------------------------------------------------------------------------} procedure TWinControl.CNSysKeyDown(var Message: TLMKeyDown); begin if not DoKeyDown(Message) then {inherited}; // there is nothing to inherit end; {------------------------------------------------------------------------------ procedure TWinControl.CNSysKeyUp(var Message: TLMKeyUp); ------------------------------------------------------------------------------} procedure TWinControl.CNSysKeyUp(var Message: TLMKeyUp); begin end; {------------------------------------------------------------------------------ Method: TWinControl.CNKeyUp Params: Msg: The message Returns: nothing event handler. ------------------------------------------------------------------------------} procedure TWinControl.CNKeyUp(var Message: TLMKeyUp); begin end; {------------------------------------------------------------------------------ Method: TWinControl.CNChar Params: Msg: The message Returns: nothing event handler. CNChar is sent by the interface before it has handled the keypress itself. ------------------------------------------------------------------------------} procedure TWinControl.CNChar(var Message: TLMKeyUp); var c: TUTF8Char; begin //debugln('TWinControl.CNChar A ',DbgSName(Self),' ',dbgs(Message.CharCode),' ',dbgs(IntfSendsUTF8KeyPress)); if not DoKeyPress(Message) then {inherited}; // there is nothing to inherit //debugln('TWinControl.CNChar B ',DbgSName(Self),' ',dbgs(Message.CharCode),' ',dbgs(IntfSendsUTF8KeyPress)); if not IntfSendsUTF8KeyPress then begin // current interface does not (yet) send UTF8 key press notifications // -> emulate if Message.CharCode < %11000000 then begin c:=chr(Message.CharCode); IntfUTF8KeyPress(c,1); if (length(c)<>1) or (c[1]<>chr(Message.CharCode)) then begin // character changed if length(c)=1 then Message.CharCode:=ord(c[1]) else Message.CharCode:=0; end; end; end; end; procedure TWinControl.CNSysChar(var Message: TLMKeyUp); begin if not DoKeyPress(Message) then {inherited}; // there is nothing to inherit end; {------------------------------------------------------------------------------ Method: TWinControl.WMNofity Params: Msg: The message Returns: nothing event handler. ------------------------------------------------------------------------------} procedure TWInControl.WMNotify(var Message: TLMNotify); Begin if not DoControlMsg(Message.NMHdr^.hwndfrom,Message) then exit; //Inherited; end; {------------------------------------------------------------------------------ Method: TWinControl.WMShowWindow Params: Msg: The message Returns: nothing event handler. ------------------------------------------------------------------------------} procedure TWinControl.WMShowWindow(var Message: TLMShowWindow); begin Assert(False, Format('Trace: TODO: [TWinControl.LMShowWindow] %s', [ClassName])); end; {------------------------------------------------------------------------------ Method: TWinControl.WMEnter Params: Msg: The message Returns: nothing event handler. ------------------------------------------------------------------------------} procedure TWinControl.WMEnter(var Message: TLMEnter); begin Assert(False, Format('Trace: TODO: [TWinControl.LMEnter] %s', [ClassName])); end; {------------------------------------------------------------------------------ Method: TWinControl.WMEraseBkgnd Params: Msg: The message Returns: nothing event handler. ------------------------------------------------------------------------------} procedure TWinControl.WMEraseBkgnd(var Message: TLMEraseBkgnd); begin if (Message.DC<>0) and (wcfEraseBackground in FWinControlFlags) then EraseBackground(Message.DC); end; {------------------------------------------------------------------------------ Method: TWinControl.WMExit Params: Msg: The message Returns: nothing event handler. ------------------------------------------------------------------------------} procedure TWinControl.WMExit(var Message: TLMExit); begin Assert(False, Format('Trace: TODO: [TWinControl.LMExit] %s', [ClassName])); end; {------------------------------------------------------------------------------ Method: TWinControl.WMMouseWheel Params: Msg: The message Returns: nothing event handler. ------------------------------------------------------------------------------} procedure TWinControl.WMMouseWheel(var Message: TLMMouseEvent); Var MousePos : TPoint; Shift : TShiftState; begin Assert(False, Format('Trace: [TWinControl.LMMouseWheel] %s', [ClassName])); MousePos.X := Message.X; MousePos.Y := Message.Y; { always the middle button } Shift := [ssMiddle]; DoMouseWheel(Shift, Message.WheelDelta, MousePos); inherited; end; {------------------------------------------------------------------------------ Method: TWinControl.WMChar Params: Msg: The message Returns: nothing event handler. WMChar is sent by the interface after it has handled the keypress by itself. ------------------------------------------------------------------------------} procedure TWinControl.WMChar(var Message: TLMChar); begin Assert(False, Format('Trace:[TWinControl.WMChar] %s', [ClassName])); end; procedure TWinControl.WMSysChar(var Message: TLMChar); begin end; {------------------------------------------------------------------------------ Method: TWinControl.WMKeyDown Params: Msg: The message Returns: nothing Event handler for keys not handled by the interface ------------------------------------------------------------------------------} Procedure TWinControl.WMKeyDown(Var Message: TLMKeyDown); begin DoRemainginKeyDown(Message); end; procedure TWinControl.WMSysKeyDown(var Message: TLMKeyDown); begin DoRemainginKeyDown(Message); end; {------------------------------------------------------------------------------ procedure TWinControl.WMSysKeyUp(var Message: TLMKeyUp); ------------------------------------------------------------------------------} procedure TWinControl.WMSysKeyUp(var Message: TLMKeyUp); begin if not DoKeyUp(Message) then {inherited}; // there is nothing to inherit end; {------------------------------------------------------------------------------ Method: TWinControl.WMKeyUp Params: Msg: The message Returns: nothing event handler. ------------------------------------------------------------------------------} Procedure TWinControl.WMKeyUp(Var Message: TLMKeyUp); Begin if not DoKeyUp(Message) then {inherited}; // there is nothing to inherit end; {------------------------------------------------------------------------------ Function: TWinControl.HandleAllocated Params: None Returns: True is handle is allocated Checks if a handle is allocated. I.E. if the control is mapped ------------------------------------------------------------------------------} function TWinControl.HandleAllocated : Boolean; begin HandleAllocated := (FHandle <> 0); end; {------------------------------------------------------------------------------ Method: TWinControl.CreateHandle Params: None Returns: Nothing Creates the handle ( = object) if not already done. ------------------------------------------------------------------------------} procedure TWinControl.CreateHandle; begin if (not HandleAllocated) then CreateWnd; end; {------------------------------------------------------------------------------ Method: TWinControl.CreateWnd Params: None Returns: Nothing Creates the interface object and assigns the handle ------------------------------------------------------------------------------} procedure TWinControl.CreateWnd; var Params: TCreateParams; n: Integer; i: Integer; { procedure WriteClientRect(const Prefix: string); var r: TRect; begin LCLIntf.GetClientRect(Handle,r); if csDesigning in ComponentState then DebugLn('WriteClientRect ',Prefix,' ',Name,':',ClassName,' r=',r.Right,',',r.Bottom); end;} begin //DebugLn('[TWinControl.CreateWnd] START ',Name,':',Classname); if (csDestroying in ComponentState) then exit; if wcfCreatingChildHandles in FWinControlFlags then begin DebugLn('[WARNING] Recursive call to CreateWnd for ',DbgSName(Self)); Exit; end; try Include(FWinControlFlags,wcfCreatingChildHandles); Include(FWinControlFlags,wcfCreatingHandle); try CreateParams(Params); with Params do begin if (WndParent = 0) and (Style and WS_CHILD <> 0) then RaiseGDBException('TWinControl.CreateWnd: no parent '+Name+':'+ClassName); Assert((parent <> nil) or (WndParent = 0), 'TODO: find parent if parent=nil and WndParent <> 0'); end; FHandle := TWSWinControlClass(WidgetSetClass).CreateHandle(Self, Params); if not HandleAllocated then RaiseGDBException('Handle creation failed creating '+DbgSName(Self)); Constraints.UpdateInterfaceConstraints; InvalidatePreferredSize; TWSWinControlClass(WidgetSetClass).ConstraintsChange(Self); FWinControlFlags:=FWinControlFlags-[wcfColorChanged,wcfFontChanged]; finally Exclude(FWinControlFlags,wcfCreatingHandle); end; //WriteClientRect('A'); if Parent <> nil then AddControl; //WriteClientRect('B'); InitializeWnd; //DebugLn('[TWinControl.CreateWnd] ',Name,':',ClassName,' ',Left,',',Top,',',Width,',',Height); //WriteClientRect('C'); if FWinControls <> nil then begin for n := 0 to FWinControls.Count - 1 do with TWinControl(FWinControls.Items[n]) do if Visible then HandleNeeded; end; ChildHandlesCreated; finally Exclude(FWinControlFlags,wcfCreatingChildHandles); end; // size this control {$IFDEF EnablePreferredSize} AdjustSize; if FControls<>nil then for i:=0 to FControls.Count-1 do TControl(FControls[i]).DoAutoSize; {$ENDIF} // realign childs ReAlign; //DebugLn('[TWinControl.CreateWnd] END ',Name,':',Classname); //WriteClientRect('D'); end; {------------------------------------------------------------------------------ procedure TWinControl.CreateComponent(TheOwner : TComponent); ------------------------------------------------------------------------------} (* procedure TWinControl.CreateComponent(TheOwner : TComponent); procedure RaiseError(const Msg: string); begin RaiseGDBException('TWinControl.CreateComponent: '+Name+':'+ClassName+' '+Msg); end; begin if HandleAllocated then RaiseError('Handle already created'); CNSendMessage(LM_CREATE, Self, nil); Constraints.UpdateInterfaceConstraints; FFlags:=FFlags-[wcfColorChanged,wcfFontChanged]; if not HandleAllocated then RaiseError('Handle creation failed'); end; *) {------------------------------------------------------------------------------ TWinControl Destroy Component ------------------------------------------------------------------------------} procedure TWinControl.DestroyComponent; begin if not HandleAllocated then RaiseGDBException('TWinControl.DestroyComponent Handle already destroyed'); TWSWinControlClass(WidgetSetClass).DestroyHandle(Self); InvalidatePreferredSize; end; {------------------------------------------------------------------------------ Method: TWinControl.InitializeWnd Params: none Returns: Nothing Gets called after the window is created, but before the child controls are created. Place cached property code here. ------------------------------------------------------------------------------} procedure TWinControl.InitializeWnd; begin Assert(False, Format('Trace:[TWinControl.InitializeWnd] %s', [ClassName])); // set all cached properties //DebugLn('[TWinControl.InitializeWnd] ',Name,':',ClassName,':', FCaption,' ',Left,',',Top,',',Width,',',Height); //First set the WinControl property. //The win32 interface depends on it to determine where to send call backs. SetProp(Handle,'WinControl',TWinControl(Self)); SetProp(Handle,'Control',TControl(Self)); DoSendBoundsToInterface; TWSWinControlClass(WidgetSetClass).ShowHide(Self); if [wcfColorChanged,wcfFontChanged]*FWinControlFlags<>[] then begin // replace by update style call TWSWinControlClass(WidgetSetClass).SetColor(Self); FWinControlFlags:=FWinControlFlags-[wcfColorChanged,wcfFontChanged]; end; if not (csDesigning in ComponentState) then EnableWindow(Handle, Enabled); // Delay the setting of text until it is completely loaded if not (csLoading in ComponentState) then TWSWinControlClass(WidgetSetClass).SetText(Self, FCaption); // send pending resize event Resize; end; {------------------------------------------------------------------------------ procedure TWinControl.ParentFormHandleInitialized; Called after all childs handles of the ParentForm are created. ------------------------------------------------------------------------------} procedure TWinControl.ParentFormHandleInitialized; var i: Integer; begin inherited ParentFormHandleInitialized; if FWinControls <> nil then begin for i := 0 to FWinControls.Count - 1 do TWinControl(FWinControls.Items[i]).ParentFormHandleInitialized; end; //debugln('TWinControl.ParentFormHandleInitialized A ',DbgSName(Self)); if wcfAutoSizeNeeded in FWinControlFlags then AdjustSize; end; {------------------------------------------------------------------------------ procedure TWinControl.ChildHandlesCreated; Called after all childs handles are created. ------------------------------------------------------------------------------} procedure TWinControl.ChildHandlesCreated; begin Exclude(FWinControlFlags,wcfCreatingChildHandles); end; {------------------------------------------------------------------------------ function TWinControl.ParentHandlesAllocated: boolean; Checks if all Handles of all Parents are created. ------------------------------------------------------------------------------} function TWinControl.ParentHandlesAllocated: boolean; var CurControl: TWinControl; begin Result:=false; CurControl:=Self; while CurControl<>nil do begin if (not CurControl.HandleAllocated) or ([csDestroying,csDestroyingHandle]*ComponentState<>[]) then exit; CurControl:=CurControl.Parent; end; Result:=true; end; {------------------------------------------------------------------------------ procedure TWinControl.Loaded; ------------------------------------------------------------------------------} procedure TWinControl.Loaded; begin inherited Loaded; if HandleAllocated then begin // Set cached caption TWSWinControlClass(WidgetSetClass).SetText(Self, FCaption); if [wcfColorChanged,wcfFontChanged]*FWinControlFlags<>[] then begin TWSWinControlClass(WidgetSetClass).SetColor(Self); FWinControlFlags:=FWinControlFlags-[wcfColorChanged,wcfFontChanged]; end; end; FixupTabList; // autosize this control if wcfAutoSizeNeeded in FWinControlFlags then AdjustSize; RealizeBounds; // align the childs if wcfReAlignNeeded in FWinControlFlags then ReAlign; end; {------------------------------------------------------------------------------ Method: TWinControl.DestroyWnd Params: None Returns: Nothing Destroys the interface object. ------------------------------------------------------------------------------} procedure TWinControl.DestroyWnd; var S: String; begin if HandleAllocated then begin // make sure our text is saved if TWSWinControlClass(WidgetSetClass).GetText(Self, S) then FCaption := S; DestroyComponent; Handle := 0; end; end; {------------------------------------------------------------------------------ Method: TWinControl.HandleNeeded Params: None Returns: Nothing Description of the procedure for the class. ------------------------------------------------------------------------------} procedure TWinControl.HandleNeeded; begin if (not HandleAllocated) and (not (csDestroying in ComponentState)) then begin if Parent = Self then begin Assert(False, Format('Trace:[TWinControl.HandleNeeded] Somebody set Parent := Self in %s. DONT DO THAT !!', [Classname])); end else begin if (Parent <> nil) then begin Parent.HandleNeeded; // has parent triggered us to create our handle ? if HandleAllocated then exit; end; end; CreateHandle; end; end; function TWinControl.BrushCreated: Boolean; begin Result:=FBrush<>nil; end; {------------------------------------------------------------------------------ Method: TWinControl.BeginUpdateBounds Params: None Returns: Nothing increases the BoundsLockCount ------------------------------------------------------------------------------} procedure TWinControl.BeginUpdateBounds; begin inc(FBoundsLockCount); end; {------------------------------------------------------------------------------ Method: TControl.EndUpdateBounds Params: None Returns: Nothing decreases the BoundsLockCount ------------------------------------------------------------------------------} procedure TWinControl.EndUpdateBounds; procedure RaiseTooManyEndUpdates; begin raise Exception.Create('TWinControl.EndUpdateBounds '+DbgSName(Self) +' too many calls.'); end; begin if FBoundsLockCount<=0 then RaiseTooManyEndUpdates; dec(FBoundsLockCount); if FBoundsLockCount=0 then begin SetBounds(Left,Top,Width,Height); end; end; procedure TWinControl.LockRealizeBounds; begin inc(FRealizeBoundsLockCount); end; procedure TWinControl.UnlockRealizeBounds; begin if FRealizeBoundsLockCount<=0 then RaiseGDBException('UnlockRealizeBounds'); dec(FRealizeBoundsLockCount); if FRealizeBoundsLockCount=0 then RealizeBounds; end; {------------------------------------------------------------------------------ procedure TWinControl.DockDrop(DockObject: TDragDockObject; X, Y: Integer); ------------------------------------------------------------------------------} procedure TWinControl.DockDrop(DockObject: TDragDockObject; X, Y: Integer); var DestRect: TRect; ParentForm: TCustomForm; MappedLeftTop: TPoint; begin // get dock destination rectangle and map it to the client area DestRect := DockObject.DockRect; MappedLeftTop:=ScreenToClient(DestRect.TopLeft); OffsetRect(DestRect, DestRect.Left-MappedLeftTop.X,DestRect.Top-MappedLeftTop.Y); DebugLn('TWinControl.DockDrop A ',Name,' DockControl=',DbgSName(DockObject.Control),' DestRect=',dbgs(DestRect)); DisableAlign; try if (not UseDockManager) or (DockManager=nil) then begin // Delphi ignores the DropAlign when no DockManager is available // Why that? DockObject.Control.Align:=DockObject.DropAlign; end; DockObject.Control.Dock(Self, DestRect); if UseDockManager and (DockManager <> nil) then DockManager.InsertControl(DockObject.Control, DockObject.DropAlign, DockObject.DropOnControl); finally EnableAlign; end; ParentForm := GetParentForm(Self); if ParentForm<>nil then ParentForm.BringToFront; if Assigned(FOnDockDrop) then FOnDockDrop(Self, DockObject, X, Y); end; {------------------------------------------------------------------------------ Method: TControl.GetIsResizing Params: None Returns: Nothing decreases the BoundsLockCount ------------------------------------------------------------------------------} function TWinControl.GetIsResizing: boolean; begin Result:=BoundsLockCount>0; end; {------------------------------------------------------------------------------ function TWinControl.GetTabOrder: TTabOrder; ------------------------------------------------------------------------------} function TWinControl.GetTabOrder: TTabOrder; begin if FParent <> nil then Result := TTabOrder(FParent.FTabList.IndexOf(Self)) else Result := FTabOrder; end; {------------------------------------------------------------------------------ function TWinControl.GetVisibleDockClientCount: Integer; ------------------------------------------------------------------------------} function TWinControl.GetVisibleDockClientCount: Integer; var i: integer; begin Result := 0; for i:=FDockClients.Count-1 downto 0 do if TControl(FDockClients[I]).Visible then inc(Result); end; {------------------------------------------------------------------------------ procedure TWinControl.SetChildSizing(const AValue: TControlChildSizing); ------------------------------------------------------------------------------} procedure TWinControl.SetChildSizing(const AValue: TControlChildSizing); begin if (FChildSizing=AValue) or (FChildSizing.IsEqual(AValue)) then exit; FChildSizing.Assign(AValue); end; {------------------------------------------------------------------------------ procedure TWinControl.SetDockSite(const NewDockSite: Boolean); ------------------------------------------------------------------------------} procedure TWinControl.SetDockSite(const NewDockSite: Boolean); begin if FDockSite=NewDockSite then exit; FDockSite := NewDockSite; if not (csDesigning in ComponentState) then begin RegisterDockSite(Self,NewDockSite); if not NewDockSite then begin FreeThenNil(FDockClients); FDockClients := nil; FDockManager := nil; end else begin if FDockClients = nil then FDockClients := TList.Create; FDockManager := CreateDockManager; end; end; end; {------------------------------------------------------------------------------ Method: TWinControl.SetBounds Params: aLeft, aTop, aWidth, aHeight Returns: Nothing Sets the bounds of the control. ------------------------------------------------------------------------------} procedure TWinControl.SetBounds(aLeft, aTop, aWidth, aHeight : integer); procedure CheckDesignBounds; begin if FRealizeBoundsLockCount>0 then exit; // the user changed the bounds if aWidth<0 then raise Exception.Create( 'TWinControl.SetBounds ('+DbgSName(Self)+'): Negative width ' +dbgs(aWidth)+' not allowed.'); if aHeight<0 then raise Exception.Create( 'TWinControl.SetBounds ('+DbgSName(Self)+'): Negative height ' +dbgs(aHeight)+' not allowed.'); end; var NewBounds, OldBounds: TRect; begin {$IFDEF CHECK_POSITION} //if csDesigning in ComponentState then if AnsiCompareText(ClassName,'TScrollBar')=0 then DebugLn('[TWinControl.SetBounds] START ',Name,':',ClassName, ' Old=',Left,',',Top,',',Width,',',Height, ' -> New=',ALeft,',',ATop,',',AWidth,',',AHeight, ' Lock=',BoundsLockCount, ' Realized=',FBoundsRealized.Left,',',FBoundsRealized.Top, ',',FBoundsRealized.Right-FBoundsRealized.Left,',',FBoundsRealized.Bottom-FBoundsRealized.Top ); {$ENDIF} if BoundsLockCount<>0 then exit; OldBounds:=BoundsRect; NewBounds:=Bounds(ALeft, ATop, AWidth, AHeight); if not CompareRect(@NewBounds,@OldBounds) then begin if [csDesigning,csDestroying,csLoading]*ComponentState=[csDesigning] then CheckDesignBounds; // LCL bounds are not up2date -> process new bounds LockRealizeBounds; try {$IFDEF CHECK_POSITION} //if csDesigning in ComponentState then if AnsiCompareText(ClassName,'TScrollBar')=0 then DebugLn('[TWinControl.SetBounds] Set LCL Bounds ',Name,':',ClassName, ' OldBounds=',Left,',',Top,',',Left+Width,',',Top+Height, ' -> New=',ALeft,',',ATop,',',ALeft+AWidth,',',ATop+AHeight); {$ENDIF} inherited SetBounds(ALeft, ATop, AWidth, AHeight); NewBounds:=Bounds(Left, Top, Width, Height); finally UnlockRealizeBounds; end; end; end; {------------------------------------------------------------------------------ procedure TWinControl.CalculatePreferredSize(var PreferredWidth, PreferredHeight: integer); Calculates the default/preferred width and height for a TWinControl, which is used by the LCL autosizing algorithms as default size. Only positive values are valid. Negative or 0 are treated as undefined and the LCL uses other sizes instead. TWinControl overrides this: If there are childs, their total preferred size is calculated. If this value can not be computed (e.g. the childs depend too much on their parent clientrect), then the interface is asked for the preferred size. For example the preferred size of a TButton is the size, where the label fits exactly. This depends heavily on the current theme and widgetset. This value is independent of constraints and siblings, only the inner parts are relevant. ------------------------------------------------------------------------------} procedure TWinControl.CalculatePreferredSize(var PreferredWidth, PreferredHeight: integer); var ChildBounds: TRect; NewClientWidth: Integer; NewClientHeight: Integer; OldClientRect: TRect; begin inherited CalculatePreferredSize(PreferredWidth, PreferredHeight); if HandleAllocated then TWSWinControlClass(WidgetSetClass).GetPreferredSize(Self, PreferredWidth, PreferredHeight); if ControlCount>0 then begin GetChildBounds(ChildBounds,true); NewClientWidth := ChildBounds.Right - ChildBounds.Left; NewClientHeight := ChildBounds.Bottom - ChildBounds.Top; OldClientRect := GetClientRect; {$IFDEF VerboseAutoSize} debugln('TWinControl.CalculatePreferredSize ',DbgSName(Self), ' HandleAllocated=',dbgs(HandleAllocated)+' ChildBounds='+dbgs(ChildBounds), ' Cur='+dbgs(Width)+'x'+dbgs(Height)+ ' Client='+dbgs(OldClientRect.Right)+'x'+dbgs(OldClientRect.Bottom)); {$ENDIF} PreferredWidth:= Max(PreferredWidth,Width-OldClientRect.Right+NewClientWidth); PreferredHeight:= Max(PreferredHeight,Height-OldClientRect.Bottom+NewClientHeight); end; {$IFDEF VerboseAutoSize} debugln('TWinControl.CalculatePreferredSize ',DbgSName(Self), ' HandleAllocated=',dbgs(HandleAllocated), ' Preferred=',dbgs(PreferredWidth),'x',dbgs(PreferredHeight)); {$ENDIF} end; {------------------------------------------------------------------------------ procedure TWinControl.GetChildBounds(var ChildBounds: TRect; WithBorderSpace: boolean); Calculates the bounds of all visible childs in client coordinates. ------------------------------------------------------------------------------} procedure TWinControl.GetChildBounds(var ChildBounds: TRect; WithBorderSpace: boolean); var SpaceAround: TRect; I: Integer; AControl: TControl; ChildWidth,ChildHeight: integer; begin ChildBounds := Rect(High(Integer),High(Integer),0,0); SpaceAround:=Rect(0,0,0,0); For I := 0 to ControlCount - 1 do begin AControl:=Controls[I]; If AControl.Visible then begin AControl.GetPreferredSize(ChildWidth,ChildHeight,false); // TODO: aligned controls if WithBorderSpace then begin AControl.BorderSpacing.GetSpaceAround(SpaceAround); if SpaceAround.LeftChildBounds.Right then begin ChildBounds.Left:=0; ChildBounds.Right:=0; end; if ChildBounds.Top>ChildBounds.Bottom then begin ChildBounds.Top:=0; ChildBounds.Bottom:=0; end; end; {------------------------------------------------------------------------------ Method: TWinControl.RealGetText Params: None Returns: The text Gets the text/caption of a control ------------------------------------------------------------------------------} function TWinControl.RealGetText: TCaption; begin if not HandleAllocated or (csLoading in ComponentState) or (not TWSWinControlClass(WidgetSetClass).GetText(Self, Result)) then Result := inherited RealGetText; end; {------------------------------------------------------------------------------ Method: TWinControl.GetTextLen Params: None Returns: The length of the text Gets the length of the text/caption of a control ------------------------------------------------------------------------------} function TWinControl.GetTextLen: Integer; begin if not HandleAllocated or (csLoading in ComponentState) or not TWSWinControlClass(WidgetSetClass).GetTextLen(Self, Result) then Result := inherited GetTextLen; end; {------------------------------------------------------------------------------ Method: TWinControl.RealSetText Params: Value: the text to be set Returns: Nothing Sets the text/caption of a control ------------------------------------------------------------------------------} procedure TWinControl.RealSetText(const AValue: TCaption); begin if HandleAllocated and (not (csLoading in ComponentState)) then TWSWinControlClass(WidgetSetClass).SetText(Self, AValue); inherited RealSetText(AValue); end; {------------------------------------------------------------------------------ Method: TWinControl.GetDeviceContext Params: WindowHandle: the windowhandle of this control Returns: a Devicecontext Get the devicecontext for this WinControl. ------------------------------------------------------------------------------} function TWinControl.GetDeviceContext(var WindowHandle: HWnd): HDC; begin Result := GetDC(Handle); //DebugLn('[TWinControl.GetDeviceContext] ',ClassName,' DC=',HexStr(Cardinal(Result),8),' Handle=',HexStr(Cardinal(FHandle),8)); if Result = 0 then raise EOutOfResources.CreateFmt(rsErrorCreatingDeviceContext, [Name, ClassName]); WindowHandle := Handle; end; {------------------------------------------------------------------------------ Method: TWinControl.CMVisibleChanged Params: Message : not used Returns: nothing Performs actions when visibility has changed ------------------------------------------------------------------------------} procedure TWinControl.CMVisibleChanged(var TheMessage : TLMessage); begin if not FVisible and (Parent <> nil) then RemoveFocus(False); if not (csDesigning in ComponentState) or (csNoDesignVisible in ControlStyle) then UpdateControlState; end; procedure TWinControl.ControlsAligned; begin end; procedure TWinControl.DoSendBoundsToInterface; var NewBounds: TRect; begin NewBounds:=Bounds(Left, Top, Width, Height); //DebugLn('TWinControl.DoSendBoundsToInterface A ',Name,':',ClassName,' Old=',FBoundsRealized.Left,',',FBoundsRealized.Top,',',FBoundsRealized.Right,',',FBoundsRealized.Bottom, //' New=',NewBounds.Left,',',NewBounds.Top,',',NewBounds.Right,',',NewBounds.Bottom); FBoundsRealized:=NewBounds; TWSWinControlClass(WidgetSetClass).SetBounds(Self, Left, Top, Width, Height); end; procedure TWinControl.RealizeBounds; var NewBounds: TRect; begin NewBounds:=Bounds(Left, Top, Width, Height); if HandleAllocated and (not (csLoading in ComponentState)) and (not CompareRect(@NewBounds,@FBoundsRealized)) then begin // the new bounds were not yet sent to the InterfaceObject -> send them {$IFDEF CHECK_POSITION} //if csDesigning in ComponentState then if AnsiCompareText(ClassName,'TScrollBar')=0 then DebugLn('[TWinControl.RealizeBounds] A ',Name,':',ClassName, ' OldRelBounds=',dbgs(FBoundsRealized), ' -> NewBounds=',dbgs(NewBounds)); {$ENDIF} BeginUpdateBounds; try DoSendBoundsToInterface; finally EndUpdateBounds; end; end; end; {------------------------------------------------------------------------------ Method: TWinControl.CMShowingChanged Params: Message : not used Returns: nothing Shows or hides a control ------------------------------------------------------------------------------} procedure TWinControl.CMShowingChanged(var Message: TLMessage); begin // ToDo: do not send this while loading, send it after loading. if HandleAllocated and ([csDestroying]*ComponentState=[])then TWSWinControlClass(WidgetSetClass).ShowHide(Self); end; {------------------------------------------------------------------------------ Method: TWinControl.ShowControl Params: AControl: Control to show Returns: nothing Askes the parent to show ourself. ------------------------------------------------------------------------------} procedure TWinControl.ShowControl(AControl: TControl); begin if Parent <> nil then Parent.ShowControl(Self); end; { $UNDEF CHECK_POSITION} {$IFDEF ASSERT_IS_ON} {$UNDEF ASSERT_IS_ON} {$C-} {$ENDIF} { ============================================================================= $Log$ Revision 1.304 2005/01/21 19:18:35 mattias implemented option to reduce designer painting Revision 1.303 2005/01/21 11:52:01 micha cleanup focus; fix tabbing Revision 1.302 2005/01/21 10:34:56 mattias implemented streaming of anchorsides Revision 1.301 2005/01/18 18:46:59 mattias improved invert assignment tool by multilines from Andrew Haines Revision 1.300 2005/01/17 17:49:27 mattias fixed constraints for forms under gtk Revision 1.299 2005/01/17 16:42:35 mattias improved TLabel autosizing Revision 1.298 2005/01/16 11:40:10 mattias fixed TGtkWidgetSet.ExtSelectClipRGN for DCOrigin Revision 1.297 2005/01/13 19:52:50 mattias added desgntime check for TControl.Width/Height for negative values Revision 1.296 2005/01/08 14:23:56 micha move taborder and tabstop to twincontrol Revision 1.295 2005/01/04 11:26:26 micha let canfocus imply that setfocus can be called Revision 1.294 2005/01/03 22:44:31 mattias implemented TControl.AnchorSide Revision 1.293 2005/01/01 18:56:47 mattias implemented TTIProgressBar Revision 1.292 2004/12/01 16:17:17 mattias updated fpdoc sceletons for lcl and gtk intf Revision 1.291 2004/11/29 01:12:36 mattias added SysKey messages to gtk intf and LCL Revision 1.290 2004/11/28 01:03:26 mattias do not send OnExit/OnEnter during destroy, design or loading Revision 1.289 2004/11/10 18:23:56 mattias impementing changing a TLabel.Font properties Size, Height, Name, Style - set only at Handle creation time Revision 1.288 2004/11/07 20:44:49 micha handle "re-entrancy" into handleneeded (via parent); fixes crash upon showing file diff dialog Revision 1.287 2004/11/05 22:08:53 mattias implemented auto sizing: child to parent sizing Revision 1.286 2004/11/03 14:18:36 mattias implemented preferred size for controls for theme depending AutoSizing Revision 1.285 2004/10/30 16:24:06 mattias disabled alClient RemainingClientRect adjust Revision 1.284 2004/10/28 17:56:11 mattias implemented Borderspacing Revision 1.283 2004/10/28 09:30:49 mattias implemented borderspacing TWinControl.ChildSizing.Left/Top Revision 1.282 2004/09/24 21:34:14 micha convert LM_CREATE message to interface methods remove SendMsgToInterface, CNSendMessage and related methods remove TWidgetSet.IntSendMessage3; all LCL to interface messages have been converted Revision 1.281 2004/09/24 17:20:43 micha convert LM_SETGEOMETRY message to interface method Revision 1.280 2004/09/21 10:05:26 mattias fixed disable at designtime and bounding TCustomProgressBar position Revision 1.279 2004/09/18 12:43:15 micha convert LM_DESTROY message to interface methods Revision 1.278 2004/09/14 15:48:28 micha convert LM_INVALIDATE message to interface method Revision 1.277 2004/09/12 19:50:35 micha convert LM_SETSIZE message to new interface method Revision 1.276 2004/09/12 13:52:26 micha convert LM_SETFONT to interface method Revision 1.275 2004/09/10 16:28:50 mattias implemented very rudimentary TTabControl Revision 1.274 2004/09/08 20:47:16 micha convert LM_SHOWHIDE message to new intf method TWSWinControl.ShowHide Revision 1.273 2004/09/08 19:09:34 micha convert LM_SETCOLOR message to new intf method TWSWinControl.SetColor Revision 1.272 2004/09/04 22:24:16 mattias added default values for compiler skip options and improved many parts of synedit for UTF8 Revision 1.271 2004/09/02 17:59:59 mattias removed double KeyPress method in synedit Revision 1.270 2004/09/02 17:42:38 mattias fixed changing CNCHar.CharCode when key changed Revision 1.269 2004/09/02 09:16:59 mattias improved double byte char fonts for gtk1, started synedit UTF8 support Revision 1.268 2004/08/30 16:37:58 mattias added OnUTF8KeyPresss Revision 1.267 2004/08/30 10:49:20 mattias fixed focus catch for combobox csDropDownList Revision 1.266 2004/08/26 19:09:34 mattias moved navigation key handling to TApplication and added options for custom navigation Revision 1.265 2004/08/25 22:22:39 mattias added unit info to View menu Revision 1.264 2004/08/18 22:56:11 mattias implemented basic manual docking Revision 1.263 2004/08/18 20:49:02 mattias simple forms can now be child controls Revision 1.262 2004/08/17 19:01:36 mattias gtk intf now ignores size notifications of unrealized widgets Revision 1.261 2004/08/13 19:48:53 mattias added default assembler style for compiler options Revision 1.260 2004/08/13 16:40:47 mazen + TCharater type used to allow UTF8 keyboard with gtk2 Revision 1.259 2004/08/04 07:32:01 micha fix win32 keyhandling, send cn_char Revision 1.258 2004/08/03 09:01:54 mattias LCL now handles for non win32 CN_CHAR Revision 1.257 2004/07/17 15:08:36 mattias fixed tab for TPanel and TPage Revision 1.256 2004/07/16 21:49:00 mattias added RTTI controls Revision 1.255 2004/07/11 17:20:47 marc * Implemented most of TListColoum/Item in the Ws for gtk and win32 Revision 1.254 2004/07/10 18:17:30 mattias added Delphi ToDo support, Application.WndProc, small bugfixes from Colin Revision 1.253 2004/07/07 22:26:58 mattias fixed showing grabers for boundless components Revision 1.252 2004/07/04 11:09:43 mattias fixed IFDEF tool for blocks from Colin Revision 1.251 2004/07/03 14:59:42 mattias fixed keydown geting all keys Revision 1.250 2004/07/03 11:11:08 mattias TGTKListStringList now keeps selection on Put and Move Revision 1.249 2004/07/02 12:23:24 micha fix capture return/escape key if no handler Revision 1.248 2004/07/01 20:42:11 micha implement better ExecuteXXAction design; break dependency on TButton class in TCustomForm Revision 1.247 2004/07/01 17:55:55 mattias LCL navigation keys are now handled after interface handles keys Revision 1.246 2004/07/01 10:08:31 mattias made key handling more flexible Revision 1.245 2004/06/30 11:07:20 micha implement return key clicks default button; escape key clicks cancel button Revision 1.244 2004/06/29 10:23:00 micha fix cnkeydown to check wm_getdlgcode result fix win32 intf to also send wm_keydown of cn_keydown wasn't processed Revision 1.243 2004/06/28 18:57:55 mattias fixed GetControlAtPos for non designing Revision 1.242 2004/06/28 18:54:27 mattias further fixed GetControlAtPos Revision 1.241 2004/06/28 18:47:30 mattias further fixed GetControlAtPos Revision 1.240 2004/06/28 17:41:26 mattias fixed GetControlAtPos Revision 1.239 2004/06/28 17:03:37 mattias clean up Revision 1.238 2004/06/20 21:21:49 micha fix GetVisible to return this control's visibility, instead introduce IsVisible to check for recursive visibility Revision 1.237 2004/06/20 20:25:47 micha fix tabbing to next control to skip invisible notebook pages Revision 1.236 2004/06/01 09:58:35 mattias implemented setting TCustomPage.PageIndex from Andrew Haines Revision 1.235 2004/05/31 13:06:47 marc * Patch from Vincent, moved SetProp(wincontrol) Revision 1.234 2004/05/30 14:02:30 mattias implemented OnChange for TRadioButton, TCheckBox, TToggleBox and some more docking stuff Revision 1.233 2004/05/22 14:35:32 mattias fixed button return key Revision 1.232 2004/05/21 21:58:01 vincents Added if HandleAllocated to SetBorderStyle Revision 1.231 2004/05/21 10:02:59 micha consistent BorderStyle naming Revision 1.230 2004/05/21 09:03:55 micha implement new borderstyle - centralize to twincontrol (protected) - public expose at tcustomcontrol to let interface access it Revision 1.229 2004/05/19 18:41:54 micha trigger repaint on borderwidth change Revision 1.228 2004/05/16 22:43:23 mattias WMSize from interface are now ignored when BoundsRealized the same Revision 1.227 2004/05/11 11:42:27 mattias replaced writeln by debugln Revision 1.226 2004/05/11 10:53:59 mattias replaced writeln by debugln Revision 1.225 2004/05/11 09:49:46 mattias started sending CN_KEYUP Revision 1.224 2004/05/02 17:06:01 marc - Removed TWSWinControl.HasText Revision 1.223 2004/04/28 06:50:21 micha more detailed error message req. by ML Revision 1.222 2004/04/26 10:01:27 mattias fixed TSynEdit.RealGetText Revision 1.221 2004/04/23 11:18:28 mattias fixed unsetting csFocusing Revision 1.220 2004/04/20 23:39:01 marc * Fixed setting of TWincontrol.Text during load Revision 1.219 2004/04/18 23:55:39 marc * Applied patch from Ladislav Michl * Changed the way TControl.Text is resolved * Added setting of text to TWSWinControl Revision 1.218 2004/04/10 17:58:57 mattias implemented mainunit hints for include files Revision 1.217 2004/04/10 17:54:52 micha - added: [win32] mousewheel default handler sends scrollbar messages - fixed: lmsetcursor; partial todo Revision 1.216 2004/04/09 23:52:01 mattias fixed hiding uninitialized controls Revision 1.215 2004/04/04 12:32:21 mattias TWinControl.CanTab now checks for CanFocus Revision 1.214 2004/03/30 20:38:14 mattias fixed interface constraints, fixed syncompletion colors Revision 1.213 2004/03/19 00:03:15 marc * Moved the implementation of (GTK)ButtonCreateHandle to the new (GTK)WSButton class Revision 1.212 2004/03/08 22:36:01 mattias added TWinControl.ParentFormInitializeWnd Revision 1.211 2004/03/07 09:37:20 mattias added workaround for AutoSize in TCustomLabel Revision 1.210 2004/02/28 00:34:35 mattias fixed CreateComponent for buttons, implemented basic Drag And Drop Revision 1.209 2004/02/27 00:42:41 marc * Interface CreateComponent splitup * Implemented CreateButtonHandle on GTK interface on win32 interface it still needs to be done * Changed ApiWizz to support multilines and more interfaces Revision 1.208 2004/02/23 23:15:13 mattias improved FindDragTarget Revision 1.207 2004/02/23 18:24:38 mattias completed new TToolBar Revision 1.206 2004/02/23 08:19:04 micha revert intf split Revision 1.204 2004/02/22 15:39:43 mattias fixed error handling on saving lpi file Revision 1.203 2004/02/22 10:43:20 mattias added child-parent checks Revision 1.202 2004/02/21 15:37:33 mattias moved compiler options to project menu, added -CX for smartlinking Revision 1.201 2004/02/13 15:49:54 mattias started advanced LCL auto sizing Revision 1.200 2004/02/12 18:09:10 mattias removed win32 specific TToolBar code in new TToolBar, implemented TWinControl.FlipChildren Revision 1.199 2004/02/09 19:52:52 mattias implemented ByteOrder for TLazIntfImage and added call of to LM_SETFONT Revision 1.198 2004/02/04 23:30:18 mattias completed TControl actions Revision 1.197 2004/02/04 17:39:30 mattias quick fixed TToolBar destruction Revision 1.196 2004/02/02 16:59:28 mattias more Actions TAction, TBasicAction, ... Revision 1.195 2004/02/02 12:44:45 mattias implemented interface constraints Revision 1.194 2004/02/02 11:07:43 mattias constraints and aligning now work together Revision 1.193 2004/02/02 00:41:06 mattias TScrollBar now automatically checks Align and Anchors for useful values Revision 1.192 2004/01/27 21:32:11 mattias improved changing style of controls Revision 1.191 2004/01/13 16:39:01 mattias changed consistency stops during var renaming to errors Revision 1.190 2004/01/12 08:36:34 micha statusbar interface dependent reimplementation (from vincent) Revision 1.189 2004/01/10 02:01:37 mattias implemented Undo property for OI Revision 1.188 2004/01/09 13:49:43 mattias improved gtk intf key fetching and OI keyboard navigation Revision 1.187 2004/01/06 17:58:06 mattias fixed setting TRadioButton.Caption for gtk Revision 1.186 2004/01/03 23:14:59 mattias default font can now change height and fixed gtk crash Revision 1.185 2004/01/03 21:06:06 micha - fix win32/checklistbox - implement proper lcl to interface move/size notify via setwindowpos - fix treeview to use inherited canvas from customcontrol - implement double buffering in win32 Revision 1.184 2003/12/29 14:22:22 micha fix a lot of range check errors win32 Revision 1.183 2003/12/25 14:17:07 mattias fixed many range check warnings Revision 1.182 2003/12/23 16:50:45 micha fix defocus control when destroying it Revision 1.181 2003/12/14 19:18:04 micha hint fixes: parentfont, font itself, showing/hiding + more Revision 1.180 2003/12/06 19:20:46 mattias codecompletion: forward proc body position now block sensitive Revision 1.179 2003/11/23 00:28:51 mattias fixed closing IDE while debugging Revision 1.178 2003/10/31 11:49:30 micha fix win32 designer: grid, non-windowed components, selectiongrabbers Revision 1.177 2003/10/16 19:43:44 ajgenius disable Buffering in TWinControl.WM_PAINT Revision 1.176 2003/10/06 10:50:10 mattias added recursion to InvalidateClientRectCache Revision 1.175 2003/10/02 11:33:39 mattias completed compstyles and fixed calendar date parsing from Karl Revision 1.174 2003/09/26 06:59:59 mattias implemented GetBrush Revision 1.173 2003/09/25 09:01:54 mattias increased rpm version Revision 1.172 2003/09/23 08:00:46 mattias improved OnEnter for gtkcombo Revision 1.171 2003/09/20 13:27:49 mattias varois improvements for ParentColor from Micha Revision 1.170 2003/09/18 09:21:03 mattias renamed LCLLinux to LCLIntf Revision 1.169 2003/09/17 15:26:41 mattias fixed removing TPage Revision 1.168 2003/09/13 16:43:01 mattias fixed PerformTab call Revision 1.167 2003/09/13 14:01:39 mattias fixed taborder dlg Revision 1.166 2003/08/31 17:30:49 mattias fixed TControl painting for win32 Revision 1.165 2003/08/27 11:01:10 mattias started TDockTree Revision 1.164 2003/08/26 14:33:40 mattias implemented component tree for OI Revision 1.163 2003/08/25 16:18:15 mattias fixed background color of TPanel and clicks of TSpeedButton from Micha Revision 1.162 2003/08/23 21:17:09 mattias several fixes for the win32 intf, added pending OnResize events Revision 1.161 2003/08/23 11:30:50 mattias fixed SetComboHeight in win32 intf and finddeclaration of overloaded proc definition Revision 1.160 2003/08/21 13:04:10 mattias implemented insert marks for TTreeView Revision 1.159 2003/08/12 16:12:42 mattias reduced output Revision 1.158 2003/08/12 16:04:22 mattias added groupboxnested example Revision 1.157 2003/08/12 14:02:54 mattias fixed keypress/keyup, createcaret on synedit focus Revision 1.156 2003/07/30 13:03:44 mattias replaced label with memo Revision 1.155 2003/07/25 08:00:36 mattias fixed sending follow up move/size messages from gtk Revision 1.154 2003/07/24 06:54:32 mattias fixed anti circle mechnism for aligned controls Revision 1.153 2003/07/07 07:59:34 mattias made Size_SourceIsInterface a flag Revision 1.152 2003/07/06 20:40:34 mattias TWinControl.WmSize/Move now updates interface messages smarter Revision 1.151 2003/07/04 10:12:16 mattias added default message handler to win32 interface Revision 1.150 2003/07/02 15:56:15 mattias fixed win32 painting and started creating bitmaps from rawimages Revision 1.149 2003/06/30 16:39:40 mattias clean up Revision 1.148 2003/06/30 14:58:29 mattias implemented multi file add to package editor Revision 1.147 2003/06/30 07:05:30 mattias activated EraseBKGND hack Revision 1.146 2003/06/30 07:00:18 mattias activated EraseBckGrd messages in doublebuffer WMPaint section Revision 1.145 2003/06/28 12:10:02 mattias fixed LM_SETSIZE in InitializeWnd Revision 1.144 2003/06/27 23:42:38 mattias fixed TScrollBar resizing Revision 1.143 2003/06/27 22:07:39 mattias fixed targetos for clean all Revision 1.142 2002/08/17 23:41:34 mattias many clipping fixes Revision 1.141 2003/06/20 12:56:53 mattias reduced paint messages on destroy Revision 1.140 2003/06/19 22:38:21 mattias fixed update on changing package usage options Revision 1.139 2003/06/19 16:36:35 mattias started codeexplorer Revision 1.138 2003/06/19 09:26:58 mattias fixed changing unitname during update Revision 1.137 2003/06/18 11:21:06 mattias fixed taborder=0, implemented TabOrder Editor Revision 1.136 2003/06/12 18:55:44 mattias improved designer to recognize auto child moves Revision 1.135 2003/06/11 22:29:42 mattias fixed realizing bounds after loading form Revision 1.134 2003/06/10 17:23:35 mattias implemented tabstop Revision 1.133 2003/06/10 12:28:23 mattias fixed anchoring controls Revision 1.132 2003/06/10 00:46:16 mattias fixed aligning controls Revision 1.131 2003/06/01 21:09:09 mattias implemented datamodules Revision 1.130 2003/05/24 08:51:41 mattias implemented designer close query Revision 1.129 2003/04/20 20:32:40 mattias implemented removing, re-adding, updating project dependencies Revision 1.128 2003/04/11 10:31:57 mattias added Sender to Application OnKeyDownHandler Revision 1.127 2003/04/11 10:23:23 mattias added Application OnKeyDownHandler Revision 1.126 2003/04/10 09:22:42 mattias implemented changing dependency version Revision 1.125 2003/04/04 09:19:22 mattias activated TDataSource Revision 1.124 2003/03/28 19:39:54 mattias started typeinfo for double extended Revision 1.123 2003/03/25 10:45:41 mattias reduced focus handling and improved focus setting Revision 1.122 2003/03/18 13:04:25 mattias improved focus debugging output Revision 1.121 2003/03/17 08:51:09 mattias added IsWindowVisible Revision 1.120 2003/03/11 07:46:44 mattias more localization for gtk- and win32-interface and lcl Revision 1.119 2003/03/09 17:44:12 mattias finshed Make Resourcestring dialog and implemented TToggleBox Revision 1.118 2003/02/26 12:44:52 mattias readonly flag is now only saved if user set Revision 1.117 2003/02/09 18:07:42 mattias cleanup Revision 1.116 2003/01/24 13:53:53 mattias fixed TRadioGroup.Items editing in IDE Revision 1.115 2003/01/18 21:31:43 mattias fixed scrolling offset of TScrollingWinControl Revision 1.114 2003/01/01 13:04:26 mattias clean ups Revision 1.113 2003/01/01 13:01:01 mattias fixed setcolor for streamed components Revision 1.112 2002/12/29 18:13:38 mattias identifier completion: basically working, still hidden Revision 1.111 2002/12/28 17:43:43 mattias fixed FindControl and searching overloaded procs Revision 1.110 2002/12/28 12:42:38 mattias focus fixes, reduced lpi size Revision 1.109 2002/12/27 17:46:04 mattias fixed SetColor Revision 1.108 2002/12/27 17:12:38 mattias added more Delphi win32 compatibility functions Revision 1.107 2002/02/09 01:48:23 mattias renamed TinterfaceObject.Init to AppInit and TWinControls can now contain childs in gtk Revision 1.106 2002/12/04 20:39:15 mattias patch from Vincent: clean ups and fixed crash on destroying window Revision 1.105 2002/12/03 09:28:31 mattias cleaned up Revision 1.104 2002/11/30 08:35:42 mattias TCustomForm.WMDestroy does not Free anymore Revision 1.103 2002/11/29 15:14:48 mattias replaced many invalidates by invalidaterect Revision 1.102 2002/11/27 15:40:36 mattias fixed resize request Revision 1.101 2002/11/21 18:49:53 mattias started OnMouseEnter and OnMouseLeave Revision 1.100 2002/11/10 21:49:28 lazarus MG: added smart hints in edit mode Revision 1.99 2002/11/09 18:13:33 lazarus MG: fixed gdkwindow checks Revision 1.98 2002/11/03 22:40:28 lazarus MG: fixed ControlAtPos Revision 1.97 2002/11/01 14:40:31 lazarus MG: fixed mouse coords on scrolling wincontrols Revision 1.96 2002/10/31 22:14:16 lazarus MG: fixed GetClipBox when clipping region invalid Revision 1.95 2002/10/31 21:29:47 lazarus MG: implemented TControlScrollBar.Size Revision 1.94 2002/10/26 15:15:49 lazarus MG: broke LCL<->interface circles Revision 1.93 2002/10/09 10:22:54 lazarus MG: fixed client origin coordinates Revision 1.92 2002/10/08 22:32:27 lazarus MG: fixed cool little bug (menu double attaching bug) Revision 1.91 2002/10/04 20:46:51 lazarus MG: improved TComboBox.SetItemIndex Revision 1.90 2002/10/04 14:24:15 lazarus MG: added DrawItem to TComboBox/TListBox Revision 1.89 2002/09/29 15:08:38 lazarus MWE: Applied patch from "Andrew Johnson" Patch includes: -fixes Problems with hiding modal forms -temporarily fixes TCustomForm.BorderStyle in bsNone -temporarily fixes problems with improper tabbing in TSynEdit Revision 1.88 2002/09/27 20:52:23 lazarus MWE: Applied patch from "Andrew Johnson" Here is the run down of what it includes - -Vasily Volchenko's Updated Russian Localizations -improvements to GTK Styles/SysColors -initial GTK Palette code - (untested, and for now useless) -Hint Windows and Modal dialogs now try to stay transient to the main program form, aka they stay on top of the main form and usually minimize/maximize with it. -fixes to Form BorderStyle code(tool windows needed a border) -fixes DrawFrameControl DFCS_BUTTONPUSH to match Win32 better when flat -fixes DrawFrameControl DFCS_BUTTONCHECK to match Win32 better and to match GTK theme better. It works most of the time now, but some themes, noteably Default, don't work. -fixes bug in Bitmap code which broke compiling in NoGDKPixbuf mode. -misc other cleanups/ fixes in gtk interface -speedbutton's should now draw correctly when flat in Win32 -I have included an experimental new CheckBox(disabled by default) which has initial support for cbGrayed(Tri-State), and WordWrap, and misc other improvements. It is not done, it is mostly a quick hack to test DrawFrameControl DFCS_BUTTONCHECK, however it offers many improvements which can be seen in cbsCheck/cbsCrissCross (aka non-themed) state. -fixes Message Dialogs to more accurately determine button Spacing/Size, and Label Spacing/Size based on current System font. -fixes MessageDlgPos, & ShowMessagePos in Dialogs -adds InputQuery & InputBox to Dialogs -re-arranges & somewhat re-designs Control Tabbing, it now partially works - wrapping around doesn't work, and subcontrols(Panels & Children, etc) don't work. TabOrder now works to an extent. I am not sure what is wrong with my code, based on my other tests at least wrapping and TabOrder SHOULD work properly, but.. Anyone want to try and fix? -SynEdit(Code Editor) now changes mouse cursor to match position(aka over scrollbar/gutter vs over text edit) -adds a TRegion property to Graphics.pp, and Canvas. Once I figure out how to handle complex regions(aka polygons) data properly I will add Region functions to the canvas itself (SetClipRect, intersectClipRect etc.) -BitBtn now has a Stored flag on Glyph so it doesn't store to lfm/lrs if Glyph is Empty, or if Glyph is not bkCustom(aka bkOk, bkCancel, etc.) This should fix most crashes with older GDKPixbuf libs. Revision 1.87 2002/09/16 15:42:17 lazarus MG: fixed calling DestroyHandle if not HandleAllocated Revision 1.86 2002/09/10 06:49:19 lazarus MG: scrollingwincontrol from Andrew Revision 1.85 2002/09/05 12:11:43 lazarus MG: TNotebook is now streamable Revision 1.84 2002/09/03 08:07:20 lazarus MG: image support, TScrollBox, and many other things from Andrew Revision 1.83 2002/09/01 16:11:22 lazarus MG: double, triple and quad clicks now works Revision 1.82 2002/08/31 11:37:09 lazarus MG: fixed destroying combobox Revision 1.81 2002/08/30 12:32:21 lazarus MG: MoveWindowOrgEx, Splitted FWinControls/FControls, TControl drawing, Better DesignerDrawing, ... Revision 1.80 2002/08/30 06:46:03 lazarus Use comboboxes. Use history. Prettify the dialog. Preselect text on show. Make the findreplace a dialog. Thus removing resiying code (handled by Anchors now anyway). Make Anchors work again and publish them for various controls. SelStart and Co. for TEdit, SelectAll procedure for TComboBox and TEdit. Clean up and fix some bugs for TComboBox, plus selection stuff. Revision 1.79 2002/08/25 14:32:11 lazarus MG: calendar now ignores double clicks Revision 1.78 2002/08/24 12:54:59 lazarus MG: fixed mouse capturing, OI edit focus Revision 1.77 2002/08/24 06:51:22 lazarus MG: from Andrew: style list fixes, autosize for radio/checkbtns Revision 1.76 2002/08/17 15:45:33 lazarus MG: removed ClientRectBugfix defines Revision 1.75 2002/08/05 07:43:28 lazarus MG: fixed BadCursor bug and Circle Reference of FixedWidget of csPanel Revision 1.74 2002/06/21 15:41:56 lazarus MG: moved RectVisible, ExcludeClipRect and IntersectClipRect to interface dependent functions Revision 1.73 2002/06/19 19:46:09 lazarus MG: Form Editing: snapping, guidelines, modified on move/resize, creating components in csDesigning, ... Revision 1.72 2002/06/11 13:41:09 lazarus MG: fixed mouse coords and fixed mouse clicked thru bug Revision 1.71 2002/05/28 15:05:59 lazarus MG: reduced output Revision 1.70 2002/05/28 14:58:30 lazarus MG: added scrollbars for TListView Revision 1.69 2002/05/27 14:38:34 lazarus MG; fixed find declaration of overloaded procs and expression input types Revision 1.68 2002/05/24 07:16:32 lazarus MG: started mouse bugfix and completed Makefile.fpc Revision 1.67 2002/05/13 14:47:00 lazarus MG: fixed client rectangles, TRadioGroup, RecreateWnd Revision 1.66 2002/05/12 04:56:20 lazarus MG: client rect bugs nearly completed Revision 1.65 2002/05/10 06:05:56 lazarus MG: changed license to LGPL Revision 1.64 2002/05/09 12:41:28 lazarus MG: further clientrect bugfixes Revision 1.63 2002/05/06 08:50:36 lazarus MG: replaced logo, increased version to 0.8.3a and some clientrectbugfix Revision 1.62 2002/04/28 14:10:31 lazarus MG: fixes for saving resource files Revision 1.61 2002/04/27 15:35:50 lazarus MG: fixed window shrinking Revision 1.60 2002/04/24 16:11:17 lazarus MG: started new client rectangle Revision 1.59 2002/04/22 13:07:45 lazarus MG: fixed AdjustClientRect of TGroupBox Revision 1.58 2002/04/18 08:13:36 lazarus MG: added include comments Revision 1.56 2002/04/04 12:25:01 lazarus MG: changed except statements to more verbosity Revision 1.55 2002/03/31 23:20:38 lazarus MG: fixed initial size of TPage Revision 1.54 2002/03/29 14:32:49 lazarus MG: further internationalization Revision 1.53 2002/03/25 17:59:20 lazarus GTK Cleanup Shane Revision 1.52 2002/03/16 21:40:55 lazarus MG: reduced size+move messages between lcl and interface Revision 1.51 2002/03/14 23:25:52 lazarus MG: fixed TBevel.Create and TListView.Destroy Revision 1.50 2002/03/13 22:48:16 lazarus Constraints implementation (first cut) and sizig - moving system rework to better match Delphi/Kylix way of doing things (the existing implementation worked by acident IMHO :-) Revision 1.49 2002/01/21 14:17:47 lazarus MG: added find-block-start and renamed find-block-other-end Revision 1.48 2002/01/01 15:50:15 lazarus MG: fixed initial component aligning Revision 1.47 2001/12/31 22:43:00 lazarus Added a TViewColumn editor to be used in the object inspector as TViewColumn's property editor. Shane Revision 1.46 2001/12/28 15:12:02 lazarus MG: LM_SIZE and LM_MOVE messages are now send directly, not queued Revision 1.45 2001/12/20 14:41:20 lazarus Fixed setfocus for TComboBox and TMemo Shane Revision 1.44 2001/12/08 08:54:45 lazarus MG: added TControl.Refresh Revision 1.43 2001/12/07 20:12:15 lazarus Added a watch dialog. Shane Revision 1.42 2001/11/10 10:48:00 lazarus MG: fixed set formicon on invisible forms Revision 1.41 2001/11/09 19:14:23 lazarus HintWindow changes Shane Revision 1.40 2001/10/31 16:29:22 lazarus Fixed the gtk mousemove bug where the control gets the coord's based on it's parent instead of itself. Shane Revision 1.39 2001/10/10 17:55:04 lazarus MG: fixed caret lost, gtk cleanup, bracket lvls, bookmark saving Revision 1.38 2001/10/07 07:28:33 lazarus MG: fixed setpixel and TCustomForm.OnResize event Revision 1.37 2001/10/03 17:34:27 lazarus MG: activated TCustomForm.OnCreate event Revision 1.35 2001/08/07 11:05:51 lazarus MG: small bugfixes Revision 1.34 2001/06/27 21:43:23 lazarus MG: added project bookmark support Revision 1.33 2001/06/15 10:31:06 lazarus MG: set longstrings as default Revision 1.32 2001/06/14 14:57:59 lazarus MG: small bugfixes and less notes Revision 1.31 2001/06/05 10:32:05 lazarus MG: small bugfixes for bitbtn, handles Revision 1.30 2001/05/16 10:00:00 lazarus MG: fixed wrong page index in editor closing Revision 1.29 2001/05/13 22:07:08 lazarus Implemented BringToFront / SendToBack. Revision 1.28 2001/04/02 14:45:26 lazarus MG: bugfixes for TBevel Revision 1.27 2001/03/27 14:27:43 lazarus Changes from Nagy Zsolt Shane Revision 1.26 2001/03/26 14:58:31 lazarus MG: setwindowpos + bugfixes Revision 1.24 2001/03/19 14:38:39 lazarus MG: fixed many unreleased DC and GDIObj bugs Revision 1.21 2001/03/12 12:17:02 lazarus MG: fixed random function results Revision 1.20 2001/02/28 13:17:33 lazarus Added some debug code for the top,left reporting problem. Shane Revision 1.19 2001/02/06 20:59:17 lazarus Trying to get the last control of the last form focused when a dialog closes. Still working on it. Shane Revision 1.18 2001/02/06 18:19:37 lazarus Shane Revision 1.17 2001/02/06 14:52:47 lazarus Changed TSpeedbutton in gtkobject so it erases itself when it's set to visible=false; Shane Revision 1.15 2001/02/04 04:18:12 lazarus Code cleanup and JITFOrms bug fix. Shane Revision 1.14 2001/02/01 19:34:50 lazarus TScrollbar created and a lot of code added. It's cose to working. Shane Revision 1.13 2001/01/30 18:15:02 lazarus Added code for TStatusBar I'm now capturing WMPainT and doing the drawing myself. Shane Revision 1.12 2001/01/28 21:06:07 lazarus Changes for TComboBox events KeyPress Focus. Shane Revision 1.11 2001/01/23 23:33:54 lazarus MWE: - Removed old LM_InvalidateRect - did some cleanup in old code + added some comments on gtkobject data (gtkproc) Revision 1.10 2001/01/18 13:27:31 lazarus Minor changees Shane Revision 1.9 2001/01/15 18:25:51 lazarus Fixed a stupid error I caused by using a variable as an index in main.pp and this variable sometimes caused an exception because the index was out of range. Shane Revision 1.8 2001/01/12 20:22:09 lazarus Shiftstate fixed so it reports ssCtrl and ssShift now. You can use Shift-Ctrl-Up and Down to jump to procedures in the code explorer. Shane Revision 1.7 2001/01/09 18:23:21 lazarus Worked on moving controls. It's just not working with the X and Y coord's I'm getting. Shane Revision 1.6 2000/12/29 18:33:54 lazarus TStatusBar's create and destroy were not set to override TWinControls so they were never called. Shane Revision 1.5 2000/12/29 13:14:05 lazarus Using the lresources.pp and registering components. This is a major change but will create much more flexibility for the IDE. Shane Revision 1.4 2000/12/20 17:35:58 lazarus Added GetChildren Shane Revision 1.3 2000/09/10 23:08:30 lazarus MWE: + Added CreateCompatibeleBitamp function + Updated TWinControl.WMPaint + Added some checks to avoid gtk/gdk errors - Removed no fixed warning from GetDC - Removed some output Revision 1.2 2000/07/30 21:48:32 lazarus MWE: = Moved ObjectToGTKObject to GTKProc unit * Fixed array checking in LoadPixmap = Moved LM_SETENABLED to API func EnableWindow and EnableMenuItem ~ Some cleanup Revision 1.1 2000/07/13 10:28:28 michael + Initial import Revision 1.16 2000/07/09 20:18:56 lazarus MWE: + added new controlselection + some fixes ~ some cleanup Revision 1.15 2000/06/28 13:11:37 lazarus Fixed TNotebook so it gets page change events. Shane Revision 1.14 2000/06/19 18:21:22 lazarus Spinedit was never getting created Shane Revision 1.13 2000/06/16 13:33:21 lazarus Created a new method for adding controls to the toolbar to be dropped onto the form! Shane Revision 1.12 2000/06/01 21:53:19 lazarus MWE: + Added check for HandleCreated in CMShowHintChanged Revision 1.11 2000/05/27 22:20:55 lazarus MWE & VRS: + Added new hint code Revision 1.10 2000/05/17 22:34:07 lazarus MWE: * Fixed Sizing & events Revision 1.9 2000/05/14 21:56:11 lazarus MWE: + added local messageloop + added PostMessage * fixed Peekmessage * fixed ClientToScreen * fixed Flat style of Speedutton (TODO: Draw) + Added TApplicatio.OnIdle Revision 1.8 2000/05/10 22:52:58 lazarus MWE: = Moved some global api stuf to gtkobject Revision 1.7 2000/05/09 12:52:03 lazarus *** empty log message *** Revision 1.6 2000/05/09 02:07:40 lazarus Replaced writelns with Asserts. CAW Revision 1.5 2000/05/08 16:07:32 lazarus fixed screentoclient and clienttoscreen Shane Revision 1.4 2000/04/10 15:05:30 lazarus Modified the way the MOuseCapture works. Shane Revision 1.2 2000/04/07 16:59:55 lazarus Implemented GETCAPTURE and SETCAPTURE along with RELEASECAPTURE. Shane Revision 1.1 2000/04/02 20:49:57 lazarus MWE: Moved lazarus/lcl/*.inc files to lazarus/lcl/include Revision 1.77 2000/03/30 18:07:55 lazarus Added some drag and drop code Added code to change the unit name when it's saved as a different name. Not perfect yet because if you are in a comment it fails. Shane Revision 1.76 2000/03/21 23:47:33 lazarus MWE: + Added TBitmap.MaskHandle & TGraphic.Draw & TBitmap.Draw Revision 1.75 2000/03/15 00:51:58 lazarus MWE: + Added LM_Paint on expose + Added forced creation of gdkwindow if needed ~ Modified DrawFrameControl + Added BF_ADJUST support on DrawEdge - Commented out LM_IMAGECHANGED in TgtkObject.IntSendMessage3 (It did not compile) Revision 1.74 2000/03/14 19:49:05 lazarus Modified the painting process for TWincontrol. Now it runs throug it's FCONTROLS list and paints all them Shane Revision 1.73 2000/03/09 23:48:10 lazarus MWE: * Fixed colorcache * Fixed black window in new editor ~ Did some cosmetic stuff From Peter Dyson : + Added Rect api support functions + Added the start of ScrollWindowEx Revision 1.72 2000/03/08 23:57:39 lazarus MWE: Added SetSysColors Fixed TEdit text bug (thanks to hans-joachim ott ) Finished GetKeyState Added changes from Peter Dyson - a new GetSysColor - some improvements on ExTextOut Revision 1.71 2000/03/03 22:58:27 lazarus MWE: Fixed focussing problem. LM-FOCUS was bound to the wrong signal Added GetKeyState api func. Now LCL knows if shift/trl/alt is pressed (might be handy for keyboard selections ;-) Revision 1.70 2000/03/01 00:41:03 lazarus MWE: Fixed updateshowing problem Added some debug code to display the name of messages Did a bit of cleanup in main.pp to get the code a bit more readable (my editor does funny things with tabs if the indent differs) Revision 1.69 2000/02/28 00:15:54 lazarus MWE: Fixed creation of visible componets at runtime. (when a new editor was created it didn't show up) Made the hiding/showing of controls more delphi compatible Revision 1.68 2000/02/26 23:31:50 lazarus MWE: Fixed notebook crash on insert Fixed loadfont problem for win32 (tleast now a fontname is required) Revision 1.67 2000/02/25 19:28:34 lazarus Played with TNotebook to see why it crashes when I add a tab and the tnotebook is showing. Havn't figured it out Shane Revision 1.66 2000/02/22 23:26:13 lazarus MWE: Fixed cursor movement in editor Started on focus problem Revision 1.65 2000/02/22 22:19:50 lazarus TCustomDialog is a descendant of TComponent. Initial cuts a form's proper Close behaviour. Revision 1.64 2000/02/22 17:32:49 lazarus Modified the ShowModal call. For TCustomForm is simply sets the visible to true now and adds fsModal to FFormState. In gtkObject.inc FFormState is checked. If it contains fsModal then either gtk_grab_add or gtk_grab_remove is called depending on the value of VISIBLE. The same goes for TCustomDialog (open, save, font, color). I moved the Execute out of the individual dialogs and moved it into TCustomDialog and made it virtual because FONT needs to set some stuff before calling the inherited execute. Shane Revision 1.63 2000/02/20 20:13:47 lazarus On my way to make alignments and stuff work :-) Revision 1.62 2000/02/19 18:11:59 lazarus More work on moving, resizing, forms' border style etc. Revision 1.61 2000/02/18 19:38:53 lazarus Implemented TCustomForm.Position Better implemented border styles. Still needs some tweaks. Changed TComboBox and TListBox to work again, at least partially. Minor cleanups. Revision 1.60 2000/01/18 21:47:00 lazarus Added OffSetRec Revision 1.59 2000/01/10 00:07:13 lazarus MWE: Added more scrollbar support for TWinControl Most signals for TWinContorl are jet connected to the wrong widget (now scrolling window, should be fixed) Added some cvs entries Revision 1.58 2000/01/04 21:00:34 lazarus *** empty log message *** Revision 1.57 2000/01/03 00:19:21 lazarus MWE: Added keyup and buttonup events Added LM_MOUSEMOVE callback Started with scrollbars in editor Revision 1.56 2000/01/02 00:29:27 lazarus Stoppok: - safety check if fCompStyle <> csNone before call to CreateHandle Revision 1.55 1999/12/31 14:58:01 lazarus MWE: Set unkown VK_ codesto 0 Added pfDevice support for bitmaps Revision 1.54 1999/12/23 21:48:13 lazarus *** empty log message *** Revision 1.52 1999/12/22 01:16:04 lazarus MWE: Changed/recoded keyevent callbacks We Can Edit! Commented out toolbar stuff Revision 1.51 1999/12/21 21:35:54 lazarus committed the latest toolbar code. Currently it doesn't appear anywhere and I have to get it to add buttons correctly through (I think) setstyle. I think I'll implement the LM_TOOLBARINSERTBUTTON call there. Shane Revision 1.50 1999/12/21 00:07:06 lazarus MWE: Some fixes Completed a bit of DraWEdge Revision 1.49 1999/12/20 21:01:14 lazarus Added a few things for compatability with Delphi and TToolbar Shane Revision 1.48 1999/12/18 18:27:32 lazarus MWE: Rearranged some events to get a LM_SIZE, LM_MOVE and LM_WINDOWPOSCHANGED Initialized the TextMetricstruct to zeros to clear unset values Get mwEdit to show more than one line Fixed some errors in earlier commits Revision 1.47 1999/12/14 21:16:26 lazarus Added Autosize to TControl Shane Revision 1.46 1999/12/14 00:16:43 lazarus MWE: Renamed LM... message handlers to WM... to be compatible and to get more edit parts to compile Started to implement GetSystemMetrics Removed some Lazarus specific parts from mwEdit Revision 1.45 1999/12/10 00:47:01 lazarus MWE: Fixed some samples Fixed Dialog parent is no longer needed Fixed (Win)Control Destruction Fixed MenuClick Revision 1.44 1999/12/08 21:42:37 lazarus Moved more messages over to wndproc. Shane Revision 1.43 1999/12/08 00:56:07 lazarus MWE: Fixed menus. Events aren't enabled yet (dumps --> invalid typecast ??) Revision 1.42 1999/12/07 01:19:26 lazarus MWE: Removed some double events Changed location of SetCallBack Added call to remove signals Restructured somethings Started to add default handlers in TWinControl Made some parts of TControl and TWinControl more delphi compatible ... and lots more ... Revision 1.41 1999/12/03 00:26:47 lazarus MWE: fixed control location added gdiobject reference counter Revision 1.40 1999/12/02 19:00:59 lazarus MWE: Added (GDI)Pen Changed (GDI)Brush Changed (GDI)Font (color) Changed Canvas to use/create pen/brush/font Hacked mwedit to allow setting the number of chars (till it get a WM/LM_SIZE event) The editor shows a line ! Revision 1.39 1999/11/30 21:30:06 lazarus Minor Issues Shane Revision 1.38 1999/11/25 23:45:08 lazarus MWE: Added font as GDIobject Added some API testcode to testform Commented out some more IFDEFs in mwCustomEdit Revision 1.37 1999/11/19 01:09:43 lazarus MWE: implemented TCanvas.CopyRect Added StretchBlt Enabled creation of TCustomControl.Canvas Added a temp hack in TWinControl.Repaint to get a LM_PAINT Revision 1.36 1999/11/17 01:16:40 lazarus MWE: Added some more API stuff Added an initial TBitmapCanvas Added some DC stuff Changed and commented out, original gtk linedraw/rectangle code. This is now called through the winapi wrapper. Revision 1.35 1999/11/05 17:48:17 lazarus Added a mwedit1 component to lazarus (MAIN.PP) It crashes on create. Shane Revision 1.34 1999/11/04 21:52:08 lazarus wndproc being used a little Shane Revision 1.33 1999/11/01 01:28:30 lazarus MWE: Implemented HandleNeeded/CreateHandle/CreateWND Now controls are created on demand. A call to CreateComponent shouldn't be needed. It is now part of CreateWnd Revision 1.32 1999/10/30 17:03:15 lazarus MWE: Typo Revision 1.31 1999/10/30 16:42:12 lazarus MWE: Moved the Parent <> self check to the Parent property Revision 1.30 1999/10/30 12:30:02 peter * fixed some stupid crashes Revision 1.29 1999/10/28 23:48:57 lazarus MWE: Added new menu classes and started to use handleneeded Revision 1.28 1999/10/28 19:25:10 lazarus Added a ton of messaging stuff Shane Revision 1.27 1999/10/28 17:17:43 lazarus Removed references to FCOmponent. Shane Revision 1.26 1999/10/27 17:27:08 lazarus Added alot of changes and TODO: statements shane Revision 1.25 1999/10/25 21:07:49 lazarus Many changes for compatability made again.. Shane Revision 1.24 1999/10/25 17:38:52 lazarus More stuff added for compatability. Most stuff added was put in the windows.pp file. CONST scroll bar messages and such. 2 functions were also added to that unit that needs to be completed. Shane Revision 1.23 1999/10/25 15:33:54 lazarus Added a few more procedures for compatability. Shane Revision 1.22 1999/10/22 18:56:36 lazarus Fixed a linking error in wincontrol.inc Shane Revision 1.21 1999/10/22 18:39:43 lazarus Added kEYUP- KeyPress - Keydown, etc. Shane Revision 1.20 1999/10/20 21:08:16 lazarus added OnDblClick, OnShowHint, OnParentShowHint, etc for compatability. Revision 1.18 1999/09/30 21:59:03 lazarus MWE: Fixed TNoteBook problems Modifications: A few - Removed some debug messages + Added some others * changed fixed widged of TPage. Code is still broken. + TWinControls are also added to the Controls collection + Added TControl.Controls[] property Revision 1.17 1999/09/26 13:30:15 lazarus Implemented OnEnter & OnExit events for TTrackbar. These properties and handler functions have been added to TWincontrol, two new callbacks have been added to gtkcallback. stoppok Revision 1.16 1999/09/17 23:12:58 lazarus *** empty log message *** Revision 1.15 1999/09/15 03:17:32 lazarus Changes to Editor.pp If the text was actually displayed, then it would work better. :-) Revision 1.14 1999/09/15 02:14:44 lazarus *** empty log message *** Revision 1.13 1999/09/11 12:16:16 lazarus Fixed a bug in key press evaluation. Initial cut at Invalidate problem. Revision 1.12 1999/08/26 23:36:03 peter + paintbox + generic keydefinitions and gtk conversion * gtk state -> shiftstate conversion Revision 1.11 1999/08/24 21:26:53 lazarus *** empty log message *** Revision 1.9 1999/08/16 15:48:50 lazarus Changes by file: Control: TCOntrol-Function GetRect added ClientRect property added TImageList - Added Count TWinControl- Function Focused added. Graphics: TCanvas - CopyRect added - nothing finished on it though Draw added - nothing finiushed on it though clbtnhighlight and clbtnshadow added. Actual color values not right. IMGLIST.PP and IMGLIST.INC files added. A few other minor changes for compatability added. Shane Revision 1.8 1999/08/12 18:36:58 lazarus Added a bunch of "stuff" for compatablility. Not sure if it'll all compile yet, will look at that shortly. Revision 1.7 1999/08/11 20:41:35 lazarus Minor changes and additions made. Lazarus may not compile due to these changes Revision 1.6 1999/08/07 17:59:25 lazarus buttons.pp the DoLeave and DoEnter were connected to the wrong event. The rest were modified to use the new SendMessage function. MAH Revision 1.5 1999/07/31 14:27:04 peter * mouse fixes * wheel support Revision 1.4 1999/07/31 06:39:32 lazarus Modified the IntSendMessage3 to include a data variable. It isn't used yet but will help in merging the Message2 and Message3 features. Adjusted TColor routines to match Delphi color format Added a TGdkColorToTColor routine in gtkproc.inc Finished the TColorDialog added to comDialog example. MAH }