⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 tntforms.pas

📁 TNTUniCtrlsWithExceptions UniCode 国际化语言
💻 PAS
📖 第 1 页 / 共 2 页
字号:

procedure TTntForm.WMWindowPosChanging(var Message: TMessage);
begin
  inherited;
  // This message *sometimes* means that the Menu.BiDiMode changed.
  FixMenuBiDiProblem(Menu);
end;

function TTntForm.CreateDockManager: IDockManager;
begin
  if (DockManager = nil) and DockSite and UseDockManager then
    HandleNeeded; // force TNT subclassing to occur first
  Result := inherited CreateDockManager;
end;

{ TTntApplication }

constructor TTntApplication.Create(AOwner: TComponent);
begin
  inherited;
  Application.HookMainWindow(WndProc);
  FSettingChangeTime := GetTickCount;
  TntSysUtils._SettingChangeTime := GetTickCount;
end;

destructor TTntApplication.Destroy;
begin
  FreeAndNil(FTntAppIdleEventControl);
  Application.UnhookMainWindow(WndProc);
  inherited;
end;

function TTntApplication.GetHint: WideString;
begin
  // check to see if the hint has already been set on application.idle
  if Application.Hint = AnsiString(ApplicationMouseControlHint) then
    FHint := ApplicationMouseControlHint;
  // get the synced string
  Result := GetSyncedWideString(FHint, Application.Hint)
end;

procedure TTntApplication.SetAnsiAppHint(const Value: AnsiString);
begin
  Application.Hint := Value;
end;

procedure TTntApplication.SetHint(const Value: WideString);
begin
  SetSyncedWideString(Value, FHint, Application.Hint, SetAnsiAppHint);
end;

function TTntApplication.GetExeName: WideString;
begin
  Result := WideParamStr(0);
end;

function TTntApplication.GetTitle: WideString;
begin
  if (Application.Handle <> 0) and Win32PlatformIsUnicode then begin
    SetLength(Result, DefWindowProcW(Application.Handle, WM_GETTEXTLENGTH, 0, 0) + 1);
    DefWindowProcW(Application.Handle, WM_GETTEXT, Length(Result), Integer(PWideChar(Result)));
    SetLength(Result, Length(Result) - 1);
  end else
    Result := GetSyncedWideString(FTitle, Application.Title);
end;

procedure TTntApplication.SetAnsiApplicationTitle(const Value: AnsiString);
begin
  Application.Title := Value;
end;

procedure TTntApplication.SetTitle(const Value: WideString);
begin
  if (Application.Handle <> 0) and Win32PlatformIsUnicode then begin
    if (GetTitle <> Value) or (FTitle <> '') then begin
      DefWindowProcW(Application.Handle, WM_SETTEXT, 0, lParam(PWideChar(Value)));
      FTitle := '';
    end
  end else
    SetSyncedWideString(Value, FTitle, Application.Title, SetAnsiApplicationTitle);
end;

{$IFDEF COMPILER_6} // verified against VCL source in Delphi 6 and BCB 6
type
  THackApplication = class(TComponent)
  protected
    FxxxxxxxxxHandle: HWnd;
    FxxxxxxxxxBiDiMode: TBiDiMode;
    FxxxxxxxxxBiDiKeyboard: AnsiString;
    FxxxxxxxxxNonBiDiKeyboard: AnsiString;
    FxxxxxxxxxObjectInstance: Pointer;
    FxxxxxxxxxMainForm: TForm{TNT-ALLOW TForm};
    FMouseControl: TControl;
  end;
{$ENDIF}
{$IFDEF DELPHI_7} // verified against VCL source in Delphi 7
type
  THackApplication = class(TComponent)
  protected
    FxxxxxxxxxHandle: HWnd;
    FxxxxxxxxxBiDiMode: TBiDiMode;
    FxxxxxxxxxBiDiKeyboard: AnsiString;
    FxxxxxxxxxNonBiDiKeyboard: AnsiString;
    FxxxxxxxxxObjectInstance: Pointer;
    FxxxxxxxxxMainForm: TForm{TNT-ALLOW TForm};
    FMouseControl: TControl;
  end;
{$ENDIF}
{$IFDEF DELPHI_9} // verified against VCL source in Delphi 9
type
  THackApplication = class(TComponent)
  protected
    FxxxxxxxxxHandle: HWnd;
    FxxxxxxxxxBiDiMode: TBiDiMode;
    FxxxxxxxxxBiDiKeyboard: AnsiString;
    FxxxxxxxxxNonBiDiKeyboard: AnsiString;
    FxxxxxxxxxObjectInstance: Pointer;
    FxxxxxxxxxMainForm: TForm{TNT-ALLOW TForm};
    FMouseControl: TControl;
  end;
{$ENDIF}
{$IFDEF DELPHI_10} // verified against VCL source in Delphi 10
type
  THackApplication = class(TComponent)
  protected
    FxxxxxxxxxHandle: HWnd;
    FxxxxxxxxxBiDiMode: TBiDiMode;
    FxxxxxxxxxBiDiKeyboard: AnsiString;
    FxxxxxxxxxNonBiDiKeyboard: AnsiString;
    FxxxxxxxxxObjectInstance: Pointer;
    FxxxxxxxxxMainForm: TForm{TNT-ALLOW TForm};
    FMouseControl: TControl;
  end;
{$ENDIF}

