📄 jvqcombolistbox.pas
字号:
State: TOwnerDrawState): Boolean;
var
P: TPicture;
B: TBitmap;
Points: array[0..4] of TPoint;
TmpRect: TRect;
Pt: TPoint;
I: Integer;
AText: string;
begin
Result := False;
if (Index < 0) or (Index >= Items.Count) or Assigned(OnDrawItem) then
Exit;
Result := True;
Canvas.Lock;
try
Canvas.Font := Font;
Canvas.Brush.Color := Self.Color;
if State * [odSelected, odFocused] <> [] then
begin
Canvas.Brush.Color := clHighlight;
Canvas.Font.Color := clHighlightText;
end;
if Items.Objects[Index] is TPicture then
P := TPicture(Items.Objects[Index])
else
P := nil;
if (P = nil) or (DrawStyle <> dsStretch) then
Canvas.FillRect(Rect);
if (P <> nil) and (P.Graphic <> nil) then
begin
TmpRect := Classes.Rect(0, 0, P.Graphic.Width, P.Graphic.Height);
if DoDrawImage(Index, P, Rect) then
begin
case DrawStyle of
dsOriginal:
begin
B := TBitmap.Create;
try
B.Assign(P.Bitmap);
TmpRect := GetOffset(Rect, Classes.Rect(0, 0, B.Width, B.Height));
B.Width := Min(B.Width,TmpRect.Right - TmpRect.Left);
B.Height := Min(B.Height,TmpRect.Bottom - TmpRect.Top);
Canvas.Draw(TmpRect.Left, TmpRect.Top, B);
finally
B.Free;
end;
end;
dsStretch, dsProportional:
begin
TmpRect := DestRect(P, Rect);
OffsetRect(TmpRect, Rect.Left, Rect.Top);
Canvas.StretchDraw(TmpRect, P.Graphic);
end;
end;
end;
end
else
begin
TmpRect := Rect;
InflateRect(TmpRect, -2, -2);
if DoDrawText(Index, Items[Index], TmpRect) then
begin
AText := Items[Index];
DoGetText(Index, AText);
DrawText(Canvas.Handle, PChar(AText), Length(AText),
TmpRect, DT_WORDBREAK or DT_LEFT or DT_TOP or DT_EDITCONTROL or DT_NOPREFIX or DT_END_ELLIPSIS);
end;
end;
// draw the combo button
GetCursorPos(Pt);
Pt := ScreenToClient(Pt);
I := ItemAtPos(Pt, True);
if (not HotTrackCombo and (State * [odSelected, odFocused] <> [])) or (HotTrackCombo and (I = Index)) then
begin
// draw frame
Canvas.Brush.Style := bsClear;
Canvas.Pen.Color := clHighlight;
Canvas.Pen.Width := 1 + Ord(not HotTrackCombo);
Points[0] := Point(Rect.Left, Rect.Top);
Points[1] := Point(Rect.Right - 2, Rect.Top);
Points[2] := Point(Rect.Right - 2, Rect.Bottom - 2);
Points[3] := Point(Rect.Left, Rect.Bottom - 2);
Points[4] := Point(Rect.Left, Rect.Top);
Canvas.Polygon(Points);
// draw button body
if ButtonWidth > 2 then // 2 because Pen.Width is 2
begin
TmpRect := Classes.Rect(Rect.Right - ButtonWidth - 1,
Rect.Top + 1, Rect.Right - 2 - Ord(FPushed), Rect.Bottom - 2 - Ord(FPushed));
DrawComboArrow(Canvas, TmpRect, FMouseOver and Focused, FPushed);
end;
Canvas.Brush.Style := bsSolid;
end
else
if odFocused in State then
Canvas.DrawFocusRect(Rect);
Canvas.Pen.Color := clBtnShadow;
Canvas.Pen.Width := 1;
Canvas.MoveTo(Rect.Left, Rect.Bottom - 1);
Canvas.LineTo(Rect.Right, Rect.Bottom - 1);
Canvas.MoveTo(Rect.Right - 1, Rect.Top);
Canvas.LineTo(Rect.Right - 1, Rect.Bottom - 1);
finally
Canvas.Unlock;
end;
end;
procedure TJvComboListBox.DoGetText(Index: Integer; var Text: string);
begin
if Assigned(FOnGetText) then
FOnGetText(Self, Index, Text);
end;
function TJvComboListBox.GetOffset(OrigRect, ImageRect: TRect): TRect;
var
W, H, W2, H2: Integer;
begin
Result := OrigRect;
W := ImageRect.Right - ImageRect.Left;
H := ImageRect.Bottom - ImageRect.Top;
W2 := OrigRect.Right - OrigRect.Left;
H2 := OrigRect.Bottom - OrigRect.Top;
if W2 > W then
OffsetRect(Result, (W2 - W) div 2, 0);
if H2 > H then
OffsetRect(Result, 0, (H2 - H) div 2);
end;
procedure TJvComboListBox.InsertImage(Index: Integer; P: TPicture);
var
P2: TPicture;
begin
P2 := TPicture.Create;
P2.Assign(P);
Items.InsertObject(Index, '', P2);
end;
procedure TJvComboListBox.InsertText(Index: Integer; const S: string);
begin
Items.Insert(Index, S);
end;
procedure TJvComboListBox.InvalidateItem(Index: Integer);
var
R, R2: TRect;
begin
if Index < 0 then
Index := ItemIndex;
R := ItemRect(Index);
R2 := R;
// we only want to redraw the combo button
if not IsRectEmpty(R) then
begin
R.Right := R.Right - ButtonWidth;
// don't redraw content, just button
ExcludeClipRect(Canvas.Handle, R.Left, R.Top, R.Right, R.Bottom);
QWindows.InvalidateRect(Handle, @R2, False);
end;
end;
procedure TJvComboListBox.MouseDown(Button: TMouseButton; Shift: TShiftState;
X, Y: Integer);
var
I: Integer;
R: TRect;
P: TPoint;
begin
inherited MouseDown(Button, Shift, X, Y);
if ItemIndex > -1 then
begin
P := Point(X, Y);
I := ItemAtPos(P, True);
R := ItemRect(I);
if (I = ItemIndex) and (X >= R.Right - ButtonWidth) and (X <= R.Right) then
begin
FMouseOver := True;
FPushed := True;
InvalidateItem(I);
if (DropdownMenu <> nil) and DoDropDown(I, X, Y) then
begin
case DropdownMenu.Alignment of
paRight:
P.X := R.Right;
paLeft:
P.X := R.Left;
paCenter:
P.X := R.Left + (R.Right - R.Left) div 2;
end;
P.Y := R.Top + ItemHeight;
P := ClientToScreen(P);
DropdownMenu.PopupComponent := Self;
DropdownMenu.Popup(P.X, P.Y);
//QWindows.IgnoreMouseEvents(Handle);
end;
MouseUp(Button, Shift, X, Y);
end;
end;
end;
procedure TJvComboListBox.MouseMove(Shift: TShiftState; X, Y: Integer);
var
P: TPoint;
I: Integer;
R: TRect;
begin
if (DropdownMenu <> nil) or HotTrackCombo then
begin
P := Point(X, Y);
I := ItemAtPos(P, True);
R := ItemRect(I);
if HotTrackCombo and (I <> FLastHotTrack) then
begin
if FLastHotTrack > -1 then
InvalidateItem(FLastHotTrack);
FLastHotTrack := I;
if FLastHotTrack > -1 then
InvalidateItem(FLastHotTrack);
end;
if ((I = ItemIndex) or HotTrackCombo) and (X >= R.Right - ButtonWidth) and (X <= R.Right) then
begin
if not FMouseOver then
begin
FMouseOver := True;
InvalidateItem(I);
end;
end
else
if FMouseOver then
begin
FMouseOver := False;
InvalidateItem(I);
end;
end;
inherited MouseMove(Shift, X, Y);
end;
procedure TJvComboListBox.MouseUp(Button: TMouseButton; Shift: TShiftState;
X, Y: Integer);
begin
inherited MouseUp(Button, Shift, X, Y);
if FPushed then
begin
FPushed := False;
InvalidateItem(ItemIndex);
end;
end;
procedure TJvComboListBox.Notification(AComponent: TComponent;
Operation: TOperation);
begin
inherited Notification(AComponent, Operation);
if (Operation = opRemove) and (AComponent = DropdownMenu) then
DropdownMenu := nil;
end;
procedure TJvComboListBox.SetButtonWidth(const Value: Integer);
begin
if FButtonWidth <> Value then
begin
FButtonWidth := Value;
Invalidate;
end;
end;
procedure TJvComboListBox.SetDrawStyle(const Value: TJvComboListBoxDrawStyle);
begin
if FDrawStyle <> Value then
begin
FDrawStyle := Value;
Invalidate;
end;
end;
procedure TJvComboListBox.SetHotTrackCombo(const Value: Boolean);
begin
if FHotTrackCombo <> Value then
begin
FHotTrackCombo := Value;
Invalidate;
end;
end;
procedure TJvComboListBox.Resize;
begin
inherited Resize;
Invalidate;
end;
{$IFDEF UNITVERSIONING}
const
UnitVersioning: TUnitVersionInfo = (
RCSfile: '$RCSfile: JvQComboListBox.pas,v $';
Revision: '$Revision: 1.15 $';
Date: '$Date: 2005/02/06 14:06:03 $';
LogPath: 'JVCL\run'
);
initialization
RegisterUnitVersion(HInstance, UnitVersioning);
finalization
UnregisterUnitVersion(HInstance);
{$ENDIF UNITVERSIONING}
end.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -