home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Chip 1997 April
/
Chip_1997-04_cd.bin
/
prezent
/
cb
/
data.z
/
CONTROLS.PAS
< prev
next >
Wrap
Pascal/Delphi Source File
|
1997-01-16
|
165KB
|
5,780 lines
{*******************************************************}
{ }
{ Delphi Visual Component Library }
{ }
{ Copyright (c) 1995,96 Borland International }
{ }
{*******************************************************}
unit Controls;
{$P+,S-,W-,R-}
{$C PRELOAD}
interface
{$R CONTROLS}
uses Messages, Windows, Classes, Sysutils, Graphics, Menus, CommCtrl, Imm;
{ VCL control message IDs }
const
CM_BASE = $B000;
CM_ACTIVATE = CM_BASE + 0;
CM_DEACTIVATE = CM_BASE + 1;
CM_GOTFOCUS = CM_BASE + 2;
CM_LOSTFOCUS = CM_BASE + 3;
CM_CANCELMODE = CM_BASE + 4;
CM_DIALOGKEY = CM_BASE + 5;
CM_DIALOGCHAR = CM_BASE + 6;
CM_FOCUSCHANGED = CM_BASE + 7;
CM_PARENTFONTCHANGED = CM_BASE + 8;
CM_PARENTCOLORCHANGED = CM_BASE + 9;
CM_HITTEST = CM_BASE + 10;
CM_VISIBLECHANGED = CM_BASE + 11;
CM_ENABLEDCHANGED = CM_BASE + 12;
CM_COLORCHANGED = CM_BASE + 13;
CM_FONTCHANGED = CM_BASE + 14;
CM_CURSORCHANGED = CM_BASE + 15;
CM_CTL3DCHANGED = CM_BASE + 16;
CM_PARENTCTL3DCHANGED = CM_BASE + 17;
CM_TEXTCHANGED = CM_BASE + 18;
CM_MOUSEENTER = CM_BASE + 19;
CM_MOUSELEAVE = CM_BASE + 20;
CM_MENUCHANGED = CM_BASE + 21;
CM_APPKEYDOWN = CM_BASE + 22;
CM_APPSYSCOMMAND = CM_BASE + 23;
CM_BUTTONPRESSED = CM_BASE + 24;
CM_SHOWINGCHANGED = CM_BASE + 25;
CM_ENTER = CM_BASE + 26;
CM_EXIT = CM_BASE + 27;
CM_DESIGNHITTEST = CM_BASE + 28;
CM_ICONCHANGED = CM_BASE + 29;
CM_WANTSPECIALKEY = CM_BASE + 30;
CM_INVOKEHELP = CM_BASE + 31;
CM_WINDOWHOOK = CM_BASE + 32;
CM_RELEASE = CM_BASE + 33;
CM_SHOWHINTCHANGED = CM_BASE + 34;
CM_PARENTSHOWHINTCHANGED = CM_BASE + 35;
CM_SYSCOLORCHANGE = CM_BASE + 36;
CM_WININICHANGE = CM_BASE + 37;
CM_FONTCHANGE = CM_BASE + 38;
CM_TIMECHANGE = CM_BASE + 39;
CM_TABSTOPCHANGED = CM_BASE + 40;
CM_UIACTIVATE = CM_BASE + 41;
CM_UIDEACTIVATE = CM_BASE + 42;
CM_DOCWINDOWACTIVATE = CM_BASE + 43;
CM_CONTROLLISTCHANGE = CM_BASE + 44;
CM_GETDATALINK = CM_BASE + 45;
CM_CHILDKEY = CM_BASE + 46;
CM_DRAG = CM_BASE + 47;
CM_HINTSHOW = CM_BASE + 48;
CM_DIALOGHANDLE = CM_BASE + 49;
CM_ISTOOLCONTROL = CM_BASE + 50;
CM_RECREATEWND = CM_BASE + 51;
CM_INVALIDATE = CM_BASE + 52;
{ VCL control notification IDs }
const
CN_BASE = $BC00;
CN_CHARTOITEM = CN_BASE + WM_CHARTOITEM;
CN_COMMAND = CN_BASE + WM_COMMAND;
CN_COMPAREITEM = CN_BASE + WM_COMPAREITEM;
CN_CTLCOLORBTN = CN_BASE + WM_CTLCOLORBTN;
CN_CTLCOLORDLG = CN_BASE + WM_CTLCOLORDLG;
CN_CTLCOLOREDIT = CN_BASE + WM_CTLCOLOREDIT;
CN_CTLCOLORLISTBOX = CN_BASE + WM_CTLCOLORLISTBOX;
CN_CTLCOLORMSGBOX = CN_BASE + WM_CTLCOLORMSGBOX;
CN_CTLCOLORSCROLLBAR = CN_BASE + WM_CTLCOLORSCROLLBAR;
CN_CTLCOLORSTATIC = CN_BASE + WM_CTLCOLORSTATIC;
CN_DELETEITEM = CN_BASE + WM_DELETEITEM;
CN_DRAWITEM = CN_BASE + WM_DRAWITEM;
CN_HSCROLL = CN_BASE + WM_HSCROLL;
CN_MEASUREITEM = CN_BASE + WM_MEASUREITEM;
CN_PARENTNOTIFY = CN_BASE + WM_PARENTNOTIFY;
CN_VKEYTOITEM = CN_BASE + WM_VKEYTOITEM;
CN_VSCROLL = CN_BASE + WM_VSCROLL;
CN_KEYDOWN = CN_BASE + WM_KEYDOWN;
CN_KEYUP = CN_BASE + WM_KEYUP;
CN_CHAR = CN_BASE + WM_CHAR;
CN_SYSKEYDOWN = CN_BASE + WM_SYSKEYDOWN;
CN_SYSCHAR = CN_BASE + WM_SYSCHAR;
CN_NOTIFY = CN_BASE + WM_NOTIFY;
{ TModalResult values }
const
mrNone = 0;
mrOk = idOk;
mrCancel = idCancel;
mrAbort = idAbort;
mrRetry = idRetry;
mrIgnore = idIgnore;
mrYes = idYes;
mrNo = idNo;
mrAll = mrNo + 1;
{ Cursor identifiers }
{ Cursor type }
type
TCursor = -32768..32767;
const
crDefault = TCursor(0);
crNone = TCursor(-1);
crArrow = TCursor(-2);
crCross = TCursor(-3);
crIBeam = TCursor(-4);
crSize = TCursor(-5);
crSizeNESW = TCursor(-6);
crSizeNS = TCursor(-7);
crSizeNWSE = TCursor(-8);
crSizeWE = TCursor(-9);
crUpArrow = TCursor(-10);
crHourGlass = TCursor(-11);
crDrag = TCursor(-12);
crNoDrop = TCursor(-13);
crHSplit = TCursor(-14);
crVSplit = TCursor(-15);
crMultiDrag = TCursor(-16);
crSQLWait = TCursor(-17);
crNo = TCursor(-18);
crAppStart = TCursor(-19);
crHelp = TCursor(-20);
type
{ Forward declarations }
TDragObject = class;
TControl = class;
TWinControl = class;
TCustomImageList = class;
{ VCL control message records }
TCMActivate = TWMNoParams;
TCMDeactivate = TWMNoParams;
TCMGotFocus = TWMNoParams;
TCMLostFocus = TWMNoParams;
TCMDialogKey = TWMKey;
TCMDialogChar = TWMKey;
TCMHitTest = TWMNCHitTest;
TCMEnter = TWMNoParams;
TCMExit = TWMNoParams;
TCMDesignHitTest = TWMMouse;
TCMWantSpecialKey = TWMKey;
TCMCancelMode = record
Msg: Cardinal;
Unused: Integer;
Sender: TControl;
Result: Longint;
end;
TCMFocusChanged = record
Msg: Cardinal;
Unused: Integer;
Sender: TWinControl;
Result: Longint;
end;
TCMControlListChange = record
Msg: Cardinal;
Control: TControl;
Inserting: LongBool;
Result: Longint;
end;
TCMChildKey = record
Msg: Cardinal;
CharCode: Word;
Unused: Word;
Sender: TWinControl;
Result: Longint;
end;
TDragMessage = (dmDragEnter, dmDragLeave, dmDragMove, dmDragDrop, dmDragCancel,
dmFindTarget);
PDragRec = ^TDragRec;
TDragRec = record
Pos: TPoint;
Source: TDragObject;
Target: Pointer;
end;
TCMDrag = packed record
Msg: Cardinal;
DragMessage: TDragMessage;
Reserved1: Byte;
Reserved2: Word;
DragRec: PDragRec;
Result: Longint;
end;
{ Exception classes }
EOutOfResources = class(EOutOfMemory);
EInvalidOperation = class(Exception);
{ Dragging objects }
TDragObject = class(TObject)
private
procedure MouseMsg(var Msg: TMessage);
function Capture: HWND;
procedure ReleaseCapture(Handle: HWND);
protected
function GetDragImages: TCustomImageList; virtual;
function GetDragCursor(Accepted: Boolean; X, Y: Integer): TCursor; virtual;
procedure Finished(Target: TObject; X, Y: Integer; Accepted: Boolean); virtual;
public
function Instance: THandle; virtual;
function GetName: string; virtual;
procedure HideDragImage; virtual;
procedure ShowDragImage; virtual;
end;
TDragControlObject = class(TDragObject)
private
FControl: TControl;
public
function GetDragImages: TCustomImageList; override;
function GetDragCursor(Accepted: Boolean; X, Y: Integer): TCursor; override;
procedure Finished(Target: TObject; X, Y: Integer; Accepted: Boolean); override;
protected
constructor Create(AControl: TControl);
property Control: TControl read FControl;
procedure HideDragImage; override;
procedure ShowDragImage; override;
end;
{ Controls }
TControlCanvas = class(TCanvas)
private
FControl: TControl;
FDeviceContext: HDC;
FWindowHandle: HWnd;
procedure SetControl(AControl: TControl);
protected
procedure CreateHandle; override;
public
destructor Destroy; override;
procedure FreeHandle;
property Control: TControl read FControl write SetControl;
end;
TAlign = (alNone, alTop, alBottom, alLeft, alRight, alClient);
TControlState = set of (csLButtonDown, csClicked, csPalette,
csReadingState, csAlignmentNeeded, csFocusing, csCreating,
csPaintCopy);
TControlStyle = set of (csAcceptsControls, csCaptureMouse,
csDesignInteractive, csClickEvents, csFramed, csSetCaption, csOpaque,
csDoubleClicks, csFixedWidth, csFixedHeight, csNoDesignVisible,
csReplicatable, csNoStdEvents, csDisplayDragImage);
TMouseButton = (mbLeft, mbRight, mbMiddle);
TDragMode = (dmManual, dmAutomatic);
TDragState = (dsDragEnter, dsDragLeave, dsDragMove);
TTabOrder = -1..32767;
TCaption = type string;
TScalingFlags = set of (sfLeft, sfTop, sfWidth, sfHeight, sfFont);
TMouseEvent = procedure(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer) of object;
TMouseMoveEvent = procedure(Sender: TObject; Shift: TShiftState;
X, Y: Integer) of object;
TKeyEvent = procedure(Sender: TObject; var Key: Word;
Shift: TShiftState) of object;
TKeyPressEvent = procedure(Sender: TObject; var Key: Char) of object;
TDragOverEvent = procedure(Sender, Source: TObject; X, Y: Integer;
State: TDragState; var Accept: Boolean) of object;
TDragDropEvent = procedure(Sender, Source: TObject;
X, Y: Integer) of object;
TStartDragEvent = procedure(Sender: TObject;
var DragObject: TDragObject) of object;
TEndDragEvent = procedure(Sender, Target: TObject;
X, Y: Integer) of object;
TWndMethod = procedure(var Message: TMessage) of object;
TControl = class(TComponent)
private
FParent: TWinControl;
FWindowProc: TWndMethod;
FLeft: Integer;
FTop: Integer;
FWidth: Integer;
FHeight: Integer;
FControlStyle: TControlStyle;
FControlState: TControlState;
FVisible: Boolean;
FEnabled: Boolean;
FParentFont: Boolean;
FParentColor: Boolean;
FAlign: TAlign;
FDragMode: TDragMode;
FIsControl: Boolean;
FText: PChar;
FFont: TFont;
FColor: TColor;
FCursor: TCursor;
FDragCursor: TCursor;
FPopupMenu: TPopupMenu;
FHint: string;
FFontHeight: Integer;
FScalingFlags: TScalingFlags;
FShowHint: Boolean;
FParentShowHint: Boolean;
FOnMouseDown: TMouseEvent;
FOnMouseMove: TMouseMoveEvent;
FOnMouseUp: TMouseEvent;
FOnDragDrop: TDragDropEvent;
FOnDragOver: TDragOverEvent;
FOnStartDrag: TStartDragEvent;
FOnEndDrag: TEndDragEvent;
FOnClick: TNotifyEvent;
FOnDblClick: TNotifyEvent;
procedure CheckMenuPopup(const Pos: TSmallPoint);
procedure DoDragMsg(var DragMsg: TCMDrag);
procedure DoMouseDown(var Message: TWMMouse; Button: TMouseButton;
Shift: TShiftState);
procedure DoMouseUp(var Message: TWMMouse; Button: TMouseButton);
procedure FontChanged(Sender: TObject);
function GetBoundsRect: TRect;
function GetClientHeight: Integer;
function GetClientWidth: Integer;
function GetMouseCapture: Boolean;
function GetText: TCaption;
procedure InvalidateControl(IsVisible, IsOpaque: Boolean);
function IsColorStored: Boolean;
function IsFontStored: Boolean;
function IsShowHintStored: Boolean;
procedure ReadIsControl(Reader: TReader);
procedure RequestAlign;
procedure SetAlign(Value: TAlign);
procedure SetBoundsRect(const Rect: TRect);
procedure SetClientHeight(Value: Integer);
procedure SetClientSize(Value: TPoint);
procedure SetClientWidth(Value: Integer);
procedure SetColor(Value: TColor);
procedure SetCursor(Value: TCursor);
procedure SetEnabled(Value: Boolean);
procedure SetFont(Value: TFont);
procedure SetHeight(Value: Integer);
procedure SetLeft(Value: Integer);
procedure SetMouseCapture(Value: Boolean);
procedure SetParentColor(Value: Boolean);
procedure SetParentFont(Value: Boolean);
procedure SetShowHint(Value: Boolean);
procedure SetParentShowHint(Value: Boolean);
procedure SetPopupMenu(Value: TPopupMenu);
procedure SetText(const Value: TCaption);
procedure SetTop(Value: Integer);
procedure SetVisible(Value: Boolean);
procedure SetWidth(Value: Integer);
procedure SetZOrderPosition(Position: Integer);
procedure WriteIsControl(Writer: TWriter);
procedure WMLButtonDown(var Message: TWMLButtonDown); message WM_LBUTTONDOWN;
procedure WMNCLButtonDown(var Message: TWMNCLButtonDown); message WM_NCLBUTTONDOWN;
procedure WMRButtonDown(var Message: TWMRButtonDown); message WM_RBUTTONDOWN;
procedure WMMButtonDown(var Message: TWMMButtonDown); message WM_MBUTTONDOWN;
procedure WMLButtonDblClk(var Message: TWMLButtonDblClk); message WM_LBUTTONDBLCLK;
procedure WMRButtonDblClk(var Message: TWMRButtonDblClk); message WM_RBUTTONDBLCLK;
procedure WMMButtonDblClk(var Message: TWMMButtonDblClk); message WM_MBUTTONDBLCLK;
procedure WMMouseMove(var Message: TWMMouseMove); message WM_MOUSEMOVE;
procedure WMLButtonUp(var Message: TWMLButtonUp); message WM_LBUTTONUP;
procedure WMRButtonUp(var Message: TWMRButtonUp); message WM_RBUTTONUP;
procedure WMMButtonUp(var Message: TWMMButtonUp); message WM_MBUTTONUP;
procedure WMCancelMode(var Message: TWMCancelMode); message WM_CANCELMODE;
procedure CMVisibleChanged(var Message: TMessage); message CM_VISIBLECHANGED;
procedure CMEnabledChanged(var Message: TMessage); message CM_ENABLEDCHANGED;
procedure CMFontChanged(var Message: TMessage); message CM_FONTCHANGED;
procedure CMColorChanged(var Message: TMessage); message CM_COLORCHANGED;
procedure CMParentFontChanged(var Message: TMessage); message CM_PARENTFONTCHANGED;
procedure CMParentColorChanged(var Message: TMessage); message CM_PARENTCOLORCHANGED;
procedure CMParentShowHintChanged(var Message: TMessage); message CM_PARENTSHOWHINTCHANGED;
procedure CMHitTest(var Message: TCMHitTest); message CM_HITTEST;
procedure CMMouseEnter(var Message: TMessage); message CM_MOUSEENTER;
procedure CMMouseLeave(var Message: TMessage); message CM_MOUSELEAVE;
procedure CMDesignHitTest(var Message: TCMDesignHitTest); message CM_DESIGNHITTEST;
protected
procedure ChangeScale(M, D: Integer); dynamic;
procedure Click; dynamic;
procedure DblClick; dynamic;
procedure DefaultHandler(var Message); override;
procedure DefineProperties(Filer: TFiler); override;
procedure DragCanceled; dynamic;
procedure DragOver(Source: TObject; X, Y: Integer; State: TDragState;
var Accept: Boolean); dynamic;
procedure DoEndDrag(Target: TObject; X, Y: Integer); dynamic;
procedure DoStartDrag(var DragObject: TDragObject); dynamic;
function GetClientOrigin: TPoint; virtual;
function GetClientRect: TRect; virtual;
function GetDeviceContext(var WindowHandle: HWnd): HDC; virtual;
function GetDragImages: TCustomImageList; virtual;
function GetPalette: HPALETTE; dynamic;
function GetParentComponent: TComponent; override;
function GetPopupMenu: TPopupMenu; dynamic;
function HasParent: Boolean; override;
procedure MouseDown(Button: TMouseButton; Shift: TShiftState;
X, Y: Integer); dynamic;
procedure MouseMove(Shift: TShiftState; X, Y: Integer); dynamic;
procedure MouseUp(Button: TMouseButton; Shift: TShiftState;
X, Y: Integer); dynamic;
procedure Notification(AComponent: TComponent;
Operation: TOperation); override;
function PaletteChanged(Foreground: Boolean): Boolean; dynamic;
procedure ReadState(Reader: TReader); override;
procedure SendCancelMode(Sender: TControl);
procedure SetDragMode(Value: TDragMode); virtual;
procedure SetParent(AParent: TWinControl); virtual;
procedure SetParentComponent(Value: TComponent); override;
procedure SetName(const Value: TComponentName); override;
procedure SetZOrder(TopMost: Boolean); dynamic;
procedure UpdateBoundsRect(const R: TRect);
procedure VisibleChanging; dynamic;
procedure WndProc(var Message: TMessage); virtual;
property Caption: TCaption read GetText write SetText;
property Color: TColor read FColor write SetColor stored IsColorStored default clWindow;
property DragCursor: TCursor read FDragCursor write FDragCursor default crDrag;
property DragMode: TDragMode read FDragMode write SetDragMode default dmManual;
property Font: TFont read FFont write SetFont stored IsFontStored;
property IsControl: Boolean read FIsControl write FIsControl;
property MouseCapture: Boolean read GetMouseCapture write SetMouseCapture;
property ParentColor: Boolean read FParentColor write SetParentColor default True;
property ParentFont: Boolean read FParentFont write SetParentFont default True;
property ParentShowHint: Boolean read FParentShowHint write SetParentShowHint default True;
property PopupMenu: TPopupMenu read FPopupMenu write SetPopupMenu;
property ScalingFlags: TScalingFlags read FScalingFlags write FScalingFlags;
property Text: TCaption read GetText write SetText;
property WindowText: PChar read FText write FText;
property OnClick: TNotifyEvent read FOnClick write FOnClick;
property OnDblClick: TNotifyEvent read FOnDblClick write FOnDblClick;
property OnDragDrop: TDragDropEvent read FOnDragDrop write FOnDragDrop;
property OnDragOver: TDragOverEvent read FOnDragOver write FOnDragOver;
property OnEndDrag: TEndDragEvent read FOnEndDrag write FOnEndDrag;
property OnMouseDown: TMouseEvent read FOnMouseDown write FOnMouseDown;
property OnMouseMove: TMouseMoveEvent read FOnMouseMove write FOnMouseMove;
property OnMouseUp: TMouseEvent read FOnMouseUp write FOnMouseUp;
property OnStartDrag: TStartDragEvent read FOnStartDrag write FOnStartDrag;
public
constructor Create(AOwner: TComponent); override;
destructor Destroy; override;
procedure BeginDrag(Immediate: Boolean);
procedure BringToFront;
function ClientToScreen(const Point: TPoint): TPoint;
function Dragging: Boolean;
procedure DragDrop(Source: TObject; X, Y: Integer); dynamic;
procedure EndDrag(Drop: Boolean);
function GetTextBuf(Buffer: PChar; BufSize: Integer): Integer;
function GetTextLen: Integer;
procedure Hide;
procedure Invalidate; virtual;
function Perform(Msg: Cardinal; WParam, LParam: Longint): Longint;
procedure Refresh;
procedure Repaint; virtual;
function ScreenToClient(const Point: TPoint): TPoint;
procedure SendToBack;
procedure SetBounds(ALeft, ATop, AWidth, AHeight: Integer); virtual;
procedure SetTextBuf(Buffer: PChar);
procedure Show;
procedure Update; virtual;
property Align: TAlign read FAlign write SetAlign default alNone;
property BoundsRect: TRect read GetBoundsRect write SetBoundsRect;
property ClientHeight: Integer read GetClientHeight write SetClientHeight stored False;
property ClientOrigin: TPoint read GetClientOrigin;
property ClientRect: TRect read GetClientRect;
property ClientWidth: Integer read GetClientWidth write SetClientWidth stored False;
property ControlState: TControlState read FControlState write FControlState;
property ControlStyle: TControlStyle read FControlStyle write FControlStyle;
property Parent: TWinControl read FParent write SetParent;
property ShowHint: Boolean read FShowHint write SetShowHint stored IsShowHintStored;
property Visible: Boolean read FVisible write SetVisible default True;
property Enabled: Boolean read FEnabled write SetEnabled default True;
property WindowProc: TWndMethod read FWindowProc write FWindowProc;
published
property Left: Integer read FLeft write SetLeft;
property Top: Integer read FTop write SetTop;
property Width: Integer read FWidth write SetWidth;
property Height: Integer read FHeight write SetHeight;
property Cursor: TCursor read FCursor write SetCursor default crDefault;
property Hint: string read FHint write FHint;
end;
TControlClass = class of TControl;
TCreateParams = record
Caption: PChar;
Style: Longint;
ExStyle: Longint;
X, Y: Integer;
Width, Height: Integer;
WndParent: HWnd;
Param: Pointer;
WindowClass: TWndClass;
WinClassName: array[0..63] of Char;
end;
TImeMode = (imDisable, imClose, imOpen, imDontCare,
imSAlpha, imAlpha, imHira, imSKata, imKata,
imChinese, imSHanguel, imHanguel);
TImeName = type string;
TWinControl = class(TControl)
private
FObjectInstance: Pointer;
FDefWndProc: Pointer;
FControls: TList;
FWinControls: TList;
FTabList: TList;
FBrush: TBrush;
FHandle: HWnd;
FParentWindow: HWnd;
FTabStop: Boolean;
FCtl3D: Boolean;
FParentCtl3D: Boolean;
FShowing: Boolean;
FTabOrder: Integer;
FAlignLevel: Word;
FHelpContext: THelpContext;
FImeMode: TImeMode;
FImeName: TImeName;
FOnKeyDown: TKeyEvent;
FOnKeyPress: TKeyPressEvent;
FOnKeyUp: TKeyEvent;
FOnEnter: TNotifyEvent;
FOnExit: TNotifyEvent;
procedure AlignControl(AControl: TControl);
function GetControl(Index: Integer): TControl;
function GetControlCount: Integer;
function GetHandle: HWnd;
function GetTabOrder: TTabOrder;
procedure Insert(AControl: TControl);
procedure InvalidateFrame;
function IsCtl3DStored: Boolean;
function PrecedingWindow(Control: TWinControl): HWnd;
procedure Remove(AControl: TControl);
procedure RemoveFocus(Removing: Boolean);
procedure SetCtl3D(Value: Boolean);
procedure SetParentCtl3D(Value: Boolean);
procedure SetParentWindow(Value: HWnd);
procedure SetTabOrder(Value: TTabOrder);
procedure SetTabStop(Value: Boolean);
procedure SetZOrderPosition(Position: Integer);
procedure UpdateTabOrder(Value: TTabOrder);
procedure UpdateBounds;
procedure UpdateShowing;
function IsMenuKey(var Message: TWMKey): Boolean;
procedure WMPaint(var Message: TWMPaint); message WM_PAINT;
procedure WMCommand(var Message: TWMCommand); message WM_COMMAND;
procedure WMNotify(var Message: TWMNotify); message WM_NOTIFY;
procedure WMSysColorChange(var Message: TWMSysColorChange); message WM_SYSCOLORCHANGE;
procedure WMHScroll(var Message: TWMHScroll); message WM_HSCROLL;
procedure WMVScroll(var Message: TWMVScroll); message WM_VSCROLL;
procedure WMCompareItem(var Message: TWMCompareItem); message WM_COMPAREITEM;
procedure WMDeleteItem(var Message: TWMDeleteItem); message WM_DELETEITEM;
procedure WMDrawItem(var Message: TWMDrawItem); message WM_DRAWITEM;
procedure WMMeasureItem(var Message: TWMMeasureItem); message WM_MEASUREITEM;
procedure WMEraseBkgnd(var Message: TWmEraseBkgnd); message WM_ERASEBKGND;
procedure WMWindowPosChanged(var Message: TWMWindowPosChanged); message WM_WINDOWPOSCHANGED;
procedure WMSize(var Message: TWMSize); message WM_SIZE;
procedure WMMove(var Message: TWMMove); message WM_MOVE;
procedure WMSetCursor(var Message: TWMSetCursor); message WM_SETCURSOR;
procedure WMKeyDown(var Message: TWMKeyDown); message WM_KEYDOWN;
procedure WMSysKeyDown(var Message: TWMKeyDown); message WM_SYSKEYDOWN;
procedure WMKeyUp(var Message: TWMKeyUp); message WM_KEYUP;
procedure WMSysKeyUp(var Message: TWMKeyUp); message WM_SYSKEYUP;
procedure WMChar(var Message: TWMChar); message WM_CHAR;
procedure WMSysCommand(var Message: TWMSysCommand); message WM_SYSCOMMAND;
procedure WMCharToItem(var Message: TWMCharToItem); message WM_CHARTOITEM;
procedure WMParentNotify(var Message: TWMParentNotify); message WM_PARENTNOTIFY;
procedure WMVKeyToItem(var Message: TWMVKeyToItem); message WM_VKEYTOITEM;
procedure WMDestroy(var Message: TWMDestroy); message WM_DESTROY;
procedure WMNCDestroy(var Message: TWMNCDestroy); message WM_NCDESTROY;
procedure WMNCHitTest(var Message: TWMNCHitTest); message WM_NCHITTEST;
procedure WMQueryNewPalette(var Message: TMessage); message WM_QUERYNEWPALETTE;
procedure WMPaletteChanged(var Message: TMessage); message WM_PALETTECHANGED;
procedure WMWinIniChange(var Message: TMessage); message WM_WININICHANGE;
procedure WMFontChange(var Message: TMessage); message WM_FONTCHANGE;
procedure WMTimeChange(var Message: TMessage); message WM_TIMECHANGE;
procedure WMSetFocus(var Message: TWMSetFocus); message WM_SETFOCUS;
procedure WMKillFocus(var Message: TWMSetFocus); message WM_KILLFOCUS;
procedure WMIMEStartComp(var Message: TMessage); message WM_IME_STARTCOMPOSITION;
procedure WMIMEEndComp(var Message: TMessage); message WM_IME_ENDCOMPOSITION;
procedure CMChildKey(var Message: TMessage); message CM_CHILDKEY;
procedure CMDialogKey(var Message: TCMDialogKey); message CM_DIALOGKEY;
procedure CMDialogChar(var Message: TCMDialogChar); message CM_DIALOGCHAR;
procedure CMFocusChanged(var Message: TCMFocusChanged); message CM_FOCUSCHANGED;
procedure CMVisibleChanged(var Message: TMessage); message CM_VISIBLECHANGED;
procedure CMEnabledChanged(var Message: TMessage); message CM_ENABLEDCHANGED;
procedure CMColorChanged(var Message: TMessage); message CM_COLORCHANGED;
procedure CMFontChanged(var Message: TMessage); message CM_FONTCHANGED;
procedure CMCursorChanged(var Message: TMessage); message CM_CURSORCHANGED;
procedure CMCtl3DChanged(var Message: TMessage); message CM_CTL3DCHANGED;
procedure CMParentCtl3DChanged(var Message: TMessage); message CM_PARENTCTL3DCHANGED;
procedure CMShowingChanged(var Message: TMessage); message CM_SHOWINGCHANGED;
procedure CMShowHintChanged(var Message: TMessage); message CM_SHOWHINTCHANGED;
procedure CMEnter(var Message: TCMEnter); message CM_ENTER;
procedure CMExit(var Message: TCMExit); message CM_EXIT;
procedure CMDesignHitTest(var Message: TCMDesignHitTest); message CM_DESIGNHITTEST;
procedure CMSysColorChange(var Message: TMessage); message CM_SYSCOLORCHANGE;
procedure CMWinIniChange(var Message: TWMWinIniChange); message CM_WININICHANGE;
procedure CMFontChange(var Message: TMessage); message CM_FONTCHANGE;
procedure CMTimeChange(var Message: TMessage); message CM_TIMECHANGE;
procedure CMDrag(var Message: TCMDrag); message CM_DRAG;
procedure CNKeyDown(var Message: TWMKeyDown); message CN_KEYDOWN;
procedure CNKeyUp(var Message: TWMKeyUp); message CN_KEYUP;
procedure CNChar(var Message: TWMChar); message CN_CHAR;
procedure CNSysKeyDown(var Message: TWMKeyDown); message CN_SYSKEYDOWN;
procedure CNSysChar(var Message: TWMChar); message CN_SYSCHAR;
procedure CMControlListChange(var Message: TMessage); message CM_CONTROLLISTCHANGE;
procedure CMRecreateWnd(var Message: TMessage); message CM_RECREATEWND;
procedure CMInvalidate(var Message: TMessage); message CM_INVALIDATE;
protected
FInImeComposition: Boolean;
procedure AlignControls(AControl: TControl; var Rect: TRect); virtual;
procedure ChangeScale(M, D: Integer); override;
procedure CreateHandle; virtual;
procedure CreateParams(var Params: TCreateParams); virtual;
procedure CreateSubClass(var Params: TCreateParams;
ControlClassName: PChar);
procedure CreateWindowHandle(const Params: TCreateParams); virtual;
procedure CreateWnd; virtual;
procedure DefaultHandler(var Message); override;
procedure DestroyHandle;
procedure DestroyWindowHandle; virtual;
procedure DestroyWnd; virtual;
procedure DoEnter; dynamic;
procedure DoExit; dynamic;
function DoKeyDown(var Message: TWMKey): Boolean;
function DoKeyPress(var Message: TWMKey): Boolean;
function DoKeyUp(var Message: TWMKey): Boolean;
function FindNextControl(CurControl: TWinControl;
GoForward, CheckTabStop, CheckParent: Boolean): TWinControl;
procedure FixupTabList;
procedure GetChildren(Proc: TGetChildProc); override;
function GetClientOrigin: TPoint; override;
function GetClientRect: TRect; override;
function GetDeviceContext(var WindowHandle: HWnd): HDC; override;
function IsControlMouseMsg(var Message: TWMMouse): Boolean;
procedure KeyDown(var Key: Word; Shift: TShiftState); dynamic;
procedure KeyUp(var Key: Word; Shift: TShiftState); dynamic;
procedure KeyPress(var Key: Char); dynamic;
procedure MainWndProc(var Message: TMessage);
procedure NotifyControls(Msg: Word);
procedure PaintControls(DC: HDC; First: TControl);
procedure PaintHandler(var Message: TWMPaint);
procedure PaintWindow(DC: HDC); virtual;
function PaletteChanged(Foreground: Boolean): Boolean; override;
procedure ReadState(Reader: TReader); override;
procedure RecreateWnd;
procedure ResetIme;
function ResetImeComposition(Action: DWORD): Boolean;
procedure ScaleControls(M, D: Integer);
procedure SelectFirst;
procedure SelectNext(CurControl: TWinControl;
GoForward, CheckTabStop: Boolean);
procedure SetChildOrder(Child: TComponent; Order: Integer); override;
procedure SetIme;
function SetImeCompositionWindow(hWnd: HWND; Font: TFont;
XPos, YPos: Integer): Boolean;
procedure SetZOrder(TopMost: Boolean); override;
procedure ShowControl(AControl: TControl); virtual;
procedure WndProc(var Message: TMessage); override;
property Ctl3D: Boolean read FCtl3D write SetCtl3D stored IsCtl3DStored;
property DefWndProc: Pointer read FDefWndProc write FDefWndProc;
property ImeMode: TImeMode read FImeMode write FImeMode default imDontCare;
property ImeName: TImeName read FImeName write FImeName;
property ParentCtl3D: Boolean read FParentCtl3D write SetParentCtl3D default True;
property WindowHandle: HWnd read FHandle write FHandle;
property OnEnter: TNotifyEvent read FOnEnter write FOnEnter;
property OnExit: TNotifyEvent read FOnExit write FOnExit;
property OnKeyDown: TKeyEvent read FOnKeyDown write FOnKeyDown;
property OnKeyPress: TKeyPressEvent read FOnKeyPress write FOnKeyPress;
property OnKeyUp: TKeyEvent read FOnKeyUp write FOnKeyUp;
public
constructor Create(AOwner: TComponent); override;
constructor CreateParented(ParentWindow: HWnd);
destructor Destroy; override;
procedure Broadcast(var Message);
function CanFocus: Boolean;
function ContainsControl(Control: TControl): Boolean;
function ControlAtPos(const Pos: TPoint; AllowDisabled: Boolean): TControl;
procedure DisableAlign;
procedure EnableAlign;
function Focused: Boolean;
procedure GetTabOrderList(List: TList); dynamic;
function HandleAllocated: Boolean;
procedure HandleNeeded;
procedure InsertControl(AControl: TControl);
procedure Invalidate; override;
procedure PaintTo(DC: HDC; X, Y: Integer);
procedure RemoveControl(AControl: TControl);
procedure Realign;
procedure Repaint; override;
procedure ScaleBy(M, D: Integer);
procedure ScrollBy(DeltaX, DeltaY: Integer);
procedure SetBounds(ALeft, ATop, AWidth, AHeight: Integer); override;
procedure SetFocus; virtual;
procedure Update; override;
procedure UpdateControlState;
property Brush: TBrush read FBrush;
property Controls[Index: Integer]: TControl read GetControl;
property ControlCount: Integer read GetControlCount;
property Handle: HWnd read GetHandle;
property ParentWindow: HWnd read FParentWindow write SetParentWindow;
property Showing: Boolean read FShowing;
property TabOrder: TTabOrder read GetTabOrder write SetTabOrder default -1;
property TabStop: Boolean read FTabStop write SetTabStop default False;
published
property HelpContext: THelpContext read FHelpContext write FHelpContext default 0;
end;
TGraphicControl = class(TControl)
private
FCanvas: TCanvas;
procedure WMPaint(var Message: TWMPaint); message WM_PAINT;
protected
procedure Paint; virtual;
property Canvas: TCanvas read FCanvas;
public
constructor Create(AOwner: TComponent); override;
destructor Destroy; override;
end;
TCustomControl = class(TWinControl)
private
FCanvas: TCanvas;
procedure WMPaint(var Message: TWMPaint); message WM_PAINT;
protected
procedure Paint; virtual;
procedure PaintWindow(DC: HDC); override;
property Canvas: TCanvas read FCanvas;
public
constructor Create(AOwner: TComponent); override;
destructor Destroy; override;
end;
THintWindow = class(TCustomControl)
private
procedure CMTextChanged(var Message: TMessage); message CM_TEXTCHANGED;
protected
procedure CreateParams(var Params: TCreateParams); override;
procedure Paint; override;
public
constructor Create(AOwner: TComponent); override;
procedure ActivateHint(Rect: TRect; const AHint: string); virtual;
function IsHintMsg(var Msg: TMsg): Boolean; virtual;
procedure ReleaseHandle;
property Caption;
property Color;
property Canvas;
end;
THintWindowClass = class of THintWindow;
{ TChangeLink }
TChangeLink = class(TObject)
private
FSender: TCustomImageList;
FOnChange: TNotifyEvent;
public
destructor Destroy; override;
procedure Change; dynamic;
property OnChange: TNotifyEvent read FOnChange write FOnChange;
property Sender: TCustomImageList read FSender write FSender;
end;
{ TCustomImageList }
TDrawingStyle = (dsFocus, dsSelected, dsNormal, dsTransparent);
TImageType = (itImage, itMask);
TResType = (rtBitmap, rtCursor, rtIcon);
TOverlay = 0..3;
TLoadResource = (lrDefaultColor, lrDefaultSize, lrFromFile,
lrMap3DColors, lrTransparent, lrMonoChrome);
TLoadResources = set of TLoadResource;
TCustomImageList = class(TComponent)
private
FHeight: Integer;
FWidth: Integer;
FAllocBy: Integer;
FHandle: HImageList;
FDrawingStyle: TDrawingStyle;
FMasked: Boolean;
FShareImages: Boolean;
FImageType: TImageType;
FBkColor: TColor;
FBlendColor: TColor;
FClients: TList;
FDragHandle: HWND;
FDragging: Boolean;
FDragCursor: TCursor;
FBitmap: TBitmap;
FOnChange: TNotifyEvent;
procedure AssignTo(Dest: TPersistent); override;
procedure InitBitmap;
procedure CheckImage(Image: TGraphic);
procedure CombineDragCursor;
procedure CopyImages(Value: HImageList);
procedure CreateImageList;
procedure FreeHandle;
function GetCount: Integer;
function GetBkColor: TColor;
function GetHandle: HImageList;
function GetImageHandle(Image: TBitmap): HBITMAP;
procedure InsertImage(Index: Integer; Image, Mask: TBitmap; MaskColor: TColor);
procedure ReadData(Stream: TStream);
procedure SetBkColor(Value: TColor);
procedure SetDragCursor(Value: TCursor);
procedure SetHandle(Value: HImageList);
procedure SetHeight(Value: Integer);
procedure SetNewDimensions(Value: HImageList);
procedure SetWidth(Value: Integer);
procedure WriteData(Stream: TStream);
protected
procedure Change; dynamic;
procedure DefineProperties(Filer: TFiler); override;
procedure GetImages(Index: Integer; Image, Mask: TBitmap);
procedure HandleNeeded;
procedure Initialize;
property BlendColor: TColor read FBlendColor write FBlendColor default clNone;
property BkColor: TColor read GetBkColor write SetBkColor default clNone;
property AllocBy: Integer read FAllocBy write FAllocBy default 4;
property DrawingStyle: TDrawingStyle read FDrawingStyle write FDrawingStyle default dsNormal;
property Height: Integer read FHeight write SetHeight default 16;
property ImageType: TImageType read FImageType write FImageType default itImage;
property Masked: Boolean read FMasked write FMasked default True;
property OnChange: TNotifyEvent read FOnChange write FOnChange;
property ShareImages: Boolean read FShareImages write FShareImages default False;
property Width: Integer read FWidth write SetWidth default 16;
public
constructor Create(AOwner: TComponent); override;
constructor CreateSize(AWidth, AHeight: Integer);
destructor Destroy; override;
procedure Assign(Source: TPersistent); override;
function Add(Image, Mask: TBitmap): Integer;
function AddIcon(Image: TIcon): Integer;
procedure AddImages(Value: TCustomImageList);
function AddMasked(Image: TBitmap; MaskColor: TColor): Integer;
function BeginDrag(Window: HWND; X, Y: Integer): Boolean;
procedure Clear;
procedure Delete(Index: Integer);
function DragLock(Window: HWND; XPos, YPos: Integer): Boolean;
function DragMove(X, Y: Integer): Boolean;
procedure DragUnlock;
procedure Draw(Canvas: TCanvas; X, Y, Index: Integer);
procedure DrawOverlay(Canvas: TCanvas; X, Y: Integer;
ImageIndex: Integer; Overlay: TOverlay);
function EndDrag: Boolean;
function FileLoad(ResType: TResType; Name: string;
MaskColor: TColor): Boolean;
procedure GetBitmap(Index: Integer; Image: TBitmap);
function GetHotSpot: TPoint;
procedure GetIcon(Index: Integer; Image: TIcon);
function GetImageBitmap: HBITMAP;
function GetMaskBitmap: HBITMAP;
function GetResource(ResType: TResType; Name: string;
Width: Integer; LoadFlags: TLoadResources; MaskColor: TColor): Boolean;
function HandleAllocated: Boolean;
procedure HideDragImage;
procedure Insert(Index: Integer; Image, Mask: TBitmap);
procedure InsertIcon(Index: Integer; Image: TIcon);
procedure InsertMasked(Index: Integer; Image: TBitmap; MaskColor: TColor);
procedure Move(CurIndex, NewIndex: Integer);
function Overlay(ImageIndex: Integer; Overlay: TOverlay): Boolean;
procedure RegisterChanges(Value: TChangeLink);
function ResourceLoad(ResType: TResType; Name: string;
MaskColor: TColor): Boolean;
procedure Replace(Index: Integer; Image, Mask: TBitmap);
procedure ReplaceIcon(Index: Integer; Image: TIcon);
procedure ReplaceMasked(Index: Integer; NewImage: TBitmap; MaskColor: TColor);
function SetDragImage(Index, HotSpotX, HotSpotY: Integer): Boolean;
procedure ShowDragImage;
procedure UnRegisterChanges(Value: TChangeLink);
property Count: Integer read GetCount;
property DragCursor: TCursor read FDragCursor write SetDragCursor;
property Dragging: Boolean read FDragging;
property Handle: HImageList read GetHandle write SetHandle;
end;
{ TImageList }
TImageList = class(TCustomImageList)
published
property BlendColor;
property BkColor;
property AllocBy;
property DrawingStyle;
property Height;
property ImageType;
property Masked;
property OnChange;
property ShareImages;
property Width;
end;
function IsDragObject(Sender: TObject): Boolean;
function FindControl(Handle: HWnd): TWinControl;
function FindVCLWindow(const Pos: TPoint): TWinControl;
function FindDragTarget(const Pos: TPoint; AllowDisabled: Boolean): TControl;
function GetCaptureControl: TControl;
procedure SetCaptureControl(Control: TControl);
procedure CancelDrag;
function CursorToString(Cursor: TCursor): string;
function StringToCursor(const S: string): TCursor;
procedure GetCursorValues(Proc: TGetStrProc);
function CursorToIdent(Cursor: Longint; var Ident: string): Boolean;
function IdentToCursor(const Ident: string; var Cursor: Longint): Boolean;
function GetShortHint(const Hint: string): string;
function GetLongHint(const Hint: string): string;
var
CreationControl: TWinControl = nil;
function InitWndProc(HWindow: HWnd; Message, WParam: Longint;
LParam: Longint): Longint; stdcall;
const
CTL3D_ALL = $FFFF;
var
NewStyleControls: Boolean;
function SendAppMessage(Msg: Cardinal; WParam, LParam: Longint): Longint;
procedure MoveWindowOrg(DC: HDC; DX, DY: Integer);
procedure SetImeMode(Handle: HWnd; Mode: TImeMode);
function Win32NLSEnableIME(Handle: HWnd; Enable: Boolean): Boolean;
function Imm32GetContext(hWnd: HWND): HIMC;
function Imm32ReleaseContext(hWnd: HWND; hImc: HIMC): Boolean;
function Imm32GetConversionStatus(hImc: HIMC; var Conversion, Sentence: DWORD): Boolean;
function Imm32SetConversionStatus(hImc: HIMC; Conversion, Sentence: DWORD): Boolean;
function Imm32SetOpenStatus(hImc: HIMC; fOpen: Boolean): Boolean;
function Imm32SetCompositionWindow(hImc: HIMC; lpCompForm: PCOMPOSITIONFORM): Boolean;
function Imm32SetCompositionFont(hImc: HIMC; lpLogfont: PLOGFONTA): Boolean;
function Imm32GetCompositionString(hImc: HIMC; dWord1: DWORD; lpBuf: pointer; dwBufLen: DWORD): Longint;
function Imm32IsIME(hKl: HKL): Boolean;
function Imm32NotifyIME(hImc: HIMC; dwAction, dwIndex, dwValue: DWORD): Boolean;
implementation
uses Consts, Forms;
var
WindowAtom: TAtom;
ControlAtom: TAtom;
{ Initialization window procedure }
function InitWndProc(HWindow: HWnd; Message, WParam,
LParam: Longint): Longint;
begin
CreationControl.FHandle := HWindow;
SetWindowLong(HWindow, GWL_WNDPROC,
Longint(CreationControl.FObjectInstance));
if (GetWindowLong(HWindow, GWL_STYLE) and WS_CHILD <> 0) and
(GetWindowLong(HWindow, GWL_ID) = 0) then
SetWindowLong(HWindow, GWL_ID, HWindow);
SetProp(HWindow, MakeIntAtom(ControlAtom), THandle(CreationControl));
SetProp(HWindow, MakeIntAtom(WindowAtom), THandle(CreationControl));
asm
PUSH LParam
PUSH WParam
PUSH Message
PUSH HWindow
MOV EAX,CreationControl
MOV CreationControl,0
CALL [EAX].TWinControl.FObjectInstance
MOV Result,EAX
end;
end;
{ Find a TWinControl given a window handle }
function FindControl(Handle: HWnd): TWinControl;
begin
Result := nil;
if Handle <> 0 then
begin
Result := Pointer(GetProp(Handle, MakeIntAtom(ControlAtom)));
end;
end;
{ Send message to application object }
function SendAppMessage(Msg: Cardinal; WParam, LParam: Longint): Longint;
begin
if Application.Handle <> 0 then
Result := SendMessage(Application.Handle, Msg, WParam, LParam) else
Result := 0;
end;
{ Cursor translation function }
type
TCursorEntry = record
Value: TCursor;
Name: string;
end;
const
DeadCursors = 1;
const
Cursors: array[0..19] of TCursorEntry = (
(Value: crDefault; Name: 'crDefault'),
(Value: crArrow; Name: 'crArrow'),
(Value: crCross; Name: 'crCross'),
(Value: crIBeam; Name: 'crIBeam'),
(Value: crSizeNESW; Name: 'crSizeNESW'),
(Value: crSizeNS; Name: 'crSizeNS'),
(Value: crSizeNWSE; Name: 'crSizeNWSE'),
(Value: crSizeWE; Name: 'crSizeWE'),
(Value: crUpArrow; Name: 'crUpArrow'),
(Value: crHourGlass; Name: 'crHourGlass'),
(Value: crDrag; Name: 'crDrag'),
(Value: crNoDrop; Name: 'crNoDrop'),
(Value: crHSplit; Name: 'crHSplit'),
(Value: crVSplit; Name: 'crVSplit'),
(Value: crMultiDrag; Name: 'crMultiDrag'),
(Value: crSQLWait; Name: 'crSQLWait'),
(Value: crNo; Name: 'crNo'),
(Value: crAppStart; Name: 'crAppStart'),
(Value: crHelp; Name: 'crHelp'),
{ Dead cursors }
(Value: crSize; Name: 'crSize'));
function CursorToString(Cursor: TCursor): string;
begin
if not CursorToIdent(Cursor, Result) then FmtStr(Result, '%d', [Cursor]);
end;
function StringToCursor(const S: string): TCursor;
var
L: Longint;
begin
if not IdentToCursor(S, L) then L := StrToInt(S);
Result := L;
end;
procedure GetCursorValues(Proc: TGetStrProc);
var
I: Integer;
begin
for I := Low(Cursors) to High(Cursors) - DeadCursors do Proc(Cursors[I].Name);
end;
function CursorToIdent(Cursor: Longint; var Ident: string): Boolean;
var
I: Integer;
begin
for I := Low(Cursors) to High(Cursors) do
if Cursors[I].Value = Cursor then
begin
Result := True;
Ident := Cursors[I].Name;
Exit;
end;
Result := False;
end;
function IdentToCursor(const Ident: string; var Cursor: Longint): Boolean;
var
I: Integer;
begin
for I := Low(Cursors) to High(Cursors) do
if CompareText(Cursors[I].Name, Ident) = 0 then
begin
Result := True;
Cursor := Cursors[I].Value;
Exit;
end;
Result := False;
end;
function GetShortHint(const Hint: string): string;
var
I: Integer;
begin
I := AnsiPos('|', Hint);
if I = 0 then
Result := Hint else
Result := Copy(Hint, 1, I - 1);
end;
function GetLongHint(const Hint: string): string;
var
I: Integer;
begin
I := AnsiPos('|', Hint);
if I = 0 then
Result := Hint else
Result := Copy(Hint, I + 1, Maxint);
end;
{ Mouse capture management }
var
CaptureControl: TControl = nil;
function GetCaptureControl: TControl;
begin
Result := FindControl(GetCapture);
if (Result <> nil) and (CaptureControl <> nil) and
(CaptureControl.Parent = Result) then Result := CaptureControl;
end;
procedure SetCaptureControl(Control: TControl);
begin
ReleaseCapture;
CaptureControl := nil;
if Control <> nil then
begin
if not (Control is TWinControl) then
begin
if Control.Parent = nil then Exit;
CaptureControl := Control;
Control := Control.Parent;
end;
SetCapture(TWinControl(Control).Handle);
end;
end;
{ Drag-and-drop management }
var
DragControl: TControl;
DragObject: TDragObject;
DragFreeObject: Boolean;
DragTarget: Pointer;
DragHandle: HWND;
DragCapture: HWND;
DragStartPos: TPoint;
DragPos: TPoint;
DragSaveCursor: HCURSOR;
DragActive: Boolean;
DragImageList: TCustomImageList;
{ TDragObject }
procedure DragTo(const Pos: TPoint); forward;
procedure DragDone(Drop: Boolean); forward;
function IsDragObject(Sender: TObject): Boolean;
var
SenderClass: TClass;
begin
SenderClass := Sender.ClassType;
Result := True;
while SenderClass <> nil do
if SenderClass.ClassName = TDragObject.ClassName then
Exit else
SenderClass := SenderClass.ClassParent;
Result := False;
end;
function TDragObject.Instance: THandle;
begin
Result := System.HInstance;
end;
function TDragObject.GetName: string;
begin
Result := ClassName;
end;
function TDragObject.GetDragImages: TCustomImageList;
begin
Result := nil;
end;
function TDragObject.Capture: HWND;
begin
Result := AllocateHWND(MouseMsg);
SetCapture(Result);
end;
procedure TDragObject.ReleaseCapture(Handle: HWND);
begin
Windows.ReleaseCapture;
DeallocateHWND(Handle);
end;
function TDragObject.GetDragCursor(Accepted: Boolean; X, Y: Integer): TCursor;
begin
if Accepted then
Result := crDrag else
Result := crNoDrop;
end;
procedure TDragObject.Finished(Target: TObject; X, Y: Integer; Accepted: Boolean);
begin
end;
procedure TDragObject.HideDragImage;
begin
end;
procedure TDragObject.ShowDragImage;
begin
end;
procedure TDragObject.MouseMsg(var Msg: TMessage);
var
P: TPoint;
begin
try
case Msg.Msg of
WM_MOUSEMOVE:
begin
P := SmallPointToPoint(TWMMouse(Msg).Pos);
ClientToScreen(DragCapture, P);
DragTo(P);
end;
WM_LBUTTONUP:
DragDone(True);
end;
except
if DragControl <> nil then DragDone(False);
raise;
end;
end;
{ TDragControlObject }
constructor TDragControlObject.Create(AControl: TControl);
begin
FControl := AControl;
end;
function TDragControlObject.GetDragImages: TCustomImageList;
begin
Result := Control.GetDragImages;
end;
procedure TDragControlObject.HideDragImage;
begin
if Control.GetDragImages <> nil then
Control.GetDragImages.HideDragImage;
end;
procedure TDragControlObject.ShowDragImage;
begin
if Control.GetDragImages <> nil then
Control.GetDragImages.ShowDragImage;
end;
function TDragControlObject.GetDragCursor(Accepted: Boolean; X, Y: Integer): TCursor;
begin
if Accepted then
Result := Control.DragCursor else
Result := crNoDrop;
end;
procedure TDragControlObject.Finished(Target: TObject; X, Y: Integer; Accepted: Boolean);
begin
if not Accepted then Control.DragCanceled;
Control.DoEndDrag(Target, X, Y);
end;
{ Drag drop functions }
function DragMessage(Handle: HWND; Msg: TDragMessage;
Source: TDragObject; Target: Pointer; const Pos: TPoint): Longint;
var
DragRec: TDragRec;
begin
Result := 0;
if Handle <> 0 then
begin
DragRec.Pos := Pos;
DragRec.Target := Target;
DragRec.Source := Source;
Result := SendMessage(Handle, CM_DRAG, Longint(Msg), Longint(@DragRec));
end;
end;
function IsDelphiHandle(Handle: HWND): Boolean;
begin
Result := (Handle <> 0) and
(GetProp(Handle, MakeIntAtom(WindowAtom)) <> 0);
end;
function DragFindWindow(const Pos: TPoint): HWND;
begin
Result := WindowFromPoint(Pos);
while Result <> 0 do
if not IsDelphiHandle(Result) then
Result := GetParent(Result) else
Exit;
end;
function DragFindTarget(const Pos: TPoint; var Handle: HWND): Pointer;
begin
Handle := DragFindWindow(Pos);
Result := Pointer(DragMessage(Handle, dmFindTarget, DragObject, nil, Pos));
end;
function DoDragOver(DragMsg: TDragMessage): Boolean;
begin
Result := False;
if DragTarget <> nil then
Result := LongBool(DragMessage(DragHandle, DragMsg, DragObject, DragTarget,
DragPos));
end;
procedure DragTo(const Pos: TPoint);
const
Threshold = 5;
var
DragCursor: TCursor;
Target: TControl;
TargetHandle: HWND;
begin
if DragActive or (Abs(DragStartPos.X - Pos.X) >= Threshold) or
(Abs(DragStartPos.Y - Pos.Y) >= Threshold) then
begin
if not DragActive and (DragImageList <> nil) then
with DragStartPos do DragImageList.BeginDrag(GetDeskTopWindow, X, Y);
DragActive := True;
Target := DragFindTarget(Pos, TargetHandle);
if Target <> DragTarget then
begin
DoDragOver(dmDragLeave);
DragTarget := Target;
DragHandle := TargetHandle;
DragPos := Pos;
DoDragOver(dmDragEnter);
end;
DragPos := Pos;
DragCursor := DragObject.GetDragCursor(DoDragOver(dmDragMove), Pos.X, Pos.Y);
if DragImageList <> nil then
begin
if (Target = nil) or (csDisplayDragImage in Target.ControlStyle) then
begin
DragImageList.DragCursor := DragCursor;
if not DragImageList.Dragging then
DragImageList.BeginDrag(GetDeskTopWindow, Pos.X, Pos.Y)
else DragImageList.DragMove(Pos.X, Pos.Y);
end
else begin
DragImageList.EndDrag;
Windows.SetCursor(Screen.Cursors[DragCursor]);
end;
end else
Windows.SetCursor(Screen.Cursors[DragCursor]);
end;
end;
procedure DragInit(ADragObject: TDragObject; Immediate: Boolean);
begin
DragObject := ADragObject;
DragTarget := nil;
GetCursorPos(DragStartPos);
DragSaveCursor := Windows.GetCursor;
DragActive := Immediate;
DragImageList := DragObject.GetDragImages;
DragCapture := DragObject.Capture;
if DragActive and (DragImageList <> nil) then
with DragStartPos do DragImageList.BeginDrag(GetDeskTopWindow, X, Y);
if DragActive then DragTo(DragStartPos);
end;
procedure DragInitControl(Control: TControl; Immediate: Boolean);
var
DragObject: TDragObject;
begin
DragControl := Control;
try
DragObject := nil;
DragFreeObject := False;
Control.DoStartDrag(DragObject);
if DragObject = nil then
begin
DragObject := TDragControlObject.Create(Control);
DragFreeObject := True;
end;
DragInit(DragObject, Immediate);
except
DragControl := nil;
raise;
end;
end;
procedure DragDone(Drop: Boolean);
var
DragSave: TDragObject;
Accepted: Boolean;
DragMsg: TDragMessage;
TargetPos: TPoint;
begin
DragSave := nil;
DragControl := nil;
try
DragObject.ReleaseCapture(DragCapture);
DragSave := DragObject;
if DragImageList <> nil then
DragImageList.EndDrag else
Windows.SetCursor(DragSaveCursor);
try
if TObject(DragTarget) is TControl then
TargetPos := TControl(DragTarget).ScreenToClient(DragPos) else
TargetPos := DragPos;
Accepted := DragActive and DoDragOver(dmDragLeave) and Drop;
DragObject := nil;
DragMsg := dmDragDrop;
if not Accepted then
begin
DragMsg := dmDragCancel;
DragPos.X := 0;
DragPos.Y := 0;
TargetPos.X := 0;
TargetPos.Y := 0;
end;
DragMessage(DragHandle, DragMsg, DragSave, DragTarget, DragPos);
DragSave.Finished(DragTarget, TargetPos.X, TargetPos.Y, Accepted);
DragTarget := nil;
finally
DragObject := nil;
end;
finally
if DragFreeObject then DragSave.Free;
end;
end;
procedure CancelDrag;
begin
if DragObject <> nil then DragDone(False);
DragControl := nil;
end;
function FindVCLWindow(const Pos: TPoint): TWinControl;
var
Handle: HWND;
begin
Handle := WindowFromPoint(Pos);
Result := nil;
while Handle <> 0 do
begin
Result := FindControl(Handle);
if Result <> nil then Exit;
Handle := GetParent(Handle);
end;
end;
function FindDragTarget(const Pos: TPoint; AllowDisabled: Boolean): TControl;
var
Window: TWinControl;
Control: TControl;
begin
Result := nil;
Window := FindVCLWindow(Pos);
if Window <> nil then
begin
Result := Window;
Control := Window.ControlAtPos(Window.ScreenToClient(Pos), AllowDisabled);
if Control <> nil then Result := Control;
end;
end;
{ List helpers }
procedure ListAdd(var List: TList; Item: Pointer);
begin
if List = nil then List := TList.Create;
List.Add(Item);
end;
procedure ListRemove(var List: TList; Item: Pointer);
begin
List.Remove(Item);
if List.Count = 0 then
begin
List.Free;
List := nil;
end;
end;
{ Miscellaneous routines }
procedure MoveWindowOrg(DC: HDC; DX, DY: Integer);
var
P: TPoint;
begin
GetWindowOrgEx(DC, P);
SetWindowOrgEx(DC, P.X - DX, P.Y - DY, nil);
end;
{ Object implementations }
{ TControlCanvas }
var
CanvasList: TList;
procedure FreeDeviceContext;
begin
TControlCanvas(CanvasList[0]).FreeHandle;
end;
procedure FreeDeviceContexts;
begin
while CanvasList.Count > 0 do FreeDeviceContext;
end;
destructor TControlCanvas.Destroy;
begin
FreeHandle;
inherited Destroy;
end;
procedure TControlCanvas.CreateHandle;
begin
if FControl = nil then inherited CreateHandle else
begin
if FDeviceContext = 0 then
begin
if CanvasList.Count = CanvasList.Capacity then FreeDeviceContext;
FDeviceContext := FControl.GetDeviceContext(FWindowHandle);
CanvasList.Add(Self);
end;
Handle := FDeviceContext;
end;
end;
procedure TControlCanvas.FreeHandle;
begin
if FDeviceContext <> 0 then
begin
Handle := 0;
CanvasList.Remove(Self);
ReleaseDC(FWindowHandle, FDeviceContext);
FDeviceContext := 0;
end;
end;
procedure TControlCanvas.SetControl(AControl: TControl);
begin
if FControl <> AControl then
begin
FreeHandle;
FControl := AControl;
end;
end;
{ TControl }
constructor TControl.Create(AOwner: TComponent);
begin
inherited Create(AOwner);
FWindowProc := WndProc;
FControlStyle := [csCaptureMouse, csClickEvents, csSetCaption, csDoubleClicks];
FFont := TFont.Create;
FFont.OnChange := FontChanged;
FColor := clWindow;
FVisible := True;
FEnabled := True;
FParentFont := True;
FParentColor := True;
FParentShowHint := True;
FIsControl := False;
FDragCursor := crDrag;
end;
destructor TControl.Destroy;
begin
Application.ControlDestroyed(Self);
FFont.Free;
StrDispose(FText);
SetParent(nil);
inherited Destroy;
end;
function TControl.GetDragImages: TCustomImageList;
begin
Result := nil;
end;
function TControl.GetPalette: HPALETTE;
begin
Result := 0;
end;
function TControl.HasParent: Boolean;
begin
Result := FParent <> nil;
end;
function TControl.GetParentComponent: TComponent;
begin
Result := Parent;
end;
procedure TControl.SetParentComponent(Value: TComponent);
begin
if Value is TWinControl then SetParent(TWinControl(Value));
end;
function TControl.PaletteChanged(Foreground: Boolean): Boolean;
var
OldPalette, Palette: HPALETTE;
WindowHandle: HWnd;
DC: HDC;
begin
Result := False;
Palette := GetPalette;
if Palette <> 0 then
begin
DC := GetDeviceContext(WindowHandle);
OldPalette := SelectPalette(DC, Palette, not Foreground);
if RealizePalette(DC) <> 0 then Invalidate;
SelectPalette(DC, OldPalette, True);
RealizePalette(DC);
ReleaseDC(WindowHandle, DC);
Result := True;
end;
end;
procedure TControl.SetDragMode(Value: TDragMode);
begin
FDragMode := Value;
end;
procedure TControl.RequestAlign;
begin
if Parent <> nil then Parent.AlignControl(Self);
end;
procedure TControl.ReadState(Reader: TReader);
begin
Include(FControlState, csReadingState);
if Reader.Parent is TWinControl then Parent := TWinControl(Reader.Parent);
inherited ReadState(Reader);
Exclude(FControlState, csReadingState);
if Parent <> nil then
begin
Perform(CM_PARENTCOLORCHANGED, 0, 0);
Perform(CM_PARENTFONTCHANGED, 0, 0);
Perform(CM_PARENTSHOWHINTCHANGED, 0, 0);
end;
end;
procedure TControl.Notification(AComponent: TComponent;
Operation: TOperation);
begin
inherited Notification(AComponent, Operation);
if (AComponent = PopupMenu) and (Operation = opRemove) then PopupMenu := nil;
end;
procedure TControl.SetAlign(Value: TAlign);
var
OldAlign: TAlign;
begin
if FAlign <> Value then
begin
OldAlign := FAlign;
FAlign := Value;
if not (csLoading in ComponentState) and
((OldAlign in [alTop, alBottom]) = (Value in [alRight, alLeft])) and
not (OldAlign in [alNone, alClient]) and not (Value in [alNone, alClient]) then
SetBounds(Left, Top, Height, Width);
end;
RequestAlign;
end;
procedure TControl.SetBounds(ALeft, ATop, AWidth, AHeight: Integer);
begin
if (ALeft <> FLeft) or (ATop <> FTop) or
(AWidth <> FWidth) or (AHeight <> FHeight) then
begin
InvalidateControl(Visible, False);
FLeft := ALeft;
FTop := ATop;
FWidth := AWidth;
FHeight := AHeight;
Invalidate;
Perform(WM_WINDOWPOSCHANGED, 0, 0);
RequestAlign;
end;
end;
procedure TControl.SetLeft(Value: Integer);
begin
SetBounds(Value, FTop, FWidth, FHeight);
Include(FScalingFlags, sfLeft);
end;
procedure TControl.SetTop(Value: Integer);
begin
SetBounds(FLeft, Value, FWidth, FHeight);
Include(FScalingFlags, sfTop);
end;
procedure TControl.SetWidth(Value: Integer);
begin
SetBounds(FLeft, FTop, Value, FHeight);
Include(FScalingFlags, sfWidth);
end;
procedure TControl.SetHeight(Value: Integer);
begin
SetBounds(FLeft, FTop, FWidth, Value);
Include(FScalingFlags, sfHeight);
end;
function TControl.GetBoundsRect: TRect;
begin
Result.Left := Left;
Result.Top := Top;
Result.Right := Left + Width;
Result.Bottom := Top + Height;
end;
procedure TControl.SetBoundsRect(const Rect: TRect);
begin
with Rect do SetBounds(Left, Top, Right - Left, Bottom - Top);
end;
function TControl.GetClientRect: TRect;
begin
Result.Left := 0;
Result.Top := 0;
Result.Right := Width;
Result.Bottom := Height;
end;
function TControl.GetClientWidth: Integer;
begin
Result := ClientRect.Right;
end;
procedure TControl.SetClientWidth(Value: Integer);
begin
SetClientSize(Point(Value, ClientHeight));
end;
function TControl.GetClientHeight: Integer;
begin
Result := ClientRect.Bottom;
end;
procedure TControl.SetClientHeight(Value: Integer);
begin
SetClientSize(Point(ClientWidth, Value));
end;
function TControl.GetClientOrigin: TPoint;
begin
if Parent = nil then
raise EInvalidOperation.CreateResFmt(SParentRequired, [Name]);
Result := Parent.ClientOrigin;
Inc(Result.X, FLeft);
Inc(Result.Y, FTop);
end;
function TControl.ClientToScreen(const Point: TPoint): TPoint;
var
Origin: TPoint;
begin
Origin := ClientOrigin;
Result.X := Point.X + Origin.X;
Result.Y := Point.Y + Origin.Y;
end;
function TControl.ScreenToClient(const Point: TPoint): TPoint;
var
Origin: TPoint;
begin
Origin := ClientOrigin;
Result.X := Point.X - Origin.X;
Result.Y := Point.Y - Origin.Y;
end;
procedure TControl.SendCancelMode(Sender: TControl);
var
Form: TForm;
begin
Form := GetParentForm(Self);
if Form <> nil then Form.SendCancelMode(Sender);
end;
procedure TControl.ChangeScale(M, D: Integer);
var
X, Y, W, H: Integer;
Flags: TScalingFlags;
begin
if M <> D then
begin
if csLoading in ComponentState then
Flags := ScalingFlags else
Flags := [sfLeft, sfTop, sfWidth, sfHeight, sfFont];
if sfLeft in Flags then
X := MulDiv(FLeft, M, D) else
X := FLeft;
if sfTop in Flags then
Y := MulDiv(FTop, M, D) else
Y := FTop;
if (sfWidth in Flags) and not (csFixedWidth in ControlStyle) then
W := MulDiv(FLeft + FWidth, M, D) - X else
W := FWidth;
if (sfHeight in Flags) and not (csFixedHeight in ControlStyle) then
H := MulDiv(FTop + FHeight, M, D) - Y else
H := FHeight;
SetBounds(X, Y, W, H);
if not ParentFont and (sfFont in Flags) then
Font.Size := MulDiv(Font.Size, M, D);
end;
FScalingFlags := [];
end;
procedure TControl.SetName(const Value: TComponentName);
var
ChangeText: Boolean;
begin
ChangeText := (csSetCaption in ControlStyle) and (Name = Text) and
((Owner = nil) or not (Owner is TControl) or
not (csLoading in TControl(Owner).ComponentState));
inherited SetName(Value);
if ChangeText then Text := Value;
end;
procedure TControl.SetClientSize(Value: TPoint);
var
Client: TRect;
begin
Client := GetClientRect;
SetBounds(FLeft, FTop, Width - Client.Right + Value.X, Height -
Client.Bottom + Value.Y);
end;
procedure TControl.SetParent(AParent: TWinControl);
begin
if FParent <> AParent then
begin
if Parent = Self then
raise EInvalidOperation.CreateRes(SControlParentSetToSelf);
if FParent <> nil then FParent.RemoveControl(Self);
if AParent <> nil then AParent.InsertControl(Self);
end;
end;
procedure TControl.SetVisible(Value: Boolean);
begin
if FVisible <> Value then
begin
VisibleChanging;
FVisible := Value;
Perform(CM_VISIBLECHANGED, 0, 0);
RequestAlign;
end;
end;
procedure TControl.SetEnabled(Value: Boolean);
begin
if FEnabled <> Value then
begin
FEnabled := Value;
Perform(CM_ENABLEDCHANGED, 0, 0);
end;
end;
function TControl.GetTextLen: Integer;
begin
Result := Perform(WM_GETTEXTLENGTH, 0, 0);
end;
function TControl.GetTextBuf(Buffer: PChar; BufSize: Integer): Integer;
begin
Result := Perform(WM_GETTEXT, BufSize, Longint(Buffer));
end;
procedure TControl.SetPopupMenu(Value: TPopupMenu);
begin
FPopupMenu := Value;
if Value <> nil then Value.FreeNotification(Self);
end;
procedure TControl.SetTextBuf(Buffer: PChar);
begin
Perform(WM_SETTEXT, 0, Longint(Buffer));
Perform(CM_TEXTCHANGED, 0, 0);
end;
function TControl.GetText: TCaption;
var
Len: Integer;
begin
Len := GetTextLen;
SetString(Result, PChar(nil), Len);
if Len <> 0 then GetTextBuf(Pointer(Result), Len + 1);
end;
procedure TControl.SetText(const Value: TCaption);
begin
if GetText <> Value then SetTextBuf(PChar(Value));
end;
procedure TControl.FontChanged(Sender: TObject);
begin
FParentFont := False;
if Font.Height <> FFontHeight then
begin
Include(FScalingFlags, sfFont);
FFontHeight := Font.Height;
end;
Perform(CM_FONTCHANGED, 0, 0);
end;
procedure TControl.SetFont(Value: TFont);
begin
FFont.Assign(Value);
end;
function TControl.IsFontStored: Boolean;
begin
Result := not ParentFont;
end;
function TControl.IsShowHintStored: Boolean;
begin
Result := not ParentShowHint;
end;
procedure TControl.SetParentFont(Value: Boolean);
begin
if FParentFont <> Value then
begin
FParentFont := Value;
if FParent <> nil then Perform(CM_PARENTFONTCHANGED, 0, 0);
end;
end;
procedure TControl.SetShowHint(Value: Boolean);
begin
if FShowHint <> Value then
begin
FShowHint := Value;
FParentShowHint := False;
Perform(CM_SHOWHINTCHANGED, 0, 0);
end;
end;
procedure TControl.SetParentShowHint(Value: Boolean);
begin
if FParentShowHint <> Value then
begin
FParentShowHint := Value;
if FParent <> nil then Perform(CM_PARENTSHOWHINTCHANGED, 0, 0);
end;
end;
procedure TControl.SetColor(Value: TColor);
begin
if FColor <> Value then
begin
FColor := Value;
FParentColor := False;
Perform(CM_COLORCHANGED, 0, 0);
end;
end;
function TControl.IsColorStored: Boolean;
begin
Result := not ParentColor;
end;
procedure TControl.SetParentColor(Value: Boolean);
begin
if FParentColor <> Value then
begin
FParentColor := Value;
if FParent <> nil then Perform(CM_PARENTCOLORCHANGED, 0, 0);
end;
end;
procedure TControl.SetCursor(Value: TCursor);
begin
if FCursor <> Value then
begin
FCursor := Value;
Perform(CM_CURSORCHANGED, 0, 0);
end;
end;
function TControl.GetMouseCapture: Boolean;
begin
Result := GetCaptureControl = Self;
end;
procedure TControl.SetMouseCapture(Value: Boolean);
begin
if MouseCapture <> Value then
if Value then SetCaptureControl(Self) else SetCaptureControl(nil);
end;
procedure TControl.BringToFront;
begin
SetZOrder(True);
end;
procedure TControl.SendToBack;
begin
SetZOrder(False);
end;
procedure TControl.SetZOrderPosition(Position: Integer);
var
I, Count: Integer;
ParentForm: TForm;
begin
if FParent <> nil then
begin
I := FParent.FControls.IndexOf(Self);
if I >= 0 then
begin
Count := FParent.FControls.Count;
if Position < 0 then Position := 0;
if Position >= Count then Position := Count - 1;
if Position <> I then
begin
FParent.FControls.Delete(I);
FParent.FControls.Insert(Position, Self);
InvalidateControl(Visible, True);
ParentForm := ValidParentForm(Self);
if csPalette in ParentForm.ControlState then
TControl(ParentForm).PaletteChanged(True);
end;
end;
end;
end;
procedure TControl.SetZOrder(TopMost: Boolean);
begin
if FParent <> nil then
if TopMost then
SetZOrderPosition(FParent.FControls.Count - 1) else
SetZOrderPosition(0);
end;
function TControl.GetDeviceContext(var WindowHandle: HWnd): HDC;
begin
if Parent = nil then
raise EInvalidOperation.CreateResFmt(SParentRequired, [Name]);
Result := Parent.GetDeviceContext(WindowHandle);
SetViewportOrgEx(Result, Left, Top, nil);
IntersectClipRect(Result, 0, 0, Width, Height);
end;
procedure TControl.InvalidateControl(IsVisible, IsOpaque: Boolean);
var
Rect: TRect;
function BackgroundClipped: Boolean;
var
R: TRect;
List: TList;
I: Integer;
C: TControl;
begin
Result := True;
List := FParent.FControls;
I := List.IndexOf(Self);
while I > 0 do
begin
Dec(I);
C := List[I];
with C do
if csOpaque in ControlStyle then
begin
IntersectRect(R, Rect, BoundsRect);
if EqualRect(R, Rect) then Exit;
end;
end;
Result := False;
end;
begin
if (IsVisible or (csDesigning in ComponentState) and
not (csNoDesignVisible in ControlStyle)) and (Parent <> nil) and
Parent.HandleAllocated then
begin
Rect := BoundsRect;
InvalidateRect(Parent.Handle, @Rect, not (IsOpaque or
(csOpaque in Parent.ControlStyle) or BackgroundClipped));
end;
end;
procedure TControl.Invalidate;
begin
InvalidateControl(Visible, csOpaque in ControlStyle);
end;
procedure TControl.Hide;
begin
Visible := False;
end;
procedure TControl.Show;
begin
if Parent <> nil then Parent.ShowControl(Self);
if not (csDesigning in ComponentState) or
(csNoDesignVisible in ControlStyle) then Visible := True;
end;
procedure TControl.Update;
begin
if Parent <> nil then Parent.Update;
end;
procedure TControl.Refresh;
begin
Repaint;
end;
procedure TControl.Repaint;
var
DC: HDC;
begin
if (Visible or (csDesigning in ComponentState) and
not (csNoDesignVisible in ControlStyle)) and (Parent <> nil) and
Parent.HandleAllocated then
if csOpaque in ControlStyle then
begin
DC := GetDC(Parent.Handle);
try
IntersectClipRect(DC, Left, Top, Left + Width, Top + Height);
Parent.PaintControls(DC, Self);
finally
ReleaseDC(Parent.Handle, DC);
end;
end else
begin
Invalidate;
Update;
end;
end;
procedure TControl.BeginDrag(Immediate: Boolean);
var
P: TPoint;
begin
if Self is TForm then
raise EInvalidOperation.CreateRes(SCannotDragForm);
if DragControl = nil then
begin
DragControl := Self;
if csLButtonDown in ControlState then
begin
GetCursorPos(P);
P := ScreenToClient(P);
Perform(WM_LBUTTONUP, 0, Longint(PointToSmallPoint(P)));
end;
if DragControl = Self then DragInitControl(Self, Immediate);
end;
end;
procedure TControl.EndDrag(Drop: Boolean);
begin
if Dragging then DragDone(Drop);
end;
procedure TControl.DragCanceled;
begin
end;
function TControl.Dragging: Boolean;
begin
Result := DragControl = Self;
end;
procedure TControl.DragOver(Source: TObject; X, Y: Integer;
State: TDragState; var Accept: Boolean);
begin
Accept := True;
if Assigned(FOnDragOver) then
FOnDragOver(Self, Source, X, Y, State, Accept) else
Accept := False;
end;
procedure TControl.DragDrop(Source: TObject; X, Y: Integer);
begin
if Assigned(FOnDragDrop) then FOnDragDrop(Self, Source, X, Y);
end;
procedure TControl.DoStartDrag(var DragObject: TDragObject);
begin
if Assigned(FOnStartDrag) then FOnStartDrag(Self, DragObject);
end;
procedure TControl.DoEndDrag(Target: TObject; X, Y: Integer);
begin
if Assigned(FOnEndDrag) then FOnEndDrag(Self, Target, X, Y);
end;
procedure TControl.DoDragMsg(var DragMsg: TCMDrag);
var
S: Pointer;
Accepts: Boolean;
begin
with DragMsg, DragRec^ do
begin
S := Source;
if TDragObject(S) is TDragControlObject then
S := TDragControlObject(S).Control;
with ScreenToClient(Pos) do
case DragMessage of
dmDragEnter, dmDragLeave, dmDragMove:
begin
DragOver(S, X, Y, TDragState(DragMessage), Accepts);
Result := Ord(Accepts);
end;
dmDragDrop: DragDrop(S, X, Y);
end;
end;
end;
function TControl.Perform(Msg: Cardinal; WParam, LParam: Longint): Longint;
var
Message: TMessage;
begin
Message.Msg := Msg;
Message.WParam := WParam;
Message.LParam := LParam;
Message.Result := 0;
if Self <> nil then WindowProc(Message);
Result := Message.Result;
end;
procedure TControl.UpdateBoundsRect(const R: TRect);
begin
FLeft := R.left;
FTop := R.top;
FWidth := R.right - R.left;
FHeight := R.bottom - R.top;
end;
procedure TControl.VisibleChanging;
begin
end;
procedure TControl.WndProc(var Message: TMessage);
var
Form: TForm;
begin
if csDesigning in ComponentState then
begin
Form := GetParentForm(Self);
if (Form <> nil) and (Form.Designer <> nil) and
Form.Designer.IsDesignMsg(Self, Message) then Exit;
end;
if (Message.Msg >= WM_MOUSEFIRST) and (Message.Msg <= WM_MOUSELAST) then
begin
if not (csDoubleClicks in ControlStyle) then
case Message.Msg of
WM_LBUTTONDBLCLK, WM_RBUTTONDBLCLK, WM_MBUTTONDBLCLK:
Dec(Message.Msg, WM_LBUTTONDBLCLK - WM_LBUTTONDOWN);
end;
case Message.Msg of
WM_MOUSEMOVE: Application.HintMouseMessage(Self, Message);
WM_LBUTTONDOWN, WM_LBUTTONDBLCLK:
begin
if FDragMode = dmAutomatic then
begin
BeginDrag(True);
Exit;
end;
Include(FControlState, csLButtonDown);
end;
WM_LBUTTONUP:
Exclude(FControlState, csLButtonDown);
end;
end;
Dispatch(Message);
end;
procedure TControl.DefaultHandler(var Message);
var
P: PChar;
begin
with TMessage(Message) do
case Msg of
WM_GETTEXT:
begin
if FText <> nil then P := FText else P := '';
Result := StrLen(StrLCopy(PChar(LParam), P, WParam - 1));
end;
WM_GETTEXTLENGTH:
if FText = nil then Result := 0 else Result := StrLen(FText);
WM_SETTEXT:
begin
P := StrNew(PChar(LParam));
StrDispose(FText);
FText := P;
end;
end;
end;
procedure TControl.ReadIsControl(Reader: TReader);
begin
FIsControl := Reader.ReadBoolean;
end;
procedure TControl.WriteIsControl(Writer: TWriter);
begin
Writer.WriteBoolean(FIsControl);
end;
procedure TControl.DefineProperties(Filer: TFiler);
function DoWrite: Boolean;
begin
if Filer.Ancestor <> nil then
Result := TControl(Filer.Ancestor).IsControl <> IsControl else
Result := IsControl;
end;
begin
{ The call to inherited DefinedProperties is omitted since the Left and
Top special properties are redefined with real properties }
Filer.DefineProperty('IsControl', ReadIsControl, WriteIsControl, DoWrite);
end;
procedure TControl.Click;
begin
if Assigned(FOnClick) then FOnClick(Self);
end;
procedure TControl.DblClick;
begin
if Assigned(FOnDblClick) then FOnDblClick(Self);
end;
procedure TControl.MouseDown(Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
begin
if Assigned(FOnMouseDown) then FOnMouseDown(Self, Button, Shift, X, Y);
end;
procedure TControl.DoMouseDown(var Message: TWMMouse; Button: TMouseButton;
Shift: TShiftState);
begin
if not (csNoStdEvents in ControlStyle) then
with Message do
MouseDown(Button, KeysToShiftState(Keys) + Shift, XPos, YPos);
end;
procedure TControl.WMLButtonDown(var Message: TWMLButtonDown);
begin
SendCancelMode(Self);
inherited;
if csCaptureMouse in ControlStyle then MouseCapture := True;
if csClickEvents in ControlStyle then Include(FControlState, csClicked);
DoMouseDown(Message, mbLeft, []);
end;
procedure TControl.WMNCLButtonDown(var Message: TWMNCLButtonDown);
begin
SendCancelMode(Self);
inherited;
end;
procedure TControl.WMLButtonDblClk(var Message: TWMLButtonDblClk);
begin
SendCancelMode(Self);
inherited;
if csCaptureMouse in ControlStyle then MouseCapture := True;
if csClickEvents in ControlStyle then DblClick;
DoMouseDown(Message, mbLeft, [ssDouble]);
end;
function TControl.GetPopupMenu: TPopupMenu;
begin
Result := FPopupMenu;
end;
procedure TControl.CheckMenuPopup(const Pos: TSmallPoint);
var
Control: TControl;
PopupMenu: TPopupMenu;
begin
if csDesigning in ComponentState then Exit;
Control := Self;
while Control <> nil do
begin
PopupMenu := Control.GetPopupMenu;
if (PopupMenu <> nil) and PopupMenu.AutoPopup then
begin
SendCancelMode(nil);
PopupMenu.PopupComponent := Control;
with ClientToScreen(SmallPointToPoint(Pos)) do
PopupMenu.Popup(X, Y);
Exit;
end;
Control := Control.Parent;
end;
end;
procedure TControl.WMRButtonDown(var Message: TWMRButtonDown);
begin
inherited;
DoMouseDown(Message, mbRight, []);
end;
procedure TControl.WMRButtonDblClk(var Message: TWMRButtonDblClk);
begin
inherited;
DoMouseDown(Message, mbRight, [ssDouble]);
end;
procedure TControl.WMMButtonDown(var Message: TWMMButtonDown);
begin
inherited;
DoMouseDown(Message, mbMiddle, []);
end;
procedure TControl.WMMButtonDblClk(var Message: TWMMButtonDblClk);
begin
inherited;
DoMouseDown(Message, mbMiddle, [ssDouble]);
end;
procedure TControl.MouseMove(Shift: TShiftState; X, Y: Integer);
begin
if Assigned(FOnMouseMove) then FOnMouseMove(Self, Shift, X, Y);
end;
procedure TControl.WMMouseMove(var Message: TWMMouseMove);
begin
inherited;
if not (csNoStdEvents in ControlStyle) then
with Message do MouseMove(KeysToShiftState(Keys), XPos, YPos);
end;
procedure TControl.MouseUp(Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
begin
if Assigned(FOnMouseUp) then FOnMouseUp(Self, Button, Shift, X, Y);
end;
procedure TControl.DoMouseUp(var Message: TWMMouse; Button: TMouseButton);
begin
if not (csNoStdEvents in ControlStyle) then
with Message do MouseUp(Button, KeysToShiftState(Keys), XPos, YPos);
end;
procedure TControl.WMLButtonUp(var Message: TWMLButtonUp);
begin
inherited;
if csCaptureMouse in ControlStyle then MouseCapture := False;
if csClicked in ControlState then
begin
Exclude(FControlState, csClicked);
if PtInRect(ClientRect, SmallPointToPoint(Message.Pos)) then Click;
end;
DoMouseUp(Message, mbLeft);
end;
procedure TControl.WMRButtonUp(var Message: TWMRButtonUp);
begin
inherited;
DoMouseUp(Message, mbRight);
CheckMenuPopup(Message.Pos);
end;
procedure TControl.WMMButtonUp(var Message: TWMMButtonUp);
begin
inherited;
DoMouseUp(Message, mbMiddle);
end;
procedure TControl.WMCancelMode(var Message: TWMCancelMode);
begin
inherited;
if MouseCapture then
begin
MouseCapture := False;
if csLButtonDown in ControlState then Perform(WM_LBUTTONUP, 0, $FFFFFFFF);
end;
end;
procedure TControl.CMVisibleChanged(var Message: TMessage);
begin
if not (csDesigning in ComponentState) or
(csNoDesignVisible in ControlStyle) then
InvalidateControl(True, FVisible and (csOpaque in ControlStyle));
end;
procedure TControl.CMEnabledChanged(var Message: TMessage);
begin
Invalidate;
end;
procedure TControl.CMFontChanged(var Message: TMessage);
begin
Invalidate;
end;
procedure TControl.CMColorChanged(var Message: TMessage);
begin
Invalidate;
end;
procedure TControl.CMParentColorChanged(var Message: TMessage);
begin
if FParentColor then
begin
SetColor(FParent.FColor);
FParentColor := True;
end;
end;
procedure TControl.CMParentShowHintChanged(var Message: TMessage);
begin
if FParentShowHint then
begin
SetShowHint(FParent.FShowHint);
FParentShowHint := True;
end;
end;
procedure TControl.CMParentFontChanged(var Message: TMessage);
begin
if FParentFont then
begin
SetFont(FParent.FFont);
FParentFont := True;
end;
end;
procedure TControl.CMHitTest(var Message: TCMHitTest);
begin
Message.Result := 1;
end;
procedure TControl.CMMouseEnter(var Message: TMessage);
begin
if FParent <> nil then
FParent.Perform(CM_MOUSEENTER, 0, Longint(Self));
end;
procedure TControl.CMMouseLeave(var Message: TMessage);
begin
if FParent <> nil then
FParent.Perform(CM_MOUSELEAVE, 0, Longint(Self));
end;
procedure TControl.CMDesignHitTest(var Message: TCMDesignHitTest);
begin
Message.Result := 0;
end;
{ TWinControl }
constructor TWinControl.Create(AOwner: TComponent);
begin
inherited Create(AOwner);
FObjectInstance := MakeObjectInstance(MainWndProc);
FBrush := TBrush.Create;
FBrush.Color := FColor;
FParentCtl3D := True;
FTabOrder := -1;
FImeMode := imDontCare;
FImeName := Screen.DefaultIme;
FInImeComposition := False;
end;
constructor TWinControl.CreateParented(ParentWindow: HWnd);
begin
FParentWindow := ParentWindow;
Create(nil);
end;
destructor TWinControl.Destroy;
var
I: Integer;
Instance: TControl;
begin
Destroying;
if Parent <> nil then RemoveFocus(True);
if FHandle <> 0 then DestroyWindowHandle;
I := ControlCount;
while I <> 0 do
begin
Instance := Controls[I - 1];
Remove(Instance);
Instance.Destroy;
I := ControlCount;
end;
FBrush.Free;
if FObjectInstance <> nil then FreeObjectInstance(FObjectInstance);
inherited Destroy;
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 := 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 := List[I];
if Control <> nil then Control.UpdateTabOrder(I);
end;
finally
List.Free;
end;
end;
end;
procedure TWinControl.ReadState(Reader: TReader);
begin
DisableAlign;
try
inherited ReadState(Reader);
finally
EnableAlign;
end;
FixupTabList;
if FParent <> nil then Perform(CM_PARENTCTL3DCHANGED, 0, 0);
UpdateControlState;
end;
procedure TWinControl.AlignControls(AControl: TControl; var Rect: TRect);
var
AlignList: TList;
function InsertBefore(C1, C2: TControl; AAlign: TAlign): Boolean;
begin
Result := False;
case AAlign of
alTop: Result := C1.Top < C2.Top;
alBottom: Result := (C1.Top + C1.Height) > (C2.Top + C2.Height);
alLeft: Result := C1.Left < C2.Left;
alRight: Result := (C1.Left + C1.Width) > (C2.Left + C2.Width);
end;
end;
procedure DoPosition(Control: TControl; AAlign: TAlign);
function NonNeg(Value, Default: Integer): Integer;
begin
if Value < 0 then
Result := Default else
Result := Value;
end;
begin
with Rect do
case AAlign of
alTop: Inc(Top, Control.Height);
alBottom: Dec(Bottom, Control.Height);
alLeft: Inc(Left, Control.Width);
alRight: Dec(Right, Control.Width);
end;
with Rect do
case AAlign of
alTop: Control.SetBounds(Left, Top - Control.Height,
NonNeg(Right - Left, Control.Width), Control.Height);
alBottom: Control.SetBounds(Left, Bottom,
NonNeg(Right - Left, Control.Width), Control.Height);
alLeft: Control.SetBounds(Left - Control.Width, Top, Control.Width,
NonNeg(Bottom - Top, Control.Height));
alRight: Control.SetBounds(Right, Top, Control.Width,
NonNeg(Bottom - Top, Control.Height));
alClient: if not IsRectEmpty(Rect) then Control.SetBoundsRect(Rect);
end;
end;
procedure DoAlign(AAlign: TAlign);
var
I, J: Integer;
Control: TControl;
begin
AlignList.Clear;
if (AControl <> nil) and (AControl.Visible or
(csDesigning in AControl.ComponentState) and
not (csNoDesignVisible in AControl.ControlStyle)) and
(AControl.Align = AAlign) then
AlignList.Add(AControl);
for I := 0 to ControlCount - 1 do
begin
Control := Controls[I];
if (Control.Align = AAlign) and (Control.Visible or
(csDesigning in Control.ComponentState) and
not (csNoDesignVisible in Control.ControlStyle)) then
begin
if Control = AControl then Continue;
J := 0;
while (J < AlignList.Count) and not InsertBefore(Control,
TControl(AlignList[J]), AAlign) do Inc(J);
AlignList.Insert(J, Control);
end;
end;
for I := 0 to AlignList.Count - 1 do
DoPosition(TControl(AlignList[I]), AAlign);
end;
function AlignWork: Boolean;
var
I: Integer;
begin
Result := True;
for I := ControlCount - 1 downto 0 do
if Controls[I].Align <> alNone then Exit;
Result := False;
end;
begin
if not AlignWork then Exit; { No work to do }
AlignList := TList.Create;
try
DoAlign(alTop);
DoAlign(alBottom);
DoAlign(alLeft);
DoAlign(alRight);
DoAlign(alClient);
finally
AlignList.Free;
end;
end;
procedure TWinControl.AlignControl(AControl: TControl);
var
Rect: TRect;
begin
if not HandleAllocated then Exit;
if FAlignLevel <> 0 then
Include(FControlState, csAlignmentNeeded)
else
begin
DisableAlign;
try
Rect := GetClientRect;
AlignControls(AControl, Rect);
finally
Exclude(FControlState, csAlignmentNeeded);
EnableAlign;
end;
end;
end;
procedure TWinControl.DisableAlign;
begin
Inc(FAlignLevel);
end;
procedure TWinControl.EnableAlign;
begin
Dec(FAlignLevel);
if (FAlignLevel = 0) and (csAlignmentNeeded in ControlState) then Realign;
end;
procedure TWinControl.Realign;
begin
AlignControl(nil);
end;
function TWinControl.ContainsControl(Control: TControl): Boolean;
begin
while (Control <> nil) and (Control <> Self) do Control := Control.Parent;
Result := Control <> nil;
end;
procedure TWinControl.RemoveFocus(Removing: Boolean);
var
Form: TForm;
begin
Form := GetParentForm(Self);
if Form <> nil then Form.DefocusControl(Self, Removing);
end;
procedure TWinControl.Insert(AControl: TControl);
begin
if AControl <> nil then
begin
if AControl is TWinControl then
begin
ListAdd(FWinControls, AControl);
ListAdd(FTabList, AControl);
end else
ListAdd(FControls, AControl);
AControl.FParent := Self;
end;
end;
procedure TWinControl.Remove(AControl: TControl);
begin
if AControl is TWinControl then
begin
ListRemove(FTabList, AControl);
ListRemove(FWinControls, AControl);
end else
ListRemove(FControls, AControl);
AControl.FParent := nil;
end;
procedure TWinControl.InsertControl(AControl: TControl);
begin
Perform(CM_CONTROLLISTCHANGE, Integer(AControl), Integer(True));
Insert(AControl);
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);
if AControl is TWinControl then
begin
AControl.Perform(CM_PARENTCTL3DCHANGED, 0, 0);
UpdateControlState;
end else
if HandleAllocated then AControl.Invalidate;
AlignControl(AControl);
end;
end;
procedure TWinControl.RemoveControl(AControl: TControl);
begin
if AControl is TWinControl then
with TWinControl(AControl) do
begin
RemoveFocus(True);
DestroyHandle;
end
else
if HandleAllocated then
AControl.InvalidateControl(AControl.Visible, False);
Remove(AControl);
Perform(CM_CONTROLLISTCHANGE, Integer(AControl), Integer(False));
Realign;
end;
function TWinControl.GetControl(Index: Integer): TControl;
var
N: Integer;
begin
if FControls <> nil then N := FControls.Count else N := 0;
if Index < N then
Result := FControls[Index] else
Result := FWinControls[Index - N];
end;
function TWinControl.GetControlCount: Integer;
begin
Result := 0;
if FControls <> nil then Inc(Result, FControls.Count);
if FWinControls <> nil then Inc(Result, FWinControls.Count);
end;
procedure TWinControl.Broadcast(var Message);
var
I: Integer;
begin
for I := 0 to ControlCount - 1 do
begin
Controls[I].WindowProc(TMessage(Message));
if TMessage(Message).Result <> 0 then Exit;
end;
end;
procedure TWinControl.NotifyControls(Msg: Word);
var
Message: TMessage;
begin
Message.Msg := Msg;
Message.WParam := 0;
Message.LParam := 0;
Message.Result := 0;
Broadcast(Message);
end;
procedure TWinControl.CreateSubClass(var Params: TCreateParams;
ControlClassName: PChar);
const
CS_OFF = CS_OWNDC or CS_CLASSDC or CS_PARENTDC or CS_GLOBALCLASS;
CS_ON = CS_VREDRAW or CS_HREDRAW;
begin
if ControlClassName <> nil then
with Params do
begin
if not GetClassInfo(HInstance, ControlClassName, WindowClass) then
GetClassInfo(0, ControlClassName, WindowClass);
WindowClass.style := WindowClass.style and not CS_OFF or CS_ON;
end;
end;
procedure TWinControl.CreateParams(var Params: TCreateParams);
begin
FillChar(Params, SizeOf(Params), 0);
with Params do
begin
Caption := FText;
Style := WS_CHILD or WS_CLIPSIBLINGS;
if csAcceptsControls in ControlStyle then
Style := Style or WS_CLIPCHILDREN;
if not (csDesigning in ComponentState) and not FEnabled then
Style := Style or WS_DISABLED;
if FTabStop then Style := Style or WS_TABSTOP;
X := FLeft;
Y := FTop;
Width := FWidth;
Height := FHeight;
if Parent <> nil then
WndParent := Parent.GetHandle else
WndParent := FParentWindow;
WindowClass.style := CS_VREDRAW + CS_HREDRAW + CS_DBLCLKS;
WindowClass.lpfnWndProc := @DefWindowProc;
WindowClass.hCursor := LoadCursor(0, IDC_ARROW);
WindowClass.hbrBackground := 0;
StrPCopy(WinClassName, ClassName);
end;
end;
procedure TWinControl.CreateWnd;
var
Params: TCreateParams;
TempClass: TWndClass;
ClassRegistered: Boolean;
begin
CreateParams(Params);
with Params do
begin
if (WndParent = 0) and (Style and WS_CHILD <> 0) then
raise EInvalidOperation.CreateResFmt(SParentRequired, [Name]);
FDefWndProc := WindowClass.lpfnWndProc;
ClassRegistered := GetClassInfo(HInstance, WinClassName, TempClass);
if not ClassRegistered or (TempClass.lpfnWndProc <> @InitWndProc) then
begin
if ClassRegistered then Windows.UnregisterClass(WinClassName, HInstance);
WindowClass.lpfnWndProc := @InitWndProc;
WindowClass.hInstance := HInstance;
WindowClass.lpszClassName := WinClassName;
if Windows.RegisterClass(WindowClass) = 0 then
raise EOutOfResources.CreateRes(SWindowClass);
end;
CreationControl := Self;
CreateWindowHandle(Params);
if FHandle = 0 then raise EOutOfResources.CreateRes(SWindowCreate);
end;
StrDispose(FText);
FText := nil;
UpdateBounds;
if Application.IgnoreFontProperty and SysLocale.FarEast then
begin
FFont.Charset := DefFontData.Charset;
FFont.Name := DefFontData.Name;
FFont.Height := DefFontData.Height;
end;
Perform(WM_SETFONT, FFont.Handle, 1);
end;
procedure TWinControl.CreateWindowHandle(const Params: TCreateParams);
begin
with Params do
FHandle := CreateWindowEx(ExStyle, WinClassName, Caption, Style,
X, Y, Width, Height, WndParent, 0, HInstance, Param);
end;
procedure TWinControl.DestroyWnd;
var
Len: Integer;
begin
Len := GetTextLen;
if Len < 1 then FText := StrNew('') else
begin
FText := StrAlloc(Len + 1);
GetTextBuf(FText, StrBufSize(FText));
end;
FreeDeviceContexts;
DestroyWindowHandle;
end;
procedure TWinControl.DestroyWindowHandle;
begin
Windows.DestroyWindow(FHandle);
end;
function TWinControl.PrecedingWindow(Control: TWinControl): HWnd;
var
I: Integer;
begin
for I := FWinControls.IndexOf(Control) + 1 to FWinControls.Count - 1 do
begin
Result := TWinControl(FWinControls[I]).FHandle;
if Result <> 0 then Exit;
end;
Result := HWND_TOP;
end;
procedure TWinControl.CreateHandle;
begin
if FHandle = 0 then
begin
CreateWnd;
SetProp(FHandle, MakeIntAtom(ControlAtom), THandle(Self));
SetProp(FHandle, MakeIntAtom(WindowAtom), THandle(Self));
if Parent <> nil then
SetWindowPos(FHandle, Parent.PrecedingWindow(Self), 0, 0, 0, 0,
SWP_NOMOVE + SWP_NOSIZE + SWP_NOACTIVATE);
end;
end;
procedure TWinControl.DestroyHandle;
var
I: Integer;
begin
if FHandle <> 0 then
begin
if FWinControls <> nil then
for I := 0 to FWinControls.Count - 1 do
TWinControl(FWinControls[I]).DestroyHandle;
DestroyWnd;
end;
end;
procedure TWinControl.RecreateWnd;
begin
if FHandle <> 0 then Perform(CM_RECREATEWND, 0, 0);
end;
procedure TWinControl.CMRecreateWnd(var Message: TMessage);
var
WasFocused: Boolean;
begin
WasFocused := Focused;
DestroyHandle;
UpdateControlState;
if WasFocused and (FHandle <> 0) then Windows.SetFocus(FHandle);
end;
procedure TWinControl.UpdateShowing;
var
ShowControl: Boolean;
I: Integer;
begin
ShowControl := (FVisible or (csDesigning in ComponentState) and
not (csNoDesignVisible in ControlStyle)) and
not (csReadingState in ControlState);
if ShowControl then
begin
if FHandle = 0 then CreateHandle;
if FWinControls <> nil then
for I := 0 to FWinControls.Count - 1 do
TWinControl(FWinControls[I]).UpdateShowing;
end;
if FHandle <> 0 then
if FShowing <> ShowControl then
begin
FShowing := ShowControl;
try
Perform(CM_SHOWINGCHANGED, 0, 0);
except
FShowing := not ShowControl;
raise;
end;
end;
end;
procedure TWinControl.UpdateControlState;
var
Control: TWinControl;
begin
Control := Self;
while Control.Parent <> nil do
begin
Control := Control.Parent;
if not Control.Showing then Exit;
end;
if (Control is TForm) or (Control.FParentWindow <> 0) then UpdateShowing;
end;
procedure TWinControl.SetParentWindow(Value: HWnd);
begin
if (FParent = nil) and (FParentWindow <> Value) then
if (FHandle <> 0) and (FParentWindow <> 0) and (Value <> 0) then
begin
FParentWindow := Value;
Windows.SetParent(FHandle, Value);
end else
begin
DestroyHandle;
FParentWindow := Value;
UpdateControlState;
end;
end;
procedure TWinControl.MainWndProc(var Message: TMessage);
begin
try
try
WindowProc(Message);
finally
FreeDeviceContexts;
FreeMemoryContexts;
end;
except
Application.HandleException(Self);
end;
end;
function TWinControl.ControlAtPos(const Pos: TPoint; AllowDisabled: Boolean): TControl;
var
I: Integer;
P: TPoint;
begin
if FControls <> nil then
for I := FControls.Count - 1 downto 0 do
begin
Result := FControls[I];
with Result do
begin
P := Point(Pos.X - Left, Pos.Y - Top);
if PtInRect(ClientRect, P) and
((csDesigning in ComponentState) and (Visible or
not (csNoDesignVisible in ControlStyle)) or
(Visible and (Enabled or AllowDisabled) and
(Perform(CM_HITTEST, 0, Longint(PointToSmallPoint(P))) <> 0))) then
Exit;
end;
end;
Result := nil;
end;
function TWinControl.IsControlMouseMsg(var Message: TWMMouse): Boolean;
var
Control: TControl;
P: TPoint;
begin
if GetCapture = Handle then
begin
Control := nil;
if (CaptureControl <> nil) and (CaptureControl.Parent = Self) then
Control := CaptureControl;
end else
Control := ControlAtPos(SmallPointToPoint(Message.Pos), False);
Result := False;
if Control <> nil then
begin
P.X := Message.XPos - Control.Left;
P.Y := Message.YPos - Control.Top;
Control.Perform(Message.Msg, Message.Keys, Longint(PointToSmallPoint(P)));
Result := True;
end;
end;
procedure TWinControl.WndProc(var Message: TMessage);
var
Form: TForm;
begin
case Message.Msg of
WM_SETFOCUS:
begin
Form := GetParentForm(Self);
if (Form <> nil) and not Form.SetFocusedControl(Self) then Exit;
end;
WM_KILLFOCUS:
if csFocusing in ControlState then Exit;
WM_NCHITTEST:
begin
inherited WndProc(Message);
if (Message.Result = HTTRANSPARENT) and (ControlAtPos(ScreenToClient(
SmallPointToPoint(TWMNCHitTest(Message).Pos)), False) <> nil) then
Message.Result := HTCLIENT;
Exit;
end;
WM_MOUSEFIRST..WM_MOUSELAST:
if IsControlMouseMsg(TWMMouse(Message)) then Exit;
WM_KEYFIRST..WM_KEYLAST:
if Dragging then Exit;
WM_CANCELMODE:
if (GetCapture = Handle) and (CaptureControl <> nil) and
(CaptureControl.Parent = Self) then
CaptureControl.Perform(WM_CANCELMODE, 0, 0);
end;
inherited WndProc(Message);
end;
procedure TWinControl.DefaultHandler(var Message);
begin
if FHandle <> 0 then
with TMessage(Message) do
case Msg of
WM_CTLCOLORMSGBOX..WM_CTLCOLORSTATIC:
Result := SendMessage(LParam, CN_BASE + Msg, WParam, LParam);
CN_CTLCOLORMSGBOX..CN_CTLCOLORSTATIC:
begin
SetTextColor(WParam, ColorToRGB(FFont.Color));
SetBkColor(WParam, ColorToRGB(FBrush.Color));
Result := FBrush.Handle;
end;
else
Result := CallWindowProc(FDefWndProc, FHandle, Msg, WParam, LParam);
end
else
inherited DefaultHandler(Message);
end;
function DoControlMsg(ControlHandle: HWnd; var Message): Boolean;
var
Control: TWinControl;
begin
DoControlMsg := False;
Control := FindControl(ControlHandle);
if Control <> nil then
with TMessage(Message) do
begin
Result := Control.Perform(Msg + CN_BASE, WParam, LParam);
DoControlMsg := True;
end;
end;
procedure TWinControl.PaintHandler(var Message: TWMPaint);
var
I, Clip, SaveIndex: Integer;
DC: HDC;
PS: TPaintStruct;
begin
DC := Message.DC;
if DC = 0 then DC := BeginPaint(Handle, PS);
try
if FControls = nil then PaintWindow(DC) else
begin
SaveIndex := SaveDC(DC);
Clip := SimpleRegion;
for I := 0 to FControls.Count - 1 do
with TControl(FControls[I]) do
if (Visible or (csDesigning in ComponentState) and
not (csNoDesignVisible in ControlStyle)) and
(csOpaque in ControlStyle) then
begin
Clip := ExcludeClipRect(DC, Left, Top, Left + Width, Top + Height);
if Clip = NullRegion then Break;
end;
if Clip <> NullRegion then PaintWindow(DC);
RestoreDC(DC, SaveIndex);
end;
PaintControls(DC, nil);
finally
if Message.DC = 0 then EndPaint(Handle, PS);
end;
end;
procedure TWinControl.PaintWindow(DC: HDC);
var
Message: TMessage;
begin
Message.Msg := WM_PAINT;
Message.WParam := DC;
Message.LParam := 0;
Message.Result := 0;
DefaultHandler(Message);
end;
procedure TWinControl.PaintControls(DC: HDC; First: TControl);
var
I, Count, SaveIndex: Integer;
FrameBrush: HBRUSH;
begin
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
with TControl(FControls[I]) 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);
IntersectClipRect(DC, 0, 0, Width, Height);
Perform(WM_PAINT, DC, 0);
RestoreDC(DC, SaveIndex);
Exclude(FControlState, csPaintCopy);
end;
Inc(I);
end;
end;
if FWinControls <> nil then
for I := 0 to FWinControls.Count - 1 do
with TWinControl(FWinControls[I]) do
if FCtl3D and (csFramed in ControlStyle) and
(Visible or (csDesigning in ComponentState) and
not (csNoDesignVisible in ControlStyle)) then
begin
FrameBrush := CreateSolidBrush(ColorToRGB(clBtnShadow));
FrameRect(DC, Rect(Left - 1, Top - 1, Left + Width, Top + Height),
FrameBrush);
DeleteObject(FrameBrush);
FrameBrush := CreateSolidBrush(ColorToRGB(clBtnHighlight));
FrameRect(DC, Rect(Left, Top, Left + Width + 1, Top + Height + 1),
FrameBrush);
DeleteObject(FrameBrush);
end;
end;
procedure TWinControl.PaintTo(DC: HDC; X, Y: Integer);
var
I, EdgeFlags, BorderFlags, SaveIndex: Integer;
R: TRect;
begin
Include(FControlState, csPaintCopy);
SaveIndex := SaveDC(DC);
MoveWindowOrg(DC, X, Y);
IntersectClipRect(DC, 0, 0, Width, Height);
BorderFlags := 0;
EdgeFlags := 0;
if GetWindowLong(Handle, GWL_EXSTYLE) and WS_EX_CLIENTEDGE <> 0 then
begin
EdgeFlags := EDGE_SUNKEN;
BorderFlags := BF_RECT or BF_ADJUST
end else
if GetWindowLong(Handle, GWL_STYLE) and WS_BORDER <> 0 then
begin
EdgeFlags := BDR_OUTER;
BorderFlags := BF_RECT or BF_ADJUST or BF_MONO;
end;
if BorderFlags <> 0 then
begin
SetRect(R, 0, 0, Width, Height);
DrawEdge(DC, R, EdgeFlags, BorderFlags);
MoveWindowOrg(DC, R.Left, R.Top);
IntersectClipRect(DC, 0, 0, R.Right - R.Left, R.Bottom - R.Top);
end;
Perform(WM_ERASEBKGND, DC, 0);
Perform(WM_PAINT, DC, 0);
if FWinControls <> nil then
for I := 0 to FWinControls.Count - 1 do
with TWinControl(FWinControls[I]) do
if Visible then PaintTo(DC, Left, Top);
RestoreDC(DC, SaveIndex);
Exclude(FControlState, csPaintCopy);
end;
procedure TWinControl.WMPaint(var Message: TWMPaint);
begin
if ControlCount = 0 then inherited else PaintHandler(Message);
end;
procedure TWinControl.WMCommand(var Message: TWMCommand);
begin
if not DoControlMsg(Message.Ctl, Message) then inherited;
end;
procedure TWinControl.WMNotify(var Message: TWMNotify);
begin
if not DoControlMsg(Message.NMHdr^.hWndFrom, Message) then inherited;
end;
procedure TWinControl.WMSysColorChange(var Message: TWMSysColorChange);
begin
Graphics.PaletteChanged;
Perform(CM_SYSCOLORCHANGE, 0, 0);
end;
procedure TWinControl.WMWinIniChange(var Message: TMessage);
begin
Perform(CM_WININICHANGE, Message.wParam, Message.lParam);
end;
procedure TWinControl.WMFontChange(var Message: TMessage);
begin
Perform(CM_FONTCHANGE, 0, 0);
end;
procedure TWinControl.WMTimeChange(var Message: TMessage);
begin
Perform(CM_TIMECHANGE, 0, 0);
end;
procedure TWinControl.WMHScroll(var Message: TWMHScroll);
begin
if not DoControlMsg(Message.ScrollBar, Message) then inherited;
end;
procedure TWinControl.WMVScroll(var Message: TWMVScroll);
begin
if not DoControlMsg(Message.ScrollBar, Message) then inherited;
end;
procedure TWinControl.WMCompareItem(var Message: TWMCompareItem);
begin
if not DoControlMsg(Message.CompareItemStruct^.CtlID, Message) then inherited;
end;
procedure TWinControl.WMDeleteItem(var Message: TWMDeleteItem);
begin
if not DoControlMsg(Message.DeleteItemStruct^.CtlID, Message) then inherited;
end;
procedure TWinControl.WMDrawItem(var Message: TWMDrawItem);
begin
if not DoControlMsg(Message.DrawItemStruct^.CtlID, Message) then inherited;
end;
procedure TWinControl.WMMeasureItem(var Message: TWMMeasureItem);
begin
if not DoControlMsg(Message.MeasureItemStruct^.CtlID, Message) then inherited;
end;
procedure TWinControl.WMEraseBkgnd(var Message: TWMEraseBkgnd);
begin
FillRect(Message.DC, ClientRect, FBrush.Handle);
Message.Result := 1;
end;
procedure TWinControl.WMWindowPosChanged(var Message: TWMWindowPosChanged);
var
Framed, Resized: Boolean;
begin
Framed := FCtl3D and (csFramed in ControlStyle) and (Parent <> nil) and
(Message.WindowPos^.flags and SWP_NOREDRAW = 0);
Resized := (Message.WindowPos^.flags and (SWP_NOMOVE or SWP_NOSIZE) <>
(SWP_NOMOVE or SWP_NOSIZE)) and IsWindowVisible(FHandle);
if Framed and Resized then InvalidateFrame;
UpdateBounds;
inherited;
if Framed and (Resized or (Message.WindowPos^.flags and
(SWP_SHOWWINDOW or SWP_HIDEWINDOW) <> 0)) then
InvalidateFrame;
end;
procedure TWinControl.WMSize(var Message: TWMSize);
begin
UpdateBounds;
inherited;
Realign;
end;
procedure TWinControl.WMMove(var Message: TWMMove);
begin
inherited;
UpdateBounds;
end;
procedure TWinControl.WMSetCursor(var Message: TWMSetCursor);
var
Cursor: TCursor;
Control: TControl;
P: TPoint;
begin
with Message do
if CursorWnd = FHandle then
case Smallint(HitTest) of
HTCLIENT:
begin
if csDesigning in ComponentState then
Cursor := crArrow
else
begin
Cursor := Screen.Cursor;
if Cursor = crDefault then
begin
GetCursorPos(P);
Control := ControlAtPos(ScreenToClient(P), False);
if Control <> nil then Cursor := Control.FCursor;
if Cursor = crDefault then Cursor := FCursor;
end;
end;
if Cursor <> crDefault then
begin
Windows.SetCursor(Screen.Cursors[Cursor]);
Result := 1;
Exit;
end;
end;
HTERROR:
if (MouseMsg = WM_LBUTTONDOWN) and (Application.Handle <> 0) and
(GetForegroundWindow <> GetLastActivePopup(Application.Handle)) then
begin
Application.BringToFront;
Exit;
end;
end;
inherited;
end;
procedure TWinControl.WMSetFocus(var Message: TWMSetFocus);
begin
inherited;
SetIme;
end;
procedure TWinControl.WMKillFocus(var Message: TWMSetFocus);
begin
inherited;
ResetIme;
end;
procedure TWinControl.WMIMEStartComp(var Message: TMessage);
begin
FInImeComposition := True;
inherited;
end;
procedure TWinControl.WMIMEEndComp(var Message: TMessage);
begin
FInImeComposition := False;
inherited;
end;
function TWinControl.SetImeCompositionWindow(hWnd: HWND; Font: TFont;
XPos, YPos: Integer): Boolean;
var
H: HIMC;
CForm: TCompositionForm;
LFont: TLogFont;
begin
Result := False;
H := Imm32GetContext(hWnd);
if H <> 0 then
begin
with CForm do
begin
dwStyle := CFS_POINT;
ptCurrentPos.x := XPos;
ptCurrentPos.y := YPos;
end;
Imm32SetCompositionWindow(H, @CForm);
GetObject(Font.Handle, SizeOf(TLogFont), @LFont);
Imm32SetCompositionFont(H, @LFont);
Imm32ReleaseContext(hWnd, H);
Result := True;
end;
end;
procedure TWinControl.SetIme;
var
I: Integer;
HandleToSet: HKL;
begin
if not SysLocale.FarEast then Exit;
if FImeName <> '' then
begin
if (AnsiCompareText(FImeName, Screen.DefaultIme) <> 0) and (Screen.Imes.Count <> 0) then
begin
HandleToSet := Screen.DefaultKbLayout;
if FImeMode <> imDisable then
begin
I := Screen.Imes.IndexOf(FImeName);
if I >= 0 then
HandleToSet := HKL(Screen.Imes.Objects[I]);
end;
ActivateKeyboardLayout(HandleToSet, KLF_ACTIVATE);
end;
end;
SetImeMode(Handle, FImeMode);
end;
procedure TWinControl.ResetIme;
begin
if not SysLocale.FarEast then Exit;
if FImeName <> '' then
begin
if AnsiCompareText(FImeName, Screen.DefaultIme) <> 0 then
ActivateKeyboardLayout(Screen.DefaultKbLayout, KLF_ACTIVATE);
end;
if FImeMode = imDisable then Win32NLSEnableIME(Handle, TRUE);
end;
function TWinControl.ResetImeComposition(Action: DWORD): Boolean;
var
H: HIMC;
begin
Result := False;
if FInImeComposition then
begin
H := Imm32GetContext(Handle);
if H <> 0 then
begin
Result := Imm32NotifyIME(H, NI_COMPOSITIONSTR, Action, 0);
Imm32ReleaseContext(Handle, H);
end;
end;
end;
procedure TWinControl.DoEnter;
begin
if Assigned(FOnEnter) then FOnEnter(Self);
end;
procedure TWinControl.DoExit;
begin
if Assigned(FOnExit) then FOnExit(Self);
end;
procedure TWinControl.KeyDown(var Key: Word; Shift: TShiftState);
begin
if Assigned(FOnKeyDown) then FOnKeyDown(Self, Key, Shift);
end;
function TWinControl.DoKeyDown(var Message: TWMKey): Boolean;
var
ShiftState: TShiftState;
Form: TForm;
begin
Result := True;
Form := GetParentForm(Self);
if (Form <> nil) and (Form <> Self) and Form.KeyPreview and
TWinControl(Form).DoKeyDown(Message) then Exit;
with Message do
begin
ShiftState := KeyDataToShiftState(KeyData);
if not (csNoStdEvents in ControlStyle) then
begin
KeyDown(CharCode, ShiftState);
if CharCode = 0 then Exit;
end;
if (CharCode = VK_APPS) and (ShiftState = []) then
CheckMenuPopup(SmallPoint(0, 0));
end;
Result := False;
end;
procedure TWinControl.WMKeyDown(var Message: TWMKeyDown);
begin
if not DoKeyDown(Message) then inherited;
end;
procedure TWinControl.WMSysKeyDown(var Message: TWMKeyDown);
begin
if not DoKeyDown(Message) then inherited;
end;
procedure TWinControl.KeyUp(var Key: Word; Shift: TShiftState);
begin
if Assigned(FOnKeyUp) then FOnKeyUp(Self, Key, Shift);
end;
function TWinControl.DoKeyUp(var Message: TWMKey): Boolean;
var
Form: TForm;
begin
Result := True;
Form := GetParentForm(Self);
if (Form <> nil) and (Form <> Self) and Form.KeyPreview and
TWinControl(Form).DoKeyUp(Message) then Exit;
if not (csNoStdEvents in ControlStyle) then
with Message do
begin
KeyUp(CharCode, KeyDataToShiftState(KeyData));
if CharCode = 0 then Exit;
end;
Result := False;
end;
procedure TWinControl.WMKeyUp(var Message: TWMKeyUp);
begin
if not DoKeyUp(Message) then inherited;
end;
procedure TWinControl.WMSysKeyUp(var Message: TWMKeyUp);
begin
if not DoKeyUp(Message) then inherited;
end;
procedure TWinControl.KeyPress(var Key: Char);
begin
if Assigned(FOnKeyPress) then FOnKeyPress(Self, Key);
end;
function TWinControl.DoKeyPress(var Message: TWMKey): Boolean;
var
Form: TForm;
begin
Result := True;
Form := GetParentForm(Self);
if (Form <> nil) and (Form <> Self) and Form.KeyPreview and
TWinControl(Form).DoKeyPress(Message) then Exit;
if not (csNoStdEvents in ControlStyle) then
with Message do
begin
KeyPress(Char(CharCode));
if Char(CharCode) = #0 then Exit;
end;
Result := False;
end;
procedure TWinControl.WMChar(var Message: TWMChar);
begin
if not DoKeyPress(Message) then inherited;
end;
procedure TWinControl.WMSysCommand(var Message: TWMSysCommand);
var
Form: TForm;
begin
with Message do
if (CmdType and $FFF0 = SC_KEYMENU) and (Key <> VK_SPACE) and
(Key <> Word('-')) and not IsIconic(FHandle) and (GetCapture = 0) and
(Application.MainForm <> Self) then
begin
Form := GetParentForm(Self);
if (Form <> nil) and
(Form.Perform(CM_APPSYSCOMMAND, 0, Longint(@Message)) <> 0) then
Exit;
end;
inherited;
end;
procedure TWinControl.WMCharToItem(var Message: TWMCharToItem);
begin
if not DoControlMsg(Message.ListBox, Message) then inherited;
end;
procedure TWinControl.WMParentNotify(var Message: TWMParentNotify);
begin
with Message do
if (Event <> WM_CREATE) and (Event <> WM_DESTROY) or
not DoControlMsg(Message.ChildWnd, Message) then inherited;
end;
procedure TWinControl.WMVKeyToItem(var Message: TWMVKeyToItem);
begin
if not DoControlMsg(Message.ListBox, Message) then inherited;
end;
procedure TWinControl.WMDestroy(var Message: TWMDestroy);
begin
inherited;
RemoveProp(FHandle, MakeIntAtom(ControlAtom));
RemoveProp(FHandle, MakeIntAtom(WindowAtom));
end;
procedure TWinControl.WMNCDestroy(var Message: TWMNCDestroy);
begin
inherited;
FHandle := 0;
FShowing := False;
end;
procedure TWinControl.WMNCHitTest(var Message: TWMNCHitTest);
begin
with Message do
if (csDesigning in ComponentState) and (FParent <> nil) then
Result := HTCLIENT
else
inherited;
end;
function TWinControl.PaletteChanged(Foreground: Boolean): Boolean;
var
I: Integer;
begin
Result := inherited PaletteChanged(Foreground);
for I := ControlCount - 1 downto 0 do
begin
if Foreground and Result then Exit;
Result := Controls[I].PaletteChanged(Foreground) or Result;
end;
end;
procedure TWinControl.WMQueryNewPalette(var Message: TMessage);
begin
Include(FControlState, csPalette);
Message.Result := Longint(PaletteChanged(True));
end;
procedure TWinControl.WMPaletteChanged(var Message: TMessage);
begin
Message.Result := Longint(PaletteChanged(False));
end;
procedure TWinControl.CMShowHintChanged(var Message: TMessage);
begin
inherited;
NotifyControls(CM_PARENTSHOWHINTCHANGED);
end;
procedure TWinControl.CMEnter(var Message: TCMEnter);
begin
DoEnter;
end;
procedure TWinControl.CMExit(var Message: TCMExit);
begin
DoExit;
end;
procedure TWinControl.CMDesignHitTest(var Message: TCMDesignHitTest);
begin
if not IsControlMouseMsg(Message) then inherited;
end;
procedure TWinControl.CMChildKey(var Message: TMessage);
begin
if FParent <> nil then FParent.WindowProc(Message);
end;
procedure TWinControl.CMDialogKey(var Message: TCMDialogKey);
begin
Broadcast(Message);
end;
procedure TWinControl.CMDialogChar(var Message: TCMDialogChar);
begin
Broadcast(Message);
end;
procedure TWinControl.CMFocusChanged(var Message: TCMFocusChanged);
begin
Broadcast(Message);
end;
procedure TWinControl.CMVisibleChanged(var Message: TMessage);
begin
if not FVisible and (Parent <> nil) then RemoveFocus(False);
if not (csDesigning in ComponentState) or
(csNoDesignVisible in ControlStyle) then UpdateControlState;
end;
procedure TWinControl.CMShowingChanged(var Message: TMessage);
const
ShowFlags: array[Boolean] of Word = (
SWP_NOSIZE + SWP_NOMOVE + SWP_NOZORDER + SWP_NOACTIVATE + SWP_HIDEWINDOW,
SWP_NOSIZE + SWP_NOMOVE + SWP_NOZORDER + SWP_NOACTIVATE + SWP_SHOWWINDOW);
begin
SetWindowPos(FHandle, 0, 0, 0, 0, 0, ShowFlags[FShowing]);
end;
procedure TWinControl.CMEnabledChanged(var Message: TMessage);
begin
if not FEnabled and (Parent <> nil) then RemoveFocus(False);
if HandleAllocated and not (csDesigning in ComponentState) then
EnableWindow(FHandle, FEnabled);
end;
procedure TWinControl.CMColorChanged(var Message: TMessage);
begin
inherited;
FBrush.Color := FColor;
NotifyControls(CM_PARENTCOLORCHANGED);
end;
procedure TWinControl.CMFontChanged(var Message: TMessage);
begin
inherited;
if HandleAllocated then Perform(WM_SETFONT, FFont.Handle, 0);
NotifyControls(CM_PARENTFONTCHANGED);
end;
procedure TWinControl.CMCursorChanged(var Message: TMessage);
var
P: TPoint;
begin
if GetCapture = 0 then
begin
GetCursorPos(P);
if FindDragTarget(P, False) = Self then
Perform(WM_SETCURSOR, Handle, HTCLIENT);
end;
end;
procedure TWinControl.CMCtl3DChanged(var Message: TMessage);
begin
if (csFramed in ControlStyle) and (Parent <> nil) and HandleAllocated and
IsWindowVisible(FHandle) then InvalidateFrame;
NotifyControls(CM_PARENTCTL3DCHANGED);
end;
procedure TWinControl.CMParentCtl3DChanged(var Message: TMessage);
begin
if FParentCtl3D then
begin
SetCtl3D(FParent.FCtl3D);
FParentCtl3D := True;
end;
end;
procedure TWinControl.CMSysColorChange(var Message: TMessage);
begin
Broadcast(Message);
end;
procedure TWinControl.CMWinIniChange(var Message: TWMWinIniChange);
begin
Broadcast(Message);
end;
procedure TWinControl.CMFontChange(var Message: TMessage);
begin
Broadcast(Message);
end;
procedure TWinControl.CMTimeChange(var Message: TMessage);
begin
Broadcast(Message);
end;
procedure TWinControl.CMDrag(var Message: TCMDrag);
begin
with Message, DragRec^ do
case DragMessage of
dmDragEnter, dmDragLeave, dmDragMove, dmDragDrop:
if Target <> nil then TControl(Target).DoDragMsg(Message);
dmFindTarget:
begin
Result := Longint(ControlAtPos(ScreenToClient(Pos), False));
if Result = 0 then Result := Longint(Self);
end;
end;
end;
procedure TWinControl.CMControlListChange(var Message: TMessage);
begin
if FParent <> nil then FParent.WindowProc(Message);
end;
function TWinControl.IsMenuKey(var Message: TWMKey): Boolean;
var
Control: TWinControl;
Form: TForm;
LocalPopupMenu: TPopupMenu;
begin
Result := True;
if not (csDesigning in ComponentState) then
begin
Control := Self;
while Control <> nil do
begin
LocalPopupMenu := Control.GetPopupMenu;
if Assigned(LocalPopupMenu) and
LocalPopupMenu.IsShortCut(Message) then Exit;
Control := Control.Parent;
end;
Form := GetParentForm(Self);
if (Form <> nil) and (Form.Menu <> nil) and
Form.Menu.IsShortCut(Message) then Exit;
end;
with Message do
if SendAppMessage(CM_APPKEYDOWN, CharCode, KeyData) <> 0 then Exit;
Result := False;
end;
procedure TWinControl.CNKeyDown(var Message: TWMKeyDown);
var
Mask: Integer;
begin
with Message do
begin
Result := 1;
if IsMenuKey(Message) then Exit;
if not (csDesigning in ComponentState) then
begin
if Perform(CM_CHILDKEY, CharCode, Integer(Self)) <> 0 then Exit;
Mask := 0;
case CharCode of
VK_TAB:
Mask := DLGC_WANTTAB;
VK_LEFT, VK_RIGHT, VK_UP, VK_DOWN:
Mask := DLGC_WANTARROWS;
VK_RETURN, VK_EXECUTE, VK_ESCAPE, VK_CANCEL:
Mask := DLGC_WANTALLKEYS;
end;
if (Mask <> 0) and
(Perform(CM_WANTSPECIALKEY, CharCode, 0) = 0) and
(Perform(WM_GETDLGCODE, 0, 0) and Mask = 0) and
(GetParentForm(Self).Perform(CM_DIALOGKEY,
CharCode, KeyData) <> 0) then Exit;
end;
Result := 0;
end;
end;
procedure TWinControl.CNKeyUp(var Message: TWMKeyUp);
begin
if not (csDesigning in ComponentState) then
with Message do
case CharCode of
VK_TAB, VK_LEFT, VK_RIGHT, VK_UP, VK_DOWN,
VK_RETURN, VK_EXECUTE, VK_ESCAPE, VK_CANCEL:
Result := Perform(CM_WANTSPECIALKEY, CharCode, 0);
end;
end;
procedure TWinControl.CNChar(var Message: TWMChar);
begin
if not (csDesigning in ComponentState) then
with Message do
begin
Result := 1;
if (Perform(WM_GETDLGCODE, 0, 0) and DLGC_WANTCHARS = 0) and
(GetParentForm(Self).Perform(CM_DIALOGCHAR,
CharCode, KeyData) <> 0) then Exit;
Result := 0;
end;
end;
procedure TWinControl.CNSysKeyDown(var Message: TWMKeyDown);
begin
with Message do
begin
Result := 1;
if IsMenuKey(Message) then Exit;
if not (csDesigning in ComponentState) then
begin
if Perform(CM_CHILDKEY, CharCode, Integer(Self)) <> 0 then Exit;
if GetParentForm(Self).Perform(CM_DIALOGKEY,
CharCode, KeyData) <> 0 then Exit;
end;
Result := 0;
end;
end;
procedure TWinControl.CNSysChar(var Message: TWMChar);
begin
if not (csDesigning in ComponentState) then
with Message do
if CharCode <> VK_SPACE then
Result := GetParentForm(Self).Perform(CM_DIALOGCHAR,
CharCode, KeyData);
end;
procedure TWinControl.SetBounds(ALeft, ATop, AWidth, AHeight: Integer);
var
WindowPlacement: TWindowPlacement;
begin
if (ALeft <> FLeft) or (ATop <> FTop) or
(AWidth <> FWidth) or (AHeight <> FHeight) then
begin
if HandleAllocated and not IsIconic(FHandle) then
SetWindowPos(FHandle, 0, ALeft, ATop, AWidth, AHeight,
SWP_NOZORDER + SWP_NOACTIVATE)
else
begin
FLeft := ALeft;
FTop := ATop;
FWidth := AWidth;
FHeight := AHeight;
if HandleAllocated then
begin
WindowPlacement.Length := SizeOf(WindowPlacement);
GetWindowPlacement(FHandle, @WindowPlacement);
WindowPlacement.rcNormalPosition := BoundsRect;
SetWindowPlacement(FHandle, @WindowPlacement);
end;
end;
RequestAlign;
end;
end;
procedure TWinControl.ScaleControls(M, D: Integer);
var
I: Integer;
begin
for I := 0 to ControlCount - 1 do Controls[I].ChangeScale(M, D);
end;
procedure TWinControl.ChangeScale(M, D: Integer);
begin
DisableAlign;
try
ScaleControls(M, D);
inherited ChangeScale(M, D);
finally
EnableAlign;
end;
end;
procedure TWinControl.ScaleBy(M, D: Integer);
const
SWP_HIDE = SWP_NOSIZE + SWP_NOMOVE + SWP_NOZORDER + SWP_NOACTIVATE + SWP_HIDEWINDOW;
SWP_SHOW = SWP_NOSIZE + SWP_NOMOVE + SWP_NOZORDER + SWP_NOACTIVATE + SWP_SHOWWINDOW;
var
IsVisible: Boolean;
R: TRect;
begin
IsVisible := HandleAllocated and IsWindowVisible(Handle);
if IsVisible then SetWindowPos(Handle, 0, 0, 0, 0, 0, SWP_HIDE);
R := BoundsRect;
ChangeScale(M, D);
SetBounds(R.Left, R.Top, Width, Height);
if IsVisible then SetWindowPos(Handle, 0, 0, 0, 0, 0, SWP_SHOW);
end;
procedure TWinControl.ScrollBy(DeltaX, DeltaY: Integer);
var
IsVisible: Boolean;
I: Integer;
Control: TControl;
begin
IsVisible := (FHandle <> 0) and IsWindowVisible(FHandle);
if IsVisible then ScrollWindow(FHandle, DeltaX, DeltaY, nil, nil);
for I := 0 to ControlCount - 1 do
begin
Control := Controls[I];
if not (Control is TWinControl) or (TWinControl(Control).FHandle = 0) then
begin
Inc(Control.FLeft, DeltaX);
Inc(Control.FTop, DeltaY);
end else
if not IsVisible then
with TWinControl(Control) do
SetWindowPos(FHandle, 0, FLeft + DeltaX, FTop + DeltaY,
FWidth, FHeight, SWP_NOZORDER + SWP_NOACTIVATE);
end;
Realign;
end;
procedure TWinControl.ShowControl(AControl: TControl);
begin
if Parent <> nil then Parent.ShowControl(Self);
end;
procedure TWinControl.SetZOrderPosition(Position: Integer);
var
I, Count: Integer;
Pos: HWND;
begin
if FParent <> nil then
begin
if FParent.FControls <> nil then
Dec(Position, FParent.FControls.Count);
I := FParent.FWinControls.IndexOf(Self);
if I >= 0 then
begin
Count := FParent.FWinControls.Count;
if Position < 0 then Position := 0;
if Position >= Count then Position := Count - 1;
if Position <> I then
begin
FParent.FWinControls.Delete(I);
FParent.FWinControls.Insert(Position, Self);
end;
end;
if FHandle <> 0 then
begin
if Position = 0 then Pos := HWND_BOTTOM
else if Position = FParent.FWinControls.Count - 1 then Pos := HWND_TOP
else if Position > I then
Pos := TWinControl(FParent.FWinControls[Position + 1]).Handle
else if Position < I then
Pos := TWinControl(FParent.FWinControls[Position]).Handle
else Exit;
SetWindowPos(FHandle, Pos, 0, 0, 0, 0, SWP_NOMOVE + SWP_NOSIZE);
end;
end;
end;
procedure TWinControl.SetZOrder(TopMost: Boolean);
const
WindowPos: array[Boolean] of Word = (HWND_BOTTOM, HWND_TOP);
var
N, M: Integer;
begin
if FParent <> nil then
begin
if TopMost then N := FParent.FWinControls.Count - 1 else N := 0;
M := 0;
if FParent.FControls <> nil then M := FParent.FControls.Count;
SetZOrderPosition(M + N);
end
else if FHandle <> 0 then
SetWindowPos(FHandle, WindowPos[TopMost], 0, 0, 0, 0,
SWP_NOMOVE + SWP_NOSIZE);
end;
function TWinControl.GetDeviceContext(var WindowHandle: HWnd): HDC;
begin
if csDesigning in ComponentState then
Result := GetDCEx(Handle, 0, DCX_CACHE or DCX_CLIPSIBLINGS)
else
Result := GetDC(Handle);
if Result = 0 then raise EOutOfResources.CreateRes(SWindowDCError);
WindowHandle := FHandle;
end;
procedure TWinControl.Invalidate;
begin
Perform(CM_INVALIDATE, 0, 0);
end;
procedure TWinControl.CMInvalidate(var Message: TMessage);
begin
if HandleAllocated then
begin
if Parent <> nil then Parent.Perform(CM_INVALIDATE, 1, 0);
if Message.WParam = 0 then
InvalidateRect(FHandle, nil, not (csOpaque in ControlStyle));
end;
end;
procedure TWinControl.Update;
begin
if HandleAllocated then UpdateWindow(FHandle);
end;
procedure TWinControl.Repaint;
begin
Invalidate;
Update;
end;
procedure TWinControl.InvalidateFrame;
var
R: TRect;
begin
R := BoundsRect;
InflateRect(R, 1, 1);
InvalidateRect(Parent.FHandle, @R, True);
end;
function TWinControl.CanFocus: Boolean;
var
Control: TWinControl;
Form: TForm;
begin
Result := False;
Form := GetParentForm(Self);
if Form <> nil then
begin
Control := Self;
while Control <> Form do
begin
if not (Control.FVisible and Control.FEnabled) then Exit;
Control := Control.Parent;
end;
Result := True;
end;
end;
procedure TWinControl.SetFocus;
begin
ValidParentForm(Self).FocusControl(Self);
end;
function TWinControl.Focused: Boolean;
begin
Result := (FHandle <> 0) and (GetFocus = FHandle);
end;
procedure TWinControl.HandleNeeded;
begin
if FHandle = 0 then
begin
if Parent <> nil then Parent.HandleNeeded;
CreateHandle;
end;
end;
function TWinControl.GetHandle: HWnd;
begin
HandleNeeded;
Result := FHandle;
end;
function TWinControl.GetClientOrigin: TPoint;
begin
Result.X := 0;
Result.Y := 0;
Windows.ClientToScreen(Handle, Result);
end;
function TWinControl.GetClientRect: TRect;
begin
Windows.GetClientRect(Handle, Result);
end;
procedure TWinControl.SetCtl3D(Value: Boolean);
begin
if FCtl3D <> Value then
begin
FCtl3D := Value;
FParentCtl3D := False;
Perform(CM_CTL3DCHANGED, 0, 0);
end;
end;
function TWinControl.IsCtl3DStored: Boolean;
begin
Result := not ParentCtl3D;
end;
procedure TWinControl.SetParentCtl3D(Value: Boolean);
begin
if FParentCtl3D <> Value then
begin
FParentCtl3D := Value;
if FParent <> nil then Perform(CM_PARENTCTL3DCHANGED, 0, 0);
end;
end;
function TWinControl.GetTabOrder: TTabOrder;
begin
if FParent <> nil then
Result := FParent.FTabList.IndexOf(Self)
else
Result := -1;
end;
procedure TWinControl.UpdateTabOrder(Value: TTabOrder);
var
CurIndex, Count: Integer;
begin
CurIndex := GetTabOrder;
if CurIndex >= 0 then
begin
Count := FParent.FTabList.Count;
if Value < 0 then Value := 0;
if Value >= Count then Value := Count - 1;
if Value <> CurIndex then
begin
FParent.FTabList.Delete(CurIndex);
FParent.FTabList.Insert(Value, Self);
end;
end;
end;
procedure TWinControl.SetTabOrder(Value: TTabOrder);
begin
if csReadingState in ControlState then
FTabOrder := Value else
UpdateTabOrder(Value);
end;
procedure TWinControl.SetTabStop(Value: Boolean);
var
Style: Longint;
begin
if FTabStop <> Value then
begin
FTabStop := Value;
if HandleAllocated then
begin
Style := GetWindowLong(FHandle, GWL_STYLE) and not WS_TABSTOP;
if Value then Style := Style or WS_TABSTOP;
SetWindowLong(FHandle, GWL_STYLE, Style);
end;
Perform(CM_TABSTOPCHANGED, 0, 0);
end;
end;
function TWinControl.HandleAllocated: Boolean;
begin
Result := FHandle <> 0;
end;
procedure TWinControl.UpdateBounds;
var
ParentHandle: HWnd;
Rect: TRect;
WindowPlacement: TWindowPlacement;
begin
if IsIconic(FHandle) then
begin
WindowPlacement.Length := SizeOf(WindowPlacement);
GetWindowPlacement(FHandle, @WindowPlacement);
Rect := WindowPlacement.rcNormalPosition;
end else
GetWindowRect(FHandle, Rect);
if GetWindowLong(FHandle, GWL_STYLE) and WS_CHILD <> 0 then
begin
ParentHandle := GetWindowLong(FHandle, GWL_HWNDPARENT);
Windows.ScreenToClient(ParentHandle, Rect.TopLeft);
Windows.ScreenToClient(ParentHandle, Rect.BottomRight);
end;
FLeft := Rect.Left;
FTop := Rect.Top;
FWidth := Rect.Right - Rect.Left;
FHeight := Rect.Bottom - Rect.Top;
end;
procedure TWinControl.GetTabOrderList(List: TList);
var
I: Integer;
Control: TWinControl;
begin
if FTabList <> nil then
for I := 0 to FTabList.Count - 1 do
begin
Control := FTabList[I];
List.Add(Control);
Control.GetTabOrderList(List);
end;
end;
function TWinControl.FindNextControl(CurControl: TWinControl;
GoForward, CheckTabStop, CheckParent: Boolean): TWinControl;
var
I, StartIndex: Integer;
List: TList;
begin
Result := nil;
List := TList.Create;
try
GetTabOrderList(List);
if List.Count > 0 then
begin
StartIndex := List.IndexOf(CurControl);
if StartIndex = -1 then
if GoForward then StartIndex := List.Count - 1 else StartIndex := 0;
I := StartIndex;
repeat
if GoForward then
begin
Inc(I);
if I = List.Count then I := 0;
end else
begin
if I = 0 then I := List.Count;
Dec(I);
end;
CurControl := List[I];
if CurControl.CanFocus and
(not CheckTabStop or CurControl.TabStop) and
(not CheckParent or (CurControl.Parent = Self)) then
Result := CurControl;
until (Result <> nil) or (I = StartIndex);
end;
finally
List.Destroy;
end;
end;
procedure TWinControl.SelectNext(CurControl: TWinControl;
GoForward, CheckTabStop: Boolean);
begin
CurControl := FindNextControl(CurControl, GoForward,
CheckTabStop, not CheckTabStop);
if CurControl <> nil then CurControl.SetFocus;
end;
procedure TWinControl.SelectFirst;
var
Form: TForm;
Control: TWinControl;
begin
Form := GetParentForm(Self);
if Form <> nil then
begin
Control := FindNextControl(nil, True, True, False);
if Control = nil then
Control := FindNextControl(nil, True, False, False);
if Control <> nil then Form.ActiveControl := Control;
end;
end;
procedure TWinControl.GetChildren(Proc: TGetChildProc);
var
I: Integer;
Control: TControl;
Form: TForm;
begin
Form := GetParentForm(Self);
for I := 0 to ControlCount - 1 do
begin
Control := Controls[I];
if Control.Owner = Form then Proc(Control);
end;
end;
procedure TWinControl.SetChildOrder(Child: TComponent; Order: Integer);
begin
if Child is TWinControl then
TWinControl(Child).SetZOrderPosition(Order)
else if Child is TControl then
TControl(Child).SetZOrderPosition(Order);
end;
{ TGraphicControl }
constructor TGraphicControl.Create(AOwner: TComponent);
begin
inherited Create(AOwner);
FCanvas := TControlCanvas.Create;
TControlCanvas(FCanvas).Control := Self;
end;
destructor TGraphicControl.Destroy;
begin
FCanvas.Free;
inherited Destroy;
end;
procedure TGraphicControl.WMPaint(var Message: TWMPaint);
begin
if Message.DC <> 0 then
begin
Canvas.Handle := Message.DC;
try
Paint;
finally
Canvas.Handle := 0;
end;
end;
end;
procedure TGraphicControl.Paint;
begin
end;
{ THintWindow }
constructor THintWindow.Create(AOwner: TComponent);
var
NonClientMetrics: TNonClientMetrics;
begin
inherited Create(AOwner);
Color := $80FFFF;
NonClientMetrics.cbSize := sizeof(NonClientMetrics);
if SystemParametersInfo( SPI_GETNONCLIENTMETRICS,0,@NonClientMetrics,0) then
begin
with Canvas do
begin
Font.Handle := CreateFontIndirect(NonClientMetrics.lfStatusFont);
Brush.Style := bsClear;
end;
end else
begin
with Canvas do
begin
Font.Name := DefFontData.Name;
Font.Height := DefFontData.Height;
Brush.Style := bsClear;
end;
end;
end;
procedure THintWindow.CreateParams(var Params: TCreateParams);
begin
inherited CreateParams(Params);
with Params do
begin
Style := WS_POPUP or WS_BORDER or WS_DISABLED;
WindowClass.Style := WindowClass.Style or CS_SAVEBITS;
if NewStyleControls then ExStyle := WS_EX_TOOLWINDOW;
end;
end;
procedure THintWindow.Paint;
var
R: TRect;
begin
R := ClientRect;
Inc(R.Left, 1);
Canvas.Font.Color := clInfoText;
DrawText(Canvas.Handle, PChar(Caption), -1, R, DT_LEFT or DT_NOPREFIX or
DT_WORDBREAK);
end;
function THintWindow.IsHintMsg(var Msg: TMsg): Boolean;
begin
with Msg do
Result := ((Message >= WM_KEYFIRST) and (Message <= WM_KEYLAST)) or
((Message = CM_ACTIVATE) or (Message = CM_DEACTIVATE)) or
(Message = CM_APPKEYDOWN) or (Message = CM_APPSYSCOMMAND) or
(Message = WM_COMMAND) or ((Message > WM_MOUSEMOVE) and
(Message <= WM_MOUSELAST)) or (Message = WM_NCMOUSEMOVE);
end;
procedure THintWindow.ReleaseHandle;
begin
DestroyHandle;
end;
procedure THintWindow.CMTextChanged(var Message: TMessage);
begin
inherited;
Width := Canvas.TextWidth(Caption) + 6;
Height := Canvas.TextHeight(Caption) + 4;
end;
procedure THintWindow.ActivateHint(Rect: TRect; const AHint: string);
begin
Caption := AHint;
BoundsRect := Rect;
if Rect.Top + Height > Screen.Height then
Rect.Top := Screen.Height - Height;
if Rect.Left + Width > Screen.Width then
Rect.Left := Screen.Width - Width;
if Rect.Left < 0 then Rect.Left := 0;
if Rect.Bottom < 0 then Rect.Bottom := 0;
SetWindowPos(Handle, HWND_TOPMOST, Rect.Left, Rect.Top, 0,
0, SWP_SHOWWINDOW or SWP_NOACTIVATE or SWP_NOSIZE);
end;
{ TCustomControl }
constructor TCustomControl.Create(AOwner: TComponent);
begin
inherited Create(AOwner);
FCanvas := TControlCanvas.Create;
TControlCanvas(FCanvas).Control := Self;
end;
destructor TCustomControl.Destroy;
begin
FCanvas.Free;
inherited Destroy;
end;
procedure TCustomControl.WMPaint(var Message: TWMPaint);
begin
PaintHandler(Message);
end;
procedure TCustomControl.PaintWindow(DC: HDC);
begin
FCanvas.Handle := DC;
try
Paint;
finally
FCanvas.Handle := 0;
end;
end;
procedure TCustomControl.Paint;
begin
end;
{ TCustomImageList }
function GetRGBColor(Value: TColor): Integer;
begin
Result := ColorToRGB(Value);
case Result of
clNone: Result := CLR_NONE;
clDefault: Result := CLR_DEFAULT;
end;
end;
function GetColor(Value: Integer): TColor;
begin
Result := TColor(Value);
case Result of
CLR_NONE: Result := clNone;
CLR_DEFAULT: Result := clDefault;
end;
end;
function ClientToWindow(Handle: HWND; X, Y: Integer): TPoint;
var
Rect: TRect;
Point: TPoint;
begin
Point.X := X;
Point.Y := Y;
ClientToScreen(Handle, Point);
GetWindowRect(Handle, Rect);
Result.X := Point.X - Rect.Left;
Result.Y := Point.Y - Rect.Top;
end;
constructor TCustomImageList.Create(AOwner: TComponent);
begin
inherited Create(AOwner);
FWidth := 16;
FHeight := 16;
Initialize;
end;
constructor TCustomImageList.CreateSize(AWidth, AHeight: Integer);
begin
inherited Create(nil);
FWidth := AWidth;
FHeight := AHeight;
Initialize;
end;
destructor TCustomImageList.Destroy;
begin
while FClients.Count > 0 do
UnRegisterChanges(TChangeLink(FClients.Last));
FBitmap.Free;
FreeHandle;
FClients.Free;
inherited Destroy;
end;
procedure TCustomImageList.Initialize;
const
MaxSize = 32768;
begin
FClients := TList.Create;
if (Height < 1) or (Height > MaxSize) or (Width < 1) then
raise EInvalidOperation.CreateRes(SInvalidImageSize);
AllocBy := 4;
Masked := True;
DrawingStyle := dsNormal;
ImageType := itImage;
FBkColor := clNone;
FBlendColor := clNone;
DragCursor := crNone;
FBitmap := TBitmap.Create;
InitBitmap;
end;
function TCustomImageList.HandleAllocated: Boolean;
begin
Result := FHandle <> 0;
end;
procedure TCustomImageList.HandleNeeded;
begin
if FHandle = 0 then CreateImageList;
end;
procedure TCustomImageList.InitBitmap;
var
ScreenDC: HDC;
begin
ScreenDC := GetDC(0);
try
with FBitmap do
begin
Handle := CreateCompatibleBitmap(ScreenDC, Self.Width, Self.Height);
Canvas.Brush.Color := clBlack;
Canvas.FillRect(Rect(0, 0, Width, Height));
end;
finally
ReleaseDC(0, ScreenDC);
end;
end;
procedure TCustomImageList.SetNewDimensions(Value: HImageList);
var
AHeight, AWidth: Integer;
begin
AWidth := Width;
AHeight := Height;
ImageList_GetIconSize(Value, AWidth, AHeight);
FWidth := AWidth;
FHeight := AHeight;
InitBitmap;
end;
procedure TCustomImageList.SetWidth(Value: Integer);
begin
if Value <> Width then
begin
FWidth := Value;
if HandleAllocated then ImageList_SetIconSize(Handle, Width, Height);
Clear;
InitBitmap;
Change;
end;
end;
procedure TCustomImageList.SetHeight(Value: Integer);
begin
if Value <> Height then
begin
FHeight := Value;
if HandleAllocated then ImageList_SetIconSize(Handle, Width, Height);
Clear;
InitBitmap;
Change;
end;
end;
procedure TCustomImageList.SetHandle(Value: HImageList);
begin
FreeHandle;
if Value <> 0 then
begin
SetNewDimensions(Value);
FHandle := Value;
Change;
end;
end;
function TCustomImageList.GetHandle: HImageList;
begin
HandleNeeded;
Result := FHandle;
end;
function TCustomImageList.GetImageHandle(Image: TBitmap): HBITMAP;
begin
CheckImage(Image);
if Image <> nil then
Result := Image.Handle else
Result := FBitmap.Handle;
end;
procedure TCustomImageList.FreeHandle;
begin
if HandleAllocated and not ShareImages then
ImageList_Destroy(Handle);
FHandle := 0;
Change;
end;
procedure TCustomImageList.CreateImageList;
const
Mask: array[Boolean] of Longint = (0, ILC_MASK);
begin
FHandle := ImageList_Create(Width, Height, ILC_COLOR or Mask[Masked],
4, AllocBy);
if FHandle = 0 then raise EInvalidOperation.CreateRes(SInvalidImageList);
if FBkColor <> clNone then BkColor := FBkColor;
end;
function TCustomImageList.GetImageBitmap: HBITMAP;
var
Info: TImageInfo;
begin
if (Count > 0) and ImageList_GetImageInfo(Handle, 0, Info) then
begin
Result := Info.hbmImage;
DeleteObject(Info.hbmMask);
end
else Result := 0;
end;
function TCustomImageList.GetMaskBitmap: HBITMAP;
var
Info: TImageInfo;
begin
if (Count > 0) and ImageList_GetImageInfo(Handle, 0, Info) then
begin
Result := Info.hbmMask;
DeleteObject(Info.hbmImage);
end
else Result := 0;
end;
function TCustomImageList.Add(Image, Mask: TBitmap): Integer;
begin
Result := ImageList_Add(Handle, GetImageHandle(Image),
GetImageHandle(Mask));
end;
function TCustomImageList.AddMasked(Image: TBitmap; MaskColor: TColor): Integer;
begin
Result := ImageList_AddMasked(Handle, GetImageHandle(Image),
ColorToRGB(MaskColor));
Change;
end;
function TCustomImageList.AddIcon(Image: TIcon): Integer;
begin
if Image = nil then
Result := Add(nil, nil)
else
begin
CheckImage(Image);
Result := ImageList_AddIcon(Handle, Image.Handle);
end;
Change;
end;
procedure TCustomImageList.GetBitmap(Index: Integer; Image: TBitmap);
begin
if (Image <> nil) and HandleAllocated then
with Image do
begin
Height := FHeight;
Width := FWidth;
Draw(Canvas, 0, 0, Index);
end;
end;
procedure TCustomImageList.GetIcon(Index: Integer; Image: TIcon);
const
DrawingStyles: array[TDrawingStyle] of Longint = (ILD_FOCUS,
ILD_SELECTED, ILD_NORMAL, ILD_TRANSPARENT);
Images: array[TImageType] of Longint = (0, ILD_MASK);
begin
if (Image <> nil) and HandleAllocated then
Image.Handle := ImageList_GetIcon(Handle, Index,
DrawingStyles[DrawingStyle] or Images[ImageType]);
end;
function TCustomImageList.GetCount: Integer;
begin
if HandleAllocated then Result := ImageList_GetImageCount(Handle)
else Result := 0;
end;
procedure TCustomImageList.Replace(Index: Integer; Image, Mask: TBitmap);
begin
if HandleAllocated and not ImageList_Replace(Handle, Index,
GetImageHandle(Image), GetImageHandle(Mask)) then
raise EInvalidOperation.CreateRes(SReplaceImage);
Change;
end;
procedure TCustomImageList.ReplaceMasked(Index: Integer; NewImage: TBitmap; MaskColor: TColor);
var
TempIndex: Integer;
Image, Mask: TBitmap;
begin
if HandleAllocated then
begin
CheckImage(NewImage);
TempIndex := AddMasked(NewImage, MaskColor);
if TempIndex <> -1 then
try
Image := TBitmap.Create;
Mask := TBitmap.Create;
try
with Image do
begin
Height := FHeight;
Width := FWidth;
end;
with Mask do
begin
Height := FHeight;
Width := FWidth;
end;
ImageList_Draw(Handle, TempIndex, Image.Canvas.Handle, 0, 0, ILD_NORMAL);
ImageList_Draw(Handle, TempIndex, Mask.Canvas.Handle, 0, 0, ILD_NORMAL);
if not ImageList_Replace(Handle, Index, Image.Handle, Mask.Handle) then
raise EInvalidOperation.CreateRes(SReplaceImage);
finally
Image.Free;
Mask.Free;
end;
finally
Delete(TempIndex);
end
else raise EInvalidOperation.CreateRes(SReplaceImage);
end;
Change;
end;
procedure TCustomImageList.ReplaceIcon(Index: Integer; Image: TIcon);
begin
if HandleAllocated then
if Image = nil then Replace(Index, nil, nil)
else begin
CheckImage(Image);
if ImageList_ReplaceIcon(Handle, Index, Image.Handle) = -1 then
raise EInvalidOperation.CreateRes(SReplaceImage);
end;
Change;
end;
procedure TCustomImageList.Delete(Index: Integer);
begin
if Index >= Count then raise EInvalidOperation.CreateRes(SImageIndexError);
if HandleAllocated then ImageList_Remove(Handle, Index);
Change;
end;
procedure TCustomImageList.Clear;
begin
Delete(-1);
Change;
end;
procedure TCustomImageList.SetBkColor(Value: TColor);
begin
if HandleAllocated then ImageList_SetBkColor(Handle, GetRGBColor(Value))
else FBkColor := Value;
Change;
end;
function TCustomImageList.GetBkColor: TColor;
begin
if HandleAllocated then Result := GetColor(ImageList_GetBkColor(Handle))
else Result := FBkColor;
end;
procedure TCustomImageList.Draw(Canvas: TCanvas; X, Y, Index: Integer);
const
DrawingStyles: array[TDrawingStyle] of Longint = (ILD_FOCUS,
ILD_SELECTED, ILD_NORMAL, ILD_TRANSPARENT);
Images: array[TImageType] of Longint = (0, ILD_MASK);
begin
if HandleAllocated then
ImageList_DrawEx(Handle, Index, Canvas.Handle, X, Y, 0, 0,
GetRGBColor(BkColor), GetRGBColor(BlendColor),
DrawingStyles[DrawingStyle] or Images[ImageType]);
end;
procedure TCustomImageList.DrawOverlay(Canvas: TCanvas; X, Y: Integer;
ImageIndex: Integer; Overlay: TOverlay);
const
Images: array[TImageType] of Longint = (0, ILD_MASK);
var
Index: Integer;
begin
if HandleAllocated then
begin
Index := IndexToOverlayMask(Overlay + 1);
ImageList_Draw(Handle, ImageIndex, Canvas.Handle, X, Y,
Images[ImageType] or (ILD_OVERLAYMASK and Index));
end;
end;
function TCustomImageList.Overlay(ImageIndex: Integer; Overlay: TOverlay): Boolean;
begin
if HandleAllocated then
Result := ImageList_SetOverlayImage(Handle, ImageIndex, Overlay + 1)
else Result := False;
end;
procedure TCustomImageList.CopyImages(Value: HImageList);
var
I: Integer;
Image, Mask: TBitmap;
ARect: TRect;
begin
ARect := Rect(0, 0, Width, Height);
Image := TBitmap.Create;
with Image do
begin
Height := FHeight;
Width := FWidth;
end;
Mask := TBitmap.Create;
with Mask do
begin
Height := FHeight;
Width := FWidth;
end;
try
for I := 0 to ImageList_GetImageCount(Value) - 1 do
begin
with Image.Canvas do
begin
FillRect(ARect);
ImageList_Draw(Value, I, Handle, 0, 0, ILD_NORMAL);
end;
with Mask.Canvas do
begin
FillRect(ARect);
ImageList_Draw(Value, I, Handle, 0, 0, ILD_MASK);
end;
Add(Image, Mask);
end;
finally
Image.Free;
Mask.Free;
end;
end;
procedure TCustomImageList.GetImages(Index: Integer; Image, Mask: TBitmap);
var
R: TRect;
begin
R := Rect(0, 0, Width, Height);
with Image.Canvas do
begin
Brush.Color := clWhite;
FillRect(R);
ImageList_Draw(Self.Handle, Index, Handle, 0, 0, ILD_NORMAL);
end;
with Mask.Canvas do
begin
Brush.Color := clWhite;
FillRect(R);
ImageList_Draw(Self.Handle, Index, Handle, 0, 0, ILD_MASK);
end;
end;
procedure TCustomImageList.InsertImage(Index: Integer;
Image, Mask: TBitmap; MaskColor: TColor);
var
I: Integer;
OldImage, OldMask: TBitmap;
TempList: TCustomImageList;
begin
OldImage := TBitmap.Create;
with OldImage do
begin
Height := FHeight;
Width := FWidth;
end;
OldMask := TBitmap.Create;
with OldMask do
begin
Height := FHeight;
Width := FWidth;
end;
TempList := TCustomImageList.CreateSize(5, 5);
TempList.Assign(Self);
Clear;
if Index > TempList.Count then raise EInvalidOperation.CreateRes(SImageIndexError);
try
for I := 0 to Index - 1 do
begin
TempList.GetImages(I, OldImage, OldMask);
Add(OldImage, OldMask);
end;
if MaskColor <> -1 then
AddMasked(Image, MaskColor) else
Add(Image, Mask);
for I := Index to TempList.Count - 1 do
begin
TempList.GetImages(I, OldImage, OldMask);
Add(OldImage, OldMask);
end;
finally
TempList.Free;
OldImage.Free;
OldMask.Free;
end;
end;
procedure TCustomImageList.Insert(Index: Integer; Image, Mask: TBitmap);
begin
InsertImage(Index, Image, Mask, -1);
end;
procedure TCustomImageList.InsertMasked(Index: Integer; Image: TBitmap; MaskColor: TColor);
begin
InsertImage(Index, Image, nil, MaskColor);
end;
procedure TCustomImageList.InsertIcon(Index: Integer; Image: TIcon);
var
I: Integer;
TempList: TCustomImageList;
Icon: TIcon;
begin
Icon := TIcon.Create;
TempList := TCustomImageList.CreateSize(5, 5);
TempList.Assign(Self);
Clear;
if Index > TempList.Count then raise EInvalidOperation.CreateRes(SImageIndexError);
try
for I := 0 to Index - 1 do
begin
TempList.GetIcon(I, Icon);
AddIcon(Icon);
end;
AddIcon(Image);
for I := Index to TempList.Count - 1 do
begin
TempList.GetIcon(I, Icon);
AddIcon(Icon);
end;
finally
TempList.Free;
end;
end;
procedure TCustomImageList.Move(CurIndex, NewIndex: Integer);
var
Image, Mask: TBitmap;
begin
if CurIndex <> NewIndex then
begin
Image := TBitmap.Create;
with Image do
begin
Height := FHeight;
Width := FWidth;
end;
Mask := TBitmap.Create;
with Mask do
begin
Height := FHeight;
Width := FWidth;
end;
try
GetImages(CurIndex, Image, Mask);
Delete(CurIndex);
Insert(NewIndex, Image, Mask);
finally
Image.Free;
Mask.Free;
end;
end;
end;
procedure TCustomImageList.AddImages(Value: TCustomImageList);
begin
if Value <> nil then CopyImages(Value.Handle);
end;
procedure TCustomImageList.Assign(Source: TPersistent);
var
ImageList: TCustomImageList;
begin
if Source = nil then FreeHandle
else if Source is TCustomImageList then
begin
Clear;
ImageList := TCustomImageList(Source);
Masked := ImageList.Masked;
ImageType := ImageList.ImageType;
DrawingStyle := ImageList.DrawingStyle;
ShareImages := ImageList.ShareImages;
SetNewDimensions(ImageList.Handle);
if not HandleAllocated then HandleNeeded
else ImageList_SetIconSize(Handle, Width, Height);
BkColor := GetColor(ImageList_GetBkColor(ImageList.Handle));
BlendColor := ImageList.BlendColor;
AddImages(ImageList);
end
else inherited Assign(Source);
end;
procedure TCustomImageList.AssignTo(Dest: TPersistent);
var
ImageList: TCustomImageList;
begin
if Dest is TCustomImageList then
begin
ImageList := TCustomImageList(Dest);
ImageList.Masked := Masked;
ImageList.ImageType := ImageType;
ImageList.DrawingStyle := DrawingStyle;
ImageList.ShareImages := ShareImages;
ImageList.BlendColor := BlendColor;
with ImageList do
begin
Clear;
SetNewDimensions(Self.Handle);
if not HandleAllocated then HandleNeeded
else ImageList_SetIconSize(Handle, Width, Height);
BkColor := GetColor(ImageList_GetBkColor(Self.Handle));
AddImages(Self);
end;
end
else inherited AssignTo(Dest);
end;
procedure TCustomImageList.CheckImage(Image: TGraphic);
begin
if Image = nil then Exit;
with Image do
if (Height < FHeight) or (Width < FWidth) then
raise EInvalidOperation.CreateRes(SInvalidImageSize);
end;
procedure TCustomImageList.CombineDragCursor;
var
TempList: HImageList;
Point: TPoint;
begin
if DragCursor <> crNone then
begin
TempList := ImageList_Create(GetSystemMetrics(SM_CXCURSOR),
GetSystemMetrics(SM_CYCURSOR), ILC_MASK, 1, 1);
try
ImageList_AddIcon(TempList, Screen.Cursors[DragCursor]);
ImageList_AddIcon(TempList, Screen.Cursors[DragCursor]);
ImageList_SetDragCursorImage(TempList, 0, 0, 0);
ImageList_GetDragImage(nil, @Point);
ImageList_SetDragCursorImage(TempList, 1, Point.X, Point.Y);
finally
ImageList_Destroy(TempList);
end;
end;
end;
procedure TCustomImageList.SetDragCursor(Value: TCursor);
begin
if Value <> DragCursor then
begin
FDragCursor := Value;
if Dragging then CombineDragCursor;
end;
end;
function TCustomImageList.SetDragImage(Index, HotSpotX, HotSpotY: Integer): Boolean;
begin
if HandleAllocated then
begin
ImageList_BeginDrag(Handle, Index, HotSpotX, HotSpotY);
Result := True;
FDragging := Result;
end
else Result := False;
end;
function TCustomImageList.GetHotSpot: TPoint;
begin
Result := Point(0, 0);
if HandleAllocated and Dragging then
ImageList_GetDragImage(nil, @Result);
end;
function TCustomImageList.BeginDrag(Window: HWND; X, Y: Integer): Boolean;
begin
Result := False;
if HandleAllocated then
begin
if not Dragging then SetDragImage(0, 0, 0);
CombineDragCursor;
Result := DragLock(Window, X, Y);
if Result then ShowCursor(False);
end;
end;
function TCustomImageList.DragLock(Window: HWND; XPos, YPos: Integer): Boolean;
begin
Result := False;
if HandleAllocated and (Window <> FDragHandle) then
begin
DragUnlock;
FDragHandle := Window;
with ClientToWindow(FDragHandle, XPos, YPos) do
Result := ImageList_DragEnter(FDragHandle, X, Y);
end;
end;
procedure TCustomImageList.DragUnlock;
begin
if HandleAllocated and (FDragHandle <> 0) then
begin
ImageList_DragLeave(FDragHandle);
FDragHandle := 0;
end;
end;
function TCustomImageList.DragMove(X, Y: Integer): Boolean;
begin
if HandleAllocated then
with ClientToWindow(FDragHandle, X, Y) do
Result := ImageList_DragMove(X, Y)
else
Result := False;
end;
procedure TCustomImageList.ShowDragImage;
begin
if HandleAllocated then ImageList_DragShowNoLock(True);
end;
procedure TCustomImageList.HideDragImage;
begin
if HandleAllocated then ImageList_DragShowNoLock(False);
end;
function TCustomImageList.EndDrag: Boolean;
begin
if HandleAllocated and Dragging then
begin
DragUnlock;
Result := ImageList_EndDrag;
FDragging := False;
DragCursor := crNone;
ShowCursor(True);
end
else Result := False;
end;
function TCustomImageList.GetResource(ResType: TResType; Name: string;
Width: Integer; LoadFlags: TLoadResources; MaskColor: TColor): Boolean;
var
hImage: HImageList;
ResourceType: Integer;
Flags: Integer;
begin
case ResType of
rtBitmap: ResourceType := IMAGE_BITMAP;
rtIcon: ResourceType := IMAGE_ICON;
rtCursor: ResourceType := IMAGE_CURSOR;
end;
Flags := 0;
if lrDefaultColor in LoadFlags then Flags := Flags or LR_DEFAULTCOLOR;
if lrDefaultSize in LoadFlags then Flags := Flags or LR_DEFAULTSIZE;
if lrFromFile in LoadFlags then Flags := Flags or LR_LOADFROMFILE;
if lrMap3DColors in LoadFlags then Flags := Flags or LR_LOADMAP3DCOLORS;
if lrTransparent in LoadFlags then Flags := Flags or LR_LOADTRANSPARENT;
if lrMonoChrome in LoadFlags then Flags := Flags or LR_MONOCHROME;
hImage := ImageList_LoadImage(HInstance, PChar(Name), Width, AllocBy,
MaskColor, ResourceType, Flags);
if hImage <> 0 then
begin
CopyImages(hImage);
ImageList_Destroy(hImage);
Result := True;
end
else Result := False;
end;
function TCustomImageList.ResourceLoad(ResType: TResType; Name: string;
MaskColor: TColor): Boolean;
begin
Result := GetResource(ResType, Name, Width, [], MaskColor);
end;
function TCustomImageList.FileLoad(ResType: TResType; Name: string;
MaskColor: TColor): Boolean;
begin
Result := GetResource(ResType, Name, Width, [lrFromFile], MaskColor);
end;
procedure TCustomImageList.Change;
var
I: Integer;
begin
for I := 0 to FClients.Count - 1 do
TChangeLink(FClients[I]).Change;
if Assigned(FOnChange) then FOnChange(Self);
end;
procedure TCustomImageList.UnRegisterChanges(Value: TChangeLink);
var
I: Integer;
begin
for I := 0 to FClients.Count - 1 do
if FClients[I] = Value then
begin
Value.Sender := nil;
FClients.Delete(I);
Break;
end;
end;
procedure TCustomImageList.RegisterChanges(Value: TChangeLink);
begin
Value.Sender := Self;
FClients.Add(Value);
end;
procedure TCustomImageList.DefineProperties(Filer: TFiler);
begin
inherited DefineProperties(Filer);
Filer.DefineBinaryProperty('Bitmap', ReadData, WriteData, Count > 0);
end;
procedure TCustomImageList.ReadData(Stream: TStream);
var
FullImage, Image, FullMask, Mask: TBitmap;
I, J, Size, Pos, Count: Integer;
SrcRect: TRect;
begin
Stream.ReadBuffer(Size, SizeOf(Size));
Stream.ReadBuffer(Count, SizeOf(Count));
FullImage := TBitmap.Create;
try
Pos := Stream.Position;
FullImage.LoadFromStream(Stream);
Stream.Position := Pos + Size;
FullMask := TBitmap.Create;
try
FullMask.LoadFromStream(Stream);
Image := TBitmap.Create;
Image.Width := Width;
Image.Height := Height;
Mask := TBitmap.Create;
Mask.Width := Width;
Mask.Height := Height;
SrcRect := Rect(0, 0, Width, Height);
try
for J := 0 to (FullImage.Height div Height) - 1 do
begin
if Count = 0 then Break;
for I := 0 to (FullImage.Width div Width) - 1 do
begin
if Count = 0 then Break;
Image.Canvas.CopyRect(SrcRect, FullImage.Canvas,
Bounds(I * Width, J * Height, Width, Height));
Mask.Canvas.CopyRect(SrcRect, FullMask.Canvas,
Bounds(I * Width, J * Height, Width, Height));
Add(Image, Mask);
Dec(Count);
end;
end;
finally
Image.Free;
Mask.Free;
end;
finally
FullMask.Free;
end;
finally
FullImage.Free;
end;
end;
procedure TCustomImageList.WriteData(Stream: TStream);
var
Size, OldPos, Pos: Integer;
begin
with TBitmap.Create do
try
Handle := GetImageBitmap;
OldPos := Stream.Position;
Size := Count;
Stream.Write(Size, SizeOf(Size));
Stream.Write(Size, SizeOf(Size));
SaveToStream(Stream);
Size := Stream.Position - (OldPos + SizeOf(Size) * 2);
Handle := GetMaskBitmap;
SaveToStream(Stream);
Pos := Stream.Position;
Stream.Position := OldPos;
Stream.Write(Size, SizeOf(Size));
Stream.Position := Pos;
finally
Free;
end;
end;
{ TChangeLink }
destructor TChangeLink.Destroy;
begin
if Sender <> nil then Sender.UnRegisterChanges(Self);
inherited Destroy;
end;
procedure TChangeLink.Change;
begin
if Assigned(OnChange) then OnChange(Sender);
end;
{ Input Method Editor (IME) support code }
var
IMM32DLL: THandle = 0;
_WINNLSEnableIME: function(hwnd: HWnd; bool: Boolean): Boolean stdcall;
_ImmGetContext: function(hWnd: HWND): HIMC stdcall;
_ImmReleaseContext: function(hWnd: HWND; hImc: HIMC): Boolean stdcall;
_ImmGetConversionStatus: function(hImc: HIMC; var Conversion, Sentence: DWORD): Boolean stdcall;
_ImmSetConversionStatus: function(hImc: HIMC; Conversion, Sentence: DWORD): Boolean stdcall;
_ImmSetOpenStatus: function(hImc: HIMC; fOpen: Boolean): Boolean stdcall;
_ImmSetCompositionWindow: function(hImc: HIMC; lpCompForm: PCOMPOSITIONFORM): Boolean stdcall;
_ImmSetCompositionFont: function(hImc: HIMC; lpLogfont: PLOGFONTA): Boolean stdcall;
_ImmGetCompositionString: function(hImc: HIMC; dWord1: DWORD; lpBuf: pointer; dwBufLen: DWORD): Longint stdcall;
_ImmIsIME: function(hKl: HKL): Boolean stdcall;
_ImmNotifyIME: function(hImc: HIMC; dwAction, dwIndex, dwValue: DWORD): Boolean stdcall;
procedure InitIMM32;
var
UserHandle: THandle;
OldError: Longint;
begin
if not Syslocale.FarEast then Exit;
OldError := SetErrorMode(SEM_NOOPENFILEERRORBOX);
try
if not Assigned(_WINNLSEnableIME) then
begin
UserHandle := GetModuleHandle('USER32');
@_WINNLSEnableIME := GetProcAddress(UserHandle, 'WINNLSEnableIME');
end;
if IMM32DLL = 0 then
begin
IMM32DLL := LoadLibrary('IMM32.DLL');
if (IMM32DLL >= 0) and (IMM32DLL < 32) then IMM32DLL := 0;
if IMM32DLL <> 0 then
begin
@_ImmGetContext := GetProcAddress(IMM32DLL, 'ImmGetContext');
@_ImmReleaseContext := GetProcAddress(IMM32DLL, 'ImmReleaseContext');
@_ImmGetConversionStatus := GetProcAddress(IMM32DLL, 'ImmGetConversionStatus');
@_ImmSetConversionStatus := GetProcAddress(IMM32DLL, 'ImmSetConversionStatus');
@_ImmSetOpenStatus := GetProcAddress(IMM32DLL, 'ImmSetOpenStatus');
@_ImmSetCompositionWindow := GetProcAddress(IMM32DLL, 'ImmSetCompositionWindow');
@_ImmSetCompositionFont := GetProcAddress(IMM32DLL, 'ImmSetCompositionFontA');
@_ImmGetCompositionString := GetProcAddress(IMM32DLL, 'ImmGetCompositionStringA');
@_ImmIsIME := GetProcAddress(IMM32DLL, 'ImmIsIME');
@_ImmNotifyIME := GetProcAddress(IMM32DLL, 'ImmNotifyIME');
end;
end;
finally
SetErrorMode(OldError);
end;
end;
function Win32NLSEnableIME(Handle: HWnd; Enable: Boolean): Boolean;
begin
if Assigned(_WINNLSEnableIME) then
Result := _WINNLSEnableIME(Handle, Enable)
else
Result := False;
end;
procedure SetImeMode(Handle: HWnd; Mode: TImeMode);
const
ModeMap: array [imSAlpha..imHanguel] of Byte = // flags in use are all < 255
( { imSAlpha: } IME_CMODE_ALPHANUMERIC,
{ imAlpha: } IME_CMODE_ALPHANUMERIC or IME_CMODE_FULLSHAPE,
{ imHira: } IME_CMODE_NATIVE or IME_CMODE_FULLSHAPE,
{ imSKata: } IME_CMODE_NATIVE or IME_CMODE_KATAKANA,
{ imKata: } IME_CMODE_NATIVE or IME_CMODE_KATAKANA or IME_CMODE_FULLSHAPE,
{ imChinese:} IME_CMODE_NATIVE or IME_CMODE_FULLSHAPE,
{ imSHanguel} IME_CMODE_NATIVE,
{ imHanguel } IME_CMODE_NATIVE or IME_CMODE_FULLSHAPE );
var
IMC: HIMC;
Conv, Sent: DWORD;
begin
if (not SysLocale.FarEast) or (Mode = imDontCare) then Exit;
if Mode = imDisable then
begin
Win32NLSEnableIME(Handle, FALSE);
Exit;
end;
Win32NLSEnableIME(Handle, TRUE);
if IMM32DLL = 0 then Exit;
IMC := _ImmGetContext(Handle);
if IMC = 0 then Exit;
_ImmGetConversionStatus(IMC, Conv, Sent);
case Mode of
imClose: _ImmSetOpenStatus(IMC, FALSE);
imOpen : _ImmSetOpenStatus(IMC, TRUE);
else
_ImmSetOpenStatus(IMC, TRUE);
_ImmGetConversionStatus(IMC, Conv, Sent);
Conv := Conv and
(not(IME_CMODE_LANGUAGE or IME_CMODE_FULLSHAPE)) or ModeMap[Mode];
end;
_ImmSetConversionStatus(IMC, Conv, Sent);
_ImmReleaseContext(Handle, IMC);
end;
function Imm32GetContext(hWnd: HWND): HIMC;
begin
if IMM32DLL <> 0 then
Result := _ImmGetContext(hWnd)
else
Result := 0;
end;
function Imm32ReleaseContext(hWnd: HWND; hImc: HIMC): Boolean;
begin
if IMM32DLL <> 0 then
Result := _ImmReleaseContext(hWnd, hImc)
else
Result := False;
end;
function Imm32GetConversionStatus(hImc: HIMC; var Conversion, Sentence: DWORD): Boolean;
begin
if IMM32DLL <> 0 then
Result := _ImmGetConversionStatus(hImc, Conversion, Sentence)
else
Result := False;
end;
function Imm32SetConversionStatus(hImc: HIMC; Conversion, Sentence: DWORD): Boolean;
begin
if IMM32DLL <> 0 then
Result := _ImmSetConversionStatus(hImc, Conversion, Sentence)
else
Result := False;
end;
function Imm32SetOpenStatus(hImc: HIMC; fOpen: Boolean): Boolean;
begin
if IMM32DLL <> 0 then
Result := _ImmSetOpenStatus(hImc, fOpen)
else
Result := False;
end;
function Imm32SetCompositionWindow(hImc: HIMC; lpCompForm: PCOMPOSITIONFORM): Boolean;
begin
if IMM32DLL <> 0 then
Result := _ImmSetCompositionWindow(hImc, lpCompForm)
else
Result := False;
end;
function Imm32SetCompositionFont(hImc: HIMC; lpLogfont: PLOGFONTA): Boolean;
begin
if IMM32DLL <> 0 then
Result := _ImmSetCompositionFont(hImc, lpLogFont)
else
Result := False;
end;
function Imm32GetCompositionString(hImc: HIMC; dWord1: DWORD; lpBuf: pointer; dwBufLen: DWORD): Longint;
begin
if IMM32DLL <> 0 then
Result := _ImmGetCompositionString(hImc, dWord1, lpBuf, dwBufLen)
else
Result := 0;
end;
function Imm32IsIME(hKl: HKL): Boolean;
begin
if IMM32DLL <> 0 then
Result := _ImmIsIME(hKl)
else
Result := False;
end;
function Imm32NotifyIME(hImc: HIMC; dwAction, dwIndex, dwValue: DWORD): Boolean;
begin
if IMM32DLL <> 0 then
Result := _ImmNotifyIME(hImc, dwAction, dwIndex, dwValue)
else
Result := False;
end;
{ Initialization and cleanup }
procedure DoneControls; far;
begin
Application.Free;
Screen.Free;
GlobalDeleteAtom(ControlAtom);
GlobalDeleteAtom(WindowAtom);
if IMM32DLL <> 0 then FreeLibrary(IMM32DLL);
end;
procedure InitControls;
var
AtomText: array[0..31] of Char;
begin
WindowAtom := GlobalAddAtom(StrFmt(AtomText, 'Delphi%.8X',
[GetCurrentProcessID]));
ControlAtom := GlobalAddAtom(
StrFmt(AtomText, 'ControlOfs%.8X%.8X', [HInstance, GetCurrentThreadID]));
CanvasList := TList.Create;
CanvasList.Capacity := 4;
InitIMM32;
Screen := TScreen.Create(nil);
Application := TApplication.Create(nil);
InitCtl3D;
Application.ShowHint := True;
AddExitProc(DoneControls);
RegisterIntegerConsts(TypeInfo(TCursor), IdentToCursor, CursorToIdent);
end;
begin
NewStyleControls := Lo(GetVersion) >= 4;
InitGraphics;
InitControls;
end.