C 从Delphi调用SHGetSetSettings

C 从Delphi调用SHGetSetSettings,c,delphi,winapi,translation,msdn,C,Delphi,Winapi,Translation,Msdn,我只是阅读和阅读,从那以后我一直在尝试打电话给Delphi。这是shell32.dll的函数,但在ShlObj.pas中没有定义,因此我们需要编写自己的定义 首先,我们需要翻译结构。现在我在C语言方面的经验有限,但我认为“:1”意味着结构的成员是一个位,也就是说,它们中的八个可以打包在一个字节中。我还假设DWORD=UINT=32位无符号整数,而LONG=int是32位有符号整数。但是我们有一个问题:整个结构将占用228位,或28.5字节,这是。。。这是不可能的,至少在Delphi中,sizeo

我只是阅读和阅读,从那以后我一直在尝试打电话给Delphi。这是
shell32.dll
的函数,但在
ShlObj.pas
中没有定义,因此我们需要编写自己的定义

首先,我们需要翻译结构。现在我在C语言方面的经验有限,但我认为“:1”意味着结构的成员是一个位,也就是说,它们中的八个可以打包在一个字节中。我还假设
DWORD
=
UINT
=32位无符号整数,而
LONG
=
int
是32位有符号整数。但是我们有一个问题:整个结构将占用228位,或28.5字节,这是。。。这是不可能的,至少在Delphi中,
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;
然后我宣布(为了以后的方便)

现在我已经准备好定义了

interface
  procedure SHGetSetSettings(var ShellState: TShellState; Mask: cardinal; DoSet: boolean); stdcall;

implementation
  procedure SHGetSetSettings; external shell32 name 'SHGetSetSettings';
但是在我尝试代码之前,我注意到了一些非常奇怪的事情。我发现我声明的常量已在此处声明:。请注意,
SSF_HIDEICONS=0x00004000=16384≠ fHideIcons=4096
。如果
SSF_
常量实际上是与
SHELLSTATE
一起使用的掩码,那么当它是结构中的第13位(其掩码应为2^12)时,将
SSF_隐藏项定义为2^14是没有意义的。因此,两个MSDN参考页似乎相互矛盾


有人能澄清一下这一切吗

我对这里帮助的理解是,在检索数据时,为掩码指定了SSF_uuu常量。它们没有理由必须映射到ShellState结构中的位


如果没有,fshowsys文件将映射到8(0x04),我们从帮助中知道SSF_showsys文件是0x20。没有直接映射。

C中的Afaik位字段是integer的子类型。有很多方法可以对其进行打包,但在C中,在一组单位字段之后,将填充到下一个字节边界(甚至可能填充到下一个整数边界)。此外,C的sizeof也不支持一半


因此,它可能是sizeof(integer)=32字节的1+6+1倍。

以下是Delphi 2010中的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}

不幸的是,这没有多大帮助。

ShlObj.pas中SHELLSTATE的D2010声明不幸不正确,但第一组位(17)与
数据正确匹配:DWORD(你的的确可以)。
可能有18个或19个都是相同的。然后,我们应该为2个Win95unused多获取2个DWORD/UINT,而不仅仅是Data2

太糟糕了,因为SSF标志和SHGetSetSettings声明已经在那里完成并且正确

根据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);

是的,当然他们不必映射到结构的各个部分。但在当时,这似乎很合理!但是另一个问题呢:一个C结构是否可能没有整数个字节作为其大小?不。看看声明,位字段被指定为在BOOL中,因此底层类型是int。我将该结构的大小设置为36字节,一目了然。当然,结构打包可以改变大小,但由于这里的所有内容(int、UINT、long、DWORD)在32位操作系统上都是4字节,我认为这个估计是相当安全的。当然,一些语言律师会跳到这里来证明我错了:-)。不过,如果您使用的是64位编译器,请注意。。。这个值会改变。所以,如果我只是在必要时添加一些虚拟位来“完成布尔”,我对结构的解释将是正确的?是的。我不经常使用Delphi,但我相信打包记录无论如何都只能是整数字节。您只需确保使用足够的空间在四字节边界上启动dwWin95Unused。这实际上非常有用。除此之外,这说明所有BOOL:1一起占用八个字节。不过有点奇怪,因为17位可以放进三个字节,所以一个基数就足够了。顺便说一句:我假设UINT是一个位无符号整数,也就是基数,就像DWORD一样。但为什么要使用两个不同的“别名”?陛下我似乎只得到24个字节。。。
var
  lpss: tagSHELLSTATEW;
begin
  ZeroMemory(@lpss, SizeOf(lpss));
  SHGetSetSettings(lpss, SSF_SORTCOLUMNS, False);