代码之家  ›  专栏  ›  技术社区  ›  Andreas Rejbrand

从Delphi调用shgetsetsettings

  •  3
  • Andreas Rejbrand  · 技术社区  · 14 年前

    我刚读 this question this question 从那以后我一直在打电话 SHGetSetSettings 在Delphi中。这是 shell32.dll ,但未在中定义 ShlObj.pas 所以我们需要写下自己的定义。

    首先我们需要翻译 SHELLSTATE 结构。现在我在C方面的经验有限,但我认为“:1”意味着结构的成员是一个位,也就是说,其中八个可以打包成一个字节。我也认为 DWORD = UINT =32位无符号整数 LONG = int 是32位有符号整数。但是我们有一个问题:整个结构将占用228位,或者28.5字节,这就是…相当不可能,至少在德尔福 sizeof(SomeRecord) 必须是整数。

    然而,我试图通过在末尾添加四个虚拟位来解决这个问题。232位=29字节,很好。

    于是我尝试

    PShellState = ^TShellState;
    TShellState = packed record
      Data1: cardinal;
      Data2: cardinal;
      Data3: cardinal;
      Data4: cardinal;
      Data5: cardinal;
      Data6: cardinal;
      Data7: cardinal;
      Data8: byte; // Actually a nibble would be sufficient
    end;
    

    然后我宣布(为了以后的方便)

    const
      fShowAllObjects = 1;
      fShowExtensions = 2;
      fNoConfirmRecycle = 4;
      fShowSysFiles = 8;
      fShowCompColor = 16;
      fDoubleClickInWebView = 32;
      fDesktopHTML = 64;
      fWin95Classic = 128;
      fDontPrettyPath = 256;
      fShowAttribCol = 512;
      fMapNetDrvButton = 1024;
      fShowInfoTip = 2048;
      fHideIcons = 4096;
      fWebView = 8192;
      fFilter = 16384;
      fShowSuperHidden = 32768;
      fNoNetCrawling = 65536;
    

    现在我已经准备好定义

    interface
      procedure SHGetSetSettings(var ShellState: TShellState; Mask: cardinal; DoSet: boolean); stdcall;
    
    implementation
      procedure SHGetSetSettings; external shell32 name 'SHGetSetSettings';
    

    但是在我尝试代码之前,我注意到一些非常奇怪的事情。我发现我声明的常量已经在这里声明了: SSF Constants . 注意到 SSF_HIDEICONS = 0x00004000 = 16384 ≠ fHideIcons = 4096 . 如果 SSF_ 常量实际上是与 贝壳状的 ,那么定义 SSF_HIDEICONS 当它是结构中的第13位(并且其掩码应该是2^12)时为2^14。因此,似乎两个msdn参考页相互矛盾。

    有人能把这一切解释清楚一点吗?

    5 回复  |  直到 13 年前
        1
  •  3
  •   Bob Moore    14 年前

    我在这里读到的帮助是在检索数据时为掩码指定ssf_u常量。他们没有必要映射到shellstate结构中的位。

    如果他们做了fshowsysfiles将映射到8(0x04),并且我们从帮助中知道ssf_showsysfiles是0x20。没有直接映射。

        2
  •  2
  •   Francesca    14 年前

    很遗憾,shlobj.pas中shellstate的d2010声明不正确,但第一组位(17)与 Data: DWORD; (你的确实没问题)。 它们中可能有18或19个都是一样的。然后,我们应该为2 win95未使用的多获得2个dword/uint,而不仅仅是数据2。

    太糟糕了,因为ssf标志和shgetsetings声明已经在其中完成并正确。

    根据msdn的正确声明应为imo:

      tagSHELLSTATEW = record
        Data: DWORD;
    {   fShowAllObjects: BOOL:1;
        fShowExtensions: BOOL:1;
        fNoConfirmRecycle: BOOL:1;
        fShowSysFiles: BOOL:1;
        fShowCompColor: BOOL:1;
        fDoubleClickInWebView: BOOL:1;
        fDesktopHTML: BOOL:1;
        fWin95Classic: BOOL:1;
        fDontPrettyPath: BOOL:1;
        fShowAttribCol: BOOL:1;
        fMapNetDrvBtn: BOOL:1;
        fShowInfoTip: BOOL:1;
        fHideIcons: BOOL:1;
        fWebView: BOOL:1;
        fFilter: BOOL:1;
        fShowSuperHidden: BOOL:1;
        fNoNetCrawling: BOOL:1;}
    
        dwWin95Unused: DWORD;// Win95 only - no longer supported pszHiddenFileExts
        uWin95Unused: UINT; // Win95 only - no longer supported cbHiddenFileExts
    
        // Note: Not a typo!  This is a persisted structure so we cannot use LPARAM
        lParamSort: Integer;
        iSortDirection: Integer;
        version: UINT;
    
        // new for win2k. need notUsed var to calc the right size of ie4 struct
        // FIELD_OFFSET does not work on bit fields
        uNotUsed: UINT;// feel free to rename and use}
    
        Data2: DWORD;
    {   fSepProcess: BOOL:1;
    
        // new for Whistler.
        fStartPanelOn: BOOL:1;
        fShowStartPage: BOOL:1;
    
        // new for Windows Vista
        fAutoCheckSelect: BOOL:1;
        fIconsOnly: BOOL:1;
        fShowTypeOverlay: BOOL:1;
    
        // If you need a new flag, steal a bit from from fSpareFlags.
        // Also, keep SHELLFLAGSTATE and SHGetSettings in sync when adding new flags.
        fSpareFlag: UINT:13;}
      end;
    

    您可以通过以下方式验证这是否允许正确获取排序属性:

    var
      lpss: tagSHELLSTATEW;
    begin
      ZeroMemory(@lpss, SizeOf(lpss));
      SHGetSetSettings(lpss, SSF_SORTCOLUMNS, False);
    
        3
  •  1
  •   Alex    14 年前

    下面是Delphi2010中的tshellstate定义:

    type
      tagSHELLSTATEW = record 
        Data: DWORD;
        Data2: UINT;
    {   fShowAllObjects: BOOL:1;
        fShowExtensions: BOOL:1;
        fNoConfirmRecycle: BOOL:1;
        fShowSysFiles: BOOL:1;
        fShowCompColor: BOOL:1;
        fDoubleClickInWebView: BOOL:1;
        fDesktopHTML: BOOL:1;
        fWin95Classic: BOOL:1;
        fDontPrettyPath: BOOL:1;
        fShowAttribCol: BOOL:1;
        fMapNetDrvBtn: BOOL:1;
        fShowInfoTip: BOOL:1;
        fHideIcons: BOOL:1;
        fWebView: BOOL:1;
        fFilter: BOOL:1;
        fShowSuperHidden: BOOL:1;
        fNoNetCrawling: BOOL:1;}
    
        //dwWin95Unused: DWORD;// Win95 only - no longer supported pszHiddenFileExts
        //uWin95Unused: UINT; // Win95 only - no longer supported cbHiddenFileExts
    
        // Note: Not a typo!  This is a persisted structure so we cannot use LPARAM
        lParamSort: Integer;
        iSortDirection: Integer;
        version: UINT;
    
        // new for win2k. need notUsed var to calc the right size of ie4 struct
        // FIELD_OFFSET does not work on bit fields
        uNotUsed: UINT;// feel free to rename and use
    {   fSepProcess: BOOL:1;
    
        // new for Whistler.
        fStartPanelOn: BOOL:1;
        fShowStartPage: BOOL:1;
    
        // new for Windows Vista
        fAutoCheckSelect: BOOL:1;
        fIconsOnly: BOOL:1;
        fShowTypeOverlay: BOOL:1;
    
        // If you need a new flag, steal a bit from from fSpareFlags.
        // Also, keep SHELLFLAGSTATE and SHGetSettings in sync when adding new flags.
        fSpareFlags: UINT:11;
    }
    
      end;
      {$EXTERNALSYM tagSHELLSTATEW}
      SHELLSTATEA = tagSHELLSTATEW;
      {$EXTERNALSYM SHELLSTATEA}
      SHELLSTATEW = tagSHELLSTATEW;
      {$EXTERNALSYM SHELLSTATEW}
      SHELLSTATE = SHELLSTATEW;
      {$EXTERNALSYM SHELLSTATE}
      TShellState = SHELLSTATE;
      PShellState = ^TShellState;
    
    const
      SHELLSTATEVERSION_IE4 = 9; 
      {$EXTERNALSYM SHELLSTATEVERSION_IE4}
      SHELLSTATEVERSION_WIN2K = 10; 
      {$EXTERNALSYM SHELLSTATEVERSION_WIN2K}
    

    不幸的是,不是很有帮助。

        4
  •  0
  •   Marco van de Voort    14 年前

    C中的afaik位域是整数的子类型。有很多方法可以打包它,但是在C语言中,在一堆单位字段之后,将有填充到下一个字节边界(甚至可能是下一个整数边界)。此外,C的sizeof也不支持半个部分。

    所以可能是1+6+1乘以sizeof(integer)=32字节。

        5
  •  0
  •   Uli Gerhardt    13 年前

    我参加聚会有点晚了,但是 this article 很好地解释了位域,并为Delphi提供了一些方法。