从Delphi调用SHGetSetSettings

我刚读了这个问题和这个问题 ,从那以后我一直试图在Delphi中调用SHGetSetSettings 。 这是shell32.dll一个function,但是在ShlObj.pas没有定义,所以我们需要编写自己的定义。

首先,我们需要翻译SHELLSTATE结构。 现在我只有有限的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; 

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

 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常量 。 请注意, SSF_HIDEICONS = 0x00004000 = 16384 ≠ fHideIcons = 4096 。 如果SSF_常量实际上是与SHELLSTATE一起使用的SHELLSTATE ,那么当SSF_HIDEICONS是结构中的第13位(并且其掩码应该是2 ^ 12)时将SSF_HIDEICONS定义为2 ^ 14是没有意义的。 因此,似乎两个MSDN参考页面相互矛盾。

有人可以为这一切带来一些清晰度吗?

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

如果他们确实fShowSysFiles会映射到8(0x04),我们从帮助中知道SSF_SHOWSYSFILES是0x20。 没有直接映射。

不幸的是,ShlObj.pas中的SHELLSTATE D2010声明不正确,但第一组位(17)与Data: DWORD;正确匹配Data: 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; 

您可以validation这是否允许正确获取排序属性:

 var lpss: tagSHELLSTATEW; begin ZeroMemory(@lpss, SizeOf(lpss)); SHGetSetSettings(lpss, SSF_SORTCOLUMNS, False); 

这是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} 

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

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

所以它可能是1 + 6 + 1倍sizeof(整数)= 32字节。

我参加派对有点晚了,但是这篇文章解释了很好的bitfields,并为Delphi提供了一些方法。