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.