📄 fr_combo.pas
字号:
DC: HDC;
Brush, SaveBrush: HBRUSH;
X, Y: Integer;
Pen, SavePen: HPEN;
WindowBrush: HBRUSH;
begin
WindowBrush := GetSysColorBrush(COLOR_WINDOW);
DC := GetWindowDC(Handle);
SetRect(R, Width - FButtonWidth - 2, 2, Width -2, Height - 2);
Brush := CreateSolidBrush(GetSysColor(COLOR_BTNFACE));
SaveBrush := SelectObject(DC, Brush);
FillRect(DC, R, Brush);
SelectObject(DC, SaveBrush);
DeleteObject(Brush);
X := Trunc(FButtonWidth / 2) + Width - FButtonWidth - 4;
Y := Trunc((Height - 4) / 2) + 1;
if bnStyle = 0 then //No 3D border
begin
FrameRect (DC, R, WindowBrush);
GetWindowRect(Handle, R);
OffsetRect (R, -R.Left, -R.Top);
InflateRect(R, -FButtonWidth - 3, -2);
Pen := CreatePen(PS_SOLID, 1, ColorToRGB(clWindow));
SavePen := SelectObject(DC, Pen);
MoveToEx(DC,R.Right, R.Top, nil);
LineTo(DC, R.Right, R.Bottom);
SelectObject(DC, SavePen);
DeleteObject(Pen);
PaintButtonGlyph(DC, X, Y);
end;
if bnStyle = 1 then //3D up border
begin
DrawEdge (DC, R, BDR_RAISEDINNER, BF_RECT);
GetWindowRect(Handle, R);
OffsetRect (R, -R.Left, -R.Top);
InflateRect(R, -FButtonWidth - 3, -1);
Pen := CreatePen(PS_SOLID, 1, ColorToRGB(clBtnFace));
SavePen := SelectObject(DC, Pen);
MoveToEx(DC, R.Right, R.Top, nil);
LineTo(DC, R.Right, R.Bottom);
SelectObject(DC, SavePen);
DeleteObject(Pen);
PaintButtonGlyph(DC, X, Y);
end;
if bnStyle = 2 then //3D down border
begin
DrawEdge (DC, R, BDR_SUNKENOUTER, BF_RECT);
GetWindowRect(Handle, R);
OffsetRect (R, -R.Left, -R.Top);
InflateRect(R, -FButtonWidth - 3, -1);
Pen := CreatePen(PS_SOLID, 1, ColorToRGB(clBtnFace));
SavePen := SelectObject(DC, Pen);
MoveToEx(DC, R.Right, R.Top, nil);
LineTo(DC, R.Right, R.Bottom);
SelectObject(DC, SavePen);
DeleteObject(Pen);
PaintButtonGlyph(DC, X + 1, Y + 1);
end;
ReleaseDC(Handle, DC);
end;
procedure TfrCustomComboBox.PaintDisabled;
var
R: TRect;
Brush, SaveBrush: HBRUSH;
DC: HDC;
WindowBrush: HBRUSH;
begin
WindowBrush := GetSysColorBrush(COLOR_WINDOW);
DC := GetWindowDC(Handle);
Brush := CreateSolidBrush(GetSysColor(COLOR_BTNFACE));
SaveBrush := SelectObject(DC, Brush);
FillRect(DC, ClientRect, Brush);
SelectObject(DC, SaveBrush);
DeleteObject(Brush);
R := ClientRect;
InflateRect(R, -2, -2);
FrameRect (DC, R, WindowBrush);
PaintButtonGlyph(DC, Trunc(FButtonWidth / 2) + Width - FButtonWidth - 4,
Trunc((Height - 4) / 2) + 1);
ReleaseDC(Handle,DC);
end;
procedure TfrCustomComboBox.CMEnabledChanged(var Msg: TMessage);
begin
inherited;
Invalidate;
end;
procedure TfrCustomComboBox.CMMouseEnter(var Message: TMessage);
var
DC: HDC;
begin
inherited;
msMouseInControl := True;
if Enabled and not (GetFocus = EditHandle) and not DroppedDown then
begin
DC:=GetWindowDC(Handle);
PaintBorder(DC, True);
PaintButton(1);
ReleaseDC(Handle, DC);
end;
end;
procedure TfrCustomComboBox.CMMouseLeave(var Message: TMessage);
var
DC: HDC;
begin
inherited;
msMouseInControl := False;
if Enabled and not (GetFocus = EditHandle) and not DroppedDown then
begin
DC:=GetWindowDC(Handle);
PaintBorder(DC, False);
PaintButton(0);
ReleaseDC(Handle, DC);
end;
end;
function TfrCustomComboBox.GetSolidBorder: Boolean;
begin
Result := ((csDesigning in ComponentState)) or
(DroppedDown or (GetFocus = EditHandle) or msMouseInControl);
end;
function TfrCustomComboBox.GetListHeight: Integer;
begin
Result := ItemHeight * Min(DropDownCount, Items.Count) + 4;
if (DropDownCount <= 0) or (Items.Count = 0) then
Result := ItemHeight + 4;
end;
procedure TfrCustomComboBox.CMFontChanged(var Message: TMessage);
begin
inherited;
ItemHeight := GetFontHeight(Font);
RecreateWnd;
end;
//--- TfrFontComboBox -----------------------------------------------------------
function CreateBitmap(ResName: PChar): TBitmap;
begin
Result := TBitmap.Create;
Result.Handle := LoadBitmap(HInstance, ResName);
if Result.Handle = 0 then
begin
Result.Free;
Result := nil;
end;
end;
function EnumFontsProc(var LogFont: TLogFont; var TextMetric: TTextMetric;
FontType: Integer; Data: Pointer): Integer; stdcall;
begin
if (TStrings(Data).IndexOf(LogFont.lfFaceName) < 0) then
TStrings(Data).AddObject(LogFont.lfFaceName, TObject(FontType));
Result := 1;
end;
constructor TfrFontComboBox.Create(AOwner: TComponent);
begin
inherited Create(AOwner);
if not (csDesigning in ComponentState) then
frFontViewForm := TfrFontPreview.Create(Self);
FTrueTypeBMP := CreateBitmap('FTRUETYPE_FNT');
DropDownCount := 12;
Width := 150;
FEditOffset := 16;
FReadOnly := True;
FShowMRU := True;
Numused := -1;
FRegKey := '\Software\FastReport\MRUFont';
end;
destructor TfrFontComboBox.Destroy;
begin
FTrueTypeBMP.Free;
if not (csDesigning in ComponentState) then
frFontViewForm.Destroy;
inherited Destroy;
end;
procedure TfrFontComboBox.Loaded;
begin
inherited Loaded;
if csDesigning in ComponentState then exit;
FUpdate := True;
try
PopulateList;
if Items.IndexOf(Text) = -1 then
ItemIndex:=0;
finally
FUpdate := False;
end;
end;
procedure TfrFontComboBox.SetRegKey(Value: String);
begin
if Value = '' then
FRegKey := '\Software\FastReport\MRUFont' else
FRegKey := Value;
end;
procedure TfrFontComboBox.PopulateList;
var
LFont: TLogFont;
DC: HDC;
Reg: TRegistry;
s: String;
i: Integer;
str: TStringList;
begin
Sorted:=True;
Items.BeginUpdate;
str := TStringList.Create;
str.Sorted := True;
try
Clear;
DC := GetDC(0);
try
FillChar(LFont, sizeof(LFont), 0);
LFont.lfCharset := DEFAULT_CHARSET;
EnumFontFamiliesEx(DC, LFont, @EnumFontsProc, LongInt(str), 0);
finally
ReleaseDC(0, DC);
end;
if Printer.Printers.Count > 0 then
try
FillChar(LFont, sizeof(LFont), 0);
LFont.lfCharset := DEFAULT_CHARSET;
EnumFontFamiliesEx(Printer.Handle, LFont, @EnumFontsProc, LongInt(str), 0);
except;
end;
finally
Items.Assign(str);
Items.EndUpdate;
end;
str.Free;
Sorted := False;
if FShowMRU then
begin
Items.BeginUpdate;
Reg:=TRegistry.Create;
try
Reg.OpenKey(FRegKey, True);
for i := 4 downto 0 do
begin
s := Reg.ReadString('Font' + IntToStr(i));
if (s <> '') and (Items.IndexOf(s) <> -1) then
begin
Items.InsertObject(0, s, TObject(Reg.ReadInteger('FontType' + IntToStr(i))));
Inc(Numused);
end else
begin
Reg.WriteString('Font' + IntToStr(i), '');
Reg.WriteInteger('FontType' + IntToStr(i), 0);
end;
end;
finally
Reg.Free;
Items.EndUpdate;
end;
end;
end;
procedure TfrFontComboBox.DrawImage(DC: HDC; Index: Integer; R: TRect);
var
C: TCanvas;
Bitmap: TBitmap;
begin
inherited;
Index := Items.IndexOf(Text);
if Index = -1 then exit;
C := TCanvas.Create;
C.Handle := DC;
if (Integer(Items.Objects[Index]) and TRUETYPE_FONTTYPE) <> 0 then
Bitmap := FTrueTypeBMP
else Bitmap := nil;
if Bitmap <> nil then
begin
C.Brush.Color := clWindow;
C.BrushCopy(Bounds(R.Left, (R.Top + R.Bottom - Bitmap.Height)
div 2, Bitmap.Width, Bitmap.Height), Bitmap, Bounds(0, 0, Bitmap.Width,
Bitmap.Height), Bitmap.TransparentColor);
end;
C.Free;
end;
procedure TfrFontComboBox.DrawItem(Index: Integer; Rect: TRect;
State: TOwnerDrawState);
var
Bitmap: TBitmap;
BmpWidth: Integer;
Text: array[0..255] of Char;
begin
if odSelected in State then
begin
frFontViewForm.FPanel.Caption:=self.Items[index];
frFontViewForm.FPanel.Font.Name:=self.Items[index];
end;
with Canvas do
begin
BmpWidth := 15;
FillRect(Rect);
if (Integer(Items.Objects[Index]) and TRUETYPE_FONTTYPE) <> 0 then
Bitmap := FTrueTypeBMP
else Bitmap := nil;
if Bitmap <> nil then
begin
BmpWidth := Bitmap.Width;
BrushCopy(Bounds(Rect.Left+1 , (Rect.Top + Rect.Bottom - Bitmap.Height)
div 2, Bitmap.Width, Bitmap.Height), Bitmap, Bounds(0, 0, Bitmap.Width,
Bitmap.Height), Bitmap.TransparentColor);
end;
StrPCopy(Text, Items[Index]);
Rect.Left := Rect.Left + BmpWidth + 2;
DrawText(Canvas.Handle, Text, StrLen(Text), Rect,
{$IFDEF Delphi4}
DrawTextBiDiModeFlags(DT_SINGLELINE or DT_VCENTER or DT_NOPREFIX));
{$ELSE}
DT_SINGLELINE or DT_VCENTER or DT_NOPREFIX);
{$ENDIF}
if (Index = Numused) then
begin
Pen.Color := clBtnShadow;
MoveTo(0,Rect.Bottom - 2);
LineTo(width, Rect.Bottom - 2);
end;
if (Index = Numused + 1) and (Numused <> -1) then
begin
Pen.Color := clBtnShadow;
MoveTo(0, Rect.Top);
LineTo(width, Rect.Top);
end;
end;
end;
procedure TfrFontComboBox.CMFontChanged(var Message: TMessage);
begin
inherited;
Init;
end;
procedure TfrFontComboBox.CMFontChange(var Message: TMessage);
begin
inherited;
Reset;
end;
procedure TfrFontComboBox.Init;
begin
if GetFontHeight(Font) > FTrueTypeBMP.Height then
ItemHeight := GetFontHeight(Font)
else
ItemHeight := FTrueTypeBMP.Height + 1;
RecreateWnd;
end;
procedure TfrFontComboBox.Click;
begin
inherited Click;
if not (csReading in ComponentState) then
if not FUpdate and Assigned(FOnClick) then FOnClick(Self);
end;
procedure TfrFontComboBox.Reset;
begin
if csDesigning in ComponentState then exit;
FUpdate := True;
try
PopulateList;
if Items.IndexOf(Text) = -1 then
ItemIndex := 0;
finally
FUpdate := False;
end;
end;
procedure TfrFontComboBox.CNCommand(var Message: TWMCommand);
var
pnt:TPoint;
ind,i:integer;
Reg: TRegistry;
begin
inherited;
if (Message.NotifyCode in [CBN_CLOSEUP]) then
begin
frFontViewForm.Visible := False;
ind := itemindex;
if (ItemIndex = -1) or (ItemIndex = 0) then exit;
if FShowMRU then
begin
Items.BeginUpdate;
if Items.IndexOf(Items[ind]) <= Numused then
begin
Items.Move(Items.IndexOf(Items[ind]), 0);
ItemIndex := 0;
end else
begin
Items.InsertObject(0, Items[ItemIndex], Items.Objects[ItemIndex]);
Itemindex := 0;
if Numused < 4 then
Inc(Numused)
else
Items.Delete(5);
end;
Items.EndUpdate;
Reg := TRegistry.Create;
try
Reg.OpenKey(FRegKey,True);
for i := 0 to 4 do
if i <= Numused then
begin
Reg.WriteString('Font' + IntToStr(i), Items[i]);
Reg.WriteInteger('FontType' + IntToStr(i), Integer(Items.Objects[i]));
end else
begin
Reg.WriteString('Font' + IntToStr(i), '');
Reg.WriteInteger('FontType' + IntToStr(i), 0);
end;
finally
Reg.Free;
end;
end;
end;
if (Message.NotifyCode in [CBN_DROPDOWN]) then
begin
if ItemIndex < 5 then
PostMessage(FListHandle, LB_SETCURSEL, 0, 0);
pnt.x := (Self.Left ) + Self.width;
pnt.y := (Self.Top ) + Self.height;
pnt := Parent.ClientToScreen(pnt);
frFontViewForm.Top := pnt.y;
frFontViewForm.Left := pnt.x;
if frFontViewForm.Left+frFontViewForm.Width > Screen.Width then
begin
pnt.x := (Self.Left );
pnt := Parent.ClientToScreen(pnt);
frFontViewForm.Left := pnt.x - frFontViewForm.Width - 1;
end;
if FUpDropdown then
begin
pnt.y := (Self.Top );
pnt := Parent.ClientToScreen(pnt);
frFontViewForm.Top := pnt.y - frFontViewForm.Height;
end;
frFontViewForm.Visible := True;
end;
end;
//--- TfrFontPreview ------------------------------------------------------------
constructor TfrFontPreview.Create(AOwner: TComponent);
begin
inherited Create(AOwner);
Width := 200;
Height := 50;
Visible := False;
Parent := AOwner as TWinControl;
FPanel := TPanel.Create(Self);
with FPanel do
begin
Parent := Self;
Color := clWindow;
Ctl3D := False;
ParentCtl3D := False;
BorderStyle := bsSingle;
BevelInner := bvNone;
BevelOuter := bvNone;
Font.Color := clWindowText;
Font.Size := 18;
Align := alClient;
end;
end;
destructor TfrFontPreview.Destroy;
begin
FPanel.Free;
FPanel := nil;
inherited Destroy;
end;
procedure TfrFontPreview.CreateParams(var Params: TCreateParams);
begin
inherited CreateParams( Params);
with Params do begin
Style := WS_POPUP or WS_CLIPCHILDREN;
ExStyle := WS_EX_TOOLWINDOW;
WindowClass.Style := WindowClass.Style or CS_SAVEBITS;
end;
end;
end.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -