Как заставить TRichEdit вести себя как WordPad в Windows 7 при изменении шрифта для определенных нетекстовых символов?

54

С помощью Sertac Akyuz кажется, что прямая причина связана с кодировкой \bullet: в моей локализованной Windows вход \bullet путем ввода Alt (0149) всегда получает \fcharset134 и пытается для изменения шрифта через EM_SETCHARFORMAT всегда сбой (ну, цвет, размер, стиль действительно могут быть изменены, но не фамилия семейства шрифтов).

Простейшим обходным путем является, следовательно, первая reset кодировка, а затем изменение шрифта.

Примечание: RichEdit (версия >= 4.1) следует использовать!

Примечание: версии RichEdit можно найти в MSDN О Rich Edit Controls, Мюррей Сарджент Блог MSDN версии RichEdit и Обновление версий RichEdit до 7.0. На последних страницах были упомянуты версии RichEdit выше 4.1. В качестве теста я скопировал RICHED20.DLL, поставляемый с Office 2010 вместе с приложением к Windows 2000, и все работает как шарм!

procedure TMainForm.ButtonFontClick(Sender: TObject);
var
  format: TCharFormat2;
begin
  if dlgFontCdxTxt.Execute then
  begin
    FillChar(format, sizeof(format), 0);
    format.cbSize:= Sizeof(format);
    format.dwMask:= CFM_CHARSET;
    format.bCharSet := 1; // or 0;
    redtTextBlock.Perform(EM_SETCHARFORMAT, SCF_SELECTION, Integer(@format));

    FillChar(format, sizeof(format), 0);
    format.cbSize:= Sizeof(format);
    format.dwMask:= CFM_FACE;
    StrPLCopy(format.szFaceName, dlgFontCdxTxt.Font.Name, High(format.szFaceName));
    redtTextBlock.Perform(EM_SETCHARFORMAT, SCF_SELECTION, Integer(@format));
  end;
  redtTextBlock.SetFocus;
end;

=============================================== ===

В соответствии с Wikipedia, WordPad используется элемент управления Microsoft RichEdit, версии 1.0, 2.0 и 3.0 в Windows 95, 98 и Windows 2000, соответственно. В Windows XP с пакетом обновления 1 (SP1) и более поздних версиях WordPad использует RichEdit 4.1, включая Windows 7.

Скажите, что документ rtf, редактируемый в WordPad, содержит нетекстовый символ Alt (0149), the bullet dot •. (Или U + 2022)

В Windows 2000 SP4 или XP SP2 шрифт этой пулевой точки может использовать только шрифт WordPad по умолчанию. Иными словами, нельзя менять шрифт для этой пулевой точки интерактивно в WordPad.

Однако в Windows 7 SP1 можно изменить шрифт на first changing to "Arial Unicode MS", а затем на любой желаемый шрифт неограниченное время.

Изображение 667Изображение 668Изображение 669

Кроме того, WordPad документ, созданный с использованием WordPad в Windows 7, который содержит разные шрифты точки, можно открыть и правильно просмотреть в WordPad в Windows 2000 или XP.

TRichEdit (Delphi XE, Windows 7) также может правильно открыть и просмотреть документ WordPad, созданный с использованием WordPad в Windows 7, TRichEdit.Lines.LoadFromFile.

Изображение 670

Интерактивно TRichEdit (Delphi XE, Windows 7) позволяет изменить шрифт the bullet dot на "Arial Unicode MS". Однако, в TRichEdit нельзя перейти к другим шрифтам в интерактивном режиме. Изображение 671Изображение 672Изображение 673

Поэтому мне интересно (1) причину разного поведения WordPad в Windows 7 и (2) можно ли заставить TRichEdit вести себя одинаково?

PS: Может понадобиться несколько раз нажать Alt (0149), чтобы получить точку в WordPad. Ввод 2022 и Alt + x всегда работает, как предложено здесь.

PS: нужно "активировать" шрифты в WordPad, как указано в ответе Почему TFontDialog дает меньше шрифтов, чем Screen.Fonts?

PS: Всегда можно изменить точку на разные шрифты в Word.

sample.rtf(вставьте в текстовый файл, а затем измените расширение на rtf)

