| 1 | 
 | 
|---|
| 2 | {*****************************************************************************}
 | 
|---|
| 3 | {                                                                             }
 | 
|---|
| 4 | {    Tnt Delphi Unicode Controls                                              }
 | 
|---|
| 5 | {      http://www.tntware.com/delphicontrols/unicode/                         }
 | 
|---|
| 6 | {        Version: 2.3.0                                                       }
 | 
|---|
| 7 | {                                                                             }
 | 
|---|
| 8 | {    Copyright (c) 2002-2007, Troy Wolbrink (troy.wolbrink@tntware.com)       }
 | 
|---|
| 9 | {                                                                             }
 | 
|---|
| 10 | {*****************************************************************************}
 | 
|---|
| 11 | 
 | 
|---|
| 12 | unit TntControls;
 | 
|---|
| 13 | 
 | 
|---|
| 14 | {$INCLUDE TntCompilers.inc}
 | 
|---|
| 15 | 
 | 
|---|
| 16 | {
 | 
|---|
| 17 |   Windows NT provides support for native Unicode windows.  To add Unicode support to a
 | 
|---|
| 18 |     TWinControl descendant, override CreateWindowHandle() and call CreateUnicodeHandle().
 | 
|---|
| 19 | 
 | 
|---|
| 20 |   One major reason this works is because the VCL only uses the ANSI version of
 | 
|---|
| 21 |     SendMessage() -- SendMessageA().  If you call SendMessageA() on a UNICODE
 | 
|---|
| 22 |     window, Windows deals with the ANSI/UNICODE conversion automatically.  So
 | 
|---|
| 23 |     for example, if the VCL sends WM_SETTEXT to a window using SendMessageA,
 | 
|---|
| 24 |     Windows actually *expects* a PAnsiChar even if the target window is a UNICODE
 | 
|---|
| 25 |     window.  So caling SendMessageA with PChars causes no problems.
 | 
|---|
| 26 | 
 | 
|---|
| 27 |   A problem in the VCL has to do with the TControl.Perform() method. Perform()
 | 
|---|
| 28 |     calls the window procedure directly and assumes an ANSI window.  This is a
 | 
|---|
| 29 |     problem if, for example, the VCL calls Perform(WM_SETTEXT, ...) passing in a
 | 
|---|
| 30 |     PAnsiChar which eventually gets passed downto DefWindowProcW() which expects a PWideChar.
 | 
|---|
| 31 | 
 | 
|---|
| 32 |   This is the reason for SubClassUnicodeControl().  This procedure will subclass the
 | 
|---|
| 33 |     Windows WndProc, and the TWinControl.WindowProc pointer.  It will determine if the
 | 
|---|
| 34 |     message came from Windows or if the WindowProc was called directly.  It will then
 | 
|---|
| 35 |     call SendMessageA() for Windows to perform proper conversion on certain text messages.
 | 
|---|
| 36 | 
 | 
|---|
| 37 |   Another problem has to do with TWinControl.DoKeyPress().  It is called from the WM_CHAR
 | 
|---|
| 38 |     message.  It casts the WideChar to an AnsiChar, and sends the resulting character to
 | 
|---|
| 39 |     DefWindowProc.  In order to avoid this, the DefWindowProc is subclassed as well.  WindowProc
 | 
|---|
| 40 |     will make a WM_CHAR message safe for ANSI handling code by converting the char code to
 | 
|---|
| 41 |     #FF before passing it on.  It stores the original WideChar in the .Unused field of TWMChar.
 | 
|---|
| 42 |     The code #FF is converted back to the WideChar before passing onto DefWindowProc.
 | 
|---|
| 43 | }
 | 
|---|
| 44 | 
 | 
|---|
| 45 | {
 | 
|---|
| 46 |   Things to consider when designing new controls:
 | 
|---|
| 47 |     1)  Check that a WideString Hint property is published.
 | 
|---|
| 48 |     2)  If descending from TWinControl, override CreateWindowHandle().
 | 
|---|
| 49 |     3)  If not descending from TWinControl, handle CM_HINTSHOW message.
 | 
|---|
| 50 |     4)  Check to make sure that CN_CHAR, CN_SYSCHAR and CM_DIALOGCHAR are handled properly.
 | 
|---|
| 51 |     5)  If descending from TWinControl, verify Unicode chars are preserved after RecreateWnd.
 | 
|---|
| 52 |     6)  Consider using storage specifiers for Hint and Caption properties.
 | 
|---|
| 53 |     7)  If any class could possibly have published WideString properties,
 | 
|---|
| 54 |           override DefineProperties and call TntPersistent_AfterInherited_DefineProperties.
 | 
|---|
| 55 |     8)  Check if TTntThemeManager needs to be updated.
 | 
|---|
| 56 |     9)  Override GetActionLinkClass() and ActionChange().
 | 
|---|
| 57 |     10) If class updates Application.Hint then update TntApplication.Hint instead.
 | 
|---|
| 58 | }
 | 
|---|
| 59 | 
 | 
|---|
| 60 | interface
 | 
|---|
| 61 | 
 | 
|---|
| 62 | { TODO: Unicode enable .OnKeyPress event }
 | 
|---|
| 63 | 
 | 
|---|
| 64 | uses
 | 
|---|
| 65 |   Classes, Windows, Messages, Controls, Menus;
 | 
|---|
| 66 | 
 | 
|---|
| 67 | 
 | 
|---|
| 68 | {TNT-WARN TCaption}
 | 
|---|
| 69 | type TWideCaption = type WideString;
 | 
|---|
| 70 | 
 | 
|---|
| 71 | // caption/text management
 | 
|---|
| 72 | function TntControl_IsCaptionStored(Control: TControl): Boolean;
 | 
|---|
| 73 | function TntControl_GetStoredText(Control: TControl; const Default: WideString): WideString;
 | 
|---|
| 74 | procedure TntControl_SetStoredText(Control: TControl; const Value: WideString);
 | 
|---|
| 75 | function TntControl_GetText(Control: TControl): WideString;
 | 
|---|
| 76 | procedure TntControl_SetText(Control: TControl; const Text: WideString);
 | 
|---|
| 77 | 
 | 
|---|
| 78 | // hint management
 | 
|---|
| 79 | function TntControl_IsHintStored(Control: TControl): Boolean;
 | 
|---|
| 80 | function TntControl_GetHint(Control: TControl): WideString;
 | 
|---|
| 81 | procedure TntControl_SetHint(Control: TControl; const Value: WideString);
 | 
|---|
| 82 | 
 | 
|---|
| 83 | function WideGetHint(Control: TControl): WideString;
 | 
|---|
| 84 | function WideGetShortHint(const Hint: WideString): WideString;
 | 
|---|
| 85 | function WideGetLongHint(const Hint: WideString): WideString;
 | 
|---|
| 86 | procedure ProcessCMHintShowMsg(var Message: TMessage);
 | 
|---|
| 87 | 
 | 
|---|
| 88 | type
 | 
|---|
| 89 |   TTntCustomHintWindow = class(THintWindow)
 | 
|---|
| 90 |   private
 | 
|---|
| 91 |     FActivating: Boolean;
 | 
|---|
| 92 |     FBlockPaint: Boolean;
 | 
|---|
| 93 |     function GetCaption: TWideCaption;
 | 
|---|
| 94 |     procedure SetCaption(const Value: TWideCaption);
 | 
|---|
| 95 |     procedure CMTextChanged(var Message: TMessage); message CM_TEXTCHANGED;
 | 
|---|
| 96 |   protected
 | 
|---|
| 97 |     procedure CreateWindowHandle(const Params: TCreateParams); override;
 | 
|---|
| 98 | {$IFNDEF COMPILER_7_UP}
 | 
|---|
| 99 |     procedure CreateParams(var Params: TCreateParams); override;
 | 
|---|
| 100 | {$ENDIF}
 | 
|---|
| 101 |     procedure Paint; override;
 | 
|---|
| 102 |   public
 | 
|---|
| 103 |     procedure ActivateHint(Rect: TRect; const AHint: AnsiString); override;
 | 
|---|
| 104 |     procedure ActivateHintData(Rect: TRect; const AHint: AnsiString; AData: Pointer); override;
 | 
|---|
| 105 |     function CalcHintRect(MaxWidth: Integer; const AHint: AnsiString; AData: Pointer): TRect; override;
 | 
|---|
| 106 |     property Caption: TWideCaption read GetCaption write SetCaption;
 | 
|---|
| 107 |   end;
 | 
|---|
| 108 | 
 | 
|---|
| 109 |   TTntHintWindow = class(TTntCustomHintWindow)
 | 
|---|
| 110 |   public
 | 
|---|
| 111 |     procedure ActivateHint(Rect: TRect; const AHint: WideString); reintroduce;
 | 
|---|
| 112 |     procedure ActivateHintData(Rect: TRect; const AHint: WideString; AData: Pointer); reintroduce;
 | 
|---|
| 113 |     function CalcHintRect(MaxWidth: Integer; const AHint: WideString; AData: Pointer): TRect; reintroduce;
 | 
|---|
| 114 |   end;
 | 
|---|
| 115 | 
 | 
|---|
| 116 | // text/char message
 | 
|---|
| 117 | function IsTextMessage(Msg: UINT): Boolean;
 | 
|---|
| 118 | procedure MakeWMCharMsgSafeForAnsi(var Message: TMessage);
 | 
|---|
| 119 | procedure RestoreWMCharMsg(var Message: TMessage);
 | 
|---|
| 120 | function GetWideCharFromWMCharMsg(Message: TWMChar): WideChar;
 | 
|---|
| 121 | procedure SetWideCharForWMCharMsg(var Message: TWMChar; Ch: WideChar);
 | 
|---|
| 122 | 
 | 
