[BlueLeaf1336]>
PROGRAM>
フォント一覧抽出
2004/06/27:作成
Screen.Fontsでもフォント名は取り出せるんですが、たとえばTMemo.Font.Nameにフォント名だけを設定してもCharSetによっては反映されないことがあります。
そこで、CharSetも含めて、フォント情報を取り出せるだけ取り出そうと、そういう趣旨です。
unit iScreenFont;
interface
uses
Windows, Messages, SysUtils, Classes;
type
TFontKeeper = class
private
FFontType : integer;
FEnumLogFont: TEnumLogFont;
FTextMetrics: TNewTextMetric;
public
constructor Create(FontType: integer; LogFont: TEnumLogFont; TextMetrics: TNewTextMetric);
property FontType: integer read FFontType;
property EnumLogFont: TEnumLogFont read FEnumLogFont;
property TextMetrics: TNewTextMetric read FTextMetrics;
end;
TScreenFonts = class
private
FUpdating : Boolean;
FWndHandle: THandle;
FFonts : TStringList;
FAutoRefresh: Boolean;
protected
procedure WndProc(var Msg: TMessage);
procedure Clear();
function GetFontKeeper(index: integer): TFontKeeper;
function GetEnumLogFont(index: integer): TEnumLogFont;
function GetTextMetric(index: integer): TNewTextMetric;
function GetLogFont(index: integer): TLogFont;
public
constructor Create(const AutoRefresh: Boolean);
destructor Destroy(); override;
procedure Refresh();
property Fonts: TStringList read FFonts;
property FontKeeper[index: integer]: TFontKeeper read GetFontKeeper;
property EnumLogFont[index: integer]: TEnumLogFont read GetEnumLogFont;
property TextMetrics[index: integer]: TNewTextMetric read GetTextMetric;
property LogFont[index: integer]: TLogFont read GetLogFont;
property Updating: Boolean read FUpdating;
property AutoRefresh: Boolean read FAutoRefresh write FAutoRefresh;
end;
type
TRefreshProc = procedure() of object;
var
ScreenFonts: TScreenFonts = nil;
RefreshProc: TRefreshProc = nil;
implementation
constructor TFontKeeper.Create(FontType: integer; LogFont: TEnumLogFont;
TextMetrics: TNewTextMetric);
begin
FFontType := FontType;
FEnumLogFont := LogFont;
FTextMetrics := TextMetrics;
end;
procedure TScreenFonts.WndProc(var Msg: TMessage);
begin
if Msg.Msg = WM_FONTCHANGE then
begin
if FAutoRefresh then Refresh();
end else
begin
Msg.Result := DefWindowProc(FWndHandle, Msg.Msg, Msg.wParam, Msg.lParam);
end;
end;
constructor TScreenFonts.Create(const AutoRefresh: Boolean);
begin
inherited Create;
FUpdating := false;
FAutoRefresh := AutoRefresh;
FFonts := TStringList.Create;
FWndHandle := AllocateHWnd(WndProc);
Refresh();
end;
destructor TScreenFonts.Destroy();
begin
DeallocateHWnd(FWndHandle);
FFonts.Free;
inherited Destroy;
end;
procedure TScreenFonts.Clear();
begin
while FFonts.Count > 0 do
begin
FFonts.Objects[0].Free;
FFonts.Delete(0);
end;
FFonts.Clear();
end;
function FontEnumProc(LogFont: PEnumLogFont; TextMetrics: PNewTextMetric;
FontType: integer; Strings: LPARAM): integer; stdcall;
var
FaceName: string;
FontKeeper: TFontKeeper;
begin
FaceName := TEnumLogFont(LogFont^).elfLogFont.lfFaceName;
if (Copy(FaceName, 1, 1) <> '@') then
begin
FontKeeper := TFontKeeper.Create(FontType, LogFont^, TextMetrics^);
TStrings(Strings).AddObject(FaceName, FontKeeper);
end;
Result := 1;
end;
procedure TScreenFonts.Refresh();
var
DesktopDC: HDC;
begin
FUpdating := true;
Clear();
DesktopDC := GetDC(GetDesktopWindow);
EnumFontFamilies(DesktopDC, nil, @FontEnumProc, LPARAM(FFonts));
ReleaseDC(GetDesktopWindow, DesktopDC);
FFonts.Sort();
if Assigned(RefreshProc) then RefreshProc();
FUpdating := false;
end;
function TScreenFonts.GetFontKeeper(index: integer): TFontKeeper;
begin
Result := TFontKeeper(FFonts.Objects[index]);
end;
function TScreenFonts.GetEnumLogFont(index: integer): TEnumLogFont;
begin
Result := FontKeeper[index].EnumLogFont;
end;
function TScreenFonts.GetTextMetric(index: integer): TNewTextMetric;
begin
Result := FontKeeper[index].TextMetrics;
end;
function TScreenFonts.GetLogFont(index: integer): TLogFont;
begin
Result := FontKeeper[index].EnumLogFont.elfLogFont;
end;
initialization
ScreenFonts := TScreenFonts.Create(true);
finalization
ScreenFonts.Free;
end.
モウヒトツなサンプルです。とりあえずフォントの切り替えを選択するとちゃんとCharSetも同時に比較的簡単に切り替えることができるので、正しくそのフォントで指定することができています。
ScreenFont.zip(197,720bytes)