function TTntApplication.ApplicationMouseControlHint: WideString;
var
  MouseControl: TControl;
begin
  MouseControl := THackApplication(Application).FMouseControl;
  Result := WideGetLongHint(WideGetHint(MouseControl));
end;

procedure TTntApplication.DoIdle;
begin
  // update TntApplication.Hint only when Ansi encodings are the same... (otherwise there are problems with action menus)
  if Application.Hint = AnsiString(ApplicationMouseControlHint) then
    Hint := ApplicationMouseControlHint;
end;

function TTntApplication.IsDlgMsg(var Msg: TMsg): Boolean;
begin
  Result := False;
  if (Application.DialogHandle <> 0) then begin
    if IsWindowUnicode(Application.DialogHandle) then
      Result := IsDialogMessageW(Application.DialogHandle, Msg)
    else
      Result := IsDialogMessageA(Application.DialogHandle, Msg);
  end;
end;

type
  TTntAppIdleEventControl = class(TControl)
  protected
    procedure OnIdle(Sender: TObject);
  public
    constructor Create(AOwner: TComponent); override;
    destructor Destroy; override;
  end;

constructor TTntAppIdleEventControl.Create(AOwner: TComponent);
begin
  inherited;
  ParentFont := False; { This allows Parent (Application) to be in another module. }
  Parent := Application.MainForm;
  Visible := True;
  Action := TTntAction.Create(Self);
  Action.OnExecute := OnIdle;
  Action.OnUpdate := OnIdle;
  TntApplication.FTntAppIdleEventControl := Self;
end;

destructor TTntAppIdleEventControl.Destroy;
begin
  if TntApplication <> nil then
    TntApplication.FTntAppIdleEventControl := nil;
  inherited;
end;

procedure TTntAppIdleEventControl.OnIdle(Sender: TObject);
begin
  TntApplication.DoIdle;
end;

function TTntApplication.ProcessMessage(var Msg: TMsg): Boolean;
var
  Handled: Boolean;
begin
  Result := False;
  // Check Main Form
  if (not FMainFormChecked) and (Application.MainForm <> nil) then begin
    if not (Application.MainForm is TTntForm) then begin
      // This control will help ensure that DoIdle is called
      TTntAppIdleEventControl.Create(Application.MainForm);
    end;
    FMainFormChecked := True;
  end;
  // Check for Unicode char messages
  if (Msg.message = WM_CHAR)
  and (Msg.wParam > Integer(High(AnsiChar)))
  and IsWindowUnicode(Msg.hwnd)
  and ((Application.DialogHandle = 0) or IsWindowUnicode(Application.DialogHandle))
  then begin
    Result := True;
    // more than 8-bit WM_CHAR destined for Unicode window
    Handled := False;
    if Assigned(Application.OnMessage) then
      Application.OnMessage(Msg, Handled);
    Application.CancelHint;
    // dispatch msg if not a dialog message
    if (not Handled) and (not IsDlgMsg(Msg)) then
      DispatchMessageW(Msg);
  end;
end;

function TTntApplication.WndProc(var Message: TMessage): Boolean;
var
  BasicAction: TBasicAction;
begin
  Result := False; { not handled }
  if (Message.Msg = WM_SETTINGCHANGE) then begin
    FSettingChangeTime := GetTickCount;
    TntSysUtils._SettingChangeTime := FSettingChangeTime;
  end;
  if (Message.Msg = WM_CREATE)
  and (FTitle <> '') then begin
    SetTitle(FTitle);
    FTitle := '';
  end;
  if (Message.Msg = CM_ACTIONEXECUTE) then begin
    BasicAction := TBasicAction(Message.LParam);
    if (BasicAction.ClassType = THintAction{TNT-ALLOW THintAction})
    and (THintAction{TNT-ALLOW THintAction}(BasicAction).Hint = AnsiString(Hint))
    then begin
      Result := True;
      Message.Result := 1;
      with TTntHintAction.Create(Self) do
      begin
        Hint := Self.Hint;
        try
          Execute;
        finally
          Free;
        end;
      end;
    end;
  end;
end;

function TTntApplication.MessageBox(const Text, Caption: PWideChar;
  Flags: Integer): Integer;
var
  ActiveWindow, TaskActiveWindow: HWnd;
  WindowList: Pointer;
  MBMonitor, AppMonitor: HMonitor;
  MonInfo: TMonitorInfo;
  Rect: TRect;
  FocusState: TFocusState;
begin
  with Application do
  begin
{$IFDEF DELPHI_9_UP}
    ActiveWindow := ActiveFormHandle;
{$ELSE}
    ActiveWindow := GetActiveWindow;
    if ActiveWindow = 0 then
      ActiveWindow := GetLastActivePopup(Handle);
{$ENDIF}
    if ActiveWindow = 0 then
      TaskActiveWindow := Handle
    else
      TaskActiveWindow := ActiveWindow;
    MBMonitor := MonitorFromWindow(ActiveWindow, MONITOR_DEFAULTTONEAREST);
    AppMonitor := MonitorFromWindow(Handle, MONITOR_DEFAULTTONEAREST);
    if MBMonitor <> AppMonitor then
    begin
      MonInfo.cbSize := Sizeof(TMonitorInfo);
      GetMonitorInfo(MBMonitor, @MonInfo);
      GetWindowRect(Handle, Rect);
      SetWindowPos(Handle, 0,
        MonInfo.rcMonitor.Left + ((MonInfo.rcMonitor.Right - MonInfo.rcMonitor.Left) div 2),
        MonInfo.rcMonitor.Top + ((MonInfo.rcMonitor.Bottom - MonInfo.rcMonitor.Top) div 2),
        0, 0, SWP_NOACTIVATE or SWP_NOREDRAW or SWP_NOSIZE or SWP_NOZORDER);
    end;
  WindowList := DisableTaskWindows(ActiveWindow);
    FocusState := SaveFocusState;
    if UseRightToLeftReading then Flags := Flags or MB_RTLREADING;
    try
      Result := Windows.MessageBoxW(TaskActiveWindow, Text, Caption, Flags);
    finally
      if MBMonitor <> AppMonitor then
        SetWindowPos(Handle, 0,
          Rect.Left + ((Rect.Right - Rect.Left) div 2),
          Rect.Top + ((Rect.Bottom - Rect.Top) div 2),
          0, 0, SWP_NOACTIVATE or SWP_NOREDRAW or SWP_NOSIZE or SWP_NOZORDER);
      EnableTaskWindows(WindowList);
      SetActiveWindow(ActiveWindow);
      RestoreFocusState(FocusState);
    end;
  end;
end;

procedure TTntApplication.ShowException(E: Exception);
var
  Msg: WideString;
begin
  // Because of OverwriteProcedure call in TntSystem-unit, Self could point
  // to a TApplication instance instead of a TTntApplication instance, thus
  // causing access violations. Therefore frame the whole code with a
  // "with TntApplication do"-statement.

  with TntApplication do
  begin
    if E is WideException then
    begin
      Msg := WideException(E).Message;
      if (Msg <> '') and (TntWideLastChar(Msg) > '.') then Msg := Msg + '.';
      MessageBox(PWideChar(Msg), PWideChar(Title), MB_OK + MB_ICONSTOP);
    end
    else
    begin
      Msg := Exception(E).Message;
      if (Msg <> '') and (TntWideLastChar(Msg) > '.') then Msg := Msg + '.';
      MessageBox(PWideChar(Msg), PWideChar(Title), MB_OK + MB_ICONSTOP);
    end
  end
end;

//===========================================================================
//   The NT GetMessage Hook is needed to support entering Unicode
//     characters directly from the keyboard (bypassing the IME).
//   Special thanks go to Francisco Leong for developing this solution.
//
//  Example:
//    1. Install "Turkic" language support.
//    2. Add "Azeri (Latin)" as an input locale.
//    3. In an EDIT, enter Shift+I.  (You should see a capital "I" with dot.)
//    4. In an EDIT, enter single quote (US Keyboard).  (You should see an upturned "e".)
//
var
  ManualPeekMessageWithRemove: Integer = 0;

procedure EnableManualPeekMessageWithRemove;
begin
  Inc(ManualPeekMessageWithRemove);
end;

procedure DisableManualPeekMessageWithRemove;
begin
  if (ManualPeekMessageWithRemove > 0) then
    Dec(ManualPeekMessageWithRemove);
end;

var
  NTGetMessageHook: HHOOK;