|---|
| 123 | // register/create window
 | 
|---|
| 124 | procedure SubClassUnicodeControl(Control: TWinControl; Params_Caption: PAnsiChar; IDEWindow: Boolean = False);
 | 
|---|
| 125 | procedure RegisterUnicodeClass(Params: TCreateParams; out WideWinClassName: WideString; IDEWindow: Boolean = False);
 | 
|---|
| 126 | procedure CreateUnicodeHandle(Control: TWinControl; const Params: TCreateParams;
 | 
|---|
| 127 |                                         const SubClass: WideString; IDEWindow: Boolean = False);
 | 
|---|
| 128 | procedure ReCreateUnicodeWnd(Control: TWinControl; Subclass: WideString; IDEWindow: Boolean = False);
 | 
|---|
| 129 | 
 | 
|---|
| 130 | type
 | 
|---|
| 131 |   IWideCustomListControl = interface
 | 
|---|
| 132 |     ['{C1801F41-51E9-4DB5-8DB8-58AC86698C2E}']
 | 
|---|
| 133 |     procedure AddItem(const Item: WideString; AObject: TObject);
 | 
|---|
| 134 |   end;
 | 
|---|
| 135 | 
 | 
|---|
| 136 | procedure WideListControl_AddItem(Control: TCustomListControl; const Item: WideString; AObject: TObject);
 | 
|---|
| 137 | 
 | 
|---|
| 138 | var
 | 
|---|
| 139 |   _IsShellProgramming: Boolean = False;
 | 
|---|
| 140 | 
 | 
|---|
| 141 | var
 | 
|---|
| 142 |   TNT_WM_DESTROY: Cardinal;
 | 
|---|
| 143 | 
 | 
|---|
| 144 | implementation
 | 
|---|
| 145 | 
 | 
|---|
| 146 | uses
 | 
|---|
| 147 |   ActnList, Forms, SysUtils, Contnrs, 
 | 
|---|
| 148 |   TntGraphics, TntWindows, TntClasses, TntMenus, TntSysUtils;
 | 
|---|
| 149 | 
 | 
|---|
| 150 | type
 | 
|---|
| 151 |   TAccessControl = class(TControl);
 | 
|---|
| 152 |   TAccessWinControl = class(TWinControl);
 | 
|---|
| 153 |   TAccessControlActionLink = class(TControlActionLink{TNT-ALLOW TControlActionLink});
 | 
|---|
| 154 | 
 | 
|---|
| 155 | //----------------------------------------------- WIDE CAPTION HOLDERS --------
 | 
|---|
| 156 | 
 | 
|---|
| 157 | { TWideControlHelper }
 | 
|---|
| 158 | 
 | 
|---|
| 159 | var
 | 
|---|
| 160 |   WideControlHelpers: TComponentList = nil;
 | 
|---|
| 161 | 
 | 
|---|
| 162 | type
 | 
|---|
| 163 |   TWideControlHelper = class(TWideComponentHelper)
 | 
|---|
| 164 |   private
 | 
|---|
| 165 |     FControl: TControl;
 | 
|---|
| 166 |     FWideCaption: WideString;
 | 
|---|
| 167 |     FWideHint: WideString;
 | 
|---|
| 168 |     procedure SetAnsiText(const Value: AnsiString);
 | 
|---|
| 169 |     procedure SetAnsiHint(const Value: AnsiString);
 | 
|---|
| 170 |   public
 | 
|---|
| 171 |     constructor Create(AOwner: TControl); reintroduce;
 | 
|---|
| 172 |     property WideCaption: WideString read FWideCaption;
 | 
|---|
| 173 |     property WideHint: WideString read FWideHint;
 | 
|---|
| 174 |   end;
 | 
|---|
| 175 | 
 | 
|---|
| 176 | constructor TWideControlHelper.Create(AOwner: TControl);
 | 
|---|
| 177 | begin
 | 
|---|
| 178 |   inherited CreateHelper(AOwner, WideControlHelpers);
 | 
|---|
| 179 |   FControl := AOwner;
 | 
|---|
| 180 | end;
 | 
|---|
| 181 | 
 | 
|---|
| 182 | procedure TWideControlHelper.SetAnsiText(const Value: AnsiString);
 | 
|---|
| 183 | begin
 | 
|---|
| 184 |   TAccessControl(FControl).Text := Value;
 | 
|---|
| 185 | end;
 | 
|---|
| 186 | 
 | 
|---|
| 187 | procedure TWideControlHelper.SetAnsiHint(const Value: AnsiString);
 | 
|---|
| 188 | begin
 | 
|---|
| 189 |   FControl.Hint := Value;
 | 
|---|
| 190 | end;
 | 
|---|
| 191 | 
 | 
|---|
| 192 | function FindWideControlHelper(Control: TControl; CreateIfNotFound: Boolean = True): TWideControlHelper;
 | 
|---|
| 193 | begin
 | 
|---|
| 194 |   Result := TWideControlHelper(FindWideComponentHelper(WideControlHelpers, Control));
 | 
|---|
| 195 |   if (Result = nil) and CreateIfNotFound then
 | 
|---|
| 196 |         Result := TWideControlHelper.Create(Control);
 | 
|---|
| 197 | end;
 | 
|---|
| 198 | 
 | 
|---|
| 199 | //----------------------------------------------- GET/SET WINDOW CAPTION/HINT -------------
 | 
|---|
| 200 | 
 | 
|---|
| 201 | function TntControl_IsCaptionStored(Control: TControl): Boolean;
 | 
|---|
| 202 | begin
 | 
|---|
| 203 |   with TAccessControl(Control) do
 | 
|---|
| 204 |     Result := (ActionLink = nil) or not TAccessControlActionLink(ActionLink).IsCaptionLinked;
 | 
|---|
| 205 | end;
 | 
|---|
| 206 | 
 | 
|---|
| 207 | function TntControl_GetStoredText(Control: TControl; const Default: WideString): WideString;
 | 
|---|
| 208 | var
 | 
|---|
| 209 |   WideControlHelper: TWideControlHelper;
 | 
|---|
| 210 | begin
 | 
|---|
| 211 |   WideControlHelper := FindWideControlHelper(Control, False);
 | 
|---|
| 212 |   if WideControlHelper <> nil then
 | 
|---|
| 213 |     Result := WideControlHelper.WideCaption
 | 
|---|
| 214 |   else
 | 
|---|
| 215 |     Result := Default;
 | 
|---|
| 216 | end;
 | 
|---|
| 217 | 
 | 
|---|
| 218 | procedure TntControl_SetStoredText(Control: TControl; const Value: WideString);
 | 
|---|
| 219 | begin
 | 
|---|
| 220 |   FindWideControlHelper(Control).FWideCaption := Value;
 | 
|---|
| 221 |   TAccessControl(Control).Text := Value;
 | 
|---|
| 222 | end;
 | 
|---|
| 223 | 
 | 
|---|
| 224 | function TntControl_GetText(Control: TControl): WideString;
 | 
|---|
| 225 | var
 | 
|---|
| 226 |   WideControlHelper: TWideControlHelper;
 | 
|---|
| 227 | begin
 | 
|---|
| 228 |   if (not Win32PlatformIsUnicode)
 | 
|---|
| 229 |   or ((Control is TWinControl) and TWinControl(Control).HandleAllocated and (not IsWindowUnicode(TWinControl(Control).Handle))) then
 | 
|---|
| 230 |     // Win9x / non-unicode handle
 | 
|---|
| 231 |     Result := TAccessControl(Control).Text
 | 
|---|
| 232 |   else if (not (Control is TWinControl)) then begin
 | 
|---|
| 233 |     // non-windowed TControl
 | 
|---|
| 234 |     WideControlHelper := FindWideControlHelper(Control, False);
 | 
|---|
| 235 |     if WideControlHelper = nil then
 | 
|---|
| 236 |       Result := TAccessControl(Control).Text
 | 
|---|
| 237 |     else
 | 
|---|
| 238 |       Result := GetSyncedWideString(WideControlHelper.FWideCaption, TAccessControl(Control).Text);
 | 
|---|
| 239 |   end else if (not TWinControl(Control).HandleAllocated) then begin
 | 
|---|
| 240 |     // NO HANDLE
 | 
|---|
| 241 |     Result := TntControl_GetStoredText(Control, TAccessControl(Control).Text)
 | 
|---|
| 242 |   end else begin
 | 
|---|
| 243 |     // UNICODE & HANDLE
 | 
|---|
| 244 |     SetLength(Result, GetWindowTextLengthW(TWinControl(Control).Handle) + 1);
 | 
|---|
| 245 |     GetWindowTextW(TWinControl(Control).Handle, PWideChar(Result), Length(Result));
 | 
|---|
| 246 |     SetLength(Result, Length(Result) - 1);
 | 
|---|
| 247 |   end;
 | 
|---|
| 248 | end;
 | 
|---|
| 249 | 
 | 
|---|
| 250 | procedure TntControl_SetText(Control: TControl; const Text: WideString);
 | 
|---|
| 251 | begin
 | 
|---|
| 252 |   if (not Win32PlatformIsUnicode)
 | 
|---|
| 253 |   or ((Control is TWinControl) and TWinControl(Control).HandleAllocated and (not IsWindowUnicode(TWinControl(Control).Handle))) then
 | 
|---|
| 254 |     // Win9x / non-unicode handle
 | 
|---|
| 255 |     TAccessControl(Control).Text := Text
 | 
|---|
| 256 |   else if (not (Control is TWinControl)) then begin
 | 
|---|
| 257 |     // non-windowed TControl
 | 
|---|
| 258 |     with FindWideControlHelper(Control) do
 | 
|---|
| 259 |       SetSyncedWideString(Text, FWideCaption, TAccessControl(Control).Text, SetAnsiText)
 | 
