# JvExVCL

## What is it?

JvExVCL is an extension to VCL that makes it easier to port VCL components to CLX. The classes in JvExVCL map VCL messages to CLX compatible virtual or dynamic methods. The big advantage is that you can write controls for CLX and VCL without IFDEF'ing the code (too much).

## How to use it?

Just add the required JvExXXXX unit (where XXXX is the VCL unit or the VisualCLX unit without the leading "Q") to the uses clause of your control. For example use JvExStdCtrls instead of StdCtrls or QStdCtrls. Change the base class of the control to derive from TJvExXXXX (for example, derive from TJvExCustomControl instead of TCustomControl). Now you must replace any message handler with the corresponding virtual and dynamic method. By calling inherited in the first derived class the original message handler is executed (if nothing else is specified in the following tables).

Table of message to method mapping for TControl/TGraphicControl derived VCL classes.

> message |  | corresponding virtual/dynamic method
> CM_VISIBLECHANGED |  | procedure VisibleChanged;
> CM_ENABLEDCHANGED |  | procedure EnabledChanged;
> CM_FONTCHANGED |  | procedure FontChanged;
> CM_COLORCHANGED |  | procedure ColorChanged;
> CM_PARENTFONTCHANGED |  | procedure ParentFontChanged;
> CM_PARENTCOLORCHANGED |  | procedure ParentColorChanged;
> CM_PARENTSHOWHINTCHANGED |  | procedure ParentShowHintChanged;
> CM_TEXTCHANGED |  | procedure TextChanged;
> CM_HINTSHOW |  | function HintShow(var HintInfo: THintInfo): Boolean;
> CM_HITTEST |  | function HitTest(X, Y: Integer): Boolean;
> CM_MOUSEENTER |  | procedure MouseEnter(AControl: TControl);
> CM_MOUSELEAVE |  | procedure MouseLeave(AControl: TControl);
> CM_DIALOGCHAR |  | function WantKey(Key: Integer; Shift: TShiftState; const KeyText: WideString): Boolean;
> CM_FOCUSCHANGED |  | procedure FocusChanged(AControl: TWinControl);

> Extensions
> - Introduces a virtual SetAutoSize() function for Delphi 5.
> - Introduces published property AboutJVCL
> - Introduces protected property HintColor that is assigned to Application.HintColor if it is not clNone and the hint will be shown.
> - Introduces protected event OnParentColorChange
> - Introduces protected property MouseOver that is True when the mouse is over the control.
> - Introduces protected events OnMouseEnter and OnMouseLeave.

Table of message to method mapping for TWinControl/TCustomControl derived VCL classes.

The mappings above for TControl/TGraphicControl applies to these classes as well.

> message |  | corresponding virtual/dynamic method
> CM_CURSORCHANGED |  | procedure CursorChanged;
> CM_SHOWINGCHANGED |  | procedure ShowingChanged;
> CM_SHOWHINTCHANGED |  | procedure ShowHintChanged;
> CM_CONTROLLISTCHANGE |  | procedure ControlsListChanging(Control: TControl; Inserting: Boolean); procedure ControlsListChanged(Control: TControl; Inserting: Boolean); (ControlsListChanging is called before the actual change, ControlListChanged is called after the change)
> CM_CONTROLCHANGE |  | procedure ControlsListChanging(Control: TControl; Inserting: Boolean); procedure ControlsListChanged(Control: TControl; Inserting: Boolean); (ControlsListChanging is called before the actual change, ControlListChanged is called after the change)
> WM_ERASEBKGND |  | function DoEraseBackground(Canvas: TCanvas; Param: Integer): Boolean; (DoEraseBackground is protected by SaveDC/RestoreDC, Param is the LParam from the message)
> WM_GETDLGCODE |  | procedure GetDlgCode(var Code: TDlgCodes); `TDlgCode = ( dcWantAllKeys, dcWantArrows, dcWantChars, dcButton, dcHasSetSel, dcWantTab, dcNative { if dcNative is in the set the native functions are used and DoGetDlgCode is ignored }
> );
> TDlgCodes = set of TDlgCode;`
> WM_SETFOCUS |  | procedure FocusSet(FocusedWnd: HWND);
> WM_KILLFOCUS |  | procedure FocusKilled(FocusedWnd: HWND);
> WM_SIZE |  | procedure BoundsChanged; (original WM_SIZE is called before BoundsChanged)

> Extensions
> - Introduces virtual method SetParentBackground() and a ParentBackground property for Delphi/BCB 5 and 6 if JVCLThemesEnabled is defined.

Table of message blocking for TCustomEdit/TCustomMemo derived VCL classes.

> message |  | blocked if
> WM_PASTE |  | not (caPaste in ClipboardCommand)
> WM_COPY |  | not (caCopy in ClipboardCommand)
> WM_CUT |  | not (caCut in ClipboardCommand)
> WM_UNDO |  | not (caUndo in ClipboardCommand)
> WM_CLEAR |  | not (caClear in ClipboardCommand)

> Extensions
> - Introduces property ClipboardCommands: TJvClipboardCommands for Clipboard action restrictions.

## How does it work?

The JvExVCL changes the route a message takes. It overrides the WndProc of the control and redirects some message to virtual or dynamic methods of the control. These methods can be overriden by user code. In order to allow the user-control to invoke the inherited behaviour all virtual and dynamic (message) methods call the inherited WndProc. This means that a simple "inherited" in the overriden method invokes the original message handler.

Example:
SendMessage(MyCtrl.Handle, CM_VISIBLECHANGED, 0, 0);

> TMyCtrl.WndProc()

> > TMyCtrl.VisibleChanged() // overriden method

> > > inherited VisibleChanged;

> > > > TJvExControl.VisibleChanged()

> > > > > TControl.WndProc(CM_VISIBLECHANGED)

> > > > > > TControl.CMVisibleChanged()

## How to extend the JvExVCL (developer)?

JvExVCL uses macros that are preprocessed by the Delphi Preprocessor (JVCL 3 contains a precompiled dpp32.exe). These macros allow easier modification because you only need to change one file and all classes derived from it will use the new features. This also means that you should not modify the generated JvExVCL units directly since they will be overwritten the next time the preprocessor is used.

The JvExVCL sources (un-preprocessed files) are in $(JVCL)\devtools\JvExVCL\src