mirror of
https://gitlab.com/freepascal.org/lazarus/lazarus.git
synced 2025-12-12 08:20:42 +01:00
win32: fix spacing for menu item drawing on classic windows by cobines with modifications (issue #0018424)
git-svn-id: trunk@35346 -
This commit is contained in:
parent
c6ba0c3174
commit
730a003f33
@ -93,7 +93,8 @@ uses strutils;
|
|||||||
{ helper routines }
|
{ helper routines }
|
||||||
|
|
||||||
const
|
const
|
||||||
SpaceBetweenIcons = 5;
|
SpaceNextToCheckMark = 2; // Used by Windows for check bitmap
|
||||||
|
SpaceNextToIcon = 5; // Our custom spacing for bitmaps bigger than check mark
|
||||||
|
|
||||||
// define the size of the MENUITEMINFO structure used by older Windows
|
// define the size of the MENUITEMINFO structure used by older Windows
|
||||||
// versions (95, NT4) to keep the compatibility with them
|
// versions (95, NT4) to keep the compatibility with them
|
||||||
@ -230,10 +231,8 @@ begin
|
|||||||
end;
|
end;
|
||||||
|
|
||||||
(* Get the maximum length of the given string in pixels *)
|
(* Get the maximum length of the given string in pixels *)
|
||||||
function StringSize(const aCaption: String; const aHDC: HDC; const aDecoration:TCaptionFlagsSet): TSize;
|
function StringSize(const aCaption: String; const aHDC: HDC): TSize;
|
||||||
var
|
var
|
||||||
oldFont: HFONT;
|
|
||||||
newFont: HFONT;
|
|
||||||
tmpRect: Windows.RECT;
|
tmpRect: Windows.RECT;
|
||||||
{$ifdef WindowsUnicodeSupport}
|
{$ifdef WindowsUnicodeSupport}
|
||||||
AnsiBuffer: ansistring;
|
AnsiBuffer: ansistring;
|
||||||
@ -241,8 +240,6 @@ var
|
|||||||
{$endif WindowsUnicodeSupport}
|
{$endif WindowsUnicodeSupport}
|
||||||
begin
|
begin
|
||||||
FillChar(tmpRect, SizeOf(tmpRect), 0);
|
FillChar(tmpRect, SizeOf(tmpRect), 0);
|
||||||
newFont := GetMenuItemFont(aDecoration);
|
|
||||||
oldFont := SelectObject(aHDC, newFont);
|
|
||||||
{$ifdef WindowsUnicodeSupport}
|
{$ifdef WindowsUnicodeSupport}
|
||||||
if UnicodeEnabledOS then
|
if UnicodeEnabledOS then
|
||||||
begin
|
begin
|
||||||
@ -257,33 +254,26 @@ begin
|
|||||||
{$else}
|
{$else}
|
||||||
DrawText(aHDC, pChar(aCaption), length(aCaption), @TmpRect, DT_CALCRECT);
|
DrawText(aHDC, pChar(aCaption), length(aCaption), @TmpRect, DT_CALCRECT);
|
||||||
{$endif}
|
{$endif}
|
||||||
SelectObject(aHDC, oldFont);
|
|
||||||
DeleteObject(newFont);
|
|
||||||
Result.cx := TmpRect.right - TmpRect.left;
|
Result.cx := TmpRect.right - TmpRect.left;
|
||||||
Result.cy := TmpRect.Bottom - TmpRect.Top;
|
Result.cy := TmpRect.Bottom - TmpRect.Top;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function CheckSpace(AMenuItem: TMenuItem): integer;
|
function GetAverageCharSize(AHDC: HDC): TSize;
|
||||||
|
const
|
||||||
|
alph: AnsiString = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz';
|
||||||
var
|
var
|
||||||
i: integer;
|
sz: SIZE;
|
||||||
|
tm: TEXTMETRIC;
|
||||||
begin
|
begin
|
||||||
Result := 0;
|
if GetTextMetrics(AHDC, @tm) = False then
|
||||||
if AMenuItem.IsInMenuBar then
|
Result.cy := 0
|
||||||
begin
|
|
||||||
if AMenuItem.Checked then
|
|
||||||
Result := GetSystemMetrics(SM_CXMENUCHECK);
|
|
||||||
end
|
|
||||||
else
|
else
|
||||||
begin
|
Result.cy := WORD(tm.tmHeight);
|
||||||
for i := 0 to AMenuItem.Parent.Count - 1 do
|
|
||||||
begin
|
if GetTextExtentPoint(AHDC, @alph[1], 52, @sz) = False then
|
||||||
if AMenuItem.Parent.Items[i].Checked then
|
Result.cx := 0
|
||||||
begin
|
else
|
||||||
Result := GetSystemMetrics(SM_CXMENUCHECK);
|
Result.cx := (sz.cx div 26 + 1) div 2;
|
||||||
break;
|
|
||||||
end;
|
|
||||||
end;
|
|
||||||
end;
|
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function MenuIconWidth(const AMenuItem: TMenuItem): integer;
|
function MenuIconWidth(const AMenuItem: TMenuItem): integer;
|
||||||
@ -312,22 +302,65 @@ begin
|
|||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function LeftCaptionPosition(const AMenuItem: TMenuItem): integer;
|
procedure GetNonTextSpace(const AMenuItem: TMenuItem;
|
||||||
|
AvgCharWidth: Integer;
|
||||||
|
out LeftSpace, RightSpace: Integer);
|
||||||
var
|
var
|
||||||
ImageWidth: Integer;
|
Space: Integer = SpaceNextToCheckMark;
|
||||||
|
CheckMarkWidth: Integer;
|
||||||
begin
|
begin
|
||||||
// If we have Check and Icon then we use only width of Icon
|
// If we have Check and Icon then we use only width of Icon.
|
||||||
// we draw our MenuItem so: space Image space Caption
|
// We draw our MenuItem so: space Image space Caption.
|
||||||
ImageWidth := MenuIconWidth(AMenuItem);
|
// Items not in menu bar always have enough space for a check mark.
|
||||||
if ImageWidth = 0 then
|
|
||||||
ImageWidth := CheckSpace(aMenuItem);
|
|
||||||
|
|
||||||
Result := SpaceBetweenIcons;
|
CheckMarkWidth := GetSystemMetrics(SM_CXMENUCHECK);
|
||||||
|
LeftSpace := MenuIconWidth(AMenuItem);
|
||||||
|
|
||||||
inc(Result, ImageWidth);
|
if LeftSpace > 0 then
|
||||||
|
begin
|
||||||
|
if not AMenuItem.IsInMenuBar then
|
||||||
|
begin
|
||||||
|
if LeftSpace < CheckMarkWidth then
|
||||||
|
LeftSpace := CheckMarkWidth
|
||||||
|
else
|
||||||
|
if LeftSpace > CheckMarkWidth then
|
||||||
|
Space := SpaceNextToIcon;
|
||||||
|
end;
|
||||||
|
end
|
||||||
|
else
|
||||||
|
begin
|
||||||
|
if not AMenuItem.IsInMenuBar or AMenuItem.Checked then
|
||||||
|
LeftSpace := CheckMarkWidth;
|
||||||
|
end;
|
||||||
|
|
||||||
if not aMenuItem.IsInMenuBar or (ImageWidth <> 0) then
|
if LeftSpace > 0 then
|
||||||
inc(Result, SpaceBetweenIcons);
|
begin
|
||||||
|
// Space to the left of the icon or check.
|
||||||
|
if not AMenuItem.IsInMenuBar then
|
||||||
|
Inc(LeftSpace, Space);
|
||||||
|
// Space between icon or check and caption.
|
||||||
|
if AMenuItem.Caption <> '' then
|
||||||
|
Inc(LeftSpace, Space);
|
||||||
|
end;
|
||||||
|
|
||||||
|
if AMenuItem.IsInMenuBar then
|
||||||
|
RightSpace := 0
|
||||||
|
else
|
||||||
|
RightSpace := CheckMarkWidth + AvgCharWidth;
|
||||||
|
|
||||||
|
if AMenuItem.Caption <> '' then
|
||||||
|
begin
|
||||||
|
if AMenuItem.IsInMenuBar then
|
||||||
|
begin
|
||||||
|
Inc(LeftSpace, AvgCharWidth);
|
||||||
|
Inc(RightSpace, AvgCharWidth);
|
||||||
|
end
|
||||||
|
else
|
||||||
|
begin
|
||||||
|
// Space on the right side of the text.
|
||||||
|
Inc(RightSpace, SpaceNextToCheckMark);
|
||||||
|
end;
|
||||||
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function TopPosition(const aMenuItemHeight: integer; const anElementHeight: integer): integer;
|
function TopPosition(const aMenuItemHeight: integer; const anElementHeight: integer): integer;
|
||||||
@ -756,8 +789,10 @@ end;
|
|||||||
|
|
||||||
function MenuItemSize(AMenuItem: TMenuItem; AHDC: HDC): TSize;
|
function MenuItemSize(AMenuItem: TMenuItem; AHDC: HDC): TSize;
|
||||||
var
|
var
|
||||||
decoration: TCaptionFlagsSet;
|
LeftSpace, RightSpace: Integer;
|
||||||
minimumHeight: Integer;
|
oldFont: HFONT;
|
||||||
|
newFont: HFONT;
|
||||||
|
AvgCharSize: TSize;
|
||||||
begin
|
begin
|
||||||
if IsVistaMenu then
|
if IsVistaMenu then
|
||||||
begin
|
begin
|
||||||
@ -769,36 +804,50 @@ begin
|
|||||||
end;
|
end;
|
||||||
|
|
||||||
if AMenuItem.Default then
|
if AMenuItem.Default then
|
||||||
decoration := [cfBold]
|
newFont := GetMenuItemFont([cfBold])
|
||||||
else
|
else
|
||||||
decoration := [];
|
newFont := GetMenuItemFont([]);
|
||||||
|
oldFont := SelectObject(aHDC, newFont);
|
||||||
|
AvgCharSize := GetAverageCharSize(AHDC);
|
||||||
|
|
||||||
Result := StringSize(CompleteMenuItemCaption(AMenuItem, ' '), AHDC, decoration);
|
Result := StringSize(CompleteMenuItemCaption(AMenuItem, EmptyStr), AHDC);
|
||||||
inc(Result.cx, LeftCaptionPosition(AMenuItem));
|
|
||||||
|
|
||||||
if not AMenuItem.IsInMenuBar then
|
// Space between text and shortcut.
|
||||||
inc(Result.cx, SpaceBetweenIcons)
|
if AMenuItem.ShortCut <> scNone then
|
||||||
else
|
inc(Result.cx, AvgCharSize.cx);
|
||||||
dec(Result.cx, SpaceBetweenIcons);
|
|
||||||
|
|
||||||
if (AMenuItem.ShortCut <> scNone) then
|
GetNonTextSpace(AMenuItem, AvgCharSize.cx, LeftSpace, RightSpace);
|
||||||
Inc(Result.cx, SpaceBetweenIcons);
|
inc(Result.cx, LeftSpace + RightSpace);
|
||||||
|
|
||||||
|
// Windows adds additional space to value returned from WM_MEASUREITEM
|
||||||
|
// for owner drawn menus. This is to negate that.
|
||||||
|
Dec(Result.cx, AvgCharSize.cx * 2);
|
||||||
|
|
||||||
|
// As for height of items in menu bar, regardless of what is set here,
|
||||||
|
// Windows seems to always use SM_CYMENUSIZE (space for a border is included).
|
||||||
|
|
||||||
minimumHeight := GetSystemMetrics(SM_CYMENU);
|
|
||||||
if not AMenuItem.IsInMenuBar then
|
|
||||||
Dec(minimumHeight, 2);
|
|
||||||
if AMenuItem.IsLine then
|
if AMenuItem.IsLine then
|
||||||
Result.cy := 10 // it is a separator
|
Result.cy := GetSystemMetrics(SM_CYMENUSIZE) div 2 // it is a separator
|
||||||
else
|
else
|
||||||
begin
|
begin
|
||||||
|
if AMenuItem.IsInMenuBar then
|
||||||
|
begin
|
||||||
|
Result.cy := Max(Result.cy, GetSystemMetrics(SM_CYMENUSIZE));
|
||||||
if AMenuItem.hasIcon then
|
if AMenuItem.hasIcon then
|
||||||
Result.cy := Max(Result.cy, aMenuItem.GetIconSize.y);
|
Result.cy := Max(Result.cy, aMenuItem.GetIconSize.y);
|
||||||
Inc(Result.cy, 2);
|
end
|
||||||
if Result.cy < minimumHeight then
|
else
|
||||||
Result.cy := minimumHeight;
|
begin
|
||||||
|
Result.cy := Max(Result.cy + 2, AvgCharSize.cy + 4);
|
||||||
|
if AMenuItem.hasIcon then
|
||||||
|
Result.cy := Max(Result.cy, aMenuItem.GetIconSize.y + 2);
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
SelectObject(aHDC, oldFont);
|
||||||
|
DeleteObject(newFont);
|
||||||
|
end;
|
||||||
|
|
||||||
function IsFlatMenus: Boolean; inline;
|
function IsFlatMenus: Boolean; inline;
|
||||||
var
|
var
|
||||||
IsFlatMenu: Windows.BOOL;
|
IsFlatMenu: Windows.BOOL;
|
||||||
@ -857,15 +906,21 @@ end;
|
|||||||
procedure DrawSeparator(const AHDC: HDC; const ARect: Windows.RECT);
|
procedure DrawSeparator(const AHDC: HDC; const ARect: Windows.RECT);
|
||||||
var
|
var
|
||||||
separatorRect: Windows.RECT;
|
separatorRect: Windows.RECT;
|
||||||
|
space: Integer;
|
||||||
begin
|
begin
|
||||||
separatorRect.left := ARect.left;
|
if IsFlatMenus then
|
||||||
separatorRect.right := ARect.right;
|
space := 3
|
||||||
separatorRect.top := (ARect.top + ARect.bottom ) div 2 - 1;
|
else
|
||||||
separatorRect.bottom := separatorRect.top + 2;
|
space := 1;
|
||||||
DrawEdge(aHDC, separatorRect, BDR_SUNKENOUTER, BF_RECT);
|
|
||||||
|
separatorRect.Left := ARect.Left + space;
|
||||||
|
separatorRect.Right := ARect.Right - space;
|
||||||
|
separatorRect.Top := ARect.Top + GetSystemMetrics(SM_CYMENUSIZE) div 4 - 1;
|
||||||
|
DrawEdge(AHDC, separatorRect, EDGE_ETCHED, BF_TOP);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure DrawMenuItemCheckMark(const aMenuItem: TMenuItem; const aHDC: HDC; const aRect: Windows.RECT; const aSelected: boolean);
|
procedure DrawMenuItemCheckMark(const aMenuItem: TMenuItem; const aHDC: HDC;
|
||||||
|
const aRect: Windows.RECT; const aSelected: boolean; AvgCharWidth: Integer);
|
||||||
var
|
var
|
||||||
checkMarkWidth: integer;
|
checkMarkWidth: integer;
|
||||||
checkMarkHeight: integer;
|
checkMarkHeight: integer;
|
||||||
@ -875,6 +930,7 @@ var
|
|||||||
checkMarkShape: integer;
|
checkMarkShape: integer;
|
||||||
checkMarkRect: Windows.RECT;
|
checkMarkRect: Windows.RECT;
|
||||||
x:Integer;
|
x:Integer;
|
||||||
|
space: Integer;
|
||||||
begin
|
begin
|
||||||
hdcMem := CreateCompatibleDC(aHDC);
|
hdcMem := CreateCompatibleDC(aHDC);
|
||||||
checkMarkWidth := GetSystemMetrics(SM_CXMENUCHECK);
|
checkMarkWidth := GetSystemMetrics(SM_CXMENUCHECK);
|
||||||
@ -890,10 +946,14 @@ begin
|
|||||||
else
|
else
|
||||||
checkMarkShape := DFCS_MENUCHECK;
|
checkMarkShape := DFCS_MENUCHECK;
|
||||||
DrawFrameControl(hdcMem, @checkMarkRect, DFC_MENU, checkMarkShape);
|
DrawFrameControl(hdcMem, @checkMarkRect, DFC_MENU, checkMarkShape);
|
||||||
if aMenuItem.GetIsRightToLeft then
|
if aMenuItem.IsInMenuBar then
|
||||||
x := aRect.Right - checkMarkWidth - spaceBetweenIcons
|
space := AvgCharWidth
|
||||||
else
|
else
|
||||||
x := aRect.left + spaceBetweenIcons;
|
space := SpaceNextToCheckMark;
|
||||||
|
if aMenuItem.GetIsRightToLeft then
|
||||||
|
x := aRect.Right - checkMarkWidth - space
|
||||||
|
else
|
||||||
|
x := aRect.left + space;
|
||||||
BitBlt(aHDC, x, aRect.top + topPosition(aRect.bottom - aRect.top, checkMarkRect.bottom - checkMarkRect.top), checkMarkWidth, checkMarkHeight, hdcMem, 0, 0, SRCCOPY);
|
BitBlt(aHDC, x, aRect.top + topPosition(aRect.bottom - aRect.top, checkMarkRect.bottom - checkMarkRect.top), checkMarkWidth, checkMarkHeight, hdcMem, 0, 0, SRCCOPY);
|
||||||
SelectObject(hdcMem, oldBitmap);
|
SelectObject(hdcMem, oldBitmap);
|
||||||
DeleteObject(monoBitmap);
|
DeleteObject(monoBitmap);
|
||||||
@ -901,16 +961,12 @@ begin
|
|||||||
end;
|
end;
|
||||||
|
|
||||||
procedure DrawMenuItemText(const AMenuItem: TMenuItem; const AHDC: HDC;
|
procedure DrawMenuItemText(const AMenuItem: TMenuItem; const AHDC: HDC;
|
||||||
ARect: TRect; const ASelected, ANoAccel: boolean; ItemState: UINT);
|
ARect: TRect; const ASelected, ANoAccel: boolean; ItemState: UINT;
|
||||||
|
AvgCharWidth: Integer);
|
||||||
var
|
var
|
||||||
crText: COLORREF;
|
crText: COLORREF;
|
||||||
crBkgnd: COLORREF;
|
crBkgnd: COLORREF;
|
||||||
TmpHeight: integer;
|
|
||||||
oldFont: HFONT;
|
|
||||||
newFont: HFONT;
|
|
||||||
decoration: TCaptionFlagsSet;
|
|
||||||
shortCutText: string;
|
shortCutText: string;
|
||||||
WorkRect: Windows.RECT;
|
|
||||||
IsRightToLeft: Boolean;
|
IsRightToLeft: Boolean;
|
||||||
etoFlags: Cardinal;
|
etoFlags: Cardinal;
|
||||||
dtFlags: DWord;
|
dtFlags: DWord;
|
||||||
@ -918,23 +974,17 @@ var
|
|||||||
AnsiBuffer: ansistring;
|
AnsiBuffer: ansistring;
|
||||||
WideBuffer: widestring;
|
WideBuffer: widestring;
|
||||||
{$endif WindowsUnicodeSupport}
|
{$endif WindowsUnicodeSupport}
|
||||||
|
LeftSpace, RightSpace: Integer;
|
||||||
begin
|
begin
|
||||||
crText := TextColorMenu(ItemState, AMenuItem.IsInMenuBar, AMenuItem.Enabled);
|
crText := TextColorMenu(ItemState, AMenuItem.IsInMenuBar, AMenuItem.Enabled);
|
||||||
crBkgnd := BackgroundColorMenu(ItemState, AMenuItem.IsInMenuBar);
|
crBkgnd := BackgroundColorMenu(ItemState, AMenuItem.IsInMenuBar);
|
||||||
SetTextColor(AHDC, crText);
|
SetTextColor(AHDC, crText);
|
||||||
SetBkColor(AHDC, crBkgnd);
|
SetBkColor(AHDC, crBkgnd);
|
||||||
|
|
||||||
if AMenuItem.Default then
|
|
||||||
decoration := [cfBold]
|
|
||||||
else
|
|
||||||
decoration := [];
|
|
||||||
|
|
||||||
newFont := GetMenuItemFont(decoration);
|
|
||||||
oldFont := SelectObject(AHDC, newFont);
|
|
||||||
IsRightToLeft := AMenuItem.GetIsRightToLeft;
|
IsRightToLeft := AMenuItem.GetIsRightToLeft;
|
||||||
|
|
||||||
etoFlags := ETO_OPAQUE;
|
etoFlags := ETO_OPAQUE;
|
||||||
dtFlags := DT_EXPANDTABS;
|
// DT_LEFT is default because its value is 0
|
||||||
|
dtFlags := DT_EXPANDTABS or DT_VCENTER or DT_SINGLELINE;
|
||||||
if ANoAccel then
|
if ANoAccel then
|
||||||
dtFlags := dtFlags or DT_HIDEPREFIX;
|
dtFlags := dtFlags or DT_HIDEPREFIX;
|
||||||
if IsRightToLeft then
|
if IsRightToLeft then
|
||||||
@ -949,56 +999,62 @@ begin
|
|||||||
if AMenuItem.IsInMenuBar and not IsFlatMenus then
|
if AMenuItem.IsInMenuBar and not IsFlatMenus then
|
||||||
begin
|
begin
|
||||||
if (ItemState and ODS_SELECTED) <> 0 then
|
if (ItemState and ODS_SELECTED) <> 0 then
|
||||||
DrawEdge(AHDC, ARect, BDR_SUNKENOUTER, BF_RECT or BF_ADJUST)
|
begin
|
||||||
|
DrawEdge(AHDC, ARect, BDR_SUNKENOUTER, BF_RECT);
|
||||||
|
|
||||||
|
// Adjust caption position when menu is open.
|
||||||
|
OffsetRect(ARect, 1, 1);
|
||||||
|
end
|
||||||
else
|
else
|
||||||
if (ItemState and ODS_HOTLIGHT) <> 0 then
|
if (ItemState and ODS_HOTLIGHT) <> 0 then
|
||||||
DrawEdge(AHDC, ARect, BDR_RAISEDINNER, BF_RECT);
|
DrawEdge(AHDC, ARect, BDR_RAISEDINNER, BF_RECT);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
TmpHeight := ARect.Bottom - ARect.Top;
|
GetNonTextSpace(AMenuItem, AvgCharWidth, LeftSpace, RightSpace);
|
||||||
|
|
||||||
|
if IsRightToLeft then
|
||||||
|
begin
|
||||||
|
Dec(ARect.Right, LeftSpace);
|
||||||
|
Inc(ARect.Left, RightSpace);
|
||||||
|
end
|
||||||
|
else
|
||||||
|
begin
|
||||||
|
Inc(ARect.Left, LeftSpace);
|
||||||
|
Dec(ARect.Right, RightSpace);
|
||||||
|
end;
|
||||||
|
|
||||||
|
// Move text up by 1 pixel otherwise it is too low.
|
||||||
|
Dec(ARect.Top, 1);
|
||||||
|
Dec(ARect.Bottom, 1);
|
||||||
|
|
||||||
{$ifdef WindowsUnicodeSupport}
|
{$ifdef WindowsUnicodeSupport}
|
||||||
if UnicodeEnabledOS then
|
if UnicodeEnabledOS then
|
||||||
begin
|
begin
|
||||||
WideBuffer := UTF8ToUTF16(AMenuItem.Caption);
|
WideBuffer := UTF8ToUTF16(AMenuItem.Caption);
|
||||||
DrawTextW(AHDC, PWideChar(WideBuffer), length(WideBuffer), @WorkRect, DT_CALCRECT);
|
DrawTextW(AHDC, PWideChar(WideBuffer), Length(WideBuffer), @ARect, dtFlags);
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
begin
|
begin
|
||||||
AnsiBuffer := Utf8ToAnsi(AMenuItem.Caption);
|
AnsiBuffer := Utf8ToAnsi(AMenuItem.Caption);
|
||||||
DrawText(AHDC, PChar(AnsiBuffer), length(AnsiBuffer), @WorkRect, DT_CALCRECT);
|
|
||||||
end;
|
|
||||||
{$else}
|
|
||||||
DrawText(AHDC, PChar(AMenuItem.Caption), length(AMenuItem.Caption), @WorkRect, DT_CALCRECT);
|
|
||||||
{$endif}
|
|
||||||
|
|
||||||
if IsRightToLeft then
|
|
||||||
Dec(ARect.Right, LeftCaptionPosition(AMenuItem))
|
|
||||||
else
|
|
||||||
Inc(ARect.Left, LeftCaptionPosition(AMenuItem));
|
|
||||||
Inc(ARect.Top, TopPosition(TmpHeight, WorkRect.Bottom - WorkRect.Top));
|
|
||||||
|
|
||||||
{$ifdef WindowsUnicodeSupport}
|
|
||||||
if UnicodeEnabledOS then
|
|
||||||
DrawTextW(AHDC, PWideChar(WideBuffer), Length(WideBuffer), @ARect, dtFlags)
|
|
||||||
else
|
|
||||||
DrawText(AHDC, PChar(AnsiBuffer), Length(AnsiBuffer), @ARect, dtFlags);
|
DrawText(AHDC, PChar(AnsiBuffer), Length(AnsiBuffer), @ARect, dtFlags);
|
||||||
|
end;
|
||||||
{$else}
|
{$else}
|
||||||
DrawText(AHDC, PChar(AMenuItem.Caption), Length(AMenuItem.Caption), @ARect, dtFlags);
|
DrawText(AHDC, PChar(AMenuItem.Caption), Length(AMenuItem.Caption), @ARect, dtFlags);
|
||||||
{$endif}
|
{$endif}
|
||||||
|
|
||||||
if AMenuItem.ShortCut <> scNone then
|
if AMenuItem.ShortCut <> scNone then
|
||||||
begin
|
begin
|
||||||
|
dtFlags := DT_VCENTER or DT_SINGLELINE;
|
||||||
shortCutText := MenuItemShortCut(AMenuItem);
|
shortCutText := MenuItemShortCut(AMenuItem);
|
||||||
if IsRightToLeft then
|
if IsRightToLeft then
|
||||||
begin
|
begin
|
||||||
Inc(ARect.Left, GetSystemMetrics(SM_CXMENUCHECK));
|
Inc(ARect.Left, GetSystemMetrics(SM_CXMENUCHECK));
|
||||||
dtFlags := DT_LEFT;
|
dtFlags := dtFlags or DT_LEFT;
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
begin
|
begin
|
||||||
Dec(ARect.Right, GetSystemMetrics(SM_CXMENUCHECK));
|
Dec(ARect.Right, GetSystemMetrics(SM_CXMENUCHECK));
|
||||||
dtFlags := DT_RIGHT;
|
dtFlags := dtFlags or DT_RIGHT;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
{$ifdef WindowsUnicodeSupport}
|
{$ifdef WindowsUnicodeSupport}
|
||||||
@ -1016,8 +1072,6 @@ begin
|
|||||||
DrawText(AHDC, PChar(shortCutText), Length(shortCutText), @ARect, dtFlags);
|
DrawText(AHDC, PChar(shortCutText), Length(shortCutText), @ARect, dtFlags);
|
||||||
{$endif}
|
{$endif}
|
||||||
end;
|
end;
|
||||||
SelectObject(AHDC, oldFont);
|
|
||||||
DeleteObject(newFont);
|
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure DrawMenuItemIcon(const AMenuItem: TMenuItem; const AHDC: HDC;
|
procedure DrawMenuItemIcon(const AMenuItem: TMenuItem; const AHDC: HDC;
|
||||||
@ -1063,14 +1117,31 @@ procedure DrawClassicMenuItemIcon(const AMenuItem: TMenuItem; const AHDC: HDC;
|
|||||||
const ARect: TRect; const ASelected, AChecked: boolean);
|
const ARect: TRect; const ASelected, AChecked: boolean);
|
||||||
var
|
var
|
||||||
x: Integer;
|
x: Integer;
|
||||||
|
Space: Integer = SpaceNextToCheckMark;
|
||||||
ImageRect: TRect;
|
ImageRect: TRect;
|
||||||
IconSize: TPoint;
|
IconSize: TPoint;
|
||||||
|
checkMarkWidth: integer;
|
||||||
begin
|
begin
|
||||||
IconSize := AMenuItem.GetIconSize;
|
IconSize := AMenuItem.GetIconSize;
|
||||||
if AMenuItem.GetIsRightToLeft then
|
checkMarkWidth := GetSystemMetrics(SM_CXMENUCHECK);
|
||||||
x := ARect.Right - IconSize.x - spaceBetweenIcons
|
if not AMenuItem.IsInMenuBar then
|
||||||
|
begin
|
||||||
|
if IconSize.x < checkMarkWidth then
|
||||||
|
begin
|
||||||
|
// Center the icon horizontally inside check mark space.
|
||||||
|
Inc(Space, TopPosition(checkMarkWidth, IconSize.x));
|
||||||
|
end
|
||||||
else
|
else
|
||||||
x := ARect.Left + spaceBetweenIcons;
|
if IconSize.x > checkMarkWidth then
|
||||||
|
begin
|
||||||
|
Space := SpaceNextToIcon;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
if AMenuItem.GetIsRightToLeft then
|
||||||
|
x := ARect.Right - IconSize.x - Space
|
||||||
|
else
|
||||||
|
x := ARect.Left + Space;
|
||||||
|
|
||||||
ImageRect := Rect(x, ARect.top + TopPosition(ARect.Bottom - ARect.Top, IconSize.y),
|
ImageRect := Rect(x, ARect.top + TopPosition(ARect.Bottom - ARect.Top, IconSize.y),
|
||||||
IconSize.x, IconSize.y);
|
IconSize.x, IconSize.y);
|
||||||
@ -1085,6 +1156,36 @@ begin
|
|||||||
DrawMenuItemIcon(AMenuItem, AHDC, ImageRect, ASelected);
|
DrawMenuItemIcon(AMenuItem, AHDC, ImageRect, ASelected);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
procedure DrawClassicMenuItem(const AMenuItem: TMenuItem; const AHDC: HDC;
|
||||||
|
const ARect: Windows.RECT; const ASelected, ANoAccel: boolean; ItemState: UINT);
|
||||||
|
var
|
||||||
|
oldFont: HFONT;
|
||||||
|
newFont: HFONT;
|
||||||
|
AvgCharWidth: Integer;
|
||||||
|
begin
|
||||||
|
if AMenuItem.IsLine then
|
||||||
|
DrawSeparator(AHDC, ARect)
|
||||||
|
else
|
||||||
|
begin
|
||||||
|
if AMenuItem.Default then
|
||||||
|
newFont := GetMenuItemFont([cfBold])
|
||||||
|
else
|
||||||
|
newFont := GetMenuItemFont([]);
|
||||||
|
oldFont := SelectObject(AHDC, newFont);
|
||||||
|
AvgCharWidth := GetAverageCharSize(AHDC).cx;
|
||||||
|
|
||||||
|
DrawMenuItemText(AMenuItem, AHDC, ARect, ASelected, ANoAccel, ItemState, AvgCharWidth);
|
||||||
|
if aMenuItem.HasIcon then
|
||||||
|
DrawClassicMenuItemIcon(AMenuItem, AHDC, ARect, ASelected, AMenuItem.Checked)
|
||||||
|
else
|
||||||
|
if AMenuItem.Checked then
|
||||||
|
DrawMenuItemCheckMark(AMenuItem, AHDC, ARect, ASelected, AvgCharWidth);
|
||||||
|
|
||||||
|
SelectObject(AHDC, oldFont);
|
||||||
|
DeleteObject(newFont);
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
procedure DrawMenuItem(const AMenuItem: TMenuItem; const AHDC: HDC; const ARect: Windows.RECT; const ItemAction, ItemState: UINT);
|
procedure DrawMenuItem(const AMenuItem: TMenuItem; const AHDC: HDC; const ARect: Windows.RECT; const ItemAction, ItemState: UINT);
|
||||||
var
|
var
|
||||||
ASelected, ANoAccel: Boolean;
|
ASelected, ANoAccel: Boolean;
|
||||||
@ -1104,20 +1205,9 @@ begin
|
|||||||
DrawVistaMenuBar(AMenuItem, AHDC, ARect, ASelected, ANoAccel, ItemAction, ItemState)
|
DrawVistaMenuBar(AMenuItem, AHDC, ARect, ASelected, ANoAccel, ItemAction, ItemState)
|
||||||
else
|
else
|
||||||
DrawVistaPopupMenu(AMenuItem, AHDC, ARect, ASelected, ANoAccel);
|
DrawVistaPopupMenu(AMenuItem, AHDC, ARect, ASelected, ANoAccel);
|
||||||
Exit;
|
end
|
||||||
end;
|
|
||||||
|
|
||||||
if aMenuItem.IsLine then
|
|
||||||
DrawSeparator(AHDC, ARect)
|
|
||||||
else
|
else
|
||||||
begin
|
DrawClassicMenuItem(AMenuItem, AHDC, ARect, ASelected, ANoAccel, ItemState);
|
||||||
DrawMenuItemText(AMenuItem, AHDC, ARect, ASelected, ANoAccel, ItemState);
|
|
||||||
if aMenuItem.HasIcon then
|
|
||||||
DrawClassicMenuItemIcon(AMenuItem, AHDC, ARect, ASelected, AMenuItem.Checked)
|
|
||||||
else
|
|
||||||
if AMenuItem.Checked then
|
|
||||||
DrawMenuItemCheckMark(AMenuItem, AHDC, ARect, ASelected);
|
|
||||||
end;
|
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TriggerFormUpdate(const AMenuItem: TMenuItem);
|
procedure TriggerFormUpdate(const AMenuItem: TMenuItem);
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user