|---|
| 260 |   end else if (not TWinControl(Control).HandleAllocated) then begin
 | 
|---|
| 261 |     // NO HANDLE
 | 
|---|
| 262 |     TntControl_SetStoredText(Control, Text);
 | 
|---|
| 263 |   end else if TntControl_GetText(Control) <> Text then begin
 | 
|---|
| 264 |     // UNICODE & HANDLE
 | 
|---|
| 265 |     Tnt_SetWindowTextW(TWinControl(Control).Handle, PWideChar(Text));
 | 
|---|
| 266 |     Control.Perform(CM_TEXTCHANGED, 0, 0);
 | 
|---|
| 267 |   end;
 | 
|---|
| 268 | end;
 | 
|---|
| 269 | 
 | 
|---|
| 270 | // hint management -----------------------------------------------------------------------
 | 
|---|
| 271 | 
 | 
|---|
| 272 | function TntControl_IsHintStored(Control: TControl): Boolean;
 | 
|---|
| 273 | begin
 | 
|---|
| 274 |   with TAccessControl(Control) do
 | 
|---|
| 275 |     Result := (ActionLink = nil) or not TAccessControlActionLink(ActionLink).IsHintLinked;
 | 
|---|
| 276 | end;
 | 
|---|
| 277 | 
 | 
|---|
| 278 | function TntControl_GetHint(Control: TControl): WideString;
 | 
|---|
| 279 | var
 | 
|---|
| 280 |   WideControlHelper: TWideControlHelper;
 | 
|---|
| 281 | begin
 | 
|---|
| 282 |   if (not Win32PlatformIsUnicode) then
 | 
|---|
| 283 |     Result := Control.Hint
 | 
|---|
| 284 |   else begin
 | 
|---|
| 285 |     WideControlHelper := FindWideControlHelper(Control, False);
 | 
|---|
| 286 |     if WideControlHelper <> nil then
 | 
|---|
| 287 |       Result := GetSyncedWideString(WideControlHelper.FWideHint, Control.Hint)
 | 
|---|
| 288 |     else
 | 
|---|
| 289 |       Result := Control.Hint;
 | 
|---|
| 290 |   end;
 | 
|---|
| 291 | end;
 | 
|---|
| 292 | 
 | 
|---|
| 293 | procedure TntControl_SetHint(Control: TControl; const Value: WideString);
 | 
|---|
| 294 | begin
 | 
|---|
| 295 |   if (not Win32PlatformIsUnicode) then
 | 
|---|
| 296 |     Control.Hint := Value
 | 
|---|
| 297 |   else
 | 
|---|
| 298 |     with FindWideControlHelper(Control) do
 | 
|---|
| 299 |       SetSyncedWideString(Value, FWideHint, Control.Hint, SetAnsiHint);
 | 
|---|
| 300 | end;
 | 
|---|
| 301 | 
 | 
|---|
| 302 | function WideGetHint(Control: TControl): WideString;
 | 
|---|
| 303 | begin
 | 
|---|
| 304 |   while Control <> nil do
 | 
|---|
| 305 |     if TntControl_GetHint(Control) = '' then
 | 
|---|
| 306 |       Control := Control.Parent
 | 
|---|
| 307 |     else
 | 
|---|
| 308 |     begin
 | 
|---|
| 309 |       Result := TntControl_GetHint(Control);
 | 
|---|
| 310 |       Exit;
 | 
|---|
| 311 |     end;
 | 
|---|
| 312 |   Result := '';
 | 
|---|
| 313 | end;
 | 
|---|
| 314 | 
 | 
|---|
| 315 | function WideGetShortHint(const Hint: WideString): WideString;
 | 
|---|
| 316 | var
 | 
|---|
| 317 |   I: Integer;
 | 
|---|
| 318 | begin
 | 
|---|
| 319 |   I := Pos('|', Hint);
 | 
|---|
| 320 |   if I = 0 then
 | 
|---|
| 321 |     Result := Hint else
 | 
|---|
| 322 |     Result := Copy(Hint, 1, I - 1);
 | 
|---|
| 323 | end;
 | 
|---|
| 324 | 
 | 
|---|
| 325 | function WideGetLongHint(const Hint: WideString): WideString;
 | 
|---|
| 326 | var
 | 
|---|
| 327 |   I: Integer;
 | 
|---|
| 328 | begin
 | 
|---|
| 329 |   I := Pos('|', Hint);
 | 
|---|
| 330 |   if I = 0 then
 | 
|---|
| 331 |     Result := Hint else
 | 
|---|
| 332 |     Result := Copy(Hint, I + 1, Maxint);
 | 
|---|
| 333 | end;
 | 
|---|
| 334 | 
 | 
|---|
| 335 | //----------------------------------------------------------------------------------------
 | 
|---|
| 336 | 
 | 
|---|
| 337 | var UnicodeCreationControl: TWinControl = nil;
 | 
|---|
| 338 | 
 | 
|---|
| 339 | function IsUnicodeCreationControl(Handle: HWND): Boolean;
 | 
|---|
| 340 | begin
 | 
|---|
| 341 |   Result := (UnicodeCreationControl <> nil)
 | 
|---|
| 342 |         and (UnicodeCreationControl.HandleAllocated)
 | 
|---|
| 343 |         and (UnicodeCreationControl.Handle = Handle);
 | 
|---|
| 344 | end;
 | 
|---|
| 345 | 
 | 
|---|
| 346 | function WMNotifyFormatResult(FromHandle: HWND): Integer;
 | 
|---|
| 347 | begin
 | 
|---|
| 348 |   if Win32PlatformIsUnicode
 | 
|---|
| 349 |   and (IsWindowUnicode(FromHandle) or IsUnicodeCreationControl(FromHandle)) then
 | 
|---|
| 350 |     Result := NFR_UNICODE
 | 
|---|
| 351 |   else
 | 
|---|
| 352 |     Result := NFR_ANSI;
 | 
|---|
| 353 | end;
 | 
|---|
| 354 | 
 | 
|---|
| 355 | function IsTextMessage(Msg: UINT): Boolean;
 | 
|---|
| 356 | begin
 | 
|---|
| 357 |   // WM_CHAR is omitted because of the special handling it receives
 | 
|---|
| 358 |   Result := (Msg = WM_SETTEXT)
 | 
|---|
| 359 |          or (Msg = WM_GETTEXT)
 | 
|---|
| 360 |          or (Msg = WM_GETTEXTLENGTH);
 | 
|---|
| 361 | end;
 | 
|---|
| 362 | 
 | 
|---|
| 363 | const
 | 
|---|
| 364 |   ANSI_UNICODE_HOLDER = $FF;
 | 
|---|
| 365 | 
 | 
|---|
| 366 | procedure MakeWMCharMsgSafeForAnsi(var Message: TMessage);
 | 
|---|
| 367 | begin
 | 
|---|
| 368 |   with TWMChar(Message) do begin
 | 
|---|
| 369 |     Assert(Msg = WM_CHAR);
 | 
|---|
| 370 |     if not _IsShellProgramming then
 | 
|---|
| 371 |       Assert(Unused = 0)
 | 
|---|
| 372 |     else begin
 | 
|---|
| 373 |       Assert((Unused = 0) or (CharCode <= Word(High(AnsiChar))));
 | 
|---|
| 374 |       // When a Unicode control is embedded under non-Delphi Unicode
 | 
|---|
| 375 |       //   window something strange happens
 | 
|---|
| 376 |       if (Unused <> 0) then begin
 | 
|---|
| 377 |         CharCode := (Unused shl 8) or CharCode;
 | 
|---|
| 378 |       end;
 | 
|---|
| 379 |     end;
 | 
|---|
| 380 |     if (CharCode > Word(High(AnsiChar))) then begin
 | 
|---|
| 381 |       Unused := CharCode;
 | 
|---|
| 382 |       CharCode := ANSI_UNICODE_HOLDER;
 | 
|---|
| 383 |     end;
 | 
|---|
| 384 |   end;
 | 
|---|
| 385 | end;
 | 
|---|
| 386 | 
 | 
|---|
| 387 | procedure RestoreWMCharMsg(var Message: TMessage);
 | 
|---|
| 388 | begin
 | 
|---|
| 389 |   with TWMChar(Message) do begin
 | 
|---|
| 390 |     Assert(Message.Msg = WM_CHAR);
 | 
|---|
| 391 |     if (Unused > 0)
 | 
|---|
| 392 |     and (CharCode = ANSI_UNICODE_HOLDER) then
 | 
|---|
| 393 |       CharCode := Unused;
 | 
|---|
| 394 |     Unused := 0;
 | 
|---|
| 395 |   end;
 | 
|---|
| 396 | end;
 | 
|---|
| 397 | 
 | 
|---|
| 398 | function GetWideCharFromWMCharMsg(Message: TWMChar): WideChar;
 | 
|---|
| 399 | begin
 | 
|---|
| 400 |   if (Message.CharCode = ANSI_UNICODE_HOLDER)
 | 
|---|
| 401 |   and (Message.Unused <> 0) then
 | 
|---|
| 402 |     Result := WideChar(Message.Unused)
 | 
|---|
| 403 |   else
 | 
|---|
| 404 |     Result := WideChar(Message.CharCode);
 | 
|---|
| 405 | end;
 | 
|---|
| 406 | 
 | 
|---|
| 407 | procedure SetWideCharForWMCharMsg(var Message: TWMChar; Ch: WideChar);
 | 
|---|
| 408 | begin
 | 
|---|
| 409 |   Message.CharCode := Word(Ch);
 | 
|---|
| 410 |   Message.Unused := 0;
 | 
|---|
| 411 |   MakeWMCharMsgSafeForAnsi(TMessage(Message));
 | 
|---|
| 412 | end;
 | 
|---|
| 413 | 
 | 
|---|
| 414 | //-----------------------------------------------------------------------------------
 | 
|---|
| 415 | type
 | 
|---|
| 416 |   TWinControlTrap = class(TComponent)
 | 
|---|
| 417 |   private
 | 
|---|
| 418 |     WinControl_ObjectInstance: Pointer;
 | 
|---|
| 419 |     ObjectInstance: Pointer;
 | 
|---|
| 420 |     DefObjectInstance: Pointer;
 | 
|---|
| 421 |     function IsInSubclassChain(Control: TWinControl): Boolean;
 | 
|---|
| 422 |     procedure SubClassWindowProc;
 | 
|---|
| 423 |   private
 | 
|---|
| 424 |     FControl: TAccessWinControl;
 | 
|---|
| 425 |     Handle: THandle;
 | 
|---|
| 426 |     PrevWin32Proc: Pointer;
 | 
|---|
| 427 |     PrevDefWin32Proc: Pointer;
 | 
|---|
| 428 |     PrevWindowProc: TWndMethod;
 | 
|---|
| 429 |   private
 | 
|---|
| 430 |     LastWin32Msg: UINT;
 | 
|---|
| 431 |     Win32ProcLevel: Integer;
 | 
|---|
| 432 |     IDEWindow: Boolean;
 | 
|---|
| 433 |     DestroyTrap: Boolean;
 | 
|---|
| 434 |     TestForNull: Boolean;
 | 
|---|
| 435 |     FoundNull: Boolean;
 | 
|---|
| 436 |     {$IFDEF TNT_VERIFY_WINDOWPROC}
 | 
|---|
| 437 |     LastVerifiedWindowProc: TWndMethod;
 | 
|---|
| 438 |     {$ENDIF}
 | 
|---|
| 439 |     procedure Win32Proc(var Message: TMessage);
 | 
|---|
| 440 |     procedure DefWin32Proc(var Message: TMessage);
 | 
|---|
| 441 |     procedure WindowProc(var Message: TMessage);
 | 
|---|
| 442 |   private
 | 
|---|
| 443 |     procedure SubClassControl(Params_Caption: PAnsiChar);
 | 
|---|
| 444 |     procedure UnSubClassUnicodeControl;
 | 
|---|
| 445 |   protected
 | 
|---|
| 446 |     procedure Notification(AComponent: TComponent; Operation: TOperation); override;
 | 
|---|
| 447 |   public
 | 
|---|
| 448 |     constructor Create(AOwner: TComponent); override;
 | 
|---|
| 449 |     destructor Destroy; override;
 | 
|---|
| 450 |   end;
 | 
|---|
| 451 | 
 | 
|---|
| 452 | constructor TWinControlTrap.Create(AOwner: TComponent);
 | 
|---|
| 453 | begin
 | 
|---|
| 454 |   FControl := TAccessWinControl(AOwner as TWinControl);
 | 
|---|
| 455 |   inherited Create(nil);
 | 
|---|
| 456 |   FControl.FreeNotification(Self);
 | 
|---|
| 457 | 
 | 
|---|
| 458 |   WinControl_ObjectInstance := Classes.MakeObjectInstance(FControl.MainWndProc);
 | 
|---|
| 459 |   ObjectInstance := Classes.MakeObjectInstance(Win32Proc);
 | 
|---|
| 460 |   DefObjectInstance := Classes.MakeObjectInstance(DefWin32Proc);
 | 
|---|
| 461 | end;
 | 
|---|
| 462 | 
 | 
|---|
| 463 | destructor TWinControlTrap.Destroy;
 | 
|---|
| 464 | begin
 | 
|---|
| 465 |   Classes.FreeObjectInstance(ObjectInstance);
 | 
|---|
| 466 |   Classes.FreeObjectInstance(DefObjectInstance);
 | 
|---|
| 467 |   Classes.FreeObjectInstance(WinControl_ObjectInstance);
 | 
|---|
| 468 |   inherited;
 | 
|---|
| 469 | end;
 | 
|---|
| 470 | 
 | 
|---|
| 471 | procedure TWinControlTrap.Notification(AComponent: TComponent; Operation: TOperation);
 | 
|---|
| 472 | begin
 | 
|---|
| 473 |   inherited;
 | 
|---|
| 474 |   if (AComponent = FControl) and (Operation = opRemove) then begin
 | 
|---|
| 475 |     FControl := nil;
 | 
|---|
| 476 |     if Win32ProcLevel = 0 then
 | 
|---|
| 477 |       Free
 | 
|---|
| 478 |     else
 | 
|---|
| 479 |       DestroyTrap := True;
 | 
|---|
| 480 |   end;
 | 
|---|
| 481 | end;
 | 
|---|
| 482 | 
 | 
|---|
| 483 | procedure TWinControlTrap.SubClassWindowProc;
 | 
|---|
| 484 | begin
 | 
|---|
| 485 |   if not IsInSubclassChain(FControl) then begin
 | 
|---|
| 486 |     PrevWindowProc := FControl.WindowProc;
 | 
|---|
| 487 |     FControl.WindowProc := Self.WindowProc;
 | 
|---|
| 488 |   end;
 | 
|---|
| 489 |   {$IFDEF TNT_VERIFY_WINDOWPROC}
 | 
|---|
| 490 |   LastVerifiedWindowProc := FControl.WindowProc;
 | 
|---|
| 491 |   {$ENDIF}
 | 
|---|
| 492 | end;
 | 
|---|
| 493 | 
 | 
|---|
| 494 | procedure TWinControlTrap.SubClassControl(Params_Caption: PAnsiChar);
 | 
|---|
| 495 | begin
 | 
|---|
| 496 |   // initialize trap object
 | 
|---|
| 497 |   Handle := FControl.Handle;
 | 
|---|
| 498 |   PrevWin32Proc := Pointer(GetWindowLongW(FControl.Handle, GWL_WNDPROC));
 | 
|---|
| 499 |   PrevDefWin32Proc := FControl.DefWndProc;
 | 
|---|
| 500 | 
 | 
|---|
| 501 |   // subclass Window Procedures
 | 
|---|
| 502 |   SetWindowLongW(FControl.Handle, GWL_WNDPROC, Integer(ObjectInstance));
 | 
|---|
| 503 |   FControl.DefWndProc := DefObjectInstance;
 | 
|---|
| 504 |   SubClassWindowProc;
 | 
|---|
| 505 | 
 | 
|---|
| 506 |   // For some reason, caption gets garbled after calling SetWindowLongW(.., GWL_WNDPROC).
 | 
|---|
| 507 |   TntControl_SetText(FControl, TntControl_GetStoredText(FControl, Params_Caption));
 | 
|---|
| 508 | end;
 | 
|---|
| 509 | 
 | 
|---|
| 510 | function SameWndMethod(A, B: TWndMethod): Boolean;
 | 
|---|
| 511 | begin
 | 
|---|
| 512 |   Result := @A = @B;
 | 
|---|
| 513 | end;
 | 
|---|
| 514 | 
 | 
|---|
| 515 | var
 | 
|---|
| 516 |   PendingRecreateWndTrapList: TComponentList = nil;
 | 
|---|
| 517 | 
 | 
|---|
| 518 | procedure TWinControlTrap.UnSubClassUnicodeControl;
 | 
|---|
| 519 | begin
 | 
|---|
| 520 |   // remember caption for future window creation
 | 
|---|
| 521 |   if not (csDestroying in FControl.ComponentState) then
 | 
|---|
| 522 |     TntControl_SetStoredText(FControl, TntControl_GetText(FControl));
 | 
|---|
| 523 | 
 | 
|---|
| 524 |   // restore window procs (restore WindowProc only if we are still the direct subclass)
 | 
|---|
| 525 |   if SameWndMethod(FControl.WindowProc, Self.WindowProc) then
 | 
|---|
| 526 |     FControl.WindowProc := PrevWindowProc;
 | 
|---|
| 527 |   TAccessWinControl(FControl).DefWndProc := PrevDefWin32Proc;
 | 
|---|
| 528 |   SetWindowLongW(FControl.Handle, GWL_WNDPROC, Integer(PrevWin32Proc));
 | 
|---|
| 529 | 
 | 
|---|
| 530 |   if IDEWindow then
 | 
|---|
| 531 |     DestroyTrap := True
 | 
|---|
| 532 |   else if not (csDestroying in FControl.ComponentState) then
 | 
|---|
| 533 |     // control not being destroyed, probably recreating window
 | 
|---|
| 534 |     PendingRecreateWndTrapList.Add(Self);
 | 
|---|
| 535 | end;
 | 
|---|
| 536 | 
 | 
|---|
| 537 | var
 | 
