【问题标题】:Where is the 'EnablePinning' property in the ribbon framework's recent items?功能区框架的最近项目中的“EnablePinning”属性在哪里?
【发布时间】:2023-10-22 02:07:01
【问题描述】:

Windows 功能区框架标记支持应用程序菜单中最近项目菜单的 EnablePinning 属性:

<ApplicationMenu.RecentItems>
  <RecentItems CommandName="MRU" EnablePinning="true" />
</ApplicationMenu.RecentItems>

我预计会有一个可以在运行时查询/更新的匹配属性,但我找不到属性键。有谁知道有没有,如果有,是什么?

或者,是否有另一种方法可以在运行时打开/关闭固定?元素和它的父元素都不支持应用模式。

TIA

澄清:我要做的是在运行时启用/禁用整个菜单的固定。我不关心单个项目的引脚状态。

【问题讨论】:

    标签: windows winapi ribbon recent-file-list windows-ribbon-framework


    【解决方案1】:

    我不确定您是否可以从现有条目修改固定状态,但绝对可以使用 UI_PKEY_Pinned 属性以编程方式查询状态并添加具有特定状态的新项目: https://msdn.microsoft.com/en-us/library/windows/desktop/dd940401(v=vs.85).aspx

    Windows Ribbon Framework for DelphiWindows Ribbon for WinForms (.NET) 等包装器提供了对 API 模型的轻松访问。 This CodeProject 文章还介绍了如何使用 C# 查询/添加最近的项目。

    如果您想在运行时更改状态,例如,您可以查询所有项目的状态,从列表中删除它们,调整您需要的任何内容,然后再次将它们添加到列表中。还没有这样做,不过值得一试。

    【讨论】:

    • 对不起,我想我的问题不够清楚。我需要做的是启用/禁用整个菜单的固定。相当于在标记中从“EnablePinning=true”切换到“EnablePinning=false”(反之亦然),但在运行时。我不关心单个项目的引脚状态。我正在尝试启用或禁用用户固定项目的能力。
    【解决方案2】:

    嗯...这将很难完成,因为标志是在 XML 中定义的,它将被编译成链接到应用程序的资源文件,然后在启动时加载。如果您想禁用/启用标记,您可以创建另一个资源定义并重新加载功能区,但这会带来很多开销,并且从用户的角度来看肯定是显而易见的,因为它需要创建新的窗口句柄。

    【讨论】:

    • 我希望有一个运行时可访问的属性,就像许多其他命令属性一样。但是好像一个也没有。谢谢。
    【解决方案3】:

    我将最近的项目放在 UpdateProperty 中

      TRecentItem = class(TInterfacedObject, IUISimplePropertySet)
        private
          FRecentFile: TSSettings.TRecentFile;
        protected
          function GetValue(const key: TUIPropertyKey; out value: TPropVariant): HRESULT; stdcall;
        public
          procedure Initialize(const RecentFile: TSSettings.TRecentFile); safecall;
        end;
    
    function TMyForm.UpdateProperty(commandId: UInt32; const key: TUIPropertyKey;
      currentValue: PPropVariant; out newValue: TPropVariant): HRESULT;
    var
      I: Integer;
      psa: PSafeArray;
      pv: Pointer;
      RecentItem: TRecentItem;
    begin
      if (key = UI_PKEY_RecentItems) then
      begin
        psa := SafeArrayCreateVector(VT_UNKNOWN, 0, Settings.RecentFiles.Count);
    
        if (not Assigned(psa)) then
          Result := E_FAIL
        else
        begin
          for I := 0 to Settings.RecentFiles.Count - 1 do
          begin
            RecentItem := TRecentItem.NewInstance() as TRecentItem;
            RecentItem.Initialize(Settings.RecentFiles[I]);
            pv := Pointer(IUnknown(RecentItem));
            Check(SafeArrayPutElement(psa, I, pv^));
          end;
    
          Result := UIInitPropertyFromIUnknownArray(UI_PKEY_RecentItems, psa, PropVar);
    
          SafeArrayDestroy(psa);
        end;
      end;
    

    如果更改了 pin,我会在关闭应用程序菜单时收到此命令:

    function TMyForm.Execute(commandId: UInt32; verb: _UIExecutionVerb;
      key: PUIPropertyKey; currentValue: PPropVariant;
      commandExecutionProperties: IUISimplePropertySet): HRESULT; stdcall;
    var
      Count: Integer;
      I: Integer;
      Pinned: Boolean;
      psa: PSafeArray;
      pv: IUnknown;
      RecentFile: UInt32;
      SimplePropertySet: IUISimplePropertySet;
      Value: TPropVariant;
    begin
      if ((commandId = cmdAppRecentItems)
        and Assigned(key) and (key^ = UI_PKEY_RecentItems)
        and Assigned(currentValue) and (currentValue^.vt = VT_ARRAY + VT_UNKNOWN)) then
      begin
        psa := nil;
        Result := UIPropertyToIUnknownArrayAlloc(key^, currentValue^, psa);
        if (Succeeded(Result)) then
        begin
          Result := SafeArrayGetUBound(psa, 1, Count);
          for I := 0 to Count do
            if (Succeeded(Result)) then
            begin
              Result := SafeArrayGetElement(psa, I, pv);
              if (Succeeded(Result) and Assigned(pv)) then
              begin
                Result := pv.QueryInterface(IUISimplePropertySet, SimplePropertySet);
                if (Succeeded(Result)) then
                  Result := SimplePropertySet.GetValue(UI_PKEY_Pinned, Value);
                if (Succeeded(Result)) then
                  Result := UIPropertyToBoolean(UI_PKEY_Pinned, Value, Pinned);
                if (Succeeded(Result)) then
                  Settings.RecentFiles.SetPinned(I, Pinned);
              end;
            end;
          SafeArrayDestroy(psa);
        end;
      end
    end;
    

    ...但我没有找到此解决方案的文档。

    【讨论】: