Создание приложений в стиле ленты
Используя стандартные компоненты Delphi TRibbon, я заметил, что они не такие блестящие.
Во-первых, они не выглядят так же хорошо, как Microsoft, например, эффекты свечения и цвета в TRibbon не выглядят такими же впечатляющими, как те, что используются в Wordpad или Paint в Windows 7.
Во-вторых, если вы хотите создать интерфейсы в стиле ленты, я заметил, что не существует меню в стиле ленты или всплывающих меню, независимых от TRibbon. Для реальной ленты есть, но если, скажем, в целях обеспечения непрерывности вы хотели, чтобы всплывающие меню стиля ленты, например, присваивались TListbox или TListView, то, похоже, их нет.
В-третьих, иногда, когда действие ленты отключено, оно по-прежнему показывает эффект "Горячее свечение", как если бы оно висело над действием, даже если оно отключено.
Наконец, мне очень неловко пытаться поместить в контейнер компоненты контейнера, такие как TCombobox. Это действительно неловко, размер элементов управления и положение и т. Д.
Я предполагаю, что моя точка зрения состоит в том, что использование стандартных компонентов Delphi TRibbon, похоже, не лучший подход как визуально, так и практично. Как сделать так, чтобы приложение в стиле ленты выглядело и работало так же аккуратно, как и приложения Microsoft, как я говорил ранее, как Wordpad и Paint в Windows 7?
Посмотрите на этот сравнительный скриншот, чтобы получить лучшее представление:
Лента Дельфи кажется неполной, если я не ожидаю слишком многого. Я полагал, что ленточные компоненты должны предоставить вашему приложению лучший опыт для конечного пользователя, как визуально, так и лучшее рабочее пространство и т. Д.
Какие предложения вы могли бы дать, чтобы улучшить или заставить TRibbon работать и выглядеть как предложения Microsoft?
Я не использую Ribbon Style Interfaces все время, поэтому я не хочу покупать сторонние компоненты. Я смотрел на TMS и DevExpress, но по цене они тоже выглядят не так хорошо. TMS выглядят хуже, чем стандартный Delphi TRibbon.
3 ответа
Для естественного внешнего вида, проверьте Windows Ribbon Framework для Delphi.
Это оболочка с открытым исходным кодом для Windows Ribbon Framework, доступная начиная с Windows 7 (и Vista после установки какого-либо официального обновления). Это API, используемый Windows 7 Word Pad.
Также обратите внимание, что у вас есть два типа макетов: Office 2007 и Office 2010. Лента Delphi VCL реализует стиль Office 2007, тогда как Windows Seven WordPad использует стиль Office 2010.
В некоторых наших проектах для некоторых клиентов мы использовали программные компоненты ленты TMS. Код немного слишком большой (много дубликатов или плохо написанных вещей, таких как постоянство компонентов), но он работает и хорошо воспроизводится, поддерживая стили ленты 2007 и 2010 годов. Для наших клиентов рендеринг был тем, что имело значение. Для нашей среды с открытым исходным кодом мы опубликовали двойное решение для создания ленточного графического интерфейса, сгенерированного из кода: в нем будут использоваться либо стандартные компоненты VCL для базовой компоновки, либо компоненты TMS для полной визуализации Office 2007/2010. Мы только что определили некоторые классы, реализованные любой из библиотек. Если вы используете универсальные компоненты, как определено в SQLite3ToolBar (то есть TSynForm, TSynToolBar, TSynToolButton, TSynPopupMenu, TSynPage, TSynPager, TSynBodyPager
а также TSynBodyPage
классы) и SynTaskDialog (для TSynButton
) в вашем собственном коде условие USETMSPACK сделает всю магию за вас.
Мы еще не использовали компонент Ribbon, как он был представлен в Delphi 2009. Его дизайн, ориентированный на действия, не позволит легко взаимодействовать с управляемым событиями дизайном обработки нашего пользовательского интерфейса, и мы должны признать, что этот компонент имеет довольно плохая репутация (по крайней мере, в версии Delphi 2009).
Отличная Windows Ribbon Framework для Delphi не будет соответствовать нашей потребности в сгенерированной на лету ленте из кода. Его дизайн, от самой реализации Microsoft, заключается в создании пользовательского интерфейса из XML-ресурса, связанного при компиляции... так что он не будет соответствовать нашим потребностям, но, вероятно, соответствует вашим, для более "статического" дизайна пользовательского интерфейса приложения.
Если вы используете Office-подобную ленту в своем приложении, помните о лицензировании пользовательского интерфейса Office.
Я использую Windows Ribbon Framework - нативный компонент, который поставляется с Windows (7).
Вот очень короткий учебник по Windows Ribbon Framework от Delphi; скопируйте и вставьте важные части кода без особых объяснений:
procedure TfrmTicketDetail.ShowScenicRibbon;
begin
try
Fframework := UIRibbon.CoUIRibbonFramework.Create;
Fframework.Initialize(Self.Handle, Self); //Give the ribbon the hwnd, and our implementation of uiapplication for callbacks
OleCheck(Fframework.LoadUI(hInstance, 'APPLICATION_RIBBON'));
except
on e:Exception do
begin
if DebugHook > 0 then
raise;
Exit;
end;
end;
end;
Но это начинает становиться волосатым, так как вы должны следовать API Microsoft.
{IUIApplication}
function OnViewChanged(viewId: SYSUINT; typeID: UI_VIEWTYPE; const view: IUnknown;
verb: UI_VIEWVERB; uReasonCode: SYSINT): HResult; stdcall;
function OnCreateUICommand(commandId: SYSUINT; typeID: UI_COMMANDTYPE;
out commandHandler: IUICommandHandler): HResult; stdcall;
function OnDestroyUICommand(commandId: SYSUINT; typeID: UI_COMMANDTYPE;
const commandHandler: IUICommandHandler): HResult; stdcall;
И тогда вы должны их реализовать:
function TfrmTicketDetail.OnViewChanged(viewId: SYSUINT;
typeID: UI_VIEWTYPE; const view: IUnknown; verb: UI_VIEWVERB;
uReasonCode: SYSINT): HResult;
var
cy: integer;
begin
Result := S_OK;
//viewID: The ID for the view. Only a value of zero is valid.
if viewID <> 0 then
Exit;
//typeID: The only declared typeID is UI_VIEWTYPE_RIBBON
if typeID <> UI_VIEWTYPE_RIBBON then
Exit;
case verb of //there are only 4 verbs: create, destroy, size, error
UI_VIEWVERB_CREATE:
begin
{ The view was resized.
In the case of the Ribbon view, the application should call
GetHeight() to determine the height of the Ribbon.}
(view as IUIRibbon).GetHeight(cy);
bvTopSpacer.Height := cy;
end;
UI_VIEWVERB_SIZE:
begin
{ The view was resized.
In the case of the Ribbon view, the application should call
GetHeight() to determine the height of the Ribbon.}
(view as IUIRibbon).GetHeight(cy);
bvTopSpacer.Height := cy;
end;
UI_VIEWVERB_DESTROY: {nop};
UI_VIEWVERB_ERROR: {nop};
end;
Result := S_OK;
end;
function TfrmTicketDetail.OnCreateUICommand(commandId: SYSUINT;
typeID: UI_COMMANDTYPE; out commandHandler: IUICommandHandler): HResult;
begin
commandHandler := Self; //this form will handle all commands on the ribbon;
Result := S_OK;
end;
function TfrmTicketDetail.OnDestroyUICommand(commandId: SYSUINT; typeID: UI_COMMANDTYPE;
const commandHandler: IUICommandHandler): HResult;
begin
Result := E_NOTIMPL;
end;
И тогда вы также должны
- воплощать в жизнь
IUICommandHandler
- создать XML-файл ленты
- скомпилируйте XML-файл ленты с помощью компилятора ленты
включите скомпилированную ленту в качестве ресурса:
{$RESOURCE '..\Resource\UIRibbon\Ribbon_frmTicketDetails.res'}
Вот дамп ленты XML, которую я имею для своего приложения:
<?xml version="1.0" encoding="utf-8"?>
<Application xmlns="http://schemas.microsoft.com/windows/2009/Ribbon">
<!-- Commands are like actions, with a name, a numeric ID, caption (LabelTitle), Large and Small images, etc -->
<Application.Commands>
<Command Name="cmdNew" Id="0xE100" Symbol="ID_CMD_NEW" LabelTitle="New document" />
<Command Name="cmdSaveAs" Id="0xE102" Symbol="ID_CMD_SAVEAS" LabelTitle="Save as" />
<Command Name="cmdOpen" Id="0xE103" Symbol="ID_CMD_OPEN" LabelTitle="Open" />
<Command Name="cmdExit" Id="0xE104" Symbol="ID_CMD_EXIT" LabelTitle="Exit" />
<Command Name="cmdUndo" Id="0xE105" Symbol="ID_CMD_UNDO" LabelTitle="Undo" />
<Command Name="cmdCut" Id="0xE110" Symbol="ID_CMD_CUT" LabelTitle="Cut" />
<Command Name="cmdCopy" Id="0xE111" Symbol="ID_CMD_COPY" LabelTitle="Copy" />
<Command Name="cmdPaste" Id="0xE112" Symbol="ID_CMD_PASTE" LabelTitle="Paste" />
<Command Name="cmdDelete" Id="0xE113" Symbol="ID_CMD_DELETE" LabelTitle="Delete" />
<Command Name="cmdZoom" Id="0xE114" Symbol="ID_CMD_ZOOM" LabelTitle="Zoom" />
<Command Name="tabHome" LabelTitle="Home" />
<Command Name="grpActions" LabelTitle="Actions" />
<Command Name="cmdSaveAndClose" Id="1101" Symbol="ID_ACTION_SAVEANDCLOSE" LabelTitle="Save and Close">
<Command.TooltipTitle>Save and Close (Alt+S)</Command.TooltipTitle>
<Command.TooltipDescription>Saves the current ticket and closes the detail screen.</Command.TooltipDescription>
<Command.LargeImages>
<Image Source="SaveAndClose.bmp" />
</Command.LargeImages>
</Command>
<Command Name="cmdBack" Id="1102" LabelTitle="Back" />
<Command Name="cmdControlPanel" Id="1103" LabelTitle="Control Panel" />
<Command Name="cmdSave" Id="1104" LabelTitle="Save" />
<Command Name="grpShow" Id="1201" LabelTitle="Show" />
<Command Name="cmdShowTicket" Id="1202" LabelTitle="Ticket" ></Command>
<Command Name="cmdShowDiaryEntries" Id="1203" LabelTitle="Diary Entries" >
<Command.LargeImages>
<Image Source="PencilLog_32x32.bmp" />
</Command.LargeImages>
</Command>
<Command Name="cmdShowAttachments" Id="1204" LabelTitle="Attachments" />
<Command Name="cmdShowAuditLog" Id="1205" LabelTitle="Audit Log" />
<Command Name="cmdShowAdditional" Id="1206" LabelTitle="Additional" />
<Command Name="grpActivity" LabelTitle="Activity" />
<Command Name="cmdStartWorking" Id="1301" LabelTitle="Start Working"></Command>
<Command Name="cmdStopWorking" Id="1302" LabelTitle="Stop Working"></Command>
<Command Name="cmdPrint" Id="1303" LabelTitle="Print" >
<Command.LargeImages>
<Image Source="Printer - 256x256.bmp" />
</Command.LargeImages>
<Command.SmallImages>
<Image Source="Printer_16x16.bmp" />
</Command.SmallImages>
</Command>
<Command Name="cmdDuplicateTicket" Id="1304" LabelTitle="Duplicate Ticket" >
<Command.SmallImages>
<Image Source="DuplicateTicket16.bmp" />
</Command.SmallImages>
</Command>
<Command Name="grpTicketStatus" LabelTitle="Ticket Status" />
<Command Name="cmdCloseTicket" Id="1402" LabelTitle="Close Ticket" />
<Command Name="cmdOnHold" Id="1403" LabelTitle="On Hold" />
<Command Name="cmdReadyForInstall" Id="1404" LabelTitle="Ready for install" />
<Command Name="cmdReopenTicket" Id="1405" LabelTitle="Reopen Ticket" />
</Application.Commands>
<!-- Above is all the commands (i.e. Actions). Now we get to the tool on screen (i.e. a DFM) -->
<Application.Views>
<Ribbon>
<!-- Items that appear under the "round button" menu -->
<Ribbon.ApplicationMenu>
<ApplicationMenu CommandName="cmdFileMenu">
<MenuGroup>
<Button CommandName="cmdNew" />
<Button CommandName="cmdOpen" />
<Button CommandName="cmdSave" />
<Button CommandName="cmdSaveAs" />
</MenuGroup>
<MenuGroup>
<Button CommandName="cmdExit" />
</MenuGroup>
</ApplicationMenu>
</Ribbon.ApplicationMenu>
<!--What commands to add to the quick access toolbar
Right now only Save and Undo, just for fun-->
<Ribbon.QuickAccessToolbar>
<QuickAccessToolbar>
<QuickAccessToolbar.ApplicationDefaults>
<Button CommandName="cmdSave" />
<Button CommandName="cmdUndo" />
</QuickAccessToolbar.ApplicationDefaults>
</QuickAccessToolbar>
</Ribbon.QuickAccessToolbar>
<!-- And now finally the actual tabs -->
<Ribbon.Tabs>
<!--Our one and only tab is "Home" -->
<Tab CommandName="tabHome">
<Tab.ScalingPolicy>
<ScalingPolicy>
<ScalingPolicy.IdealSizes>
<Scale Group="grpActions" Size="Medium"/>
<Scale Group="grpShow" Size="Medium"/>
<Scale Group="grpActivity" Size="Medium"/>
<Scale Group="grpTicketStatus" Size="Medium"/>
</ScalingPolicy.IdealSizes>
<Scale Group="grpActions" Size="Small"/>
<Scale Group="grpShow" Size="Small"/>
<Scale Group="grpActivity" Size="Small"/>
<Scale Group="grpTicketStatus" Size="Small"/>
</ScalingPolicy>
</Tab.ScalingPolicy>
<!-- Home\Actions -->
<Group CommandName="grpActions" SizeDefinition="FourButtons">
<Button CommandName="cmdSaveAndClose" />
<Button CommandName="cmdBack" />
<Button CommandName="cmdControlPanel" />
<Button CommandName="cmdSave" />
</Group>
<!-- Home\Show group -->
<Group CommandName="grpShow" SizeDefinition="FiveButtons">
<ToggleButton CommandName="cmdShowTicket" />
<ToggleButton CommandName="cmdShowDiaryEntries" />
<ToggleButton CommandName="cmdShowAttachments" />
<ToggleButton CommandName="cmdShowAuditLog" />
<ToggleButton CommandName="cmdShowAdditional" />
</Group>
<!-- Home\Activity group, with a custom sizing definition
so i get my "FourButtons-TwoBigTwoSmall" look -->
<Group CommandName="grpActivity" >
<SizeDefinition>
<ControlNameMap>
<ControlNameDefinition Name="button1"/>
<ControlNameDefinition Name="button2"/>
<ControlNameDefinition Name="button3"/>
<ControlNameDefinition Name="button4"/>
</ControlNameMap>
<GroupSizeDefinition Size="Large">
<ControlSizeDefinition ControlName="button1" ImageSize="Large" IsLabelVisible="true" />
<ControlSizeDefinition ControlName="button2" ImageSize="Large" IsLabelVisible="true" />
<ColumnBreak ShowSeparator="true"/>
<ControlSizeDefinition ControlName="button3" ImageSize="Large" IsLabelVisible="true" />
<ControlSizeDefinition ControlName="button4" ImageSize="Large" IsLabelVisible="true" />
</GroupSizeDefinition>
<GroupSizeDefinition Size="Medium">
<ControlSizeDefinition ControlName="button1" ImageSize="Large" IsLabelVisible="true" />
<ControlSizeDefinition ControlName="button2" ImageSize="Large" IsLabelVisible="true" />
<ColumnBreak ShowSeparator="true"/>
<Row>
<ControlSizeDefinition ControlName="button3" ImageSize="Small" IsLabelVisible="true" />
</Row>
<Row>
<ControlSizeDefinition ControlName="button4" ImageSize="Small" IsLabelVisible="true" />
</Row>
</GroupSizeDefinition>
<GroupSizeDefinition Size="Small">
<Row>
<ControlSizeDefinition ControlName="button1" ImageSize="Small" IsLabelVisible="true" />
<ControlSizeDefinition ControlName="button3" ImageSize="Small" IsLabelVisible="false" />
</Row>
<Row>
<ControlSizeDefinition ControlName="button2" ImageSize="Small" IsLabelVisible="true" />
<ControlSizeDefinition ControlName="button4" ImageSize="Small" IsLabelVisible="false" />
</Row>
</GroupSizeDefinition>
</SizeDefinition>
<Button CommandName="cmdStartWorking" />
<Button CommandName="cmdStopWorking" />
<Button CommandName="cmdPrint" />
<Button CommandName="cmdDuplicateTicket" />
</Group>
<!-- Home\Ticket Status group -->
<Group CommandName="grpTicketStatus" SizeDefinition="FourButtons">
<Button CommandName="cmdCloseTicket" />
<Button CommandName="cmdOnHold" />
<Button CommandName="cmdReadyForInstall" />
<Button CommandName="cmdReopenTicket" />
</Group>
</Tab>
</Ribbon.Tabs>
<!-- End of the actual tabs -->
</Ribbon>
</Application.Views>
</Application>
Прагматичный ответ - использовать другой набор компонентов. Версия программного обеспечения TMS кажется хорошей, но я использую DevExpress ExpressBars, которая работает очень хорошо для меня.