|---|
| 538 |   Finalized: Boolean; { If any tnt controls are still around after finalization it must be due to a memory leak.
 | 
|---|
| 539 |                         Windows will still try to send a WM_DESTROY, but we will just ignore it if we're finalized. }
 | 
|---|
| 540 | 
 | 
|---|
| 541 | procedure TWinControlTrap.Win32Proc(var Message: TMessage);
 | 
|---|
| 542 | begin
 | 
|---|
| 543 |   if (not Finalized) then begin
 | 
|---|
| 544 |     Inc(Win32ProcLevel);
 | 
|---|
| 545 |     try
 | 
|---|
| 546 |       with Message do begin
 | 
|---|
| 547 |         {$IFDEF TNT_VERIFY_WINDOWPROC}
 | 
|---|
| 548 |         if not SameWndMethod(FControl.WindowProc, LastVerifiedWindowProc) then begin
 | 
|---|
| 549 |           SubClassWindowProc;
 | 
|---|
| 550 |           LastVerifiedWindowProc := FControl.WindowProc;
 | 
|---|
| 551 |         end;
 | 
|---|
| 552 |         {$ENDIF}
 | 
|---|
| 553 |         LastWin32Msg := Msg;
 | 
|---|
| 554 |         Result := CallWindowProcW(PrevWin32Proc, Handle, Msg, wParam, lParam);
 | 
|---|
| 555 |       end;
 | 
|---|
| 556 |     finally
 | 
|---|
| 557 |       Dec(Win32ProcLevel);
 | 
|---|
| 558 |     end;
 | 
|---|
| 559 |     if (Win32ProcLevel = 0) and (DestroyTrap) then
 | 
|---|
| 560 |       Free;
 | 
|---|
| 561 |   end else if (Message.Msg = WM_DESTROY) or (Message.Msg = TNT_WM_DESTROY) then
 | 
|---|
| 562 |     FControl.WindowHandle := 0
 | 
|---|
| 563 | end;
 | 
|---|
| 564 | 
 | 
|---|
| 565 | procedure TWinControlTrap.DefWin32Proc(var Message: TMessage);
 | 
|---|
| 566 | 
 | 
|---|
| 567 |   function IsChildEdit(AHandle: HWND): Boolean;
 | 
|---|
| 568 |   var
 | 
|---|
| 569 |     AHandleClass: WideString;
 | 
|---|
| 570 |   begin
 | 
|---|
| 571 |     Result := False;
 | 
|---|
| 572 |     if (FControl.Handle = GetParent(Handle)) then begin
 | 
|---|
| 573 |       // child control
 | 
|---|
| 574 |       SetLength(AHandleClass, 255);
 | 
|---|
| 575 |       SetLength(AHandleClass, GetClassNameW(AHandle, PWideChar(AHandleClass), Length(AHandleClass)));
 | 
|---|
| 576 |       Result := WideSameText(AHandleClass, 'EDIT');
 | 
|---|
| 577 |     end;
 | 
|---|
| 578 |   end;
 | 
|---|
| 579 | 
 | 
|---|
| 580 | begin
 | 
|---|
| 581 |   with Message do begin
 | 
|---|
| 582 |     if Msg = WM_NOTIFYFORMAT then
 | 
|---|
| 583 |       Result := WMNotifyFormatResult(HWND(Message.wParam))
 | 
|---|
| 584 |     else begin
 | 
|---|
| 585 |       if (Msg = WM_CHAR) then begin
 | 
|---|
| 586 |         RestoreWMCharMsg(Message)
 | 
|---|
| 587 |       end;
 | 
|---|
| 588 |       if (Msg = WM_IME_CHAR) and (not _IsShellProgramming) and (not Win32PlatformIsXP) then
 | 
|---|
| 589 |       begin
 | 
|---|
| 590 |         { In Windows XP, DefWindowProc handles WM_IME_CHAR fine for VCL windows. }
 | 
|---|
| 591 |         { Before XP, DefWindowProc will sometimes produce incorrect, non-Unicode WM_CHAR. }
 | 
|---|
| 592 |         { Also, using PostMessageW on Windows 2000 didn't always produce the correct results. }
 | 
|---|
| 593 |         Message.Result := SendMessageW(Handle, WM_CHAR, wParam, lParam)
 | 
|---|
| 594 |       end else if (Msg = WM_IME_CHAR) and (_IsShellProgramming) then begin
 | 
|---|
| 595 |         { When a Tnt control is hosted by a non-delphi control, DefWindowProc doesn't always work even on XP. }
 | 
|---|
| 596 |         if IsChildEdit(Handle) then
 | 
|---|
| 597 |           Message.Result := Integer(PostMessageW(Handle, WM_CHAR, wParam, lParam)) // native edit child control
 | 
|---|
| 598 |         else
 | 
|---|
| 599 |           Message.Result := SendMessageW(Handle, WM_CHAR, wParam, lParam);
 | 
|---|
| 600 |       end else begin
 | 
|---|
| 601 |         if (Msg = WM_DESTROY) then begin
 | 
|---|
| 602 |           UnSubClassUnicodeControl; {The reason for doing this in DefWin32Proc is because in D9, TWinControl.WMDestroy() does a perform(WM_TEXT) operation. }
 | 
|---|
| 603 |         end;
 | 
|---|
| 604 |         { Normal DefWindowProc }
 | 
|---|
| 605 |         Result := CallWindowProcW(PrevDefWin32Proc, Handle, Msg, wParam, lParam);
 | 
|---|
| 606 |       end;
 | 
|---|
| 607 |     end;
 | 
|---|
| 608 |   end;
 | 
|---|
| 609 | end;
 | 
|---|
| 610 | 
 | 
|---|
| 611 | procedure ProcessCMHintShowMsg(var Message: TMessage);
 | 
|---|
| 612 | begin
 | 
|---|
| 613 |   if Win32PlatformIsUnicode then begin
 | 
|---|
| 614 |     with TCMHintShow(Message) do begin
 | 
|---|
| 615 |       if (HintInfo.HintWindowClass = THintWindow)
 | 
|---|
| 616 |       or (HintInfo.HintWindowClass.InheritsFrom(TTntCustomHintWindow)) then begin
 | 
|---|
| 617 |         if (HintInfo.HintWindowClass = THintWindow) then
 | 
|---|
| 618 |           HintInfo.HintWindowClass := TTntCustomHintWindow;
 | 
|---|
| 619 |         HintInfo.HintData := HintInfo;
 | 
|---|
| 620 |         HintInfo.HintStr := WideGetShortHint(WideGetHint(HintInfo.HintControl));
 | 
|---|
| 621 |       end;
 | 
|---|
| 622 |     end;
 | 
|---|
| 623 |   end;
 | 
|---|
| 624 | end;
 | 
|---|
| 625 | 
 | 
|---|
| 626 | function TWinControlTrap.IsInSubclassChain(Control: TWinControl): Boolean;
 | 
|---|
| 627 | var
 | 
|---|
| 628 |   Message: TMessage;
 | 
|---|
| 629 | begin
 | 
|---|
| 630 |   if SameWndMethod(Control.WindowProc, TAccessWinControl(Control).WndProc) then
 | 
|---|
| 631 |     Result := False { no subclassing }
 | 
|---|
| 632 |   else if SameWndMethod(Control.WindowProc, Self.WindowProc) then
 | 
|---|
| 633 |     Result := True { directly subclassed }
 | 
|---|
| 634 |   else begin
 | 
|---|
| 635 |     TestForNull := True;
 | 
|---|
| 636 |     FoundNull := False;
 | 
|---|
| 637 |     ZeroMemory(@Message, SizeOf(Message));
 | 
|---|
| 638 |     Message.Msg := WM_NULL;
 | 
|---|
| 639 |     Control.WindowProc(Message);
 | 
|---|
| 640 |     Result := FoundNull; { indirectly subclassed }
 | 
|---|
| 641 |   end;
 | 
|---|
| 642 | end;
 | 
|---|
| 643 | 
 | 
|---|
| 644 | procedure TWinControlTrap.WindowProc(var Message: TMessage);
 | 
|---|
| 645 | var
 | 
|---|
| 646 |   CameFromWindows: Boolean;
 | 
|---|
| 647 | begin
 | 
|---|
| 648 |   if TestForNull and (Message.Msg = WM_NULL) then
 | 
|---|
| 649 |     FoundNull := True;
 | 
|---|
| 650 | 
 | 
|---|
| 651 |   if (not FControl.HandleAllocated) then
 | 
|---|
| 652 |     FControl.WndProc(Message)
 | 
|---|
| 653 |   else begin
 | 
|---|
| 654 |     CameFromWindows := LastWin32Msg <> WM_NULL;
 | 
|---|
| 655 |     LastWin32Msg := WM_NULL;
 | 
|---|
| 656 |     with Message do begin
 | 
|---|
| 657 |       if Msg = CM_HINTSHOW then
 | 
|---|
| 658 |         ProcessCMHintShowMsg(Message);
 | 
|---|
| 659 |       if (not CameFromWindows)
 | 
|---|
| 660 |       and (IsTextMessage(Msg)) then
 | 
|---|
| 661 |         Result := SendMessageA(Handle, Msg, wParam, lParam)
 | 
|---|
| 662 |       else begin
 | 
|---|
| 663 |         if (Msg = WM_CHAR) then begin
 | 
|---|
| 664 |           MakeWMCharMsgSafeForAnsi(Message);
 | 
|---|
| 665 |         end;
 | 
|---|
| 666 |         PrevWindowProc(Message)
 | 
|---|
| 667 |       end;
 | 
|---|
| 668 |       if (Msg = TNT_WM_DESTROY) then 
 | 
|---|
| 669 |         UnSubClassUnicodeControl; {The reason for doing this in DefWin32Proc is because in D9, TWinControl.WMDestroy() does a perform(WM_TEXT) operation. }
 | 
|---|
| 670 |     end;
 | 
|---|
| 671 |   end;
 | 
|---|
| 672 | end;
 | 
|---|
| 673 | 
 | 
|---|
| 674 | //----------------------------------------------------------------------------------
 | 
|---|
| 675 | 
 | 
|---|
| 676 | function FindOrCreateWinControlTrap(Control: TWinControl): TWinControlTrap;
 | 
|---|
| 677 | var
 | 
|---|
| 678 |   i: integer;
 | 
|---|
| 679 | begin
 | 
|---|
| 680 |   // find or create trap object
 | 
|---|
| 681 |   Result := nil;
 | 
|---|
| 682 |   for i := PendingRecreateWndTrapList.Count - 1 downto 0 do begin
 | 
|---|
| 683 |     if TWinControlTrap(PendingRecreateWndTrapList[i]).FControl = Control then begin
 | 
|---|
| 684 |       Result := TWinControlTrap(PendingRecreateWndTrapList[i]);
 | 
|---|
| 685 |       PendingRecreateWndTrapList.Delete(i);
 | 
|---|
| 686 |       break; { found it }
 | 
|---|
| 687 |     end;
 | 
|---|
| 688 |   end;
 | 
|---|
| 689 |   if Result = nil then
 | 
|---|
| 690 |     Result := TWinControlTrap.Create(Control);
 | 
|---|
| 691 | end;
 | 
|---|
| 692 | 
 | 
|---|
| 693 | procedure SubClassUnicodeControl(Control: TWinControl; Params_Caption: PAnsiChar; IDEWindow: Boolean = False);
 | 
|---|
| 694 | var
 | 
|---|
| 695 |   WinControlTrap: TWinControlTrap;
 | 
|---|
| 696 | begin
 | 
|---|
| 697 |   if not IsWindowUnicode(Control.Handle) then
 | 
|---|
| 698 |     raise ETntInternalError.Create('Internal Error: SubClassUnicodeControl.Control is not Unicode.');
 | 
|---|
| 699 | 
 | 
|---|
| 700 |   WinControlTrap := FindOrCreateWinControlTrap(Control);
 | 
|---|
| 701 |   WinControlTrap.SubClassControl(Params_Caption);
 | 
|---|
| 702 |   WinControlTrap.IDEWindow := IDEWindow;
 | 
|---|
| 703 | end;
 | 
|---|
| 704 | 
 | 
|---|
| 705 | 
 | 
|---|
| 706 | //----------------------------------------------- CREATE/DESTROY UNICODE HANDLE
 | 
|---|
| 707 | 
 | 
|---|
| 708 | var
 | 
|---|
| 709 |   WindowAtom: TAtom;
 | 
|---|
| 710 |   ControlAtom: TAtom;
 | 
|---|
| 711 |   WindowAtomString: AnsiString;
 | 
|---|
| 712 |   ControlAtomString: AnsiString;
 | 
|---|
| 713 | 
 | 
|---|
| 714 | type
 | 
|---|
| 715 |   TWndProc = function(HWindow: HWnd; Message, WParam, LParam: Longint): Longint; stdcall;
 | 
|---|
| 716 | 
 | 
|---|
| 717 | function InitWndProcW(HWindow: HWnd; Message, WParam, LParam: Longint): Longint; stdcall;
 | 
|---|
| 718 | 
 | 
|---|
| 719 |     function GetObjectInstance(Control: TWinControl): Pointer;
 | 
|---|
| 720 |     var
 | 
|---|
| 721 |       WinControlTrap: TWinControlTrap;
 | 
|---|
| 722 |     begin
 | 
|---|
| 723 |       WinControlTrap := FindOrCreateWinControlTrap(Control);
 | 
|---|
| 724 |       PendingRecreateWndTrapList.Add(WinControlTrap);
 | 
|---|
| 725 |       Result := WinControlTrap.WinControl_ObjectInstance;
 | 
|---|
| 726 |     end;
 | 
|---|
| 727 | 
 | 
|---|
| 728 | var
 | 
|---|
| 729 |   ObjectInstance: Pointer;
 | 
|---|
| 730 | begin
 | 
|---|
| 731 |   TAccessWinControl(CreationControl).WindowHandle := HWindow;
 | 
|---|
| 732 |   ObjectInstance := GetObjectInstance(CreationControl);
 | 
|---|
| 733 |   {Controls.InitWndProc converts control to ANSI here by calling SetWindowLongA()!}
 | 
|---|
| 734 |   SetWindowLongW(HWindow, GWL_WNDPROC, Integer(ObjectInstance));
 | 
|---|
| 735 |   if  (GetWindowLongW(HWindow, GWL_STYLE) and WS_CHILD <> 0)
 | 
|---|
| 736 |   and (GetWindowLongW(HWindow, GWL_ID) = 0) then
 | 
|---|
| 737 |     SetWindowLongW(HWindow, GWL_ID, Integer(HWindow));
 | 
|---|
| 738 |   SetProp(HWindow, MakeIntAtom(ControlAtom), THandle(CreationControl));
 | 
|---|
| 739 |   SetProp(HWindow, MakeIntAtom(WindowAtom), THandle(CreationControl));
 | 
|---|
| 740 |   CreationControl := nil;
 | 
|---|
| 741 |   Result := TWndProc(ObjectInstance)(HWindow, Message, WParam, lParam);
 | 
|---|
| 742 | end;
 | 
|---|
| 743 | 
 | 
|---|
| 744 | procedure RegisterUnicodeClass(Params: TCreateParams; out WideWinClassName: WideString; IDEWindow: Boolean = False);
 | 
|---|
| 745 | const
 | 
|---|
| 746 |   UNICODE_CLASS_EXT = '.UnicodeClass';
 | 
|---|
| 747 | var
 | 
|---|
| 748 |   TempClass: TWndClassW;
 | 
|---|
| 749 |   WideClass: TWndClassW;
 | 
|---|
| 750 |   ClassRegistered: Boolean;
 | 
|---|
| 751 |   InitialProc: TFNWndProc;
 | 
|---|
| 752 | begin
 | 
|---|
| 753 |   if IDEWindow then
 | 
|---|
| 754 |     InitialProc := @InitWndProc
 | 
|---|
| 755 |   else
 | 
|---|
| 756 |     InitialProc := @InitWndProcW;
 | 
|---|
| 757 | 
 | 
|---|
| 758 |   with Params do begin
 | 
|---|
| 759 |     WideWinClassName := WinClassName + UNICODE_CLASS_EXT;
 | 
|---|
| 760 |     ClassRegistered := GetClassInfoW(hInstance, PWideChar(WideWinClassName), TempClass);
 | 
|---|
| 761 |     if (not ClassRegistered) or (TempClass.lpfnWndProc <> InitialProc)
 | 
|---|
| 762 |     then begin
 | 
|---|
| 763 |       if ClassRegistered then Win32Check(Windows.UnregisterClassW(PWideChar(WideWinClassName), hInstance));
 | 
|---|
| 764 |       // Prepare a TWndClassW record
 | 
|---|
| 765 |       WideClass := TWndClassW(WindowClass);
 | 
|---|
| 766 |       WideClass.hInstance := hInstance;
 | 
|---|
| 767 |       WideClass.lpfnWndProc := InitialProc;
 | 
|---|
| 768 |       if not Tnt_Is_IntResource(PWideChar(WindowClass.lpszMenuName)) then begin
 | 
|---|
| 769 |         WideClass.lpszMenuName := PWideChar(WideString(WindowClass.lpszMenuName));
 | 
|---|
| 770 |       end;
 | 
|---|
| 771 |       WideClass.lpszClassName := PWideChar(WideWinClassName);
 | 
|---|
| 772 | 
 | 
|---|
| 773 |       // Register the UNICODE class
 | 
|---|
| 774 |       if RegisterClassW(WideClass) = 0 then RaiseLastOSError;
 | 
|---|
| 775 |     end;
 | 
|---|
| 776 |   end;
 | 
|---|
| 777 | end;
 | 
|---|
| 778 | 
 | 
|---|
| 779 | procedure CreateUnicodeHandle(Control: TWinControl; const Params: TCreateParams;
 | 
|---|
| 780 |                                         const SubClass: WideString; IDEWindow: Boolean = False);
 | 
|---|
| 781 | var
 | 
|---|
| 782 |   TempSubClass: TWndClassW;
 | 
|---|
| 783 |   WideWinClassName: WideString;
 | 
|---|
| 784 |   Handle: THandle;
 | 
|---|
| 785 | begin
 | 
|---|
| 786 |   if (not Win32PlatformIsUnicode) then begin
 | 
|---|
| 787 |     with Params do
 | 
|---|
| 788 |       TAccessWinControl(Control).WindowHandle := CreateWindowEx(ExStyle, WinClassName,
 | 
|---|
| 789 |         Caption, Style, X, Y, Width, Height, WndParent, 0, WindowClass.hInstance, Param);
 | 
|---|
| 790 |   end else begin
 | 
|---|
| 791 |     // SubClass the unicode version of this control by getting the correct DefWndProc
 | 
|---|
| 792 |     if (SubClass <> '')
 | 
|---|
| 793 |     and GetClassInfoW(Params.WindowClass.hInstance, PWideChar(SubClass), TempSubClass) then
 | 
|---|
| 794 |       TAccessWinControl(Control).DefWndProc := TempSubClass.lpfnWndProc
 | 
|---|
| 795 |     else
 | 
|---|
| 796 |       TAccessWinControl(Control).DefWndProc := @DefWindowProcW;
 | 
|---|
| 797 | 
 | 
|---|
| 798 |     // make sure Unicode window class is registered
 | 
|---|
| 799 |     RegisterUnicodeClass(Params, WideWinClassName, IDEWindow);
 | 
|---|
| 800 | 
 | 
|---|
| 801 |     // Create UNICODE window handle
 | 
|---|
| 802 |     UnicodeCreationControl := Control;
 | 
|---|
| 803 |     try
 | 
|---|
| 804 |       with Params do
 | 
|---|
| 805 |         Handle := CreateWindowExW(ExStyle, PWideChar(WideWinClassName), nil,
 | 
|---|
| 806 |           Style, X, Y, Width, Height, WndParent, 0, hInstance, Param);
 | 
|---|
| 807 |       if Handle = 0 then
 | 
|---|
| 808 |         RaiseLastOSError;
 | 
|---|
| 809 |       TAccessWinControl(Control).WindowHandle := Handle;
 | 
|---|
| 810 |       if IDEWindow then
 | 
|---|
| 811 |         SetWindowLongW(Handle, GWL_WNDPROC, GetWindowLong(Handle, GWL_WNDPROC));
 | 
|---|
| 812 |     finally
 | 
|---|
| 813 |       UnicodeCreationControl := nil;
 | 
|---|
| 814 |     end;
 | 
|---|
| 815 | 
 | 
|---|
| 816 |     SubClassUnicodeControl(Control, Params.Caption, IDEWindow);
 | 
|---|
| 817 |   end;
 | 
|---|
| 818 | end;
 | 
|---|
| 819 | 
 | 
|---|
| 820 | procedure ReCreateUnicodeWnd(Control: TWinControl; Subclass: WideString; IDEWindow: Boolean = False);
 | 
|---|
| 821 | var
 | 
|---|
| 822 |   WasFocused: Boolean;
 | 
|---|
| 823 |   Params: TCreateParams;
 | 
|---|
| 824 | begin
 | 
|---|
| 825 |   with TAccessWinControl(Control) do begin
 | 
|---|
| 826 |     WasFocused := Focused;
 | 
|---|
| 827 |     DestroyHandle;
 | 
|---|
| 828 |     CreateParams(Params);
 | 
|---|
| 829 |     CreationControl := Control;
 | 
|---|
| 830 |     CreateUnicodeHandle(Control, Params, SubClass, IDEWindow);
 | 
|---|
| 831 |     StrDispose{TNT-ALLOW StrDispose}(WindowText);
 | 
|---|
| 832 |     WindowText := nil;
 | 
|---|
| 833 |     Perform(WM_SETFONT, Integer(Font.Handle), 1);
 | 
|---|
| 834 |     if AutoSize then AdjustSize;
 | 
|---|
| 835 |     UpdateControlState;
 | 
|---|
| 836 |     if WasFocused and (WindowHandle <> 0) then Windows.SetFocus(WindowHandle);
 | 
|---|
| 837 |   end;
 | 
|---|
| 838 | end;
 | 
|---|
| 839 | 
 | 
|---|
| 840 | { TTntCustomHintWindow procs }
 | 
|---|
| 841 | 
 | 
|---|
| 842 | function DataPointsToHintInfoForTnt(AData: Pointer): Boolean;
 | 
|---|
| 843 | begin
 | 
|---|
| 844 |   try
 | 
|---|
| 845 |     Result := (AData <> nil)
 | 
|---|
| 846 |           and (PHintInfo(AData).HintData = AData) {points to self}
 | 
|---|
| 847 |           and (PHintInfo(AData).HintWindowClass.InheritsFrom(TTntCustomHintWindow));
 | 
|---|
| 848 |   except
 | 
|---|
| 849 |     Result := False;
 | 
|---|
| 850 |   end;
 | 
|---|
| 851 | end;
 | 
|---|
| 852 | 
 | 
|---|
| 853 | function ExtractTntHintCaption(AData: Pointer): WideString;
 | 
|---|
| 854 | var
 | 
|---|
| 855 |   Control: TControl;
 | 
|---|
| 856 |   WideHint: WideString;
 | 
|---|
| 857 |   AnsiHintWithShortCut: AnsiString;
 | 
|---|
| 858 |   ShortCut: TShortCut;
 | 
|---|
| 859 | begin
 | 
|---|
| 860 |   Result := PHintInfo(AData).HintStr;
 | 
|---|
| 861 |   if Result <> '' then begin
 | 
|---|
| 862 |     Control := PHintInfo(AData).HintControl;
 | 
|---|
| 863 |     WideHint := WideGetShortHint(WideGetHint(Control));
 | 
|---|
| 864 |     if (AnsiString(WideHint) = PHintInfo(AData).HintStr) then
 | 
|---|
| 865 |       Result := WideHint
 | 
|---|
| 866 |     else if Application.HintShortCuts and (Control <> nil)
 | 
|---|
| 867 |     and (Control.Action is TCustomAction{TNT-ALLOW TCustomAction}) then begin
 | 
|---|
| 868 |       ShortCut := TCustomAction{TNT-ALLOW TCustomAction}(Control.Action).ShortCut;
 | 
|---|
| 869 |       if (ShortCut <> scNone) then
 | 
|---|
| 870 |       begin
 | 
|---|
| 871 |         AnsiHintWithShortCut := Format{TNT-ALLOW Format}('%s (%s)', [WideHint, ShortCutToText{TNT-ALLOW ShortCutToText}(ShortCut)]);
 | 
|---|
| 872 |         if AnsiHintWithShortCut = PHintInfo(AData).HintStr then
 | 
|---|
| 873 |           Result := WideFormat('%s (%s)', [WideHint, WideShortCutToText(ShortCut)]);
 | 
|---|
| 874 |       end;
 | 
|---|
| 875 |     end;
 | 
|---|
| 876 |   end;
 | 
|---|
| 877 | end;
 | 
|---|
| 878 | 
 | 
|---|
| 879 | { TTntCustomHintWindow }
 | 
|---|
| 880 | 
 | 
|---|
| 881 | procedure TTntCustomHintWindow.CreateWindowHandle(const Params: TCreateParams);
 | 
|---|
| 882 | begin
 | 
|---|
| 883 |   CreateUnicodeHandle(Self, Params, '');
 | 
|---|
| 884 | end;
 | 
|---|
| 885 | 
 | 
|---|
| 886 | {$IFNDEF COMPILER_7_UP}
 | 
|---|
| 887 | procedure TTntCustomHintWindow.CreateParams(var Params: TCreateParams);
 | 
|---|
| 888 | const
 | 
|---|
| 889 |   CS_DROPSHADOW = $00020000;
 | 
|---|
| 890 | begin
 | 
|---|
| 891 |   inherited;
 | 
|---|
| 892 |   if Win32PlatformIsXP then { Enable drop shadow effect on Windows XP and later. }
 | 
|---|
| 893 |     Params.WindowClass.Style := Params.WindowClass.Style or CS_DROPSHADOW;
 | 
|---|
| 894 | end;
 | 
|---|
| 895 | {$ENDIF}
 | 
|---|
| 896 | 
 | 
|---|
| 897 | function TTntCustomHintWindow.GetCaption: TWideCaption;
 | 
|---|
| 898 | begin
 | 
|---|
| 899 |   Result := TntControl_GetText(Self)
 | 
|---|
| 900 | end;
 | 
|---|
| 901 | 
 | 
|---|
| 902 | procedure TTntCustomHintWindow.SetCaption(const Value: TWideCaption);
 | 
|---|
| 903 | begin
 | 
|---|
| 904 |   TntControl_SetText(Self, Value);
 | 
|---|
| 905 | end;
 | 
|---|
| 906 | 
 | 
|---|
| 907 | procedure TTntCustomHintWindow.Paint;
 | 
|---|
| 908 | var
 | 
|---|
| 909 |   R: TRect;
 | 
|---|
| 910 | begin
 | 
|---|
| 911 |   if FBlockPaint then
 | 
|---|
| 912 |     exit;
 | 
|---|
| 913 |   if (not Win32PlatformIsUnicode) then
 | 
|---|
| 914 |     inherited
 | 
|---|
| 915 |   else begin
 | 
|---|
| 916 |     R := ClientRect;
 | 
|---|
| 917 |     Inc(R.Left, 2);
 | 
|---|
| 918 |     Inc(R.Top, 2);
 | 
|---|
| 919 |     Canvas.Font.Color := Screen.HintFont.Color;
 | 
|---|
| 920 |     Tnt_DrawTextW(Canvas.Handle, PWideChar(Caption), -1, R, DT_LEFT or DT_NOPREFIX or
 | 
|---|
| 921 |       DT_WORDBREAK or DrawTextBiDiModeFlagsReadingOnly);
 | 
|---|
| 922 |   end;
 | 
|---|
| 923 | end;
 | 
|---|
| 924 | 
 | 
|---|
| 925 | procedure TTntCustomHintWindow.CMTextChanged(var Message: TMessage);
 | 
|---|
| 926 | begin
 | 
|---|
| 927 |   { Avoid flicker when calling ActivateHint }
 | 
|---|
| 928 |   if FActivating then Exit;
 | 
|---|
| 929 |   Width := WideCanvasTextWidth(Canvas, Caption) + 6;
 | 
|---|
| 930 |   Height := WideCanvasTextHeight(Canvas, Caption) + 6;
 | 
|---|
| 931 | end;
 | 
|---|
| 932 | 
 | 
|---|
| 933 | procedure TTntCustomHintWindow.ActivateHint(Rect: TRect; const AHint: AnsiString);
 | 
|---|
| 934 | var
 | 
|---|
| 935 |   SaveActivating: Boolean;
 | 
|---|
| 936 | begin
 | 
|---|
| 937 |   SaveActivating := FActivating;
 | 
|---|
| 938 |   try
 | 
|---|
| 939 |     FActivating := True;
 | 
|---|
| 940 |     inherited;
 | 
|---|
| 941 |   finally
 | 
|---|
| 942 |     FActivating := SaveActivating;
 | 
|---|
| 943 |   end;
 | 
|---|
| 944 | end;
 | 
|---|
| 945 | 
 | 
|---|
| 946 | procedure TTntCustomHintWindow.ActivateHintData(Rect: TRect; const AHint: AnsiString; AData: Pointer);
 | 
|---|
| 947 | var
 | 
|---|
| 948 |   SaveActivating: Boolean;
 | 
|---|
| 949 | begin
 | 
|---|
| 950 |   if (not Win32PlatformIsUnicode)
 | 
|---|
| 951 |   or (not DataPointsToHintInfoForTnt(AData)) then
 | 
|---|
| 952 |     inherited
 | 
|---|
| 953 |   else begin
 | 
|---|
| 954 |     FBlockPaint := True;
 | 
|---|
| 955 |     try
 | 
|---|
| 956 |       SaveActivating := FActivating;
 | 
|---|
| 957 |       try
 | 
|---|
| 958 |         FActivating := True;
 | 
|---|
| 959 |         inherited;
 | 
|---|
| 960 |         Caption := ExtractTntHintCaption(AData);
 | 
|---|
| 961 |       finally
 | 
|---|
| 962 |         FActivating := SaveActivating;
 | 
|---|
| 963 |       end;
 | 
|---|
| 964 |     finally
 | 
|---|
| 965 |       FBlockPaint := False;
 | 
|---|
| 966 |     end;
 | 
|---|
| 967 |     Invalidate;
 | 
|---|
| 968 |   end;
 | 
|---|
| 969 | end;
 | 
|---|
| 970 | 
 | 
|---|
| 971 | function TntHintWindow_CalcHintRect(HintWindow: TTntCustomHintWindow; MaxWidth: Integer; const AHint: WideString): TRect;
 | 
|---|
| 972 | begin
 | 
|---|
| 973 |   Result := Rect(0, 0, MaxWidth, 0);
 | 
|---|
| 974 |   Tnt_DrawTextW(HintWindow.Canvas.Handle, PWideChar(AHint), -1, Result, DT_CALCRECT or DT_LEFT or
 | 
|---|
| 975 |     DT_WORDBREAK or DT_NOPREFIX or HintWindow.DrawTextBiDiModeFlagsReadingOnly);
 | 
|---|
| 976 |   Inc(Result.Right, 6);
 | 
|---|
| 977 |   Inc(Result.Bottom, 2);
 | 
|---|
| 978 | end;
 | 
|---|
| 979 | 
 | 
|---|
| 980 | function TTntCustomHintWindow.CalcHintRect(MaxWidth: Integer; const AHint: AnsiString; AData: Pointer): TRect;
 | 
|---|
| 981 | var
 | 
|---|
| 982 |   WideHintStr: WideString;
 | 
|---|
| 983 | begin
 | 
|---|
| 984 |   if (not Win32PlatformIsUnicode)
 | 
|---|
| 985 |   or (not DataPointsToHintInfoForTnt(AData)) then
 | 
|---|
| 986 |     Result := inherited CalcHintRect(MaxWidth, AHint, AData)
 | 
|---|
| 987 |   else begin
 | 
|---|
| 988 |     WideHintStr := ExtractTntHintCaption(AData);
 | 
|---|
| 989 |     Result := TntHintWindow_CalcHintRect(Self, MaxWidth, WideHintStr);
 | 
|---|
| 990 |   end;
 | 
|---|
| 991 | end;
 | 
|---|
| 992 | 
 | 
|---|
| 993 | { TTntHintWindow }
 | 
|---|
| 994 | 
 | 
|---|
| 995 | procedure TTntHintWindow.ActivateHint(Rect: TRect; const AHint: WideString);
 | 
|---|
| 996 | var
 | 
|---|
| 997 |   SaveActivating: Boolean;
 | 
|---|
| 998 | begin
 | 
|---|
| 999 |   SaveActivating := FActivating;
 | 
|---|
| 1000 |   try
 | 
|---|
| 1001 |     FActivating := True;
 | 
|---|
| 1002 |     Caption := AHint;
 | 
|---|
| 1003 |     inherited ActivateHint(Rect, AHint);
 | 
|---|
| 1004 |   finally
 | 
|---|
| 1005 |     FActivating := SaveActivating;
 | 
|---|
| 1006 |   end;
 | 
|---|
| 1007 | end;
 | 
|---|
| 1008 | 
 | 
|---|
| 1009 | procedure TTntHintWindow.ActivateHintData(Rect: TRect; const AHint: WideString; AData: Pointer);
 | 
|---|
| 1010 | var
 | 
|---|
| 1011 |   SaveActivating: Boolean;
 | 
|---|
| 1012 | begin
 | 
|---|
| 1013 |   FBlockPaint := True;
 | 
|---|
| 1014 |   try
 | 
|---|
| 1015 |     SaveActivating := FActivating;
 | 
|---|
| 1016 |     try
 | 
|---|
| 1017 |       FActivating := True;
 | 
|---|
| 1018 |       Caption := AHint;
 | 
|---|
| 1019 |       inherited ActivateHintData(Rect, AHint, AData);
 | 
|---|
| 1020 |     finally
 | 
|---|
| 1021 |       FActivating := SaveActivating;
 | 
|---|
| 1022 |     end;
 | 
|---|
| 1023 |   finally
 | 
|---|
| 1024 |     FBlockPaint := False;
 | 
|---|
| 1025 |   end;
 | 
|---|
| 1026 |   Invalidate;
 | 
|---|
| 1027 | end;
 | 
|---|
| 1028 | 
 | 
|---|
| 1029 | function TTntHintWindow.CalcHintRect(MaxWidth: Integer; const AHint: WideString; AData: Pointer): TRect;
 | 
|---|
| 1030 | begin
 | 
|---|
| 1031 |   Result := TntHintWindow_CalcHintRect(Self, MaxWidth, AHint);
 | 
|---|
| 1032 | end;
 | 
|---|
| 1033 | 
 | 
|---|
| 1034 | procedure WideListControl_AddItem(Control: TCustomListControl; const Item: WideString; AObject: TObject);
 | 
|---|
| 1035 | var
 | 
|---|
| 1036 |   WideControl: IWideCustomListControl;
 | 
|---|
| 1037 | begin
 | 
|---|
| 1038 |   if Control.GetInterface(IWideCustomListControl, WideControl) then
 | 
|---|
| 1039 |     WideControl.AddItem(Item, AObject)
 | 
|---|
| 1040 |   else
 | 
|---|
| 1041 |     Control.AddItem(Item, AObject);
 | 
|---|
| 1042 | end;
 | 
|---|
| 1043 | 
 | 
|---|
| 1044 | procedure InitControls;
 | 
|---|
| 1045 | 
 | 
|---|
| 1046 |   procedure InitAtomStrings_D6_D7_D9;
 | 
|---|
| 1047 |   var
 | 
|---|
| 1048 |     Controls_HInstance: Cardinal;
 | 
|---|
| 1049 |   begin
 | 
|---|
| 1050 |     Controls_HInstance := FindClassHInstance(TWinControl);
 | 
|---|
| 1051 |     WindowAtomString := Format{TNT-ALLOW Format}('Delphi%.8X',[GetCurrentProcessID]);
 | 
|---|
| 1052 |     ControlAtomString := Format{TNT-ALLOW Format}('ControlOfs%.8X%.8X', [Controls_HInstance, GetCurrentThreadID]);
 | 
|---|
| 1053 |   end;
 | 
|---|
| 1054 | 
 | 
|---|
| 1055 |   {$IFDEF COMPILER_6} // verified against VCL source in Delphi 6 and BCB 6
 | 
|---|
| 1056 |   procedure InitAtomStrings;
 | 
|---|
| 1057 |   begin
 | 
|---|
| 1058 |     InitAtomStrings_D6_D7_D9;
 | 
|---|
| 1059 |   end;
 | 
|---|
| 1060 |   {$ENDIF}
 | 
|---|
| 1061 |   {$IFDEF DELPHI_7} // verified against VCL source in Delphi 7
 | 
|---|
| 1062 |   procedure InitAtomStrings;
 | 
|---|
| 1063 |   begin
 | 
|---|
| 1064 |     InitAtomStrings_D6_D7_D9;
 | 
|---|
| 1065 |   end;
 | 
|---|
| 1066 |   {$ENDIF}
 | 
|---|
| 1067 |   {$IFDEF DELPHI_9} // verified against VCL source in Delphi 9
 | 
|---|
| 1068 |   procedure InitAtomStrings;
 | 
|---|
| 1069 |   begin
 | 
|---|
| 1070 |     InitAtomStrings_D6_D7_D9;
 | 
|---|
| 1071 |   end;
 | 
|---|
| 1072 |   {$ENDIF}
 | 
|---|
| 1073 |   {$IFDEF DELPHI_10} // verified against VCL source in Delphi 10
 | 
|---|
| 1074 |   procedure InitAtomStrings;
 | 
|---|
| 1075 |   begin
 | 
|---|
| 1076 |     InitAtomStrings_D6_D7_D9;
 | 
|---|
| 1077 |   end;
 | 
|---|
| 1078 |   {$ENDIF}
 | 
|---|
| 1079 | 
 | 
|---|
| 1080 | begin
 | 
|---|
| 1081 |   InitAtomStrings;
 | 
|---|
| 1082 |   WindowAtom := WinCheckH(GlobalAddAtom(PAnsiChar(WindowAtomString)));
 | 
|---|
| 1083 |   ControlAtom := WinCheckH(GlobalAddAtom(PAnsiChar(ControlAtomString)));
 | 
|---|
| 1084 | end;
 | 
|---|
| 1085 | 
 | 
|---|
| 1086 | initialization
 | 
|---|
| 1087 |   TNT_WM_DESTROY := RegisterWindowMessage('TntUnicodeVcl.DestroyWindow');
 | 
|---|
| 1088 |   WideControlHelpers := TComponentList.Create(True);
 | 
|---|
| 1089 |   PendingRecreateWndTrapList := TComponentList.Create(False);
 | 
|---|
| 1090 |   InitControls;
 | 
|---|
| 1091 | 
 | 
|---|
| 1092 | finalization
 | 
|---|
| 1093 |   GlobalDeleteAtom(ControlAtom);
 | 
|---|
| 1094 |   GlobalDeleteAtom(WindowAtom);
 | 
|---|
| 1095 |   FreeAndNil(WideControlHelpers);
 | 
|---|
| 1096 |   FreeAndNil(PendingRecreateWndTrapList);
 | 
|---|
| 1097 |   Finalized := True;
 | 
|---|
| 1098 | 
 | 
|---|
| 1099 | end.
 | 
|---|