kolmck/Addons/KOLFontEditor.pas

425 lines
14 KiB
ObjectPascal

unit KOLFontEditor;
{
==================================================================
TKOLFont Property Editor
for MCK
-----------------------------------------------
Version: 1.0
Date: 16-sep-2003
Author: (C) Alexander Pravdin (aka SPeller)
e-mail: speller@mail.primorye.ru
www: http://kol.mastak.ru
http://bonanzas.rinet.ru
Thanks to:
Dmitry Zharov (aka Gandalf):
Start point of this component (MHFontDialog).
Delphi 5 and Delphi 7 support.
Tested Delphi versions: 5, 6, 7.
==================================================================}
interface
{$I KOLDEF.INC}
uses KOL, Windows, Messages, Graphics, Forms, CommDlg, Mirror,
{$IFDEF _D6orHigher}
DesignEditors, DesignIntf;
{$ELSE}
DsgnIntf;
{$ENDIF}
type
TKOLFontProperty = class(TClassProperty)
private
DlgWnd,
hWndOwner,
LabelWnd,
PickWnd,
FontLWnd,
EditWnd,
CBWnd: HWND;
ColorDlg: PColorDialog;
Top, Left, Height, Width,
OldPickWndProc,
OldEditWndProc: Integer;
Colors: PList;
Font: TFont;
Color: Integer;
function DlgExecute: Boolean;
public
function GetAttributes: TPropertyAttributes; override;
procedure Edit; override;
end;
procedure Register;
implementation
const
ID_DLGOBJ = 'ID_DLGOBJ'#0;
DLG_LBLID = 11200;
DLG_PICKID = 11201;
DLG_EDITID = 11202;
DLG_COLORCB = 1139;
DLG_EFFECTSGROUP = 1072;
CN_APPLYCOLOR = 501;
function PickWndProc(Wnd: HWND; Msg: Cardinal; wParam, lParam: Integer): Integer; stdcall;
var
_Self : TKOLFontProperty;
R : TRect;
hBr, DC : THandle;
begin
_Self := TKOLFontProperty(GetProp(Wnd, ID_DLGOBJ));
with _Self do
begin
case Msg of
WM_PAINT:
begin
GetClientRect(Wnd, R);
CallWindowProc(Pointer(OldPickWndProc), Wnd, Msg, wParam, lParam);
hBr := CreateSolidBrush(Color);
DC := GetDC(Wnd);
FillRect(DC, R, hBr);
ReleaseDC(Wnd, DC);
DeleteObject(hBr);
Result := 0;
Exit;
end;
end; // case
Result := CallWindowProc(Pointer(OldPickWndProc), Wnd, Msg, wParam, lParam);
end; // with
end;
function EditWndProc(Wnd: HWND; Msg: Cardinal; wParam, lParam: Integer): Integer; stdcall;
var
_Self : TKOLFontProperty;
begin
_Self := TKOLFontProperty(GetProp(Wnd, ID_DLGOBJ));
with _Self do
begin
Result := CallWindowProc(Pointer(OldEditWndProc), Wnd, Msg, wParam, lParam);
end; // with
end;
function FontDialogHook(Wnd: HWnd; Msg: UINT; WParam: WPARAM; LParam: LPARAM): UINT; stdcall;
var
_Self : TKOLFontProperty;
R, R2, SR : TRect;
I, tmID, CBCurSel, CBCount: Integer;
PCF : PChooseFontA;
tmWnd, ChildWnd, hFont: THandle;
st : string;
FR : Boolean;
begin
Result := 0;
_Self := TKOLFontProperty(GetProp(Wnd, ID_DLGOBJ));
if (_Self = nil) and (Msg = WM_INITDIALOG) then
begin
PCF := Pointer(lParam);
SetProp(Wnd, ID_DLGOBJ, Cardinal(PCF.lCustData));
_Self := TKOLFontProperty(GetProp(Wnd, ID_DLGOBJ));
end;
with _Self do
begin
case Msg of
WM_INITDIALOG:
begin
DlgWnd := Wnd;
GetWindowRect(Wnd, R);
SR := MakeRect(0, 0, GetSystemMetrics(SM_CXSCREEN), GetSystemMetrics(SM_CYSCREEN));
Width := R.Right - R.Left;
Height := R.Bottom - R.Top + 0;
Left := (SR.Left + SR.Right - Width) div 2;
Top := (SR.Top + SR.Bottom - Height) div 2;
SetWindowPos(Wnd, 0, Left, Top, Width, Height, SWP_NOZORDER);
ChildWnd := 0;
repeat
ChildWnd := FindWindowEx(Wnd, ChildWnd, 'COMBOBOX', nil);
tmID := GetWindowLong(ChildWnd, GWL_ID);
until (tmID = DLG_COLORCB) or (ChildWnd = 0);
if ChildWnd <> 0 then
begin
CBWnd := ChildWnd;
GetWindowRect(CBWnd, R);
R.Right := R.Right + 5;
SetWindowPos(CBWnd, 0, 0, 0, R.Right - R.Left, R.Bottom - R.Top, SWP_NOZORDER or SWP_NOMOVE);
end else
Exit;
ChildWnd := 0;
repeat
ChildWnd := FindWindowEx(Wnd, ChildWnd, 'BUTTON', nil);
tmID := GetWindowLong(ChildWnd, GWL_ID);
until (tmID = DLG_EFFECTSGROUP) or (ChildWnd = 0);
if ChildWnd <> 0 then
begin
tmWnd := ChildWnd;
GetWindowRect(tmWnd, R);
ScreenToClient(Wnd, R.TopLeft);
ScreenToClient(Wnd, R.BottomRight);
R.Bottom := R.Bottom + 20;
SetWindowPos(tmWnd, HWND_BOTTOM, R.Left, R.Top, R.Right - R.Left, R.Bottom - R.Top, 0);
end else
Exit;
ChildWnd := 0;
repeat
ChildWnd := FindWindowEx(Wnd, ChildWnd, 'STATIC', nil);
tmID := GetWindowLong(ChildWnd, GWL_ID);
until (tmID = 1093) or (ChildWnd = 0);
if ChildWnd <> 0 then
begin
FontLWnd := ChildWnd;
GetWindowRect(FontLWnd, R2);
R2 := MakeRect(7, 172, 219, 20);
R2.Top := R2.Top + 25;
R2.Bottom := R2.Bottom + 20;
SetWindowPos(FontLWnd, 0, R2.Left, R2.Top, R2.Right - R2.Left, R2.Bottom - R2.Top, SWP_NOZORDER);
end;
LabelWnd := CreateWindow('STATIC', 'Exactly:',
SS_LEFT or WS_VISIBLE or WS_CHILD,
R.Left + 10, R.Bottom - 26, 40, 15,
Wnd, 0, hInstance, nil);
SetWindowLong(LabelWnd, GWL_ID, DLG_LBLID);
SetProp(LabelWnd, ID_DLGOBJ, Cardinal(_Self));
hFont := SendMessage(Wnd, WM_GETFONT, 0, 0);
SendMessage(LabelWnd, WM_SETFONT, hFont, 0);
if WinVer >= wvXP then
begin
I := 0;
tmID := WS_BORDER;
end else
begin
I := WS_EX_CLIENTEDGE;
tmID := 0;
end;
PickWnd := CreateWindowEx(I,
'STATIC', nil,
WS_VISIBLE or WS_CHILD or SS_NOTIFY or tmID,
R.Left + 116, R.Bottom - 30, 21, 21,
Wnd, 0, hInstance, nil);
SetProp(PickWnd, ID_DLGOBJ, Cardinal(_Self));
SetWindowLong(PickWnd, GWL_ID, DLG_PICKID);
OldPickWndProc := SetWindowLong(PickWnd, GWL_WNDPROC, Integer(@PickWndProc));
EditWnd := CreateWindowEx(WS_EX_CLIENTEDGE,
'EDIT', nil,
WS_VISIBLE or WS_CHILD or ES_UPPERCASE or ES_AUTOHSCROLL,
R.Left + 60, R.Bottom - 30, 55, 21,
Wnd, 0, hInstance, nil);
SetWindowLong(EditWnd, GWL_ID, DLG_EDITID);
SetProp(EditWnd, ID_DLGOBJ, Cardinal(_Self));
SendMessage(EditWnd, WM_SETFONT, hFont, 0);
SendMessage(EditWnd, EM_SETLIMITTEXT, 6, 0);
OldEditWndProc := SetWindowLong(EditWnd, GWL_WNDPROC, Integer(@EditWndProc));
ColorDlg.OwnerWindow := Wnd;
CBCount := SendMessage(CBWnd, CB_GETCOUNT, 0, 0);
for I := 0 to CBCount - 1 do
begin
Colors.Add(Pointer(SendMessage(CBWnd, CB_GETITEMDATA, I, 0)));
end;
CBCurSel := Colors.IndexOf(Pointer(Color));
if CBCurSel < 0 then
begin
SendMessage(CBWnd, CB_ADDSTRING, 0, Integer(PChar('$' + Int2Hex(Color, 6))));
Colors.Add(Pointer(Color));
CBCurSel := Colors.Count - 1;
SendMessage(CBWnd, CB_SETITEMDATA, CBCurSel, Color);
end;
SendMessage(CBWnd, CB_SETCURSEL, CBCurSel, 0);
TSmallPoint(I).x := DLG_COLORCB;
TSmallPoint(I).y := CBN_SELCHANGE;
SendMessage(Wnd, WM_COMMAND, I, CBWnd);
end;
WM_COMMAND:
begin
case TSmallPoint(wParam).X of
DLG_PICKID:
begin
case TSmallPoint(wParam).Y of
STN_CLICKED:
begin
if GetWindowLong(PickWnd, GWL_USERDATA) = CN_APPLYCOLOR then
FR := True
else
begin
ColorDlg.Color := Color;
FR := ColorDlg.Execute;
if FR then Color := ColorDlg.Color;
end;
if FR then
begin
//-----
CBCurSel := Colors.IndexOf(Pointer(Color));
if CBCurSel < 0 then
begin
SendMessage(CBWnd, CB_ADDSTRING, 0, Integer(PChar('$' + Int2Hex(Color, 6))));
Colors.Add(Pointer(Color));
CBCurSel := Colors.Count - 1;
SendMessage(CBWnd, CB_SETITEMDATA, CBCurSel, Color);
end;
SendMessage(CBWnd, CB_SETCURSEL, CBCurSel, 0);
TSmallPoint(I).Y := CBN_SELCHANGE;
TSmallPoint(I).X := DLG_COLORCB;
SendMessage(Wnd, WM_COMMAND, I, CBWnd);
//-----
end;
end; // STN_CLICKED
end; // case
end; // DLG_PICKID
DLG_COLORCB:
begin
if TSmallPoint(wParam).Y = CBN_SELCHANGE then
begin
CBCurSel := SendMessage(CBWnd, CB_GETCURSEL, 0, 0);
if CBCurSel >= 0 then
begin
Color := SendMessage(CBWnd, CB_GETITEMDATA, CBCurSel, 0);
SetWindowText(EditWnd, PChar(Int2Hex(Color, 6)));
SendMessage(PickWnd, WM_PAINT, 0, 0);
end;
end;
end; // DLG_COLORCB
DLG_EDITID:
begin
case TSmallPoint(wParam).Y of
EN_CHANGE:
begin
SetLength(st, 20);
GetWindowText(EditWnd, @st[1], 18);
Color := Hex2Int(st);
SendMessage(PickWnd, WM_PAINT, 0, 0);
end;
end;
end; // DLG_EDITID
end; // case TSmallPoint( wParam ).X
end; // WM_COMMAND
end; // case
end; // with
end;
function TKOLFontProperty.DlgExecute: Boolean;
var
TMPCF : tagChooseFont;
TMPLogFont : tagLogFontA;
begin
FillChar(TMPCF, SizeOf(TMPCF), 0);
GetObject(Font.Handle, SizeOf(tagLOGFONT), @TMPLogFont);
TMPCF.lStructSize := Sizeof(TMPCF);
TMPCF.hWndOwner := hWndOwner;
TMPCF.Flags := CF_EFFECTS or CF_BOTH or CF_ENABLEHOOK or CF_INITTOLOGFONTSTRUCT;
TMPCF.lpfnHook := FontDialogHook;
TMPCF.lpLogFont := @TMPLogFont;
TMPCF.rgbColors := Color2RGB(Font.Color);
TMPCF.lCustData := Integer(Self);
Color := TMPCF.rgbColors;
Result := ChooseFont(TMPCF);
if Result then
begin
DeleteObject(Font.Handle);
Font.Handle := CreateFontIndirectA(TMPLogFont);
Font.Color := Color;
end;
end;
function TKOLFontProperty.GetAttributes: TPropertyAttributes;
begin
Result := inherited GetAttributes + [paDialog, paReadOnly];
end;
procedure TKOLFontProperty.Edit;
const
Pitch2API : array[TFontPitch] of Byte = (DEFAULT_PITCH, VARIABLE_PITCH, FIXED_PITCH);
var
LF : tagLOGFONT;
F : TKOLFont;
FS1 : TFontStyles;
begin
//----------------
hWndOwner := Application.Handle;
Font := TFont.Create;
Colors := NewList;
ColorDlg := NewColorDialog(ccoFullOpen);
//-----------------
F := TKOLFont(GetOrdValue);
FillChar(LF, SizeOf(tagLOGFONT), 0);
LF.lfHeight := F.FontHeight;
LF.lfWidth := F.FontWidth;
LF.lfOrientation := F.FontOrientation;
if fsBold in F.FontStyle then LF.lfWeight := 700;
LF.lfItalic := Byte(fsItalic in F.FontStyle);
LF.lfUnderline := Byte(fsUnderline in F.FontStyle);
LF.lfStrikeOut := Byte(fsStrikeOut in F.FontStyle);
LF.lfCharSet := F.FontCharset;
LF.lfPitchAndFamily := Pitch2API[F.FontPitch];
Move(F.FontName[1], LF.lfFaceName, Length(F.FontName));
Font.Color := F.Color;
Font.Handle := CreateFontIndirect(LF);
if DlgExecute then
begin
FillChar(LF, SizeOf(tagLOGFONT), 0);
GetObject(Font.Handle, SizeOf(tagLOGFONT), @LF);
F.FontHeight := LF.lfHeight;
F.FontWidth := LF.lfWidth;
F.FontOrientation := LF.lfOrientation;
FS1 := [];
if Boolean(LF.lfItalic) then Include(FS1, fsItalic);
if Boolean(LF.lfUnderline) then Include(FS1, fsUnderline);
if Boolean(LF.lfStrikeOut) then Include(FS1, fsStrikeout);
if LF.lfWeight > FW_NORMAL then Include(FS1, fsBold);
F.FontStyle := FS1;
F.FontCharset := LF.lfCharSet;
case LF.lfPitchAndFamily of
DEFAULT_PITCH: F.FontPitch := fpDefault;
FIXED_PITCH: F.FontPitch := fpFixed;
VARIABLE_PITCH: F.FontPitch := fpVariable;
end;
F.FontName := LF.lfFaceName;
F.Color := Font.Color;
SetOrdValue(Integer(F));
end;
//-----------------
ColorDlg.Free;
Colors.Free;
Font.Free;
//-----------------
end;
procedure Register;
begin
RegisterPropertyEditor(TypeInfo(TKOLFont), nil, '', TKOLFontProperty);
end;
end.