function GetMessageForNT(Code: Integer; wParam: Integer; lParam: Integer): LRESULT; stdcall;
var
  ThisMsg: PMSG;
begin
  if (Code >= 0)
  and (wParam = PM_REMOVE)
  and (ManualPeekMessageWithRemove = 0) then
  begin
    ThisMsg := PMSG(lParam);
    if (TntApplication <> nil)
    and TntApplication.ProcessMessage(ThisMsg^) then
      ThisMsg.message := WM_NULL; { clear for further processing }
  end;
  Result := CallNextHookEx(NTGetMessageHook, Code, wParam, lParam);
end;

procedure CreateGetMessageHookForNT;
begin
  Assert(Win32Platform = VER_PLATFORM_WIN32_NT);
  NTGetMessageHook := SetWindowsHookExW(WH_GETMESSAGE, GetMessageForNT, 0, GetCurrentThreadID);
  if NTGetMessageHook = 0 then
    RaiseLastOSError;
end;

//---------------------------------------------------------------------------------------------
//                                 Tnt Environment Setup
//---------------------------------------------------------------------------------------------

procedure InitTntEnvironment;

    function GetDefaultFont: WideString;

        function RunningUnderIDE: Boolean;
        begin
          Result := ModuleIsPackage and
            (    WideSameText(WideExtractFileName(WideGetModuleFileName(0)), 'bds.exe')
              or WideSameText(WideExtractFileName(WideGetModuleFileName(0)), 'delphi32.exe')
              or WideSameText(WideExtractFileName(WideGetModuleFileName(0)), 'bcb.exe'));
        end;

        function GetProfileStr(const Section, Key, Default: AnsiString; MaxLen: Integer): AnsiString;
        var
          Len: Integer;
        begin
          SetLength(Result, MaxLen + 1);
          Len := GetProfileString(PAnsiChar(Section), PAnsiChar(Key), PAnsiChar(Default),
            PAnsiChar(Result), Length(Result));
          SetLength(Result, Len);
        end;

        procedure SetProfileStr(const Section, Key, Value: AnsiString);
        var
          DummyResult: Cardinal;
        begin
          try
            Win32Check(WriteProfileString(PAnsiChar(Section), PAnsiChar(Key), PAnsiChar(Value)));
            if Win32Platform = VER_PLATFORM_WIN32_WINDOWS then
              WriteProfileString(nil, nil, nil); {this flushes the WIN.INI cache}
            SendMessageTimeout(HWND_BROADCAST, WM_SETTINGCHANGE, 0, Integer(PAnsiChar(Section)),
              SMTO_NORMAL, 250, DummyResult);
          except
            on E: Exception do begin
              E.Message := 'Couldn''t create font substitutes.' + CRLF + E.Message;
              Application.HandleException(nil);
            end;
          end;
        end;

    var
      ShellDlgFontName_1: WideString;
      ShellDlgFontName_2: WideString;
    begin
      ShellDlgFontName_1 := GetProfileStr('FontSubstitutes', 'MS Shell Dlg', '', LF_FACESIZE);
      if ShellDlgFontName_1 = '' then begin
        ShellDlgFontName_1 := 'MS Sans Serif';
        SetProfileStr('FontSubstitutes', 'MS Shell Dlg', ShellDlgFontName_1);
      end;
      ShellDlgFontName_2 := GetProfileStr('FontSubstitutes', 'MS Shell Dlg 2', '', LF_FACESIZE);
      if ShellDlgFontName_2 = '' then begin
        if Screen.Fonts.IndexOf('Tahoma') <> -1 then
          ShellDlgFontName_2 := 'Tahoma'
        else
          ShellDlgFontName_2 := ShellDlgFontName_1;
        SetProfileStr('FontSubstitutes', 'MS Shell Dlg 2', ShellDlgFontName_2);
      end;
      if RunningUnderIDE then begin
        Result := 'MS Shell Dlg 2' {Delphi is running}
      end else
        Result := ShellDlgFontName_2;
    end;

begin
  // Tnt Environment Setup
  InstallTntSystemUpdates;
  DefFontData.Name := GetDefaultFont;
  Forms.HintWindowClass := TntControls.TTntHintWindow;
end;

initialization
  TntApplication := TTntApplication.Create(nil);
  if Win32Platform = VER_PLATFORM_WIN32_NT then
    CreateGetMessageHookForNT;

finalization
  if NTGetMessageHook <> 0 then begin
    UnhookWindowsHookEx(NTGetMessageHook) // no Win32Check, fails in too many cases, and doesn't matter
  end;
  FreeAndNil(TntApplication);

end.

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -