C 从Delphi调用SHGetSetSettings
我只是阅读和阅读,从那以后我一直在尝试打电话给Delphi。这是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
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);