{\rtf1\ansi\ansicpg936\deff0\deflang1033\deflangfe2052{\fonttbl{\f0\fswiss\fprq2\fcharset134 Arial Unicode MS;}{\f1\fnil\fcharset0 Arial Unicode MS;}{\f2\froman\fprq2\fcharset0 Times New Roman;}{\f3\fscript\fprq2\fcharset0 Comic Sans MS;}{\f4\fnil\fcharset0 Comic Sans MS;}{\f5\fmodern\fprq1\fcharset0 Consolas;}{\f6\fnil\fcharset0 Consolas;}{\f7\fmodern\fprq1\fcharset0 Lucida Console;}{\f8\fnil\fcharset0 Lucida Console;}{\f9\froman\fprq2\fcharset2 Symbol;}{\f10\froman\fprq2\fcharset0 Symbol;}{\f11\fnil\fcharset134 \'cb\'ce\'cc\'e5;}}
{\*\generator Msftedit 5.41.21.2510;}\viewkind4\uc1\pard\nowidctlpar\sa200\sl276\slmult1\lang2052\f0\fs22 Arial sample text \lang1033\f1\bullet\f2\par
\b\f3 Comic sample text \f4\bullet\f2\par
\b0\f5 Consolas sample text \f6\bullet\f2\par
\f7 Lucida sample text \f8\bullet\f2\par
\pard\nowidctlpar\qj\lang2052\f9 symbl sample text \lang1033\f10\u149?\kerning2\fs21\par
\pard\sa200\sl276\slmult1\lang2052\kerning0\f11\fs22\par
}

uMainForm.dfm для просмотра формата строк TRichEdit

object MainForm: TMainForm
  Left = 0
  Top = 0
  Caption = 'MainForm'
  ClientHeight = 362
  ClientWidth = 637
  Color = clBtnFace
  Font.Charset = DEFAULT_CHARSET
  Font.Color = clWindowText
  Font.Height = -11
  Font.Name = 'Tahoma'
  Font.Style = []
  OldCreateOrder = False
  OnCreate = FormCreate
  PixelsPerInch = 96
  TextHeight = 13
  object pnlBtn: TPanel
    Left = 0
    Top = 0
    Width = 637
    Height = 57
    Align = alTop
    Caption = 'pnlBtn'
    TabOrder = 0
    object Button1: TButton
      Left = 240
      Top = 14
      Width = 137
      Height = 31
      Caption = 'Analyze Rich Edit'
      TabOrder = 0
      OnClick = Button1Click
    end
  end
  object pnlClient: TPanel
    Left = 0
    Top = 57
    Width = 637
    Height = 305
    Align = alClient
    Caption = 'pnlClient'
    TabOrder = 1
    object redtTextBlock: TRichEdit
      Left = 1
      Top = 1
      Width = 225
      Height = 303
      Align = alLeft
      Font.Charset = GB2312_CHARSET
      Font.Color = clWindowText
      Font.Height = -11
      Font.Name = 'Tahoma'
      Font.Style = []
      Lines.Strings = (
        'redt1')
      ParentFont = False
      TabOrder = 0
    end
    object mmo1: TMemo
      Left = 226
      Top = 1
      Width = 410
      Height = 303
      Align = alClient
      Lines.Strings = (
        'mmo1')
      TabOrder = 1
    end
  end
  object Button2: TButton
    Left = 36
    Top = 14
    Width = 171
    Height = 31
    Caption = 'Font...'
    TabOrder = 2
    OnClick = Button2Click
  end
  object dlgFontCdxTxt: TFontDialog
    Font.Charset = DEFAULT_CHARSET
    Font.Color = clWindowText
    Font.Height = -11
    Font.Name = 'Tahoma'
    Font.Style = []
    Left = 480
    Top = 16
  end
end

uMainForm.pas для просмотра формата строк TRichEdit

unit uMainForm;

interface

uses
  Contnrs,
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, ComCtrls, ExtCtrls;

type

  TCdxmlStyle = class
  public
    FontName: string;
    Str: string;
  end;

  TCdxmlText = class
  public
    Styles: TObjectList;
    constructor Create;
  end;

  TMainForm = class(TForm)
    redtTextBlock: TRichEdit;
    mmo1: TMemo;
    pnlBtn: TPanel;
    pnlClient: TPanel;
    Button1: TButton;
    Button2: TButton;
    dlgFontCdxTxt: TFontDialog;
    procedure Button1Click(Sender: TObject);
    procedure Button2Click(Sender: TObject);
    procedure FormCreate(Sender: TObject);
  private
    { Private declarations }
    procedure TestLoadFromFile;
    procedure AnalyzeRichEdit;
  public
    { Public declarations }
  end;

var
  MainForm: TMainForm;

implementation

{$R *.dfm}

uses
  RichEdit, StrUtils;

{ TCdxmlText }

constructor TCdxmlText.Create;
begin
  Styles := TObjectList.Create;
end;

var
  l_HiddenRichEdit: TRichEdit;

{ TMainForm }

procedure TMainForm.FormCreate(Sender: TObject);
begin
  TestLoadFromFile;
  AnalyzeRichEdit;
end;

procedure TMainForm.Button2Click(Sender: TObject);
var
  format: TCharFormat2;
begin
  if dlgFontCdxTxt.Execute then
  begin
    FillChar(format, sizeof(format), 0);
    format.cbSize:= Sizeof(format);
    format.dwMask:= CFM_FACE;

    StrPLCopy(format.szFaceName, dlgFontCdxTxt.Font.Name, High(format.szFaceName));

    redtTextBlock.Perform(EM_SETCHARFORMAT, SCF_SELECTION, Integer(@format));
  end;
  redtTextBlock.SetFocus;
end;

procedure TMainForm.Button1Click(Sender: TObject);
begin
  AnalyzeRichEdit;
end;

procedure TMainForm.TestLoadFromFile;
begin
  redtTextBlock.Clear;

  redtTextBlock.Lines.LoadFromFile('sample.rtf');
end;

procedure TMainForm.AnalyzeRichEdit;
var
  l_MemStream: TMemoryStream;
  l_Format: TCharFormat2;

  I, J: Integer;
  l_CdxmlStyle, l_CdxmlStyleWorker: TCdxmlStyle;
  l_StyleFont: string;

  l_CdxmlText: TCdxmlText;
begin
  l_CdxmlStyle := nil;
  l_CdxmlStyleWorker := nil;

  mmo1.Clear;

  l_MemStream := TMemoryStream.Create;
  redtTextBlock.Lines.SaveToStream(l_MemStream);
  l_MemStream.Seek(0, soFromBeginning);
  l_HiddenRichEdit.Lines.LoadFromStream(l_MemStream);

  l_CdxmlText := TCdxmlText.Create;
  for I := 0 to Length(TrimRight(l_HiddenRichEdit.Text)) - 1 do
  begin
    l_CdxmlStyleWorker := TCdxmlStyle.Create;

    FillChar(l_Format, sizeof(l_Format), 0);
    l_Format.cbSize:= Sizeof(l_Format);
    l_Format.dwMask:= CFM_FACE;

    l_HiddenRichEdit.SelStart := I;
    l_HiddenRichEdit.SelLength := 1;
    l_HiddenRichEdit.Perform(EM_GETCHARFORMAT, SCF_SELECTION, Integer(@l_Format));

    l_CdxmlStyleWorker.FontName := l_Format.szFaceName;

    l_CdxmlStyleWorker.Str := AnsiReplaceStr(l_HiddenRichEdit.SelText, #13, #13#10);

    if l_CdxmlStyle = nil then
    begin
      l_CdxmlText.Styles.Add(l_CdxmlStyleWorker);
      l_CdxmlStyle := l_CdxmlStyleWorker;
    end
    else if (l_CdxmlStyleWorker.FontName  <> l_CdxmlStyle.FontName ) then
    begin
      l_CdxmlText.Styles.Add(l_CdxmlStyleWorker);
      l_CdxmlStyle := l_CdxmlStyleWorker;
    end
    else
    begin
      l_CdxmlStyle.Str := l_CdxmlStyle.Str + l_CdxmlStyleWorker.Str;
    end;
  end;

  for I := 0 to l_CdxmlText.Styles.Count - 1 do
  begin
    l_CdxmlStyle := TCdxmlStyle(l_CdxmlText.Styles[I]);
    mmo1.Lines.Add(l_CdxmlStyle.Str + ':' + l_CdxmlStyle.FontName);
  end;
end;

initialization

  l_HiddenRichEdit := TRichEdit.CreateParented(HWND_MESSAGE);

end.
  • 2
    Просто Sidenote, François писал о том , как использовать другую версию богатого управления редактирования в this blog post . Вы можете попытаться использовать это тоже.
  • 1
    @TLama: Большое спасибо за ваш комментарий! Я только что попробовал RichEdit 4.1 (проверено путем вставки в цветную таблицу), как вы предлагаете, но я все еще не могу изменить шрифт точки, например, Comic или Lucida в TRichEdit.
Теги:
fonts
wordpad
trichedit

1 ответ

1

Одна вещь, которую нужно проверить, - проверить, являются ли элементы управления richedit, используемые WordPad и TRichEdit одинаковыми. Я бы порекомендовал вам проверить (Spy ++) Spyxx.exe, чтобы убедиться, что элемент управления имеет тот же класс и те же стили. Если они совпадают, я также проверял бы, чтобы элементы управления получали одни и те же сообщения, снова используя Spy ++. Я предполагаю, что элементы управления не совпадают или они не настроены одинаково.

Если они не являются одним и тем же элементом управления, тогда вы должны иметь возможность использовать тот же элемент управления, что и WordPad (при условии, что он является частью стандартных пользовательских элементов управления Windows). И используйте Spy ++, чтобы установить стиль так же, как WordPad. Кроме того, вам может потребоваться отправить ему те же сообщения.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню